# HG changeset patch
# User robcast
# Date 1377184473 -7200
# Node ID 59d615f4e5f31fe8c185745b35aa9fd41851f23c
# Parent ee5d2ce6b11ace5c3df5cd65767d7c16bd23a7b7
refactored setWithIiifPath(String) into string splitter and setWithIiifParams().
diff -r ee5d2ce6b11a -r 59d615f4e5f3 common/src/main/java/digilib/conf/DigilibConfiguration.java
--- a/common/src/main/java/digilib/conf/DigilibConfiguration.java Mon Jul 22 21:18:50 2013 +0200
+++ b/common/src/main/java/digilib/conf/DigilibConfiguration.java Thu Aug 22 17:14:33 2013 +0200
@@ -44,8 +44,9 @@
/** Log4J logger */
protected static Logger logger = Logger.getLogger(DigilibConfiguration.class);
+ /** digilib version */
public static String getVersion() {
- return "2.2.1";
+ return "2.2.2";
}
/**
diff -r ee5d2ce6b11a -r 59d615f4e5f3 common/src/main/java/digilib/conf/DigilibRequest.java
--- a/common/src/main/java/digilib/conf/DigilibRequest.java Mon Jul 22 21:18:50 2013 +0200
+++ b/common/src/main/java/digilib/conf/DigilibRequest.java Thu Aug 22 17:14:33 2013 +0200
@@ -282,8 +282,14 @@
if (path == null) {
return false;
}
- // alway set HTTP status code error reporting
- options.setOption("errcode");
+
+ String identifier = null;
+ String region = null;
+ String size = null;
+ String rotation = null;
+ String quality = null;
+ String format = null;
+
// enable passing of delimiter to get empty parameters
StringTokenizer query = new StringTokenizer(path, "/", true);
String token;
@@ -308,17 +314,7 @@
if (query.hasMoreTokens()) {
token = getNextDecodedToken(query);
if (!token.equals("/")) {
- try {
- if (token.contains("%")) {
- // still escape chars -- decode again
- token = URLDecoder.decode(token, "UTF-8");
- }
- setValueFromString("fn", token);
- } catch (UnsupportedEncodingException e) {
- errorMessage = "Error decoding identifier in IIIF path!";
- logger.error(errorMessage);
- return false;
- }
+ identifier = token;
// skip /
if (query.hasMoreTokens()) {
query.nextToken();
@@ -331,53 +327,12 @@
if (query.hasMoreTokens()) {
token = getNextDecodedToken(query);
if (!token.equals("/")) {
- if (token.equals("info.json")) {
- // info request
- options.setOption("info");
- return true;
- } else if (token.equals("full")) {
- // full region -- default
- } else if (token.startsWith("pct:")) {
- // pct:x,y,w,h -- region in % of original image
- String[] parms = token.substring(4).split(",");
- try {
- float x = Float.parseFloat(parms[0]);
- setValue("wx", x / 100f);
- float y = Float.parseFloat(parms[1]);
- setValue("wy", y / 100f);
- float w = Float.parseFloat(parms[2]);
- setValue("ww", w / 100f);
- float h = Float.parseFloat(parms[3]);
- setValue("wh", h / 100f);
- } catch (Exception e) {
- errorMessage = "Error parsing range parameter in IIIF path!";
- logger.error(errorMessage, e);
- return false;
- }
- } else {
- // x,y,w,h -- region in pixel of original image :-(
- String[] parms = token.split(",");
- if (parms.length != 4) {
- errorMessage = "Error parsing range parameter in IIIF path!";
- logger.error(errorMessage);
- return false;
- } else {
- options.setOption("pxarea");
- setValueFromString("wx", parms[0]);
- setValueFromString("wy", parms[1]);
- setValueFromString("ww", parms[2]);
- setValueFromString("wh", parms[3]);
- }
- }
+ region = token;
// skip /
if (query.hasMoreTokens()) {
query.nextToken();
}
}
- } else {
- // region omitted -- assume info request
- options.setOption("info");
- return true;
}
/*
* fourth parameter size
@@ -385,60 +340,12 @@
if (query.hasMoreTokens()) {
token = getNextDecodedToken(query);
if (!token.equals("/")) {
- if (token.equals("full")) {
- // full -- size of original
- options.setOption("ascale");
- setValue("scale", 1f);
- } else if (token.startsWith("pct:")) {
- // pct:n -- n% size of original
- try {
- float pct = Float.parseFloat(token.substring(4));
- options.setOption("ascale");
- setValue("scale", pct / 100);
- } catch (NumberFormatException e) {
- errorMessage = "Error parsing size parameter in IIIF path!";
- logger.error(errorMessage, e);
- return false;
- }
- } else {
- // w,h -- pixel size
- try {
- String[] parms = token.split(",", 2);
- if (parms[0].length() > 0) {
- // width param
- if (parms[0].startsWith("!")) {
- // width (in digilib-like bounding box)
- setValueFromString("dw", parms[0].substring(1));
- } else if (parms[1].length() == 0) {
- // width only
- setValueFromString("dw", parms[0]);
- } else {
- // w,h -- according to spec, we should distort the image to match ;-(
- errorMessage = "Non-uniform-scale size parameter in IIIF path not supported!";
- logger.error(errorMessage);
- return false;
- }
- }
- if (parms[1].length() > 0) {
- // height param
- setValueFromString("dh", parms[1]);
- }
- } catch (Exception e) {
- errorMessage = "Error parsing size parameter in IIIF path!";
- logger.error(errorMessage, e);
- return false;
- }
- }
+ size = token;
// skip /
if (query.hasMoreTokens()) {
query.nextToken();
}
}
- } else {
- // size omitted -- assume "full"
- options.setOption("ascale");
- setValue("scale", 1f);
- return true;
}
/*
* fifth parameter rotation
@@ -446,14 +353,7 @@
if (query.hasMoreTokens()) {
token = getNextDecodedToken(query);
if (!token.equals("/")) {
- try {
- float rot = Float.parseFloat(token);
- setValue("rot", rot);
- } catch (NumberFormatException e) {
- errorMessage = "Error parsing rotation parameter in IIIF path!";
- logger.error(errorMessage, e);
- return false;
- }
+ rotation = token;
// skip /
if (query.hasMoreTokens()) {
query.nextToken();
@@ -469,26 +369,10 @@
try {
String[] parms = token.split("\\.");
// quality param
- if (parms[0].equals("native")||parms[0].equals("color")) {
- // native is default anyway
- } else if (parms[0].equals("grey")) {
- setValueFromString("colop", "grayscale");
- } else {
- errorMessage = "Invalid quality parameter in IIIF path!";
- logger.error(errorMessage);
- return false;
- }
- // format param (we only support jpg and png)
- if (parms.length > 1 && parms[1].equals("jpg")) {
- // force jpg
- options.setOption("jpg");
- } else if (parms.length > 1 && parms[1].equals("png")) {
- // force png
- options.setOption("png");
- } else if (parms.length > 1) {
- errorMessage = "Invalid format parameter in IIIF path!";
- logger.error(errorMessage);
- return false;
+ quality = parms[0];
+ // format param
+ if (parms.length > 1) {
+ format = parms[1];
}
} catch (Exception e) {
errorMessage = "Error parsing quality and format parameters in IIIF path!";
@@ -496,7 +380,9 @@
return false;
}
}
- return true;
+
+ // set request with these parameters
+ return setWithIiifParams(identifier, region, size, rotation, quality, format);
}
private String getNextDecodedToken(StringTokenizer tokens) {
@@ -510,6 +396,195 @@
return null;
}
+ /**
+ * Populate a request from IIIF image API parameters.
+ *
+ * {scheme}://{server}{/prefix}/{identifier}/{region}/{size}/{rotation}/{quality}{.format}
+ *
+ * @see IIIF Image
+ * API
+ */
+ public boolean setWithIiifParams(String identifier, String region, String size,
+ String rotation, String quality, String format) {
+ // alway set HTTP status code error reporting
+ options.setOption("errcode");
+
+ /*
+ * parameter identifier (encoded)
+ */
+ if (identifier != null) {
+ try {
+ if (identifier.contains("%")) {
+ // still escape chars -- decode again
+ identifier = URLDecoder.decode(identifier, "UTF-8");
+ }
+ setValueFromString("fn", identifier);
+ } catch (UnsupportedEncodingException e) {
+ errorMessage = "Error decoding identifier in IIIF path!";
+ logger.error(errorMessage);
+ return false;
+ }
+ } else {
+ errorMessage = "Missing identifier in IIIF path!";
+ logger.error(errorMessage);
+ return false;
+ }
+
+ /*
+ * parameter region
+ */
+ if (region != null) {
+ if (region.equals("info.json")) {
+ // info request
+ options.setOption("info");
+ return true;
+ } else if (region.equals("full")) {
+ // full region -- default
+ } else if (region.startsWith("pct:")) {
+ // pct:x,y,w,h -- region in % of original image
+ String[] parms = region.substring(4).split(",");
+ try {
+ float x = Float.parseFloat(parms[0]);
+ setValue("wx", x / 100f);
+ float y = Float.parseFloat(parms[1]);
+ setValue("wy", y / 100f);
+ float w = Float.parseFloat(parms[2]);
+ setValue("ww", w / 100f);
+ float h = Float.parseFloat(parms[3]);
+ setValue("wh", h / 100f);
+ } catch (Exception e) {
+ errorMessage = "Error parsing range parameter in IIIF path!";
+ logger.error(errorMessage, e);
+ return false;
+ }
+ } else {
+ // x,y,w,h -- region in pixel of original image :-(
+ String[] parms = region.split(",");
+ if (parms.length != 4) {
+ errorMessage = "Error parsing range parameter in IIIF path!";
+ logger.error(errorMessage);
+ return false;
+ } else {
+ options.setOption("pxarea");
+ setValueFromString("wx", parms[0]);
+ setValueFromString("wy", parms[1]);
+ setValueFromString("ww", parms[2]);
+ setValueFromString("wh", parms[3]);
+ }
+ }
+ } else {
+ // region omitted -- assume info request
+ options.setOption("info");
+ return true;
+ }
+
+ /*
+ * parameter size
+ */
+ if (size != null) {
+ if (size.equals("full")) {
+ // full -- size of original
+ options.setOption("ascale");
+ setValue("scale", 1f);
+ } else if (size.startsWith("pct:")) {
+ // pct:n -- n% size of original
+ try {
+ float pct = Float.parseFloat(size.substring(4));
+ options.setOption("ascale");
+ setValue("scale", pct / 100);
+ } catch (NumberFormatException e) {
+ errorMessage = "Error parsing size parameter in IIIF path!";
+ logger.error(errorMessage, e);
+ return false;
+ }
+ } else {
+ // w,h -- pixel size
+ try {
+ String[] parms = size.split(",", 2);
+ if (parms[0].length() > 0) {
+ // width param
+ if (parms[0].startsWith("!")) {
+ // width (in digilib-like bounding box)
+ setValueFromString("dw", parms[0].substring(1));
+ } else if (parms[1].length() == 0) {
+ // width only
+ setValueFromString("dw", parms[0]);
+ } else {
+ // w,h -- according to spec, we should distort the
+ // image to match ;-(
+ errorMessage = "Non-uniform-scale size parameter in IIIF path not supported!";
+ logger.error(errorMessage);
+ return false;
+ }
+ }
+ if (parms[1].length() > 0) {
+ // height param
+ setValueFromString("dh", parms[1]);
+ }
+ } catch (Exception e) {
+ errorMessage = "Error parsing size parameter in IIIF path!";
+ logger.error(errorMessage, e);
+ return false;
+ }
+ }
+ } else {
+ // size omitted -- assume "full"
+ options.setOption("ascale");
+ setValue("scale", 1f);
+ return true;
+ }
+
+ /*
+ * parameter rotation
+ */
+ if (rotation != null) {
+ try {
+ float rot = Float.parseFloat(rotation);
+ setValue("rot", rot);
+ } catch (NumberFormatException e) {
+ errorMessage = "Error parsing rotation parameter in IIIF path!";
+ logger.error(errorMessage, e);
+ return false;
+ }
+ }
+
+ /*
+ * parameter quality
+ */
+ if (quality != null) {
+ // quality param
+ if (quality.equals("native") || quality.equals("color")) {
+ // native is default anyway
+ } else if (quality.equals("grey")) {
+ setValueFromString("colop", "grayscale");
+ } else {
+ errorMessage = "Invalid quality parameter in IIIF path!";
+ logger.error(errorMessage);
+ return false;
+ }
+ }
+
+ /*
+ * parameter format
+ */
+ if (format != null) {
+ // format param (we only support jpg and png)
+ if (format.equals("jpg")) {
+ // force jpg
+ options.setOption("jpg");
+ } else if (format.equals("png")) {
+ // force png
+ options.setOption("png");
+ } else {
+ errorMessage = "Invalid format parameter in IIIF path!";
+ logger.error(errorMessage);
+ return false;
+ }
+ }
+ return true;
+ }
+
+
/**
* Test if option string opt
is set. Checks if the substring
* opt
is contained in the options string param
.
diff -r ee5d2ce6b11a -r 59d615f4e5f3 servlet/src/main/java/digilib/servlet/ServletOps.java
--- a/servlet/src/main/java/digilib/servlet/ServletOps.java Mon Jul 22 21:18:50 2013 +0200
+++ b/servlet/src/main/java/digilib/servlet/ServletOps.java Thu Aug 22 17:14:33 2013 +0200
@@ -44,6 +44,7 @@
import digilib.conf.DigilibServletRequest;
import digilib.image.DocuImage;
import digilib.image.ImageOpException;
+import digilib.io.FileOpException;
import digilib.io.FileOps;
import digilib.io.ImageInput;
import digilib.util.ImageSize;
@@ -353,6 +354,7 @@
* @param dlReq
* @param response
* @param logger
+ * @throws FileOpException
* @throws ServletException
* @see IIIF Image Information Request
*/
@@ -361,34 +363,44 @@
logger.error("No response!");
return;
}
+ ImageSize size = null;
try {
// get original image size
- ImageInput img = dlReq.getJobDescription().getImageSet().getBiggest();
- ImageSize size = img.getSize();
- String url = dlReq.getServletRequest().getRequestURL().toString();
- if (url.endsWith("/info.json")) {
- url = url.substring(0, url.lastIndexOf("/info.json"));
- } else if (url.endsWith("/")) {
- url = url.substring(0, url.lastIndexOf("/"));
+ ImageInput img;
+ img = dlReq.getJobDescription().getImageSet().getBiggest();
+ size = img.getSize();
+ } catch (FileOpException e) {
+ try {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND);
+ return;
+ } catch (IOException e1) {
+ throw new ServletException("Unable to write error response!", e);
}
- response.setContentType("application/json;charset=UTF-8");
- PrintWriter writer = response.getWriter();
+ }
+ String url = dlReq.getServletRequest().getRequestURL().toString();
+ if (url.endsWith("/info.json")) {
+ url = url.substring(0, url.lastIndexOf("/info.json"));
+ } else if (url.endsWith("/")) {
+ url = url.substring(0, url.lastIndexOf("/"));
+ }
+ response.setContentType("application/json;charset=UTF-8");
+ PrintWriter writer;
+ try {
+ writer = response.getWriter();
writer.println("{");
writer.println("\"@context\" : \"http://library.stanford.edu/iiif/image-api/1.1/context.json\",");
- writer.println("\"@id\" : \""+url+"\",");
- writer.println("\"width\" : "+size.width+",");
- writer.println("\"height\" : "+size.height+",");
+ writer.println("\"@id\" : \"" + url + "\",");
+ writer.println("\"width\" : " + size.width + ",");
+ writer.println("\"height\" : " + size.height + ",");
writer.println("\"formats\" : [\"jpg\", \"png\"],");
writer.println("\"qualities\" : [\"native\", \"color\", \"grey\"],");
writer.println("\"profile\" : \"http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level2\"");
writer.println("}");
} catch (IOException e) {
- throw new ServletException("Error sending info:", e);
+ throw new ServletException("Unable to write response!", e);
}
- // TODO: should we: finally { img.dispose(); }
}
-
/** Returns text representation of headers for debuggging purposes.
* @param req
* @return