001: /**
002: *
003: */package org.enhydra.util.fo;
004:
005: import java.awt.print.PrinterJob;
006: import java.io.ByteArrayInputStream;
007: import java.io.ByteArrayOutputStream;
008: import java.io.File;
009: import java.io.IOException;
010: import java.util.Date;
011: import java.util.StringTokenizer;
012:
013: import javax.xml.transform.Result;
014: import javax.xml.transform.Source;
015: import javax.xml.transform.Transformer;
016: import javax.xml.transform.TransformerFactory;
017: import javax.xml.transform.sax.SAXResult;
018: import javax.xml.transform.stream.StreamSource;
019:
020: import org.apache.fop.apps.FOUserAgent;
021: import org.apache.fop.apps.Fop;
022: import org.apache.fop.apps.FopFactory;
023: import org.apache.fop.apps.MimeConstants;
024: import org.apache.fop.pdf.PDFEncryptionParams;
025: import org.enhydra.util.ResponsePostProcessor;
026: import org.enhydra.xml.io.OutputOptions;
027: import org.w3c.dom.Node;
028:
029: import com.lutris.logging.LogChannel;
030: import com.lutris.logging.Logger;
031: import com.lutris.util.Config;
032: import com.lutris.util.ConfigException;
033:
034: /**
035: * @author Slobodan Vujasinovic, Aleksandar Stojsavljevic
036: *
037: */
038: public class Fo2FopResponsePostProcessor implements
039: ResponsePostProcessor {
040:
041: /*
042: * Name of the post processor
043: */
044: private String name = null;
045:
046: /**
047: * LogChannel used by ResponsePostProcessor
048: */
049: private LogChannel logChannel;
050:
051: private File fopBaseDir = null;
052:
053: private File userConfigFile = null;
054:
055: /*
056: * Name of the post processor supported mime type
057: */
058: public static final String mimeType = "text/fo+fop";
059:
060: /*
061: * Name of the post processor generated mime type
062: */
063: private String outMimeType = "application/pdf";
064:
065: // Chiba Adaptor attributes
066: private static final String BASE_DIR_PARAM_NAME = "BaseDirectory";
067:
068: private static final String DEFAULT_BASE_DIR_PARAM_VALUE = ".";
069:
070: private static final String CONF_FILE_PARAM_NAME = "ConfFile";
071:
072: private static final String DEFAULT_CONF_FILE_PARAM_VALUE = "userconfig.xml";
073:
074: public static final String PRODUCER_PARAM_NAME = "producer";
075: public static final String CREATOR_PARAM_NAME = "creator";
076: public static final String AUTHOR_PARAM_NAME = "author";
077: public static final String TITLE_PARAM_NAME = "title";
078: public static final String KEYWORDS_PARAM_NAME = "keywords";
079: public static final String TARGET_RESOLUTION_PARAM_NAME = "targetResolution";
080: public static final String CREATION_DATE_PARAM_NAME = "creationDate";
081:
082: public static final String ALLOW_PRINT_PARAM_NAME = "allowPrint";
083: public static final String ALLOW_COPY_CONTENT_PARAM_NAME = "allowCopyContent";
084: public static final String ALLOW_EDIT_CONTENT_PARAM_NAME = "allowEditContent";
085: public static final String ALLOW_EDIT_ANNOTATIONS_PARAM_NAME = "allowEditAnnotations";
086:
087: public static final String USER_PASS_PARAM_NAME = "username";
088: public static final String OWNER_PASS_PARAM_NAME = "password";
089:
090: //TODO
091: private static String producer = "";
092: private static String creator = "Together Application Framework";
093: private static String author = "";
094: private static String title = "";
095: private static String keywords = "";
096: private static int targetResolution = 300;
097: private static Date creationDate = new Date();
098: private static boolean allowPrint = true;
099: private static boolean allowCopyContent = true;
100: private static boolean allowEditContent = true;
101: private static boolean allowEditAnnotations = true;
102: private static String userPass = "";
103: private static String ownerPass = "";
104:
105: public Fo2FopResponsePostProcessor() {
106: super ();
107: }
108:
109: public Fo2FopResponsePostProcessor(LogChannel logChannel) {
110: super ();
111: this .logChannel = logChannel;
112: }
113:
114: /*
115: * (non-Javadoc)
116: *
117: * @see org.enhydra.util.ResponsePostProcessor#configure(com.lutris.util.Config)
118: */
119: public void configure(Config config) {
120: try {
121: // String fopBaseDirStr = config.getString(BASE_DIR_PARAM_NAME,
122: // DEFAULT_BASE_DIR_PARAM_VALUE);
123: String fopBaseDirStr = getAbsolutePath(BASE_DIR_PARAM_NAME,
124: config, DEFAULT_BASE_DIR_PARAM_VALUE, true);
125:
126: fopBaseDir = new File(fopBaseDirStr);
127:
128: // String confFile = config.getString(CONF_FILE_PARAM_NAME,
129: // DEFAULT_CONF_FILE_PARAM_VALUE);
130: String confFile = getAbsolutePath(CONF_FILE_PARAM_NAME,
131: config, DEFAULT_CONF_FILE_PARAM_VALUE, false);
132:
133: userConfigFile = new File(confFile);
134:
135: if (!userConfigFile.exists())
136: throw new Exception(
137: "FOP configuration file doesn't exist!");
138:
139: if (logChannel != null) {
140: logChannel.write(Logger.DEBUG,
141: "Fo2Pdf Post Processor (" + name
142: + ") - Initialized successfully!");
143: }
144: } catch (Exception ex) {
145: if (logChannel != null) {
146: logChannel
147: .write(
148: Logger.WARNING,
149: "Fo2Pdf Post Processor ("
150: + name
151: + ") - Initialized with default configuration settings!",
152: ex);
153: }
154:
155: String fopBaseDirStr = DEFAULT_BASE_DIR_PARAM_VALUE;
156:
157: fopBaseDir = new File(fopBaseDirStr);
158:
159: String confFile = DEFAULT_CONF_FILE_PARAM_VALUE;
160:
161: userConfigFile = new File(confFile);
162:
163: // if (!userConfigFile.exists())
164: // throw new Exception("FOP configuration file doesn't exist!");
165: }
166: }
167:
168: /*
169: * (non-Javadoc)
170: *
171: * @see org.enhydra.util.ResponsePostProcessor#process(java.util.Map,
172: * org.w3c.dom.Node)
173: */
174: public Node process(OutputOptions oo, Node document) {
175: // This point can be used for some post-processor specific
176: // (re)configuration
177: // posted from PO at runtim e
178:
179: if (logChannel != null) {
180: logChannel.write(Logger.DEBUG, "Fo2Pdf Post Processor ("
181: + name + ") - Processing parameters (if any)!");
182: }
183:
184: if (oo.getFreeformOption(BASE_DIR_PARAM_NAME) != null) {
185: String fopBaseDirStr = (String) oo
186: .getFreeformOption(BASE_DIR_PARAM_NAME);
187: fopBaseDir = new File(fopBaseDirStr);
188: }
189:
190: if (oo.getFreeformOption(CONF_FILE_PARAM_NAME) != null) {
191: String confFile = (String) oo
192: .getFreeformOption(CONF_FILE_PARAM_NAME);
193: userConfigFile = new File(confFile);
194: }
195:
196: if (oo.getFreeformOption(PRODUCER_PARAM_NAME) != null) {
197: producer = (String) oo
198: .getFreeformOption(PRODUCER_PARAM_NAME);
199: }
200:
201: if (oo.getFreeformOption(CREATOR_PARAM_NAME) != null) {
202: creator = (String) oo.getFreeformOption(CREATOR_PARAM_NAME);
203: }
204:
205: if (oo.getFreeformOption(AUTHOR_PARAM_NAME) != null) {
206: author = (String) oo.getFreeformOption(AUTHOR_PARAM_NAME);
207: }
208:
209: if (oo.getFreeformOption(TITLE_PARAM_NAME) != null) {
210: title = (String) oo.getFreeformOption(TITLE_PARAM_NAME);
211: }
212:
213: if (oo.getFreeformOption(KEYWORDS_PARAM_NAME) != null) {
214: keywords = (String) oo
215: .getFreeformOption(KEYWORDS_PARAM_NAME);
216: }
217:
218: if (oo.getFreeformOption(TARGET_RESOLUTION_PARAM_NAME) != null) {
219: targetResolution = ((Integer) oo
220: .getFreeformOption(TARGET_RESOLUTION_PARAM_NAME))
221: .intValue();
222: }
223:
224: if (oo.getFreeformOption(CREATION_DATE_PARAM_NAME) != null) {
225: creationDate = (Date) oo
226: .getFreeformOption(CREATION_DATE_PARAM_NAME);
227: }
228:
229: if (oo.getFreeformOption(ALLOW_PRINT_PARAM_NAME) != null) {
230: allowPrint = ((Boolean) oo
231: .getFreeformOption(ALLOW_PRINT_PARAM_NAME))
232: .booleanValue();
233: }
234:
235: if (oo.getFreeformOption(ALLOW_COPY_CONTENT_PARAM_NAME) != null) {
236: allowCopyContent = ((Boolean) oo
237: .getFreeformOption(ALLOW_COPY_CONTENT_PARAM_NAME))
238: .booleanValue();
239: }
240:
241: if (oo.getFreeformOption(ALLOW_EDIT_CONTENT_PARAM_NAME) != null) {
242: allowEditContent = ((Boolean) oo
243: .getFreeformOption(ALLOW_EDIT_CONTENT_PARAM_NAME))
244: .booleanValue();
245: }
246:
247: if (oo.getFreeformOption(ALLOW_EDIT_ANNOTATIONS_PARAM_NAME) != null) {
248: allowEditAnnotations = ((Boolean) oo
249: .getFreeformOption(ALLOW_EDIT_ANNOTATIONS_PARAM_NAME))
250: .booleanValue();
251: }
252:
253: if (oo.getFreeformOption(USER_PASS_PARAM_NAME) != null) {
254: userPass = (String) oo
255: .getFreeformOption(USER_PASS_PARAM_NAME);
256: }
257:
258: if (oo.getFreeformOption(OWNER_PASS_PARAM_NAME) != null) {
259: ownerPass = (String) oo
260: .getFreeformOption(OWNER_PASS_PARAM_NAME);
261: }
262:
263: return document;
264: }
265:
266: /*
267: * (non-Javadoc)
268: *
269: * @see org.enhydra.util.ResponsePostProcessor#process(java.util.Map, byte
270: * [])
271: */
272: public byte[] process(byte[] byteArray, String mimeEncoding,
273: String mimeType) {
274:
275: StringTokenizer st = new StringTokenizer(mimeType, "+");
276: st.nextToken();// fo
277: String fopMimePart = st.nextToken();
278: st = new StringTokenizer(fopMimePart, "-");
279: st.nextToken();// fop
280:
281: // FOP render
282: String fopRender = "";
283:
284: String fopRenderStr = "PDF";
285: boolean fopPrint = false;
286: while (st.hasMoreTokens()) {
287: fopRenderStr = st.nextToken();
288:
289: // do the render map stuff here
290: if ("PDF".equalsIgnoreCase(fopRenderStr)) {
291: fopRender = MimeConstants.MIME_PDF;
292: outMimeType = "application/pdf";
293: mimeType = outMimeType;
294: } else if ("TXT".equalsIgnoreCase(fopRenderStr)) {
295: fopRender = MimeConstants.MIME_PLAIN_TEXT;
296: outMimeType = "text/plain";
297: mimeType = outMimeType;
298: } else if ("XML".equalsIgnoreCase(fopRenderStr)) {
299: fopRender = MimeConstants.MIME_FOP_AREA_TREE;
300: outMimeType = "text/xml";
301: mimeType = outMimeType;
302: } else if ("PS".equalsIgnoreCase(fopRenderStr)) {
303: fopRender = MimeConstants.MIME_POSTSCRIPT;
304: outMimeType = "application/postscript";
305: mimeType = outMimeType;
306: } else if ("PCL".equalsIgnoreCase(fopRenderStr)) {
307: fopRender = MimeConstants.MIME_PCL;
308: outMimeType = "application/vnd.hp-pcl";
309: mimeType = outMimeType;
310: } else if ("RTF".equalsIgnoreCase(fopRenderStr)) {
311: fopRender = MimeConstants.MIME_RTF;
312: outMimeType = "application/rtf";
313: mimeType = outMimeType;
314: } else if ("AFP".equalsIgnoreCase(fopRenderStr)) {
315: fopRender = MimeConstants.MIME_AFP;
316: outMimeType = "application/vnd.ibm.modcap";
317: mimeType = outMimeType;
318: } else if ("PRINT".equalsIgnoreCase(fopRenderStr)) {
319: fopPrint = true;
320: }
321: }
322:
323: if (logChannel != null) {
324: logChannel.write(Logger.DEBUG, "Fo2Pdf Post Processor ("
325: + name + ") - Processing response!");
326: }
327:
328: ByteArrayOutputStream baos = null;
329: try {
330: // TODO
331: // driver.setLogger(new ConsoleLogger(ConsoleLogger.LEVEL_INFO));
332:
333: ByteArrayInputStream bais = new ByteArrayInputStream(
334: byteArray);
335: ByteArrayInputStream bais1 = new ByteArrayInputStream(
336: byteArray);
337:
338: baos = new ByteArrayOutputStream();
339:
340: FopFactory fopFactory = FopFactory.newInstance();
341: fopFactory.setUserConfig(userConfigFile);
342:
343: FOUserAgent userAgent = fopFactory.newFOUserAgent();
344: userAgent.setBaseURL("file:///"
345: + fopBaseDir.getCanonicalPath() + "/");
346:
347: try {
348: // if document should be printed
349: if (fopPrint) {
350: PrinterJob pj = PrinterJob.getPrinterJob();
351: org.apache.fop.render.print.PrintRenderer renderer = new org.apache.fop.render.print.PrintRenderer(
352: pj);
353:
354: userAgent.setRendererOverride(renderer);
355:
356: Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF,
357: userAgent, baos);
358:
359: TransformerFactory factory = TransformerFactory
360: .newInstance();
361: Transformer transformer = factory.newTransformer();
362:
363: Source src = new StreamSource(bais);
364: Result res = new SAXResult(fop.getDefaultHandler());
365: transformer.transform(src, res);
366: }
367:
368: // if we should additionally print document to the request
369: if (!fopRender.equals("") || !fopPrint) {
370: userAgent.setRendererOverride(null);
371:
372: userAgent.setProducer(producer);
373: userAgent.setCreator(creator);
374: userAgent.setAuthor(author);
375: userAgent.setCreationDate(creationDate);
376: userAgent.setTitle(title);
377: userAgent.setKeywords(keywords);
378: userAgent.setTargetResolution(targetResolution);
379:
380: userAgent.getRendererOptions().put(
381: "encryption-params",
382: new PDFEncryptionParams(userPass,
383: ownerPass, allowPrint,
384: allowCopyContent, allowEditContent,
385: allowEditAnnotations));
386:
387: Fop fop = fopFactory.newFop(fopRender, userAgent,
388: baos);
389:
390: TransformerFactory factory = TransformerFactory
391: .newInstance();
392: Transformer transformer = factory.newTransformer();
393:
394: Source src = new StreamSource(bais1);
395: Result res = new SAXResult(fop.getDefaultHandler());
396: transformer.transform(src, res);
397:
398: byteArray = baos.toByteArray();
399: mimeType = outMimeType;
400: } else {
401: String sMsg = "<html>"
402: + "<title>Success</title>\n"
403: + "<body>\n"
404: + "<h1>Together Application Framework - FOP Post-Processor: </h1>\n"
405: + "<h3>The requested data was printed successfully!!!</h3>\n"
406: + "</body>\n" + "</html>";
407:
408: byteArray = sMsg.getBytes();
409: outMimeType = "text/html";
410: mimeType = outMimeType;
411: }
412: } catch (Exception e) {
413: e.printStackTrace();
414: } finally {
415: try {
416: if (bais != null)
417: bais.close();
418: if (bais1 != null)
419: bais1.close();
420: } catch (IOException ioex) {
421: bais = null;
422: bais1 = null;
423: }
424: }
425: } catch (Exception e) {
426: e.printStackTrace();
427: }
428: return byteArray;
429: }
430:
431: /*
432: * (non-Javadoc)
433: *
434: * @see org.enhydra.util.ResponsePostProcessor#setName(java.lang.String)
435: */
436: public void setName(String name) {
437: this .name = name;
438: }
439:
440: /*
441: * (non-Javadoc)
442: *
443: * @see org.enhydra.util.ResponsePostProcessor#getName()
444: */
445: public String getName() {
446: return name;
447: }
448:
449: /*
450: * (non-Javadoc)
451: *
452: * @see org.enhydra.util.RequestPreProcessor#setLogChannel()
453: */
454: public void setLogChannel(LogChannel logChannel) {
455: this .logChannel = logChannel;
456: }
457:
458: /*
459: * (non-Javadoc)
460: *
461: * @see org.enhydra.util.RequestPreProcessor#getLogChannel()
462: */
463: public LogChannel getLogChannel() {
464: return logChannel;
465: }
466:
467: /*
468: * (non-Javadoc)
469: *
470: * @see org.enhydra.util.ResponsePostProcessor#shouldProcess(java.lang.String)
471: */
472: public boolean shouldProcess(String mimeType) {
473: if (mimeType != null
474: && mimeType
475: .startsWith(Fo2FopResponsePostProcessor.mimeType))
476: return true;
477: return false;
478: }
479:
480: /*
481: * (non-Javadoc)
482: *
483: * @see org.enhydra.util.ResponsePostProcessor#getOutputMimeType()
484: */
485: public String getOutputMimeType() {
486: return this .outMimeType;
487: }
488:
489: /**
490: * Method returns absolute path to file (directory)!
491: *
492: * @param Property
493: * Name
494: * @param Configuration
495: * Object
496: * @param Default
497: * Property Value
498: * @param If
499: * This Is Directory
500: * @return Absolute File Path
501: */
502: private String getAbsolutePath(String propName, Config config,
503: String defaultValue, boolean isDirectory) {
504: String absoultePath = null;
505: try {
506: absoultePath = config.getString(propName, defaultValue);
507:
508: if (absoultePath != null) {
509: File temp = new File(absoultePath);
510:
511: if ((!temp.isDirectory() && isDirectory)
512: || !temp.exists()) {
513: temp = new File(config.getConfigFile().getFile()
514: .getParentFile().getAbsolutePath()
515: + File.separator + absoultePath);
516:
517: if ((!temp.isDirectory() && isDirectory)
518: || !temp.exists()) {
519: if (logChannel != null)
520: logChannel
521: .write(
522: Logger.WARNING,
523: propName
524: + " application parameter isn't properly initialized!");
525:
526: } else {
527: try {
528: absoultePath = temp.getCanonicalPath();
529: } catch (Exception e) {
530: }
531: }
532: } else {
533: try {
534: absoultePath = temp.getCanonicalPath();
535: } catch (Exception e) {
536: }
537: }
538: }
539: } catch (ConfigException e) {
540: if (logChannel != null) {
541: logChannel
542: .write(
543: Logger.WARNING,
544: propName
545: + " application parameter isn't properly initialized!");
546:
547: }
548: }
549:
550: return absoultePath;
551: }
552:
553: // This is stolen from PrintStarter
554: /*static class PrintRenderer extends AWTRenderer {
555:
556: private static final int EVEN_AND_ALL = 0;
557:
558: private static final int EVEN = 1;
559:
560: private static final int ODD = 2;
561:
562: private int startNumber;
563:
564: private int endNumber;
565:
566: private int mode = EVEN_AND_ALL;
567:
568: // private int copies = 1;
569:
570: private PrinterJob printerJob;
571:
572: PrintRenderer(PrinterJob printerJob) {
573: super();
574:
575: this.printerJob = printerJob;
576: startNumber = 0;
577: endNumber = -1;
578:
579: printerJob.setPageable(this);
580:
581: mode = EVEN_AND_ALL;
582: String str = System.getProperty("even");
583: if (str != null) {
584: try {
585: mode = Boolean.valueOf(str).booleanValue() ? EVEN : ODD;
586: } catch (Exception e) {
587: }
588:
589: }
590: }
591:
592: public void stopRenderer(OutputStream outputStream) throws IOException {
593: super.stopRenderer();
594:
595: if (endNumber == -1)
596: endNumber = getPageCount();
597:
598: Vector numbers = getInvalidPageNumbers();
599: for (int i = numbers.size() - 1; i > -1; i--)
600: removePage(Integer.parseInt((String) numbers.elementAt(i)));
601:
602: try {
603: printerJob.print();
604: } catch (PrinterException e) {
605: e.printStackTrace();
606: throw new IOException("Unable to print: " + e.getClass().getName() + ": "
607: + e.getMessage());
608: }
609: }
610:
611: public void renderPage(Page page) {
612: pageWidth = (int) ((float) page.getWidth() / 1000f);
613: pageHeight = (int) ((float) page.getHeight() / 1000f);
614: super.renderPage(page);
615: }
616:
617: private Vector getInvalidPageNumbers() {
618:
619: Vector vec = new Vector();
620: int max = getPageCount();
621: boolean isValid;
622: for (int i = 0; i < max; i++) {
623: isValid = true;
624: if (i < startNumber || i > endNumber) {
625: isValid = false;
626: } else if (mode != EVEN_AND_ALL) {
627: if (mode == EVEN && ((i + 1) % 2 != 0))
628: isValid = false;
629: else if (mode == ODD && ((i + 1) % 2 != 1))
630: isValid = false;
631: }
632:
633: if (!isValid)
634: vec.add(i + "");
635: }
636:
637: return vec;
638: }
639: } */// class PrintRenderer
640: public Object clone() {
641: Fo2FopResponsePostProcessor f2prpp = new Fo2FopResponsePostProcessor(
642: this.getLogChannel());
643: f2prpp.fopBaseDir = this.fopBaseDir;
644: f2prpp.userConfigFile = this.userConfigFile;
645: return f2prpp;
646: }
647:
648: }
|