Sourcecode Listing of

NeumesXSLTServlet.java





Color Key :   [•] XML code      [•] string literal      [•] XML comment   

Line
0001 /**
0002  * @(#)NeumesXSLTServlet.java
0003  * @version 1.2, 10 April 2006
0004  * @author Louis W. G. Barton
0005  *   University of Oxford
0006  *   e-mail: louis.barton.je.77@aya.yale.edu
0007  * @author Tillman Weyde
0008  *
0009  * Abstract:
0010  * For the NEUMES Project
0011  * (Neumed and Ecphonetic Universal Manuscript Encoding Standard).
0012  *
0013  * A. Background
0014  * - The content of medieval chant manuscripts are transcribed to
0015  * NeumesXML file format. Such files can be used for a variety of
0016  * purposes, one of which is visualization.
0017  * - In principle, a NeumesXML file can be directly accessed on the Web
0018  * by its URL. In such cases, the client-side browser performs the
0019  * 'parse/validation' of the file, then invokes an XSLT transformation,
0020  * which pushes a plain HTML visualization of the transcription to the
0021  * client's browser.
0022  * - The NeumesXML DTD and XSLT files reside on the Scribe server and
0023  * are addressed in a NeumesXML file by their respective URIs.
0024  * - In practice, however, many browsers in the field do not support
0025  * XSLT, or they do the parsing and transformation in a manner not
0026  * consistent with current standards.
0027  * - In order to make transcriptions available for viewing by the greatest
0028  * number of users, the NeumesXSLTServlet class performs these XML functions
0029  * for the user on the www.scribeserver.com server, and simply pushes the
0030  * resulting HTML output to the client.
0031  * - This Java program runs on the Scribe server as a servlet within the
0032  *   Tomcat or JRun servlet service.
0033  *
0034  * B. Functionality
0035  * - From an HTML menu page on the NEUMES Web site, the user is given a
0036  * choice of three processing options:
0037  *   1. View a transcription on the Scribe server (such as the Aquitanian
0038  *   "Dextera domini fecit virtutem") by attempting the 'parse/validate" and
0039  *   XSLT transformation in the client browser (in which case this servlet
0040  *   is not invoked).
0041  *   2. View a transcription on the Scribe server (such as the Aquitanian
0042  *   "Dextera domini fecit virtutem") by having this servlet do the
0043  *   'parse/validate' and XSLT transformation, then push the resulting
0044  *   HTML page to the client browser.
0045  *   3. Upload a NeumesXML transcription from user's local disk to the
0046  *   Scribe server for processing, which results in an HTML visualization
0047  *   of that transcription being pushed to the user's browser.
0048  * - The servlet checks to see whether there is an HTTP request parameter
0049  * called "com" and whether its value is "transfer_upload".
0050  * - If true, then the servlet attempts to retrieve the uploaded file
0051  * and submit it for 'parse/validation' and XSLT transformation here.
0052  *
0053  * Acknowledgments:
0054  * - This program was derived from SimpleXSLTServlet.java, which is a
0055  *   sample program provided with Xalan-Java2 (http://www.apache.org/).
0056  * - The Xalan class package (javax.xml.transform.*) for 'parse/validate' of
0057  *   XML files and XSLT transformation is Copyright
0058  *   (c) 1999 The Apache Software Foundation:
0059  *   "The end-user documentation included with the redistribution,
0060  *   if any, must include the following acknowledgment:
0061  *       'This product includes software developed by the
0062  *        Apache Software Foundation (http://www.apache.org/).'
0063  *   Alternately, this acknowledgment may appear in the software itself,
0064  *   if and wherever such third-party acknowledgments normally appear."
0065  * - The MultipartRequest class package (com.oreilly.servlet.*) for handling
0066  *   file uploads is Copyright (C) 2001-2002 by Jason Hunter:
0067  *   "Permission is granted to use these packages in the development of any
0068  *   non-commercial project. For this use you are granted a non-exclusive,
0069  *   non-transferable limited license at no cost," provided the distribution
0070  *   includes copyright notice as follows:
0071  *   "The source code, object code, and documentation in the
0072  *   com.oreilly.servlet package is copyright and owned by Jason Hunter."
0073  *
0074  * Implementation Notes:
0075  * - Processing of a NeumesXML file that resides on the server is done
0076  * by invoking the doGet() method in this servlet. Example:
0077  *   http://www.scribeserver.com/servlet/NeumesXML.NeumesXSLTServlet?filepath=
0078  *   http://www.scribeserver.com/SCRIBE/NEUMES/xml/transcriptions/Dextera_Aq_2.xml
0079  * - Processing of an uploaded NeumesXML file is done by invoking the
0080  * doPost() method in this servlet. Example:
0081  *   <FORM
0082  *   ACTION="http://www.scribeserver.com/servlet/NeumesXML.NeumesXSLTServlet"
0083  *   METHOD="POST" ENCTYPE="multipart/form-data">
0084  *   <INPUT TYPE=HIDDEN NAME="com" VALUE="transfer_upload" MAXLENGTH=200>
0085  *   <INPUT TYPE=FILE SIZE=30 NAME="thefile" MAXLENGTH=400
0086  *   ACCEPT="text/*; charset=UTF-8"><BR>
0087  *   <INPUT TYPE=SUBMIT VALUE="Upload File">
0088  *   </FORM>
0089  * - The MultipartRequest classes were designed to have no maximum upload
0090  * size limit, but for your server's protection the constructor allows you
0091  * to set a maximum POST size to accept. Any upload larger than the limit
0092  * is halted. The default maximum is 1MB.
0093  * - Xalan is the standard XML processor integrated in Java2 version 1.4.
0094  * And so, it is not really necessary to use the external library if the
0095  * servlet engine uses JDK 1.4.
0096  *
0097  * Revision History:
0098  * - Version 1.2 (10 April 2006). [LB:] added "NEUMES." to package name.
0099  * - LB, 24 February 2004:
0100  *   Changed "NeumesXSL.xsl" to "NeumesXML.xsl".
0101  *   Changed "neumesFO.xsl" to "NeumesXML_FO.xsl".
0102  *   Added to doGet() two parameters: 'testing' and 'format'.
0103  *   Added: xslt_filepath_testing; xslFO_filepath_testing.
0104  * - 01/03; minor changes added by TW to handle error conditions.
0105  * - version, 1.1, 31 December 2002.
0106  * - 12/02: code added by Tillman Weyde to allow client to upload
0107  *   file for parse/validate and XSLT transformation.
0108  * - This source code was decompiled by TW from NeumesXSLTServlet.class.
0109  *
0110  * Copyright Notice:
0111  * Copyright 2003-2004 by Louis W. G. Barton.
0112  * Copyright 2002 by the President and Fellows of Harvard College;
0113  * contains software or other intellectual property licensed from
0114  * Louis W. G. Barton, copyright 1995-2001 by Louis W. G. Barton.
0115  */
0116 
0117  package NEUMES.NeumesXML;
0118 
0119  import java.io.*;  // for CharArrayReader, CharArrayWriter, IOException,
0120                     // InputStreamReader, ObjectInputStream, PrintStream,
0121                     // PrintWriter, Reader.
0122  import java.net.*;  // for MalformedURLException, URL.
0123  import java.util.*;  // for Enumeration, Hashtable, Vector.
0124  import javax.servlet.*;  // for ServletConfig, ServletException;
0125  import javax.servlet.http.*;  // for HttpServlet, HttpServletRequest,
0126                                // HttpServletResponse.
0127  import javax.xml.transform.*;  // for Result, Source, Transformer,
0128                                 // TransformerFactory;
0129  import javax.xml.transform.sax.*;  // for SAXResult
0130  import javax.xml.transform.stream.*;  // for StreamResult, StreamSource
0131  import org.apache.avalon.framework.logger.*;  // for ConsoleLogger, Logger
0132  import org.apache.fop.apps.*;  // for Driver, XSLTInputHandler
0133  import org.apache.fop.messaging.*;  // for MessageHandler
0134  import com.oreilly.servlet.multipart.*; // for FilePart, MultipartParser,
0135                                          // ParamPart, Part
0136 
0137 
0138 public class NeumesXSLTServlet extends HttpServlet {
0139   public static final String copyright =
0140     "Copyright 2003-2006 by Louis W. G. Barton.\n"
0141     + "Copyright 2002 by the President and Fellows of Harvard College;\n"
0142     + "contains software or other intellectual property licensed from "
0143     + "Louis W. G. Barton,\n copyright 1995-2001 by Louis W. G. Barton.\n"
0144     + "e-mail: louis.barton.je.77@aya.yale.edu.\n";
0145 
0146   // Flag indicating where ther servlet is installed:
0147   static final int SCRIBE = 0;  // Scribe server
0148   static final int MUSITECH = 1;
0149   static final int LOUIS = 2;  // laptop computer, loop-back
0150   static final int TILLMAN = 3;
0151   static final int LOCATION = SCRIBE;
0152 
0153   // Maximum size constraint on uploaded NeumesXML file is to protect server
0154   // (size of a NeumesXML file is expected typically around 10kB):
0155   private final int MAXLENGTH = 0x80000;  // = 524,288 bytes (decimal)
0156 
0157   // Output format:
0158   static final int HTML_OUT = 0;
0159   static final int PDF_OUT = 1;
0160   private int outputType;  // the requested format for output
0161   // Test mode:
0162   private boolean testing = false;  // for non-production testing
0163 
0164   // Transcription file locations:
0165   private String default_infilepath;  // default transcription
0166   private String xslt_filepath;  // normal stylesheet
0167   private String xslFO_filepath;  // Formating Objects stylesheet
0168   private String xslt_filepath_testing;  // stylesheet, testing
0169   private String xslFO_filepath_testing;  // formating objects, testing
0170   private URL xslFileURL;  // address of the XSLT file
0171 
0172 
0173   /**
0174    * constructor
0175    *
0176    */
0177   public NeumesXSLTServlet() {
0178   }  //end, constructor
0179 
0180   /**
0181    * init()
0182    *
0183    */
0184   public final void init(ServletConfig config) throws ServletException {
0185     super.init(config); // super must be called
0186   } //end, init()
0187 
0188   /**
0189    * setURLs()
0190    *
0191    * Selects filepaths depending on the platform being used in production/debug.
0192    */
0193   private final void setURLs(int choice) {
0194     switch (choice) {
0195       case MUSITECH :
0196         default_infilepath =
0197           "http://musitech.fmt.uni-osnabrueck.de:8080/neumes/NeumesExample.xml";
0198         // XSLT files:
0199         xslt_filepath =
0200           "http://musitech.fmt.uni-osnabrueck.de:8080/neumes/NeumesXSL.xsl";
0201         xslFO_filepath =
0202           "http://musitech.fmt.uni-osnabrueck.de:8080/neumes/neumesFO.xsl";
0203         break;
0204       case LOUIS :
0205         // For use on laptop computer w/ Personal Web Server and loopback URL:
0206         default_infilepath =
0207         "file:/D:/inetpub/wwwroot/NEUMES/xml/transcriptions/NeumesExample.xml";
0208         xslt_filepath =
0209           "file:/D:/inetpub/wwwroot/NEUMES/xml/NeumesXML.xsl";
0210         xslFO_filepath =
0211           "file:/D:/inetpub/wwwroot/NEUMES/xml/NeumesXML_FO.xsl";
0212         break;
0213       case TILLMAN :
0214         default_infilepath =
0215           "file:///C:/EigeneDateien/neumes/NeumesXML/NeumesExample.xml";
0216         xslt_filepath =
0217           "file:///C:/EigeneDateien/neumes/NeumesXML/NeumesXML.xsl";
0218         xslFO_filepath =
0219           "file:///C:/EigeneDateien/neumes/NeumesXML/neumesFO.xsl";
0220         break;
0221       case SCRIBE :
0222       default :
0223         // Default transcription file:
0224         default_infilepath =
0225             "http://purl.oclc.org/NEUMES/ref/transcriptions/NeumesExample.xml";
0226         // XSLT files:
0227         xslt_filepath = "http://purl.oclc.org/NEUMES/ref/NeumesXML.xsl";
0228         xslFO_filepath = "http://purl.oclc.org/NEUMES/ref/NeumesXML_FO.xsl";
0229         // XSLT files for testing:
0230         xslt_filepath_testing =
0231               "http://www.scribeserver.com/NEUMES/xml/test/NeumesXML.xsl";
0232         xslFO_filepath_testing =
0233               "http://www.scribeserver.com/NEUMES/xml/test/NeumesXML_FO.xsl";
0234         break;
0235     }  //end, switch
0236   }  //end, setURLs()
0237 
0238   /**
0239    * doGet()
0240    *
0241    * doGet Responds to HTTP GET requests from browsers.
0242    * For processing a NeumesXML file of which client sends the file's URL.
0243    * Results of the XSLT transformation are pushed back to client.
0244    * If no filename is sent, then use the default example file.
0245    */
0246   public final void doGet(HttpServletRequest req, HttpServletResponse res)
0247         throws MalformedURLException, IOException, ServletException {
0248     setURLs(LOCATION);  // choose between production and debug mode
0249     String inFilepath = null;  // filepath of the input NeumesXML file
0250     String inDisplayMode = null;  // display mode for visualization
0251     URL inFileURL = null;  // URL of the NeumesXML file
0252     Source xmlSource = null;  // for Xalan
0253     Source xslSource = null;  // for Xalan
0254 
0255     res.setContentType("text/html; charset=UTF-8");
0256     // Output goes to the response PrintWriter:
0257     PrintStream out = new PrintStream(res.getOutputStream());
0258 //Debug:  printParameters(req, out);  // show the GET request parameter list
0259 
0260     // Get URL of input NeumesXML file:
0261     try {
0262       inFilepath = req.getParameter("filepath");
0263       if (inFilepath == null) {
0264         inFilepath = default_infilepath;
0265       } //end, if
0266       inFileURL = new URL(inFilepath);
0267     } catch (Exception e) {
0268       printErrorAndClose(out, "Invalid NeumesXML filepath specified.", e);
0269       return;
0270     } //end, try/catch, input file URL
0271 
0272     // Get display mode:
0273     try {
0274       inDisplayMode = req.getParameter("testing");
0275 //Debug:  out.println("inDisplayMode, testing = '" + inDisplayMode + "'.<BR>");
0276       if (inDisplayMode == null) {
0277         testing = false;
0278       } else if (inDisplayMode.equalsIgnoreCase("true")) {
0279         testing = true;
0280       } else {
0281         testing = false;
0282       }  //end, if testing
0283 
0284       inDisplayMode = req.getParameter("format");
0285 //Debug:  out.println("inDisplayMode, format = '" + inDisplayMode + "'.<BR>");
0286       if (inDisplayMode == null) {
0287         outputType = HTML_OUT;
0288       } else if (inDisplayMode.equalsIgnoreCase("pdf")) {
0289         outputType = PDF_OUT;
0290       } else {
0291         outputType = HTML_OUT;
0292       }  //end, if format
0293     } catch (Exception e) {
0294       printErrorAndClose(out,
0295            "Unable to read parameter(s) of servlet GET call.", e);
0296       return;
0297     } //end, try/catch, display mode
0298 
0299     // Get URL of the appropriate XSL Transformation file:
0300     try {
0301       if (testing == true) {
0302         if (outputType == PDF_OUT) {
0303           xslFileURL = new URL(xslFO_filepath_testing);
0304         } else {
0305           xslFileURL = new URL(xslt_filepath_testing);
0306         }  //end, if PDF
0307       }  //end, if testing
0308       else {
0309         if (outputType == PDF_OUT) {
0310           xslFileURL = new URL(xslFO_filepath);
0311         } else {
0312           xslFileURL = new URL(xslt_filepath);
0313         }  //end, if PDF
0314       }  //end, if not testing
0315     } catch (Exception e) {
0316       printErrorAndClose(out, "Unable to get URL of XSLT file.", e);
0317       return;
0318     } //end, try,catch, XSLT URL
0319 
0320 //Debug:  out.println("Got Transformation URL.<BR/>");
0321 
0322     try {
0323       TransformerFactory tFactory = TransformerFactory.newInstance();
0324       // Get the NeumesXML input document:
0325       xmlSource = new StreamSource(inFileURL.openStream());
0326 //Debug:  out.println("Got inFile Stream.<BR/>");
0327       // Get the stylesheet:
0328       xslSource = new StreamSource(xslFileURL.openStream());
0329 //Debug:  out.println("Got the Stylesheet.<BR/>");
0330       // Generate the transformer:
0331       Transformer transformer = tFactory.newTransformer(xslSource);
0332       // Perform the transformation, sending the output to the response:
0333       transformer.transform(xmlSource, new StreamResult(out));
0334     } catch (Exception e) {
0335       printErrorAndClose(out, "NeumesXML XSLT transformation Exception.<BR>", e);
0336       return;
0337     } //end, try/catch
0338 
0339     out.close();
0340   }  //end, doGet()
0341 
0342   /**
0343    * doPost()
0344    *
0345    * Responds to HTTP POST requests from browsers.
0346    * For uploading a NeumesXML file to be processed here.
0347    * Results of the XSLT transformation are delivered back to client.
0348    *
0349    * @see javax.servlet.http.HttpServlet#doPost(
0350    *   javax.servlet.http.HttpServletRequest,
0351    *   javax.servlet.http.HttpServletResponse)
0352    */
0353   public final void doPost(HttpServletRequest req, HttpServletResponse res)
0354         throws IOException, ServletException {
0355     int length;  // length of the uploaded file
0356     int filePartCount = 0;  // number of fileParts read
0357     char fileData[] = null;  // the updloaded file's data
0358     Source xmlSource = null;  // the NeumesXML source document
0359     Source xslSource = null;  // the NeumesXML transformation document
0360     MultipartParser mp = null;  // multipart parser (new)
0361     Part part;  // temp, part of the multipart
0362     String partName;  // temp, name of the part
0363     Hashtable parameters = new Hashtable();  // Parameters. A clean hashtable
0364     Vector comVals;  // Vector of parameter values
0365 
0366     setURLs(LOCATION);  // choose between production and debug mode
0367     res.setContentType("text/html; charset=UTF-8");
0368     // Output goes to the response PrintWriter:
0369     PrintStream out = new PrintStream(res.getOutputStream());
0370     length = req.getContentLength();
0371     // fileData[0] = 'a';
0372     if (length > MAXLENGTH) {
0373       printErrorAndClose(out,
0374                          "Uploaded file exceeds maximum allowed filesize of "
0375                          + MAXLENGTH + " bytes.");
0376         out.close();
0377         return;
0378     }  //end, if > MAXLENGTH
0379 
0380 /*Debug:
0381 Display information about this HTTP request:
0382 out.write("Content type = '" + req.getContentType() + "'.<BR/>");
0383 out.write("Character encoding is = " + req.getCharacterEncoding() + "<BR/>");
0384 out.write("<BR/>Query string = '" + req.getHeader("QUERY_STRING") + "'<BR/>");
0385 out.write("Uploaded file length = " + length + "<BR/>");
0386 Enumeration attribnames = req.getAttributeNames();
0387 out.write("<BR/>Attribute Names:<BR/>");
0388 while(attribnames.hasMoreElements()) {
0389   out.write("Attribute Name: '" + attribnames.nextElement() + "'<BR/>");
0390 }  //end, while
0391 out.write("==END==<BR/>");
0392 printParameters(req, out);  // local method: display the Parameter list
0393 [end, Debug] */
0394 
0395     // Catch runtime exceptions while reading multipart messages:
0396     try {
0397       String contentType = req.getContentType();
0398       if (contentType.equals("application/x-java-serialized-object")) {
0399         String fileString;
0400         try {
0401           ObjectInputStream ois = new ObjectInputStream(req.getInputStream());
0402           fileString = (String) ois.readObject();
0403         } catch (Exception e) {
0404           printErrorAndClose(out, "Could not deserialize Java String object.");
0405           return;
0406         } // end try/catch
0407         fileData = fileString.toCharArray();
0408         comVals = new Vector(1);
0409         comVals.add(req.getHeader("com"));
0410       }  //end, if Java coded data
0411       else {
0412         // not a coded Java object; should be MultiPart, then get the parser:
0413         try {
0414           mp = new MultipartParser(req, MAXLENGTH); // maxlength is settable
0415         } catch (IOException e) {
0416           out.print("This servlet's POST method can only be used with " +
0417                     "multipart encoding.");
0418           out.close();
0419           return;
0420         }  //end, try/catch, new MultipartParser
0421 
0422         // read all parts of the multipart message:
0423         while ((part = mp.readNextPart()) != null) {
0424           partName = part.getName();
0425           if (part.isParam()) {
0426             // It's a parameter part:
0427             ParamPart paramPart = (ParamPart) part;
0428             String paramValue = paramPart.getStringValue();
0429 /*Debug:
0430             out.println("<BR>Parameter name = '" + partName +
0431                         "', value = '" + paramValue + "'.");
0432  */
0433 
0434             // Store any query parameters in a Hashtable:
0435             if (parameters.get(partName) == null) {
0436               Vector vec = new Vector();
0437               vec.add(paramValue);
0438               parameters.put(partName, vec);
0439             } else {
0440               Vector vec = (Vector) parameters.get(partName);
0441               vec.add(paramValue);
0442             } //end, if/else, add to hashtable
0443 
0444           } else if (part.isFile()) {
0445             // It's a file part:
0446             filePartCount++;
0447             // Was more than one file sent?
0448             if (filePartCount > 1) {
0449               // If so, then this is an error
0450               break;  // break the multipart loop
0451             } // end if filepartcount > 1
0452             FilePart filePart = (FilePart) part;
0453             // Get the NeumesXML input document:
0454             // create Writer and Reader:
0455             CharArrayWriter writer = new CharArrayWriter();
0456             Reader reader = new InputStreamReader(filePart.getInputStream());
0457             int numChar;
0458             // get that data
0459             char readBuffer[] = new char[512];  // Q: Assumption? (declare it)
0460             while ((numChar = reader.read(readBuffer)) != -1) {
0461               writer.write(readBuffer, 0, numChar);
0462             }
0463             reader.close();
0464             writer.close();
0465             // Save the data as a char array:
0466             fileData = writer.toCharArray();
0467           } //end, if/else part is Param or File
0468         } //end, while more parts
0469 
0470         // Verify the correct request parameters for file upload:
0471         comVals = (Vector) parameters.get("com");
0472 
0473         // Check the file out of the multiple parts:
0474         if (filePartCount > 1) {
0475           out.print("Only one upload file may be transmitted.");
0476           out.close();
0477           return;
0478         }
0479         if (filePartCount < 1) {
0480           printErrorAndClose(out, "No upload file received.");
0481           return;
0482         } //end, if
0483         // file param ok if we got here
0484       }  //end, if/else Multipart
0485 
0486       // Error checking:
0487       if (comVals == null) {
0488         printErrorAndClose(out, "Missing required 'com' parameter in HTTP "
0489                            + "POST request.");
0490         return;
0491       } //end, if no com parameter
0492       if (comVals.size() > 1) {
0493         printErrorAndClose(out,
0494           "'com' parameter in HTTP POST request must only have one value.");
0495         return;
0496       }
0497       String com = (String) comVals.get(0);
0498       if (com.equalsIgnoreCase("transfer_upload")) {
0499         outputType = HTML_OUT;
0500       } else if (com.equalsIgnoreCase("transfer_upload_pdf")) {
0501         outputType = PDF_OUT;
0502       } //end, if mutliple com parameters
0503       else {
0504         printErrorAndClose(out, "Invalid com parameter value in HTTP POST "
0505              + "request. Only 'transfer_upload' and 'transfer_upload:pdf' are "
0506              + "allowed.");
0507         return;
0508       } //end, if not transfer_upload
0509       // com parameter is ok if we got here.
0510 
0511       // xmlSource = new StreamSource(tempFile);
0512       xmlSource = new StreamSource(new CharArrayReader(fileData));
0513 
0514       if (outputType == PDF_OUT) {
0515         xslFileURL = new URL(xslFO_filepath);
0516         // Construct driver:
0517         Driver driver = new Driver();
0518 
0519         // Setup logger:
0520         Logger logger = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
0521         driver.setLogger(logger);
0522         MessageHandler.setScreenLogger(logger);
0523 
0524         // Setup Renderer (output format):
0525         driver.setRenderer(Driver.RENDER_PDF);
0526 
0527         // Setup output:
0528         try {
0529           driver.setOutputStream(out);
0530 
0531           // Setup XSLT:
0532           TransformerFactory factory = TransformerFactory.newInstance();
0533           Transformer transformer =
0534             factory.newTransformer(new StreamSource(xslFileURL.openStream()));
0535 
0536           // Setup input for XSLT transformation:
0537           Source src = new StreamSource(new CharArrayReader(fileData));
0538 
0539           // Resulting SAX events (the generated FO) must be piped to FOP:
0540           Result result = new SAXResult(driver.getContentHandler());
0541           res.setContentType("application/pdf");
0542 
0543           // Start XSLT transformation and FOP processing:
0544           transformer.transform(src, result);
0545         } catch (Exception e) {
0546           printErrorAndClose(out, "PDF creation failed", e);
0547         } // end try/catch
0548         out.close(); // close flushes automatically
0549         return;
0550       }  //end, if PDF
0551 
0552       // Get URL of the XSLT transformation file:
0553       try {
0554         if (outputType == PDF_OUT) {
0555           xslFileURL = new URL(xslFO_filepath);
0556         } else if (outputType == HTML_OUT) {
0557           xslFileURL = new URL(xslt_filepath);
0558         }
0559       } catch (Exception e) {
0560         out.print("Unable to get URL of XSLT file.");
0561         out.close();
0562         return;
0563       } //end, try,catch, XSLT URL
0564 //Debug: System.out.println("Getting Factory.");
0565 
0566       // The Transformer Factory
0567       TransformerFactory tFactory = TransformerFactory.newInstance();
0568       if (tFactory == null) {
0569         printErrorAndClose(out,
0570                   "Could not get an instance of TransformerFactory.");
0571         return;
0572       }  //end, if
0573 
0574       // Get the XSLT stylesheet:
0575       xslSource = new StreamSource(xslFileURL.openStream());
0576 //Debug: System.out.println("got the xsl file");
0577 
0578       // Generate the transformer:
0579       Transformer transformer = tFactory.newTransformer(xslSource);
0580 //Debug: System.out.println("before transform");
0581       // Perform the transformation, pushing the output to the client:
0582       transformer.transform(xmlSource, new StreamResult(out));
0583       // client needs not wait for cleaning up
0584 
0585     } catch (Exception e) {
0586       printErrorAndClose(out,
0587         "NeumesXML XSLT transformation Exception. Unable to proceed.<BR>", e);
0588       return;
0589     } //end, try/catch, multipart
0590     out.close(); // close flushes automatically
0591   }  //end, doPost()
0592 
0593   /**
0594    * renderXML()
0595    *
0596    * Renders an XML file into a PDF file by applying a stylesheet
0597    * that converts the XML to XSL:FO. The PDF is written
0598    * directly to the response object's OutputStream
0599    */
0600   public final void renderXML(XSLTInputHandler input,
0601     HttpServletResponse response) throws ServletException {
0602     //      if (log == null) {
0603     //        log = new ConsoleLogger(ConsoleLogger.LEVEL_WARN);
0604     //        MessageHandler.setScreenLogger(log);
0605     //      }
0606     //      try {
0607     //        ByteArrayOutputStream out = new ByteArrayOutputStream();
0608     //        Driver driver = new Driver();
0609     //        driver.setRenderer(Driver.RENDER_PDF);
0610     //        driver.setOutputStream(out);
0611     //        XMLReader parser = input.getParser();
0612     //        driver.render(parser, input.getInputSource());
0613     //        response.setContentType("application/pdf");
0614     //        byte[] content = out.toByteArray();
0615     //        response.setContentLength(content.length);
0616     //        response.getOutputStream().write(content);
0617     //        response.getOutputStream().flush();
0618     //      } catch (Exception ex) {
0619     //        throw new ServletException(ex);
0620     //      }
0621   }  //end, renderXML()
0622 
0623   /**
0624    * printErrorAndClose()
0625    *
0626    * Print an error message in HTML format and
0627    * close the stream.
0628    * @param out The PrintWriter to write to.
0629    * @param errMsg The errMsg to print.
0630    */
0631   private final void printErrorAndClose(PrintStream out, String errMsg) {
0632     printErrorAndClose(out, errMsg, null,
0633       "An error occured in NEUMES XSLT servlet, process terminated.");
0634   }  //end, printErrorAndClose()
0635 
0636   /**
0637    * printErrorAndClose(Exception)
0638    *
0639    * Print an error message in HTML format and
0640    * close the stream.
0641    * @param out The PrintWriter to write to.
0642    * @param errMsg The errMsg to print.
0643    * @param e The Ecxception causing the error.
0644    */
0645   private final void printErrorAndClose(PrintStream out, String errMsg,
0646     Exception e) {
0647     printErrorAndClose(out, errMsg, e,
0648       "An error occured in NEUMES XSLT servlet, process terminated.");
0649   }  //end, printErrorAndClose(Exception)
0650 
0651   /**
0652    * printErrorAndClose(errTitle)
0653    *
0654    * Print an error message in HTML format and close the writer.
0655    * @param out The PrintWriter to write to.
0656    * @param errMsg The errMsg to print.
0657    * @param e The Ecxception causing the error.
0658    * @param errTitle The title for the message.
0659    */
0660   private final void printErrorAndClose(PrintStream out, String errMsg,
0661         Exception e, String errTitle) {
0662     if (errMsg != null) {
0663       out.println("<HTML>");
0664       out.println("<HEAD>");
0665       out.println("<meta " +
0666         "http-equiv='content-type' content='text/html; charset=ISO-8859-1'>" +
0667         "</HEAD>");
0668       out.println("<TITLE>");
0669       out.println(errTitle);
0670       out.println("</TITLE>");
0671       out.println("<BODY>");
0672       out.println("<H2>" + errTitle + "</H2>\n<BR>Reason: ");
0673       out.println(errMsg);
0674       if (e != null) {
0675         out.println("MSG: " + e.getMessage() + "<BR>");
0676         out.println("STR: " + e.toString() + "<BR>");
0677         out.println("<BR><PRE>");
0678         e.printStackTrace(out);
0679         out.println("</PRE><BR>");
0680       }
0681       out.println("</BODY>");
0682       out.println("</HTML>");
0683     }  //end, non-null error
0684     out.close();
0685   }  //end, printErrorAndClose(errTitle)
0686 
0687   /**
0688    * printParameters()
0689    *
0690    * For debugging: Displays a TABLE with the parameter names and their values.
0691    * @param request The request to process.
0692    * @param out The PrintWriter to write to.
0693    */
0694   private final void printParameters(HttpServletRequest request,
0695         PrintStream out) {
0696     Enumeration paramNames; // parameter names
0697     String paramName; // temp holder for parameter name
0698     String[] paramValues; // temp, values of the parameter
0699     int i; // temp index
0700 
0701     // Make an HTML TABLE:
0702     out.println(
0703       "<TABLE BORDER=1 ALIGN=CENTER>\n"
0704         + "<TR BGCOLOR="#FFAD00">\n"
0705         + "<TH>Parameter Name</TH><TH>Parameter Value(s)</TH>");
0706     paramNames = request.getParameterNames();
0707     while (paramNames.hasMoreElements()) {
0708       paramName = (String) paramNames.nextElement();
0709       out.println("<TR><TD>" + paramName + "</TD>\n<TD>");
0710       paramValues = request.getParameterValues(paramName);
0711       if (paramValues.length == 1) {
0712         String paramValue = paramValues[0];
0713         if (paramValue.length() == 0) {
0714           out.print("<I>No Value</I>");
0715         } else {
0716           out.print(paramValue);
0717         } //end, if/else (paramValue.length)
0718       } else {
0719         out.println("<UL>");
0720         for (i = 0; i < paramValues.length; i++) {
0721           out.println("<LI>" + paramValues[i]);
0722         } //end, for (i)
0723         out.println("</UL>");
0724       } //end, if/else
0725       out.println("</TD></TR>");
0726     } //end, while
0727     out.println("</TABLE><BR clear='left'/>");
0728   }  //end, printParameters()
0729 
0730 } //end, class NeumesXSLTServlet
0731 //end, NeumesXSLTServlet.java
= END LISTING =