Mercurial > hg > digilib-old
annotate servlet2/src/main/java/digilib/servlet/Scaler.java @ 969:68709fc53a59
set regions overlay div position to absolute, avoiding scrollbar jumps
author | hertzhaft |
---|---|
date | Wed, 25 Jan 2012 22:01:14 +0100 |
parents | b2d97b842612 |
children | 4e368c85cce4 |
rev | line source |
---|---|
903 | 1 package digilib.servlet; |
2 | |
3 import java.io.File; | |
4 import java.io.IOException; | |
5 import java.util.List; | |
6 import java.util.concurrent.ExecutionException; | |
7 import java.util.concurrent.Future; | |
8 | |
9 import javax.servlet.ServletConfig; | |
10 import javax.servlet.ServletContext; | |
11 import javax.servlet.ServletException; | |
12 import javax.servlet.http.HttpServlet; | |
13 import javax.servlet.http.HttpServletRequest; | |
14 import javax.servlet.http.HttpServletResponse; | |
15 | |
16 import org.apache.log4j.Logger; | |
17 | |
18 import digilib.auth.AuthOpException; | |
19 import digilib.auth.AuthOps; | |
20 import digilib.image.DocuImage; | |
21 import digilib.image.ImageJobDescription; | |
22 import digilib.image.ImageOpException; | |
23 import digilib.image.ImageWorker; | |
24 import digilib.io.DocuDirCache; | |
25 import digilib.io.DocuDirectory; | |
26 import digilib.io.ImageInput; | |
27 import digilib.util.DigilibJobCenter; | |
28 | |
29 /** | |
30 * Version of Scaler servlet that uses a thread pool but not Servlet 3.0 async API. | |
31 */ | |
32 public class Scaler extends HttpServlet { | |
33 | |
34 private static final long serialVersionUID = -5439198888139362735L; | |
35 | |
36 /** digilib servlet version (for all components) */ | |
960
b2d97b842612
moved DocuImage implementations with non-standard toolkits (JAI, ImgeJ) into separate Maven modules.
robcast
parents:
903
diff
changeset
|
37 public static final String version = "2.1b1 noasync"; |
903 | 38 |
39 /** servlet error codes */ | |
40 public static enum Error {UNKNOWN, AUTH, FILE, IMAGE}; | |
41 | |
42 /** type of error message */ | |
43 public static enum ErrMsg {IMAGE, TEXT, CODE}; | |
44 | |
45 /** logger for accounting requests */ | |
46 protected static Logger accountlog = Logger.getLogger("account.request"); | |
47 | |
48 /** gengeral logger for this class */ | |
49 protected static Logger logger = Logger.getLogger("digilib.scaler"); | |
50 | |
51 /** logger for authentication related */ | |
52 protected static Logger authlog = Logger.getLogger("digilib.auth"); | |
53 | |
54 /** DocuDirCache instance */ | |
55 protected DocuDirCache dirCache; | |
56 | |
57 /** Image executor */ | |
58 DigilibJobCenter<DocuImage> imageJobCenter; | |
59 | |
60 /** authentication error image file */ | |
61 public static File denyImgFile; | |
62 | |
63 /** image error image file */ | |
64 public static File errorImgFile; | |
65 | |
66 /** not found error image file */ | |
67 public static File notfoundImgFile; | |
68 | |
69 /** send files as is? */ | |
70 protected boolean sendFileAllowed = true; | |
71 | |
72 /** DigilibConfiguration instance */ | |
73 protected DigilibServletConfiguration dlConfig; | |
74 | |
75 /** use authorization database */ | |
76 protected boolean useAuthorization = true; | |
77 | |
78 /** AuthOps instance */ | |
79 protected AuthOps authOp; | |
80 | |
81 /** | |
82 * Initialisation on first run. | |
83 * | |
84 * @throws ServletException | |
85 * | |
86 * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) | |
87 */ | |
88 public void init(ServletConfig config) throws ServletException { | |
89 super.init(config); | |
90 | |
91 System.out | |
92 .println("***** Digital Image Library Image Scaler Servlet (version " | |
93 + version + ") *****"); | |
94 // say hello in the log file | |
95 logger.info("***** Digital Image Library Image Scaler Servlet (version " | |
96 + version + ") *****"); | |
97 | |
98 // get our ServletContext | |
99 ServletContext context = config.getServletContext(); | |
100 // see if there is a Configuration instance | |
101 dlConfig = (DigilibServletConfiguration) context | |
102 .getAttribute("digilib.servlet.configuration"); | |
103 if (dlConfig == null) { | |
104 // no Configuration | |
105 throw new ServletException("No Configuration!"); | |
106 } | |
107 // set our AuthOps | |
108 useAuthorization = dlConfig.getAsBoolean("use-authorization"); | |
109 authOp = (AuthOps) dlConfig.getValue("servlet.auth.op"); | |
110 | |
111 // DocuDirCache instance | |
112 dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache"); | |
113 | |
114 // Executor | |
115 imageJobCenter = (DigilibJobCenter<DocuImage>) dlConfig | |
116 .getValue("servlet.worker.imageexecutor"); | |
117 | |
118 denyImgFile = ServletOps.getFile( | |
119 (File) dlConfig.getValue("denied-image"), context); | |
120 errorImgFile = ServletOps.getFile( | |
121 (File) dlConfig.getValue("error-image"), context); | |
122 notfoundImgFile = ServletOps.getFile( | |
123 (File) dlConfig.getValue("notfound-image"), context); | |
124 sendFileAllowed = dlConfig.getAsBoolean("sendfile-allowed"); | |
125 } | |
126 | |
127 /** Returns modification time relevant to the request for caching. | |
128 * | |
129 * @see javax.servlet.http.HttpServlet#getLastModified(javax.servlet.http.HttpServletRequest) | |
130 */ | |
131 public long getLastModified(HttpServletRequest request) { | |
132 accountlog.debug("GetLastModified from " + request.getRemoteAddr() | |
133 + " for " + request.getQueryString()); | |
134 long mtime = -1; | |
135 // create new request | |
136 DigilibServletRequest dlReq = new DigilibServletRequest(request); | |
137 DocuDirectory dd = dirCache.getDirectory(dlReq.getFilePath()); | |
138 if (dd != null) { | |
139 mtime = dd.getDirMTime() / 1000 * 1000; | |
140 } | |
141 logger.debug(" returns "+mtime); | |
142 return mtime; | |
143 } | |
144 | |
145 /* (non-Javadoc) | |
146 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) | |
147 */ | |
148 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { | |
149 accountlog.info("GET from " + request.getRemoteAddr()); | |
150 this.processRequest(request, response); | |
151 } | |
152 | |
153 | |
154 /* (non-Javadoc) | |
155 * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) | |
156 */ | |
157 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { | |
158 accountlog.info("POST from " + request.getRemoteAddr()); | |
159 this.processRequest(request, response); | |
160 } | |
161 | |
162 | |
163 protected void doHead(HttpServletRequest req, HttpServletResponse resp) | |
164 throws ServletException, IOException { | |
165 logger.debug("HEAD from "+req.getRemoteAddr()); | |
166 super.doHead(req, resp); | |
167 } | |
168 | |
169 protected void doOptions(HttpServletRequest req, HttpServletResponse resp) | |
170 throws ServletException, IOException { | |
171 logger.debug("OPTIONS from "+req.getRemoteAddr()); | |
172 super.doOptions(req, resp); | |
173 } | |
174 | |
175 /** Service this request using the response. | |
176 * @param request | |
177 * @param response | |
178 * @throws ServletException | |
179 */ | |
180 public void processRequest(HttpServletRequest request, | |
181 HttpServletResponse response) throws ServletException { | |
182 | |
183 if (dlConfig == null) { | |
184 logger.error("ERROR: No Configuration!"); | |
185 throw new ServletException("NO VALID digilib CONFIGURATION!"); | |
186 } | |
187 | |
188 accountlog.debug("request: " + request.getQueryString()); | |
189 logger.debug("request: " + request.getQueryString()); | |
190 long startTime = System.currentTimeMillis(); | |
191 | |
192 // parse request | |
193 DigilibServletRequest dlRequest = new DigilibServletRequest(request); | |
194 // extract the job information | |
195 ImageJobDescription jobTicket = ImageJobDescription.getInstance(dlRequest, dlConfig); | |
196 | |
197 // type of error reporting | |
198 ErrMsg errMsgType = ErrMsg.IMAGE; | |
199 if (dlRequest.hasOption("errtxt")) { | |
200 errMsgType = ErrMsg.TEXT; | |
201 } else if (dlRequest.hasOption("errcode")) { | |
202 errMsgType = ErrMsg.CODE; | |
203 } | |
204 | |
205 try { | |
206 /* | |
207 * check if we can fast-track without scaling | |
208 */ | |
209 ImageInput fileToLoad = (ImageInput) jobTicket.getInput(); | |
210 | |
211 // check permissions | |
212 if (useAuthorization) { | |
213 // get a list of required roles (empty if no restrictions) | |
214 List<String> rolesRequired = authOp.rolesForPath( | |
215 jobTicket.getFilePath(), request); | |
216 if (rolesRequired != null) { | |
217 authlog.debug("Role required: " + rolesRequired); | |
218 authlog.debug("User: " + request.getRemoteUser()); | |
219 // is the current request/user authorized? | |
220 if (!authOp.isRoleAuthorized(rolesRequired, request)) { | |
221 // send deny answer and abort | |
222 throw new AuthOpException(); | |
223 } | |
224 } | |
225 } | |
226 | |
227 // if requested, send image as a file | |
228 if (sendFileAllowed && jobTicket.getSendAsFile()) { | |
229 String mt = null; | |
230 if (jobTicket.hasOption("rawfile")) { | |
231 mt = "application/octet-stream"; | |
232 } | |
233 logger.debug("Sending RAW File as is."); | |
234 ServletOps.sendFile(fileToLoad.getFile(), mt, null, response, logger); | |
235 logger.info("Done in " + (System.currentTimeMillis() - startTime) + "ms"); | |
236 return; | |
237 } | |
238 | |
239 // if possible, send the image without actually having to transform it | |
240 if (! jobTicket.isTransformRequired()) { | |
241 logger.debug("Sending File as is."); | |
242 ServletOps.sendFile(fileToLoad.getFile(), null, null, response, logger); | |
243 logger.info("Done in " + (System.currentTimeMillis() - startTime) + "ms"); | |
244 return; | |
245 } | |
246 | |
247 // check load of workers | |
248 if (imageJobCenter.isBusy()) { | |
249 logger.error("Servlet overloaded!"); | |
250 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); | |
251 return; | |
252 } | |
253 // create job | |
254 ImageWorker job = new ImageWorker(dlConfig, jobTicket); | |
255 // submit job | |
256 Future<DocuImage> jobResult = imageJobCenter.submit(job); | |
257 // wait for result | |
258 DocuImage img = jobResult.get(); | |
259 // forced destination image type | |
260 String mt = null; | |
261 if (jobTicket.hasOption("jpg")) { | |
262 mt = "image/jpeg"; | |
263 } else if (jobTicket.hasOption("png")) { | |
264 mt = "image/png"; | |
265 } | |
266 // send image | |
267 ServletOps.sendImage(img, mt, response, logger); | |
268 logger.debug("Job Processing Time: " | |
269 + (System.currentTimeMillis() - startTime) + "ms"); | |
270 | |
271 } catch (ImageOpException e) { | |
272 logger.error(e.getClass() + ": " + e.getMessage()); | |
273 digilibError(errMsgType, Error.IMAGE, null, response); | |
274 } catch (IOException e) { | |
275 logger.error(e.getClass() + ": " + e.getMessage()); | |
276 digilibError(errMsgType, Error.FILE, null, response); | |
277 } catch (AuthOpException e) { | |
278 logger.error(e.getClass() + ": " + e.getMessage()); | |
279 digilibError(errMsgType, Error.AUTH, null, response); | |
280 } catch (InterruptedException e) { | |
281 logger.error(e.getClass() + ": " + e.getMessage()); | |
282 } catch (ExecutionException e) { | |
283 logger.error(e.getClass() + ": " + e.getMessage()); | |
284 String causeMsg = e.getCause().getMessage(); | |
285 logger.error("caused by: " + causeMsg); | |
286 digilibError(errMsgType, Error.IMAGE, causeMsg, response); | |
287 } | |
288 | |
289 } | |
290 | |
291 /** | |
292 * Sends an error to the client as text or image. | |
293 * | |
294 * @param type | |
295 * @param error | |
296 * @param msg | |
297 * @param response | |
298 */ | |
299 public static void digilibError(ErrMsg type, Error error, String msg, | |
300 HttpServletResponse response) { | |
301 try { | |
302 File img = null; | |
303 int status = 0; | |
304 if (error == Error.AUTH) { | |
305 if (msg == null) { | |
306 msg = "ERROR: Unauthorized access!"; | |
307 } | |
308 img = denyImgFile; | |
309 status = HttpServletResponse.SC_FORBIDDEN; | |
310 } else if (error == Error.FILE) { | |
311 if (msg == null) { | |
312 msg = "ERROR: Image file not found!"; | |
313 } | |
314 img = notfoundImgFile; | |
315 status = HttpServletResponse.SC_NOT_FOUND; | |
316 } else { | |
317 if (msg == null) { | |
318 msg = "ERROR: Other image error!"; | |
319 } | |
320 img = errorImgFile; | |
321 status = HttpServletResponse.SC_BAD_REQUEST; | |
322 } | |
323 if (response.isCommitted()) { | |
324 // response already committed | |
325 logger.error("Unable to send error: " + msg); | |
326 return; | |
327 } | |
328 if (type == ErrMsg.TEXT) { | |
329 ServletOps.htmlMessage(msg, response); | |
330 } else if (type == ErrMsg.CODE) { | |
331 response.sendError(status, msg); | |
332 } else if (img != null) { | |
333 // default: image | |
334 ServletOps.sendFile(img, null, null, response, logger); | |
335 } | |
336 } catch (Exception e) { | |
337 logger.error("Error sending error!", e); | |
338 } | |
339 | |
340 } | |
341 | |
342 public static String getVersion() { | |
343 return version; | |
344 } | |
345 | |
346 } |