1 package pl.psnc.dl.ege.webapp.servlet;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.FileNotFoundException;
7 import java.io.FileOutputStream;
8 import java.io.IOException;
9 import java.io.InputStream;
10 import java.io.OutputStream;
11 import java.io.PrintWriter;
12 import java.util.List;
13 import java.util.Properties;
14 import java.util.Set;
15 import java.util.UUID;
16 import java.util.zip.ZipException;
17 import java.util.zip.ZipFile;
18
19 import javax.servlet.ServletException;
20 import javax.servlet.http.HttpServlet;
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
23
24 import org.apache.commons.fileupload.FileItemIterator;
25 import org.apache.commons.fileupload.FileItemStream;
26 import org.apache.commons.fileupload.FileUploadException;
27 import org.apache.commons.fileupload.servlet.ServletFileUpload;
28 import org.apache.log4j.Logger;
29
30 import pl.psnc.dl.ege.EGE;
31 import pl.psnc.dl.ege.EGEImpl;
32 import pl.psnc.dl.ege.configuration.EGEConfigurationManager;
33 import pl.psnc.dl.ege.configuration.EGEConstants;
34 import pl.psnc.dl.ege.exception.ConverterException;
35 import pl.psnc.dl.ege.exception.EGEException;
36 import pl.psnc.dl.ege.exception.ValidatorException;
37 import pl.psnc.dl.ege.types.ConversionAction;
38 import pl.psnc.dl.ege.types.ConversionsPath;
39 import pl.psnc.dl.ege.types.DataType;
40 import pl.psnc.dl.ege.types.ValidationResult;
41 import pl.psnc.dl.ege.utils.DataBuffer;
42 import pl.psnc.dl.ege.utils.EGEIOUtils;
43 import pl.psnc.dl.ege.utils.IOResolver;
44 import pl.psnc.dl.ege.webapp.config.LabelProvider;
45 import pl.psnc.dl.ege.webapp.config.MimeExtensionProvider;
46 import pl.psnc.dl.ege.webapp.config.PreConfig;
47 import pl.psnc.dl.ege.webapp.request.ConversionRequestResolver;
48 import pl.psnc.dl.ege.webapp.request.ConversionsPropertiesHandler;
49 import pl.psnc.dl.ege.webapp.request.Method;
50 import pl.psnc.dl.ege.webapp.request.OperationId;
51 import pl.psnc.dl.ege.webapp.request.RequestResolver;
52 import pl.psnc.dl.ege.webapp.request.RequestResolvingException;
53
54
55
56
57
58
59
60
61
62
63
64 public class ConversionServlet extends HttpServlet {
65
66 private static final String EZP_EXT = ".ezp";
67
68 private static final String APPLICATION_MSWORD = "application/msword";
69
70 private static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
71
72 private static final Logger LOGGER = Logger
73 .getLogger(ConversionServlet.class);
74
75 private static final long serialVersionUID = 1L;
76
77 public static final String SLASH = "/";
78
79 public static final String COMMA = ",";
80
81 public static final String SEMICOLON = ";";
82
83 public static final String R_WRONG_METHOD = "Wrong method: GET, expected: POST.";
84
85 public static final String CONVERSIONS_SLICE_BASE = "Conversions/";
86
87 public static final String ZIP_EXT = ".zip";
88
89 public static final String DOCX_EXT = ".docx";
90
91
92
93
94 public ConversionServlet() {
95 super();
96 }
97
98
99
100
101
102 protected void doGet(HttpServletRequest request,
103 HttpServletResponse response) throws ServletException, IOException {
104 try {
105 RequestResolver rr = new ConversionRequestResolver(request,
106 Method.GET);
107 if (rr.getOperationId().equals(OperationId.PRINT_CONVERSIONS_PATHS)) {
108 DataType idt = (DataType) rr.getData();
109 EGE ege = new EGEImpl();
110 List<ConversionsPath> paths = ege.findConversionPaths(idt);
111 printConversionsPaths(response, rr, paths);
112 } else if (rr.getOperationId()
113 .equals(OperationId.PRINT_INPUT_TYPES)) {
114 EGE ege = new EGEImpl();
115 Set<DataType> inpfo = ege.returnSupportedInputFormats();
116 if (inpfo.size() == 0) {
117 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
118 return;
119 }
120 printConversionPossibilities(response, rr, inpfo);
121 }
122
123 } catch (RequestResolvingException ex) {
124 if (ex.getStatus().equals(
125 RequestResolvingException.Status.WRONG_METHOD)) {
126 response.sendError(405, R_WRONG_METHOD);
127 } else {
128 throw new ServletException(ex);
129 }
130 }
131
132 }
133
134
135
136
137 protected void printConversionsPaths(HttpServletResponse response,
138 RequestResolver rr, List<ConversionsPath> paths) throws IOException {
139 LabelProvider lp = getLabelProvider();
140 PrintWriter out = response.getWriter();
141 if (paths.isEmpty()) {
142 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
143 return;
144 }
145 response.setContentType("text/xml");
146 StringBuffer resp = new StringBuffer();
147 StringBuffer sbpath = new StringBuffer();
148 StringBuffer pathopt = new StringBuffer();
149 resp.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
150 resp
151 .append("<conversions-paths xmlns:xlink=\"http://www.w3.org/1999/xlink\">");
152 int counter = 0;
153 String reqTransf;
154 for (ConversionsPath cp : paths) {
155 resp.append("<conversions-path xlink:href=\"");
156 reqTransf = rr.getRequest().getRequestURL().toString();
157 if (reqTransf.endsWith(SLASH)) {
158 reqTransf = reqTransf.substring(0, reqTransf.length() - 2);
159 resp.append(reqTransf
160 .substring(0, reqTransf.lastIndexOf(SLASH))
161 + SLASH
162 + rr.encodeDataType((DataType) rr.getData())
163 + SLASH);
164 } else {
165 resp.append(reqTransf
166 .substring(0, reqTransf.lastIndexOf(SLASH))
167 + SLASH
168 + rr.encodeDataType((DataType) rr.getData())
169 + SLASH);
170 }
171 sbpath.delete(0, sbpath.length());
172 pathopt.delete(0, pathopt.length());
173 counter = 0;
174 for (ConversionAction ca : cp.getPath()) {
175 sbpath.append(rr.encodeDataType(ca.getConversionOutputType())
176 + SLASH);
177 pathopt.append("<conversion id=\"" + ca.toString()
178 + "\" index=\"" + counter + "\" >");
179 String paramsDefs = ca.getConversionActionArguments()
180 .getPropertiesDefinitions();
181 if (paramsDefs.length() > 0) {
182 Properties props = new Properties();
183 props.loadFromXML(new ByteArrayInputStream(paramsDefs
184 .getBytes()));
185 for (Object key : props.keySet()) {
186 if (!key.toString().endsWith(".type")) {
187 pathopt.append("<property id=\"" + key
188 + "\"><value>");
189 pathopt.append("<![CDATA[" + props.get(key)
190 + "]]></value>");
191 pathopt.append("<type>"
192 + props.get(key.toString() + ".type")
193 + "</type>");
194 pathopt.append("<property-name>"
195 + lp.getLabel(key.toString())
196 + "</property-name></property>");
197 }
198 }
199 }
200 pathopt.append("</conversion>");
201 counter++;
202 }
203 resp.append(sbpath);
204 resp.append("\" ><path-name><![CDATA[ \n " + cp.toString()
205 + " \n ]]></path-name>");
206 resp.append(pathopt);
207 resp.append("</conversions-path>");
208 }
209 resp.append("</conversions-paths>");
210 out.print(resp.toString());
211 out.close();
212 }
213
214
215
216
217 protected void printConversionPossibilities(HttpServletResponse response,
218 RequestResolver rr, Set<DataType> inputDataTypes)
219 throws IOException {
220 PrintWriter out = response.getWriter();
221 response.setContentType("text/xml");
222 out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
223 out
224 .println("<input-data-types xmlns:xlink=\"http://www.w3.org/1999/xlink\">");
225 String prefix = rr.getRequest().getRequestURL().toString()
226 + (rr.getRequest().getRequestURL().toString().endsWith(SLASH) ? ""
227 : "/");
228 for (DataType dt : inputDataTypes) {
229 out.println("<input-data-type id=\"" + dt.toString()
230 + "\" xlink:href=\"" + prefix + rr.encodeDataType(dt)
231 + "/\" />");
232 }
233 out.println("</input-data-types>");
234 out.close();
235 }
236
237
238
239
240
241 protected void doPost(HttpServletRequest request,
242 HttpServletResponse response) throws ServletException, IOException {
243 try {
244 ConversionRequestResolver rr = new ConversionRequestResolver(
245 request, Method.POST);
246 List<DataType> pathFrame = (List<DataType>) rr.getData();
247 performConversion(response, rr, pathFrame);
248 } catch (RequestResolvingException ex) {
249 if (ex.getStatus().equals(
250 RequestResolvingException.Status.BAD_REQUEST)) {
251 response.sendError(HttpServletResponse.SC_BAD_REQUEST);
252 } else if (ex.getStatus().equals(
253 RequestResolvingException.Status.WRONG_METHOD)) {
254 response.sendError(405, R_WRONG_METHOD);
255 } else {
256 throw new ServletException(ex);
257 }
258 } catch (Exception ex) {
259 throw new ServletException(ex);
260 }
261 }
262
263
264
265
266 protected void performConversion(HttpServletResponse response,
267 ConversionRequestResolver rr, List<DataType> pathFrame)
268 throws IOException, FileUploadException, EGEException,
269 ConverterException, RequestResolvingException {
270 EGE ege = new EGEImpl();
271 List<ConversionsPath> cp = ege.findConversionPaths(pathFrame.get(0));
272 ConversionsPath cpath = null;
273 boolean found = false;
274 for (ConversionsPath path : cp) {
275 if ((pathFrame.size() - 1) != path.getPath().size()) {
276 continue;
277 }
278 found = true;
279 int count = 1;
280 for (ConversionAction ca : path.getPath()) {
281 if (!ca.getConversionOutputType().equals(pathFrame.get(count))) {
282 found = false;
283 break;
284 }
285 count++;
286 }
287 if (found) {
288 cpath = path;
289 break;
290 }
291 }
292 if (!found) {
293 response.sendError(HttpServletResponse.SC_BAD_REQUEST);
294 return;
295 } else {
296 doConvert(response, rr, ege, cpath);
297 }
298 }
299
300 private void doConvert(HttpServletResponse response,
301 ConversionRequestResolver rr, EGE ege, ConversionsPath cpath)
302 throws FileUploadException, IOException, RequestResolvingException,
303 EGEException, FileNotFoundException, ConverterException,
304 ZipException {
305 InputStream is = null;
306 OutputStream os = null;
307 if (ServletFileUpload.isMultipartContent(rr.getRequest())) {
308 ServletFileUpload upload = new ServletFileUpload();
309 FileItemIterator iter = upload.getItemIterator(rr.getRequest());
310 while (iter.hasNext()) {
311 FileItemStream item = iter.next();
312 if (!item.isFormField()) {
313 is = item.openStream();
314 applyConversionsProperties(
315 rr.getConversionProperties(), cpath);
316
317 DataBuffer buffer = new DataBuffer(0,
318 EGEConstants.BUFFER_TEMP_PATH);
319 String alloc = buffer.allocate(is);
320 InputStream ins = buffer.getDataAsStream(alloc);
321 is.close();
322
323
324 try {
325 ValidationResult vRes = ege.performValidation(ins,
326 cpath.getInputDataType());
327 if (vRes.getStatus().equals(
328 ValidationResult.Status.FATAL)) {
329 ValidationServlet valServ = new ValidationServlet();
330 valServ.printValidationResult(response, vRes);
331 try {
332 ins.close();
333 } finally {
334 buffer.removeData(alloc, true);
335 }
336 return;
337 }
338 } catch (ValidatorException vex) {
339 LOGGER.warn(vex.getMessage());
340 } finally {
341 try {
342 ins.close();
343 } catch (Exception ex) {
344
345 }
346 }
347 File zipFile = null;
348 FileOutputStream fos = null;
349 String newTemp = UUID.randomUUID().toString();
350 IOResolver ior = EGEConfigurationManager.getInstance()
351 .getStandardIOResolver();
352 File buffDir = new File(buffer.getDataDir(alloc));
353 zipFile = new File(EGEConstants.BUFFER_TEMP_PATH
354 + File.separator + newTemp + EZP_EXT);
355 fos = new FileOutputStream(zipFile);
356 ior.compressData(buffDir, fos);
357 ins = new FileInputStream(zipFile);
358 File szipFile = new File(EGEConstants.BUFFER_TEMP_PATH
359 + File.separator + newTemp + ZIP_EXT);
360 fos = new FileOutputStream(szipFile);
361 try {
362 try {
363 ege.performConversion(ins, fos, cpath);
364 } finally {
365 fos.close();
366 }
367 boolean isComplex = EGEIOUtils
368 .isComplexZip(szipFile);
369 response.setContentType(APPLICATION_OCTET_STREAM);
370 String fN = item.getName().substring(0,
371 item.getName().lastIndexOf("."));
372 if (isComplex) {
373 String fileExt;
374 if (cpath.getOutputDataType().getMimeType()
375 .equals(APPLICATION_MSWORD)) {
376 fileExt = DOCX_EXT;
377 } else {
378 fileExt = ZIP_EXT;
379 }
380 response.setHeader("Content-Disposition",
381 "attachment; filename=\"" + fN
382 + fileExt + "\"");
383 FileInputStream fis = new FileInputStream(
384 szipFile);
385 os = response.getOutputStream();
386 try {
387 EGEIOUtils.copyStream(fis, os);
388 } finally {
389 fis.close();
390 }
391 } else {
392 String fileExt = getMimeExtensionProvider()
393 .getFileExtension(
394 cpath.getOutputDataType()
395 .getMimeType());
396 response.setHeader("Content-Disposition",
397 "attachment; filename=\"" + fN
398 + fileExt + "\"");
399 os = response.getOutputStream();
400 EGEIOUtils.unzipSingleFile(
401 new ZipFile(szipFile), os);
402 }
403 } finally {
404 ins.close();
405 if (os != null) {
406 os.flush();
407 os.close();
408 }
409 buffer.clear(true);
410 szipFile.delete();
411 if (zipFile != null) {
412 zipFile.delete();
413 }
414 }
415 }
416 }
417 } else {
418 response.sendError(HttpServletResponse.SC_BAD_REQUEST);
419 return;
420 }
421 }
422
423 private void applyConversionsProperties(String properties,
424 ConversionsPath cP) throws RequestResolvingException {
425 ConversionsPropertiesHandler cpp = new ConversionsPropertiesHandler(
426 properties);
427 cpp.applyPathProperties(cP);
428 }
429
430
431
432
433
434
435 public LabelProvider getLabelProvider() {
436 return (LabelProvider) this.getServletContext().getAttribute(
437 PreConfig.LABEL_PROVIDER);
438 }
439
440
441
442
443
444
445 public MimeExtensionProvider getMimeExtensionProvider() {
446 return (MimeExtensionProvider) this.getServletContext().getAttribute(
447 PreConfig.MIME_EXTENSION_PROVIDER);
448 }
449
450 }