# HG changeset patch # User robcast # Date 1292921536 -3600 # Node ID 1f666c2b4578d7e11dad1d5bfffa66222de105f5 # Parent 9936604d466e3c44d8a2609519848f33f2801629# Parent 8beefd1142b28ca9b2433205e7eea82a517bb215 Merge with PDF branch 8beefd1142b28ca9b2433205e7eea82a517bb215 diff -r 9936604d466e -r 1f666c2b4578 client/.classpath --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/.classpath Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff -r 9936604d466e -r 1f666c2b4578 client/.project --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/.project Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,38 @@ + + + digilib-client + + + digilib-servlet + digilib-client + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.jdt.core.javanature + org.eclipse.wst.jsdt.core.jsNature + + diff -r 9936604d466e -r 1f666c2b4578 client/.settings/.jsdtscope --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/.settings/.jsdtscope Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff -r 9936604d466e -r 1f666c2b4578 client/.settings/org.eclipse.jdt.core.prefs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/.settings/org.eclipse.jdt.core.prefs Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,8 @@ +#Fri Oct 08 14:51:02 CEST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff -r 9936604d466e -r 1f666c2b4578 client/.settings/org.eclipse.wst.common.component --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/.settings/org.eclipse.wst.common.component Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,14 @@ + + + + + + uses + + + consumes + + + + + diff -r 9936604d466e -r 1f666c2b4578 client/.settings/org.eclipse.wst.common.project.facet.core.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/.settings/org.eclipse.wst.common.project.facet.core.xml Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,10 @@ + + + + + + + + + + diff -r 9936604d466e -r 1f666c2b4578 client/.settings/org.eclipse.wst.jsdt.ui.superType.container --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/.settings/org.eclipse.wst.jsdt.ui.superType.container Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff -r 9936604d466e -r 1f666c2b4578 client/.settings/org.eclipse.wst.jsdt.ui.superType.name --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/.settings/org.eclipse.wst.jsdt.ui.superType.name Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,1 @@ +Window \ No newline at end of file diff -r 9936604d466e -r 1f666c2b4578 client/.settings/org.eclipse.wst.ws.service.policy.prefs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/.settings/org.eclipse.wst.ws.service.policy.prefs Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,3 @@ +#Fri Oct 08 14:56:13 CEST 2010 +eclipse.preferences.version=1 +org.eclipse.wst.ws.service.policy.projectEnabled=false diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/META-INF/MANIFEST.MF --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/digitallibrary/META-INF/MANIFEST.MF Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/WEB-INF/classes/Relato.java --- a/client/digitallibrary/WEB-INF/classes/Relato.java Wed Jul 14 16:36:42 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -import java.io.*; -import java.net.*; -import java.util.*; -import javax.servlet.*; -import javax.servlet.http.*; -import javax.xml.transform.*; -import javax.xml.transform.dom.*; -import javax.xml.transform.stream.*; -import org.apache.xerces.parsers.DOMParser; -import org.apache.xpath.*; -import org.w3c.dom.*; - -public class Relato extends HttpServlet { - - public final static String FS = System.getProperty("file.separator"); - - // Respond to HTTP GET requests from browsers. - public void doGet (HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - Hashtable params = new Hashtable(); - Enumeration enum = request.getParameterNames(); - while (enum.hasMoreElements()) { - String pName = (String) enum.nextElement(); - params.put(pName, request.getParameter(pName)); - - } - // Set content type for HTML. - response.setContentType("text/html; charset=UTF-8"); - // Output goes to the response PrintWriter. - PrintWriter out = response.getWriter(); - DOMParser parser = new DOMParser(); - - try { - TransformerFactory tFactory = TransformerFactory.newInstance(); - //get the real path for xml and xsl files. - String ctx = getServletContext().getRealPath("") + FS; - - parser.parse(ctx + (String) params.get("xml")); - Document document = parser.getDocument(); - - Element topFrameset = (Element) XPathAPI.selectSingleNode(document, "/relato/frames/frameset"); - topFrameset.setAttribute("onload", "init();"); - - NodeList nodelist = XPathAPI.selectNodeList(document, "//frameset/frame"); - for (int i = 0; i < nodelist.getLength(); i++) { - Element elem = (Element)nodelist.item(i); - String name = elem.getAttribute("name"); - if (name != "") { - if (params.containsKey(name)) { - String src = (String) params.get(name); - elem.setAttribute("src", src); - } - } - } - - Source xmlSource = new DOMSource (document); - Source xslSource = new StreamSource (new URL("file", "", ctx+"relato/relato.xsl").openStream()); - // Generate the transformer. - Transformer transformer = tFactory.newTransformer(xslSource); - // Perform the transformation, sending the output to the response. - transformer.transform(xmlSource, new StreamResult(out)); - } - - // If an Exception occurs, return the error to the client. - catch (Exception e) { - out.write(e.getMessage()); - e.printStackTrace(out); - } - - // Close the PrintWriter. - out.close(); - } -} diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/WEB-INF/digilib-config.xml --- a/client/digitallibrary/WEB-INF/digilib-config.xml Wed Jul 14 16:36:42 2010 +0200 +++ b/client/digitallibrary/WEB-INF/digilib-config.xml Tue Dec 21 09:52:16 2010 +0100 @@ -58,5 +58,15 @@ + + + + + + + + + + diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/WEB-INF/lib/DigilibServlet.jar Binary file client/digitallibrary/WEB-INF/lib/DigilibServlet.jar has changed diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/WEB-INF/lib/imageinfo.jar Binary file client/digitallibrary/WEB-INF/lib/imageinfo.jar has changed diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/WEB-INF/web.xml --- a/client/digitallibrary/WEB-INF/web.xml Wed Jul 14 16:36:42 2010 +0200 +++ b/client/digitallibrary/WEB-INF/web.xml Tue Dec 21 09:52:16 2010 +0100 @@ -54,40 +54,16 @@ digilib.servlet.Texter - - - - Raster - - - The servlet for rastered SVG. - - - digilib.servlet.Raster - - - + - Mapper + PDFCache - The servlet to create image maps. + The servlet for PDF. - digilib.servlet.Mapper - - - - - - Relato - - - The relato servlet - - - Relato + digilib.servlet.PDFCache @@ -145,47 +121,21 @@ /authenticated/servlet/Texter/* - + - Raster + PDFCache - /servlet/Raster/* + /servlet/PDFCache/* - Raster - - - /authenticated/servlet/Raster/* - - - - - - Mapper + PDFCache - /servlet/Mapper/* - - - - - Mapper - - - /authenticated/servlet/Mapper/* - - - - - - Relato - - - /Relato + /authenticated/servlet/PDFCache/* diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/digilib-new.html --- a/client/digitallibrary/digilib-new.html Wed Jul 14 16:36:42 2010 +0200 +++ b/client/digitallibrary/digilib-new.html Tue Dec 21 09:52:16 2010 +0100 @@ -37,7 +37,7 @@ -
Digital Document Library (L1) diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/dlInfo-js.jsp --- a/client/digitallibrary/dlInfo-js.jsp Wed Jul 14 16:36:42 2010 +0200 +++ b/client/digitallibrary/dlInfo-js.jsp Tue Dec 21 09:52:16 2010 +0100 @@ -19,7 +19,7 @@ %> // Automatically generated JavaScript snippet with parameters <% - Object[] keys = dlRequest.keySet().toArray(); + Object[] keys = dlRequest.getParams().keySet().toArray(); java.util.Arrays.sort(keys); int l = keys.length; for (int i = 0; i < l; i++) { diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/dlInfo-xml.jsp --- a/client/digitallibrary/dlInfo-xml.jsp Wed Jul 14 16:36:42 2010 +0200 +++ b/client/digitallibrary/dlInfo-xml.jsp Tue Dec 21 09:52:16 2010 +0100 @@ -23,7 +23,7 @@ %> <% - Object[] keys = dlRequest.keySet().toArray(); + Object[] keys = dlRequest.getParams().keySet().toArray(); java.util.Arrays.sort(keys); int l = keys.length; for (int i = 0; i < l; i++) { diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/greyskin/digimage-neu.jsp --- a/client/digitallibrary/greyskin/digimage-neu.jsp Wed Jul 14 16:36:42 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,443 +0,0 @@ -<%@ page language="java" %><%! -// -- JSP init ------------- - -// create DocumentBean instance for all JSP requests -digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean(); - -// initialize DocumentBean instance in JSP init -public void jspInit() { - try { - // set servlet init-parameter - docBean.setConfig(getServletConfig()); - } catch (javax.servlet.ServletException e) { - System.out.println(e); - } -} -// -- end of JSP init ------------- -%><% -// -- JSP request ------------- - -// parsing the query -// ----------------- -digilib.servlet.DigilibRequest dlRequest = new digilib.servlet.DigilibRequest(request); -docBean.setRequest(dlRequest); -// check if authentication is needed and redirect if necessary -docBean.doAuthentication(response); -// add number of pages -dlRequest.setValue("pt", docBean.getNumPages()); -// store objects for jsp:include -pageContext.setAttribute("docBean", docBean, pageContext.REQUEST_SCOPE); -%> - - Digital Document Library NG - - - - - - - - - - - - - - -
- <% if (dlRequest.hasOption("clop", "noarrows")) { - %><% - } else { - %><% - } - %> -
- - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/greyskin/digimage.jsp --- a/client/digitallibrary/greyskin/digimage.jsp Wed Jul 14 16:36:42 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,459 +0,0 @@ -<%@ page language="java" %><%! - // -- JSP init ------------- - - // create DocumentBean instance for all JSP requests - digilib.servlet.DocumentBean docBean = new digilib.servlet.DocumentBean(); - - // initialize DocumentBean instance in JSP init - public void jspInit() { - try { - // set servlet init-parameter - docBean.setConfig(getServletConfig()); - } catch (javax.servlet.ServletException e) { - System.out.println(e); - } - } - // -- end of JSP init ------------- -%> - -<% - // -- JSP request ------------- - - // parsing the query - // ----------------- - digilib.servlet.DigilibRequest dlRequest = new digilib.servlet.DigilibRequest(request); - docBean.setRequest(dlRequest); - // check if authentication is needed and redirect if necessary - docBean.doAuthentication(response); - // add number of pages - dlRequest.setValue("pt", docBean.getNumPages()); - // store objects for jsp:include - pageContext.setAttribute("docBean", docBean, pageContext.REQUEST_SCOPE); -%> - - - - - Digital Document Library NG - - - - - - - - - - - - -
-
- -
-
- - -
-
-
-
-
-
-
-
- - -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/greyskin/digimage_img_inc.jsp --- a/client/digitallibrary/greyskin/digimage_img_inc.jsp Wed Jul 14 16:36:42 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -<%@ page language="java" %><% -// retrieve objects from context -digilib.servlet.DocumentBean docBean = (digilib.servlet.DocumentBean) pageContext.getAttribute("docBean", pageContext.REQUEST_SCOPE); -digilib.servlet.DigilibRequest dlRequest = docBean.getRequest(); -String ua = request.getHeader("User-Agent"); -boolean isN4 = ((ua.indexOf("Mozilla/4.") > -1)&&(ua.indexOf("MSIE") == -1)); -%> -<% - if (isN4) { -%><% - } else { -%>
<% - } -%> - -<% - if (isN4) { -%><% - } else { -%>
<% - } -%> diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/greyskin/digimage_tbl_inc.jsp --- a/client/digitallibrary/greyskin/digimage_tbl_inc.jsp Wed Jul 14 16:36:42 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -<%@ page language="java" %><% -// retrieve objects from context -digilib.servlet.DocumentBean docBean = (digilib.servlet.DocumentBean) pageContext.getAttribute("docBean", pageContext.REQUEST_SCOPE); -digilib.servlet.DigilibRequest dlRequest = docBean.getRequest(); -String ua = request.getHeader("User-Agent"); -boolean isN4 = ((ua.indexOf("Mozilla/4.") > -1)&&(ua.indexOf("MSIE") == -1)); -%> - - - - - - - - - - - - - - - - -
<% - if (docBean.canMoveUp()) { - %><% - } - %>
<% - if (docBean.canMoveLeft()) { - %><% - } - %> -<% - if(isN4) { - %><% - } else { - %>
<% - } -%> - -<% - if(isN4) { - %><% - } else { - %>
<% - } -%> -
<% - if (docBean.canMoveRight()) { - %><% - } - %>
<% - if (docBean.canMoveDown()) { - %><% - } - %>
diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/greyskin/diginew.jsp --- a/client/digitallibrary/greyskin/diginew.jsp Wed Jul 14 16:36:42 2010 +0200 +++ b/client/digitallibrary/greyskin/diginew.jsp Tue Dec 21 09:52:16 2010 +0100 @@ -28,7 +28,7 @@ // add number of pages dlRequest.setValue("pt", docBean.getNumPages()); // store objects for jsp:include - pageContext.setAttribute("docBean", docBean, pageContext.REQUEST_SCOPE); + pageContext.setAttribute("docBean", docBean, PageContext.REQUEST_SCOPE); %> diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/pdf/error.jsp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/digitallibrary/pdf/error.jsp Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,13 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="ISO-8859-1"%> + + + + +Error + + +

Error

+There was an error while processing your request. Please check the parameters and try again. + + diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/pdf/wip.jsp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/digitallibrary/pdf/wip.jsp Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,14 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="ISO-8859-1"%> + + + + + +Work in progress ... + + +

Please wait ...

+your request is being processed. The download starts automatically when the document is finished. + + diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/server/dlConfig.jsp --- a/client/digitallibrary/server/dlConfig.jsp Wed Jul 14 16:36:42 2010 +0200 +++ b/client/digitallibrary/server/dlConfig.jsp Tue Dec 21 09:52:16 2010 +0100 @@ -1,3 +1,4 @@ +<%@page import="digilib.util.DigilibJobCenter"%> <%@ page language="java" %> <%! @@ -26,6 +27,9 @@ dlRequest.setValue("pt", docBean.getNumPages(dlRequest)); // dir cache digilib.io.DocuDirCache dirCache = (digilib.io.DocuDirCache) dlConfig.getValue("servlet.dir.cache"); +// image JobCenter +DigilibJobCenter imageProcessor = (DigilibJobCenter)dlConfig.getValue("servlet.worker.imageexecutor"); + %> @@ -38,7 +42,7 @@ <% - Object[] keys = dlConfig.keySet().toArray(); + Object[] keys = dlConfig.getParams().keySet().toArray(); java.util.Arrays.sort(keys); int l = keys.length; for (int i = 0; i < l; i++) { @@ -70,11 +74,11 @@
- + - +
currently waiting<%= digilib.servlet.DigilibWorker.getNumWaiting() %>currently waiting<%= imageProcessor.getWaitingJobs() %>
currently running<%= digilib.servlet.DigilibWorker.getNumRunning() %>currently running<%= imageProcessor.getRunningJobs() %>
diff -r 9936604d466e -r 1f666c2b4578 client/digitallibrary/server/dlRequest.jsp --- a/client/digitallibrary/server/dlRequest.jsp Wed Jul 14 16:36:42 2010 +0200 +++ b/client/digitallibrary/server/dlRequest.jsp Tue Dec 21 09:52:16 2010 +0100 @@ -93,7 +93,7 @@ <% - Object[] keys = dlRequest.keySet().toArray(); + Object[] keys = dlRequest.getParams().keySet().toArray(); java.util.Arrays.sort(keys); int l = keys.length; for (int i = 0; i < l; i++) { diff -r 9936604d466e -r 1f666c2b4578 servlet/.classpath --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/.classpath Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 9936604d466e -r 1f666c2b4578 servlet/.project --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/.project Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,30 @@ + + + digilib-servlet + + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.wst.common.project.facet.core.nature + + diff -r 9936604d466e -r 1f666c2b4578 servlet/.settings/org.eclipse.jdt.core.prefs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/.settings/org.eclipse.jdt.core.prefs Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,12 @@ +#Tue Oct 12 18:02:03 CEST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff -r 9936604d466e -r 1f666c2b4578 servlet/.settings/org.eclipse.wst.common.component --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/.settings/org.eclipse.wst.common.component Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,6 @@ + + + + + + diff -r 9936604d466e -r 1f666c2b4578 servlet/.settings/org.eclipse.wst.common.project.facet.core.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/.settings/org.eclipse.wst.common.project.facet.core.xml Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,7 @@ + + + + + + + diff -r 9936604d466e -r 1f666c2b4578 servlet/src/META-INF/MANIFEST.MF --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/META-INF/MANIFEST.MF Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/auth/AuthOps.java --- a/servlet/src/digilib/auth/AuthOps.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/auth/AuthOps.java Tue Dec 21 09:52:16 2010 +0100 @@ -81,7 +81,7 @@ * @throws AuthOpException Exception thrown on error. * @return List of Strings with role names. */ - public List rolesForPath(String filepath, HttpServletRequest request) + public List rolesForPath(String filepath, HttpServletRequest request) throws AuthOpException; /** Authorization roles needed for request. @@ -95,7 +95,7 @@ * @throws AuthOpException Exception thrown on error. * @return List of Strings with role names. */ - public List rolesForPath(DigilibRequest request) + public List rolesForPath(DigilibRequest request) throws AuthOpException; /** Test request authorization against a list of roles. @@ -103,13 +103,13 @@ * @param request ServletRequest with address information. * @return true if the user information in the request authorizes one of the roles. */ - public boolean isRoleAuthorized(List roles, HttpServletRequest request); + public boolean isRoleAuthorized(List roles, HttpServletRequest request); /** Test request authorization against a list of roles. * @param roles List of Strings with role names. * @param request ServletRequest with address information. * @return true if the user information in the request authorizes one of the roles. */ - public boolean isRoleAuthorized(List roles, DigilibRequest request); + public boolean isRoleAuthorized(List roles, DigilibRequest request); } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/auth/AuthOpsImpl.java --- a/servlet/src/digilib/auth/AuthOpsImpl.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/auth/AuthOpsImpl.java Tue Dec 21 09:52:16 2010 +0100 @@ -21,7 +21,6 @@ package digilib.auth; import java.util.List; -import java.util.ListIterator; import javax.servlet.http.HttpServletRequest; @@ -56,7 +55,7 @@ */ public boolean isAuthRequired(String filepath, HttpServletRequest request) throws AuthOpException { // check permissions - List rolesRequired = rolesForPath(filepath, request); + List rolesRequired = rolesForPath(filepath, request); return (rolesRequired != null); } @@ -66,7 +65,7 @@ public boolean isAuthRequired(DigilibRequest request) throws AuthOpException { // check permissions - List rolesRequired = rolesForPath(request); + List rolesRequired = rolesForPath(request); return (rolesRequired != null); } @@ -80,7 +79,7 @@ * @return List of Strings with role names. */ public boolean isAuthorized(String filepath, HttpServletRequest request) throws AuthOpException { - List rolesAllowed = rolesForPath(filepath, request); + List rolesAllowed = rolesForPath(filepath, request); return isRoleAuthorized(rolesAllowed, request); } @@ -89,7 +88,7 @@ */ public boolean isAuthorized(DigilibRequest request) throws AuthOpException { - List rolesAllowed = rolesForPath(request); + List rolesAllowed = rolesForPath(request); return isRoleAuthorized(rolesAllowed, request); } @@ -98,11 +97,8 @@ * @param request ServletRequest with address information. * @return true if the user information in the request authorizes one of the roles. */ - public boolean isRoleAuthorized(List roles, HttpServletRequest request) { - ListIterator r = roles.listIterator(); - String s = ""; - while (r.hasNext()) { - s = (String)r.next(); + public boolean isRoleAuthorized(List roles, HttpServletRequest request) { + for (String s: roles) { logger.debug("Testing role: "+s); if (request.isUserInRole(s)) { logger.debug("Role Authorized"); @@ -115,11 +111,8 @@ /** * @see digilib.auth.AuthOps#isRoleAuthorized(java.util.List, digilib.servlet.DigilibRequest) */ - public boolean isRoleAuthorized(List roles, DigilibRequest request) { - ListIterator r = roles.listIterator(); - String s = ""; - while (r.hasNext()) { - s = (String)r.next(); + public boolean isRoleAuthorized(List roles, DigilibRequest request) { + for (String s: roles) { logger.debug("Testing role: "+s); if (((HttpServletRequest)request.getServletRequest()).isUserInRole(s)) { logger.debug("Role Authorized"); @@ -131,8 +124,8 @@ public abstract void init() throws AuthOpException; - public abstract List rolesForPath(String filepath, HttpServletRequest request) throws AuthOpException; + public abstract List rolesForPath(String filepath, HttpServletRequest request) throws AuthOpException; - public abstract List rolesForPath(DigilibRequest request) throws AuthOpException; + public abstract List rolesForPath(DigilibRequest request) throws AuthOpException; } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/auth/HashTree.java --- a/servlet/src/digilib/auth/HashTree.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/auth/HashTree.java Tue Dec 21 09:52:16 2010 +0100 @@ -20,7 +20,10 @@ package digilib.auth; -import java.util.*; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; /** * Tree representation wrapper for a HashMap. @@ -37,7 +40,7 @@ */ public class HashTree { - private Map table; + private Map table; private String twigSep = "/"; @@ -53,7 +56,7 @@ * @param twig_separator * @param leaf_separator */ - public HashTree(Map t, String twig_separator, String leaf_separator) { + public HashTree(Map t, String twig_separator, String leaf_separator) { table = t; twigSep = twig_separator; leafSep = leaf_separator; @@ -73,10 +76,10 @@ * @param branch * @return */ - List match(String branch) { + List match(String branch) { String b = ""; String m; - LinkedList matches = new LinkedList(); + LinkedList matches = new LinkedList(); // split branch StringTokenizer twig = new StringTokenizer(branch, twigSep); @@ -87,7 +90,7 @@ } else { b += twigSep + twig.nextToken(); } - m = (String) table.get(b); + m = table.get(b); if (m != null) { if (m.indexOf(leafSep) < 0) { // single leaf diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/auth/XMLAuthOps.java --- a/servlet/src/digilib/auth/XMLAuthOps.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/auth/XMLAuthOps.java Tue Dec 21 09:52:16 2010 +0100 @@ -69,8 +69,8 @@ */ public void init() throws AuthOpException { logger.debug("xmlauthops.init (" + configFile + ")"); - Map pathList = null; - Map ipList = null; + Map pathList = null; + Map ipList = null; try { // load authPaths XMLListLoader pathLoader = @@ -105,7 +105,7 @@ * @throws AuthOpException Exception thrown on error. * @return List of Strings with role names. */ - public List rolesForPath(String filepath, HttpServletRequest request) + public List rolesForPath(String filepath, HttpServletRequest request) throws digilib.auth.AuthOpException { logger.debug("rolesForPath (" + filepath @@ -114,13 +114,13 @@ + "]"); // check if the requests address provides a role - List provided = authIPs.match(request.getRemoteAddr()); + List provided = authIPs.match(request.getRemoteAddr()); if ((provided != null) && (provided.contains("ALL"))) { // ALL switches off checking; return null; } // which roles are required? - List required = authPaths.match(filepath); + List required = authPaths.match(filepath); // do any provided roles match? if ((provided != null) && (required != null)) { for (int i = 0; i < provided.size(); i++) { @@ -136,7 +136,7 @@ /** * @see digilib.auth.AuthOps#rolesForPath(digilib.servlet.DigilibRequest) */ - public List rolesForPath(DigilibRequest request) throws AuthOpException { + public List rolesForPath(DigilibRequest request) throws AuthOpException { logger.debug("rolesForPath (" + request.getFilePath() + ") by [" @@ -144,14 +144,14 @@ + "]"); // check if the requests address provides a role - List provided = + List provided = authIPs.match(request.getServletRequest().getRemoteAddr()); if ((provided != null) && (provided.contains("ALL"))) { // ALL switches off checking; return null; } // which roles are required? - List required = authPaths.match(request.getFilePath()); + List required = authPaths.match(request.getFilePath()); // do any provided roles match? if ((provided != null) && (required != null)) { for (int i = 0; i < provided.size(); i++) { diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/image/DocuImage.java --- a/servlet/src/digilib/image/DocuImage.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/image/DocuImage.java Tue Dec 21 09:52:16 2010 +0100 @@ -214,11 +214,17 @@ /** * Check image size and type and store in ImageFile f */ - public boolean identify(ImageFile imgf) throws IOException; + public ImageFile identify(ImageFile imgf) throws IOException; /** * Returns a list of supported image formats */ - public Iterator getSupportedFormats(); + public Iterator getSupportedFormats(); + + /** + * returns the underlying image as java.awt.Image (if possible, or null) + * @return + */ + public java.awt.Image getAwtImage(); } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/image/DocuImageImpl.java --- a/servlet/src/digilib/image/DocuImageImpl.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/image/DocuImageImpl.java Tue Dec 21 09:52:16 2010 +0100 @@ -20,16 +20,15 @@ package digilib.image; +import java.awt.Image; import java.awt.Rectangle; -import java.io.File; import java.io.IOException; -import java.io.RandomAccessFile; +import java.io.OutputStream; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.apache.log4j.Logger; -import org.marcoschmidt.image.ImageInfo; import digilib.io.FileOpException; import digilib.io.ImageFile; @@ -37,7 +36,7 @@ /** Simple abstract implementation of the DocuImage interface. * * This implementation provides basic functionality for the utility methods like - * SetUtils, and getKnownFileTypes. Image methods like + * getKnownFileTypes. Image methods like * loadImage, writeImage, getWidth, * getHeight, crop and scale must be * implemented by derived classes. @@ -72,34 +71,7 @@ this.quality = quality; } - /** Check image size and type and store in ImageFile f */ - public boolean identify(ImageFile imgf) throws IOException { - // fileset to store the information - File f = imgf.getFile(); - if (f == null) { - throw new IOException("File not found!"); - } - RandomAccessFile raf = new RandomAccessFile(f, "r"); - // set up ImageInfo object - ImageInfo iif = new ImageInfo(); - iif.setInput(raf); - iif.setCollectComments(false); - iif.setDetermineImageNumber(false); - logger.debug("identifying (ImageInfo) " + f); - // try with ImageInfo first - if (iif.check()) { - ImageSize d = new ImageSize(iif.getWidth(), iif.getHeight()); - imgf.setSize(d); - imgf.setMimetype(iif.getMimeType()); - //logger.debug(" format:"+iif.getFormatName()); - raf.close(); - logger.debug("image size: " + imgf.getSize()); - return true; - } - return false; - } - - /** Crop and scale the current image. + /** Crop and scale the current image. * * The current image is cropped to a rectangle of width, height at position * x_off, y_off. The resulting image is scaled by the factor scale using the @@ -116,7 +88,7 @@ public void cropAndScale( int x_off, int y_off, int width, int height, double scale, int qual) throws ImageOpException { - + // default implementation: first crop, then scale setQuality(qual); crop(x_off, y_off, width, height); scale(scale, scale); @@ -126,6 +98,14 @@ return mimeType; } + /* (non-Javadoc) + * @see digilib.image.DocuImage#identify(digilib.io.ImageFile) + */ + public ImageFile identify(ImageFile imgf) throws IOException { + // just a do-nothing implementation + return null; + } + public void rotate(double angle) throws ImageOpException { // just a do-nothing implementation } @@ -157,10 +137,44 @@ // emtpy implementation } - public Iterator getSupportedFormats() { - List empty = new LinkedList(); + public Iterator getSupportedFormats() { + List empty = new LinkedList(); return empty.iterator(); } - + + public void crop(int xoff, int yoff, int width, int height) + throws ImageOpException { + // TODO Auto-generated method stub + } + + public Image getAwtImage() { + // TODO Auto-generated method stub + return null; + } + + public int getHeight() { + // TODO Auto-generated method stub + return 0; + } + public int getWidth() { + // TODO Auto-generated method stub + return 0; + } + + public void loadImage(ImageFile f) throws FileOpException { + // TODO Auto-generated method stub + + } + + public void scale(double scaleX, double scaleY) throws ImageOpException { + // TODO Auto-generated method stub + + } + + public void writeImage(String mt, OutputStream ostream) + throws FileOpException { + // TODO Auto-generated method stub + } + } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/image/ImageInfoDocuImage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/image/ImageInfoDocuImage.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,51 @@ +/** + * + */ +package digilib.image; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; + +import org.marcoschmidt.image.ImageInfo; + +import digilib.io.ImageFile; + +/** Simple abstract implementation of the DocuImage interface. + * Implements only the identify method using the ImageInfo class. + * @author casties + * + */ +public abstract class ImageInfoDocuImage extends DocuImageImpl { + + /** Check image size and type and store in ImageFile f */ + public ImageFile identify(ImageFile imgf) throws IOException { + // fileset to store the information + File f = imgf.getFile(); + if (f == null) { + throw new IOException("File not found!"); + } + RandomAccessFile raf = new RandomAccessFile(f, "r"); + // set up ImageInfo object + ImageInfo iif = new ImageInfo(); + iif.setInput(raf); + iif.setCollectComments(false); + iif.setDetermineImageNumber(false); + logger.debug("identifying (ImageInfo) " + f); + // try with ImageInfo first + if (iif.check()) { + ImageSize d = new ImageSize(iif.getWidth(), iif.getHeight()); + imgf.setSize(d); + imgf.setMimetype(iif.getMimeType()); + //logger.debug(" format:"+iif.getFormatName()); + raf.close(); + logger.debug("image size: " + imgf.getSize()); + return imgf; + } else { + raf.close(); + } + return null; + } + + +} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/image/ImageJobDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/image/ImageJobDescription.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,492 @@ +package digilib.image; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.io.IOException; + +import org.apache.log4j.Logger; + +import digilib.io.DocuDirCache; +import digilib.io.DocuDirectory; +import digilib.io.FileOpException; +import digilib.io.FileOps; +import digilib.io.FileOps.FileClass; +import digilib.io.ImageFile; +import digilib.io.ImageFileset; +import digilib.servlet.DigilibConfiguration; +import digilib.util.OptionsSet; +import digilib.util.Parameter; +import digilib.util.ParameterMap; + + +/** + * A container class for storing a set of instructional parameters + * used for content generating classes like MakePDF. + * + * This contains the functionality formerly found in Scaler, processRequest, only factorized. + * + * TODO clean up... + * + * @author cmielack, casties + * + */ + +public class ImageJobDescription extends ParameterMap { + + DigilibConfiguration dlConfig = null; + protected static Logger logger = Logger.getLogger("digilib.servlet"); + + ImageFile fileToLoad = null; + ImageFileset fileset = null; + DocuDirectory fileDir = null; + String filePath = null; + ImageSize expectedSourceSize = null; + Float scaleXY = null; + Rectangle2D userImgArea = null; + Rectangle2D outerUserImgArea= null; + Boolean imageSendable = null; + String mimeType; + Integer paramDW; + Integer paramDH; + + /** create empty ImageJobDescription. + * @param dlcfg + */ + public ImageJobDescription(DigilibConfiguration dlcfg) { + super(30); + dlConfig = dlcfg; + } + + + /** set up Parameters + * @see digilib.util.ParameterMap#initParams() + */ + @Override + protected void initParams() { + // url of the page/document (second part) + newParameter("fn", "", null, 's'); + // page number + newParameter("pn", new Integer(1), null, 's'); + // width of client in pixels + newParameter("dw", new Integer(0), null, 's'); + // height of client in pixels + newParameter("dh", new Integer(0), null, 's'); + // left edge of image (float from 0 to 1) + newParameter("wx", new Float(0), null, 's'); + // top edge in image (float from 0 to 1) + newParameter("wy", new Float(0), null, 's'); + // width of image (float from 0 to 1) + newParameter("ww", new Float(1), null, 's'); + // height of image (float from 0 to 1) + newParameter("wh", new Float(1), null, 's'); + // scale factor + newParameter("ws", new Float(1), null, 's'); + // special options like 'fit' for gifs + newParameter("mo", this.options, null, 's'); + // rotation angle (degree) + newParameter("rot", new Float(0), null, 's'); + // contrast enhancement factor + newParameter("cont", new Float(0), null, 's'); + // brightness enhancement factor + newParameter("brgt", new Float(0), null, 's'); + // color multiplicative factors + newParameter("rgbm", "0/0/0", null, 's'); + // color additive factors + newParameter("rgba", "0/0/0", null, 's'); + // display dpi resolution (total) + newParameter("ddpi", new Float(0), null, 's'); + // display dpi X resolution + newParameter("ddpix", new Float(0), null, 's'); + // display dpi Y resolution + newParameter("ddpiy", new Float(0), null, 's'); + // scale factor for mo=ascale + newParameter("scale", new Float(1), null, 's'); + } + + + /* (non-Javadoc) + * @see digilib.servlet.ParameterMap#initOptions() + */ + @Override + protected void initOptions() { + String s = this.getAsString("mo"); + options = new OptionsSet(s); + } + + + /** Creates new ImageJobDescription by merging Parameters from another ParameterMap. + * @param pm + * @param dlcfg + * @return + */ + public static ImageJobDescription getInstance(ParameterMap pm, DigilibConfiguration dlcfg) { + ImageJobDescription newMap = new ImageJobDescription(dlcfg); + // add all params to this map + newMap.params.putAll(pm.getParams()); + newMap.initOptions(); + return newMap; + } + + + public String getMimeType() throws IOException { + if (mimeType == null) { + fileToLoad = getFileToLoad(); + if(! fileToLoad.isChecked()){ + DigilibConfiguration.docuImageIdentify(fileToLoad); + } + mimeType = fileToLoad.getMimetype(); + } + return mimeType; + } + + public ImageFile getFileToLoad() throws IOException { + + if(fileToLoad == null){ + fileset = getFileset(); + + /* select a resolution */ + if (getHiresOnly()) { + // get first element (= highest resolution) + fileToLoad = fileset.getBiggest(); + } else if (getLoresOnly()) { + // enforced lores uses next smaller resolution + fileToLoad = fileset.getNextSmaller(getExpectedSourceSize()); + if (fileToLoad == null) { + // this is the smallest we have + fileToLoad = fileset.getSmallest(); + } + } else { + // autores: use next higher resolution + fileToLoad = fileset.getNextBigger(getExpectedSourceSize()); + if (fileToLoad == null) { + // this is the highest we have + fileToLoad = fileset.getBiggest(); + } + } + logger.info("Planning to load: " + fileToLoad.getFile()); + } + + return fileToLoad; + + } + + public DocuDirectory getFileDirectory() throws FileOpException { + if(fileDir == null){ + DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache"); + String fp = getFilePath(); + fileDir = dirCache.getDirectory(fp); + if (fileDir == null) { + throw new FileOpException("Directory " + getFilePath() + " not found."); + } + } + return fileDir; + } + + public ImageFileset getFileset() throws FileOpException { + if(fileset==null){ + DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache"); + + fileset = (ImageFileset) dirCache.getFile(getFilePath(), getAsInt("pn"), FileClass.IMAGE); + if (fileset == null) { + throw new FileOpException("File " + getFilePath() + "(" + + getAsInt("pn") + ") not found."); + } + } + return fileset; + } + + public String getFilePath() { + if(filePath == null){ + String s = this.getAsString("request.path"); + s += this.getAsString("fn"); + filePath = FileOps.normalName(s); + } + return filePath; + } + + public boolean getHiresOnly(){ + return hasOption("clip") || hasOption("hires"); + } + + public boolean getLoresOnly(){ + return hasOption("lores"); + } + + public boolean getScaleToFit() { + return !(hasOption("clip") || hasOption("osize") || hasOption("ascale")); + } + + public boolean getAbsoluteScale(){ + return hasOption("osize") || hasOption("ascale"); + } + + + public ImageSize getExpectedSourceSize() throws IOException { + if (expectedSourceSize == null){ + expectedSourceSize = new ImageSize(); + if (getScaleToFit()) { + // scale to fit -- calculate minimum source size + float scale = (1 / Math.min(getAsFloat("ww"), getAsFloat("wh"))) * getAsFloat("ws"); + expectedSourceSize.setSize((int) (getDw() * scale), + (int) (getDh() * scale)); + } else if (getAbsoluteScale() && hasOption("ascale")) { + // absolute scale -- apply scale to hires size + expectedSourceSize = getHiresSize().getScaled(getAsFloat("scale")); + } else { + // clip to fit -- source = destination size + expectedSourceSize.setSize((int) (getDw() * getAsFloat("ws")), + (int) (getDh() * getAsFloat("ws"))); + } + } + return expectedSourceSize; + } + + public ImageSize getHiresSize() throws IOException { + logger.debug("get_hiresSize()"); + + ImageSize hiresSize = null; + ImageFileset fileset = getFileset(); + if (getAbsoluteScale()) { + ImageFile hiresFile = fileset.getBiggest(); + if (!hiresFile.isChecked()) { + DigilibConfiguration.docuImageIdentify(hiresFile); + } + hiresSize = hiresFile.getSize(); + } + return hiresSize; + } + + /** Returns image scaling factor. + * Uses image size and user parameters. + * Modifies scaleXY, userImgArea. + * @return + * @throws IOException + * @throws ImageOpException + */ + public float getScaleXY() throws IOException, ImageOpException { + //logger.debug("get_scaleXY()"); + if(scaleXY == null){ + // coordinates and scaling + float areaWidth; + float areaHeight; + float ws = getAsFloat("ws"); + ImageSize imgSize = getFileToLoad().getSize(); + // user window area in [0,1] coordinates + Rectangle2D relUserArea = new Rectangle2D.Float(getAsFloat("wx"), getAsFloat("wy"), + getAsFloat("ww"), getAsFloat("wh")); + // transform from relative [0,1] to image coordinates. + AffineTransform imgTrafo = AffineTransform.getScaleInstance(imgSize + .getWidth(), imgSize.getHeight()); + // transform user coordinate area to image coordinate area + userImgArea = imgTrafo.createTransformedShape( + relUserArea).getBounds2D(); + + if (getScaleToFit()) { + // calculate scaling factors based on inner user area + areaWidth = (float) userImgArea.getWidth(); + areaHeight = (float) userImgArea.getHeight(); + float scaleX = getDw() / areaWidth * ws; + float scaleY = getDh() / areaHeight * ws; + scaleXY = (scaleX > scaleY) ? scaleY : scaleX; + } else if (getAbsoluteScale()) { + // absolute scaling factor + if (hasOption("osize")) { + // get original resolution from metadata + fileset.checkMeta(); + float origResX = fileset.getResX(); + float origResY = fileset.getResY(); + if ((origResX == 0) || (origResY == 0)) { + throw new ImageOpException("Missing image DPI information!"); + } + if ((getAsFloat("ddpix") == 0) || (getAsFloat("ddpiy") == 0)) { + throw new ImageOpException("Missing display DPI information!"); + } + // calculate absolute scale factor + float sx = getAsFloat("ddpix") / origResX; + float sy = getAsFloat("ddpiy") / origResY; + // currently only same scale -- mean value + scaleXY = (sx + sy) / 2f; + } else { + scaleXY = getAsFloat("scale"); + } + // we need to correct the factor if we use a pre-scaled image + ImageSize hiresSize = getHiresSize(); + if (imgSize.getWidth() != hiresSize.getWidth()) { + scaleXY *= (float)hiresSize.getWidth() / (float)imgSize.getWidth(); + } + areaWidth = getDw() / scaleXY * ws; + areaHeight = getDh() / scaleXY * ws; + // reset user area size + userImgArea.setRect(userImgArea.getX(), userImgArea.getY(), + areaWidth, areaHeight); + } else { + // crop to fit -- don't scale + areaWidth = getDw() * ws; + areaHeight = getDh() * ws; + // reset user area size + userImgArea.setRect(userImgArea.getX(), userImgArea.getY(), + areaWidth, areaHeight); + scaleXY = 1f; + } + } + return (float) scaleXY; + } + + public int getDw() throws IOException { + logger.debug("get_paramDW()"); + if (paramDW == null) { + + paramDW = getAsInt("dw"); + paramDH = getAsInt("dh"); + + float imgAspect = getFileToLoad().getAspect(); + if (paramDW == 0) { + // calculate dw + paramDW = Math.round(paramDH * imgAspect); + setValue("dw", paramDW); + } else if (paramDH == 0) { + // calculate dh + paramDH = Math.round(paramDW / imgAspect); + setValue("dh", paramDH); + } + } + return paramDW; + } + + public int getDh() throws IOException { + logger.debug("get_paramDH()"); + if (paramDH == null) { + + paramDW = getAsInt("dw"); + paramDH = getAsInt("dh"); + + float imgAspect = getFileToLoad().getAspect(); + if (paramDW == 0) { + // calculate dw + paramDW = Math.round(paramDH * imgAspect); + setValue("dw", paramDW); + } else if (paramDH == 0) { + // calculate dh + paramDH = Math.round(paramDW / imgAspect); + setValue("dh", paramDH); + } + } + return paramDH; + } + + public Integer getScaleQual(){ + logger.debug("get_scaleQual()"); + Integer qual = dlConfig.getAsInt("default-quality"); + if(hasOption("q0")) + qual = 0; + else if(hasOption("q1")) + qual = 1; + else if(hasOption("q2")) + qual = 2; + return qual; + } + + + public Rectangle2D getUserImgArea() throws IOException, ImageOpException{ + if(userImgArea == null) { + // getScaleXY sets userImgArea + getScaleXY(); + } + return userImgArea; + + } + + public Rectangle2D getOuterUserImgArea() throws IOException, ImageOpException { + if(outerUserImgArea == null){ + outerUserImgArea = getUserImgArea(); + + // image size in pixels + ImageSize imgSize = getFileToLoad().getSize(); + Rectangle2D imgBounds = new Rectangle2D.Float(0, 0, imgSize.getWidth(), + imgSize.getHeight()); + + // clip area at the image border + outerUserImgArea = outerUserImgArea.createIntersection(imgBounds); + + // check image parameters sanity + scaleXY = getScaleXY(); + logger.debug("outerUserImgArea.getWidth()=" + outerUserImgArea.getWidth()); + logger.debug("get_scaleXY() * outerUserImgArea.getWidth() = " + (scaleXY * outerUserImgArea.getWidth())); + + if ((outerUserImgArea.getWidth() < 1) + || (outerUserImgArea.getHeight() < 1) + || (scaleXY * outerUserImgArea.getWidth() < 2) + || (scaleXY * outerUserImgArea.getHeight() < 2)) { + logger.error("ERROR: invalid scale parameter set!"); + throw new ImageOpException("Invalid scale parameter set!"); + } + } + return outerUserImgArea; + } + + + public float[] getRGBM(){ + float[] paramRGBM = null;//{0f,0f,0f}; + Parameter p = params.get("rgbm"); + if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) { + return p.parseAsFloatArray("/"); + } + return paramRGBM; + } + + public float[] getRGBA(){ + float[] paramRGBA = null;//{0f,0f,0f}; + Parameter p = params.get("rgba"); + if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) { + paramRGBA = p.parseAsFloatArray("/"); + } + return paramRGBA; + } + + /** Has send-as-file been requested? + * @return + */ + public boolean getSendAsFile(){ + return hasOption("file") + || hasOption("rawfile"); + } + + /** Could the image be sent without processing? + * Takes image type and additional image operations into account. + * Does not check requested size transformation. + * @return + * @throws IOException + */ + public boolean isImageSendable() throws IOException { + // cached result? + if (imageSendable == null) { + String mimeType = getMimeType(); + imageSendable = ( (mimeType.equals("image/jpeg") + || mimeType.equals("image/png") + || mimeType.equals("image/gif") ) + && + !(hasOption("hmir") + || hasOption("vmir") + || (getAsFloat("rot") != 0.0) + || (getRGBM() != null) + || (getRGBA() != null) + || (getAsFloat("cont") != 0.0) + || (getAsFloat("brgt") != 0.0))); + } + + return imageSendable; + } + + + public boolean isTransformRequired() throws IOException { + ImageSize is = getFileToLoad().getSize(); + ImageSize ess = getExpectedSourceSize(); + // nt = no transform required + boolean nt = isImageSendable() && ( + // lores: send if smaller + (getLoresOnly() && is.isSmallerThan(ess)) + // else send if it fits + || (!(getLoresOnly() || getHiresOnly()) && is.fitsIn(ess))); + return ! nt; + } +} \ No newline at end of file diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/image/ImageLoaderDocuImage.java --- a/servlet/src/digilib/image/ImageLoaderDocuImage.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/image/ImageLoaderDocuImage.java Tue Dec 21 09:52:16 2010 +0100 @@ -52,7 +52,7 @@ import digilib.io.ImageFileset; /** Implementation of DocuImage using the ImageLoader API of Java 1.4 and Java2D. */ -public class ImageLoaderDocuImage extends DocuImageImpl { +public class ImageLoaderDocuImage extends ImageInfoDocuImage { /** image object */ protected BufferedImage img; @@ -117,20 +117,21 @@ } /* returns a list of supported image formats */ - public Iterator getSupportedFormats() { + public Iterator getSupportedFormats() { String[] formats = ImageIO.getReaderFormatNames(); return Arrays.asList(formats).iterator(); } /** Check image size and type and store in ImageFile f */ - public boolean identify(ImageFile imgf) throws IOException { + public ImageFile identify(ImageFile imageFile) throws IOException { // try parent method first - if (super.identify(imgf)) { - return true; + ImageFile imf = super.identify(imageFile); + if (imf != null) { + return imf; } // fileset to store the information - ImageFileset imgfs = imgf.getParent(); - File f = imgf.getFile(); + ImageFileset imgfs = imageFile.getParent(); + File f = imageFile.getFile(); if (f == null) { throw new IOException("File not found!"); } @@ -138,47 +139,27 @@ /* * try ImageReader */ - RandomAccessFile raf = new RandomAccessFile(f, "r"); - ImageInputStream istream = ImageIO.createImageInputStream(raf); - Iterator readers = ImageIO.getImageReaders(istream); - if (readers.hasNext()) { - ImageReader reader = (ImageReader) readers.next(); - /* are there more readers? */ - logger.debug("ImageIO: this reader: " + reader.getClass()); - while (readers.hasNext()) { - logger.debug("ImageIO: next reader: " - + readers.next().getClass()); - } - try { - reader.setInput(istream); - ImageSize d = new ImageSize(reader.getWidth(0), reader.getHeight(0)); - imgf.setSize(d); - //String t = reader.getFormatName(); - String t = FileOps.mimeForFile(f); - imgf.setMimetype(t); - //logger.debug(" format:"+t); - if (imgfs != null) { - imgfs.setAspect(d); - } - return true; - } finally { - // dispose the reader to free resources - reader.dispose(); - raf.close(); - } + if ((reader == null) || (imgFile != imageFile.getFile())) { + getReader(imageFile); } - throw new FileOpException("ERROR: unknown image file format!"); + ImageSize d = new ImageSize(reader.getWidth(0), reader.getHeight(0)); + imageFile.setSize(d); + // String t = reader.getFormatName(); + String t = FileOps.mimeForFile(f); + imageFile.setMimetype(t); + // logger.debug(" format:"+t); + if (imgfs != null) { + imgfs.setAspect(d); + } + return imageFile; } - /* load image file */ public void loadImage(ImageFile f) throws FileOpException { logger.debug("loadImage " + f.getFile()); try { img = ImageIO.read(f.getFile()); - if (img == null) { - throw new FileOpException("Unable to load File!"); - } + mimeType = f.getMimetype(); } catch (IOException e) { throw new FileOpException("Error reading image."); } @@ -196,23 +177,27 @@ // clean up old reader dispose(); } - // System.gc(); RandomAccessFile rf = new RandomAccessFile(f.getFile(), "r"); ImageInputStream istream = new FileImageInputStream(rf); - // Iterator readers = ImageIO.getImageReaders(istream); + Iterator readers; String mt = f.getMimetype(); - logger.debug("File type:" + mt); - Iterator readers = ImageIO.getImageReadersByMIMEType(mt); + if (mt == null) { + logger.debug("No mime-type. Trying automagic."); + readers = ImageIO.getImageReaders(istream); + } else { + logger.debug("File type:" + mt); + readers = ImageIO.getImageReadersByMIMEType(mt); + } if (!readers.hasNext()) { - throw new FileOpException("Unable to load File!"); + rf.close(); + throw new FileOpException("Can't find Reader to load File!"); } - reader = (ImageReader) readers.next(); + reader = readers.next(); /* are there more readers? */ logger.debug("ImageIO: this reader: " + reader.getClass()); - while (readers.hasNext()) { + /* while (readers.hasNext()) { logger.debug("ImageIO: next reader: " + readers.next().getClass()); - } - // */ + } */ reader.setInput(istream); imgFile = f.getFile(); return reader; @@ -222,7 +207,6 @@ public void loadSubimage(ImageFile f, Rectangle region, int prescale) throws FileOpException { logger.debug("loadSubimage"); - // System.gc(); try { if ((reader == null) || (imgFile != f.getFile())) { getReader(f); @@ -236,13 +220,11 @@ // read image logger.debug("loading.."); img = reader.read(0, readParam); + mimeType = f.getMimetype(); logger.debug("loaded"); } catch (IOException e) { throw new FileOpException("Unable to load File!"); } - if (img == null) { - throw new FileOpException("Unable to load File!"); - } } /* write image of type mt to Stream */ @@ -325,15 +307,14 @@ AffineTransformOp scaleOp = new AffineTransformOp(AffineTransform .getScaleInstance(scale, scale), renderHint); BufferedImage scaledImg = null; - // enforce destination image type (*Java2D BUG*) + /* enforce destination image type (*Java2D BUG*) int type = img.getType(); - // FIXME: which type would be best? if ((quality > 0) && (type != 0)) { logger.debug("creating destination image"); Rectangle2D dstBounds = scaleOp.getBounds2D(img); scaledImg = new BufferedImage((int) dstBounds.getWidth(), (int) dstBounds.getHeight(), type); - } + } */ logger.debug("scaling..."); scaledImg = scaleOp.filter(img, scaledImg); if (scaledImg == null) { @@ -344,7 +325,6 @@ logger.debug("SCALE: " + scale + " ->" + scaledImg.getWidth() + "x" + scaledImg.getHeight()); img = scaledImg; - scaledImg = null; } public void blur(int radius) throws ImageOpException { @@ -364,16 +344,14 @@ // blur with convolve operation ConvolveOp blurOp = new ConvolveOp(blur, ConvolveOp.EDGE_NO_OP, renderHint); + BufferedImage blurredImg = null; // blur needs explicit destination image type for color *Java2D BUG* - BufferedImage blurredImg = null; if (img.getType() == BufferedImage.TYPE_3BYTE_BGR) { + logger.debug("blur: fixing destination image type"); blurredImg = new BufferedImage(img.getWidth(), img.getHeight(), img .getType()); } blurredImg = blurOp.filter(img, blurredImg); - if (blurredImg == null) { - throw new ImageOpException("Unable to scale"); - } img = blurredImg; } @@ -381,9 +359,6 @@ throws ImageOpException { // setup Crop BufferedImage croppedImg = img.getSubimage(x_off, y_off, width, height); - // DEBUG - // util.dprintln(2, " time - // "+(System.currentTimeMillis()-startTime)+"ms"); if (croppedImg == null) { throw new ImageOpException("Unable to crop"); } @@ -413,12 +388,10 @@ } public void enhanceRGB(float[] rgbm, float[] rgba) throws ImageOpException { - /* * The number of constants must match the number of bands in the image. * We do only 3 (RGB) bands. */ - int ncol = img.getColorModel().getNumColorComponents(); if ((ncol != 3) || (rgbm.length != 3) || (rgba.length != 3)) { logger @@ -491,17 +464,12 @@ double xoff = rotbounds.getX(); double yoff = rotbounds.getY(); // move image back in line - trafo - .preConcatenate(AffineTransform.getTranslateInstance(-xoff, - -yoff)); + trafo.preConcatenate(AffineTransform.getTranslateInstance(-xoff, -yoff)); // transform image rotOp = new AffineTransformOp(trafo, renderHint); BufferedImage rotImg = rotOp.filter(img, null); // calculate new bounding box // Rectangle2D bounds = rotOp.getBounds2D(img); - if (rotImg == null) { - throw new ImageOpException("Unable to rotate"); - } img = rotImg; // crop new image (with self-made rounding) /* @@ -536,9 +504,6 @@ AffineTransformOp mirOp = new AffineTransformOp(new AffineTransform(mx, 0, 0, my, tx, ty), renderHint); BufferedImage mirImg = mirOp.filter(img, null); - if (mirImg == null) { - throw new ImageOpException("Unable to mirror"); - } img = mirImg; } @@ -562,7 +527,7 @@ img = null; } - public Image getImage(){ + public Image getAwtImage(){ return (Image) img; } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/image/ImageOps.java --- a/servlet/src/digilib/image/ImageOps.java Wed Jul 14 16:36:42 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* ImageOps -- convenience methods for images - - Digital Image Library servlet components - - Copyright (C) 2004 Robert Casties (robcast@mail.berlios.de) - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - Please read license.txt for the full details. A copy of the GPL - may be found at http://www.gnu.org/copyleft/lgpl.html - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * Created on 13.10.2004 - */ -package digilib.image; - -import java.io.IOException; - -import digilib.io.ImageFile; - -/** - * convenience methods for images - * - * @author casties - */ -public class ImageOps { - - public static final int TYPE_AUTO = 0; - public static final int TYPE_JPEG = 1; - public static final int TYPE_PNG = 2; - - private static DocuImage docuImg; - - public static boolean checkFile(ImageFile imgf) throws IOException { - return docuImg.identify(imgf); - } - - public static void setDocuImage(DocuImage di) { - docuImg = di; - } - - public static DocuImage getDocuImage() { - return docuImg; - } -} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/image/ImageWorker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/image/ImageWorker.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,154 @@ +/** Worker (Callable) that renders an image. + * + */ +package digilib.image; + +import java.awt.Rectangle; +import java.io.IOException; +import java.util.concurrent.Callable; + +import org.apache.log4j.Logger; + +import digilib.io.FileOpException; +import digilib.servlet.DigilibConfiguration; + +/** Worker that renders an image. + * + * @author casties + * + */ +public class ImageWorker implements Callable { + + + protected static Logger logger = Logger.getLogger(ImageWorker.class); + private DigilibConfiguration dlConfig; + private ImageJobDescription jobinfo; + + public ImageWorker(DigilibConfiguration dlConfig, ImageJobDescription jobinfo) { + super(); + this.dlConfig = dlConfig; + this.jobinfo = jobinfo; + } + + /** + * render and return the image + */ + @Override + public DocuImage call() throws FileOpException, IOException, ImageOpException { + + logger.debug("image worker starting"); + long startTime = System.currentTimeMillis(); + + /* crop and scale image */ + + // new DocuImage instance + DocuImage docuImage = DigilibConfiguration.getDocuImageInstance(); + if (docuImage == null) { + throw new ImageOpException("Unable to load DocuImage class!"); + } + + // set interpolation quality + docuImage.setQuality(jobinfo.getScaleQual()); + + Rectangle loadRect = jobinfo.getOuterUserImgArea().getBounds(); + float scaleXY = jobinfo.getScaleXY(); + + // use subimage loading if possible + if (docuImage.isSubimageSupported()) { + logger.debug("Subimage: scale " + scaleXY + " = " + (1 / scaleXY)); + float subf = 1f; + float subsamp = 1f; + if (scaleXY < 1) { + subf = 1 / scaleXY; + // for higher quality reduce subsample factor by minSubsample + if (jobinfo.getScaleQual() > 0) { + subsamp = (float) Math.max(Math.floor(subf / dlConfig.getAsFloat("subsample-minimum")), 1d); + } else { + subsamp = (float) Math.floor(subf); + } + scaleXY = subsamp / subf; + logger.debug("Using subsampling: " + subsamp + " rest " + + scaleXY); + } + + docuImage.loadSubimage(jobinfo.getFileToLoad(), loadRect, (int) subsamp); + + logger.debug("SUBSAMP: " + subsamp + " -> " + docuImage.getWidth() + + "x" + docuImage.getHeight()); + + docuImage.scale(scaleXY, scaleXY); + + } else { + // else load and crop the whole file + docuImage.loadImage(jobinfo.getFileToLoad()); + docuImage.crop((int) loadRect.getX(), (int) loadRect.getY(), + (int) loadRect.getWidth(), (int) loadRect.getHeight()); + + docuImage.scale(scaleXY, scaleXY); + } + + // mirror image + // operation mode: "hmir": mirror horizontally, "vmir": mirror + // vertically + if (jobinfo.hasOption("hmir")) { + docuImage.mirror(0); + } + if (jobinfo.hasOption("vmir")) { + docuImage.mirror(90); + } + + // rotate image + if (jobinfo.getAsFloat("rot") != 0d) { + docuImage.rotate(jobinfo.getAsFloat("rot")); + /* if (jobinfo.get_wholeRotArea()) { + // crop to the inner bounding box + float xcrop = (float) (docuImage.getWidth() - jobinfo.get_innerUserImgArea().getWidth() + * scaleXY); + float ycrop = (float) (docuImage.getHeight() - jobinfo.get_innerUserImgArea().getHeight() + * scaleXY); + if ((xcrop > 0) || (ycrop > 0)) { + // only crop smaller + xcrop = (xcrop > 0) ? xcrop : 0; + ycrop = (ycrop > 0) ? ycrop : 0; + // crop image + docuImage.crop((int) (xcrop / 2), (int) (ycrop / 2), + (int) (docuImage.getWidth() - xcrop), + (int) (docuImage.getHeight() - ycrop)); + } + } */ + + } + + // color modification + float[] paramRGBM = jobinfo.getRGBM(); + float[] paramRGBA = jobinfo.getRGBA(); + if ((paramRGBM != null) || (paramRGBA != null)) { + // make sure we actually have two arrays + if (paramRGBM == null) { + paramRGBM = new float[3]; + } + if (paramRGBA == null) { + paramRGBA = new float[3]; + } + // calculate "contrast" values (c=2^x) + float[] mult = new float[3]; + for (int i = 0; i < 3; i++) { + mult[i] = (float) Math.pow(2, (float) paramRGBM[i]); + } + docuImage.enhanceRGB(mult, paramRGBA); + } + + // contrast and brightness enhancement + float paramCONT = jobinfo.getAsFloat("cont"); + float paramBRGT = jobinfo.getAsFloat("brgt"); + if ((paramCONT != 0f) || (paramBRGT != 0f)) { + float mult = (float) Math.pow(2, paramCONT); + docuImage.enhance(mult, paramBRGT); + } + + logger.debug("rendered in " + (System.currentTimeMillis() - startTime) + "ms"); + + return docuImage; + } + +} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/image/JAIDocuImage.java --- a/servlet/src/digilib/image/JAIDocuImage.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/image/JAIDocuImage.java Tue Dec 21 09:52:16 2010 +0100 @@ -49,7 +49,7 @@ import digilib.io.ImageFileset; /** A DocuImage implementation using Java Advanced Imaging Library. */ -public class JAIDocuImage extends DocuImageImpl { +public class JAIDocuImage extends ImageInfoDocuImage { protected RenderedImage img; @@ -84,30 +84,30 @@ } /* returns a list of supported image formats */ - public Iterator getSupportedFormats() { - Enumeration codecs = ImageCodec.getCodecs(); - List formats = new ArrayList(5); - for (Object codec = codecs.nextElement(); codecs.hasMoreElements(); codec = codecs - .nextElement()) { - logger - .debug("known format:" - + ((ImageCodec) codec).getFormatName()); - formats.add(((ImageCodec) codec).getFormatName()); - } - logger.debug("tilecachesize:" - + JAI.getDefaultInstance().getTileCache().getMemoryCapacity()); - return formats.iterator(); - } + @SuppressWarnings("unchecked") // ImageCodec.getCodecs() returns a naked Enumeration + public Iterator getSupportedFormats() { + Enumeration codecs = ImageCodec.getCodecs(); + List formats = new ArrayList(); + for (ImageCodec codec = codecs.nextElement(); codecs.hasMoreElements(); codec = codecs + .nextElement()) { + logger.debug("known format:"+codec.getFormatName()); + formats.add(codec.getFormatName()); + } + logger.debug("tilecachesize:" + + JAI.getDefaultInstance().getTileCache().getMemoryCapacity()); + return formats.iterator(); + } /* Check image size and type and store in ImageFile f */ - public boolean identify(ImageFile imgf) throws IOException { - // try parent method first - if (super.identify(imgf)) { - return true; + public ImageFile identify(ImageFile imageFile) throws IOException { + // try parent method first + ImageFile imf = super.identify(imageFile); + if (imf != null) { + return imf; } // fileset to store the information - ImageFileset imgfs = imgf.getParent(); - File f = imgf.getFile(); + ImageFileset imgfs = imageFile.getParent(); + File f = imageFile.getFile(); if (f == null) { throw new IOException("File not found!"); } @@ -118,15 +118,15 @@ try { RenderedOp img = JAI.create("fileload", f.getAbsolutePath()); ImageSize d = new ImageSize(img.getWidth(), img.getHeight()); - imgf.setSize(d); + imageFile.setSize(d); String t = FileOps.mimeForFile(f); - imgf.setMimetype(t); + imageFile.setMimetype(t); // logger.debug(" format:"+t); if (imgfs != null) { imgfs.setAspect(d); } - logger.debug("image size: " + imgf.getSize()); - return true; + logger.debug("image size: " + imageFile.getSize()); + return imageFile; } catch (Exception e) { throw new FileOpException("ERROR: unknown image file format!"); } @@ -138,6 +138,7 @@ if (img == null) { throw new FileOpException("Unable to load File!"); } + mimeType = f.getMimetype(); } /* Load an image file into the Object. */ @@ -168,6 +169,7 @@ // scale logger.debug("loadSubimage: scale"); img = JAI.create("scale", sp); + mimeType = f.getMimetype(); } } @@ -330,11 +332,6 @@ logger.debug("CROP: " + x_off + "," + y_off + ", " + width + "," + height + " ->" + croppedImg.getWidth() + "x" + croppedImg.getHeight()); - // DEBUG - - if (croppedImg == null) { - throw new ImageOpException("Unable to crop"); - } img = croppedImg; } @@ -384,11 +381,6 @@ logger.debug("ROTATE: " + x + "," + y + ", " + angle + " (" + rangle + ")" + " ->" + rotImg.getWidth() + "x" + rotImg.getHeight()); - // DEBUG - - if (rotImg == null) { - throw new ImageOpException("Unable to rotate"); - } img = rotImg; } @@ -442,10 +434,6 @@ logger.debug("ENHANCE: *" + mult + ", +" + add + " ->" + enhImg.getWidth() + "x" + enhImg.getHeight()); // DEBUG - - if (enhImg == null) { - throw new ImageOpException("Unable to enhance"); - } img = enhImg; } @@ -472,11 +460,6 @@ logger.debug("ENHANCE_RGB: *" + rgbm + ", +" + rgba + " ->" + enhImg.getWidth() + "x" + enhImg.getHeight()); - // DEBUG - - if (enhImg == null) { - throw new ImageOpException("Unable to enhanceRGB"); - } img = enhImg; } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/image/JAIImageLoaderDocuImage.java --- a/servlet/src/digilib/image/JAIImageLoaderDocuImage.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/image/JAIImageLoaderDocuImage.java Tue Dec 21 09:52:16 2010 +0100 @@ -20,6 +20,7 @@ package digilib.image; +import java.awt.Image; import java.awt.Rectangle; import java.awt.image.renderable.ParameterBlock; import java.io.File; @@ -89,6 +90,7 @@ if (img == null) { throw new FileOpException("Unable to load File!"); } + mimeType = f.getMimetype(); } /* Get an ImageReader for the image file. */ @@ -98,11 +100,11 @@ RandomAccessFile rf = new RandomAccessFile(f.getFile(), "r"); ImageInputStream istream = new FileImageInputStream(rf); //Iterator readers = ImageIO.getImageReaders(istream); - Iterator readers = ImageIO.getImageReadersByMIMEType(f.getMimetype()); + Iterator readers = ImageIO.getImageReadersByMIMEType(f.getMimetype()); if (! readers.hasNext()) { throw new FileOpException("Unable to load File!"); } - reader = (ImageReader) readers.next(); + reader = readers.next(); logger.debug("JAIImageIO: this reader: " + reader.getClass()); while (readers.hasNext()) { logger.debug(" next reader: " + readers.next().getClass()); @@ -139,6 +141,7 @@ throw new FileOpException("Unable to load File!"); } imgFile = f.getFile(); + mimeType = f.getMimetype(); } @@ -166,7 +169,13 @@ } } - /* (non-Javadoc) + @Override + public Image getAwtImage() { + // TODO Auto-generated method stub + return (Image) img; + } + + /* (non-Javadoc) * @see java.lang.Object#finalize() */ protected void finalize() throws Throwable { diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/io/AliasingDocuDirCache.java --- a/servlet/src/digilib/io/AliasingDocuDirCache.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/io/AliasingDocuDirCache.java Tue Dec 21 09:52:16 2010 +0100 @@ -23,9 +23,10 @@ package digilib.io; import java.io.File; -import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; +import digilib.io.FileOps.FileClass; import digilib.servlet.DigilibConfiguration; /** @@ -36,16 +37,16 @@ /** * @param baseDirs - * @param fileClasses + * @param fcs * @param confFileName * @throws FileOpException */ - public AliasingDocuDirCache(String[] baseDirs, int[] fileClasses, + public AliasingDocuDirCache(String[] baseDirs, FileClass[] fcs, File confFile, DigilibConfiguration dlConfig) throws FileOpException { // create standard DocuDirCache - super(baseDirs, fileClasses, dlConfig); - Map pathMap = null; + super(baseDirs, fcs, dlConfig); + Map pathMap = null; // read alias config file try { // load into pathMap @@ -63,18 +64,16 @@ * load map entries into cache */ - for (Iterator i = pathMap.keySet().iterator(); i.hasNext();) { - String link = (String) i.next(); - String dir = (String) pathMap.get(link); - if (dir == null) { + for (Entry linkdir: pathMap.entrySet()) { + if (linkdir.getValue() == null) { logger.error("Key mismatch in mapping file!"); break; } - DocuDirectory destDir = new DocuDirectory(dir, this); + DocuDirectory destDir = new DocuDirectory(linkdir.getValue(), this); if (destDir.isValid()) { - logger.debug("Aliasing dir: " + link); + logger.debug("Aliasing dir: " + linkdir.getKey()); // add the alias name - putName(FileOps.normalName(link), destDir); + putName(FileOps.normalName(linkdir.getKey()), destDir); // add the real dir putDir(destDir); } @@ -87,13 +86,12 @@ * @param name * @param newdir */ - public void putName(String name, DocuDirectory newdir) { - if (map.containsKey(name)) { - logger - .warn("Duplicate key in AliasingDocuDirCache.put -- ignored!"); - } else { - map.put(name, newdir); - } - } + public void putName(String name, DocuDirectory newdir) { + if (map.containsKey(name)) { + logger.warn("Duplicate key in AliasingDocuDirCache.put -- ignored!"); + } else { + map.put(name, newdir); + } + } } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/io/DigilibInfoReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/DigilibInfoReader.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,76 @@ +package digilib.io; + +/** DigilibInfoReader + * A class for reading the information from info.xml files used in digilib image directories. + * + */ + +import java.io.File; +import java.util.List; + +import org.apache.log4j.Logger; +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.input.SAXBuilder; + + + +public class DigilibInfoReader { + + /** gengeral logger for this class */ + protected static Logger logger = Logger.getLogger("digilib.servlet"); + + private String filename = null; + //private static String base_element = "info"; + + public DigilibInfoReader(String fn){ + filename = fn; + } + + /** + * Returns the attribute defined by 'attr' as a String. + * + * @param attr + * @return + */ + @SuppressWarnings("unchecked") // Element.getChildren() returns naked List + public String getAsString(String attr){ + try{ + SAXBuilder builder = new SAXBuilder(); + Document doc = builder.build(new File(filename)); + Element root = doc.getRootElement(); + List mainElements = root.getChildren(); + // logger.debug("XML mainElements:"+mainElements.toString()); + + for(int i=0; i map = null; /** names of base directories */ String[] baseDirNames = null; /** array of allowed file classes (image/text) */ - private int[] fileClasses = null; + private FileClass[] fileClasses = null; /** number of files in the whole cache (approximate) */ long numFiles = 0; @@ -59,9 +59,6 @@ /** number of cache misses */ long misses = 0; - /** use safe (but slow) indexing */ - boolean safeDirIndex = false; - /** the root directory element */ public static Directory ROOT = null; @@ -71,12 +68,11 @@ * @param bd * base directory names */ - public DocuDirCache(String[] bd, int[] fileClasses, + public DocuDirCache(String[] bd, FileClass[] fcs, DigilibConfiguration dlConfig) { baseDirNames = bd; - map = new HashMap(); - this.fileClasses = fileClasses; - safeDirIndex = dlConfig.getAsBoolean("safe-dir-index"); + map = new HashMap(); + this.fileClasses = fcs; } /** @@ -87,10 +83,9 @@ */ public DocuDirCache(String[] bd) { baseDirNames = bd; - map = new HashMap(); + map = new HashMap(); // default file class is CLASS_IMAGE - fileClasses = new int[1]; - fileClasses[0] = FileOps.CLASS_IMAGE; + fileClasses = new FileClass[] { FileClass.IMAGE }; } /** @@ -127,7 +122,7 @@ String parent = FileOps.parent(newDir.getDirName()); if (parent != "") { // check the parent in the cache - DocuDirectory pd = (DocuDirectory) map.get(parent); + DocuDirectory pd = map.get(parent); if (pd == null) { // the parent is unknown pd = new DocuDirectory(parent, this); @@ -149,11 +144,9 @@ * find all children and their children. * @return */ - public List getChildren(String dirname, boolean recurse) { - List l = new LinkedList(); - for (Iterator i = map.keySet().iterator(); i.hasNext();) { - String n = (String) i.next(); - DocuDirectory dd = (DocuDirectory) map.get(n); + public List getChildren(String dirname, boolean recurse) { + List l = new LinkedList(); + for (DocuDirectory dd: map.values()) { if (recurse) { if (dd.getDirName().startsWith(dirname)) { l.add(dd); @@ -182,12 +175,12 @@ * file class * @return */ - public DocuDirent getFile(String fn, int in, int fc) { + public DocuDirent getFile(String fn, int in, FileClass fc) { DocuDirectory dd; // file number is 1-based, vector index is 0-based int n = in - 1; // first, assume fn is a directory and look in the cache - dd = (DocuDirectory) map.get(fn); + dd = map.get(fn); // logger.debug("fn: " + fn); // logger.debug("dd: " + dd); if (dd == null) { @@ -213,7 +206,7 @@ String d = FileOps.parent(fn); // try it in the cache // logger.debug(fn + " is a file in dir " + d); - dd = (DocuDirectory) map.get(d); + dd = map.get(d); if (dd == null) { // try to read from disk dd = new DocuDirectory(d, this); @@ -262,7 +255,7 @@ public DocuDirectory getDirectory(String fn) { DocuDirectory dd; // first, assume fn is a directory and look in the cache - dd = (DocuDirectory) map.get(fn); + dd = map.get(fn); if (dd == null) { // cache miss misses++; @@ -278,7 +271,7 @@ // maybe it's a file if (f.canRead()) { // try the parent directory in the cache - dd = (DocuDirectory) map.get(f.getParent()); + dd = map.get(f.getParent()); if (dd == null) { // try to read from disk dd = new DocuDirectory(f.getParent(), this); @@ -350,14 +343,14 @@ /** * @return */ - public int[] getFileClasses() { + public FileClass[] getFileClasses() { return fileClasses; } /** * @param fileClasses */ - public void setFileClasses(int[] fileClasses) { + public void setFileClasses(FileClass[] fileClasses) { this.fileClasses = fileClasses; } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/io/DocuDirectory.java --- a/servlet/src/digilib/io/DocuDirectory.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/io/DocuDirectory.java Tue Dec 21 09:52:16 2010 +0100 @@ -25,19 +25,20 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Map; import org.xml.sax.SAXException; +import digilib.io.FileOps.FileClass; + /** * @author casties */ public class DocuDirectory extends Directory { /** list of files (DocuDirent) */ - private ArrayList[] list = null; + private List> list = null; /** directory object is valid (exists on disk) */ private boolean isValid = false; @@ -49,13 +50,13 @@ private String dirName = null; /** directory metadata */ - private Map dirMeta = null; + private MetadataMap dirMeta = null; /** state of metadata is valid */ private boolean metaChecked = false; /** unresolved file metadata */ - private Map unresolvedFileMeta = null; + private Map unresolvedFileMeta = null; /** time of last access of this object (not the filesystem) */ private long objectATime = 0; @@ -89,8 +90,13 @@ */ protected void initDir() { String baseDirName = cache.getBaseDirNames()[0]; - // clear directory first - list = new ArrayList[FileOps.NUM_CLASSES]; + // clear directory list + FileClass[] fcs = FileClass.values(); + list = new ArrayList>(fcs.length); + // create empty list for all classes + for (@SuppressWarnings("unused") FileClass fc: fcs) { + list.add(null); + } isValid = false; dirMTime = 0; // the first directory has to exist @@ -102,7 +108,7 @@ * */ public int size() { - return ((list != null) && (list[0] != null)) ? list[0].size() : 0; + return ((list != null) && (list.get(0) != null)) ? list.get(0).size() : 0; } /** @@ -111,21 +117,21 @@ * @param fc * fileClass */ - public int size(int fc) { - return ((list != null) && (list[fc] != null)) ? list[fc].size() : 0; + public int size(FileClass fc) { + return ((list != null) && (list.get(fc.ordinal()) != null)) ? list.get(fc.ordinal()).size() : 0; } /** - * Returns the ImageFile at the index. + * Returns the ImageFileSet at the index. * * @param index * @return */ public ImageFileset get(int index) { - if ((list == null) || (list[0] == null) || (index >= list[0].size())) { + if ((list == null) || (list.get(0) == null) || (index >= list.get(0).size())) { return null; } - return (ImageFileset) list[0].get(index); + return (ImageFileset) list.get(0).get(index); } /** @@ -136,11 +142,11 @@ * fileClass * @return */ - public DocuDirent get(int index, int fc) { - if ((list == null) || (list[fc] == null) || (index >= list[fc].size())) { + public DocuDirent get(int index, FileClass fc) { + if ((list == null) || (list.get(fc.ordinal()) == null) || (index >= list.get(fc.ordinal()).size())) { return null; } - return (DocuDirent) list[fc].get(index); + return (DocuDirent) list.get(fc.ordinal()).get(index); } /** @@ -180,11 +186,8 @@ * extensions) but slower. */ File[] allFiles = null; - if (cache.safeDirIndex) { - allFiles = dir.listFiles(new FileOps.ReadableFileFilter()); - } else { - allFiles = dir.listFiles(); - } + // allFiles = dir.listFiles(new FileOps.ReadableFileFilter()); + allFiles = dir.listFiles(); //logger.debug(" done"); if (allFiles == null) { // not a directory @@ -210,10 +213,9 @@ } // go through all file classes - for (int classIdx = 0; classIdx < FileOps.NUM_CLASSES; classIdx++) { - int fileClass = cache.getFileClasses()[classIdx]; - //logger.debug("filtering directory "+dir.getPath()+" for class - // "+fc); + //for (int classIdx = 0; classIdx < FileOps.NUM_CLASSES; classIdx++) { + for (FileClass fileClass: cache.getFileClasses()) { + //fileClass = cache.getFileClasses()[classIdx]; File[] fileList = FileOps.listFiles(allFiles, FileOps .filterForClass(fileClass)); //logger.debug(" done"); @@ -221,10 +223,10 @@ int numFiles = fileList.length; if (numFiles > 0) { // create new list - list[fileClass] = new ArrayList(numFiles); + list.set(fileClass.ordinal(), new ArrayList(numFiles)); // sort the file names alphabetically and iterate the list // Arrays.sort(fileList); // not needed - Map hints = FileOps.newHints(FileOps.HINT_BASEDIRS, dirs); + Map hints = FileOps.newHints(FileOps.HINT_BASEDIRS, dirs); hints.put(FileOps.HINT_FILEEXT, scalext); for (int i = 0; i < numFiles; i++) { DocuDirent f = FileOps.fileForClass(fileClass, fileList[i], @@ -232,11 +234,12 @@ // add the file to our list // logger.debug(f.getName()); - list[fileClass].add(f); + list.get(fileClass.ordinal()).add(f); f.setParent(this); } - // we sort the ArrayList, not the Array, for binarySearch to work - Collections.sort(list[fileClass]); + // we sort the inner ArrayList (the list of files not the list of file types) + // for binarySearch to work (DocuDirent's natural sort order is by filename) + Collections.sort(list.get(fileClass.ordinal())); } } // clear the scaled directories @@ -282,12 +285,12 @@ XMLMetaLoader ml = new XMLMetaLoader(); try { // read directory meta file - Map fileMeta = ml.loadURL(mf.getAbsolutePath()); + Map fileMeta = ml.loadURL(mf.getAbsolutePath()); if (fileMeta == null) { return; } // meta for the directory itself is in the "" bin - dirMeta = (Map) fileMeta.remove(""); + dirMeta = fileMeta.remove(""); // read meta for files in this directory readFileMeta(fileMeta, null); // is there meta for other files left? @@ -334,25 +337,23 @@ * @param fc * fileClass */ - protected void readFileMeta(Map fileMeta, String relPath) { + protected void readFileMeta(Map fileMeta, String relPath) { if (list == null) { // there are no files return; } String path = (relPath != null) ? (relPath + "/") : ""; // go through all file classes - for (int nc = 0; nc < list.length; nc++) { - int fc = cache.getFileClasses()[nc]; - if (list[fc] == null) { + for (FileClass fc: FileClass.values()) { + if (list.get(fc.ordinal()) == null) { continue; } // iterate through the list of files in this directory - for (Iterator i = list[fc].iterator(); i.hasNext();) { - DocuDirent f = (DocuDirent) i.next(); + for (DocuDirent f: list.get(fc.ordinal())) { // prepend path to the filename String fn = path + f.getName(); // look up meta for this file and remove from dir - Map meta = (Map) fileMeta.remove(fn); + MetadataMap meta = fileMeta.remove(fn); if (meta != null) { // store meta in file f.setFileMeta(meta); @@ -361,13 +362,13 @@ } } - protected void notifyChildMeta(Map childmeta) { - List children = cache.getChildren(this.dirName, true); + protected void notifyChildMeta(MetadataMap childmeta) { + List children = cache.getChildren(this.dirName, true); if (children.size() > 0) { - for (Iterator i = children.iterator(); i.hasNext();) { + /*for (DocuDirectory d: children) { // TODO: finish this! //((DocuDirectory) i.next()).readFileMeta() - } + }*/ } } @@ -395,7 +396,7 @@ * @return int index of file fn */ public int indexOf(String fn) { - int fc = FileOps.classForFilename(fn); + FileClass fc = FileOps.classForFilename(fn); return indexOf(fn, fc); } @@ -409,20 +410,20 @@ * filename * @return int index of file fn */ - public int indexOf(String fn, int fc) { + public int indexOf(String fn, FileClass fc) { if (!isRead()) { // read directory now if (!readDir()) { return -1; } } - List fileList = list[fc]; + List fileList = list.get(fc.ordinal()); // empty directory? if (fileList == null) { return -1; } - // search for exact match + // search for exact match (DocuDirent does compareTo) // OBS: fileList needs to be sorted first (see )! int idx = Collections.binarySearch(fileList, fn); if (idx >= 0) { @@ -432,15 +433,15 @@ // try closest matches without extension idx = -idx - 1; if ((idx < fileList.size()) - && isBaseInList(fileList, idx, fn)) { + && isBasenameInList(fileList, idx, fn)) { // idx matches return idx; } else if ((idx > 0) - && isBaseInList(fileList, idx-1, fn)) { + && isBasenameInList(fileList, idx-1, fn)) { // idx-1 matches return idx - 1; } else if ((idx + 1 < fileList.size()) - && isBaseInList(fileList, idx+1, fn)) { + && isBasenameInList(fileList, idx+1, fn)) { // idx+1 matches return idx + 1; } @@ -449,8 +450,8 @@ return -1; } - private boolean isBaseInList(List fl, int idx, String fn) { - String dfn = FileOps.basename(((DocuDirent) fl.get(idx)) + private boolean isBasenameInList(List fl, int idx, String fn) { + String dfn = FileOps.basename((fl.get(idx)) .getName()); return (dfn.equals(fn)||dfn.equals(FileOps.basename(fn))); } @@ -467,10 +468,10 @@ * @return DocuDirent */ public DocuDirent find(String fn) { - int fc = FileOps.classForFilename(fn); + FileClass fc = FileOps.classForFilename(fn); int i = indexOf(fn, fc); if (i >= 0) { - return (DocuDirent) list[0].get(i); + return (DocuDirent) list.get(0).get(i); } return null; } @@ -486,10 +487,10 @@ * filename * @return DocuDirent */ - public DocuDirent find(String fn, int fc) { + public DocuDirent find(String fn, FileClass fc) { int i = indexOf(fn, fc); if (i >= 0) { - return (DocuDirent) list[fc].get(i); + return (DocuDirent) list.get(fc.ordinal()).get(i); } return null; } @@ -531,7 +532,7 @@ /** * @return Hashtable */ - public Map getDirMeta() { + public MetadataMap getDirMeta() { return dirMeta; } @@ -560,7 +561,7 @@ * @param dirMeta * The dirMeta to set */ - public void setDirMeta(Map dirMeta) { + public void setDirMeta(MetadataMap dirMeta) { this.dirMeta = dirMeta; } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/io/DocuDirent.java --- a/servlet/src/digilib/io/DocuDirent.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/io/DocuDirent.java Tue Dec 21 09:52:16 2010 +0100 @@ -27,18 +27,20 @@ import org.apache.log4j.Logger; +import digilib.io.FileOps.FileClass; + /** * Abstract directory entry in a DocuDirectory. * * @author casties * */ -public abstract class DocuDirent implements Comparable { +public abstract class DocuDirent implements Comparable { /** the file class of this file */ - protected static int fileClass = FileOps.CLASS_NONE; + protected static FileClass fileClass = FileClass.NONE; /** HashMap with metadata */ - protected Map fileMeta = null; + protected MetadataMap fileMeta = null; /** Is the Metadata valid */ protected boolean metaChecked = false; /** the parent directory */ @@ -73,11 +75,11 @@ XMLMetaLoader ml = new XMLMetaLoader(); try { // read meta file - Map meta = ml.loadURL(mf.getAbsolutePath()); + Map meta = ml.loadURL(mf.getAbsolutePath()); if (meta == null) { return; } - fileMeta = (Map) meta.get(getName()); + fileMeta = meta.get(getName()); } catch (Exception e) { Logger.getLogger(this.getClass()).warn("error reading file .meta", e); } @@ -121,7 +123,7 @@ * * @return HashMap */ - public Map getFileMeta() { + public MetadataMap getFileMeta() { return fileMeta; } @@ -131,7 +133,7 @@ * @param fileMeta * The fileMeta to set */ - public void setFileMeta(Map fileMeta) { + public void setFileMeta(MetadataMap fileMeta) { this.fileMeta = fileMeta; } @@ -145,7 +147,7 @@ /** * @return */ - public static int getFileClass() { + public static FileClass getFileClass() { return fileClass; } @@ -156,9 +158,11 @@ * @see java.lang.Comparable#compareTo(java.lang.Object) */ public int compareTo(Object arg0) { - return (arg0 instanceof DocuDirent) - ? getName().compareTo(((DocuDirent) arg0).getName()) - : getName().compareTo((String) arg0); + if (arg0 instanceof DocuDirent) { + return getName().compareTo(((DocuDirent) arg0).getName()); + } else { + return getName().compareTo((String) arg0); + } } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/io/FileOps.java --- a/servlet/src/digilib/io/FileOps.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/io/FileOps.java Tue Dec 21 09:52:16 2010 +0100 @@ -44,23 +44,15 @@ { "htm", "text/html" }, { "xml", "text/xml" }, { "svg", "image/svg+xml" }, { "meta", "text/xml" } }; - public static Map fileTypes; - - public static List imageExtensions; + public static Map fileTypes; - public static List textExtensions; - - public static List svgExtensions; + public static List imageExtensions; - public static final int CLASS_NONE = -1; - - public static final int CLASS_IMAGE = 0; + public static List textExtensions; - public static final int CLASS_TEXT = 1; + public static List svgExtensions; - public static final int CLASS_SVG = 2; - - public static final int NUM_CLASSES = 3; + public static enum FileClass {NONE, IMAGE, TEXT, SVG} public static final Integer HINT_BASEDIRS = new Integer(1); @@ -72,20 +64,20 @@ * static initializer for FileOps */ static { - fileTypes = new HashMap(); - imageExtensions = new ArrayList(); - textExtensions = new ArrayList(); - svgExtensions = new ArrayList(); + fileTypes = new HashMap(); + imageExtensions = new ArrayList(); + textExtensions = new ArrayList(); + svgExtensions = new ArrayList(); // iterate through file types in ft and fill the Map and Lists for (int i = 0; i < ft.length; i++) { String ext = ft[i][0]; String mt = ft[i][1]; fileTypes.put(ext, mt); - if (classForMimetype(mt) == CLASS_IMAGE) { + if (classForMimetype(mt) == FileClass.IMAGE) { imageExtensions.add(ext); - } else if (classForMimetype(mt) == CLASS_TEXT) { + } else if (classForMimetype(mt) == FileClass.TEXT) { textExtensions.add(ext); - } else if (classForMimetype(mt) == CLASS_SVG) { + } else if (classForMimetype(mt) == FileClass.SVG) { svgExtensions.add(ext); } } @@ -97,18 +89,18 @@ * @param mt * @return */ - public static int classForMimetype(String mt) { + public static FileClass classForMimetype(String mt) { if (mt == null) { - return CLASS_NONE; + return FileClass.NONE; } if (mt.startsWith("image/svg")) { - return CLASS_SVG; + return FileClass.SVG; } else if (mt.startsWith("image")) { - return CLASS_IMAGE; + return FileClass.IMAGE; } else if (mt.startsWith("text")) { - return CLASS_TEXT; + return FileClass.TEXT; } - return CLASS_NONE; + return FileClass.NONE; } /** @@ -124,23 +116,36 @@ * @param fn * @return */ - public static int classForFilename(String fn) { + public static FileClass classForFilename(String fn) { String mt = (String) fileTypes.get(extname(fn).toLowerCase()); return classForMimetype(mt); } - public static Iterator getImageExtensionIterator() { + public static Iterator getImageExtensionIterator() { return imageExtensions.iterator(); } - public static Iterator getTextExtensionIterator() { + public static List getImageExtensions() { + return imageExtensions; + } + + public static Iterator getTextExtensionIterator() { return textExtensions.iterator(); } - public static Iterator getSVGExtensionIterator() { + public static List getTextExtensions() { + return textExtensions; + } + + public static Iterator getSVGExtensionIterator() { return svgExtensions.iterator(); } + public static List getSvgExtensions() { + return svgExtensions; + } + + /** * convert a string with a list of pathnames into an array of strings using * the system's path separator string @@ -277,7 +282,7 @@ static class ImageFileFilter implements FileFilter { public boolean accept(File f) { - return (classForFilename(f.getName()) == CLASS_IMAGE); + return (classForFilename(f.getName()) == FileClass.IMAGE); } } @@ -287,7 +292,7 @@ static class TextFileFilter implements FileFilter { public boolean accept(File f) { - return (classForFilename(f.getName()) == CLASS_TEXT); + return (classForFilename(f.getName()) == FileClass.TEXT); } } @@ -298,7 +303,7 @@ static class SVGFileFilter implements FileFilter { public boolean accept(File f) { - return (classForFilename(f.getName()) == CLASS_SVG); + return (classForFilename(f.getName()) == FileClass.SVG); } } @@ -308,14 +313,14 @@ * @param fileClass * @return */ - public static FileFilter filterForClass(int fileClass) { - if (fileClass == CLASS_IMAGE) { + public static FileFilter filterForClass(FileClass fileClass) { + if (fileClass == FileClass.IMAGE) { return new ImageFileFilter(); } - if (fileClass == CLASS_TEXT) { + if (fileClass == FileClass.TEXT) { return new TextFileFilter(); } - if (fileClass == CLASS_SVG) { + if (fileClass == FileClass.SVG) { return new SVGFileFilter(); } return null; @@ -333,15 +338,15 @@ * optional additional parameters * @return */ - public static DocuDirent fileForClass(int fileClass, File file, Map hints) { + public static DocuDirent fileForClass(FileClass fileClass, File file, Map hints) { // what class of file do we have? - if (fileClass == CLASS_IMAGE) { + if (fileClass == FileClass.IMAGE) { // image file return new ImageFileset(file, hints); - } else if (fileClass == CLASS_TEXT) { + } else if (fileClass == FileClass.TEXT) { // text file return new TextFile(file); - } else if (fileClass == CLASS_SVG) { + } else if (fileClass == FileClass.SVG) { // text file return new SVGFile(file); } @@ -379,8 +384,8 @@ * @param value * @return */ - public static Map newHints(Integer type, Object value) { - Map m = new HashMap(); + public static Map newHints(Integer type, Object value) { + Map m = new HashMap(); if (type != null) { m.put(type, value); } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/io/ImageFileset.java --- a/servlet/src/digilib/io/ImageFileset.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/io/ImageFileset.java Tue Dec 21 09:52:16 2010 +0100 @@ -22,11 +22,13 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; +import java.util.List; import java.util.ListIterator; import java.util.Map; -import digilib.image.ImageOps; import digilib.image.ImageSize; +import digilib.io.FileOps.FileClass; +import digilib.servlet.DigilibConfiguration; /** * @author casties @@ -34,10 +36,10 @@ public class ImageFileset extends DocuDirent { /** this is an image file */ - protected static int fileClass = FileOps.CLASS_IMAGE; + protected static FileClass fileClass = FileClass.IMAGE; /** list of files (ImageFile) */ - private ArrayList list = null; + private List list = null; /** aspect ratio (width/height) */ private float aspect = 0; @@ -55,7 +57,7 @@ * @param initialCapacity */ public ImageFileset() { - list = new ArrayList(); + list = new ArrayList(); } /** @@ -66,10 +68,10 @@ * @param file * @param hints */ - public ImageFileset(File file, Map hints) { + public ImageFileset(File file, Map hints) { Directory[] dirs = (Directory[]) hints.get(FileOps.HINT_BASEDIRS); int nb = dirs.length; - list = new ArrayList(nb); + list = new ArrayList(nb); parent = dirs[0]; fill(dirs, file, hints); } @@ -105,7 +107,7 @@ * */ public File getFile() { - return (list != null) ? ((ImageFile) list.get(0)).getFile() : null; + return (list != null) ? list.get(0).getFile() : null; } /** @@ -116,7 +118,7 @@ * @return */ public ImageFile get(int index) { - return (ImageFile) list.get(index); + return list.get(index); } /** @@ -132,11 +134,11 @@ * @return */ public ImageFile getNextSmaller(ImageSize size) { - for (Iterator i = getHiresIterator(); i.hasNext();) { - ImageFile f = (ImageFile) i.next(); + for (Iterator i = getHiresIterator(); i.hasNext();) { + ImageFile f = i.next(); try { if (!f.isChecked()) { - ImageOps.checkFile(f); + DigilibConfiguration.docuImageIdentify(f); } if (f.getSize().isTotallySmallerThan(size)) { return f; @@ -160,11 +162,11 @@ * @return */ public ImageFile getNextBigger(ImageSize size) { - for (ListIterator i = getLoresIterator(); i.hasPrevious();) { - ImageFile f = (ImageFile) i.previous(); + for (ListIterator i = getLoresIterator(); i.hasPrevious();) { + ImageFile f = i.previous(); try { if (!f.isChecked()) { - ImageOps.checkFile(f); + DigilibConfiguration.docuImageIdentify(f); } if (f.getSize().isBiggerThan(size)) { return f; @@ -202,7 +204,7 @@ * * @return */ - public ListIterator getHiresIterator() { + public ListIterator getHiresIterator() { return list.listIterator(); } @@ -216,7 +218,7 @@ * * @return */ - public ListIterator getLoresIterator() { + public ListIterator getLoresIterator() { return list.listIterator(list.size()); } @@ -231,7 +233,7 @@ * @param hints * */ - void fill(Directory[] dirs, File fl, Map hints) { + void fill(Directory[] dirs, File fl, Map hints) { int nb = dirs.length; String fn = fl.getName(); String baseFn = FileOps.basename(fn); @@ -271,7 +273,7 @@ continue; } } - if (FileOps.classForFilename(dirFiles[fileIdx]) == FileOps.CLASS_IMAGE) { + if (FileOps.classForFilename(dirFiles[fileIdx]) == fileClass) { /* logger.debug("adding file " + dirFiles[fileIdx] + " to Fileset " + this.getName()); */ add(new ImageFile(dirFiles[fileIdx], this, dirs[dirIdx])); diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/io/MetadataMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/MetadataMap.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,14 @@ +/** + * + */ +package digilib.io; + +import java.util.HashMap; + +/** Map for metadata related to files. + * @author casties + * + */ +public class MetadataMap extends HashMap { + +} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/io/SVGFile.java --- a/servlet/src/digilib/io/SVGFile.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/io/SVGFile.java Tue Dec 21 09:52:16 2010 +0100 @@ -23,6 +23,8 @@ import java.io.File; +import digilib.io.FileOps.FileClass; + /** Class for SVG files. * * @author casties @@ -30,7 +32,7 @@ */ public class SVGFile extends DocuDirent { /** this is a text file */ - protected static int fileClass = FileOps.CLASS_SVG; + protected static FileClass fileClass = FileClass.SVG; /** our File instance */ protected File file = null; diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/io/TextFile.java --- a/servlet/src/digilib/io/TextFile.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/io/TextFile.java Tue Dec 21 09:52:16 2010 +0100 @@ -23,6 +23,8 @@ import java.io.File; +import digilib.io.FileOps.FileClass; + /** Class for text files. * * @author casties @@ -30,7 +32,7 @@ */ public class TextFile extends DocuDirent { /** this is a text file */ - protected static int fileClass = FileOps.CLASS_TEXT; + protected static FileClass fileClass = FileClass.TEXT; /** our File instance */ protected File file = null; diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/io/XMLListLoader.java --- a/servlet/src/digilib/io/XMLListLoader.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/io/XMLListLoader.java Tue Dec 21 09:52:16 2010 +0100 @@ -75,17 +75,17 @@ */ private class XMLListParser extends DefaultHandler { - private Map listData; - private LinkedList tagSpace; + private Map listData; + private LinkedList tagSpace; - public Map getData() { + public Map getData() { return listData; } // Parser calls this once at the beginning of a document public void startDocument() throws SAXException { - listData = new HashMap(); - tagSpace = new LinkedList(); + listData = new HashMap(); + tagSpace = new LinkedList(); } // Parser calls this for each element in a document @@ -151,7 +151,7 @@ * load and parse a file (as URL) * returns HashMap with list data */ - public Map loadURL(String path) throws SAXException, IOException { + public Map loadURL(String path) throws SAXException, IOException { //System.out.println("loadurl ("+path+")"); // Create a JAXP SAXParserFactory and configure it SAXParserFactory spf = SAXParserFactory.newInstance(); diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/io/XMLMetaLoader.java --- a/servlet/src/digilib/io/XMLMetaLoader.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/io/XMLMetaLoader.java Tue Dec 21 09:52:16 2010 +0100 @@ -52,9 +52,9 @@ */ private class XMLMetaParser extends DefaultHandler { - private LinkedList tags; - private Map files; - private Map meta; + private LinkedList tags; + private Map files; + private MetadataMap meta; private StringBuffer content; private boolean collecting; private StringBuffer collectedContent; @@ -96,8 +96,8 @@ // Parser calls this once at the beginning of a document public void startDocument() throws SAXException { - tags = new LinkedList(); - files = new HashMap(); + tags = new LinkedList(); + files = new HashMap(); collecting = false; collectedContent = null; } @@ -118,13 +118,13 @@ if (name.equals(metaTag)) { // new meta tag - meta = new HashMap(); + meta = new MetadataMap(); collectedContent = new StringBuffer(); } else if (name.equals(fileTag)) { // new file tag fileName = null; filePath = null; - meta = new HashMap(); + meta = new MetadataMap(); collectedContent = new StringBuffer(); } else if (name.equals(collectTag)) { // start collecting @@ -162,7 +162,7 @@ String name = getName(localName, qName); // exit the tag tags.removeLast(); - String lastTag = (tags.isEmpty()) ? "" : (String) tags.getLast(); + String lastTag = (tags.isEmpty()) ? "" : tags.getLast(); // was it a file/name tag? if (name.equals(fileNameTag) && lastTag.equals(fileTag)) { @@ -260,7 +260,7 @@ * load and parse a file (as URL) * returns HashMap with list data */ - public Map loadURL(String path) throws SAXException, IOException { + public Map loadURL(String path) throws SAXException, IOException { logger.debug("loading meta: "+path); // Create a JAXP SAXParserFactory and configure it SAXParserFactory spf = SAXParserFactory.newInstance(); diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/pdf/PDFFileWorker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/pdf/PDFFileWorker.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,58 @@ +/** + * + */ +package digilib.pdf; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.concurrent.Callable; + +import digilib.image.DocuImage; +import digilib.servlet.DigilibConfiguration; +import digilib.servlet.PDFRequest; +import digilib.util.DigilibJobCenter; + +/** + * @author casties + * + */ +public class PDFFileWorker implements Callable { + /** the wrapped PDFStreamWorker */ + protected PDFStreamWorker streamWorker; + + /** the temporary output file */ + protected File tempFile; + + /** the final output file */ + protected File finalFile; + + /** Create new PDFFileWorker. + * @param dlConfig + * @param tempFile + * @param job_info + * @param imageJobCenter + * @throws FileNotFoundException + */ + public PDFFileWorker(DigilibConfiguration dlConfig, + File tempFile, File finalFile, + PDFRequest job_info, + DigilibJobCenter imageJobCenter) throws FileNotFoundException { + this.tempFile = tempFile; + OutputStream outstream = new FileOutputStream(tempFile); + this.finalFile = finalFile; + this.streamWorker = new PDFStreamWorker(dlConfig, outstream, job_info, imageJobCenter); + } + + @Override + public File call() throws Exception { + OutputStream outstream = streamWorker.call(); + outstream.flush(); + // move temporary to final file + tempFile.renameTo(finalFile); + return finalFile; + } + + +} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/pdf/PDFStreamWorker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/pdf/PDFStreamWorker.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,162 @@ +package digilib.pdf; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import org.apache.log4j.Logger; + +import com.itextpdf.text.Document; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.Image; +import com.itextpdf.text.PageSize; +import com.itextpdf.text.pdf.PdfWriter; + +import digilib.image.DocuImage; +import digilib.image.ImageJobDescription; +import digilib.image.ImageWorker; +import digilib.servlet.DigilibConfiguration; +import digilib.servlet.PDFRequest; +import digilib.util.DigilibJobCenter; +import digilib.util.NumRange; + +public class PDFStreamWorker implements Callable { + + protected static Logger logger = Logger.getLogger(PDFStreamWorker.class); + + protected DigilibConfiguration dlConfig = null; + + protected Document doc = null; + + protected OutputStream outstream = null; + + protected PDFRequest job_info = null; + + protected DigilibJobCenter imageJobCenter = null; + + /** + * @param dlConfig + * @param outputfile + * @param job_info + */ + public PDFStreamWorker(DigilibConfiguration dlConfig, OutputStream outputfile, + PDFRequest job_info, + DigilibJobCenter imageJobCenter) { + super(); + this.dlConfig = dlConfig; + this.outstream = outputfile; + this.job_info = job_info; + this.imageJobCenter = imageJobCenter; + } + + public OutputStream call() throws Exception { + outstream = renderPDF(); + return outstream; + } + + /** + * @throws DocumentException + * @throws InterruptedException + * @throws ExecutionException + * @throws IOException + */ + protected OutputStream renderPDF() throws DocumentException, InterruptedException, + ExecutionException, IOException { + // create document object + doc = new Document(PageSize.A4, 0, 0, 0, 0); + PdfWriter docwriter = null; + + long start_time = System.currentTimeMillis(); + + docwriter = PdfWriter.getInstance(doc, outstream); + + setPDFProperties(doc); + + doc.open(); + + addTitlePage(doc); + + logger.debug("- " + outstream + " doc.open()ed (" + + (System.currentTimeMillis() - start_time) + "ms)"); + start_time = System.currentTimeMillis(); + + NumRange pgs = job_info.getPages(); + + for (int p : pgs) { + logger.debug(" - adding Image " + p + " to " + outstream); + // create ImageJobInformation + ImageJobDescription iji = ImageJobDescription.getInstance(job_info, job_info.getDlConfig()); + iji.setValue("pn", p); + addImage(doc, iji); + logger.debug(" - done adding Image " + p + " to " + outstream); + } + + logger.debug(" - done adding all Images to " + outstream); + + doc.close(); + logger.debug("- " + outstream + " doc.close() (" + + (System.currentTimeMillis() - start_time) + "ms)"); + docwriter.close(); + return outstream; + } + + /** + * Set PDF-Meta-Attributes. + */ + public Document setPDFProperties(Document doc) { + // TODO get proper Information from dlConfig + doc.addAuthor(this.getClass().getName()); + doc.addCreationDate(); + doc.addKeywords("digilib"); + doc.addTitle("digilib PDF"); + doc.addCreator(this.getClass().getName()); + return doc; + } + + /** + * Create a title page and append it to the document (should, of course, be + * called first) + * + * @throws DocumentException + */ + public Document addTitlePage(Document doc) throws DocumentException { + PDFTitlePage titlepage = new PDFTitlePage(job_info); + doc.add(titlepage.getPageContents()); + doc.newPage(); + return doc; + } + + /** + * adds an image to the document. + * + * @param doc + * @param iji + * @return + * @throws InterruptedException + * @throws ExecutionException + * @throws IOException + * @throws DocumentException + */ + public Document addImage(Document doc, ImageJobDescription iji) + throws InterruptedException, ExecutionException, IOException, + DocumentException { + // create image worker + ImageWorker job = new ImageWorker(dlConfig, iji); + // submit + Future jobTicket = imageJobCenter.submit(job); + // wait for result + DocuImage img = jobTicket.get(); + // scale the image + Image pdfimg = Image.getInstance(img.getAwtImage(), null); + float docW = PageSize.A4.getWidth() - 2 * PageSize.A4.getBorder(); + float docH = PageSize.A4.getHeight() - 2 * PageSize.A4.getBorder(); + // TODO: do we really scale this again? + pdfimg.scaleToFit(docW, docH); + // add to PDF + doc.add(pdfimg); + return doc; + } + +} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/pdf/PDFTitlePage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/pdf/PDFTitlePage.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,184 @@ +package digilib.pdf; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.log4j.Logger; + +import com.itextpdf.text.Anchor; +import com.itextpdf.text.BadElementException; +import com.itextpdf.text.Chunk; +import com.itextpdf.text.Element; +import com.itextpdf.text.FontFactory; +import com.itextpdf.text.Image; +import com.itextpdf.text.Paragraph; + + +import digilib.io.DigilibInfoReader; +import digilib.io.DocuDirCache; +import digilib.servlet.PDFCache; +import digilib.servlet.PDFRequest; + +/** A class for the generation of title pages for the generated pdf documents. + * + * + */ +public class PDFTitlePage { + + private PDFRequest job_info = null; + private DigilibInfoReader info_reader= null; + private DocuDirCache dirCache = null; + protected static Logger logger = Logger.getLogger("digilib.servlet"); + + + /** + * Initialize a TitlePage + * @param pdfji + */ + public PDFTitlePage(PDFRequest pdfji){ + job_info = pdfji; + dirCache = (DocuDirCache) job_info.getDlConfig().getValue("servlet.dir.cache"); + + String fn = getBase(dirCache.getDirectory(pdfji.getImageJobInformation().getAsString("fn")).getDir().getPath()) + "presentation/info.xml"; + + info_reader = new DigilibInfoReader(fn); + } + + /** + * generate iText-PDF-Contents for the title page + * + * @return + */ + public Element getPageContents(){ + Paragraph content = new Paragraph(); + content.setAlignment(Element.ALIGN_CENTER); + + // add vertical whitespace + for(int i=0; i<8; i++){ + content.add(Chunk.NEWLINE); + } + + + // add logo + content.add(getLogo()); + content.add(Chunk.NEWLINE); + content.add(Chunk.NEWLINE); + + // add title + Anchor title = new Anchor(new Paragraph(getTitle(),FontFactory.getFont(FontFactory.HELVETICA,16))); + String burl = job_info.getImageJobInformation().getAsString("base.url"); + + title.setReference(burl+"digilib.jsp?fn="+job_info.getImageJobInformation().getAsString("fn")); + content.add(title); + content.add(Chunk.NEWLINE); + + // add author + if(getDate()!=" ") + content.add(new Paragraph(getAuthor()+" ("+getDate()+")",FontFactory.getFont(FontFactory.HELVETICA,14))); + else + content.add(new Paragraph(getAuthor(),FontFactory.getFont(FontFactory.HELVETICA,14))); + + content.add(Chunk.NEWLINE); + + // add page numbers + content.add(new Paragraph(getPages(), FontFactory.getFont(FontFactory.HELVETICA, 12))); + + + content.add(Chunk.NEWLINE); + content.add(Chunk.NEWLINE); + content.add(Chunk.NEWLINE); + + // add credits + content.add(new Paragraph("MPIWG Berlin 2009", FontFactory.getFont(FontFactory.HELVETICA,10))); + + // add digilib version + content.add(new Paragraph(getDigilibVersion(),FontFactory.getFont(FontFactory.HELVETICA,10))); + + for(int i=0; i<8; i++){ + content.add(Chunk.NEWLINE); + } + Anchor address = new Anchor( + new Paragraph(burl+"digilib.jsp?fn="+job_info.getImageJobInformation().getAsString("fn"), FontFactory.getFont(FontFactory.COURIER, 9)) + ); + address.setReference(burl+"digilib.jsp?fn="+job_info.getImageJobInformation().getAsString("fn")); + + content.add(address); + + + return content; + } + + /** + * return base directory of an image directory + * + * @param path + * @return + */ + private String getBase(String path){ + if(path.contains("/")){ + String[] x = path.split("/"); + String newpath = ""; + for(int i=0; i docuImageClass = null; /** Log4J logger */ private Logger logger = Logger.getLogger("digilib.config"); @@ -63,11 +65,16 @@ * */ public DigilibConfiguration() { - // create HashMap(20) super(20); // we start with a default logger config BasicConfigurator.configure(); + initParams(); + } + /** + * + */ + protected void initParams() { /* * Definition of parameters and default values. System parameters that * are not read from config file have a type 's'. @@ -91,6 +98,12 @@ 's'); // AuthOps instance for authentication newParameter("servlet.auth.op", null, null, 's'); + // Executor for image operations + newParameter("servlet.worker.imageexecutor", null, null, 's'); + // Executor for PDF operations + newParameter("servlet.worker.pdfexecutor", null, null, 's'); + // Executor for PDF-image operations + newParameter("servlet.worker.pdfimageexecutor", null, null, 's'); /* * parameters that can be read from config file have a type 'f' @@ -123,8 +136,6 @@ newParameter("auth-file", new File("digilib-auth.xml"), null, 'f'); // sending image files as-is allowed newParameter("sendfile-allowed", Boolean.TRUE, null, 'f'); - // Debug level - newParameter("debug-level", new Integer(5), null, 'f'); // Type of DocuImage instance newParameter( "docuimage-class", @@ -140,18 +151,29 @@ // use mapping file to translate paths newParameter("use-mapping", Boolean.FALSE, null, 'f'); // mapping file location - newParameter("mapping-file", new File("WEB-INF/digilib-map.xml"), null, 'f'); + newParameter("mapping-file", new File("digilib-map.xml"), null, 'f'); // log4j config file location - newParameter("log-config-file", new File("WEB-INF/log4j-config.xml"), null, 'f'); + newParameter("log-config-file", new File("log4j-config.xml"), null, 'f'); // maximum destination image size (0 means no limit) newParameter("max-image-size", new Integer(0), null, 'f'); - // use safe (but slower) directory indexing - newParameter("safe-dir-index", Boolean.FALSE, null, 'f'); // number of working threads newParameter("worker-threads", new Integer(1), null, 'f'); // max number of waiting threads - newParameter("max-waiting-threads", new Integer(0), null, 'f'); - + newParameter("max-waiting-threads", new Integer(20), null, 'f'); + // number of pdf-generation threads + newParameter("pdf-worker-threads", new Integer(1), null, 'f'); + // max number of waiting pdf-generation threads + newParameter("pdf-max-waiting-threads", new Integer(20), null, 'f'); + // number of pdf-image generation threads + newParameter("pdf-image-worker-threads", new Integer(1), null, 'f'); + // max number of waiting pdf-image generation threads + newParameter("pdf-image-max-waiting-threads", new Integer(10), null, 'f'); + // PDF generation temp directory + newParameter("pdf-temp-dir", "pdf_temp", null, 'f'); + // PDF generation cache directory + newParameter("pdf-cache-dir", "pdf_cache", null, 'f'); + // PDF generation cache directory + newParameter("pdf-cache-dir", "pdf_cache", null, 'f'); } /** @@ -167,127 +189,111 @@ /** * read parameter list from the XML file in init parameter "config-file" + * or file digilib-config.xml */ - public void readConfig(ServletConfig config) throws Exception { + @SuppressWarnings("unchecked") + public void readConfig(ServletConfig c) throws Exception { /* * Get config file name. The file name is first looked for as an init * parameter, then in a fixed location in the webapp. */ - if (config == null) { + if (c == null) { // no config no file... return; } - String fn = config.getInitParameter("config-file"); + String fn = c.getInitParameter("config-file"); if (fn == null) { - fn = ServletOps.getFile("WEB-INF/digilib-config.xml", config); + fn = ServletOps.getConfigFile("digilib-config.xml", c); if (fn == null) { logger.fatal("readConfig: no param config-file"); throw new ServletException("ERROR: no digilib config file!"); } } - File configFile = new File(fn); + File f = new File(fn); // setup config file list reader XMLListLoader lilo = new XMLListLoader("digilib-config", "parameter", "name", "value"); // read config file into HashMap - Map confTable = lilo.loadURL(configFile.toURL().toString()); + Map confTable = lilo.loadURL(f.toURL().toString()); // set config file path parameter - setValue("servlet.config.file", configFile.getCanonicalPath()); + setValue("servlet.config.file", f.getCanonicalPath()); /* - * process parameters from file + * read parameters */ - for (Iterator i = confTable.keySet().iterator(); i.hasNext();) { - String key = (String) i.next(); - String val = (String) confTable.get(key); - Parameter p = get(key); + for (Entry confEntry: confTable.entrySet()) { + Parameter p = get(confEntry.getKey()); if (p != null) { if (p.getType() == 's') { // type 's' Parameters are not overwritten. continue; } - if (!p.setValueFromString(val)) { + if (!p.setValueFromString(confEntry.getValue())) { /* * automatic conversion failed -- try special cases */ // basedir-list - if (key.equals("basedir-list")) { + if (confEntry.getKey().equals("basedir-list")) { // split list into directories - String[] sa = FileOps.pathToArray(val); + String[] sa = FileOps.pathToArray(confEntry.getValue()); if (sa != null) { p.setValue(sa); } } - } } else { // parameter unknown -- just add - newParameter(key, null, val, 'f'); + newParameter(confEntry.getKey(), null, confEntry.getValue(), 'f'); } } - - /* - * process all parameters - */ - for (Iterator i = this.keySet().iterator(); i.hasNext();) { - String key = (String) i.next(); - Parameter para = (Parameter) this.get(key); - - // basedir-list - if (key.equals("basedir-list")) { - // split list into directories - String[] dirs = (String[]) para.getValue(); - for (int j = 0; j < dirs.length; j++) { - // make relative directory paths be inside the webapp - dirs[j] = ServletOps.getFile(dirs[j], config); - } - para.setValue(dirs); - } - - // File types - if (para.getValue() instanceof File) { - File pf = (File) para.getValue(); - // make relative paths be inside the webapp - para.setValue(ServletOps.getFile(pf, config)); - } - - } - + // initialise static DocuImage class instance + DigilibConfiguration.docuImageClass = (Class) Class.forName(getAsString("docuimage-class")); } /** * Creates a new DocuImage instance. * - * The type of DocuImage is specified by docuImageType. + * The type of DocuImage is specified by docuimage-class. * * @return DocuImage */ - public DocuImage getDocuImageInstance() { + public static DocuImage getDocuImageInstance() { DocuImageImpl di = null; try { - if (docuImageClass == null) { - docuImageClass = Class.forName(getAsString("docuimage-class")); - } - di = (DocuImageImpl) docuImageClass.newInstance(); + di = docuImageClass.newInstance(); } catch (Exception e) { } return di; } /** + * Check image size and type and store in ImageFile imgf + * + * @param imgf + * @return + * @throws IOException + */ + public static ImageFile docuImageIdentify(ImageFile imgf) throws IOException { + // use fresh DocuImage instance + DocuImage di = getDocuImageInstance(); + return di.identify(imgf); + } + + /** * @return Returns the docuImageClass. */ - public Class getDocuImageClass() { + public static Class getDocuImageClass() { return docuImageClass; } + /** * @param docuImageClass The docuImageClass to set. */ - public void setDocuImageClass(Class docuImageClass) { - this.docuImageClass = docuImageClass; + public static void setDocuImageClass(Class dic) { + docuImageClass = dic; } } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/DigilibImageWorker.java --- a/servlet/src/digilib/servlet/DigilibImageWorker.java Wed Jul 14 16:36:42 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,281 +0,0 @@ -/* DigilibImageWorker.java -- worker for image operations - * - * Digital Image Library servlet components - * - * Copyright (C) 2004 Robert Casties (robcast@mail.berlios.de) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * Please read license.txt for the full details. A copy of the GPL may be found - * at http://www.gnu.org/copyleft/lgpl.html - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - * - * Created on 19.10.2004 - */ - -package digilib.servlet; - -import java.awt.Rectangle; -import java.awt.geom.Rectangle2D; -import java.io.IOException; - -import javax.servlet.http.HttpServletResponse; - -import digilib.image.DocuImage; -import digilib.image.ImageOpException; -import digilib.image.ImageOps; -import digilib.io.FileOpException; -import digilib.io.ImageFile; - -/** - * worker for image operations. - * - * @author casties - * - */ -public class DigilibImageWorker extends DigilibWorker { - - private DigilibConfiguration dlConfig; - - HttpServletResponse response; - - long startTime; - - String mimeType; - - int scaleQual; - - DigilibRequest dlRequest; - - float paramROT; - - float paramCONT; - - float paramBRGT; - - float[] paramRGBM; - - float[] paramRGBA; - - ImageFile fileToLoad; - - float areaXoff; - - float areaYoff; - - float areaWidth; - - float areaHeight; - - float scaleXY; - - Rectangle2D outerUserImgArea; - - Rectangle2D innerUserImgArea; - - float minSubsample; - - boolean wholeRotArea; - - int forceType; - - /** - * @param dlConfig - * @param response - * @param mimeType - * @param scaleQual - * @param dlRequest - * @param paramROT - * @param paramCONT - * @param paramBRGT - * @param paramRGBM - * @param paramRGBA - * @param fileToLoad - * @param areaXoff - * @param outerUserImgArea - * @param innerUserImgArea - * @param minSubsample - * @param wholeRotArea - * @param forceType - */ - public DigilibImageWorker(DigilibConfiguration dlConfig, - HttpServletResponse response, String mimeType, int scaleQual, - DigilibRequest dlRequest, float paramROT, float paramCONT, - float paramBRGT, float[] paramRGBM, float[] paramRGBA, - ImageFile fileToLoad, float scaleXY, Rectangle2D outerUserImgArea, - Rectangle2D innerUserImgArea, float minSubsample, - boolean wholeRotArea, int forceType) { - super(); - this.dlConfig = dlConfig; - this.response = response; - this.mimeType = mimeType; - this.scaleQual = scaleQual; - this.dlRequest = dlRequest; - this.paramROT = paramROT; - this.paramCONT = paramCONT; - this.paramBRGT = paramBRGT; - this.paramRGBM = paramRGBM; - this.paramRGBA = paramRGBA; - this.fileToLoad = fileToLoad; - this.scaleXY = scaleXY; - this.outerUserImgArea = outerUserImgArea; - this.innerUserImgArea = innerUserImgArea; - this.minSubsample = minSubsample; - this.wholeRotArea = wholeRotArea; - this.forceType = forceType; - } - - /* - * do the work - */ - public DocuImage render() throws FileOpException, IOException, ImageOpException { - ; - logger.debug("image worker " + this.getName() + " working"); - startTime = System.currentTimeMillis(); - - /* crop and scale image */ - - // new DocuImage instance - DocuImage docuImage = dlConfig.getDocuImageInstance(); - if (docuImage == null) { - throw new ImageOpException("Unable to load DocuImage class!"); - } - - // set interpolation quality - docuImage.setQuality(scaleQual); - - Rectangle loadRect = outerUserImgArea.getBounds(); - // use subimage loading if possible - if (docuImage.isSubimageSupported()) { - logger.debug("Subimage: scale " + scaleXY + " = " + (1 / scaleXY)); - float subf = 1f; - float subsamp = 1f; - if (scaleXY < 1) { - subf = 1 / scaleXY; - // for higher quality reduce subsample factor by - // minSubsample - if (scaleQual > 0) { - subsamp = (float) Math.max(Math.floor(subf / minSubsample), - 1d); - } else { - subsamp = (float) Math.floor(subf); - } - scaleXY = subsamp / subf; - logger.debug("Using subsampling: " + subsamp + " rest " - + scaleXY); - } - - docuImage.loadSubimage(fileToLoad, loadRect, (int) subsamp); - - logger.debug("SUBSAMP: " + subsamp + " -> " + docuImage.getWidth() - + "x" + docuImage.getHeight()); - - docuImage.scale(scaleXY, scaleXY); - - } else { - // else load and crop the whole file - docuImage.loadImage(fileToLoad); - docuImage.crop((int) loadRect.getX(), (int) loadRect.getY(), - (int) loadRect.getWidth(), (int) loadRect.getHeight()); - - docuImage.scale(scaleXY, scaleXY); - } - - // mirror image - // operation mode: "hmir": mirror horizontally, "vmir": mirror - // vertically - if (dlRequest.hasOption("mo", "hmir")) { - docuImage.mirror(0); - } - if (dlRequest.hasOption("mo", "vmir")) { - docuImage.mirror(90); - } - - // rotate image - if (paramROT != 0d) { - docuImage.rotate(paramROT); - if (wholeRotArea) { - // crop to the inner bounding box - float xcrop = (float) (docuImage.getWidth() - innerUserImgArea - .getWidth() - * scaleXY); - float ycrop = (float) (docuImage.getHeight() - innerUserImgArea - .getHeight() - * scaleXY); - if ((xcrop > 0) || (ycrop > 0)) { - // only crop smaller - xcrop = (xcrop > 0) ? xcrop : 0; - ycrop = (ycrop > 0) ? ycrop : 0; - // crop image - docuImage.crop((int) (xcrop / 2), (int) (ycrop / 2), - (int) (docuImage.getWidth() - xcrop), - (int) (docuImage.getHeight() - ycrop)); - } - } - - } - - // color modification - if ((paramRGBM != null) || (paramRGBA != null)) { - // make shure we actually have two arrays - if (paramRGBM == null) { - paramRGBM = new float[3]; - } - if (paramRGBA == null) { - paramRGBA = new float[3]; - } - // calculate "contrast" values (c=2^x) - float[] mult = new float[3]; - for (int i = 0; i < 3; i++) { - mult[i] = (float) Math.pow(2, (float) paramRGBM[i]); - } - docuImage.enhanceRGB(mult, paramRGBA); - } - - // contrast and brightness enhancement - if ((paramCONT != 0f) || (paramBRGT != 0f)) { - float mult = (float) Math.pow(2, paramCONT); - docuImage.enhance(mult, paramBRGT); - } - - logger.debug("rendered in " + (System.currentTimeMillis() - startTime) + "ms"); - - return docuImage; - } - - public void write(DocuImage img) throws FileOpException, IOException { - /* write the resulting image */ - - // setup output -- if output type is forced use that otherwise - // if source is JPG then dest will be JPG else it's PNG - if (forceType != ImageOps.TYPE_AUTO) { - if (forceType == ImageOps.TYPE_JPEG) { - mimeType = "image/jpeg"; - } - if (forceType == ImageOps.TYPE_PNG) { - mimeType = "image/png"; - } - } else if ((mimeType.equals("image/jpeg") - || mimeType.equals("image/jp2") || mimeType.equals("image/fpx"))) { - mimeType = "image/jpeg"; - } else { - mimeType = "image/png"; - } - response.setContentType(mimeType); - - // write the image - img.writeImage(mimeType, response.getOutputStream()); - response.flushBuffer(); - - logger.info("image worker " + this.getName() + " done in " - + (System.currentTimeMillis() - startTime)); - - img.dispose(); - } -} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/DigilibRequest.java --- a/servlet/src/digilib/servlet/DigilibRequest.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/servlet/DigilibRequest.java Tue Dec 21 09:52:16 2010 +0100 @@ -26,29 +26,19 @@ package digilib.servlet; -import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Iterator; import java.util.StringTokenizer; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; -import org.apache.log4j.Logger; - -import com.hp.hpl.mesa.rdf.jena.mem.ModelMem; -import com.hp.hpl.mesa.rdf.jena.model.Model; -import com.hp.hpl.mesa.rdf.jena.model.Property; -import com.hp.hpl.mesa.rdf.jena.model.ResIterator; -import com.hp.hpl.mesa.rdf.jena.model.Resource; -import com.hp.hpl.mesa.rdf.jena.model.Statement; -import com.hp.hpl.mesa.rdf.jena.model.StmtIterator; - import digilib.image.DocuImage; import digilib.io.FileOps; +import digilib.util.OptionsSet; +import digilib.util.Parameter; +import digilib.util.ParameterMap; /** * Class holding the parameters of a digilib user request. The parameters are @@ -74,25 +64,30 @@ */ public class DigilibRequest extends ParameterMap { - private static final long serialVersionUID = -4707707539569977901L; + protected DocuImage image; // internal DocuImage instance for this request - private final static String ECHO = "http://echo.unibe.ch/digilib/rdf#"; + protected ServletRequest servletRequest; // internal ServletRequest - private final static String DIGILIB = "Digilib"; - - private Logger logger = Logger.getLogger(this.getClass()); - - private boolean boolRDF = false; // use RDF Parameters + public DigilibRequest() { + super(30); + } - private DocuImage image; // internal DocuImage instance for this request - - private ServletRequest servletRequest; // internal ServletRequest + /** + * Creates a new instance of DigilibRequest with parameters from a + * ServletRequest. All undefined parameters are set to default values. + * + * @param request + */ + public DigilibRequest(ServletRequest request) { + super(30); + setWithRequest(request); + initOptions(); + } - /** Creates a new instance of DigilibRequest and sets default values. */ - public DigilibRequest() { - // create HashMap(20) - super(30); - + /** set up parameters. + * + */ + protected void initParams() { /* * Definition of parameters and default values. Parameter of type 's' * are for the servlet. @@ -117,7 +112,7 @@ // scale factor newParameter("ws", new Float(1), null, 's'); // special options like 'fit' for gifs - newParameter("mo", "", null, 's'); + newParameter("mo", this.options, null, 's'); // rotation angle (degree) newParameter("rot", new Float(0), null, 's'); // contrast enhancement factor @@ -175,19 +170,15 @@ newParameter("lv", new Integer(2), null, 'c'); // marks newParameter("mk", "", null, 'c'); - } - /** - * Creates a new instance of DigilibRequest with parameters from a - * ServletRequest. All undefined parameters are set to default values. - * - * @param request - */ - public DigilibRequest(ServletRequest request) { - this(); - setWithRequest(request); - } + /* (non-Javadoc) + * @see digilib.servlet.ParameterMap#initOptions() + */ + @Override + protected void initOptions() { + options = (OptionsSet) getValue("mo"); + } /** * Populate the request object with data from a ServletRequest. @@ -199,11 +190,7 @@ servletRequest = request; // decide if it's old-style or new-style String qs = ((HttpServletRequest) request).getQueryString(); - if (request.getParameter("rdf") != null) { - // RDF stuff - boolRDF = true; - setWithRDF(request); - } else if (qs != null) { + if (qs != null) { if (qs.indexOf("&") > -1) { // & separator setWithParamString(qs, "&"); @@ -349,8 +336,7 @@ public String getAsString(int type) { StringBuffer s = new StringBuffer(50); // go through all values - for (Iterator i = this.values().iterator(); i.hasNext();) { - Parameter p = (Parameter) i.next(); + for (Parameter p: params.values()) { if ((type > 0) && (p.getType() != type)) { // skip the wrong types continue; @@ -406,13 +392,14 @@ * @param request * ServletRequest to get parameters from. */ - public void setWithParamRequest(ServletRequest request) { + //@SuppressWarnings("unchecked") // ServletRequest.getParameterNames() returns naked Enumeration + public void setWithParamRequest(ServletRequest request) { setValue("servlet.request", request); // go through all request parameters - for (Enumeration i = request.getParameterNames(); i.hasMoreElements();) { + for (Enumeration i = request.getParameterNames(); i.hasMoreElements();) { String name = (String) i.nextElement(); // is this a known parameter? - if (this.containsKey(name)) { + if (params.containsKey(name)) { Parameter p = (Parameter) this.get(name); // internal parameters are not set if (p.getType() == 'i') { @@ -447,7 +434,7 @@ String name = URLDecoder.decode(nv[0], "UTF-8"); String val = URLDecoder.decode(nv[1], "UTF-8"); // is this a known parameter? - if (this.containsKey(name)) { + if (params.containsKey(name)) { Parameter p = (Parameter) this.get(name); // internal parameters are not set if (p.getType() == 'i') { @@ -466,78 +453,9 @@ } /** - * - * - */ - public void setWithRDF(ServletRequest request) { - String strRDF; - strRDF = request.getParameter("rdf"); - if (strRDF != null) { - Hashtable hashRDF = rdf2hash(strRDF); - // go through all parameters - for (Iterator i = hashRDF.keySet().iterator(); i.hasNext();) { - String name = (String) i.next(); - // is this a known parameter? - if (this.containsKey(name)) { - Parameter p = (Parameter) this.get(name); - // internal parameters are not set - if (p.getType() == 'i') { - continue; - } - p.setValueFromString((String) hashRDF.get(name)); - } - } - } - // add path from request - setValue("request.path", ((HttpServletRequest) request).getPathInfo()); - } - - private Hashtable rdf2hash(String strRDF) { - Hashtable hashParams = new Hashtable(); - try { - // create an empty model - Model model = new ModelMem(); - StringReader sr = new StringReader(strRDF); - model.read(sr, ""); - // get Property type -> digilib - Property property = model.getProperty(DigilibRequest.ECHO, "type"); - if (property != null) { - ResIterator resourceIterator = model - .listSubjectsWithProperty(property); - while (resourceIterator.hasNext()) { - Resource resource = resourceIterator.next(); - StmtIterator statementIterator = resource.listProperties(); - String type = resource.getProperty(property).getResource() - .getURI(); - if (type == null) { - continue; - } - if (type.equals(DigilibRequest.ECHO - + DigilibRequest.DIGILIB)) { - while (statementIterator.hasNext()) { - Statement statement = statementIterator.next(); - Property predicate = statement.getPredicate(); - if (predicate.getNameSpace().equals( - DigilibRequest.ECHO)) { - hashParams.put(predicate.getLocalName(), - statement.getObject().toString()); - } - } - } - } - } else { - logger.warn("The type property was null! So the rdf-model" - + " sent to Digilib was probably incorrect!"); - } - } catch (Exception e) { - logger.warn("rdf2hash function caused an error: ", e); - } - return hashParams; - } - - /** * Test if option string opt is set. Checks if the substring * opt is contained in the options string param. + * Deprecated! use hasOption(String opt) for "mo"-options. * * @param opt * Option string to be tested. @@ -614,10 +532,6 @@ setValue("docu.image", image); } - public boolean isRDF() { - return boolRDF; - } - /** * @return */ diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/DigilibWorker.java --- a/servlet/src/digilib/servlet/DigilibWorker.java Wed Jul 14 16:36:42 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,195 +0,0 @@ - /* DigilibWorker.java -- image operation worker - * - * Digital Image Library servlet components - * - * Copyright (C) 2004 Robert Casties (robcast@mail.berlios.de) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * Please read license.txt for the full details. A copy of the GPL may be found - * at http://www.gnu.org/copyleft/lgpl.html - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - * - * Created on 18.10.2004 - */ -package digilib.servlet; - -import java.util.concurrent.Semaphore; - -import org.apache.log4j.Logger; - -import digilib.image.DocuImage; - -/** - * image operation worker. - * - * @author casties - */ -public abstract class DigilibWorker { - - protected static Logger logger = Logger.getLogger(DigilibWorker.class); - - private static int maxRunningThreads = 0; - - private static int runningThreads = 0; - - private static int waitingThreads = 0; - - private static int maxWaitingThreads = 0; - - public static Semaphore sem = new Semaphore(2, true); - - protected Throwable error; - - /** - * @param job - */ - public DigilibWorker() { - super(); - error = null; - } - - public abstract DocuImage render() throws Exception; - - public abstract void write(DocuImage img) throws Exception; - - /** - * Do the work. - */ - public void run() { - logger.debug((++waitingThreads) + " waiting threads"); - DocuImage img = null; - try { - sem.acquire(); - waitingThreads--; - } catch (InterruptedException e) { - error = e; - waitingThreads--; - // should we reinterrupt? - return; - } - logger.debug((++runningThreads) + " running threads"); - try { - /* - * do rendering under the semaphore - */ - img = render(); - } catch (Throwable e) { - error = e; - logger.error(e); - } finally { - runningThreads--; - sem.release(); - } - /* - * write the result without semaphore - */ - if (!hasError()) { - try{ - write(img); - } catch (Throwable e) { - error = e; - logger.error(e); - } - } - } - - /** - * Returns the name of this thread. - * - * @return - */ - public String getName() { - return Thread.currentThread().getName(); - } - - /** Returns if the worker could run (i.e. is not overloaded). - * - * @return - */ - public static boolean canRun() { - return ((DigilibWorker.maxWaitingThreads == 0) || (DigilibWorker.getNumWaiting() <= DigilibWorker.maxWaitingThreads)); - } - - /** - * returns if an error occurred. - * - * @return - */ - public boolean hasError() { - return (error != null); - } - - /** - * @return Returns the error. - */ - public Throwable getError() { - return error; - } - - /** - * @return Returns the semaphore. - */ - public static Semaphore getSemaphore() { - return sem; - } - - /** - * @param sem - * The semaphore to set. - */ - public static void setSemaphore(Semaphore sem) { - DigilibWorker.sem = sem; - } - - public static void setSemaphore(int maxrun, boolean fair) { - sem = new Semaphore(maxrun, fair); - maxRunningThreads = maxrun; - } - - /** - * The number of currently running threads (approximate). - * - * @return - */ - public static int getNumRunning() { - return (maxRunningThreads - sem.availablePermits()); - } - - /** - * The number of currently waiting threads (approximate). - * - * @return - */ - public static int getNumWaiting() { - return sem.getQueueLength(); - } - - /** - * @return Returns the maxWaitingThreads. - */ - public static int getMaxWaitingThreads() { - return maxWaitingThreads; - } - - /** - * @param maxWaitingThreads The maxWaitingThreads to set. - */ - public static void setMaxWaitingThreads(int maxWaitingThreads) { - DigilibWorker.maxWaitingThreads = maxWaitingThreads; - } - - public static int getMaxRunningThreads() { - return maxRunningThreads; - } - - public static void setMaxRunningThreads(int maxRunningThreads) { - DigilibWorker.maxRunningThreads = maxRunningThreads; - } -} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/DocumentBean.java --- a/servlet/src/digilib/servlet/DocumentBean.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/servlet/DocumentBean.java Tue Dec 21 09:52:16 2010 +0100 @@ -33,11 +33,10 @@ import digilib.auth.AuthOpException; import digilib.auth.AuthOps; -import digilib.image.ImageOps; import digilib.image.ImageSize; import digilib.io.DocuDirCache; import digilib.io.DocuDirectory; -import digilib.io.FileOps; +import digilib.io.FileOps.FileClass; import digilib.io.ImageFile; import digilib.io.ImageFileset; @@ -128,7 +127,7 @@ * return a list of authorization roles needed for request to access the * specified path */ - public List rolesForPath(DigilibRequest request) throws AuthOpException { + public List rolesForPath(DigilibRequest request) throws AuthOpException { logger.debug("rolesForPath"); return useAuthentication ? authOp.rolesForPath(request) : null; } @@ -136,7 +135,7 @@ /** * check request authorization against a list of roles */ - public boolean isRoleAuthorized(List roles, DigilibRequest request) { + public boolean isRoleAuthorized(List roles, DigilibRequest request) { logger.debug("isRoleAuthorized"); return useAuthentication ? authOp.isRoleAuthorized(roles, request) : true; @@ -193,7 +192,7 @@ String fn = dlRequest.getFilePath(); // get information about the file ImageFileset fileset = (ImageFileset) dirCache.getFile(fn, dlRequest - .getAsInt("pn"), FileOps.CLASS_IMAGE); + .getAsInt("pn"), FileClass.IMAGE); if (fileset == null) { return; } @@ -211,9 +210,9 @@ // get original pixel size ImageFile origfile = fileset.getBiggest(); // check image for size if mo=hires - if ((! origfile.isChecked())&&dlRequest.hasOption("mo", "hires")) { + if ((! origfile.isChecked())&&dlRequest.hasOption("hires")) { logger.debug("pre-checking image!"); - ImageOps.checkFile(origfile); + DigilibConfiguration.docuImageIdentify(origfile); } ImageSize pixsize = origfile.getSize(); if (pixsize != null) { @@ -238,15 +237,22 @@ return getNumPages(dlRequest); } + /** + * get the number of image pages/files in the directory + */ + public int getNumPages(DigilibRequest request) throws Exception { + return getNumPages(request, FileClass.IMAGE); + } + /** - * get the number of pages/files in the directory + * get the number of pages/files of type fc in the directory */ - public int getNumPages(DigilibRequest request) throws Exception { + public int getNumPages(DigilibRequest request, FileClass fc) throws Exception { logger.debug("getNumPages"); DocuDirectory dd = (dirCache != null) ? dirCache.getDirectory(request .getFilePath()) : null; if (dd != null) { - return dd.size(); + return dd.size(fc); } return 0; } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/Initialiser.java --- a/servlet/src/digilib/servlet/Initialiser.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/servlet/Initialiser.java Tue Dec 21 09:52:16 2010 +0100 @@ -21,6 +21,8 @@ package digilib.servlet; import java.io.File; +import java.io.OutputStream; +import java.util.List; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; @@ -32,39 +34,42 @@ import digilib.auth.AuthOps; import digilib.auth.XMLAuthOps; -import digilib.image.ImageOps; +import digilib.image.DocuImage; import digilib.io.AliasingDocuDirCache; import digilib.io.DocuDirCache; -import digilib.io.FileOps; +import digilib.io.FileOps.FileClass; +import digilib.util.DigilibJobCenter; /** - * Initalisation servlet for setup tasks. + * Singleton initalisation servlet for setup tasks and resources. * * @author casties * */ +@SuppressWarnings("serial") public class Initialiser extends HttpServlet { - private static final long serialVersionUID = -5126621114382549343L; - /** servlet version */ - public static final String iniVersion = "0.2"; + public static final String version = "0.2"; /** gengeral logger for this class */ private static Logger logger = Logger.getLogger("digilib.init"); - /** AuthOps instance */ - AuthOps authOp; - /** DocuDirCache instance */ DocuDirCache dirCache; /** DigilibConfiguration instance */ DigilibConfiguration dlConfig; - /** use authorization database */ - boolean useAuthentication = false; - + /** Executor for digilib image jobs */ + DigilibJobCenter imageEx; + + /** Executor for PDF jobs */ + DigilibJobCenter pdfEx; + + /** Executor for PDF image jobs */ + DigilibJobCenter pdfImageEx; + /** * Initialisation on first run. * @@ -75,13 +80,12 @@ System.out .println("***** Digital Image Library Initialisation Servlet (version " - + iniVersion + ") *****"); + + version + ") *****"); // get our ServletContext ServletContext context = config.getServletContext(); // see if there is a Configuration instance - dlConfig = (DigilibConfiguration) context - .getAttribute("digilib.servlet.configuration"); + dlConfig = (DigilibConfiguration) context.getAttribute("digilib.servlet.configuration"); if (dlConfig == null) { // create new Configuration try { @@ -99,11 +103,10 @@ // say hello in the log file logger .info("***** Digital Image Library Initialisation Servlet (version " - + iniVersion + ") *****"); + + version + ") *****"); // directory cache String[] bd = (String[]) dlConfig.getValue("basedir-list"); - int[] fcs = { FileOps.CLASS_IMAGE, FileOps.CLASS_TEXT, - FileOps.CLASS_SVG }; + FileClass[] fcs = { FileClass.IMAGE, FileClass.TEXT }; if (dlConfig.getAsBoolean("use-mapping")) { // with mapping file File mapConf = ServletOps.getConfigFile((File) dlConfig @@ -123,21 +126,28 @@ // XML version File authConf = ServletOps.getConfigFile((File) dlConfig .getValue("auth-file"), config); - authOp = new XMLAuthOps(authConf); + AuthOps authOp = new XMLAuthOps(authConf); dlConfig.setValue("servlet.auth.op", authOp); dlConfig.setValue("auth-file", authConf); } // DocuImage class - Class cl = Class.forName(dlConfig - .getAsString("docuimage-class")); - dlConfig.setDocuImageClass(cl); - dlConfig.setValue("servlet.docuimage.class", cl.getName()); - ImageOps.setDocuImage(dlConfig.getDocuImageInstance()); - // worker threads + DocuImage di = DigilibConfiguration.getDocuImageInstance(); + dlConfig.setValue("servlet.docuimage.class", di.getClass().getName()); + // digilib worker threads int nt = dlConfig.getAsInt("worker-threads"); - DigilibWorker.setSemaphore(nt, true); - int mt = dlConfig.getAsInt("max-waiting-threads"); - DigilibWorker.setMaxWaitingThreads(mt); + int mt = dlConfig.getAsInt("max-waiting-threads"); + imageEx = new DigilibJobCenter(nt, mt, true, "servlet.worker.imageexecutor"); + dlConfig.setValue("servlet.worker.imageexecutor", imageEx); + // PDF worker threads + int pnt = dlConfig.getAsInt("pdf-worker-threads"); + int pmt = dlConfig.getAsInt("pdf-max-waiting-threads"); + pdfEx = new DigilibJobCenter(pnt, pmt, true, "servlet.worker.pdfexecutor"); + dlConfig.setValue("servlet.worker.pdfexecutor", pdfEx); + // PDF image worker threads + int pint = dlConfig.getAsInt("pdf-image-worker-threads"); + int pimt = dlConfig.getAsInt("pdf-image-max-waiting-threads"); + pdfImageEx = new DigilibJobCenter(pint, pimt, true, "servlet.worker.pdfimageexecutor"); + dlConfig.setValue("servlet.worker.pdfimageexecutor", pdfImageEx); // set as the servlets main config context.setAttribute("digilib.servlet.configuration", dlConfig); @@ -148,15 +158,45 @@ // say hello in the log file logger .info("***** Digital Image Library Initialisation Servlet (version " - + iniVersion + ") *****"); - logger.warn("Already initialised?"); - // set our AuthOps - useAuthentication = dlConfig.getAsBoolean("use-authorization"); - // AuthOps instance - authOp = (AuthOps) dlConfig.getValue("servlet.auth.op"); - // DocuDirCache instance - dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache"); + + version + ") *****"); + logger.warn("Already initialised!"); } } + /** clean up local resources + * @see javax.servlet.GenericServlet#destroy() + */ + @Override + public void destroy() { + if (dirCache != null) { + // shut down dirCache? + dirCache = null; + } + if (imageEx != null) { + // shut down image thread pool + List rj = imageEx.shutdownNow(); + int nrj = rj.size(); + if (nrj > 0) { + logger.error("Still running threads when shutting down image job queue: "+nrj); + } + } + if (pdfEx != null) { + // shut down pdf thread pool + List rj = pdfEx.shutdownNow(); + int nrj = rj.size(); + if (nrj > 0) { + logger.error("Still running threads when shutting down PDF job queue: "+nrj); + } + } + if (pdfImageEx != null) { + // shut down pdf image thread pool + List rj = pdfImageEx.shutdownNow(); + int nrj = rj.size(); + if (nrj > 0) { + logger.error("Still running threads when shutting down PDF-image job queue: "+nrj); + } + } + super.destroy(); + } + } diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/PDFCache.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/servlet/PDFCache.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,371 @@ +package digilib.servlet; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.concurrent.Future; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; + +import digilib.image.DocuImage; +import digilib.pdf.PDFFileWorker; +import digilib.util.DigilibJobCenter; + +/** + * A class for handling user requests for pdf documents from digilib images. + * + * If a document does not already exist, it will be enqueued for generation; if it does exist, it is sent + * to the user. + * + * @author cmielack + * + */ + +@SuppressWarnings("serial") +public class PDFCache extends HttpServlet { + + public static String version = "0.3a"; + + /** logger for accounting requests */ + protected static Logger accountlog = Logger.getLogger("account.pdf.request"); + + /** gengeral logger for this class */ + protected static Logger logger = Logger.getLogger("digilib.pdfcache"); + + /** logger for authentication related */ + protected static Logger authlog = Logger.getLogger("digilib.pdf.auth"); + + private DigilibConfiguration dlConfig = null; + + public static String instanceKey = "digilib.servlet.PDFCache"; + + private DigilibJobCenter pdfJobCenter = null; + + private DigilibJobCenter pdfImageJobCenter = null; + + private File cache_directory = new File("cache"); + + private File temp_directory = new File("pdf_temp"); + + private static String JSP_WIP = "/pdf/wip.jsp"; + + private static String JSP_ERROR = "/pdf/error.jsp"; + + /** document status. + * DONE: document exists in cache + * WIP: document is "work in progress" + * NONEXISTENT: document does not exist in cache and is not in progress + * ERROR: an error occurred while processing the request + */ + public static enum PDFStatus {DONE, WIP, NONEXISTENT, ERROR}; + + + public void init(ServletConfig config) throws ServletException { + super.init(config); + + System.out.println("***** Digital Image Library Image PDF-Cache Servlet (version " + + version + ") *****"); + // say hello in the log file + logger.info("***** Digital Image Library Image PDF-Cache Servlet (version " + + version + ") *****"); + + ServletContext context = getServletContext(); + dlConfig = (DigilibConfiguration) context.getAttribute("digilib.servlet.configuration"); + if (dlConfig == null) { + // no Configuration + throw new ServletException("No Configuration!"); + } + + String temp_fn = dlConfig.getAsString("pdf-temp-dir"); + temp_directory = new File(temp_fn); + if (!temp_directory.exists()) { + // try to create + temp_directory.mkdirs(); + } else { + // rid the temporary directory of possible incomplete document files + emptyDirectory(temp_directory); + } + if (!temp_directory.isDirectory()) { + throw new ServletException("Configuration error: problem with pdf-temp-dir="+temp_fn); + } + + String cache_fn = dlConfig.getAsString("pdf-cache-dir"); + cache_directory = new File(cache_fn); + if (!cache_directory.exists()) { + // try to create + cache_directory.mkdirs(); + } + if (!cache_directory.isDirectory()) { + throw new ServletException("Configuration error: problem with pdf-cache-dir="+cache_fn); + } + + pdfJobCenter = (DigilibJobCenter) dlConfig.getValue("servlet.worker.pdfexecutor"); + pdfImageJobCenter = (DigilibJobCenter) dlConfig.getValue("servlet.worker.pdfimageexecutor"); + + // register this instance globally + context.setAttribute(instanceKey, this); + + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { + accountlog.info("GET from " + request.getRemoteAddr()); + this.processRequest(request, response); + } + + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { + accountlog.info("POST from " + request.getRemoteAddr()); + this.processRequest(request, response); + } + + /** + * clean up any broken and unfinished files from the temporary directory. + */ + public void emptyDirectory(File dir){ + File[] temp_files = dir.listFiles(); + for (File f: temp_files){ + f.delete(); + } + } + + + public void processRequest(HttpServletRequest request, + HttpServletResponse response) throws ServletException { + + if (dlConfig == null) { + logger.error("ERROR: No Configuration!"); + throw new ServletException("NO VALID digilib CONFIGURATION!"); + } + + String docid = ""; + try { + // evaluate request ( make a PDFJobDeclaration , get the DocumentId) + PDFRequest pdfji = new PDFRequest(request, dlConfig); + + docid = pdfji.getDocumentId(); + + // if some invalid data has been entered ... + if(!pdfji.checkValidity()) { + notifyUser(PDFStatus.ERROR, docid, request, response); + return; + } + + PDFStatus status = getStatus(docid); + + if (status == PDFStatus.NONEXISTENT) { + // not there -- start creation + try { + createNewPdfDocument(pdfji, docid); + notifyUser(status, docid, request, response); + } catch (FileNotFoundException e) { + // error in pdf creation + logger.error(e.getMessage()); + notifyUser(PDFStatus.ERROR, docid, request, response); + } + } else if (status == PDFStatus.DONE) { + // pdf created -- send it + try { + ServletOps.sendFile(getCacheFile(docid), "application/pdf", getDownloadFilename(pdfji), response); + //sendFile(docid, getDownloadFilename(pdfji), response); + } catch (IOException e) { + // sending didn't work + logger.error(e.getMessage()); + } + } else { + // should be work in progress + notifyUser(status, docid, request, response); + } + } catch (Exception e) { + // error in pdf creation + logger.error(e.getMessage()); + notifyUser(PDFStatus.ERROR, docid, request, response); + } + } + + /** + * depending on the documents status, redirect the user to the appropriate waiting or download page. + * + * @param status + * @param documentid + * @param request + * @param response + */ + public void notifyUser(PDFStatus status, String documentid, HttpServletRequest request, HttpServletResponse response){ + + String jsp=null; + + if(status == PDFStatus.NONEXISTENT){ + // tell the user that the document has to be created before he/she can download it + logger.debug("PDFCache: "+documentid+" has STATUS_NONEXISTENT."); + jsp = JSP_WIP; + } else if(status == PDFStatus.WIP){ + logger.debug("PDFCache: "+documentid+" has STATUS_WIP."); + jsp = JSP_WIP; + + // TODO: estimate remaining work time + // TODO: tell the user he/she has to wait + } else if(status == PDFStatus.DONE){ + logger.debug("PDFCache: "+documentid+" has STATUS_DONE."); + } else { + logger.debug("PDFCache: "+documentid+" has STATUS_ERROR."); + jsp = JSP_ERROR; + } + + try { + // forward to the relevant jsp + ServletContext context = getServletContext(); + RequestDispatcher dispatch = context.getRequestDispatcher(jsp); + dispatch.forward(request, response); + } catch (ServletException e) { + logger.debug(e.getMessage()); + e.printStackTrace(); + } catch (IOException e) { + logger.debug(e.getMessage()); + e.printStackTrace(); + } + + } + + + /** check the status of the document corresponding to the documentid */ + public PDFStatus getStatus(String documentid){ + // looks into the cache and temp directory in order to find out the status of the document + File cached = getCacheFile(documentid); + File wip = getTempFile(documentid); + if(cached.exists()){ + return PDFStatus.DONE; + } else if (wip.exists()){ + return PDFStatus.WIP; + } else { + return PDFStatus.NONEXISTENT; + } + } + + /** + * create new thread for pdf generation. + * + * @param pdfji + * @param filename + * @return + * @throws FileNotFoundException + */ + public Future createNewPdfDocument(PDFRequest pdfji, String filename) throws FileNotFoundException{ + // start new worker + File tempf = this.getTempFile(filename); + File finalf = this.getCacheFile(filename); + PDFFileWorker job = new PDFFileWorker(dlConfig, tempf, finalf, pdfji, pdfImageJobCenter); + // start job + Future jobTicket = pdfJobCenter.submit(job); + return jobTicket; + } + + + /** + * generate the filename the user is going to receive the pdf as + * + * @param pdfji + * @return + */ + public String getDownloadFilename(PDFRequest pdfji){ + // filename example: digilib_example_pgs1-3.pdf + String filename; + filename = "digilib_"; + filename += pdfji.getAsString("fn"); + filename += "_pgs" + pdfji.getAsString("pgs"); + filename += ".pdf"; + + return filename; + } + + /** + * sends a document to the user + * + * @param cachefile The filename of the document in cache. + * @param filename The filename used for downloading. + * @param response + * @throws IOException + */ + public void sendFile(String cachefile, String filename, HttpServletResponse response) throws IOException{ + File cached_file = null; + FileInputStream fis = null; + ServletOutputStream sos = null; + BufferedInputStream bis = null; + + try { + // get file handle + cached_file = new File(cache_directory, cachefile); + // create necessary streams + fis = new FileInputStream(cached_file); + sos = response.getOutputStream(); + bis = new BufferedInputStream(fis); + + int bytes = 0; + + // set http headers + response.setContentType("application/pdf"); + response.addHeader("Content-Disposition", "attachment; filename="+filename); + response.setContentLength( (int) cached_file.length()); + + // send the bytes + while ((bytes = bis.read()) != -1){ + sos.write(bytes); + } + } + catch(Exception e){ + logger.error(e.getMessage()); + } + finally{ + // close all streams + if (fis != null) + fis.close(); + if (bis != null) + bis.close(); + if (sos != null) + sos.close(); + } + + } + + public File getCacheDirectory(){ + return cache_directory; + } + + public File getTempDirectory(){ + return temp_directory; + } + + /** + * returns a File object based on filename in the temp directory. + * @param filename + * @return + */ + public File getTempFile(String filename) { + return new File(temp_directory, filename); + } + + /** + * returns a File object based on filename in the cache directory. + * @param filename + * @return + */ + public File getCacheFile(String filename) { + return new File(cache_directory, filename); + } +} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/PDFRequest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/servlet/PDFRequest.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,150 @@ +package digilib.servlet; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.log4j.Logger; + +import digilib.image.ImageJobDescription; +import digilib.io.DocuDirectory; +import digilib.io.FileOpException; +import digilib.io.FileOps.FileClass; +import digilib.util.NumRange; +import digilib.util.OptionsSet; +import digilib.util.ParameterMap; + + +/** + * A container class for storing a set of instruction parameters + * used for content generator classes like MakePDF. + * + * + * @author cmielack, casties + * + */ +public class PDFRequest extends ParameterMap { + + DigilibConfiguration dlConfig = null; + NumRange pages = null; + /** general logger for this class */ + protected static Logger logger = Logger.getLogger("digilib.servlet"); + + + /** + * Initialize the PDFJobInformation + * + * @param dlcfg + * The DigilibConfiguration. + */ + public PDFRequest(DigilibConfiguration dlcfg) { + super(30); + dlConfig = dlcfg; + } + + /** + * Initialize the PDFJobInformation with a request. + * + * @param dlcfg The DigilibConfiguration. + * @param request + * @throws FileOpException + */ + public PDFRequest(HttpServletRequest request, DigilibConfiguration dlcfg) throws FileOpException { + super(30); + dlConfig = dlcfg; + this.setWithRequest(request); + } + + + protected void initParams() { + // page numbers + newParameter("pgs", "", null, 's'); + // url of the page/document (second part) + newParameter("fn", "", null, 's'); + // width of client in pixels + newParameter("dw", new Integer(0), null, 's'); + // height of client in pixels + newParameter("dh", new Integer(500), null, 's'); + } + + /* (non-Javadoc) + * @see digilib.servlet.ParameterMap#initOptions() + */ + @Override + protected void initOptions() { + options = (OptionsSet) getValue("mo"); + } + + /** + * Read the request object. + * + * @param request + * @throws FileOpException + */ + public void setWithRequest(HttpServletRequest request) throws FileOpException { + // read matching request parameters for the parameters in this map + for (String k : params.keySet()) { + if (request.getParameterMap().containsKey(k)) { + setValueFromString(k, request.getParameter(k)); + } + } + // process parameters + pages = new NumRange(getAsString("pgs")); + ImageJobDescription ij = ImageJobDescription.getInstance(this, dlConfig); + DocuDirectory dir = ij.getFileDirectory(); + int dirsize = dir.size(FileClass.IMAGE); + pages.setMaxnum(dirsize); + } + + + /** + * Generate a filename for the pdf to be created. + * + * @return + */ + public String getDocumentId(){ + String fn = getAsString("fn"); + String dh = getAsString("dh"); + String dw = getAsString("dw"); + String pgs = getAsString("pgs"); + + String id = "fn=" + fn + "&dw=" + dw + "&dh=" + dh + "&pgs=" + pgs + ".pdf"; + // make safe to use as filename by urlencoding + try { + id = URLEncoder.encode(id, "UTF-8"); + } catch (UnsupportedEncodingException e) { + // this shouldn't happen + } + return id; + } + + + public ImageJobDescription getImageJobInformation(){ + return ImageJobDescription.getInstance(this, dlConfig); + } + + + public NumRange getPages() { + return pages; + } + + + /** + * Check parameters for validity. + * Returns true if no errors are found. + * + * @return + */ + public boolean checkValidity(){ + if (pages != null) { + return true; + } + return false; + } + + public DigilibConfiguration getDlConfig(){ + return dlConfig; + } + +} \ No newline at end of file diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/Parameter.java --- a/servlet/src/digilib/servlet/Parameter.java Wed Jul 14 16:36:42 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,275 +0,0 @@ -/* Parameter -- General digilib parameter class. - - Digital Image Library servlet components - - Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - Please read license.txt for the full details. A copy of the GPL - may be found at http://www.gnu.org/copyleft/lgpl.html - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * - * Created on 02.09.2003 by casties - * - */ -package digilib.servlet; - -import java.io.File; -import java.io.IOException; - -/** - * General digilib parameter class. - * - * @author casties - * - */ -public class Parameter { - /** real value */ - protected Object value = null; - - /** default value */ - protected Object defval = null; - - /** parameter name (e.g. in config file) */ - protected String name = null; - - /** parameter type */ - protected int type = 0; - - /** - * Default constructor. - * - */ - public Parameter() { - super(); - } - - /** - * Constructor with name, default, and value. - * - * @param value - * @param defval - */ - public Parameter(String name, Object defval, Object value) { - this.name = name; - this.value = value; - this.defval = defval; - } - - /** - * Constructor with name, default, value, and type. - * - * @param value - * @param defval - */ - public Parameter(String name, Object defval, Object value, int type) { - this.name = name; - this.value = value; - this.defval = defval; - this.type = type; - } - - /** - * Is the value valid. - * - * @return - */ - public boolean hasValue() { - return (value != null); - } - - /** - * Try to set the value from a String. - * - * Tries to convert the String to the same type as the default value. Sets - * the value anyway if the default is null. Returns if the value could be - * set. - * - * @param val - * @return - */ - public boolean setValueFromString(String val) { - // no default matches all - if (defval == null) { - this.value = val; - return true; - } - Class c = defval.getClass(); - // take String as is - if (c == String.class) { - this.value = val; - return true; - } - // set File - if (c == File.class) { - this.value = new File(val); - return true; - } - // set Boolean if string == "true" - if (c == Boolean.class) { - this.value = new Boolean(val.compareToIgnoreCase("true") == 0); - return true; - } - try { - // set Integer - if (c == Integer.class) { - this.value = new Integer(Integer.parseInt(val)); - return true; - } - // set Float - if (c == Float.class) { - this.value = new Float(Float.parseFloat(val)); - return true; - } - } catch (NumberFormatException e) { - } - // then it's unknown - return false; - } - - /** - * Get the default as Object. - * - * @return - */ - public Object getDefault() { - return defval; - } - - /** - * Set the default. - * - * @param defval - */ - public void setDefault(Object defval) { - this.defval = defval; - } - - /** - * Get the value as Object. - * - * Returns the default if the value is not set. - * - * @return - */ - public Object getValue() { - return (value != null) ? value : defval; - } - - public int getAsInt() { - Integer i = (Integer) getValue(); - return (i != null) ? i.intValue() : 0; - } - - public float getAsFloat() { - Float f = (Float) getValue(); - return (f != null) ? f.floatValue() : 0f; - } - - public String getAsString() { - Object s = getValue(); - if (s == null) { - return ""; - } - if (s.getClass() == File.class) { - try { - return ((File) s).getCanonicalPath(); - } catch (IOException e) { - return "ERR: " + s.toString(); - } - } - return s.toString(); - } - - public boolean getAsBoolean() { - Boolean b = (Boolean) getValue(); - return (b != null) ? b.booleanValue() : false; - } - - public String[] parseAsArray(String separator) { - String s = getAsString(); - String[] sa = s.split(separator); - return sa; - } - - public float[] parseAsFloatArray(String separator) { - String s = getAsString(); - String[] sa = s.split(separator); - float[] fa = null; - try { - int n = sa.length; - fa = new float[n]; - for (int i = 0; i < n; i++) { - float f = Float.parseFloat(sa[i]); - fa[i] = f; - } - } catch (Exception e) { - } - - return fa; - } - - /** - * Set the value. - * - * @param value - */ - public void setValue(Object value) { - this.value = value; - } - - /** - * Set the value. - * - * @param value - */ - public void setValue(int value) { - this.value = new Integer(value); - } - - /** - * Set the value. - * - * @param value - */ - public void setValue(float value) { - this.value = new Float(value); - } - - /** - * @return - */ - public String getName() { - return name; - } - - /** - * @param name - */ - public void setName(String name) { - this.name = name; - } - - /** - * @return - */ - public int getType() { - return type; - } - - /** - * @param type - */ - public void setType(int type) { - this.type = type; - } - -} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/ParameterMap.java --- a/servlet/src/digilib/servlet/ParameterMap.java Wed Jul 14 16:36:42 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,251 +0,0 @@ -/* ParameterMap.java -- HashMap of Parameters. - - Digital Image Library servlet components - - Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - Please read license.txt for the full details. A copy of the GPL - may be found at http://www.gnu.org/copyleft/lgpl.html - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * Created on 02.09.2003 by casties - * - */ -package digilib.servlet; - -import java.util.HashMap; - -/** HashMap of digilib.servlet.Parameter's. - * - * Keys are Strings. Values are Parameters. - * - * @author casties - * - */ -public class ParameterMap extends HashMap { - - private static final long serialVersionUID = 1530820988748391313L; - - /** Default constructor. - * - */ - public ParameterMap() { - super(); - } - - /** Construcotr with initial size. - * @param arg0 - */ - public ParameterMap(int arg0) { - super(arg0); - } - - /** Get the Parameter with the corresponding key. - * - * Returns null if no element is associated with key. - * - * @param key - * @return - */ - public Parameter get(String key) { - return (Parameter) super.get(key); - } - - /** Get the Parameter with the corresponding key. - * - * Returns null if no element is associated with key. - * - * @param key - * @return - */ - public Object getValue(String key) { - Parameter p = (Parameter) super.get(key); - return (p != null) ? p.getValue() : null; - } - - /** Get the Parameter with the corresponding key. - * - * Returns null if no element is associated with key. - * - * @param key - * @return - */ - public String getAsString(String key) { - Parameter p = (Parameter) super.get(key); - return (p != null) ? p.getAsString() : null; - } - - /** Get the Parameter with the corresponding key. - * - * Returns null if no element is associated with key. - * - * @param key - * @return - */ - public int getAsInt(String key) { - Parameter p = (Parameter) super.get(key); - return (p != null) ? p.getAsInt() : 0; - } - - /** Get the Parameter with the corresponding key. - * - * Returns null if no element is associated with key. - * - * @param key - * @return - */ - public float getAsFloat(String key) { - Parameter p = (Parameter) super.get(key); - return (p != null) ? p.getAsFloat() : 0f; - } - - /** Get the Parameter with the corresponding key. - * - * Returns null if no element is associated with key. - * - * @param key - * @return - */ - public boolean getAsBoolean(String key) { - Parameter p = (Parameter) super.get(key); - return (p != null) ? p.getAsBoolean() : false; - } - - /** Returns if the Parameter's value has been set. - * - * @param key - * @return - */ - public boolean hasValue(String key) { - Parameter p = (Parameter) super.get(key); - return (p != null) ? p.hasValue() : false; - } - - /** Add the Parameter to the map with a certain key. - * - * Returns the value that was previously associated with key. - * - * @param key - * @param val - * @return - */ - public Parameter put(String key, Parameter val) { - return (Parameter) super.put(key, val); - } - - /** Add the Parameter val to the map, using val's name. - * - * Returns the value that was previously associated with val's name. - * - * @param val - * @return - */ - public Parameter put(Parameter val) { - return (Parameter) super.put(val.getName(), val); - } - - /** Add a new Parameter with name, default and value. - * - * Returns the key that was previously associated with name. - * - * @param name - * @param def - * @param val - * @return - */ - public Parameter newParameter(String name, Object def, Object val) { - Parameter p = new Parameter(name, def, val); - return (Parameter) super.put(name, p); - } - - /** Add a new Parameter with name, default, value and type. - * - * Returns the key that was previously associated with name. - * - * @param name - * @param def - * @param val - * @param type - * @return - */ - public Parameter newParameter(String name, Object def, Object val, int type) { - Parameter p = new Parameter(name, def, val, type); - return (Parameter) super.put(name, p); - } - - /** Set the value of an existing parameter. - * - * Sets the value and returns true if the parameter exists. - * - * @param key - * @param val - * @return - */ - public boolean setValue(String key, Object val) { - Parameter p = get(key); - if (p != null) { - p.setValue(val); - return true; - } - return false; - } - - /** Set the value of an existing parameter. - * - * Sets the value and returns true if the parameter exists. - * - * @param key - * @param val - * @return - */ - public boolean setValue(String key, int val) { - Parameter p = get(key); - if (p != null) { - p.setValue(val); - return true; - } - return false; - } - - /** Set the value of an existing parameter. - * - * Sets the value and returns true if the parameter exists. - * - * @param key - * @param val - * @return - */ - public boolean setValue(String key, float val) { - Parameter p = get(key); - if (p != null) { - p.setValue(val); - return true; - } - return false; - } - - /** Set the value of an existing parameter. - * - * Sets the value and returns true if the parameter exists. - * - * @param key - * @param val - * @return - */ - public boolean setValueFromString(String key, String val) { - Parameter p = get(key); - if (p != null) { - p.setValueFromString(val); - return true; - } - return false; - } -} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/Raster.java --- a/servlet/src/digilib/servlet/Raster.java Wed Jul 14 16:36:42 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,328 +0,0 @@ -/* - * Raster -- Servlet for displaying rasterized SVG graphics - * - * Digital Image Library servlet components - * - * Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * Please read license.txt for the full details. A copy of the GPL may be found - * at http://www.gnu.org/copyleft/lgpl.html You should have received a copy of - * the GNU General Public License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 USA - * - * Created on 25.11.2003 by casties - */ - -package digilib.servlet; - -import java.awt.geom.Rectangle2D; -import java.io.IOException; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.xml.parsers.SAXParserFactory; - -import org.apache.batik.dom.svg.SAXSVGDocumentFactory; -import org.apache.batik.transcoder.TranscoderException; -import org.apache.batik.transcoder.TranscoderInput; -import org.apache.batik.transcoder.TranscoderOutput; -import org.apache.batik.transcoder.image.PNGTranscoder; -import org.apache.batik.util.XMLResourceDescriptor; -import org.apache.log4j.Logger; -import org.w3c.dom.svg.SVGDocument; -import org.w3c.dom.svg.SVGSVGElement; - -import digilib.auth.AuthOps; -import digilib.io.DocuDirCache; -import digilib.io.DocuDirectory; -import digilib.io.FileOpException; -import digilib.io.FileOps; -import digilib.io.SVGFile; - -/** - * Servlet for displaying SVG graphics - * - * @author casties - * - */ -public class Raster extends HttpServlet { - - private static final long serialVersionUID = -7756999389932675241L; - - /** Servlet version */ - public static String servletVersion = "0.2b1"; - /** DigilibConfiguration instance */ - DigilibConfiguration dlConfig = null; - /** general logger */ - Logger logger = Logger.getLogger("digilib.raster"); - /** AuthOps instance */ - AuthOps authOp; - /** DocuDirCache instance */ - DocuDirCache dirCache; - /** SVG document factory */ - SAXSVGDocumentFactory docFactory; - - /** use authentication */ - boolean useAuthentication = false; - - /* - * (non-Javadoc) - * - * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) - */ - public void init(ServletConfig config) throws ServletException { - super.init(config); - - System.out.println( - "***** Digital Image Library SVG Render Servlet (version " - + servletVersion - + ") *****"); - - // get our ServletContext - ServletContext context = config.getServletContext(); - // see if there is a Configuration instance - dlConfig = - (DigilibConfiguration) context.getAttribute( - "digilib.servlet.configuration"); - if (dlConfig == null) { - // no config - throw new ServletException("ERROR: No Configuration!"); - } - // say hello in the log file - logger.info( - "***** Digital Image Library SVG Render Servlet (version " - + servletVersion - + ") *****"); - - // set our AuthOps - useAuthentication = dlConfig.getAsBoolean("use-authorization"); - authOp = (AuthOps) dlConfig.getValue("servlet.auth.op"); - // DocuDirCache instance - dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache"); - // parser name as a String (I hate you for not using JAXP, Batik!) - String parserName = null; - try { - // try the proper JAXP way - parserName = SAXParserFactory.newInstance().newSAXParser().getXMLReader().getClass().getName(); - } catch (Exception e) { - // fall back to Batik's hack - parserName = XMLResourceDescriptor.getXMLParserClassName(); - } - logger.debug("parser name: "+parserName); - docFactory = new SAXSVGDocumentFactory(parserName); - } - - /* - * (non-Javadoc) - * - * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, - * javax.servlet.http.HttpServletResponse) - */ - protected void doGet( - HttpServletRequest request, - HttpServletResponse response) - throws ServletException, IOException { - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // add DigilibRequest to ServletRequest - request.setAttribute("digilib.servlet.request", dlReq); - // do the processing - processRequest(request, response); - } - - /* - */ - protected void doPost( - HttpServletRequest request, - HttpServletResponse response) - throws ServletException, IOException { - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // add DigilibRequest to ServletRequest - request.setAttribute("digilib.servlet.request", dlReq); - // do the processing - processRequest(request, response); - } - - /* - * (non-Javadoc) - * - * @see javax.servlet.http.HttpServlet#getLastModified(javax.servlet.http.HttpServletRequest) - */ - protected long getLastModified(HttpServletRequest request) { - logger.debug("GetLastModified from " + request.getRemoteAddr() - + " for " + request.getQueryString()); - long mtime = -1; - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // find the requested file - - // get PathInfo - String loadPathName = dlReq.getFilePath(); - // find the file(set) - SVGFile fileToLoad = - (SVGFile) dirCache.getFile( - loadPathName, - dlReq.getAsInt("pn"), - FileOps.CLASS_SVG); - if (fileToLoad != null) { - DocuDirectory dd = (DocuDirectory) fileToLoad.getParent(); - mtime = dd.getDirMTime() / 1000 * 1000; - } - return mtime; - } - - - - - protected void processRequest( - HttpServletRequest request, - HttpServletResponse response) - throws ServletException, IOException { - - logger.debug("request: "+request.getQueryString()); - // time for benchmarking - long startTime = System.currentTimeMillis(); - - /* - * request parameters - */ - DigilibRequest dlRequest = - (DigilibRequest) request.getAttribute("digilib.servlet.request"); - - // destination image width - int paramDW = dlRequest.getAsInt("dw"); - // destination image height - int paramDH = dlRequest.getAsInt("dh"); - // relative area x_offset (0..1) - float paramWX = dlRequest.getAsFloat("wx"); - // relative area y_offset - float paramWY = dlRequest.getAsFloat("wy"); - // relative area width (0..1) - double paramWW = dlRequest.getAsFloat("ww"); - // relative area height - double paramWH = dlRequest.getAsFloat("wh"); - - try { - - /* - * find the file to load/send - */ - - // get PathInfo - String loadPathName = dlRequest.getFilePath(); - // find the file(set) - SVGFile fileToLoad = - (SVGFile) dirCache.getFile( - loadPathName, - dlRequest.getAsInt("pn"), - FileOps.CLASS_SVG); - if (fileToLoad == null) { - throw new FileOpException( - "File " - + loadPathName - + "(" - + dlRequest.getAsString("pn") - + ") not found."); - } - - /* - * read the SVG document - */ - - // read the document - SVGDocument doc = - docFactory.createSVGDocument( - fileToLoad.getFile().toURI().toString()); - // extract the SVG root - SVGSVGElement svgroot = doc.getRootElement(); - // get document width and height - float imgWidth = svgroot.getWidth().getBaseVal().getValue(); - float imgHeight = svgroot.getHeight().getBaseVal().getValue(); - logger.debug("IMG: "+imgWidth+"x"+imgHeight); - - /* - * set up the transcoder - */ - - // create a PNG transcoder - PNGTranscoder transcoder = new PNGTranscoder(); - // create the transcoder input - //InputStream is = new FileInputStream(fileToLoad.getFile()); - TranscoderInput input = new TranscoderInput(doc); - logger.info("Loading: " + fileToLoad.getFile()); - // create the transcoder output - TranscoderOutput output = - new TranscoderOutput(response.getOutputStream()); - // output is image/png - response.setContentType("image/png"); - - // area of interest - Rectangle2D aoi = - new Rectangle2D.Double( - paramWX * imgWidth, - paramWY * imgHeight, - paramWW * imgWidth, - paramWH * imgHeight); - transcoder.addTranscodingHint(PNGTranscoder.KEY_AOI, aoi); - - // destination image dimensions - if (paramDW > 0) { - transcoder.addTranscodingHint( - PNGTranscoder.KEY_WIDTH, - new Float(paramDW)); - } - if (paramDH > 0) { - transcoder.addTranscodingHint( - PNGTranscoder.KEY_HEIGHT, - new Float(paramDH)); - } - - /* - * transcode - */ - - transcoder.transcode(input, output); - - logger.info( - "Done in " + (System.currentTimeMillis() - startTime) + "ms"); - - /* - * error handling - */ - - } catch (FileOpException e) { - logger.error("ERROR: File IO Error: ", e); - try { - ServletOps.htmlMessage("ERROR: File IO Error: " + e, response); - } catch (Exception ex) { - } // so we don't get a loop - } catch (TranscoderException e) { - logger.error("ERROR: SVG encoder error: ", e); - try { - ServletOps.htmlMessage( - "ERROR: SVG encoder error: " + e, - response); - } catch (Exception ex) { - } // so we don't get a loop - } - - } - -} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/Scaler.java --- a/servlet/src/digilib/servlet/Scaler.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/servlet/Scaler.java Tue Dec 21 09:52:16 2010 +0100 @@ -1,32 +1,10 @@ -/* - * Scaler -- Scaler servlet main class - * - * Digital Image Library servlet components - * - * Copyright (C) 200-2004 Robert Casties (robcast@mail.berlios.de) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * Please read license.txt for the full details. A copy of the GPL may be found - * at http://www.gnu.org/copyleft/lgpl.html - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - package digilib.servlet; -import java.awt.geom.AffineTransform; -import java.awt.geom.NoninvertibleTransformException; -import java.awt.geom.Rectangle2D; import java.io.File; import java.io.IOException; import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; @@ -39,714 +17,303 @@ import digilib.auth.AuthOpException; import digilib.auth.AuthOps; -import digilib.image.ImageOpException; -import digilib.image.ImageOps; -import digilib.image.ImageSize; +import digilib.image.DocuImage; +import digilib.image.ImageJobDescription; +import digilib.image.ImageWorker; import digilib.io.DocuDirCache; import digilib.io.DocuDirectory; import digilib.io.DocuDirent; -import digilib.io.FileOpException; -import digilib.io.FileOps; +import digilib.io.FileOps.FileClass; import digilib.io.ImageFile; -import digilib.io.ImageFileset; +import digilib.util.DigilibJobCenter; -/** - * @author casties - */ -// public class Scaler extends HttpServlet implements SingleThreadModel { +@SuppressWarnings("serial") public class Scaler extends HttpServlet { - private static final long serialVersionUID = -325080527268912852L; - - /** digilib servlet version (for all components) */ - public static final String dlVersion = "1.7.1b"; - - /** logger for accounting requests */ - private static Logger accountlog = Logger.getLogger("account.request"); - - /** gengeral logger for this class */ - private static Logger logger = Logger.getLogger("digilib.servlet"); - - /** logger for authentication related */ - private static Logger authlog = Logger.getLogger("digilib.auth"); - - /** general error code */ - public static final int ERROR_UNKNOWN = 0; + /** digilib servlet version (for all components) */ + public static final String version = "1.9.0a"; - /** error code for authentication error */ - public static final int ERROR_AUTH = 1; - - /** error code for file operation error */ - public static final int ERROR_FILE = 2; - - /** error code for image operation error */ - public static final int ERROR_IMAGE = 3; + /** servlet error codes */ + public static enum Error {UNKNOWN, AUTH, FILE, IMAGE}; + + /** type of error message */ + public static enum ErrMsg {IMAGE, TEXT, CODE}; + + /** logger for accounting requests */ + protected static Logger accountlog = Logger.getLogger("account.request"); - /** DocuDirCache instance */ - DocuDirCache dirCache; - - /** authentication error image file */ - File denyImgFile; - - /** image error image file */ - File errorImgFile; - - /** not found error image file */ - File notfoundImgFile; + /** gengeral logger for this class */ + protected static Logger logger = Logger.getLogger("digilib.servlet"); - /** subsampling before scaling */ - float minSubsample = 2f; - - /** send files as is? */ - boolean sendFileAllowed = true; - - /** default scaling quality */ - int defaultQuality = 1; + /** logger for authentication related */ + protected static Logger authlog = Logger.getLogger("digilib.auth"); - /** DigilibConfiguration instance */ - DigilibConfiguration dlConfig; - - /** use authorization database */ - boolean useAuthorization = true; - - /** AuthOps instance */ - AuthOps authOp; + /** DocuDirCache instance */ + DocuDirCache dirCache; - // EXPRIMENTAL - /** try to enlarge cropping area for "oblique" angles */ - boolean wholeRotArea = false; + /** Image executor */ + DigilibJobCenter imageJobCenter; - /** - * Initialisation on first run. - * - * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) - */ - public void init(ServletConfig config) throws ServletException { - super.init(config); + /** authentication error image file */ + File denyImgFile; - System.out - .println("***** Digital Image Library Image Scaler Servlet (version " - + dlVersion + ") *****"); - // say hello in the log file - logger - .info("***** Digital Image Library Image Scaler Servlet (version " - + dlVersion + ") *****"); + /** image error image file */ + File errorImgFile; - // get our ServletContext - ServletContext context = config.getServletContext(); - // see if there is a Configuration instance - dlConfig = (DigilibConfiguration) context - .getAttribute("digilib.servlet.configuration"); - if (dlConfig == null) { - // no Configuration - throw new ServletException("No Configuration!"); - } - // set our AuthOps - useAuthorization = dlConfig.getAsBoolean("use-authorization"); - authOp = (AuthOps) dlConfig.getValue("servlet.auth.op"); + /** not found error image file */ + File notfoundImgFile; + + /** send files as is? */ + boolean sendFileAllowed = true; - // DocuDirCache instance - dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache"); - denyImgFile = ServletOps.getFile((File) dlConfig.getValue("denied-image"), config); - errorImgFile = ServletOps.getFile((File) dlConfig.getValue("error-image"), config); - notfoundImgFile = ServletOps.getFile((File) dlConfig.getValue("notfound-image"), config); - sendFileAllowed = dlConfig.getAsBoolean("sendfile-allowed"); - minSubsample = dlConfig.getAsFloat("subsample-minimum"); - defaultQuality = dlConfig.getAsInt("default-quality"); - } + /** DigilibConfiguration instance */ + DigilibConfiguration dlConfig; - /** Process the HTTP Get request */ - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - accountlog.info("GET from " + request.getRemoteAddr()); - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // add DigilibRequest to ServletRequest - request.setAttribute("digilib.servlet.request", dlReq); - // do the processing - processRequest(request, response); - } + /** use authorization database */ + boolean useAuthorization = true; + + /** AuthOps instance */ + AuthOps authOp; - /** Process the HTTP Post request */ - public void doPost(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - accountlog.info("POST from " + request.getRemoteAddr()); - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // add DigilibRequest to ServletRequest - request.setAttribute("digilib.servlet.request", dlReq); - // do the processing - processRequest(request, response); - } + /** + * Initialisation on first run. + * + * @throws ServletException + * + * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); - /* - * (non-Javadoc) - * - * @see javax.servlet.http.HttpServlet#getLastModified(javax.servlet.http.HttpServletRequest) - */ - protected long getLastModified(HttpServletRequest request) { - accountlog.debug("GetLastModified from " + request.getRemoteAddr() - + " for " + request.getQueryString()); - long mtime = -1; - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // find the requested file - DocuDirent f = findFile(dlReq); - if (f != null) { - DocuDirectory dd = (DocuDirectory) f.getParent(); - mtime = dd.getDirMTime() / 1000 * 1000; - } - return mtime; - } - - /** main request handler. */ -void processRequest(HttpServletRequest request, HttpServletResponse response) - throws ServletException { - - if (dlConfig == null) { - throw new ServletException("ERROR: No Configuration!"); - } - - accountlog.debug("request: " + request.getQueryString()); - logger.debug("request: " + request.getQueryString()); - - // time for benchmarking - long startTime = System.currentTimeMillis(); - // output mime-type - String mimeType = "image/png"; + System.out + .println("***** Digital Image Library Image Scaler Servlet (version " + + version + ") *****"); + // say hello in the log file + logger.info("***** Digital Image Library Image Scaler Servlet (version " + + version + ") *****"); - /* preset request parameters */ - - // scale the image file to fit window size i.e. respect dw,dh - boolean scaleToFit = true; - // scale the image by a fixed factor only - boolean absoluteScale = false; - // use low resolution images only - boolean loresOnly = false; - // use hires images only - boolean hiresOnly = false; - // send the image always as a specific type (e.g. JPEG or PNG) - int forceType = ImageOps.TYPE_AUTO; - // interpolation to use for scaling - int scaleQual = defaultQuality; - // send html error message (or image file) - boolean errorMsgHtml = false; - // original (hires) image resolution - float origResX = 0; - float origResY = 0; - - /* request parameters */ - - DigilibRequest dlRequest = (DigilibRequest) request - .getAttribute("digilib.servlet.request"); + // get our ServletContext + ServletContext context = config.getServletContext(); + // see if there is a Configuration instance + dlConfig = (DigilibConfiguration) context + .getAttribute("digilib.servlet.configuration"); + if (dlConfig == null) { + // no Configuration + throw new ServletException("No Configuration!"); + } + // set our AuthOps + useAuthorization = dlConfig.getAsBoolean("use-authorization"); + authOp = (AuthOps) dlConfig.getValue("servlet.auth.op"); - // destination image width - int paramDW = dlRequest.getAsInt("dw"); - // destination image height - int paramDH = dlRequest.getAsInt("dh"); - // relative area x_offset (0..1) - float paramWX = dlRequest.getAsFloat("wx"); - // relative area y_offset - float paramWY = dlRequest.getAsFloat("wy"); - // relative area width (0..1) - float paramWW = dlRequest.getAsFloat("ww"); - // relative area height - float paramWH = dlRequest.getAsFloat("wh"); - // scale factor (additional to dw/width, dh/height) - float paramWS = dlRequest.getAsFloat("ws"); - // rotation angle - float paramROT = dlRequest.getAsFloat("rot"); - // contrast enhancement - float paramCONT = dlRequest.getAsFloat("cont"); - // brightness enhancement - float paramBRGT = dlRequest.getAsFloat("brgt"); - // color modification - float[] paramRGBM = null; - Parameter p = dlRequest.get("rgbm"); - if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) { - paramRGBM = p.parseAsFloatArray("/"); - } - float[] paramRGBA = null; - p = dlRequest.get("rgba"); - if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) { - paramRGBA = p.parseAsFloatArray("/"); - } - // destination resolution (DPI) - float paramDDPIX = dlRequest.getAsFloat("ddpix"); - float paramDDPIY = dlRequest.getAsFloat("ddpiy"); - if ((paramDDPIX == 0) || (paramDDPIY == 0)) { - // if X or Y resolution isn't set, use DDPI - paramDDPIX = dlRequest.getAsFloat("ddpi"); - paramDDPIY = paramDDPIX; - } - // absolute scale factor for mo=ascale (and mo=osize) - float paramSCALE = dlRequest.getAsFloat("scale"); + // DocuDirCache instance + dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache"); + + // Executor + imageJobCenter = (DigilibJobCenter) dlConfig + .getValue("servlet.worker.imageexecutor"); + + denyImgFile = ServletOps.getFile( + (File) dlConfig.getValue("denied-image"), config); + errorImgFile = ServletOps.getFile( + (File) dlConfig.getValue("error-image"), config); + notfoundImgFile = ServletOps.getFile( + (File) dlConfig.getValue("notfound-image"), config); + sendFileAllowed = dlConfig.getAsBoolean("sendfile-allowed"); + } - /* - * operation mode: "fit": always fit to page, "clip": send original - * resolution cropped, "file": send whole file (if allowed) - */ - if (dlRequest.hasOption("mo", "clip")) { - scaleToFit = false; - absoluteScale = false; - hiresOnly = true; - } else if (dlRequest.hasOption("mo", "fit")) { - scaleToFit = true; - absoluteScale = false; - hiresOnly = false; - } else if (dlRequest.hasOption("mo", "osize")) { - scaleToFit = false; - absoluteScale = true; - hiresOnly = true; - } else if (dlRequest.hasOption("mo", "ascale")) { - scaleToFit = false; - absoluteScale = true; - hiresOnly = false; - } + /** Returns modification time relevant to the request for caching. + * + * @see javax.servlet.http.HttpServlet#getLastModified(javax.servlet.http.HttpServletRequest) + */ + protected long getLastModified(HttpServletRequest request) { + accountlog.debug("GetLastModified from " + request.getRemoteAddr() + + " for " + request.getQueryString()); + long mtime = -1; + // create new request + DigilibRequest dlReq = new DigilibRequest(request); + // find the file(set) + DocuDirent f = dirCache.getFile(dlReq.getFilePath(), + dlReq.getAsInt("pn"), FileClass.IMAGE); + // find the requested file + if (f != null) { + DocuDirectory dd = (DocuDirectory) f.getParent(); + mtime = dd.getDirMTime() / 1000 * 1000; + } + return mtime; + } - // operation mode: "lores": try to use scaled image, "hires": use - // unscaled image - // "autores": try best fitting resolution - if (dlRequest.hasOption("mo", "lores")) { - loresOnly = true; - hiresOnly = false; - } else if (dlRequest.hasOption("mo", "hires")) { - loresOnly = false; - hiresOnly = true; - } else if (dlRequest.hasOption("mo", "autores")) { - loresOnly = false; - hiresOnly = false; - } - // operation mode: "errtxt": error message in html, "errimg": error - // image - if (dlRequest.hasOption("mo", "errtxt")) { - errorMsgHtml = true; - } else if (dlRequest.hasOption("mo", "errimg")) { - errorMsgHtml = false; - } - // operation mode: "q0" - "q2": interpolation quality - if (dlRequest.hasOption("mo", "q0")) { - scaleQual = 0; - } else if (dlRequest.hasOption("mo", "q1")) { - scaleQual = 1; - } else if (dlRequest.hasOption("mo", "q2")) { - scaleQual = 2; - } - // operation mode: "jpg": always use JPEG - if (dlRequest.hasOption("mo", "jpg")) { - forceType = ImageOps.TYPE_JPEG; - } - // operation mode: "png": always use PNG - if (dlRequest.hasOption("mo", "png")) { - forceType = ImageOps.TYPE_PNG; - } + /* (non-Javadoc) + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { + accountlog.info("GET from " + request.getRemoteAddr()); + this.processRequest(request, response); + } + - // check with the maximum allowed size (if set) - int maxImgSize = dlConfig.getAsInt("max-image-size"); - if (maxImgSize > 0) { - paramDW = (paramDW * paramWS > maxImgSize) ? (int) (maxImgSize / paramWS) - : paramDW; - paramDH = (paramDH * paramWS > maxImgSize) ? (int) (maxImgSize / paramWS) - : paramDH; - } - - // "big" try for all file/image actions - try { - - // ImageFileset of the image to load - ImageFileset fileset = null; - - /* find the file to load/send */ - - // get PathInfo - String loadPathName = dlRequest.getFilePath(); + /* (non-Javadoc) + * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { + accountlog.info("POST from " + request.getRemoteAddr()); + this.processRequest(request, response); + } + - /* check permissions */ - if (useAuthorization) { - // get a list of required roles (empty if no restrictions) - List rolesRequired = authOp.rolesForPath(loadPathName, request); - if (rolesRequired != null) { - authlog.debug("Role required: " + rolesRequired); - authlog.debug("User: " + request.getRemoteUser()); - // is the current request/user authorized? - if (!authOp.isRoleAuthorized(rolesRequired, request)) { - // send deny answer and abort - throw new AuthOpException(); - } - } - } + /** Service this request using the response. + * @param request + * @param response + * @throws ServletException + */ + public void processRequest(HttpServletRequest request, + HttpServletResponse response) throws ServletException { - // find the file - fileset = (ImageFileset) findFile(dlRequest); - if (fileset == null) { - throw new FileOpException("File " + loadPathName + "(" - + dlRequest.getAsInt("pn") + ") not found."); - } + if (dlConfig == null) { + logger.error("ERROR: No Configuration!"); + throw new ServletException("NO VALID digilib CONFIGURATION!"); + } - /* for absolute scale and original size we need the hires size */ - ImageSize hiresSize = null; - if (absoluteScale) { - ImageFile hiresFile = fileset.getBiggest(); - if (!hiresFile.isChecked()) { - ImageOps.checkFile(hiresFile); - } - hiresSize = hiresFile.getSize(); - - /* prepare resolution and scale factor for original size */ - if (dlRequest.hasOption("mo", "osize")) { - // get original resolution from metadata - fileset.checkMeta(); - origResX = fileset.getResX(); - origResY = fileset.getResY(); - if ((origResX == 0) || (origResY == 0)) { - throw new ImageOpException("Missing image DPI information!"); - } + accountlog.debug("request: " + request.getQueryString()); + logger.debug("request: " + request.getQueryString()); + long startTime = System.currentTimeMillis(); - if ((paramDDPIX == 0) || (paramDDPIY == 0)) { - throw new ImageOpException( - "Missing display DPI information!"); - } - // calculate absolute scale factor - float sx = paramDDPIX / origResX; - float sy = paramDDPIY / origResY; - // currently only same scale :-( - paramSCALE = (sx + sy)/2f; - } - - } - + // parse request + DigilibRequest dlRequest = new DigilibRequest(request); + // extract the job information + ImageJobDescription jobTicket = ImageJobDescription.getInstance(dlRequest, dlConfig); - /* calculate expected source image size */ - ImageSize expectedSourceSize = new ImageSize(); - if (scaleToFit) { - // scale to fit -- calculate minimum source size - float scale = (1 / Math.min(paramWW, paramWH)) * paramWS; - expectedSourceSize.setSize((int) (paramDW * scale), - (int) (paramDH * scale)); - } else if (absoluteScale && dlRequest.hasOption("mo", "ascale")) { - // absolute scale -- apply scale to hires size - expectedSourceSize = hiresSize.getScaled(paramSCALE); - } else { - // clip to fit -- source = destination size - expectedSourceSize.setSize((int) (paramDW * paramWS), - (int) (paramDH * paramWS)); - } - - ImageFile fileToLoad; - /* select a resolution */ - if (hiresOnly) { - // get first element (= highest resolution) - fileToLoad = fileset.getBiggest(); - } else if (loresOnly) { - // enforced lores uses next smaller resolution - fileToLoad = fileset.getNextSmaller(expectedSourceSize); - if (fileToLoad == null) { - // this is the smallest we have - fileToLoad = fileset.getSmallest(); - } - } else { - // autores: use next higher resolution - fileToLoad = fileset.getNextBigger(expectedSourceSize); - if (fileToLoad == null) { - // this is the highest we have - fileToLoad = fileset.getBiggest(); - } - } - logger.info("Planning to load: " + fileToLoad.getFile()); + // type of error reporting + ErrMsg errMsgType = ErrMsg.IMAGE; + if (dlRequest.hasOption("errtxt")) { + errMsgType = ErrMsg.TEXT; + } else if (dlRequest.hasOption("errcode")) { + errMsgType = ErrMsg.CODE; + } + + try { + /* + * check if we can fast-track without scaling + */ + ImageFile fileToLoad = jobTicket.getFileToLoad(); - /* - * send the image if its mo=(raw)file - */ - if (dlRequest.hasOption("mo", "file") - || dlRequest.hasOption("mo", "rawfile")) { - if (sendFileAllowed) { - String mt = null; - if (dlRequest.hasOption("mo", "rawfile")) { - mt = "application/octet-stream"; - } - logger.debug("Sending RAW File as is."); - ServletOps.sendFile(fileToLoad.getFile(), mt, response); - logger.info("Done in " - + (System.currentTimeMillis() - startTime) + "ms"); - return; - } - } - - // check the source image - if (!fileToLoad.isChecked()) { - ImageOps.checkFile(fileToLoad); - } - // get the source image type - mimeType = fileToLoad.getMimetype(); - // get the source image size - ImageSize imgSize = fileToLoad.getSize(); - - // decide if the image can be sent as is - boolean mimetypeSendable = mimeType.equals("image/jpeg") - || mimeType.equals("image/png") - || mimeType.equals("image/gif"); - boolean imagoOptions = dlRequest.hasOption("mo", "hmir") - || dlRequest.hasOption("mo", "vmir") || (paramROT != 0) - || (paramRGBM != null) || (paramRGBA != null) - || (paramCONT != 0) || (paramBRGT != 0); - boolean imageSendable = mimetypeSendable && !imagoOptions; - - /* - * if not autoRes and image smaller than requested size then send as - * is. if autoRes and image has requested size then send as is. if - * not autoScale and not scaleToFit nor cropToFit then send as is - * (mo=file) - */ - if (imageSendable - && ((loresOnly && fileToLoad.getSize().isSmallerThan( - expectedSourceSize)) || (!(loresOnly || hiresOnly) && fileToLoad - .getSize().fitsIn(expectedSourceSize)))) { - - logger.debug("Sending File as is."); + // check permissions + if (useAuthorization) { + // get a list of required roles (empty if no restrictions) + List rolesRequired = authOp.rolesForPath( + jobTicket.getFilePath(), request); + if (rolesRequired != null) { + authlog.debug("Role required: " + rolesRequired); + authlog.debug("User: " + request.getRemoteUser()); + // is the current request/user authorized? + if (!authOp.isRoleAuthorized(rolesRequired, request)) { + // send deny answer and abort + throw new AuthOpException(); + } + } + } - ServletOps.sendFile(fileToLoad.getFile(), null, response); - - logger.info("Done in " - + (System.currentTimeMillis() - startTime) + "ms"); - return; - } + // if requested, send image as a file + if (sendFileAllowed && jobTicket.getSendAsFile()) { + String mt = null; + if (jobTicket.hasOption("rawfile")) { + mt = "application/octet-stream"; + } + logger.debug("Sending RAW File as is."); + ServletOps.sendFile(fileToLoad.getFile(), mt, null, response); + logger.info("Done in " + (System.currentTimeMillis() - startTime) + "ms"); + return; + } - - /* - * stop here if we're overloaded... - * - * 503 Service Unavailable - * The server is currently unable to - * handle the request due to a temporary overloading or maintenance - * of the server. The implication is that this is a temporary - * condition which will be alleviated after some delay. If known, - * the length of the delay MAY be indicated in a Retry-After header. - * If no Retry-After is given, the client SHOULD handle the response - * as it would for a 500 response. Note: The existence of the 503 - * status code does not imply that a server must use it when - * becoming overloaded. Some servers may wish to simply refuse the - * connection. - * (RFC2616 HTTP1.1) - */ - if (! DigilibWorker.canRun()) { - logger.error("Servlet overloaded!"); - response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); - return; - } - - // set missing dw or dh from aspect ratio - float imgAspect = fileToLoad.getAspect(); - if (paramDW == 0) { - paramDW = (int) Math.round(paramDH * imgAspect); - } else if (paramDH == 0) { - paramDH = (int) Math.round(paramDW / imgAspect); - } - - /* crop and scale the image */ - - logger.debug("IMG: " + imgSize.getWidth() + "x" - + imgSize.getHeight()); - logger.debug("time " + (System.currentTimeMillis() - startTime) - + "ms"); - - // coordinates and scaling - float areaWidth; - float areaHeight; - float scaleX; - float scaleY; - float scaleXY; + // if possible, send the image without actually having to transform it + if (! jobTicket.isTransformRequired()) { + logger.debug("Sending File as is."); + ServletOps.sendFile(fileToLoad.getFile(), null, null, response); + logger.info("Done in " + (System.currentTimeMillis() - startTime) + "ms"); + return; + } - // coordinates using Java2D - // image size in pixels - Rectangle2D imgBounds = new Rectangle2D.Float(0, 0, imgSize - .getWidth(), imgSize.getHeight()); - // user window area in [0,1] coordinates - Rectangle2D relUserArea = new Rectangle2D.Float(paramWX, paramWY, - paramWW, paramWH); - // transform from relative [0,1] to image coordinates. - AffineTransform imgTrafo = AffineTransform.getScaleInstance(imgSize - .getWidth(), imgSize.getHeight()); - // transform user coordinate area to image coordinate area - Rectangle2D userImgArea = imgTrafo.createTransformedShape( - relUserArea).getBounds2D(); + // check load of workers + if (imageJobCenter.isBusy()) { + logger.error("Servlet overloaded!"); + response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); + return; + } + // create job + ImageWorker job = new ImageWorker(dlConfig, jobTicket); + // submit job + Future jobResult = imageJobCenter.submit(job); + // wait for result + DocuImage img = jobResult.get(); + // send image + ServletOps.sendImage(img, null, response); + logger.debug("Job Processing Time: " + + (System.currentTimeMillis() - startTime) + "ms"); - // calculate scaling factors based on inner user area - if (scaleToFit) { - areaWidth = (float) userImgArea.getWidth(); - areaHeight = (float) userImgArea.getHeight(); - scaleX = paramDW / areaWidth * paramWS; - scaleY = paramDH / areaHeight * paramWS; - scaleXY = (scaleX > scaleY) ? scaleY : scaleX; - } else if (absoluteScale) { - scaleXY = paramSCALE; - // we need to correct the factor if we use a pre-scaled image - if (imgSize.getWidth() != hiresSize.getWidth()) { - scaleXY *= (float)hiresSize.getWidth() / (float)imgSize.getWidth(); - } - scaleX = scaleXY; - scaleY = scaleXY; - areaWidth = paramDW / scaleXY * paramWS; - areaHeight = paramDH / scaleXY * paramWS; - // reset user area size - userImgArea.setRect(userImgArea.getX(), userImgArea.getY(), - areaWidth, areaHeight); - } else { - // crop to fit - areaWidth = paramDW * paramWS; - areaHeight = paramDH * paramWS; - // reset user area size - userImgArea.setRect(userImgArea.getX(), userImgArea.getY(), - areaWidth, areaHeight); - scaleX = 1f; - scaleY = 1f; - scaleXY = 1f; - } + } catch (IOException e) { + logger.error(e.getClass() + ": " + e.getMessage()); + digilibError(errMsgType, Error.FILE, null, response); + } catch (AuthOpException e) { + logger.error(e.getClass() + ": " + e.getMessage()); + digilibError(errMsgType, Error.AUTH, null, response); + } catch (InterruptedException e) { + logger.error(e.getClass() + ": " + e.getMessage()); + } catch (ExecutionException e) { + logger.error(e.getClass() + ": " + e.getMessage()); + String causeMsg = e.getCause().getMessage(); + logger.error("caused by: " + causeMsg); + digilibError(errMsgType, Error.IMAGE, causeMsg, response); + } - // enlarge image area for rotations to cover additional pixels - Rectangle2D outerUserImgArea = userImgArea; - Rectangle2D innerUserImgArea = userImgArea; - if (wholeRotArea) { - if (paramROT != 0) { - try { - // rotate user area coordinates around center of user - // area - AffineTransform rotTrafo = AffineTransform - .getRotateInstance(Math.toRadians(paramROT), - userImgArea.getCenterX(), userImgArea - .getCenterY()); - // get bounds from rotated end position - innerUserImgArea = rotTrafo.createTransformedShape( - userImgArea).getBounds2D(); - // get bounds from back-rotated bounds - outerUserImgArea = rotTrafo.createInverse() - .createTransformedShape(innerUserImgArea) - .getBounds2D(); - } catch (NoninvertibleTransformException e1) { - // this shouldn't happen anyway - logger.error(e1); - } - } - } - - logger.debug("Scale " + scaleXY + "(" + scaleX + "," + scaleY - + ") on " + outerUserImgArea); - - // clip area at the image border - outerUserImgArea = outerUserImgArea.createIntersection(imgBounds); - - // check image parameters sanity - if ((outerUserImgArea.getWidth() < 1) - || (outerUserImgArea.getHeight() < 1) - || (scaleXY * outerUserImgArea.getWidth() < 2) - || (scaleXY * outerUserImgArea.getHeight() < 2)) { - logger.error("ERROR: invalid scale parameter set!"); - throw new ImageOpException("Invalid scale parameter set!"); - } - - /* - * submit the image worker job - */ + } - DigilibWorker job = new DigilibImageWorker(dlConfig, response, - mimeType, scaleQual, dlRequest, paramROT, paramCONT, - paramBRGT, paramRGBM, paramRGBA, fileToLoad, scaleXY, - outerUserImgArea, innerUserImgArea, minSubsample, - wholeRotArea, forceType); - - job.run(); - if (job.hasError()) { - throw new ImageOpException(job.getError().toString()); - } - - logger.debug("servlet done in " - + (System.currentTimeMillis() - startTime)); - - /* error handling */ - - } // end of "big" try - catch (IOException e) { - logger.error("ERROR: File IO Error: " + e); - digilibError(errorMsgHtml, ERROR_FILE, - "ERROR: File IO Error: " + e, response); - } catch (AuthOpException e) { - logger.error("ERROR: Authorization error: " + e); - digilibError(errorMsgHtml, ERROR_AUTH, - "ERROR: Authorization error: " + e, response); - } catch (ImageOpException e) { - logger.error("ERROR: Image Error: " + e); - digilibError(errorMsgHtml, ERROR_IMAGE, - "ERROR: Image Operation Error: " + e, response); - } catch (RuntimeException e) { - // JAI likes to throw RuntimeExceptions ;-( - logger.error("ERROR: Other Image Error: " + e); - digilibError(errorMsgHtml, ERROR_IMAGE, - "ERROR: Other Image Operation Error: " + e, response); - } - } + /** + * Sends an error to the client as text or image. + * + * @param type + * @param error + * @param msg + * @param response + */ + public void digilibError(ErrMsg type, Error error, String msg, + HttpServletResponse response) { + try { + File img = null; + int status = 0; + if (error == Error.AUTH) { + if (msg == null) { + msg = "ERROR: Unauthorized access!"; + } + img = denyImgFile; + status = HttpServletResponse.SC_FORBIDDEN; + } else if (error == Error.FILE) { + if (msg == null) { + msg = "ERROR: Image file not found!"; + } + img = notfoundImgFile; + status = HttpServletResponse.SC_NOT_FOUND; + } else { + if (msg == null) { + msg = "ERROR: Other image error!"; + } + img = this.errorImgFile; + status = HttpServletResponse.SC_BAD_REQUEST; + } + if (type == ErrMsg.TEXT) { + ServletOps.htmlMessage(msg, response); + } else if (type == ErrMsg.CODE) { + response.sendError(status, msg); + } else if (img != null) { + // default: image + ServletOps.sendFile(img, null, null, response); + } + } catch (IOException e) { + logger.error("Error sending error!", e); + } - /** - * Returns the DocuDirent corresponding to the DigilibRequest. - * - * @param dlRequest - * @return - */ - public DocuDirent findFile(DigilibRequest dlRequest) { - // find the file(set) - DocuDirent f = dirCache.getFile(dlRequest.getFilePath(), dlRequest - .getAsInt("pn"), FileOps.CLASS_IMAGE); - return f; - } + } - /** - * Sends an error to the client as text or image. - * - * @param asHTML - * @param type - * @param msg - * @param response - */ - public void digilibError(boolean asHTML, int type, String msg, - HttpServletResponse response) { - try { - File img = null; - if (type == ERROR_AUTH) { - if (msg == null) { - msg = "ERROR: Unauthorized access!"; - } - img = denyImgFile; - } else if (type == ERROR_FILE) { - if (msg == null) { - msg = "ERROR: Image file not found!"; - } - img = notfoundImgFile; - } else { - if (msg == null) { - msg = "ERROR: Other image error!"; - } - img = this.errorImgFile; - } - if (asHTML && (img != null)) { - ServletOps.htmlMessage(msg, response); - } else { - ServletOps.sendFile(img, null, response); - } - } catch (IOException e) { - logger.error("Error sending error!", e); - } + public static String getVersion() { + return version; + } - } - - /** - * @return the dlVersion - */ - public static String getVersion() { - return dlVersion; - } - -} // Scaler class +} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/ServletOps.java --- a/servlet/src/digilib/servlet/ServletOps.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/servlet/ServletOps.java Tue Dec 21 09:52:16 2010 +0100 @@ -33,193 +33,226 @@ import org.apache.log4j.Logger; +import digilib.image.DocuImage; import digilib.io.FileOpException; import digilib.io.FileOps; public class ServletOps { - private static Logger logger = Logger.getLogger("servlet.op"); + private static Logger logger = Logger.getLogger("servlet.op"); - /** - * convert a string with a list of pathnames into an array of strings using - * the system's path seperator string - */ - public static String[] getPathArray(String paths) { - // split list into directories - StringTokenizer dirs = new StringTokenizer(paths, - java.io.File.pathSeparator); - int n = dirs.countTokens(); - if (n < 1) { - return null; - } - // add directories into array - String[] pathArray = new String[n]; - for (int i = 0; i < n; i++) { - pathArray[i] = dirs.nextToken(); - } - return pathArray; - } + /** + * convert a string with a list of pathnames into an array of strings using + * the system's path seperator string + */ + public static String[] getPathArray(String paths) { + // split list into directories + StringTokenizer dirs = new StringTokenizer(paths, + java.io.File.pathSeparator); + int n = dirs.countTokens(); + if (n < 1) { + return null; + } + // add directories into array + String[] pathArray = new String[n]; + for (int i = 0; i < n; i++) { + pathArray[i] = dirs.nextToken(); + } + return pathArray; + } + + /** + * get a real File for a web app File. + * + * If the File is not absolute the path is appended to the base directory of + * the web-app. + * + * @param file + * @param sc + * @return + */ + public static File getFile(File f, ServletConfig sc) { + // is the filename absolute? + if (!f.isAbsolute()) { + // relative path -> use getRealPath to resolve in WEB-INF + String fn = sc.getServletContext().getRealPath(f.getPath()); + f = new File(fn); + } + return f; + } - /** - * get a real File for a web app File. - * - * If the File is not absolute the path is appended to the base directory - * of the web-app. - * - * @param file - * @param sc - * @return - */ - public static File getFile(File f, ServletConfig sc) { - // is the filename absolute? - if (!f.isAbsolute()) { - // relative path -> use getRealPath to resolve in WEB-INF - String fn = sc.getServletContext().getRealPath(f.getPath()); - f = new File(fn); - } - return f; - } + /** + * get a real file name for a web app file pathname. + * + * If filename starts with "/" its treated as absolute else the path is + * appended to the base directory of the web-app. + * + * @param filename + * @param sc + * @return + */ + public static String getFile(String filename, ServletConfig sc) { + File f = new File(filename); + // is the filename absolute? + if (!f.isAbsolute()) { + // relative path -> use getRealPath to resolve in WEB-INF + filename = sc.getServletContext().getRealPath(filename); + } + return filename; + } - /** - * get a real file name for a web app file pathname. - * - * If filename starts with "/" its treated as absolute else the path is - * appended to the base directory of the web-app. - * - * @param filename - * @param sc - * @return - */ - public static String getFile(String filename, ServletConfig sc) { - File f = new File(filename); - // is the filename absolute? - if (!f.isAbsolute()) { - // relative path -> use getRealPath to resolve in WEB-INF - filename = sc.getServletContext() - .getRealPath(filename); - } - return filename; - } + /** + * get a real File for a config File. + * + * If the File is not absolute the path is appended to the WEB-INF directory + * of the web-app. + * + * @param file + * @param sc + * @return + */ + public static File getConfigFile(File f, ServletConfig sc) { + String fn = f.getPath(); + // is the filename absolute? + if (f.isAbsolute()) { + // does it exist? + if (f.canRead()) { + // fine + return f; + } else { + // try just the filename as relative + fn = f.getName(); + } + } + // relative path -> use getRealPath to resolve in WEB-INF + String newfn = sc.getServletContext().getRealPath("WEB-INF/" + fn); + f = new File(newfn); + return f; + } - /** - * get a real File for a config File. - * - * If the File is not absolute the path is appended to the WEB-INF directory - * of the web-app. - * - * @param file - * @param sc - * @return - */ - public static File getConfigFile(File f, ServletConfig sc) { - String fn = f.getPath(); - // is the filename absolute? - if (f.isAbsolute()) { - // does it exist? - if (f.canRead()) { - // fine - return f; - } else { - // try just the filename as relative - fn = f.getName(); - } - } - // relative path -> use getRealPath to resolve in WEB-INF - String newfn = sc.getServletContext().getRealPath( - "WEB-INF/" + fn); - f = new File(newfn); - return f; - } + /** + * get a real file name for a config file pathname. + * + * If filename starts with "/" its treated as absolute else the path is + * appended to the WEB-INF directory of the web-app. + * + * @param filename + * @param sc + * @return + */ + public static String getConfigFile(String filename, ServletConfig sc) { + File f = new File(filename); + // is the filename absolute? + if (!f.isAbsolute()) { + // relative path -> use getRealPath to resolve in WEB-INF + filename = sc.getServletContext() + .getRealPath("WEB-INF/" + filename); + } + return filename; + } - /** - * get a real file name for a config file pathname. - * - * If filename starts with "/" its treated as absolute else the path is - * appended to the WEB-INF directory of the web-app. - * - * @param filename - * @param sc - * @return - */ - public static String getConfigFile(String filename, ServletConfig sc) { - File f = new File(filename); - // is the filename absolute? - if (!f.isAbsolute()) { - // relative path -> use getRealPath to resolve in WEB-INF - filename = sc.getServletContext() - .getRealPath("WEB-INF/" + filename); - } - return filename; - } + /** + * print a servlet response and exit + */ + public static void htmlMessage(String msg, HttpServletResponse response) + throws IOException { + htmlMessage("Scaler", msg, response); + } - /** - * print a servlet response and exit - */ - public static void htmlMessage(String msg, HttpServletResponse response) - throws IOException { - htmlMessage("Scaler", msg, response); - } + /** + * print a servlet response and exit + */ + public static void htmlMessage(String title, String msg, + HttpServletResponse response) throws IOException { + response.setContentType("text/html; charset=iso-8859-1"); + PrintWriter out = response.getWriter(); + out.println(""); + out.println("" + title + ""); + out.println(""); + out.println("

" + msg + "

"); + out.println(""); + } - /** - * print a servlet response and exit - */ - public static void htmlMessage(String title, String msg, - HttpServletResponse response) throws IOException { - response.setContentType("text/html; charset=iso-8859-1"); - PrintWriter out = response.getWriter(); - out.println(""); - out.println("" + title + ""); - out.println(""); - out.println("

" + msg + "

"); - out.println(""); - } + /** + * Transfers an image file as-is with the mime type mt. + * + * The local file is copied to the OutputStream of the + * ServletResponse. If mt is null then the mime-type is + * auto-detected with mimeForFile. + * @param f + * Image file to be sent. + * @param mt + * mime-type of the file. + * @param name + * name of the download file (for application/x) + * @param res + * ServletResponse where the image file will be sent. + * + * @throws FileOpException + * Exception is thrown for a IOException. + * @throws IOException + */ + public static void sendFile(File f, String mt, String name, HttpServletResponse response) + throws FileOpException, IOException { + logger.debug("sendRawFile(" + mt + ", " + f + ")"); + if (mt == null) { + // auto-detect mime-type + mt = FileOps.mimeForFile(f); + if (mt == null) { + throw new FileOpException("Unknown file type."); + } + } + response.setContentType(mt); + // open file + if (mt.startsWith("application")) { + if (name == null) { + // no download name -- use filename + name = f.getName(); + } + response.addHeader("Content-Disposition", "attachment; filename=\""+name+"\""); + } + FileInputStream inFile = new FileInputStream(f); + OutputStream outStream = response.getOutputStream(); + response.setContentLength( (int) f.length()); + byte dataBuffer[] = new byte[4096]; + int len; + while ((len = inFile.read(dataBuffer)) != -1) { + // copy out file + outStream.write(dataBuffer, 0, len); + outStream.flush(); + } + response.flushBuffer(); + inFile.close(); + } - /** - * Transfers an image file as-is with the mime type mt. - * - * The local file is copied to the OutputStream of the - * ServletResponse. If mt is null then the mime-type is - * auto-detected with mimeForFile. - * - * @param mt - * mime-type of the file. - * @param f - * Image file to be sent. - * @param res - * ServletResponse where the image file will be sent. - * @throws FileOpException - * Exception is thrown for a IOException. - */ - public static void sendFile(File f, String mt, - HttpServletResponse response) throws FileOpException { - logger.debug("sendRawFile(" + mt + ", " + f + ")"); - if (mt == null) { - // auto-detect mime-type - mt = FileOps.mimeForFile(f); - if (mt == null) { - throw new FileOpException("Unknown file type."); - } - } - response.setContentType(mt); - // open file - try { - if (mt.equals("application/octet-stream")) { - response.addHeader("Content-Disposition", - "attachment; filename=\"" + f.getName() + "\""); - } - FileInputStream inFile = new FileInputStream(f); - OutputStream outStream = response.getOutputStream(); - byte dataBuffer[] = new byte[4096]; - int len; - while ((len = inFile.read(dataBuffer)) != -1) { - // copy out file - outStream.write(dataBuffer, 0, len); - } - inFile.close(); - response.flushBuffer(); - } catch (IOException e) { - throw new FileOpException("Unable to send file."); - } - } + /** + * Write image img to ServletResponse response. + * + * @param img + * @param mimeType + * @param response + * @throws FileOpException + * @throws IOException + */ + public static void sendImage(DocuImage img, String mimeType, + HttpServletResponse response) throws FileOpException, IOException { + OutputStream outstream = response.getOutputStream(); + // setup output -- if mime type is set use that otherwise + // if source is JPG then dest will be JPG else it's PNG + if (mimeType == null) { + mimeType = img.getMimetype(); + } + if ((mimeType.equals("image/jpeg") || mimeType.equals("image/jp2") || mimeType + .equals("image/fpx"))) { + mimeType = "image/jpeg"; + } else { + mimeType = "image/png"; + } + + // write the image + img.writeImage(mimeType, outstream); + outstream.flush(); + img.dispose(); + } } \ No newline at end of file diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/servlet/Texter.java --- a/servlet/src/digilib/servlet/Texter.java Wed Jul 14 16:36:42 2010 +0200 +++ b/servlet/src/digilib/servlet/Texter.java Tue Dec 21 09:52:16 2010 +0100 @@ -31,6 +31,7 @@ import digilib.io.DocuDirCache; import digilib.io.FileOpException; import digilib.io.FileOps; +import digilib.io.FileOps.FileClass; import digilib.io.TextFile; /** @@ -107,12 +108,6 @@ */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // add DigilibRequest to ServletRequest - request.setAttribute("digilib.servlet.request", dlReq); // do the processing processRequest(request, response); } @@ -125,12 +120,6 @@ */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - // create new request with defaults - DigilibRequest dlReq = new DigilibRequest(); - // set with request parameters - dlReq.setWithRequest(request); - // add DigilibRequest to ServletRequest - request.setAttribute("digilib.servlet.request", dlReq); // do the processing processRequest(request, response); } @@ -141,7 +130,8 @@ /* * request parameters */ - DigilibRequest dlRequest = (DigilibRequest) request.getAttribute("digilib.servlet.request"); + // create new request with defaults + DigilibRequest dlRequest = new DigilibRequest(request); try { /* @@ -149,11 +139,11 @@ */ TextFile f = getTextFile(dlRequest, "/txt"); if (f != null) { - ServletOps.sendFile(f.getFile(), null, response); + ServletOps.sendFile(f.getFile(), null, null, response); } else { f = getTextFile(dlRequest, ""); if (f != null) { - ServletOps.sendFile(f.getFile(), null, response); + ServletOps.sendFile(f.getFile(), null, null, response); } else { response.sendError(HttpServletResponse.SC_NOT_FOUND, "Text-File not found!"); //ServletOps.htmlMessage("No Text-File!", response); @@ -185,6 +175,6 @@ String loadPathName = dlRequest.getFilePath() + subDirectory; // find the file(set) return (TextFile) dirCache.getFile(loadPathName, dlRequest - .getAsInt("pn"), FileOps.CLASS_TEXT); + .getAsInt("pn"), FileClass.TEXT); } } \ No newline at end of file diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/util/DigilibJobCenter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/util/DigilibJobCenter.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,114 @@ +/** Wrapper around ExecutionService. + * + */ +package digilib.util; + +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; + +import org.apache.log4j.Logger; + +import digilib.image.DocuImage; + +/** Wrapper around ExecutionService. + * + * @author casties + * + */ +public class DigilibJobCenter { + /** general logger for this class */ + private static Logger logger = Logger.getLogger("digilib.jobcenter"); + /** ExecutorService */ + private ExecutorService executor; + /** max number of running threads */ + private int maxThreads = 1; + /** max number of waiting threads */ + private int maxQueueLen = 50; + /** label for this job center */ + private String label = ""; + + /** + * @param maxThreads + * @param label TODO + * @param maxQueueLength + */ + public DigilibJobCenter(int maxThreads, int maxQueueLen, boolean prestart, String label) { + super(); + this.label = (label != null) ? label : ""; + this.maxThreads = maxThreads; + this.maxQueueLen = maxQueueLen; + executor = Executors.newFixedThreadPool(maxThreads); + if (prestart) { + // prestart threads so Tomcat's leak protection doesn't complain + int st = ((ThreadPoolExecutor)executor).prestartAllCoreThreads(); + logger.debug(label+" prestarting threads: "+st); + } + } + + /** Submit job to execute + * + * @param job + * @return Future to control the job + */ + public Future submit(Callable job) { + return executor.submit(job); + } + + /** Returns if the service is not overloaded. + * + * @return + */ + public boolean canRun() { + int jql = getWaitingJobs(); + int jrl = getRunningJobs(); + logger.debug(label+" canRun: waiting jobs="+jql+" running jobs="+jrl); + return (jql <= maxQueueLen); + } + + /** Returns if the service is overloaded. + * + * @return + */ + public boolean isBusy() { + int jql = getWaitingJobs(); + int jrl = getRunningJobs(); + logger.debug(label+" isBusy: waiting jobs="+jql+" running jobs="+jrl); + return (jql > maxQueueLen); + } + + public int getRunningJobs() { + return ((ThreadPoolExecutor)executor).getActiveCount(); + } + + public int getWaitingJobs() { + BlockingQueue jq = ((ThreadPoolExecutor)executor).getQueue(); + int jql = jq.size(); + return jql; + } + + public void setMaxThreads(int maxThreads) { + this.maxThreads = maxThreads; + } + + public int getMaxThreads() { + return maxThreads; + } + + public void setMaxQueueLen(int maxQueueLen) { + this.maxQueueLen = maxQueueLen; + } + + public int getMaxQueueLen() { + return maxQueueLen; + } + + public List shutdownNow() { + return executor.shutdownNow(); + } + +} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/util/NumRange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/util/NumRange.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,175 @@ +/** + * + */ +package digilib.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * @author casties + * + */ +public class NumRange implements Iterable { + + private Integer start = 1; + private Integer end = Integer.MAX_VALUE; + private List list = null; + private Integer maxnum = null; + + /** + * @param start + * @param end + */ + public NumRange(Integer start, Integer end) { + this.start = start; + this.end = end; + } + + /** + * @param range + */ + public NumRange(String range) { + parseString(range); + } + + /** + * @param range + */ + public NumRange(String range, Integer max) { + this.maxnum = max; + parseString(range); + } + + + public void parseString(String pages) { + + ArrayList pgs = new ArrayList(); + + String intervals[] = pages.split(","); + + // convert the page-interval-strings into a list containing every single + // page + for (String interval : intervals) { + if (interval.contains("-")) { + String nums[] = interval.split("-"); + int start = Integer.valueOf(nums[0]); + if (nums.length > 1) { + // second number is end of range + int end = Integer.valueOf(nums[1]); + if (intervals.length == 1) { + // optimized case of just one interval + this.start = start; + this.end = end; + this.list = null; + return; + } + for (int i = start; i <= end; i++) { + // add all numbers to list + pgs.add(i); + } + } else { + // second number missing: range to infinity + pgs.add(start); + pgs.add(Integer.MAX_VALUE); + } + } else { + // single number + pgs.add(Integer.valueOf(interval)); + } + } + if (intervals.length > 1) { + Collections.sort(pgs); + } + list = pgs; + } + + public int getStart() { + if (list == null) { + return start; + } else { + return list.get(0); + } + } + + public int getEnd() { + Integer last; + if (list == null) { + last = end; + } else { + last = list.get(list.size() - 1); + } + if (maxnum == null) { + return last; + } else { + return Math.min(last, maxnum); + } + } + + public Iterator iterator() { + if (list == null) { + // return count-based iterator + return new Iterator() { + // anonymous inner Iterator class + private int num = getStart(); + private int end = getEnd(); + + public boolean hasNext() { + return (num <= end); + } + + public Integer next() { + return num++; + } + + public void remove() { + // don't do this + } + }; + } else { + // return list-based iterator + return new Iterator() { + // anonymous inner Iterator class + private int listidx = 0; + private int listend = list.size(); + private int num = getStart(); + private int end = getEnd(); + + public boolean hasNext() { + return (num <= end); + } + + public Integer next() { + if (listidx < listend - 1) { + num = list.get(listidx++); + return num; + } else if (listidx == listend - 1) { + // last element in list + int n = list.get(listidx++); + if (n == Integer.MAX_VALUE) { + // open end -- continue + num++; + return num++; + } else { + num = n; + return num++; + } + } else { + return num++; + } + } + + public void remove() { + // don't do this + } + }; + } + } + + public void setMaxnum(Integer maxnum) { + this.maxnum = maxnum; + } + +} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/util/OptionsSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/util/OptionsSet.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,67 @@ +/** + * + */ +package digilib.util; + +import java.util.HashSet; +import java.util.StringTokenizer; + +/** + * @author casties + * + */ +@SuppressWarnings("serial") +public class OptionsSet extends HashSet { + + protected String optionSep = ","; + + public OptionsSet() { + super(); + } + + /** Constructor with String of options. + * @param s + */ + public OptionsSet(String s) { + super(); + parseString(s); + } + + /** Adds all options from String to Set. + * @param s + */ + public void parseString(String s) { + if (s != null) { + StringTokenizer i = new StringTokenizer(s, optionSep); + while (i.hasMoreTokens()) { + String opt = i.nextToken(); + this.add(opt); + } + } + } + + public boolean hasOption(String opt) { + return this.contains(opt); + } + + public String toString() { + StringBuffer b = new StringBuffer(); + for (String s: this) { + if (b.length() > 0) { + b.append(optionSep); + } + b.append(s); + } + return b.toString(); + } + + + public String getOptionSep() { + return optionSep; + } + + public void setOptionSep(String optionSep) { + this.optionSep = optionSep; + } + +} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/util/Parameter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/util/Parameter.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,284 @@ +/* Parameter -- General digilib parameter class. + + Digital Image Library servlet components + + Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + Please read license.txt for the full details. A copy of the GPL + may be found at http://www.gnu.org/copyleft/lgpl.html + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + * Created on 02.09.2003 by casties + * + */ +package digilib.util; + +import java.io.File; +import java.io.IOException; + + +/** + * General digilib parameter class. + * + * @author casties + * + */ +public class Parameter { + /** real value */ + protected Object value = null; + + /** default value */ + protected Object defval = null; + + /** parameter name (e.g. in config file) */ + protected String name = null; + + /** parameter type */ + protected int type = 0; + + /** + * Default constructor. + * + */ + public Parameter() { + super(); + } + + /** + * Constructor with name, default, and value. + * + * @param value + * @param defval + */ + public Parameter(String name, Object defval, Object value) { + this.name = name; + this.value = value; + this.defval = defval; + } + + /** + * Constructor with name, default, value, and type. + * + * @param value + * @param defval + */ + public Parameter(String name, Object defval, Object value, int type) { + this.name = name; + this.value = value; + this.defval = defval; + this.type = type; + } + + /** + * Is the value valid. + * + * @return + */ + public boolean hasValue() { + return (value != null); + } + + /** + * Try to set the value from a String. + * + * Tries to convert the String to the same type as the default value. Sets + * the value anyway if the default is null. Returns if the value could be + * set. + * + * @param val + * @return + */ + public boolean setValueFromString(String val) { + if (val == null) { + val = ""; + } + // no default matches all + if (defval == null) { + this.value = val; + return true; + } + Class c = defval.getClass(); + // take String as is + if (c == String.class) { + this.value = val; + return true; + } + // set File + if (c == File.class) { + this.value = new File(val); + return true; + } + // set Options + if (c == OptionsSet.class) { + this.value = new OptionsSet(val); + return true; + } + // set Boolean if string == "true" + if (c == Boolean.class) { + this.value = new Boolean(val.compareToIgnoreCase("true") == 0); + return true; + } + try { + // set Integer + if (c == Integer.class) { + this.value = new Integer(Integer.parseInt(val)); + return true; + } + // set Float + if (c == Float.class) { + this.value = new Float(Float.parseFloat(val)); + return true; + } + } catch (NumberFormatException e) { + } + // then it's unknown + return false; + } + + /** + * Get the default as Object. + * + * @return + */ + public Object getDefault() { + return defval; + } + + /** + * Set the default. + * + * @param defval + */ + public void setDefault(Object defval) { + this.defval = defval; + } + + /** + * Get the value as Object. + * + * Returns the default if the value is not set. + * + * @return + */ + public Object getValue() { + return (value != null) ? value : defval; + } + + public int getAsInt() { + Integer i = (Integer) getValue(); + return (i != null) ? i.intValue() : 0; + } + + public float getAsFloat() { + Float f = (Float) getValue(); + return (f != null) ? f.floatValue() : 0f; + } + + public String getAsString() { + Object s = getValue(); + if (s == null) { + return ""; + } + if (s.getClass() == File.class) { + try { + return ((File) s).getCanonicalPath(); + } catch (IOException e) { + return "ERR: " + s.toString(); + } + } + return s.toString(); + } + + public boolean getAsBoolean() { + Boolean b = (Boolean) getValue(); + return (b != null) ? b.booleanValue() : false; + } + + public String[] parseAsArray(String separator) { + String s = getAsString(); + String[] sa = s.split(separator); + return sa; + } + + public float[] parseAsFloatArray(String separator) { + String s = getAsString(); + String[] sa = s.split(separator); + float[] fa = null; + try { + int n = sa.length; + fa = new float[n]; + for (int i = 0; i < n; i++) { + float f = Float.parseFloat(sa[i]); + fa[i] = f; + } + } catch (Exception e) { + } + + return fa; + } + + /** + * Set the value. + * + * @param value + */ + public void setValue(Object value) { + this.value = value; + } + + /** + * Set the value. + * + * @param value + */ + public void setValue(int value) { + this.value = new Integer(value); + } + + /** + * Set the value. + * + * @param value + */ + public void setValue(float value) { + this.value = new Float(value); + } + + /** + * @return + */ + public String getName() { + return name; + } + + /** + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return + */ + public int getType() { + return type; + } + + /** + * @param type + */ + public void setType(int type) { + this.type = type; + } + +} diff -r 9936604d466e -r 1f666c2b4578 servlet/src/digilib/util/ParameterMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/util/ParameterMap.java Tue Dec 21 09:52:16 2010 +0100 @@ -0,0 +1,322 @@ +/* ParameterMap.java -- HashMap of Parameters. + + Digital Image Library servlet components + + Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + Please read license.txt for the full details. A copy of the GPL + may be found at http://www.gnu.org/copyleft/lgpl.html + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * Created on 02.09.2003 by casties + * + */ +package digilib.util; + +import java.util.HashMap; + + +/** HashMap of digilib.servlet.Parameter's. + * + * Keys are Strings. Values are Parameters. + * + * @author casties + * + */ +public class ParameterMap { + + protected HashMap params; + + protected OptionsSet options; + + /** Default constructor. + * + */ + public ParameterMap() { + params = new HashMap(); + options = new OptionsSet(); + initParams(); + } + + /** Constructor with initial size. + * @param size + */ + public ParameterMap(int size) { + params = new HashMap(size); + options = new OptionsSet(); + initParams(); + } + + /** Shallow copy constructor. + * Be warned that the maps are only cloned i.e. keys and values are shared! + * @param pm + */ + @SuppressWarnings("unchecked") + public static ParameterMap cloneInstance(ParameterMap pm) { + ParameterMap newPm = new ParameterMap(); + // clone params to this map + newPm.params = (HashMap) pm.params.clone(); + newPm.options = (OptionsSet) pm.options.clone(); + return newPm; + } + + + /** Creates new ParameterMap by merging Parameters from another ParameterMap. + * @param pm + * @return + */ + public static ParameterMap getInstance(ParameterMap pm) { + ParameterMap newPm = new ParameterMap(); + // add all params to this map + newPm.params.putAll(pm.params); + newPm.initOptions(); + return newPm; + } + + /** set up parameters + * + */ + protected void initParams() { + // no default parameters + } + + /** set up options + * + */ + protected void initOptions() { + // no default options + } + + /** Get the Parameter with the corresponding key. + * + * Returns null if no element is associated with key. + * + * @param key + * @return + */ + public Parameter get(String key) { + return params.get(key); + } + + /** Get the Parameter with the corresponding key. + * + * Returns null if no element is associated with key. + * + * @param key + * @return + */ + public Object getValue(String key) { + Parameter p = params.get(key); + return (p != null) ? p.getValue() : null; + } + + /** Get the Parameter with the corresponding key. + * + * Returns null if no element is associated with key. + * + * @param key + * @return + */ + public String getAsString(String key) { + Parameter p = params.get(key); + return (p != null) ? p.getAsString() : ""; + } + + /** Get the Parameter with the corresponding key. + * + * Returns null if no element is associated with key. + * + * @param key + * @return + */ + public int getAsInt(String key) { + Parameter p = params.get(key); + return (p != null) ? p.getAsInt() : 0; + } + + /** Get the Parameter with the corresponding key. + * + * Returns null if no element is associated with key. + * + * @param key + * @return + */ + public float getAsFloat(String key) { + Parameter p = params.get(key); + return (p != null) ? p.getAsFloat() : 0f; + } + + /** Get the Parameter with the corresponding key. + * + * Returns null if no element is associated with key. + * + * @param key + * @return + */ + public boolean getAsBoolean(String key) { + Parameter p = params.get(key); + return (p != null) ? p.getAsBoolean() : false; + } + + /** Returns if the Parameter's value has been set. + * + * @param key + * @return + */ + public boolean hasValue(String key) { + Parameter p = params.get(key); + return (p != null) ? p.hasValue() : false; + } + + /** Add the Parameter to the map with a certain key. + * + * Returns the value that was previously associated with key. + * + * @param key + * @param val + * @return + */ + public Parameter put(String key, Parameter val) { + return params.put(key, val); + } + + /** Add the Parameter val to the map, using val's name. + * + * Returns the value that was previously associated with val's name. + * + * @param val + * @return + */ + public Parameter put(Parameter val) { + return params.put(val.getName(), val); + } + + /** Add a new Parameter with name, default and value. + * + * Returns the key that was previously associated with name. + * + * @param name + * @param def + * @param val + * @return + */ + public Parameter newParameter(String name, Object def, Object val) { + Parameter p = new Parameter(name, def, val); + return params.put(name, p); + } + + /** Add a new Parameter with name, default, value and type. + * + * Returns the key that was previously associated with name. + * + * @param name + * @param def + * @param val + * @param type + * @return + */ + public Parameter newParameter(String name, Object def, Object val, int type) { + Parameter p = new Parameter(name, def, val, type); + return params.put(name, p); + } + + /** Set the value of an existing parameter. + * + * Sets the value and returns true if the parameter exists. + * + * @param key + * @param val + * @return + */ + public boolean setValue(String key, Object val) { + Parameter p = params.get(key); + if (p != null) { + p.setValue(val); + return true; + } + return false; + } + + /** Set the value of an existing parameter. + * + * Sets the value and returns true if the parameter exists. + * + * @param key + * @param val + * @return + */ + public boolean setValue(String key, int val) { + Parameter p = params.get(key); + if (p != null) { + p.setValue(val); + return true; + } + return false; + } + + /** Set the value of an existing parameter. + * + * Sets the value and returns true if the parameter exists. + * + * @param key + * @param val + * @return + */ + public boolean setValue(String key, float val) { + Parameter p = params.get(key); + if (p != null) { + p.setValue(val); + return true; + } + return false; + } + + /** Set the value of an existing parameter. + * + * Sets the value and returns true if the parameter exists. + * + * @param key + * @param val + * @return + */ + public boolean setValueFromString(String key, String val) { + Parameter p = params.get(key); + if (p != null) { + p.setValueFromString(val); + return true; + } + return false; + } + + /** Returns of the option has been set. + * @param opt + * @return + */ + public boolean hasOption(String opt) { + return options.hasOption(opt); + } + + public HashMap getParams() { + return params; + } + + public void setParams(HashMap params) { + this.params = params; + } + + public OptionsSet getOptions() { + return options; + } + + public void setOptions(OptionsSet options) { + this.options = options; + } +}