comparison servlet/src/digilib/servlet/Scaler.java @ 544:5ff500d6812a digilibPDF

more steps towards more standard java.util.concurrent design
author robcast
date Thu, 14 Oct 2010 20:47:31 +0200
parents 919e008ab1fb
children e1094c5ec032
comparison
equal deleted inserted replaced
543:919e008ab1fb 544:5ff500d6812a
1 package digilib.servlet; 1 package digilib.servlet;
2 2
3 import java.io.File; 3 import java.io.File;
4 import java.io.IOException; 4 import java.io.IOException;
5 import java.io.OutputStream;
6 import java.util.List; 5 import java.util.List;
7 import java.util.concurrent.ExecutionException; 6 import java.util.concurrent.ExecutionException;
8 import java.util.concurrent.ExecutorService;
9 import java.util.concurrent.Future; 7 import java.util.concurrent.Future;
10 8
11 import javax.servlet.ServletConfig; 9 import javax.servlet.ServletConfig;
12 import javax.servlet.ServletContext; 10 import javax.servlet.ServletContext;
13 import javax.servlet.ServletException; 11 import javax.servlet.ServletException;
19 import digilib.image.DocuImage; 17 import digilib.image.DocuImage;
20 import digilib.image.ImageOpException; 18 import digilib.image.ImageOpException;
21 import digilib.io.DocuDirCache; 19 import digilib.io.DocuDirCache;
22 import digilib.io.DocuDirectory; 20 import digilib.io.DocuDirectory;
23 import digilib.io.DocuDirent; 21 import digilib.io.DocuDirent;
24 import digilib.io.FileOpException;
25 import digilib.io.FileOps; 22 import digilib.io.FileOps;
26 import digilib.io.ImageFile; 23 import digilib.io.ImageFile;
27 24
28
29 // TODO digilibError is not used anymore and may need to get reintegrated 25 // TODO digilibError is not used anymore and may need to get reintegrated
30 26
31 public class Scaler extends RequestHandler { 27 public class Scaler extends RequestHandler {
32 28
33 /** digilib servlet version (for all components) */ 29 /** digilib servlet version (for all components) */
34 public static final String dlVersion = "1.8.1a"; 30 public static final String dlVersion = "1.8.1a";
35 31
36 /** general error code */ 32 /** general error code */
37 public static final int ERROR_UNKNOWN = 0; 33 public static final int ERROR_UNKNOWN = 0;
38 34
39 /** error code for authentication error */ 35 /** error code for authentication error */
40 public static final int ERROR_AUTH = 1; 36 public static final int ERROR_AUTH = 1;
41 37
42 /** error code for file operation error */ 38 /** error code for file operation error */
43 public static final int ERROR_FILE = 2; 39 public static final int ERROR_FILE = 2;
44 40
45 /** error code for image operation error */ 41 /** error code for image operation error */
46 public static final int ERROR_IMAGE = 3; 42 public static final int ERROR_IMAGE = 3;
47 43
48 /** DocuDirCache instance */ 44 /** DocuDirCache instance */
49 DocuDirCache dirCache; 45 DocuDirCache dirCache;
50 46
51 /** Image executor */ 47 /** Image executor */
52 ExecutorService imageJobCenter; 48 DigilibJobCenter imageJobCenter;
53 49
54 /** authentication error image file */ 50 /** authentication error image file */
55 File denyImgFile; 51 File denyImgFile;
56 52
57 /** image error image file */ 53 /** image error image file */
58 File errorImgFile; 54 File errorImgFile;
59 55
60 /** not found error image file */ 56 /** not found error image file */
61 File notfoundImgFile; 57 File notfoundImgFile;
62 58
63 /** subsampling before scaling */ 59 /** send files as is? */
64 float minSubsample = 2f; 60 boolean sendFileAllowed = true;
65 61
66 /** send files as is? */ 62 /** DigilibConfiguration instance */
67 boolean sendFileAllowed = true; 63 DigilibConfiguration dlConfig;
68 64
69 /** default scaling quality */ 65 /** use authorization database */
70 int defaultQuality = 1; 66 boolean useAuthorization = true;
71 67
72 /** DigilibConfiguration instance */ 68 /** AuthOps instance */
73 DigilibConfiguration dlConfig; 69 AuthOps authOp;
74 70
75 /** use authorization database */ 71 // EXPRIMENTAL
76 boolean useAuthorization = true; 72 /** try to enlarge cropping area for "oblique" angles */
77 73 boolean wholeRotArea = false;
78 /** AuthOps instance */ 74
79 AuthOps authOp; 75 protected long getLastModified(HttpServletRequest request) {
80 76 accountlog.debug("GetLastModified from " + request.getRemoteAddr()
81 // EXPRIMENTAL 77 + " for " + request.getQueryString());
82 /** try to enlarge cropping area for "oblique" angles */ 78 long mtime = -1;
83 boolean wholeRotArea = false; 79 // create new request with defaults
84 80 DigilibRequest dlReq = new DigilibRequest();
85 81 // set with request parameters
86 protected long getLastModified(HttpServletRequest request) { 82 dlReq.setWithRequest(request);
87 accountlog.debug("GetLastModified from " + request.getRemoteAddr() 83 // find the requested file
88 + " for " + request.getQueryString()); 84 DocuDirent f = findFile(dlReq);
89 long mtime = -1; 85 if (f != null) {
90 // create new request with defaults 86 DocuDirectory dd = (DocuDirectory) f.getParent();
91 DigilibRequest dlReq = new DigilibRequest(); 87 mtime = dd.getDirMTime() / 1000 * 1000;
92 // set with request parameters 88 }
93 dlReq.setWithRequest(request); 89 return mtime;
94 // find the requested file 90 }
95 DocuDirent f = findFile(dlReq); 91
96 if (f != null) { 92 /**
97 DocuDirectory dd = (DocuDirectory) f.getParent(); 93 * Returns the DocuDirent corresponding to the DigilibRequest.
98 mtime = dd.getDirMTime() / 1000 * 1000; 94 *
99 } 95 * @param dlRequest
100 return mtime; 96 * @return
101 } 97 */
102 98 public DocuDirent findFile(DigilibRequest dlRequest) {
103 /** 99 // find the file(set)
104 * Returns the DocuDirent corresponding to the DigilibRequest. 100 DocuDirent f = dirCache.getFile(dlRequest.getFilePath(),
105 * 101 dlRequest.getAsInt("pn"), FileOps.CLASS_IMAGE);
106 * @param dlRequest 102 return f;
107 * @return 103 }
108 */ 104
109 public DocuDirent findFile(DigilibRequest dlRequest) { 105 /**
110 // find the file(set) 106 * Initialisation on first run.
111 DocuDirent f = dirCache.getFile(dlRequest.getFilePath(), dlRequest 107 *
112 .getAsInt("pn"), FileOps.CLASS_IMAGE); 108 * @throws ServletException
113 return f; 109 *
114 } 110 * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
115 111 */
116 112 public void init(ServletConfig config) throws ServletException {
117 113 super.init(config);
118 /** 114
119 * Initialisation on first run. 115 System.out
120 * @throws ServletException 116 .println("***** Digital Image Library Image Scaler Servlet (version "
121 * 117 + dlVersion + ") *****");
122 * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) 118 // say hello in the log file
123 */ 119 logger.info("***** Digital Image Library Image Scaler Servlet (version "
124 public void init(ServletConfig config) throws ServletException { 120 + dlVersion + ") *****");
125 super.init(config); 121
126 122 // get our ServletContext
127 System.out 123 ServletContext context = config.getServletContext();
128 .println("***** Digital Image Library Image Scaler Servlet (version " 124 // see if there is a Configuration instance
129 + dlVersion + ") *****"); 125 dlConfig = (DigilibConfiguration) context
130 // say hello in the log file 126 .getAttribute("digilib.servlet.configuration");
131 logger 127 if (dlConfig == null) {
132 .info("***** Digital Image Library Image Scaler Servlet (version " 128 // no Configuration
133 + dlVersion + ") *****"); 129 throw new ServletException("No Configuration!");
134 130 }
135 // get our ServletContext 131 // set our AuthOps
136 ServletContext context = config.getServletContext(); 132 useAuthorization = dlConfig.getAsBoolean("use-authorization");
137 // see if there is a Configuration instance 133 authOp = (AuthOps) dlConfig.getValue("servlet.auth.op");
138 dlConfig = (DigilibConfiguration) context 134
139 .getAttribute("digilib.servlet.configuration"); 135 // DocuDirCache instance
140 if (dlConfig == null) { 136 dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
141 // no Configuration 137
142 throw new ServletException("No Configuration!"); 138 // Executor
143 } 139 imageJobCenter = (DigilibJobCenter) dlConfig
144 // set our AuthOps 140 .getValue("servlet.worker.imageexecutor");
145 useAuthorization = dlConfig.getAsBoolean("use-authorization"); 141
146 authOp = (AuthOps) dlConfig.getValue("servlet.auth.op"); 142 denyImgFile = ServletOps.getFile(
147 143 (File) dlConfig.getValue("denied-image"), config);
148 // DocuDirCache instance 144 errorImgFile = ServletOps.getFile(
149 dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache"); 145 (File) dlConfig.getValue("error-image"), config);
150 146 notfoundImgFile = ServletOps.getFile(
151 // Executor 147 (File) dlConfig.getValue("notfound-image"), config);
152 imageJobCenter = (ExecutorService) dlConfig.get("servlet.worker.imageexecutor"); 148 sendFileAllowed = dlConfig.getAsBoolean("sendfile-allowed");
153 149 }
154 denyImgFile = ServletOps.getFile((File) dlConfig.getValue("denied-image"), config); 150
155 errorImgFile = ServletOps.getFile((File) dlConfig.getValue("error-image"), config); 151 @Override
156 notfoundImgFile = ServletOps.getFile((File) dlConfig.getValue("notfound-image"), config); 152 public void processRequest(HttpServletRequest request,
157 sendFileAllowed = dlConfig.getAsBoolean("sendfile-allowed"); 153 HttpServletResponse response) throws ServletException,
158 minSubsample = dlConfig.getAsFloat("subsample-minimum"); 154 ImageOpException {
159 defaultQuality = dlConfig.getAsInt("default-quality"); 155
160 } 156 if (dlConfig == null) {
161 157 throw new ServletException("ERROR: No Configuration!");
162 158 }
163 159
164 160 accountlog.debug("request: " + request.getQueryString());
165 @Override 161 logger.debug("request: " + request.getQueryString());
166 public void processRequest(HttpServletRequest request, 162 long startTime = System.currentTimeMillis();
167 HttpServletResponse response) throws ServletException, ImageOpException { 163
168 164 // define the job information
169 165 ImageJobInformation jobdeclaration = new ImageJobInformation(dlConfig);
170 if (dlConfig == null) { 166 jobdeclaration.setWithRequest(request);
171 throw new ServletException("ERROR: No Configuration!"); 167
172 } 168 // DigilibWorker1 job=null;
173 169 ImageWorker job = null;
174 accountlog.debug("request: " + request.getQueryString()); 170 try {
175 logger.debug("request: " + request.getQueryString()); 171
176 172 ImageFile fileToLoad = jobdeclaration.get_fileToLoad();
177 173
178 // define the job information 174 /* check permissions */
179 ImageJobInformation jobdeclaration = new ImageJobInformation(dlConfig); 175 if (useAuthorization) {
180 jobdeclaration.setWithRequest(request); 176 // get a list of required roles (empty if no restrictions)
181 177 List<String> rolesRequired = authOp.rolesForPath(
182 ImageFile fileToLoad = null; 178 jobdeclaration.getFilePath(), request);
183 try { 179 if (rolesRequired != null) {
184 fileToLoad = jobdeclaration.get_fileToLoad(); 180 authlog.debug("Role required: " + rolesRequired);
185 } catch (IOException e2) { 181 authlog.debug("User: " + request.getRemoteUser());
186 // TODO Auto-generated catch block 182 // is the current request/user authorized?
187 e2.printStackTrace(); 183 if (!authOp.isRoleAuthorized(rolesRequired, request)) {
188 return; 184 // send deny answer and abort
189 } 185 throw new AuthOpException();
190 186 }
191 187 }
192 // if requested, send image as a file 188 }
193 if(sendFileAllowed && jobdeclaration.checkSendAsFile()){ 189
194 String mt = null; 190 // if requested, send image as a file
195 if (jobdeclaration.hasOption("mo", "rawfile")) { 191 if (sendFileAllowed && jobdeclaration.checkSendAsFile()) {
196 mt = "application/octet-stream"; 192 String mt = null;
197 } 193 if (jobdeclaration.hasOption("mo", "rawfile")) {
198 logger.debug("Sending RAW File as is."); 194 mt = "application/octet-stream";
199 try { 195 }
200 ServletOps.sendFile(fileToLoad.getFile(), mt, response); 196 logger.debug("Sending RAW File as is.");
201 } catch (FileOpException e) { 197 logger.info("Done in " + (System.currentTimeMillis() - startTime) + "ms");
202 e.printStackTrace(); 198 ServletOps.sendFile(fileToLoad.getFile(), mt, response);
203 } 199 return;
204 200 }
205 return; 201
206 } 202 // if possible, send the image without actually having to transform
207 203 // it
208 204 if (jobdeclaration.noTransformRequired()) {
209 205 logger.debug("Sending File as is.");
210 // if possible, send the image without actually having to transform it 206 ServletOps.sendFile(fileToLoad.getFile(), null, response);
211 if(jobdeclaration.noTransformRequired()){ 207 logger.info("Done in " + (System.currentTimeMillis() - startTime) + "ms");
212 logger.debug("Sending File as is."); 208 return;
213 209 }
214 try { 210
215 ServletOps.sendFile(fileToLoad.getFile(), null, response); 211 // check load of workers
216 } catch (FileOpException e) { 212 if (imageJobCenter.isBusy()) {
217 e.printStackTrace(); 213 logger.error("Servlet overloaded!");
218 } 214 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
219 215 return;
220 //logger.info("Done in " 216 }
221 // + (System.currentTimeMillis() - startTime) + "ms"); 217 // create job
222 return; 218 job = new ImageWorker(dlConfig, jobdeclaration);
223 } 219 // submit job
224
225
226
227
228 if (! DigilibWorker1.canRun()) {
229 logger.error("Servlet overloaded!");
230 try {
231 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
232 } catch (IOException e) {
233 e.printStackTrace();
234 }
235 return;
236 }
237
238
239 //DigilibWorker1 job=null;
240 ImageWorker job = null;
241 try {
242
243 long startTime = System.currentTimeMillis();
244
245 OutputStream outputstream = null;
246 outputstream = response.getOutputStream();
247
248 /* check permissions */
249 if (useAuthorization) {
250 // get a list of required roles (empty if no restrictions)
251 List<String> rolesRequired;
252 try {
253 rolesRequired = authOp.rolesForPath(jobdeclaration.getFilePath(), request);
254 if (rolesRequired != null) {
255 authlog.debug("Role required: " + rolesRequired);
256 authlog.debug("User: " + request.getRemoteUser());
257 // is the current request/user authorized?
258 if (!authOp.isRoleAuthorized(rolesRequired, request)) {
259 // send deny answer and abort
260 throw new AuthOpException();
261 }
262 }
263
264 } catch (AuthOpException e) {
265 // TODO Auto-generated catch block
266 e.printStackTrace();
267 }
268 }
269
270
271 //job = new DigilibImageWorker1(dlConfig, outputstream , jobdeclaration);
272 //job.run();
273
274 // create job
275 job = new ImageWorker(dlConfig, jobdeclaration);
276 // submit job
277 Future<DocuImage> jobResult = imageJobCenter.submit(job); 220 Future<DocuImage> jobResult = imageJobCenter.submit(job);
278 // wait for result 221 // wait for result
279 DocuImage img = jobResult.get(); 222 DocuImage img = jobResult.get();
280 // send image 223 // send image
281 ServletOps.writeImage(img, null, outputstream); 224 ServletOps.sendImage(img, null, response);
282 225 logger.debug("Job Processing Time: "
283 logger.debug("Job Processing Time: "+ (System.currentTimeMillis()-startTime) + "ms"); 226 + (System.currentTimeMillis() - startTime) + "ms");
284 227
285 } catch (IOException e) { 228 } catch (IOException e) {
286 e.printStackTrace(); 229 logger.error(e.getClass() + ": " + e.getMessage());
287 logger.error(e.getClass()+": "+ e.getMessage()); 230 // response.sendError(1);
288 //response.sendError(1); 231 } catch (AuthOpException e) {
289 } catch (InterruptedException e) { 232 logger.error(e.getClass() + ": " + e.getMessage());
290 // TODO Auto-generated catch block 233 // response.sendError(1);
291 e.printStackTrace(); 234 } catch (InterruptedException e) {
292 logger.error(e.getClass()+": "+ e.getMessage()); 235 logger.error(e.getClass() + ": " + e.getMessage());
293 } catch (ExecutionException e) { 236 } catch (ExecutionException e) {
294 // TODO Auto-generated catch block 237 logger.error(e.getClass() + ": " + e.getMessage());
295 e.printStackTrace(); 238 logger.error("caused by: " + e.getCause().getMessage());
296 logger.error(e.getClass()+": "+ e.getMessage()); 239 }
297 logger.error("caused by: "+ e.getCause().getMessage()); 240
298 } 241 }
299 242
300 } 243 /**
301 244 * Sends an error to the client as text or image.
302 245 *
303 /** 246 * @param asHTML
304 * Sends an error to the client as text or image. 247 * @param type
305 * 248 * @param msg
306 * @param asHTML 249 * @param response
307 * @param type 250 */
308 * @param msg 251 public void digilibError(boolean asHTML, int type, String msg,
309 * @param response 252 HttpServletResponse response) {
310 */ 253 try {
311 public void digilibError(boolean asHTML, int type, String msg, 254 File img = null;
312 HttpServletResponse response) { 255 if (type == ERROR_AUTH) {
313 try { 256 if (msg == null) {
314 File img = null; 257 msg = "ERROR: Unauthorized access!";
315 if (type == ERROR_AUTH) { 258 }
316 if (msg == null) { 259 img = denyImgFile;
317 msg = "ERROR: Unauthorized access!"; 260 } else if (type == ERROR_FILE) {
318 } 261 if (msg == null) {
319 img = denyImgFile; 262 msg = "ERROR: Image file not found!";
320 } else if (type == ERROR_FILE) { 263 }
321 if (msg == null) { 264 img = notfoundImgFile;
322 msg = "ERROR: Image file not found!"; 265 } else {
323 } 266 if (msg == null) {
324 img = notfoundImgFile; 267 msg = "ERROR: Other image error!";
325 } else { 268 }
326 if (msg == null) { 269 img = this.errorImgFile;
327 msg = "ERROR: Other image error!"; 270 }
328 } 271 if (asHTML && (img != null)) {
329 img = this.errorImgFile; 272 ServletOps.htmlMessage(msg, response);
330 } 273 } else {
331 if (asHTML && (img != null)) { 274 ServletOps.sendFile(img, null, response);
332 ServletOps.htmlMessage(msg, response); 275 }
333 } else { 276 } catch (IOException e) {
334 ServletOps.sendFile(img, null, response); 277 logger.error("Error sending error!", e);
335 } 278 }
336 } catch (IOException e) { 279
337 logger.error("Error sending error!", e); 280 }
338 } 281
339 282 public static String getVersion() {
340 } 283 return dlVersion;
341 284 }
342 public static String getVersion(){
343 return dlVersion;
344 }
345
346 285
347 } 286 }