Monitor.java example

//------------------FOR DEMO USE ONLY----------------------------------
//-------- Copyright by Artem Saveliev artem@savelev.com ------------
//---------------------------------------------------------------------

package com.broadstr.xslfoserver;

import java.io.*;


import javax.xml.transform.TransformerException;
import org.apache.xpath.XPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.w3c.dom.Element;

import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.net.URI;
import java.net.URISyntaxException;
import java.nio.channels.FileChannel;
import java.util.TimerTask;


import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.DocPrintJob;
import javax.print.Doc;
import javax.print.SimpleDoc;
import javax.print.PrintException;

import javax.print.DocFlavor;
import javax.print.DocFlavor.INPUT_STREAM;
import javax.print.attribute.DocAttributeSet;
import javax.print.attribute.HashDocAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;

import javax.print.attribute.standard.Destination;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.tanukisoftware.wrapper.WrapperManager;


public class Monitor extends TimerTask {

    public String in;
    public String out;
    public fo2pdf app;
    public FilenameFilter fo;
    public Document document;
    private Element printNameSpace;
    
    public Monitor(){
        app = new fo2pdf();
        fo = new FOFilter();
    }

    public void run() {
            File pdffile;
            File psfile;
            String outfile;
            String outputType;
            File inDir = new File(in);
            File outDir = new File(out);
            Node n;
       
            File[] fofiles = inDir.listFiles(fo);
            if (fofiles == null) return;
            for (int fileIndex = 0;fileIndex < fofiles.length; fileIndex++){
                WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Found file " + fofiles[fileIndex].getPath());
                outfile = fofiles[fileIndex].getName().replaceAll("\\.fo","");
                try{
                    if (LoadFODOM(fofiles[fileIndex].getPath())){
                        WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Loaded FO file");
                        
                    //-- Convert to PDF if required

                        NodeList nl;
                        try{
                            nl = XPathAPI.selectNodeList(document,"//print:printManifest/out[format='pdf']",printNameSpace);
                        }
                        catch (Exception e) {
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Unable to find PDF format of text, query failed\n\t"+e.getMessage());
                            throw new Exception("Reading print manifest failed");
                        }
                        WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"\nTotal PDF requests found: " + nl.getLength());
                        if (nl.getLength()> 0){
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Found PDF generation request in " + fofiles[fileIndex].getName());
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Generating empty file object");
                            pdffile = new File(out,outfile+".pdf.temp");
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Converting to PDF");
                            app.convertFO2PDF(fofiles[fileIndex], pdffile);
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Distributing to location");
                            for(int i=0;i<nl.getLength();i++)
                            {
                                n = nl.item(i);
                                
                                try{
                                    
                                    outputType = ((Text)XPathAPI.selectSingleNode(n,"./outputType/text()")).getNodeValue();
                                }
                                catch (Exception e) {
                                    WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Reading output type falied");
                                    throw new Exception("Reading output type falied");
                                }

                                WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Saving to "+outputType);

                                if (outputType.equals("screen")){
                                    WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Found request to output PDF to screen in " + fofiles[fileIndex].getName());
                                    copyFile(pdffile.getPath(),new File(out,outfile+".pdf").getPath());
                                }
                                else if (outputType.equals("file")){
                                    WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Found request to output PDF to file in " + fofiles[fileIndex].getName());
                                    copyFile(pdffile.getPath(),((Text)XPathAPI.selectSingleNode(n,"./location/text()")).getNodeValue()+".pdf");
                                }
                                else if (outputType.equals("print")){
                                    WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Found request to output PDF to printer in " + fofiles[fileIndex].getName());
                                    printFile(pdffile,n);
                                }
                             }
                            pdffile.delete();
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Done with PDF generation\n");
                        }
                        
                    //-- Convert to PS if required

                        try{
                            nl = XPathAPI.selectNodeList(document,"//print:printManifest/out[format='ps']",printNameSpace);
                        }
                        catch (Exception e) {
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Unable to find PS format of text, query failed\n\t"+e.getMessage());
                            throw new Exception("Reading print manifest failed");
                        }
                        WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Total PS requests found: " + nl.getLength());
                        if (nl.getLength()> 0){
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Found PS generation request in " + fofiles[fileIndex].getName());
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Generating empty file object");
                            psfile = new File(out,outfile+".ps.temp");
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Converting to PDF");
                            app.convertFO2PS(fofiles[fileIndex], psfile);
                            for(int i=0;i<nl.getLength();i++)
                            {
                                n = nl.item(i);
                                try{
                                    outputType = ((Text)XPathAPI.selectSingleNode(n,"./outputType/text()")).getNodeValue();
                                }
                                catch (Exception e) {
                                    WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Reading output type falied");
                                    throw new Exception("Reading output type falied");
                                }

                                WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Saving to "+outputType);
                                if (outputType.equals("screen")){
                                    WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Found request to output PS to screen in " + fofiles[fileIndex].getName());
                                    copyFile(psfile.getPath(),new File(out,outfile+".ps").getPath());
                                }
                                else if (outputType.equals("file")){
                                    WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Found request to output PS to file in " + fofiles[fileIndex].getName());
                                    copyFile(psfile.getPath(),((Text)XPathAPI.selectSingleNode(n,"./location/text()")).getNodeValue()+".ps");
                                }
                                else if (outputType.equals("print")){
                                    WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Found request to output PS to printer in " + fofiles[fileIndex].getName());
                                    printFile(psfile,n);
                                }
                             }
                             psfile.delete();
                             WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Done with PS generation\n");
                        }
                        //--- Remove source file after done

                        try{
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Done with file, deleting " + fofiles[fileIndex].getName());
                            fofiles[fileIndex].delete();
                        }
                        catch (Exception e){
                            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Unable to delete "+ fofiles[fileIndex].getPath());
                        }
                    }
                    else
                        fofiles[fileIndex].renameTo(new File(out,outfile+".fo.err"));
                } catch (Exception e) {
                    WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Error: can not process file, general error\n\t" + e.getMessage());
                    fofiles[fileIndex].renameTo(new File(out,outfile+".fo.err"));
                }
                
            }
    }
    
    public boolean LoadFODOM(String filename){
        WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Loading FO file");
        try {
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Creating Factory");
            DocumentBuilderFactory factory = 
            DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            DocumentBuilder builder = factory.newDocumentBuilder();
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Parsing FO file");
            document = builder.parse(filename);

            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Creating namespace node");
            printNameSpace = document.createElementNS("http://www.broadstr.com/xslfoPrinter","print");
            document.getDocumentElement().appendChild(printNameSpace);

            return true;
        }
        catch (FactoryConfigurationError e) {
            // unable to get a document builder factory

            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Error: can not parse file in DOM, factory config error\n" + e.getMessage());
            return false;
        } 
        catch (ParserConfigurationException e) {
            // parser was unable to be configured
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Error: can not parse file in DOM, parser config error\n\t" + e.getMessage());
            return false;
        }
        catch (SAXException e) {
            // parsing error

            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Error: can not parse file in DOM, SAX error\n\t" + e.getMessage());
            return false;
        } 
        catch (IOException e) {
            // i/o error
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Error: can not parse file in DOM, i/o error\n\t" + e.getMessage());
            return false;
        }
    }
    
    public void copyFile(String inputFile, String outputFile){
        try{
            // Create channel on the source

            FileChannel srcChannel = new FileInputStream(inputFile).getChannel();

            // Create channel on the destination
            FileChannel dstChannel = new FileOutputStream(outputFile).getChannel();

            // Copy file contents from source to destination
            dstChannel.transferFrom(srcChannel, 0, srcChannel.size());

            // Close the channels

            srcChannel.close();
            dstChannel.close();
        }
        catch (FileNotFoundException e){
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Error: can not find file to copy to destination\n\t" + e.getMessage());
        }
        catch (IOException e){
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Error: can not copy file, i/o error\n\t" + e.getMessage());
        }
    }
    
// Sends file to printer device
    public boolean printFile(File file, Node props) throws TransformerException, URISyntaxException, FileNotFoundException, Exception {
        String printername;
        WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Starting printing");
        if (((Text)XPathAPI.selectSingleNode(props,"./format/text()")).getNodeValue().equals("ps")){
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Printing PostScript file");
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Reading printer name");
            try{
                printername = ((Text)XPathAPI.selectSingleNode(props,"./location/text()")).getNodeValue();
            }
            catch (Exception e){
                WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Error Reading printer name");
                throw new Exception("Error reading printer name "+e.getMessage());
            }
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Printer name: "+printername);

            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Adjusting PS file: "+file.getPath());
            
            File adjustedFile = adjustPSFile(file, props);
            
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Opening PS file: "+adjustedFile.getPath());
            
            FileInputStream inFile=new FileInputStream(adjustedFile);
            int size=(int)adjustedFile.length ();
            DataInputStream input =new DataInputStream(inFile);
            byte type[]=new byte[size];
            input.read(type);
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Creating output stream");
            FileOutputStream os = new FileOutputStream(printername);

            PrintStream ps = new PrintStream(os);
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Printing!");
            ps.write (type);

            if(ps.checkError ()==true)
                return false;
            ps.print("\f");
            ps.close();
            input.close ();
            adjustedFile.delete();
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Printing done");
            

/*---       javax.print part, not working for now

            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Printing PostScript file");
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Initialize print service and job");
            DocFlavor flavor = INPUT_STREAM.POSTSCRIPT;
            PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Setting printer to "+ printername);
            aset.add(new Destination(new URI("file:"+printername)));
            PrintService[] service = PrintServiceLookup.lookupPrintServices(flavor,aset);    
            PrintService s = service[0];
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Found printer service "+ s.getName());
            DocPrintJob job = s.createPrintJob();
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Opening file input stream from "+file.getPath());
            FileInputStream f = new FileInputStream(file);
            DocAttributeSet das = new HashDocAttributeSet();
            Doc doc = new SimpleDoc(f, flavor, das);
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Sending document to printer the document");
            job.print(doc, aset);
 */
        }
        return true;
    }
//    Edits the resulting PostScript file to add tray and duplex instructions
    public File adjustPSFile(File input,Node props) throws Exception{
        boolean duplex = false;
        try{
            if (XPathAPI.selectSingleNode(props,"./duplex")!=null)
                if (((Text)XPathAPI.selectSingleNode(props,"./duplex/text()")).getNodeValue().equals("yes")) duplex = true;
        }
        catch (TransformerException e){
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Error Reading duplex param");
            throw new Exception("Error reading printer name "+e.getMessage());
        }
            
        int tray = 0;
        try{
            if (XPathAPI.selectSingleNode(props,"./tray")!= null)
                tray = Integer.parseInt(((Text)XPathAPI.selectSingleNode(props,"./tray/text()")).getNodeValue());
        }
        catch (TransformerException e){
            WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_ERROR,"Error Reading duplex param");
            throw new Exception("Error reading printer name "+e.getMessage());
        }

        boolean propertiesAdded = false; 
        
        String str;
        String previousline = "   ";
        File output = new File(input.getPath()+".spool");
        BufferedReader in  = new BufferedReader(new FileReader(input));
        BufferedWriter out = new BufferedWriter(new FileWriter(output));
        while ((str=in.readLine())!=null){
            if (!propertiesAdded && !str.substring(0,2).equals("%%") && previousline.substring(0,2).equals("%%"))
            {
                WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Found end of comments");
                propertiesAdded = true;
                
                if (duplex){
                    WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Adding duplex command");
                    out.write("<< /Duplex true >> setpagedevice");
                    out.newLine();
                }

                if (tray > 1){
                    WrapperManager.log(WrapperManager.WRAPPER_LOG_LEVEL_DEBUG,"Setting tray to "+tray);
                    out.write("<< /ManualFeed false /MediaPosition null >> setpagedevice");
                    out.newLine();
                    out.write("userdict /lms");
                    out.newLine();
                    out.write("currentpagedevice /InputAttributes get "+(tray-1)+" known { "+(tray-1)+" }{ 0 }ifelse put");
                    out.newLine();
                    out.write("currentpagedevice /InputAttributes get lms get setpagedevice");
                    out.newLine();
                    out.write("<< /InputAttributes << /Priority [lms] >> >> setpagedevice");
                    out.newLine();
                    out.write("<< /Policies << /PageSize 7 >> >> setpagedevice");
                    out.newLine();
                }
            }
            out.write(str);
            out.newLine();
            previousline = str;
        }
        in.close();
        out.close();
        return output;
    }
}