001 /* */
002 /* Image Viewer - MCR-IView 1.0, 05-2006 */
003 /* +++++++++++++++++++++++++++++++++++++ */
004 /* */
005 /* Andreas Trappe - concept, devel. in misc. */
006 /* Britta Kapitzki - Design */
007 /* Thomas Scheffler - html prototype */
008 /* Stephan Schmidt - html prototype */
009 /* */
010
011 package org.mycore.frontend.iview;
012
013 import java.awt.Point;
014 import java.io.FileNotFoundException;
015 import java.io.IOException;
016 import java.io.UnsupportedEncodingException;
017 import java.text.DateFormat;
018 import java.text.SimpleDateFormat;
019 import java.util.Enumeration;
020 import java.util.GregorianCalendar;
021 import java.util.List;
022 import java.util.Map;
023 import java.util.Properties;
024 import java.util.StringTokenizer;
025 import java.util.Vector;
026
027 import javax.servlet.ServletException;
028 import javax.servlet.ServletOutputStream;
029 import javax.servlet.http.HttpServletRequest;
030 import javax.servlet.http.HttpServletResponse;
031
032 import org.apache.log4j.Logger;
033 import org.jdom.Document;
034 import org.jdom.Element;
035 import org.jdom.JDOMException;
036 import org.mycore.common.MCRCache;
037 import org.mycore.common.MCRConfiguration;
038 import org.mycore.common.MCRConfigurationException;
039 import org.mycore.common.MCRException;
040 import org.mycore.common.MCRSession;
041 import org.mycore.common.MCRSessionMgr;
042 import org.mycore.datamodel.ifs.MCRDirectory;
043 import org.mycore.datamodel.ifs.MCRFile;
044 import org.mycore.datamodel.ifs.MCRFilesystemNode;
045 import org.mycore.datamodel.metadata.MCRDerivate;
046 import org.mycore.frontend.servlets.MCRServlet;
047 import org.mycore.frontend.servlets.MCRServletJob;
048 import org.mycore.services.imaging.MCRImgCacheCommands;
049 import org.mycore.services.imaging.MCRImgService;
050 import org.mycore.services.imaging.Stopwatch;
051
052 /**
053 * @author Andreas Trappe, Chi Vu Huu
054 *
055 */
056
057 public class MCRIViewServlet extends MCRServlet {
058
059 private static final long serialVersionUID = 1L;
060
061 private static Logger LOGGER = Logger.getLogger(MCRIViewServlet.class);
062
063 private Stopwatch timer = new Stopwatch();
064
065 private String dateFormat = "dd.MM.yyyy HH:mm:ss";
066
067 private DateFormat dateFormatter = new SimpleDateFormat(dateFormat);
068
069 public void init() throws MCRConfigurationException, ServletException {
070 super.init();
071 }
072
073 public void doGetPost(MCRServletJob job) throws IOException, ServletException, JDOMException {
074
075 HttpServletRequest request = job.getRequest();
076 HttpServletResponse response = job.getResponse();
077
078 // get host config
079 String hostAlias = getProperty(request, "hosts");
080 if ((hostAlias == null) || (hostAlias.trim().length() == 0))
081 hostAlias = "local";
082
083 // get PATH of MCRNode
084 String requestPath = request.getPathInfo();
085
086 // printRequest(request);
087
088 // generate error page if path is empty
089 if (requestPath == null)
090 prepareErrorPage(request, response, "Error: HTTP request path is null");
091 // generate error page if path is incorrect
092 StringTokenizer st = new StringTokenizer(requestPath, "/");
093 if (!st.hasMoreTokens())
094 prepareErrorPage(request, response, "Error: HTTP request path is null");
095
096 /*
097 * ######################################################################
098 * ####################################### // get mode and process
099 */
100 timer.start();
101 if ((request.getParameter("mode") != null) && (!request.getParameter("mode").equals(""))) {
102 if (request.getParameter("mode").equals("generateLayout")) {
103 generateLayout(request, response);
104 } else if (request.getParameter("mode").equals("getImage")) {
105 getImage(request, response);
106 } else if (request.getParameter("mode").equals("getMetadata")) {
107 getMetadata(request, response, st);
108 } else if (request.getParameter("mode").equals("setMetadata"))
109 setMetadata(request, response);
110 }
111 timer.stop();
112 timer.reset();
113 }
114
115 public void setMetadata(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
116
117 LOGGER.debug("AJAX: received size of image area - " + "width=" + request.getParameter("XSL.browser.res.width.SESSION")
118 + "px, height=" + request.getParameter("XSL.browser.res.height.SESSION") + "...");
119 Properties resolution = new Properties();
120 resolution.put("XSL.browser.res.width.SESSION", request.getParameter("XSL.browser.res.width.SESSION"));
121 resolution.put("XSL.browser.res.height.SESSION", request.getParameter("XSL.browser.res.height.SESSION"));
122 updateIViewConfig(new Properties(), request, resolution, "AJAX resol. data added...");
123
124 forwardJDOM(request, response, new Element("setMetadata").setText("successfully"));
125
126 }
127
128 public void generateLayout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException,
129 JDOMException {
130
131 MCRFilesystemNode nodeToBeDisplayed = getMCRNodeByRequest(request, response);
132 Properties iViewConfig = setIViewConfig(request);
133 response.setHeader("pragma", "no-cache");
134
135 setZoom(request, iViewConfig, nodeToBeDisplayed);
136 // move ? -> recalculate POI
137 if (iViewConfig.getProperty("MCR.Module-iview.move") != null)
138 movePOI(request, iViewConfig, nodeToBeDisplayed);
139
140 int origWidth = getWidthOfImage(nodeToBeDisplayed);
141 int origHeight = getHeightOfImage(nodeToBeDisplayed);
142
143 // thumbnail highlighting
144 float orig2ThumbSF = MCRIViewTools.computeScaleFactor(getWidthOfImage(nodeToBeDisplayed), getHeightOfImage(nodeToBeDisplayed),
145 getWidthOfThumbnail(iViewConfig), getHeightOfThumbnail(iViewConfig));
146 int thumbPOIX = Math.round(getPOI(iViewConfig).x * orig2ThumbSF);
147 int thumbPOIY = Math.round(getPOI(iViewConfig).y * orig2ThumbSF);
148 int thumbWidth = Math.round(origWidth * orig2ThumbSF);
149 int thumbHeight = Math.round(origHeight * orig2ThumbSF);
150
151 // generate jdom ############################
152 // ############# header
153 Element jdom = new Element("iview");
154 jdom.addContent(new Element("header"));
155 // header - current zoom value
156 jdom.getChild("header").addContent(new Element("currentZoom").setText(getZoom(iViewConfig)));
157 // header - thumbnail highlighting data
158 jdom.getChild("header").addContent(new Element("thumbHighLighting-X").setText(Integer.toString(thumbPOIX)));
159 jdom.getChild("header").addContent(new Element("thumbHighLighting-Y").setText(Integer.toString(thumbPOIY)));
160 jdom.getChild("header").addContent(new Element("thumbHighLighting-SF").setText(Float.toString(orig2ThumbSF)));
161 jdom.getChild("header").addContent(new Element("thumbWidth").setText(Integer.toString(thumbWidth)));
162 jdom.getChild("header").addContent(new Element("thumbHeight").setText(Integer.toString(thumbHeight)));
163 jdom.getChild("header").addContent(new Element("origWidth").setText(Integer.toString(origWidth)));
164 jdom.getChild("header").addContent(new Element("origHeight").setText(Integer.toString(origHeight)));
165
166 // content
167 jdom.addContent(new Element("content").addContent(new Element("ownerID").setText(nodeToBeDisplayed.getOwnerID())));
168 // header - path
169 if (nodeToBeDisplayed instanceof MCRFile)
170 jdom.getChild("content").addContent(new Element("path").setText(nodeToBeDisplayed.getParent().getPath().toString()));
171 else
172 jdom.getChild("content").addContent(new Element("path").setText(nodeToBeDisplayed.getPath().toString()));
173 // header - fileToBeDisplayed
174 if (nodeToBeDisplayed instanceof MCRFile)
175 jdom.getChild("content").addContent(new Element("fileToBeDisplayed").setText(nodeToBeDisplayed.getAbsolutePath().toString()));
176 // header - parent
177 if (nodeToBeDisplayed.hasParent()) {
178 if ((nodeToBeDisplayed instanceof MCRFile) && (nodeToBeDisplayed.getParent().hasParent()))
179 jdom.getChild("content").addContent(new Element("parent").setText(nodeToBeDisplayed.getParent().getParent().getPath()));
180 else if (nodeToBeDisplayed instanceof MCRDirectory)
181 jdom.getChild("content").addContent(new Element("parent").setText(nodeToBeDisplayed.getParent().getPath().toString()));
182 }
183
184 // ############# node list
185 if (nodeToBeDisplayed != null && nodeToBeDisplayed instanceof MCRFile)
186 jdom.getChild("content").addContent(getNodeList(nodeToBeDisplayed.getParent(), iViewConfig, request, response).detach());
187 else if (nodeToBeDisplayed != null && nodeToBeDisplayed instanceof MCRDirectory)
188 jdom.getChild("content").addContent(getNodeList((MCRDirectory) nodeToBeDisplayed, iViewConfig, request, response).detach());
189
190 // forward jdom ############################
191 forwardJDOM(request, response, jdom);
192 }
193
194 /**
195 * Returns the width of an image as int, if possible. If not -1 will be
196 * returned.
197 *
198 * @param MCRFilesystemNode
199 * @return width of image as int or -1, if no width can be found.
200 */
201 private int getWidthOfImage(MCRFilesystemNode fsn) {
202 try {
203 if (fsn instanceof MCRFile) {
204 Element addData = fsn.getAdditionalData("ImageMetaData");
205 // in some unknown circumstances this value is empty, so create
206 // again
207 if (addData == null) {
208 MCRImgCacheCommands.cacheFile((MCRFile) fsn, false);
209 addData = fsn.getAdditionalData("ImageMetaData");
210 }
211 String widthString = addData.getChild("imageSize").getChildText("width");
212 int width = Integer.parseInt(widthString);
213 return width;
214 } else
215 return -1;
216 } catch (NumberFormatException nfe) {
217 LOGGER.warn("", nfe);
218 return -1;
219 } catch (IOException ioe) {
220 LOGGER.warn("", ioe);
221 return -1;
222 } catch (JDOMException jde) {
223 LOGGER.warn("", jde);
224 return -1;
225 }
226 }
227
228 /**
229 * Returns the height of an image as int, if possible. If not -1 will be
230 * returned.
231 *
232 * @param MCRFilesystemNode
233 * @return height of image as int or -1, if no height can be found.
234 */
235 private int getHeightOfImage(MCRFilesystemNode fsn) {
236 try {
237 if (fsn instanceof MCRFile) {
238 Element addData = fsn.getAdditionalData("ImageMetaData");
239 if (addData == null)
240 return -1;
241 String widthString = addData.getChild("imageSize").getChildText("height");
242 int width = Integer.parseInt(widthString);
243 return width;
244 } else
245 return -1;
246 } catch (NumberFormatException nfe) {
247 return -1;
248 } catch (IOException ioe) {
249 return -1;
250 } catch (JDOMException jde) {
251 return -1;
252 }
253 }
254
255 /**
256 * Use this to put the value of a zoom to iViewConfig, if nothing is known.
257 * E.g. zoom can be "thumbnail", "fitToScreen", "0.7", "+0.1" etc. Zoom in
258 * (+) and zoom out (-) are calculated. "fitToScreen", "thumbnail" and
259 * "fitToWidth" are not calculated!
260 *
261 * @param request
262 * HttpRequest
263 * @param Properties
264 * iViewConfig
265 */
266 private void setZoom(HttpServletRequest request, Properties iViewConfig, MCRFilesystemNode fsn) {
267
268 String zoom = getZoom(iViewConfig);
269 float newZoom;
270
271 // zoom out
272 if (zoom.substring(0, 1).equals("-")) {
273 // calculate zoom
274 float lastZoom = getZoomValue(iViewConfig);
275 newZoom = getZoomOut(lastZoom);
276 // save zoom
277 Properties zoomProp = new Properties();
278 zoomProp.put("XSL.MCR.Module-iview.navi.zoom.SESSION", java.lang.Float.toString(newZoom));
279 updateIViewConfig(iViewConfig, request, zoomProp, "setZoomOut=" + java.lang.Float.toString(newZoom)
280 + "........................");
281 // save zoomValue
282 setZoomValue(request, newZoom, iViewConfig);
283 // move poi
284 Point poi = calculatePOIAfterZooming(iViewConfig, getPOI(iViewConfig), lastZoom, newZoom, fsn, true);
285 setPOI(request, iViewConfig, poi);
286 }
287 // zoom in
288 else if (zoom.substring(0, 1).equals(" ")) {
289 // calculate zoom
290 float lastZoom = getZoomValue(iViewConfig);
291 newZoom = getZoomIn(lastZoom);
292 // save zoom
293 Properties zoomProp = new Properties();
294 zoomProp.put("XSL.MCR.Module-iview.navi.zoom.SESSION", java.lang.Float.toString(newZoom));
295 updateIViewConfig(iViewConfig, request, zoomProp, "setZoomIn=" + java.lang.Float.toString(newZoom) + "........................");
296 // save zoomValue
297 setZoomValue(request, newZoom, iViewConfig);
298 // move poi
299 Point poi = calculatePOIAfterZooming(iViewConfig, getPOI(iViewConfig), lastZoom, newZoom, fsn, true);
300 setPOI(request, iViewConfig, poi);
301 }
302 // real given zoom value (is not "thumbnail | fitToScreen | fitToWidth")
303 else if (!(zoom.equals("thumbnail") || zoom.equals("fitToScreen") || zoom.equals("fitToWidth"))) {
304 float oldZoomValue = getZoomValue(iViewConfig);
305 newZoom = java.lang.Float.parseFloat(zoom);
306 newZoom = validateZoom(newZoom);
307 // zoom changed ?
308 if (oldZoomValue != newZoom) {
309 // move poi
310 Point poi = calculatePOIAfterZooming(iViewConfig, getPOI(iViewConfig), getZoomValue(iViewConfig), newZoom, fsn, true);
311 setPOI(request, iViewConfig, poi);
312 }
313 setZoomValue(request, newZoom, iViewConfig);
314 }
315 }
316
317 private Point calculatePOIAfterZooming(Properties iViewConfig, Point oldPOI, float oldZoom, float newZoom, MCRFilesystemNode fsn,
318 boolean log) {
319
320 Point midpoint = new Point();
321 midpoint.x = Math.round(oldPOI.x + (getWidthOfBrowser(iViewConfig) / oldZoom) / 2);
322 midpoint.y = Math.round(oldPOI.y + (getHeightOfBrowser(iViewConfig) / oldZoom) / 2);
323
324 Point newPOI = new Point();
325 newPOI.x = midpoint.x - Math.round(getWidthOfBrowser(iViewConfig) / newZoom / 2);
326 newPOI.y = midpoint.y - Math.round(getHeightOfBrowser(iViewConfig) / newZoom / 2);
327
328 if (log)
329 LOGGER.debug("calculatePOIAfterZooming: new POI=(" + newPOI.x + "," + newPOI.y + ")");
330
331 newPOI = validatePOI(newPOI, iViewConfig, fsn, true);
332
333 return newPOI;
334 }
335
336 private void setZoomValue(HttpServletRequest request, float zoomValue, Properties iViewConfig) {
337 Properties zoomValueProp = new Properties();
338 zoomValueProp.put("XSL.MCR.Module-iview.navi.zoomValue.SESSION", java.lang.Float.toString(zoomValue));
339 updateIViewConfig(iViewConfig, request, zoomValueProp, "setZoomValue=" + java.lang.Float.toString(zoomValue)
340 + "........................");
341 }
342
343 private float getZoomValue(Properties iViewConfig) {
344 if (iViewConfig.containsKey("MCR.Module-iview.navi.zoomValue")) {
345 return java.lang.Float.parseFloat(iViewConfig.getProperty("MCR.Module-iview.navi.zoomValue"));
346 } else {
347 return 1.0F;
348 }
349 }
350
351 private float getZoomIn(float currentZoom) {
352 // calculate
353 float newZoom;
354 float zoomDistance = getZoomDistance();
355 newZoom = currentZoom + zoomDistance;
356 // validate if out of border
357 newZoom = validateZoom(newZoom);
358 // round
359 newZoom = roundZoom(newZoom, true);
360 LOGGER.debug("zoom in value calculated = " + java.lang.Float.toString(newZoom) + " (old: " + java.lang.Float.toString(currentZoom)
361 + ")");
362 return newZoom;
363 }
364
365 private float roundZoom(float zoom, boolean log) {
366 float zoomRounded = (float) (Math.round(zoom * 10)) / 10;
367 if (log)
368 LOGGER.debug("zoom value rounded=" + zoom + " (old:" + zoomRounded);
369 return zoomRounded;
370 }
371
372 private float getZoomOut(float currentZoom) {
373 // calculate
374 float newZoom;
375 float zoomDistance = getZoomDistance();
376 newZoom = currentZoom - zoomDistance;
377 // validate if out of border
378 newZoom = validateZoom(newZoom);
379 // round
380 newZoom = roundZoom(newZoom, true);
381 LOGGER.debug("zoom out value calculated = " + java.lang.Float.toString(newZoom) + " (old: " + java.lang.Float.toString(currentZoom)
382 + ")");
383 return newZoom;
384 }
385
386 private float getZoomDistance() {
387 float zoomDist = java.lang.Float.parseFloat((MCRConfiguration.instance().getString("MCR.Module-iview.zoomDistance")));
388 LOGGER.debug("getZoomDistance=" + java.lang.Float.toString(zoomDist));
389 return zoomDist;
390 }
391
392 private float validateZoom(float zoom) {
393 float verZoom = zoom;
394 if (verZoom < 0.1F)
395 verZoom = 0.1F;
396 else if (verZoom > 1.0F)
397 verZoom = 1.0F;
398 return verZoom;
399 }
400
401 public void getImage(HttpServletRequest request, HttpServletResponse response) throws ServletException, FileNotFoundException,
402 IOException {
403
404 // get right file
405 MCRFilesystemNode nodeToBeDisplayed = getMCRNodeByRequest(request, response);
406 MCRFile image = null;
407 if (nodeToBeDisplayed instanceof MCRFile)
408 image = (MCRFile) nodeToBeDisplayed;
409 else {
410 prepareErrorPage(request, response, "mode=getImage only works with MCRFile, "
411 + "requested MCRFilesystemNode is not of type MCRFile");
412 }
413
414 // get viewer properties
415 Properties iViewConfig = setIViewConfig(request);
416 String zoom = "";
417 int availableWidth = 0;
418 int availableHeight = 0;
419 int xPOI = 0;
420 int yPOI = 0;
421 // // direct call of getImage to get thumbnail
422 if (request.getParameter("XSL.MCR.Module-iview.navi.zoom") != null
423 && request.getParameter("XSL.MCR.Module-iview.navi.zoom").equals("thumbnail")) {
424 zoom = "thumbnail";
425 } // // call from IView
426 else {
427 zoom = getZoom(iViewConfig);
428 availableWidth = getAvailableWidth(zoom, nodeToBeDisplayed, iViewConfig);
429 availableHeight = getAvailableHeight(zoom, nodeToBeDisplayed, iViewConfig);
430 LOGGER.debug("requested zoomFactor=" + zoom);
431 // //// get ROI (Region of interest)
432 xPOI = getPOI(iViewConfig).x;
433 yPOI = getPOI(iViewConfig).y;
434 }
435
436 // put image in requested size to output stream
437 ServletOutputStream out = response.getOutputStream();
438 response.setContentType("image/jpeg");
439 MCRImgService imgService = new MCRImgService();
440 Stopwatch timer = new Stopwatch();
441 timer.start();
442
443 if (zoom.equals("thumbnail")) {
444 int thumbnailWidth = getWidthOfThumbnail(iViewConfig);
445 int thumbnailHeight = getHeightOfThumbnail(iViewConfig);
446 imgService.getImage(image, thumbnailWidth, thumbnailHeight, out, MCRImgService.ScaleMode.normal);
447 timer.stop();
448 LOGGER.debug("finished getting image with zoom=thumbnail from ");
449 } else if (zoom.equals("fitToWidth")) {
450
451 if (scrollBar(iViewConfig)) {
452 imgService.getImage(image, availableWidth, availableWidth, out, MCRImgService.ScaleMode.fitWidth);
453 } else
454 imgService.getImage(image, xPOI, yPOI, availableWidth, availableHeight, out);
455
456 float zoomValue = imgService.getScaleFactor();
457 setZoomValue(request, zoomValue, iViewConfig);
458 LOGGER.debug("finished getting image with zoom=fitToWidth(" + zoomValue + ") from ");
459 } else if (zoom.equals("fitToScreen")) {
460 imgService.getImage(image, availableWidth, availableHeight, out, MCRImgService.ScaleMode.normal);
461 float zoomValue = imgService.getScaleFactor();
462 setZoomValue(request, zoomValue, iViewConfig);
463 LOGGER.debug("finished getting image with zoom=fitToScreen(" + zoomValue + ") from ");
464 } // normal number (10 or 20...)
465 else {
466 float zoomValue = java.lang.Float.parseFloat(zoom);
467 LOGGER.debug("imgService.getImage(image, xPOI(" + xPOI + "), yPOI(" + yPOI + "), " + "availableWidth(" + availableWidth
468 + "), availableHeight(" + availableHeight + "), zoomValue(" + zoomValue + "), out);");
469 imgService.getImage(image, xPOI, yPOI, availableWidth, availableHeight, zoomValue, out);
470 timer.stop();
471 LOGGER.debug("finished getting image with real given zoom=" + zoomValue + " from ");
472 }
473 out.flush();
474 out.close();
475
476 }
477
478 private int getAvailableWidth(String zoom, MCRFilesystemNode nodeToBeDisplayed, Properties iViewConfig) {
479 if (scrollBar(iViewConfig)) {
480 if (zoom.equals("fitToWidth") || zoom.equals("fitToScreen")) {
481 return getWidthOfBrowser(iViewConfig);
482 } // normal number (10 or 20...)
483 else {
484 return getWidthOfImage(nodeToBeDisplayed);
485 }
486 } else {
487 return getWidthOfBrowser(iViewConfig);
488 }
489 }
490
491 private int getAvailableHeight(String zoom, MCRFilesystemNode nodeToBeDisplayed, Properties iViewConfig) {
492 if (scrollBar(iViewConfig)) {
493 if (zoom.equals("fitToWidth")) {
494 return getHeightOfImage(nodeToBeDisplayed);
495 } else if (zoom.equals("fitToScreen")) {
496 return getHeightOfBrowser(iViewConfig);
497 }
498 // normal number (10 or 20...)
499 else
500 return getHeightOfImage(nodeToBeDisplayed);
501 } else {
502 return getHeightOfBrowser(iViewConfig);
503 }
504 }
505
506 private boolean scrollBar(Properties iViewConfig) {
507 if (!iViewConfig.getProperty("MCR.Module-iview.scrollBars", "true").equals("true"))
508 return false;
509 else
510 return true;
511 }
512
513 private int getHeightOfThumbnail(Properties iViewConfig) {
514 int thumbnailHeight = Integer.parseInt(iViewConfig.getProperty("MCR.Module-iview.thumbnail.size.height"));
515 return thumbnailHeight;
516 }
517
518 private int getWidthOfThumbnail(Properties iViewConfig) {
519 int thumbnailWidth = Integer.parseInt(iViewConfig.getProperty("MCR.Module-iview.thumbnail.size.width"));
520 return thumbnailWidth;
521 }
522
523 private String getZoom(Properties iViewConfig) {
524 return iViewConfig.getProperty("MCR.Module-iview.navi.zoom");
525 }
526
527 private int getHeightOfBrowser(Properties iViewConfig) {
528 return Integer.parseInt(iViewConfig.getProperty("browser.res.height").toString());
529 }
530
531 private int getWidthOfBrowser(Properties iViewConfig) {
532 return Integer.parseInt(iViewConfig.getProperty("browser.res.width").toString());
533 }
534
535 public boolean stringNotEmpty(String string) {
536 if (string != null && !string.equals(""))
537 return true;
538 else
539 return false;
540 }
541
542 /**
543 * generates an JDOM-Element containing a list of supported children of a
544 * given node
545 */
546 private Element getNodeList(MCRDirectory dir, Properties iViewConfig, HttpServletRequest request, HttpServletResponse response)
547 throws IOException, ServletException, JDOMException {
548 // get cached file node list from MCRSession OR init new one
549 MCRSession session = MCRSessionMgr.getCurrentSession();
550 String cacheObjKey = "IView.FileNodesList";
551 Object cacheObj = session.get(cacheObjKey);
552 MCRCache cachedFileNodeList;
553 // // init new one
554 if (cacheObj == null) {
555 cachedFileNodeList = new MCRCache(10, "IViewFileNodeList in MCRSession,session=" + session.getID());
556 session.put(cacheObjKey, cachedFileNodeList);
557 } // get cached one
558 else
559 cachedFileNodeList = (MCRCache) cacheObj;
560 String cachedFileNodeListID = dir.getID();
561
562 // get node list from cache
563 if (cachedFileNodeList.get(cachedFileNodeListID) != null
564 && !stringNotEmpty(request.getParameter("XSL.MCR.Module-iview.defaultSort.SESSION"))) {
565 Element nodeList = (Element) cachedFileNodeList.get(cachedFileNodeListID);
566 return nodeList;
567 }
568 // generate node list and put to cache
569 else {
570 String sort = iViewConfig.getProperty("MCR.Module-iview.defaultSort").toString();
571 String sortOrder = iViewConfig.getProperty("MCR.Module-iview.defaultSort.order").toString();
572 int sortValue = 0;
573 int orderValue = 0;
574 if (sort.equals("name"))
575 sortValue = 1;
576 else if (sort.equals("size"))
577 sortValue = 2;
578 else if (sort.equals("lastModified"))
579 sortValue = 3;
580 if (sortOrder.equals("ascending"))
581 orderValue = 4;
582 else
583 orderValue = 5;
584 LOGGER.debug("sort nodes by " + sort + ", order=" + sortOrder);
585 MCRFileNodeComparator comp = new MCRFileNodeComparator(sortValue, orderValue);
586 // get nodes
587 Element root = new Element("nodes");
588 LOGGER.debug("start to get children list");
589 MCRFilesystemNode[] children = dir.getChildren(comp);
590 LOGGER.debug("finsihshed getting children list");
591
592 LOGGER.debug("start to go throug children list");
593 for (int i = 0; i < children.length; i++) {
594 if (getSupport(children[i])) {
595 Element node = new Element("node");
596 node.setAttribute("ID", children[i].getID());
597 root.addContent(node);
598 addChild(node, "name", children[i].getName());
599 addChild(node, "size", String.valueOf(children[i].getSize()));
600 addDate(node, "lastModified", children[i].getLastModified());
601 if (children[i] instanceof MCRFile) {
602 node.setAttribute("type", "file");
603 MCRFile file = (MCRFile) (children[i]);
604 addChild(node, "contentType", file.getContentTypeID());
605 addChild(node, "md5", file.getMD5());
606 addChild(node, "label", file.getLabel());
607 } else
608 node.setAttribute("type", "directory");
609 }
610 }
611 LOGGER.debug("finished to go throug children list");
612 // cache
613 cachedFileNodeList.put(cachedFileNodeListID, root);
614 LOGGER.debug("finished to get node list for" + dir.getName());
615 return root;
616 }
617 }
618
619 private void addChild(Element parent, String itemName, String content) {
620 if ((content == null) || (content.trim().length() == 0))
621 return;
622 parent.addContent(new Element(itemName).addContent(content.trim()));
623 }
624
625 private void addDate(Element parent, String type, GregorianCalendar date) {
626 Element xDate = new Element("date");
627 parent.addContent(xDate);
628
629 xDate.setAttribute("type", type);
630
631 String time = dateFormatter.format(date.getTime());
632
633 xDate.setAttribute("format", dateFormat);
634 xDate.addContent(time);
635 }
636
637 public void prepareErrorPage(HttpServletRequest request, HttpServletResponse response, String errorMessage) throws IOException,
638 ServletException {
639 LOGGER.error(errorMessage);
640 generateErrorPage(request, response, HttpServletResponse.SC_BAD_REQUEST, errorMessage, new MCRException(errorMessage), false);
641 return;
642 }
643
644 private Point getPOI(Properties iViewConfig) {
645 int x = 0;
646 int y = 0;
647
648 if (!scrollBar(iViewConfig)) {
649 if (iViewConfig.getProperty("MCR.Module-iview.roi.xpos") != null
650 || iViewConfig.getProperty("MCR.Module-iview.roi.ypos") != null) {
651 x = Integer.parseInt(iViewConfig.getProperty("MCR.Module-iview.roi.xpos"));
652 y = Integer.parseInt(iViewConfig.getProperty("MCR.Module-iview.roi.ypos"));
653 }
654 }
655
656 return new Point(x, y);
657 }
658
659 public void movePOI(HttpServletRequest request, Properties iViewConfig, MCRFilesystemNode fsn) {
660
661 Point point = getPOI(iViewConfig);
662
663 // position = 0,0
664 if (iViewConfig.getProperty("MCR.Module-iview.move").equals("reset")) {
665 LOGGER.debug("MCR.Module-iview.move=reset received -> xpos and ypos = 0");
666 point.x = 0;
667 point.y = 0;
668 } // new position to be calculated
669 else {
670 // get distance to be moved
671 int deltaX = getXDistance(iViewConfig, true);
672 int deltaY = getYDistance(iViewConfig, true);
673
674 getZoomValue(iViewConfig);
675
676 if (iViewConfig.getProperty("MCR.Module-iview.move").equals("up")) {
677 point.y = point.y - deltaY;
678 LOGGER.debug("move up, new ROI=" + Integer.toString(point.x) + "," + Integer.toString(point.y) + "...");
679 } else if (iViewConfig.getProperty("MCR.Module-iview.move").equals("right")) {
680 point.x = point.x + deltaX;
681 LOGGER.debug("move right, new ROI=" + Integer.toString(point.x) + "," + Integer.toString(point.y) + "...");
682 } else if (iViewConfig.getProperty("MCR.Module-iview.move").equals("down")) {
683 point.y = point.y + deltaY;
684 LOGGER.debug("move down, new ROI=" + Integer.toString(point.x) + "," + Integer.toString(point.y) + "...");
685 } else if (iViewConfig.getProperty("MCR.Module-iview.move").equals("left")) {
686 point.x = point.x - deltaX;
687 LOGGER.debug("move left, new ROI=" + Integer.toString(point.x) + "," + Integer.toString(point.y) + "...");
688 } else if (iViewConfig.getProperty("MCR.Module-iview.move").equals("draged")) {
689 LOGGER.debug("move by draging, old ROI=" + Integer.toString(point.x) + "," + Integer.toString(point.y) + "...");
690 point.x = point.x - deltaX;
691 point.y = point.y - deltaY;
692 LOGGER.debug("move by draging, new ROI=" + Integer.toString(point.x) + "," + Integer.toString(point.y) + "...");
693 }
694 // verify
695 point = validatePOI(point, iViewConfig, fsn, true);
696 }
697 setPOI(request, iViewConfig, point);
698 }
699
700 private void setPOI(HttpServletRequest request, Properties iViewConfig, Point point) {
701 // save
702 Properties roi = new Properties();
703 roi.put("XSL.MCR.Module-iview.roi.xpos.SESSION", Integer.toString(point.x));
704 roi.put("XSL.MCR.Module-iview.roi.ypos.SESSION", Integer.toString(point.y));
705 updateIViewConfig(iViewConfig, request, roi, "save POI(" + Integer.toString(point.x) + "," + Integer.toString(point.y) + ")");
706 }
707
708 private int getXDistance(Properties iViewConfig, boolean log) {
709 int deltaX = 0;
710 if (iViewConfig.getProperty("MCR.Module-iview.move") != null && iViewConfig.getProperty("MCR.Module-iview.move").equals("draged")) {
711 // x draged distance
712 if (iViewConfig.containsKey("MCR.Module-iview.move.distanceX"))
713 deltaX = Integer.parseInt(iViewConfig.getProperty("MCR.Module-iview.move.distanceX").toString());
714 } else {
715 // browser area
716 deltaX = getWidthOfBrowser(iViewConfig);
717 }
718 // adaptated to current zoom
719 // float deltaXAdap = deltaX/getZoomValue(iViewConfig);
720 // round
721 // deltaX = Math.round(deltaXAdap);
722 if (log)
723 LOGGER.debug("x-Distance ==> orig " + deltaX);
724 deltaX = (int) (deltaX / getZoomValue(iViewConfig));
725 if (log)
726 LOGGER.debug("x-Distance ==> browser resol.(" + getWidthOfBrowser(iViewConfig) + ") / " + "currentZoomValue("
727 + getZoomValue(iViewConfig) + ") = " + getWidthOfBrowser(iViewConfig) / getZoomValue(iViewConfig) + " -> rounded = "
728 + deltaX);
729
730 return deltaX;
731 }
732
733 private int getYDistance(Properties iViewConfig, boolean log) {
734 int deltaY = 0;
735 if (iViewConfig.getProperty("MCR.Module-iview.move") != null && iViewConfig.getProperty("MCR.Module-iview.move").equals("draged")) {
736 // x draged distance
737 if (iViewConfig.containsKey("MCR.Module-iview.move.distanceY"))
738 deltaY = Integer.parseInt(iViewConfig.getProperty("MCR.Module-iview.move.distanceY").toString());
739 } else {
740 // browser area
741 deltaY = getHeightOfBrowser(iViewConfig);
742 }
743 // adaptated to current zoom
744 // float deltaYAdap = deltaY/getZoomValue(iViewConfig);
745 // round
746 // deltaY = Math.round(deltaYAdap);
747 if (log)
748 LOGGER.debug("y-Distance ==> orig " + deltaY);
749 deltaY = (int) (deltaY / getZoomValue(iViewConfig));
750 if (log)
751 LOGGER.debug("y-Distance ==> browser resol.(" + getHeightOfBrowser(iViewConfig) + ") / " + "currentZoomValue("
752 + getZoomValue(iViewConfig) + ") = " + getHeightOfBrowser(iViewConfig) / getZoomValue(iViewConfig) + " -> rounded = "
753 + deltaY);
754 return deltaY;
755 }
756
757 /**
758 * Verify if ROI is right and/or below out of image
759 *
760 * @param point
761 */
762 public Point validatePOI(Point point, Properties iViewConfig, MCRFilesystemNode fsn, boolean log) {
763 Point valPoint = new Point(point.x, point.y);
764 int width = getWidthOfImage(fsn);
765 int height = getHeightOfImage(fsn);
766
767 // out on right side
768 if (width > -1) {
769 int xDistance = getXDistance(iViewConfig, false);
770 int widthOfImage = getWidthOfImage(fsn);
771 int outOfBorder = (valPoint.x + xDistance) - widthOfImage;
772
773 if (outOfBorder > 0) {
774 if (log)
775 LOGGER.debug("validatePOI: found x=" + valPoint.x + " which is right out --> reset to " + (valPoint.x - outOfBorder));
776 valPoint.x = valPoint.x - outOfBorder;
777 }
778 }
779 // out on below side
780 if (height > -1) {
781 int outOfBorder = (valPoint.y + getYDistance(iViewConfig, false)) - getHeightOfImage(fsn);
782 if (outOfBorder > 0) {
783 if (log)
784 LOGGER.debug("validatePOI: found y=" + valPoint.y + " which is below out --> reset to " + (valPoint.y - outOfBorder));
785 valPoint.y = valPoint.y - outOfBorder;
786 }
787 }
788 // out on left side
789 if (valPoint.x < 0) {
790 if (log)
791 LOGGER.debug("validatePOI: found x=" + valPoint.x + " which is left out --> reset to 0");
792 valPoint.x = 0;
793 }
794 // out on above side
795 if (valPoint.y < 0) {
796 if (log)
797 LOGGER.debug("validatePOI: found y=" + valPoint.y + " which is above out --> reset to 0");
798 valPoint.y = 0;
799 }
800
801 return valPoint;
802 }
803
804 public void forwardJDOM(HttpServletRequest request, HttpServletResponse response, Element elem) throws IOException {
805
806 // name of target xsl
807 if (getProperty(request, "XSL.Style") == null)
808 request.setAttribute("XSL.Style", "iview");
809 // SAXBuilder builder = new SAXBuilder();
810 Element root = new Element("mcr-module");
811 root.addContent(elem);
812 Document jdom = new Document(root);
813 getLayoutService().doLayout(request, response, jdom);
814 }
815
816 /**
817 * @param node
818 * - The MCRFilesystemNode to be verified
819 * @return true if module imaging supports this MCRFile or at least one
820 * MCRFile within MCRDirectory, false if no support
821 */
822 public boolean getSupport(MCRFilesystemNode node) {
823 String suppContTypes = new String(MCRConfiguration.instance().getString("MCR.Module-iview.SupportedContentTypes"));
824 if (node instanceof MCRDirectory) {
825 List<MCRFile> list = new Vector<MCRFile>();
826 getFirstSupportedFile(list, suppContTypes, (MCRDirectory) node);
827 if (list.size() == 1)
828 return true;
829 else
830 return false;
831 } else {
832 MCRFile file = (MCRFile) node;
833 if (getFileSupport(file))
834 return true;
835 else
836 return false;
837 }
838 }
839
840 public boolean getFileSupport(MCRFile file) {
841 boolean support = false;
842 String suppContTypes = new String(MCRConfiguration.instance().getString("MCR.Module-iview.SupportedContentTypes"));
843 if (file instanceof MCRFile && suppContTypes.indexOf(file.getContentTypeID()) > -1)
844 support = true;
845 return support;
846 }
847
848 public void getFirstSupportedFile(List<MCRFile> list, String contentType, MCRDirectory rootNode) {
849 MCRFilesystemNode[] nodes = rootNode.getChildren();
850 int i = 0;
851 while ((i < nodes.length) && list.size() != 1) {
852 if (nodes[i] instanceof MCRDirectory) {
853 MCRDirectory dir = (MCRDirectory) (nodes[i]);
854 getFirstSupportedFile(list, contentType, dir);
855 } else {
856 MCRFile file = (MCRFile) (nodes[i]);
857 if (contentType.indexOf(file.getContentTypeID()) > -1) {
858 list.add(file);
859 }
860 }
861 i++;
862 }
863 }
864
865 public MCRFilesystemNode getMCRNodeByRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException,
866 IOException {
867 String reqPath = request.getPathInfo();
868 StringTokenizer st = new StringTokenizer(reqPath, "/");
869 String ownerID = st.nextToken(); // ownerID
870
871 // get node
872 MCRFilesystemNode root = MCRFilesystemNode.getRootNode(ownerID);
873 MCRDirectory dirOwnerID = (MCRDirectory) root;
874 MCRFilesystemNode nodeToBeDisplayed = null;
875 if (reqPath.length() - 1 == ownerID.length()) { // root of derivate
876 nodeToBeDisplayed = dirOwnerID;
877 } // some subfolder or file
878 else {
879 int pos = ownerID.length() + 1;
880 String path = reqPath.substring(pos); // path of node without
881 // ownerID
882 nodeToBeDisplayed = dirOwnerID.getChildByPath(path);
883 }
884 if (nodeToBeDisplayed != null && !getSupport(nodeToBeDisplayed))
885 prepareErrorPage(request, response, "Error: MCRFilesystemNode=" + nodeToBeDisplayed.getID()
886 + "is not supported by Module-IView");
887 return nodeToBeDisplayed;
888 }
889
890 public void getMetadata(HttpServletRequest request, HttpServletResponse response, StringTokenizer st) throws ServletException,
891 IOException {
892
893 // type == "support"
894 // verifies if a Derrivat's main file is supported
895 // and responses <support mainfile="...">true|false</support>
896 if (request.getParameter("type").equals("support")) {
897 // get name main file
898 String derivID = st.nextToken();
899 MCRDerivate deriv = new MCRDerivate();
900 deriv.receiveFromDatastore(derivID);
901 String nameOfMainFile = deriv.getDerivate().getInternals().getMainDoc();
902 // verify support
903 if (nameOfMainFile != null && !nameOfMainFile.equals("")) {
904 MCRDirectory root = (MCRDirectory) MCRFilesystemNode.getRootNode(derivID);
905 // get main file
906 MCRFile mainFile = (MCRFile) root.getChildByPath(nameOfMainFile);
907 if (getFileSupport(mainFile)) {
908 forwardJDOM(request, response, new Element("support").setAttribute("mainFile", mainFile.getAbsolutePath()).setText(
909 "true"));
910 } else
911 forwardJDOM(request, response, new Element("support").setText("false"));
912 } else
913 forwardJDOM(request, response, new Element("support").setText("false"));
914 }
915 }
916
917 public Properties getIViewConfig(HttpServletRequest request) {
918 LOGGER.debug("getting IViewConfig....................................");
919 try {
920 return setIViewConfig(request);
921 } catch (UnsupportedEncodingException e) {
922 LOGGER.error("Error while getting IViewConfig from request.", e);
923 return null;
924 }
925 }
926
927 public void updateIViewConfig(Properties iViewConfig, HttpServletRequest request, Properties dateUp, String logMessage) {
928 LOGGER.debug("updating iViewConfig (" + logMessage + ").....................................");
929
930 MCRSession mcrSession = MCRSessionMgr.getCurrentSession();
931 Enumeration<?> e = dateUp.keys();
932 while (e.hasMoreElements()) {
933 String key = e.nextElement().toString();
934 String value = dateUp.get(key).toString();
935
936 if (key.startsWith("XSL.")) {
937 // store parameter in session 'cause it ends with *.SESSION
938 if (key.endsWith(".SESSION")) {
939 String key4IViewConfig = key.substring(4, key.length() - 8);
940 String key4Session = key.substring(0, key.length() - 8);
941
942 iViewConfig.put(key4IViewConfig, value);
943 mcrSession.put(key4Session, value);
944 LOGGER.debug("update IViewConfig: found " + key + "=" + dateUp.getProperty(key)
945 + " that should be saved in session, safed " + key4Session + "=" + value);
946 } else {
947 iViewConfig.put(key.substring(4), value);
948 }
949 }
950
951 }
952 // return iViewConfig;
953 }
954
955 @SuppressWarnings("unchecked")
956 public Properties setIViewConfig(HttpServletRequest request) throws UnsupportedEncodingException {
957
958 LOGGER.debug("setting IViewConfig....................................");
959
960 // PROPERTIES: Read all properties from mycore.properties
961 Properties iViewConfig = (Properties) (MCRConfiguration.instance().getProperties().clone());
962
963 // SESSION: Read all *.xsl attributes that are stored in the browser
964 MCRSession mcrSession = MCRSessionMgr.getCurrentSession();
965 for (Map.Entry<Object, Object> entry : mcrSession.getMapEntries()) {
966 String key = entry.getKey().toString();
967 if (key.startsWith("XSL.")) {
968 iViewConfig.put(key.substring(4), entry.getValue());
969 }
970 }
971
972 // HTTP-REQUEST-PARAMETER: Read all *.xsl attributes from the client
973 for (Enumeration e = request.getParameterNames(); e.hasMoreElements();) {
974 String name = (String) (e.nextElement());
975
976 if (name.startsWith("XSL.")) {
977 if (!name.endsWith(".SESSION")) {
978 iViewConfig.put(name.substring(4), request.getParameter(name));
979 } // store parameter in session if ends with *.SESSION
980 else {
981 iViewConfig.put(name.substring(4, name.length() - 8), request.getParameter(name));
982 if (mcrSession != null) {
983 mcrSession.put(name.substring(0, name.length() - 8), request.getParameter(name));
984 LOGGER.debug("found HTTP-Req.-Parameter " + name + "=" + request.getParameter(name)
985 + " that should be saved in session, safed " + name.substring(0, name.length() - 8) + "="
986 + request.getParameter(name));
987 }
988
989 }
990 }
991 }
992
993 // SERVLETS-REQUEST-ATTRIBUTES: Read all *.xsl attributes provided by
994 // the invoking servlet
995 for (Enumeration e = request.getAttributeNames(); e.hasMoreElements();) {
996 String name = (String) (e.nextElement());
997 if (name.startsWith("XSL.")) {
998 if (!name.endsWith(".SESSION")) {
999 iViewConfig.put(name.substring(4), request.getAttribute(name));
1000 } // store parameter in session if ends with *.SESSION
1001 else {
1002 iViewConfig.put(name.substring(4, name.length() - 8), request.getAttribute(name));
1003 if (mcrSession != null) {
1004 mcrSession.put(name.substring(0, name.length() - 8), request.getAttribute(name));
1005 LOGGER.debug("found Req.-Attribut " + name + "=" + request.getAttribute(name)
1006 + " that should be saved in session, safed " + name.substring(0, name.length() - 8) + "="
1007 + request.getAttribute(name));
1008 }
1009
1010 }
1011 }
1012
1013 }
1014 LOGGER.debug("+++++++++++++++++++++++++++++++++++++++++++++ ");
1015
1016 // ensure iview session is not timed out
1017 verifyIViewConfig(iViewConfig, request);
1018
1019 return iViewConfig;
1020 }
1021
1022 /**
1023 * Ensure iview session is not timed out
1024 *
1025 * @param iViewConfig
1026 * @param request
1027 * TODO
1028 * @throws UnsupportedEncodingException
1029 */
1030 private void verifyIViewConfig(Properties iViewConfig, HttpServletRequest request) throws UnsupportedEncodingException {
1031 Properties dateUp = new Properties();
1032 if (!iViewConfig.containsKey("MCR.Module-iview.navi.zoom"))
1033 dateUp.put("XSL.MCR.Module-iview.navi.zoom.SESSION", "fitToScreen");
1034 if (!iViewConfig.containsKey("MCR.Module-iview.display"))
1035 dateUp.put("XSL.MCR.Module-iview.display.SESSION", "normal");
1036 if (!iViewConfig.containsKey("MCR.Module-iview.style"))
1037 dateUp.put("XSL.MCR.Module-iview.style.SESSION", "image");
1038 if (!iViewConfig.containsKey("MCR.Module-iview.embedded"))
1039 dateUp.put("XSL.MCR.Module-iview.embedded.SESSION", "false");
1040 if (!iViewConfig.containsKey("MCR.Module-iview.lastEmbeddedURL"))
1041 dateUp.put("XSL.MCR.Module-iview.lastEmbeddedURL.SESSION", MCRServlet.getBaseURL());
1042
1043 updateIViewConfig(iViewConfig, request, dateUp, "session timed out, reset essential parameters");
1044 }
1045
1046 @SuppressWarnings("unchecked")
1047 public void printRequest(HttpServletRequest request) {
1048 LOGGER.debug("############################################# ");
1049 for (Enumeration<String> e = request.getHeaderNames(); e.hasMoreElements();) {
1050 String name = e.nextElement();
1051 LOGGER.debug("HEADER: " + name + "=" + request.getHeader(name));
1052 }
1053 LOGGER.debug("start print Request-Parameters ############## ");
1054 for (Enumeration<String> e = request.getParameterNames(); e.hasMoreElements();) {
1055 String name = e.nextElement();
1056 LOGGER.debug("" + name + "=" + request.getParameter(name));
1057 }
1058 LOGGER.debug("finished printing Request-Parameters ######### ");
1059 LOGGER.debug(" ");
1060
1061 LOGGER.debug("start print Request-Attributes ################ ");
1062 for (Enumeration<String> e = request.getAttributeNames(); e.hasMoreElements();) {
1063 String name = e.nextElement();
1064 LOGGER.debug("" + name + "=" + request.getAttribute(name));
1065 }
1066 LOGGER.debug("finished printing Request-Attributes ########## ");
1067 LOGGER.debug("############################################### ");
1068 }
1069
1070 public void printIViewConfig(Properties iViewConfig) {
1071 LOGGER.debug("############################################# ");
1072 LOGGER.debug("start printing IViewCOnfig-Parameters ####### ");
1073
1074 for (Object key : iViewConfig.keySet()) {
1075 String name = key.toString();
1076 String value = iViewConfig.getProperty(name);
1077 if (name.startsWith("MCR.Module-iview") || name.startsWith("browser"))
1078 LOGGER.debug(name + "=" + value);
1079 }
1080 LOGGER.debug("finished printing IViewCOnfig-Parameters ###### ");
1081 LOGGER.debug("############################################### ");
1082 }
1083
1084 }