comparison pdf/src/main/java/digilib/servlet/PDFCache.java @ 903:7779b37d1d05

refactored into maven modules per servlet type. can build servlet-api 2.3 and 3.0 via profile now!
author robcast
date Tue, 26 Apr 2011 20:24:31 +0200
parents
children
comparison
equal deleted inserted replaced
902:89ba3ffcf552 903:7779b37d1d05
1 package digilib.servlet;
2
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.io.IOException;
6 import java.util.concurrent.Future;
7
8 import javax.servlet.RequestDispatcher;
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.image.DocuImage;
19 import digilib.pdf.PDFFileWorker;
20 import digilib.util.DigilibJobCenter;
21
22 /**
23 * A class for handling user requests for pdf documents made from digilib images.
24 *
25 * If a document does not already exist, it will be enqueued for generation; if it does exist, it is sent
26 * to the user.
27 *
28 * @author cmielack
29 *
30 */
31
32 @SuppressWarnings("serial")
33 public class PDFCache extends HttpServlet {
34
35 public static String version = "0.3a";
36
37 /** logger for accounting requests */
38 protected static Logger accountlog = Logger.getLogger("account.pdf.request");
39
40 /** gengeral logger for this class */
41 protected static Logger logger = Logger.getLogger("digilib.pdfcache");
42
43 /** logger for authentication related */
44 protected static Logger authlog = Logger.getLogger("digilib.pdf.auth");
45
46 private DigilibConfiguration dlConfig = null;
47
48 public static String instanceKey = "digilib.servlet.PDFCache";
49
50 private DigilibJobCenter<File> pdfJobCenter = null;
51
52 private DigilibJobCenter<DocuImage> pdfImageJobCenter = null;
53
54 private File cache_directory = new File("cache");
55
56 private File temp_directory = new File("pdf_temp");
57
58 private static String JSP_WIP = "/pdf/wip.jsp";
59
60 private static String JSP_ERROR = "/pdf/error.jsp";
61
62 /** document status.
63 * DONE: document exists in cache
64 * WIP: document is "work in progress"
65 * NONEXISTENT: document does not exist in cache and is not in progress
66 * ERROR: an error occurred while processing the request
67 */
68 public static enum PDFStatus {DONE, WIP, NONEXISTENT, ERROR};
69
70
71 public void init(ServletConfig config) throws ServletException {
72 super.init(config);
73
74 System.out.println("***** Digital Image Library Image PDF-Cache Servlet (version "
75 + version + ") *****");
76 // say hello in the log file
77 logger.info("***** Digital Image Library Image PDF-Cache Servlet (version "
78 + version + ") *****");
79
80 ServletContext context = getServletContext();
81 dlConfig = (DigilibConfiguration) context.getAttribute("digilib.servlet.configuration");
82 if (dlConfig == null) {
83 // no Configuration
84 throw new ServletException("No Configuration!");
85 }
86
87 String temp_fn = dlConfig.getAsString("pdf-temp-dir");
88 temp_directory = new File(temp_fn);
89 if (!temp_directory.exists()) {
90 // try to create
91 temp_directory.mkdirs();
92 } else {
93 // rid the temporary directory of possible incomplete document files
94 emptyDirectory(temp_directory);
95 }
96 if (!temp_directory.isDirectory()) {
97 throw new ServletException("Configuration error: problem with pdf-temp-dir="+temp_fn);
98 }
99
100 String cache_fn = dlConfig.getAsString("pdf-cache-dir");
101 cache_directory = new File(cache_fn);
102 if (!cache_directory.exists()) {
103 // try to create
104 cache_directory.mkdirs();
105 }
106 if (!cache_directory.isDirectory()) {
107 throw new ServletException("Configuration error: problem with pdf-cache-dir="+cache_fn);
108 }
109
110 pdfJobCenter = (DigilibJobCenter<File>) dlConfig.getValue("servlet.worker.pdfexecutor");
111 pdfImageJobCenter = (DigilibJobCenter<DocuImage>) dlConfig.getValue("servlet.worker.pdfimageexecutor");
112
113 // register this instance globally
114 context.setAttribute(instanceKey, this);
115
116 }
117
118 /* (non-Javadoc)
119 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
120 */
121 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
122 accountlog.info("GET from " + request.getRemoteAddr());
123 this.processRequest(request, response);
124 }
125
126
127 /* (non-Javadoc)
128 * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
129 */
130 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {
131 accountlog.info("POST from " + request.getRemoteAddr());
132 this.processRequest(request, response);
133 }
134
135 /**
136 * clean up any broken and unfinished files from the temporary directory.
137 */
138 public void emptyDirectory(File dir){
139 File[] temp_files = dir.listFiles();
140 for (File f: temp_files){
141 f.delete();
142 }
143 }
144
145
146 public void processRequest(HttpServletRequest request,
147 HttpServletResponse response) throws ServletException {
148
149 if (dlConfig == null) {
150 logger.error("ERROR: No Configuration!");
151 throw new ServletException("NO VALID digilib CONFIGURATION!");
152 }
153
154 String docid = "";
155 try {
156 // evaluate request ( make a PDFJobDeclaration , get the DocumentId)
157 PDFRequest pdfji = new PDFRequest(request, dlConfig);
158
159 docid = pdfji.getDocumentId();
160
161 // if some invalid data has been entered ...
162 if(!pdfji.checkValidity()) {
163 notifyUser(PDFStatus.ERROR, docid, request, response);
164 return;
165 }
166
167 PDFStatus status = getStatus(docid);
168
169 if (status == PDFStatus.NONEXISTENT) {
170 // not there -- start creation
171 try {
172 createNewPdfDocument(pdfji, docid);
173 notifyUser(status, docid, request, response);
174 return;
175 } catch (FileNotFoundException e) {
176 // error in pdf creation
177 logger.error(e.getMessage());
178 notifyUser(PDFStatus.ERROR, docid, request, response);
179 return;
180 }
181 } else if (status == PDFStatus.DONE) {
182 // pdf created -- send it
183 try {
184 ServletOps.sendFile(getCacheFile(docid), "application/pdf", getDownloadFilename(pdfji), response, logger);
185 return;
186 } catch (Exception e) {
187 // sending didn't work
188 logger.error(e.getMessage());
189 return;
190 }
191 } else {
192 // should be work in progress
193 notifyUser(status, docid, request, response);
194 return;
195 }
196 } catch (Exception e) {
197 // error in pdf creation
198 logger.error(e.getMessage());
199 notifyUser(PDFStatus.ERROR, docid, request, response);
200 return;
201 }
202 }
203
204 /**
205 * depending on the documents status, redirect the user to the appropriate
206 * waiting or download page.
207 *
208 * @param status
209 * @param documentid
210 * @param request
211 * @param response
212 */
213 public void notifyUser(PDFStatus status, String documentid,
214 HttpServletRequest request, HttpServletResponse response) {
215
216 String jsp = null;
217
218 if (status == PDFStatus.NONEXISTENT) {
219 // tell the user that the document has to be created before he/she
220 // can download it
221 logger.debug("PDFCache: " + documentid + " has STATUS_NONEXISTENT.");
222 jsp = JSP_WIP;
223 } else if (status == PDFStatus.WIP) {
224 logger.debug("PDFCache: " + documentid + " has STATUS_WIP.");
225 jsp = JSP_WIP;
226
227 // TODO: estimate remaining work time
228 // TODO: tell the user he/she has to wait
229 } else if (status == PDFStatus.DONE) {
230 logger.debug("PDFCache: " + documentid + " has STATUS_DONE.");
231 } else {
232 logger.debug("PDFCache: " + documentid + " has STATUS_ERROR.");
233 jsp = JSP_ERROR;
234 }
235
236 try {
237 // forward to the relevant jsp
238 ServletContext context = getServletContext();
239 RequestDispatcher dispatch = context.getRequestDispatcher(jsp);
240 dispatch.forward(request, response);
241 } catch (ServletException e) {
242 logger.debug(e.getMessage());
243 e.printStackTrace();
244 } catch (IOException e) {
245 logger.debug(e.getMessage());
246 e.printStackTrace();
247 }
248
249 }
250
251
252 /** check the status of the document corresponding to the documentid */
253 public PDFStatus getStatus(String documentid){
254 // looks into the cache and temp directory in order to find out the status of the document
255 File cached = getCacheFile(documentid);
256 File wip = getTempFile(documentid);
257 if(cached.exists()){
258 return PDFStatus.DONE;
259 } else if (wip.exists()){
260 return PDFStatus.WIP;
261 } else {
262 return PDFStatus.NONEXISTENT;
263 }
264 }
265
266 /**
267 * create new thread for pdf generation.
268 *
269 * @param pdfji
270 * @param filename
271 * @return
272 * @throws FileNotFoundException
273 */
274 public Future<File> createNewPdfDocument(PDFRequest pdfji, String filename) throws FileNotFoundException{
275 // start new worker
276 File tempf = this.getTempFile(filename);
277 File finalf = this.getCacheFile(filename);
278 PDFFileWorker job = new PDFFileWorker(dlConfig, tempf, finalf, pdfji, pdfImageJobCenter);
279 // start job
280 Future<File> jobTicket = pdfJobCenter.submit(job);
281 return jobTicket;
282 }
283
284
285 /**
286 * generate the filename the user is going to receive the pdf as
287 *
288 * @param pdfji
289 * @return
290 */
291 public String getDownloadFilename(PDFRequest pdfji){
292 // filename example: digilib_example_pgs1-3.pdf
293 String filename;
294 filename = "digilib_";
295 filename += pdfji.getAsString("fn");
296 filename += "_pgs" + pdfji.getAsString("pgs");
297 filename += ".pdf";
298
299 return filename;
300 }
301
302 public File getCacheDirectory(){
303 return cache_directory;
304 }
305
306 public File getTempDirectory(){
307 return temp_directory;
308 }
309
310 /**
311 * returns a File object based on filename in the temp directory.
312 * @param filename
313 * @return
314 */
315 public File getTempFile(String filename) {
316 return new File(temp_directory, filename);
317 }
318
319 /**
320 * returns a File object based on filename in the cache directory.
321 * @param filename
322 * @return
323 */
324 public File getCacheFile(String filename) {
325 return new File(cache_directory, filename);
326 }
327 }