001 /*
002 Copyright (c) 1996-2011, Damon Hart-Davis
003 All rights reserved.
004
005 Redistribution and use in source and binary forms, with or without
006 modification, are permitted provided that the following conditions are
007 met:
008
009 * Redistributions of source code must retain the above copyright
010 notice, this list of conditions and the following disclaimer.
011
012 * Redistributions in binary form must reproduce the above copyright
013 notice, this list of conditions and the following disclaimer in the
014 documentation and/or other materials provided with the
015 distribution.
016
017 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
018 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
019 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
020 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
021 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
022 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
024 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
025 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
027 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028 */
029
030 package org.hd.d.pg2k.webSvr.virtualHosts.AlohaEarth;
031
032 import java.io.IOException;
033 import java.io.OutputStream;
034
035 import javax.servlet.ServletContext;
036 import javax.servlet.ServletException;
037 import javax.servlet.http.HttpServlet;
038 import javax.servlet.http.HttpServletRequest;
039 import javax.servlet.http.HttpServletResponse;
040
041 import org.hd.d.pg2k.svrCore.CoreConsts;
042 import org.hd.d.pg2k.svrCore.ROByteArray;
043 import org.hd.d.pg2k.webSvr.exhibit.DataSourceBean;
044
045 /**Servlet to serve dynamic Aloha Earth map image.
046 * This expects to be able to collect parameters with a AEParams object.
047 * <p>
048 * If the parameters are missing or out of bounds then a default image
049 * is produced.
050 * <p>
051 * The image produced is with the type indicated by DYN_MAP_IMG_TYPE,
052 * in an efficient (small), indexed format.
053 * <p>
054 * Images may be cached, possibly with SoftReference,
055 * though any such cache may need to be cleared when the
056 * exhibit set or meta data changes.
057 */
058 public final class AlohaEarthMapServlet extends HttpServlet
059 {
060 /**Respond to a GET request for the content served by this servlet.
061 *
062 * @param request The servlet request we are processing
063 * @param response The servlet response we are producing
064 *
065 * @exception IOException if an input/output error occurs
066 * @exception ServletException if a servlet error occurs
067 */
068 @Override
069 public void doGet(final HttpServletRequest request,
070 final HttpServletResponse response)
071 throws IOException, ServletException
072 {
073 doAction(request, response);
074 }
075
076 /**Respond to a HEAD request for the content served by this servlet.
077 *
078 * @param request The servlet request we are processing
079 * @param response The servlet response we are producing
080 *
081 * @exception IOException if an input/output error occurs
082 * @exception ServletException if a servlet error occurs
083 */
084 @Override
085 public void doHead(final HttpServletRequest request,
086 final HttpServletResponse response)
087 throws IOException, ServletException
088 {
089 doAction(request, response);
090 }
091
092 /**Respond to a GET/HEAD request for the content served by this servlet.
093 * Returns the exhibit data, with a correct MIME type.
094 *
095 * @param request The servlet request we are processing
096 * @param response The servlet response we are producing
097 *
098 * @exception IOException if an input/output error occurs
099 * @exception ServletException if a servlet error occurs
100 */
101 public void doAction(final HttpServletRequest request,
102 final HttpServletResponse response)
103 throws IOException, ServletException
104 {
105 try
106 {
107 // Get/create encoded image ready to send to the browser.
108 final AEParams aeps = (new AEParams()).setRequest(request);
109 final ServletContext ctxt = getServletContext();
110 final DataSourceBean dsb = DataSourceBean.getApplicationInstance(ctxt);
111 final ROByteArray encodedImage = AEUtils.getAemfb(dsb).
112 selectMapEncodedImage(aeps, ctxt);
113
114 // Set the correct MIME type and result length.
115 response.setContentType(AEUtils.ETP.mimeType);
116 response.setContentLength(encodedImage.length());
117
118 // Set some cacheing headers too.
119 // We let the image stay in cache for our standard `slackness'.
120 // These images may change with the exhibit set.
121 final int cacheLifetime = CoreConsts.DEFAULT_TEMPORAL_SLACKNESS_S * 1000;
122 response.setHeader("Cache-Control", "max-age="+(cacheLifetime/1000));
123 response.setDateHeader("Expires", System.currentTimeMillis() + cacheLifetime);
124
125 // If this is a HEAD, then return without providing the body.
126 if("HEAD".equalsIgnoreCase(request.getMethod()))
127 { return; }
128
129 // Write entire map-fragment image in one go for efficiency.
130 final OutputStream os = response.getOutputStream();
131 os.write(encodedImage.toByteArray());
132 os.flush();
133 }
134 catch(final Exception e)
135 {
136 // Log the problem!
137 getServletContext().log("failed to generate Aloha Earth map image", e);
138 // Redirect back to original raw image in case of error.
139 // (This may force the browser to rescale the image)
140 // If our result is already committed this may be messy...
141 response.reset();
142 response.resetBuffer();
143 request.getRequestDispatcher(AEUtils.BASE_2D_EARTH_MAP_RRURL).
144 forward(request, response);
145 return;
146 }
147 }
148
149 /**Have the last-modified date be the AEP unchanged-since timestamp. */
150 @Override protected long getLastModified(final HttpServletRequest request)
151 {
152 try
153 {
154 final ServletContext ctxt = getServletContext();
155 final DataSourceBean dsb = DataSourceBean.getApplicationInstance(ctxt);
156 return(dsb.getAllExhibitProperties(-1).hashNotChangedSince);
157 }
158 catch(final IOException e)
159 { return(-1); /* "Not known/available" value. */ }
160 }
161
162 /**Unique Serialisation class ID generated by http://random.hd.org/. */
163 private static final long serialVersionUID = -6552601635962150780L;
164 }