Changeset 25613

Show
Ignore:
Timestamp:
16.05.2012 20:04:02 (7 years ago)
Author:
ak19
Message:

The formatting changes in 25602 and 25603 undone so that actual differences between earlier versions (revision 25501) become clear

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/XMLTransformer.java

    r25604 r25613  
    5858import org.apache.log4j.*; 
    5959 
    60 /** 
    61  * XMLTransformer - utility class for greenstone 
    62  *  
     60/** XMLTransformer - utility class for greenstone 
     61 * 
    6362 * transforms xml using xslt 
    64  *  
     63 * 
    6564 * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a> 
    6665 * @version $Revision$ 
    6766 */ 
    68 public class XMLTransformer 
    69 { 
    70     private static int debugFileCount = 0; // for unique filenames when debugging XML transformations with physical files 
    71  
    72     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.XMLTransformer.class.getName()); 
    73  
    74     /** The transformer factory we're using */ 
    75     TransformerFactory t_factory = null; 
    76  
    77     /** 
    78      * The no-arguments constructor. 
    79      *  
    80      * Any exceptions thrown are caught internally 
    81      *  
    82      * @see javax.xml.transform.TransformerFactory 
    83      */ 
    84     public XMLTransformer() 
    85     { 
    86         // http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/api/index.html?javax/xml/transform/TransformerFactory.html states that 
    87         // TransformerFactory.newInstance() looks in jar files for a Factory specified in META-INF/services/javax.xml.transform.TransformerFactory,  
    88         // else it will use the "platform default" 
    89         // In this case: xalan.jar's META-INF/services/javax.xml.transform.TransformerFactory contains org.apache.xalan.processor.TransformerFactoryImpl 
    90         // as required. 
    91  
    92         // This means we no longer have to do a System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl"); 
    93         // followed by a this.t_factory = org.apache.xalan.processor.TransformerFactoryImpl.newInstance(); 
    94         // The System.setProperty step to force the TransformerFactory implementation that gets used, conflicts with 
    95         // Fedora (visiting the Greenstone server pages breaks the Greenstone-tomcat hosted Fedora pages) as Fedora  
    96         // does not include the xalan.jar and therefore can't then find the xalan TransformerFactory explicitly set. 
    97  
    98         // Gone back to forcing use of xalan transformer, since other jars like crimson.jar, which may be on some 
    99         // classpaths, could be be chosen as the TransformerFactory implementation over xalan. This is what used to 
    100         // give problems before. Instead, have placed copies of the jars that Fedora needs (xalan.jar and serializer.jar  
    101         // and the related xsltc.jar which it may need) into packages/tomcat/lib so that it's on the server's classpath 
    102         // and will be found by Fedora. 
    103  
    104         // make sure we are using the xalan transformer 
    105         System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl"); 
    106         try 
    107         { 
    108             this.t_factory = org.apache.xalan.processor.TransformerFactoryImpl.newInstance(); 
    109             //this.t_factory = TransformerFactory.newInstance(); 
    110             this.t_factory.setErrorListener(new TransformErrorListener()); // handle errors in the xml Source used to instantiate transformers 
    111         } 
    112         catch (Exception e) 
    113         { 
    114             logger.error("exception creating t_factory " + e.getMessage()); 
    115         } 
     67public class XMLTransformer { 
     68    private static int debugFileCount = 0; // for unique filenames when debugging XML transformations with physical files 
     69 
     70    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.XMLTransformer.class.getName()); 
     71     
     72  /** The transformer factory we're using */ 
     73    TransformerFactory t_factory=null; 
     74   
     75  /** 
     76   * The no-arguments constructor.  
     77   * 
     78   * Any exceptions thrown are caught internally 
     79   *  
     80   * @see javax.xml.transform.TransformerFactory 
     81   */ 
     82    public XMLTransformer() { 
     83    // http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/api/index.html?javax/xml/transform/TransformerFactory.html states that 
     84    // TransformerFactory.newInstance() looks in jar files for a Factory specified in META-INF/services/javax.xml.transform.TransformerFactory,  
     85    // else it will use the "platform default" 
     86    // In this case: xalan.jar's META-INF/services/javax.xml.transform.TransformerFactory contains org.apache.xalan.processor.TransformerFactoryImpl 
     87    // as required. 
     88 
     89    // This means we no longer have to do a System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl"); 
     90    // followed by a this.t_factory = org.apache.xalan.processor.TransformerFactoryImpl.newInstance(); 
     91    // The System.setProperty step to force the TransformerFactory implementation that gets used, conflicts with 
     92    // Fedora (visiting the Greenstone server pages breaks the Greenstone-tomcat hosted Fedora pages) as Fedora  
     93    // does not include the xalan.jar and therefore can't then find the xalan TransformerFactory explicitly set. 
     94 
     95    // Gone back to forcing use of xalan transformer, since other jars like crimson.jar, which may be on some 
     96    // classpaths, could be be chosen as the TransformerFactory implementation over xalan. This is what used to 
     97    // give problems before. Instead, have placed copies of the jars that Fedora needs (xalan.jar and serializer.jar  
     98    // and the related xsltc.jar which it may need) into packages/tomcat/lib so that it's on the server's classpath 
     99    // and will be found by Fedora. 
     100 
     101    // make sure we are using the xalan transformer 
     102    System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl"); 
     103    try { 
     104        this.t_factory = org.apache.xalan.processor.TransformerFactoryImpl.newInstance(); 
     105        //this.t_factory = TransformerFactory.newInstance(); 
     106        this.t_factory.setErrorListener(new TransformErrorListener()); // handle errors in the xml Source used to instantiate transformers 
     107    } catch (Exception e) { 
     108        logger.error("exception creating t_factory "+e.getMessage()); 
    116109    } 
    117  
    118     /** 
    119      * Transform an XML document using a XSLT stylesheet 
    120      *  
    121      * @param stylesheet 
    122      *            a filename for an XSLT stylesheet 
    123      * @param xml_in 
    124      *            the XML to be transformed 
    125      * @return the transformed XML 
    126      */ 
    127     public String transform(String stylesheet, String xml_in) 
    128     { 
    129  
    130         try 
    131         { 
    132             TransformErrorListener transformerErrorListener = (TransformErrorListener) this.t_factory.getErrorListener(); 
    133             transformerErrorListener.setStylesheet(stylesheet); 
    134             // Use the TransformerFactory to process the stylesheet Source and generate a Transformer. 
    135             Transformer transformer = this.t_factory.newTransformer(new StreamSource(stylesheet)); 
    136  
    137             // Use the Transformer to transform an XML Source and send the output to a Result object. 
    138             StringWriter output = new StringWriter(); 
    139             StreamSource streamSource = new StreamSource(new StringReader(xml_in)); 
    140             transformer.setErrorListener(new TransformErrorListener(stylesheet, streamSource)); 
    141             transformer.transform(streamSource, new StreamResult(output)); 
    142             return output.toString(); 
    143         } 
    144         catch (TransformerConfigurationException e) 
    145         { 
    146             logger.error("couldn't create transformer object: " + e.getMessageAndLocation()); 
    147             logger.error(e.getLocationAsString()); 
    148             return ""; 
    149         } 
    150         catch (TransformerException e) 
    151         { 
    152             logger.error("couldn't transform the source: " + e.getMessageAndLocation()); 
    153             return ""; 
    154         } 
     110    } 
     111     
     112  /** 
     113   * Transform an XML document using a XSLT stylesheet 
     114   *  
     115   * @param stylesheet a filename for an XSLT stylesheet 
     116   * @param xml_in the XML to be transformed 
     117   * @return the transformed XML 
     118   */ 
     119    public String transform(String stylesheet, String xml_in) { 
     120     
     121    try { 
     122        TransformErrorListener transformerErrorListener = (TransformErrorListener) this.t_factory.getErrorListener(); 
     123        transformerErrorListener.setStylesheet(stylesheet); 
     124        // Use the TransformerFactory to process the stylesheet Source and generate a Transformer. 
     125        Transformer transformer = this.t_factory.newTransformer(new StreamSource(stylesheet)); 
     126 
     127        // Use the Transformer to transform an XML Source and send the output to a Result object. 
     128        StringWriter output = new StringWriter(); 
     129        StreamSource streamSource = new StreamSource(new StringReader(xml_in)); 
     130        transformer.setErrorListener(new TransformErrorListener(stylesheet, streamSource)); 
     131        transformer.transform(streamSource, new StreamResult(output)); 
     132        return output.toString(); 
     133    } catch (TransformerConfigurationException e) { 
     134        logger.error("couldn't create transformer object: "+e.getMessageAndLocation()); 
     135        logger.error(e.getLocationAsString());   
     136        return ""; 
     137    } catch (TransformerException e) { 
     138        logger.error("couldn't transform the source: " + e.getMessageAndLocation()); 
     139        return ""; 
     140    }    
     141    } 
     142 
     143    public String transformToString(Document stylesheet, Document source) { 
     144    return transformToString(stylesheet, source, null); 
     145    } 
     146     
     147    public String transformToString(Document stylesheet, Document source, HashMap parameters) { 
     148     
     149    try { 
     150        TransformErrorListener transformerErrorListener = (TransformErrorListener) this.t_factory.getErrorListener(); 
     151        transformerErrorListener.setStylesheet(stylesheet); 
     152        // Use the TransformerFactory to process the stylesheet Source and generate a Transformer. 
     153        Transformer transformer = this.t_factory.newTransformer(new DOMSource(stylesheet)); 
     154        if (parameters != null) { 
     155        Set params = parameters.entrySet(); 
     156        Iterator i = params.iterator(); 
     157        while (i.hasNext()) { 
     158            Map.Entry m = (Map.Entry)i.next(); 
     159            transformer.setParameter((String)m.getKey(), m.getValue()); 
     160        } 
     161        } 
     162        //transformer.setParameter("page_lang", source.getDocumentElement().getAttribute(GSXML.LANG_ATT)); 
     163 
     164        // Use the Transformer to transform an XML Source and send the output to a Result object. 
     165        StringWriter output = new StringWriter(); 
     166        DOMSource domSource = new DOMSource(source); 
     167 
     168        transformer.setErrorListener(new TransformErrorListener(stylesheet, domSource)); 
     169        transformer.transform(domSource, new StreamResult(output)); 
     170        return output.toString(); 
     171    } catch (TransformerConfigurationException e) { 
     172        logger.error("couldn't create transformer object: "+e.getMessageAndLocation()); 
     173        logger.error(e.getLocationAsString());   
     174        return ""; 
     175    } catch (TransformerException e) { 
     176        logger.error("couldn't transform the source: " + e.getMessageAndLocation()); 
     177        return ""; 
    155178    } 
    156  
    157     public String transformToString(Document stylesheet, Document source) 
    158     { 
    159         return transformToString(stylesheet, source, null); 
    160     } 
    161  
    162     public String transformToString(Document stylesheet, Document source, HashMap parameters) 
    163     { 
    164  
    165         try 
    166         { 
    167             TransformErrorListener transformerErrorListener = (TransformErrorListener) this.t_factory.getErrorListener(); 
    168             transformerErrorListener.setStylesheet(stylesheet); 
    169             // Use the TransformerFactory to process the stylesheet Source and generate a Transformer. 
    170             Transformer transformer = this.t_factory.newTransformer(new DOMSource(stylesheet)); 
    171             if (parameters != null) 
    172             { 
    173                 Set params = parameters.entrySet(); 
    174                 Iterator i = params.iterator(); 
    175                 while (i.hasNext()) 
    176                 { 
    177                     Map.Entry m = (Map.Entry) i.next(); 
    178                     transformer.setParameter((String) m.getKey(), m.getValue()); 
    179                 } 
    180             } 
    181             //transformer.setParameter("page_lang", source.getDocumentElement().getAttribute(GSXML.LANG_ATT)); 
    182  
    183             // Use the Transformer to transform an XML Source and send the output to a Result object. 
    184             StringWriter output = new StringWriter(); 
    185             DOMSource domSource = new DOMSource(source); 
    186  
    187             transformer.setErrorListener(new TransformErrorListener(stylesheet, domSource)); 
    188             transformer.transform(domSource, new StreamResult(output)); 
    189             return output.toString(); 
    190         } 
    191         catch (TransformerConfigurationException e) 
    192         { 
    193             logger.error("couldn't create transformer object: " + e.getMessageAndLocation()); 
    194             logger.error(e.getLocationAsString()); 
    195             return ""; 
    196         } 
    197         catch (TransformerException e) 
    198         { 
    199             logger.error("couldn't transform the source: " + e.getMessageAndLocation()); 
    200             return ""; 
    201         } 
    202     } 
     179    } 
    203180 
    204181    /** 
     
    206183     * whose node should be set to the Document donated by resultNode 
    207184     */ 
    208     public Node transform_withResultNode(Document stylesheet, Document source, Document resultNode) 
    209     { 
    210         return transform(stylesheet, source, null, null, resultNode); 
    211     } 
    212  
    213     public Node transform(Document stylesheet, Document source) 
    214     { 
    215         return transform(stylesheet, source, null, null, null); 
    216     } 
    217  
    218     public Node transform(Document stylesheet, Document source, HashMap parameters) 
    219     { 
    220         return transform(stylesheet, source, parameters, null, null); 
    221     } 
    222  
    223     public Node transform(Document stylesheet, Document source, HashMap parameters, Document docDocType) 
    224     { 
    225         return transform(stylesheet, source, parameters, docDocType, null); 
    226     } 
    227  
    228     protected Node transform(Document stylesheet, Document source, HashMap parameters, Document docDocType, Document resultNode) 
    229     { 
    230         try 
    231         { 
     185    public Node transform_withResultNode(Document stylesheet, Document source, Document resultNode) { 
     186        return transform(stylesheet, source, null, null, resultNode); 
     187    } 
     188 
     189    public Node transform(Document stylesheet, Document source) { 
     190        return transform(stylesheet, source, null, null, null); 
     191    } 
     192     
     193    public Node transform(Document stylesheet, Document source, HashMap parameters) { 
     194        return transform(stylesheet, source, parameters, null, null); 
     195    } 
     196 
     197    public Node transform(Document stylesheet, Document source, HashMap parameters, Document docDocType) { 
     198    return transform(stylesheet, source, parameters, docDocType, null); 
     199    } 
     200 
     201    protected Node transform(Document stylesheet, Document source, HashMap parameters, Document docDocType, Document resultNode) { 
     202        try { 
    232203            // Use the TransformerFactory to process the stylesheet Source and generate a Transformer. 
    233204            TransformErrorListener transformerErrorListener = (TransformErrorListener) this.t_factory.getErrorListener(); 
    234205            transformerErrorListener.setStylesheet(stylesheet); 
    235206            Transformer transformer = this.t_factory.newTransformer(new DOMSource(stylesheet)); 
    236  
    237             //logger.info("XMLTransformer transformer is " + transformer); //done in ErrorListener 
    238             if (parameters != null) 
    239             { 
     207            //logger.info("XMLTransformer transformer is " + transformer); //done in ErrorListener 
     208             
     209            if (parameters != null) { 
    240210                Set params = parameters.entrySet(); 
    241211                Iterator i = params.iterator(); 
    242                 while (i.hasNext()) 
    243                 { 
    244                     Map.Entry m = (Map.Entry) i.next(); 
    245                     transformer.setParameter((String) m.getKey(), m.getValue()); 
     212                while (i.hasNext()) { 
     213                    Map.Entry m = (Map.Entry)i.next(); 
     214                    transformer.setParameter((String)m.getKey(), m.getValue()); 
    246215                } 
    247216            } 
     
    253222            // that does not contain any doctype (like we use to do before). 
    254223            DOMResult result = docDocType == null ? new DOMResult() : new DOMResult(docDocType); 
    255             if (resultNode != null) 
    256             { 
    257                 result.setNode(resultNode); 
     224            if(resultNode != null) { 
     225                result.setNode(resultNode); 
    258226            } 
    259227            DOMSource domSource = new DOMSource(source); 
     
    261229            transformer.transform(domSource, result); 
    262230            return result.getNode(); // pass the entire document 
    263         } 
    264         catch (TransformerConfigurationException e) 
    265         { 
    266             return transformError("XMLTransformer.transform(Doc, Doc, HashMap, Doc)" + "\ncouldn't create transformer object", e); 
    267         } 
    268         catch (TransformerException e) 
    269         { 
    270             return transformError("XMLTransformer.transform(Doc, Doc, HashMap, Doc)" + "\ncouldn't transform the source", e); 
    271         } 
    272     } 
    273  
    274     public Node transform(File stylesheet, File source) 
    275     { 
    276         return transform(stylesheet, source, null); 
    277     } 
    278  
    279     // debugAsFile is only to be set to true when either the stylesheet or source parameters  
    280     // are not objects of type File. The debugAsFile variable is passed into the  
    281     // TransformErrorListener. When set to true, the TransformErrorListener will itself create 
    282     // two files containing the stylesheet and source XML, and try to transform the new source 
    283     // file with the stylesheet file for debugging purposes. 
    284     protected Node transform(File stylesheet, File source, Document docDocType) 
    285     { 
    286         try 
    287         { 
    288             TransformErrorListener transformerErrorListener = (TransformErrorListener) this.t_factory.getErrorListener(); 
    289             transformerErrorListener.setStylesheet(stylesheet); 
    290             Transformer transformer = this.t_factory.newTransformer(new StreamSource(stylesheet)); 
    291             DOMResult result = (docDocType == null) ? new DOMResult() : new DOMResult(docDocType); 
    292             StreamSource streamSource = new StreamSource(source); 
    293  
    294             transformer.setErrorListener(new TransformErrorListener(stylesheet, streamSource)); 
    295  
    296             transformer.transform(streamSource, result); 
    297             return result.getNode().getFirstChild(); 
    298         } 
    299         catch (TransformerConfigurationException e) 
    300         { 
    301             return transformError("XMLTransformer.transform(File, File)" + "\ncouldn't create transformer object for files\n" + stylesheet + "\n" + source, e); 
    302         } 
    303         catch (TransformerException e) 
    304         { 
    305             return transformError("XMLTransformer.transform(File, File)" + "\ncouldn't transform the source for files\n" + stylesheet + "\n" + source, e); 
    306         } 
    307     } 
    308  
     231        }  
     232        catch (TransformerConfigurationException e) { 
     233            return transformError("XMLTransformer.transform(Doc, Doc, HashMap, Doc)" 
     234                + "\ncouldn't create transformer object", e); 
     235        }  
     236        catch (TransformerException e) { 
     237            return transformError("XMLTransformer.transform(Doc, Doc, HashMap, Doc)" 
     238                + "\ncouldn't transform the source", e); 
     239        } 
     240    } 
     241 
     242    public Node transform(File stylesheet, File source) { 
     243    return transform(stylesheet, source, null); 
     244    } 
     245 
     246    // debugAsFile is only to be set to true when either the stylesheet or source parameters  
     247    // are not objects of type File. The debugAsFile variable is passed into the  
     248    // TransformErrorListener. When set to true, the TransformErrorListener will itself create 
     249    // two files containing the stylesheet and source XML, and try to transform the new source 
     250    // file with the stylesheet file for debugging purposes. 
     251    protected Node transform(File stylesheet, File source, Document docDocType) { 
     252    try { 
     253        TransformErrorListener transformerErrorListener = (TransformErrorListener) this.t_factory.getErrorListener(); 
     254        transformerErrorListener.setStylesheet(stylesheet); 
     255        Transformer transformer = this.t_factory.newTransformer(new StreamSource(stylesheet)); 
     256        DOMResult result = (docDocType == null) ? new DOMResult() : new DOMResult(docDocType); 
     257        StreamSource streamSource = new StreamSource(source); 
     258 
     259        transformer.setErrorListener(new TransformErrorListener(stylesheet, streamSource)); 
     260 
     261        transformer.transform(streamSource, result); 
     262        return result.getNode().getFirstChild(); 
     263    } catch (TransformerConfigurationException e) { 
     264            return transformError("XMLTransformer.transform(File, File)" 
     265                + "\ncouldn't create transformer object for files\n"  
     266                + stylesheet + "\n" + source, e); 
     267    }  
     268    catch (TransformerException e) { 
     269        return transformError("XMLTransformer.transform(File, File)" 
     270                + "\ncouldn't transform the source for files\n"  
     271                + stylesheet + "\n" + source, e); 
     272    }    
     273    } 
     274      
    309275    // Given a heading string on the sort of transformation error that occurred and the exception object itself,  
    310276    // this method prints the exception to the tomcat window (system.err) and the greenstone log and then returns 
    311277    // an xhtml error page that is constructed from it. 
    312     protected Node transformError(String heading, TransformerException e) 
    313     { 
     278    protected Node transformError(String heading, TransformerException e) { 
    314279        String message = heading + "\n" + e.getMessage(); 
    315280        logger.error(heading + ": " + e.getMessage()); 
    316  
    317         String location = e.getLocationAsString(); 
    318         if (location != null) 
    319         { 
     281         
     282        String location = e.getLocationAsString();       
     283        if(location != null) { 
    320284            logger.error(location); 
    321285            message = message + "\n" + location; 
     
    324288        return constructErrorXHTMLPage(message); 
    325289    } 
    326  
     290     
    327291    // Given an error message, splits it into separate lines based on any newlines present and generates an xhtml page 
    328292    // (xml Element)  with paragraphs for each line. This is then returned so that it can be displayed in the browser. 
    329     public static Element constructErrorXHTMLPage(String message) 
    330     { 
    331         try 
    332         { 
     293    public static Element constructErrorXHTMLPage(String message) { 
     294        try{ 
    333295            String[] lines = message.split("\n"); 
    334  
    335             Document xhtmlDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 
    336             // <html></html> 
    337             Node htmlNode = xhtmlDoc.createElement("html"); 
    338             xhtmlDoc.appendChild(htmlNode); 
    339             // <head></head> 
    340             Node headNode = xhtmlDoc.createElement("head"); 
    341             htmlNode.appendChild(headNode); 
    342             // <title></title> 
    343             Node titleNode = xhtmlDoc.createElement("title"); 
    344             headNode.appendChild(titleNode); 
    345             Node titleString = xhtmlDoc.createTextNode("Error occurred"); 
    346             titleNode.appendChild(titleString); 
    347  
    348             // <body></body> 
    349             Node bodyNode = xhtmlDoc.createElement("body"); 
    350             htmlNode.appendChild(bodyNode); 
    351  
    352             // finally put the message in the body 
    353             Node h1Node = xhtmlDoc.createElement("h1"); 
    354             bodyNode.appendChild(h1Node); 
    355             Node headingString = xhtmlDoc.createTextNode("The following error occurred:"); 
    356             h1Node.appendChild(headingString); 
    357  
    358             //Node textNode = xhtmlDoc.createTextNode(message); 
    359             //bodyNode.appendChild(textNode); 
    360  
    361             for (int i = 0; i < lines.length; i++) 
    362             { 
     296         
     297            Document xhtmlDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 
     298            // <html></html> 
     299            Node htmlNode = xhtmlDoc.createElement("html"); 
     300            xhtmlDoc.appendChild(htmlNode); 
     301            // <head></head> 
     302            Node headNode = xhtmlDoc.createElement("head"); 
     303            htmlNode.appendChild(headNode); 
     304            // <title></title> 
     305            Node titleNode = xhtmlDoc.createElement("title"); 
     306            headNode.appendChild(titleNode); 
     307            Node titleString = xhtmlDoc.createTextNode("Error occurred"); 
     308            titleNode.appendChild(titleString); 
     309             
     310            // <body></body> 
     311            Node bodyNode = xhtmlDoc.createElement("body"); 
     312            htmlNode.appendChild(bodyNode); 
     313             
     314            // finally put the message in the body 
     315            Node h1Node = xhtmlDoc.createElement("h1"); 
     316            bodyNode.appendChild(h1Node); 
     317            Node headingString = xhtmlDoc.createTextNode("The following error occurred:"); 
     318            h1Node.appendChild(headingString); 
     319             
     320            //Node textNode = xhtmlDoc.createTextNode(message); 
     321            //bodyNode.appendChild(textNode); 
     322             
     323            for (int i = 0; i < lines.length; i++) { 
    363324                Node pNode = xhtmlDoc.createElement("p"); 
    364325                Node textNode = xhtmlDoc.createTextNode(lines[i]); 
     
    366327                bodyNode.appendChild(pNode); 
    367328            } 
    368  
    369             return xhtmlDoc.getDocumentElement(); 
    370  
    371         } 
    372         catch (Exception e) 
    373         { 
    374             String errmsg = "Exception trying to construct error xhtml page from message: " + message + "\n" + e.getMessage(); 
    375             System.err.println(errmsg); 
    376             logger.error(errmsg); 
    377             return null; 
    378         } 
    379     } 
    380  
     329             
     330            return xhtmlDoc.getDocumentElement(); 
     331             
     332        }catch(Exception e) { 
     333            String errmsg = "Exception trying to construct error xhtml page from message: " + message 
     334                + "\n" + e.getMessage(); 
     335            System.err.println(errmsg); 
     336            logger.error(errmsg); 
     337            return null; 
     338        } 
     339    } 
     340     
    381341    // ErrorListener class for both Transformer objects and TransformerFactory objects. 
    382342    // This class can be used to register a handler for any fatal errors, errors and warnings that 
     
    391351    // tomcat console (System.err), and the error message is stored in the errorMessage variable so that  
    392352    // it can be retrieved and be used to generate an xhtml error page. 
    393     public class TransformErrorListener implements ErrorListener 
    394     { 
    395         protected String errorMessage = null; 
    396         protected String stylesheet = null; 
    397         protected Source source = null; // can be DOMSource or StreamSource 
    398         protected boolean debugAsFile = true; // true if xslt or source are not real physical files 
    399  
     353    public class TransformErrorListener implements ErrorListener { 
     354        protected String errorMessage = null; 
     355        protected String stylesheet = null; 
     356        protected Source source = null; // can be DOMSource or StreamSource 
     357        protected boolean debugAsFile = true; // true if xslt or source are not real physical files 
     358         
    400359        // *********** METHODS TO BE CALLED WHEN SETTING AN ERROR LISTENER ON TRANSFORMERFACTORY OBJECTS 
    401360        // The default constructor is only for when setting an ErrorListener on TransformerFactory objects 
     
    429388 
    430389        // *********** METHODS TO BE CALLED WHEN SETTING AN ERROR LISTENER ON TRANSFORMERFACTORY OBJECTS 
    431         // When setting an ErrorListener on Transformer object, the ErrorListener takes a Stylesheet xslt and a Source 
    432         public TransformErrorListener(String xslt, Source source) 
    433         { 
    434             this.stylesheet = xslt; 
    435             this.source = source; 
    436             XMLTransformer.debugFileCount++; 
    437         } 
    438  
    439         public TransformErrorListener(Document xslt, Source source) 
    440         { 
    441             this.stylesheet = GSXML.elementToString(xslt.getDocumentElement(), true); 
    442             this.source = source; 
    443             XMLTransformer.debugFileCount++; 
    444         } 
    445  
    446         public TransformErrorListener(File xslt, Source source) 
    447         { 
    448             this.debugAsFile = false; // if this constructor is called, we're dealing with physical files for both xslt and source 
    449             this.source = source; 
    450             this.stylesheet = xslt.getAbsolutePath(); // not necessary to get the string from the file 
    451             // all we were going to do with it *on error* was write it out to a file anyway      
    452         } 
     390        // When setting an ErrorListener on Transformer object, the ErrorListener takes a Stylesheet xslt and a Source       
     391        public TransformErrorListener(String xslt, Source source) {  
     392        this.stylesheet = xslt;  
     393        this.source = source; 
     394        XMLTransformer.debugFileCount++; 
     395        } 
     396 
     397        public TransformErrorListener(Document xslt, Source source) {        
     398        this.stylesheet = GSXML.elementToString(xslt.getDocumentElement(), true); 
     399        this.source = source; 
     400        XMLTransformer.debugFileCount++; 
     401        } 
     402 
     403        public TransformErrorListener(File xslt, Source source) { 
     404        this.debugAsFile = false; // if this constructor is called, we're dealing with physical files for both xslt and source 
     405        this.source = source; 
     406        this.stylesheet = xslt.getAbsolutePath(); // not necessary to get the string from the file 
     407                   // all we were going to do with it *on error* was write it out to a file anyway       
     408        } 
    453409 
    454410        // *********** METHODS CALLED AUTOMATICALLY ON ERROR 
    455  
    456         //  Receive notification of a recoverable error. 
    457         public void error(TransformerException exception) 
    458         { 
    459             handleError("Error:\n", exception); 
    460         } 
    461  
    462         // Receive notification of a non-recoverable error. 
    463         public void fatalError(TransformerException exception) 
    464         { 
    465             handleError("Fatal Error:\n", exception); 
    466         } 
    467  
    468         // Receive notification of a warning. 
    469         public void warning(TransformerException exception) 
    470         { 
    471             handleError("Warning:\n", exception); 
    472         } 
    473  
    474         public String toString(TransformerException e) 
    475         { 
    476             String msg = "Exception encountered was:\n\t"; 
    477             String location = e.getLocationAsString(); 
    478             if (location != null) 
    479             { 
    480                 msg = msg + "Location: " + location + "\n\t"; 
    481             } 
    482  
    483             return msg + "Message: " + e.getMessage(); 
    484         } 
    485  
    486         // clears the errorPage variable after the first call to this method 
    487         public String getErrorMessage() 
    488         { 
    489             String errMsg = this.errorMessage; 
    490             if (this.errorMessage != null) 
    491             { 
    492                 this.errorMessage = null; 
    493             } 
    494             return errMsg; 
    495         } 
    496  
    497         // sets the errorMessage member variable to the data stored in the exception 
    498         // and writes the errorMessage to the logger and tomcat's System.err 
    499         protected void handleError(String errorType, TransformerException exception) 
    500         { 
    501  
    502             this.errorMessage = errorType + toString(exception); 
    503  
    504             // If either the stylesheet or the source to be transformed with it were not files, 
    505             // so that the transformation was performed in-memory, then the "location" information 
    506             // during the error handling (if any) wouldn't have been helpful. 
    507             // To allow proper debugging, we write both stylesheet and source out as physical files 
    508             // and perform the same transformation again, so that when a transformation error does  
    509             // occur, the files are not in-memory but can be viewed, and any location information 
    510             // for the error given by the ErrorListener will be sensible (instead of the unhelpful 
    511             // "line#0 column#0 in file://somewhere/dummy.xsl"). 
    512             // Note that if the stylesheet and the source it is to transform were both physical  
    513             // files to start off with, we will not need to perform the same transformation again 
    514             // since the error reporting would have provided accurate locations for those. 
    515             if (debugAsFile) 
    516             { 
    517  
    518                 performTransformWithPhysicalFiles(); // will give accurate line numbers 
    519  
    520                 // No need to print out the current error message (seen in the Else statement below),  
    521                 // as the recursive call to XMLTransformer.transform(File, File, false) in method 
    522                 // performTransformWithPhysicalFiles() will do this for us. 
    523             } 
    524             else 
    525             { 
    526                 // printing out the error message 
    527                 // since !debugAsFile, we are dealing with physical files,  
    528                 // variable stylesheet would have stored the filename instead of contents 
    529                 this.errorMessage = this.errorMessage + "\nstylesheet filename: " + stylesheet; 
    530  
    531                 this.errorMessage += "\nException CAUSE:\n" + exception.getCause(); 
    532                 System.err.println("\n****Error transforming xml:\n" + this.errorMessage + "\n****\n"); 
    533                 //System.err.println("Stylesheet was:\n + this.stylesheet + "************END STYLESHEET***********\n\n");            
    534  
    535                 logger.error(this.errorMessage); 
    536  
    537                 // now print out the source to a file, and run the stylesheet on it using a transform() 
    538                 // then any error will be referring to one of these two input files. 
    539             } 
    540         } 
    541  
    542         // This method will redo the transformation that went wrong with *real* files:  
    543         // it writes out the stylesheet and source XML to files first, then performs the transformation 
    544         // to get the actual line location of where things went wrong (instead of "line#0 column#0 in dummy.xsl") 
    545         protected void performTransformWithPhysicalFiles() 
    546         { 
    547             File webLogsTmpFolder = new File(GlobalProperties.getGSDL3Home() + File.separator + "logs" + File.separator + "tmp"); 
    548             if (!webLogsTmpFolder.exists()) 
    549             { 
    550                 webLogsTmpFolder.mkdirs(); // create any necessary folders 
    551             } 
    552             File styleFile = new File(webLogsTmpFolder + File.separator + "stylesheet" + XMLTransformer.debugFileCount + ".xml"); 
    553             File sourceFile = new File(webLogsTmpFolder + File.separator + "source" + XMLTransformer.debugFileCount + ".xml"); 
    554  
    555             try 
    556             { 
    557                 // write stylesheet to a file called stylesheet_systemID in tmp 
    558                 FileWriter styleSheetWriter = new FileWriter(styleFile); 
    559                 styleSheetWriter.write(stylesheet, 0, stylesheet.length()); 
    560                 styleSheetWriter.flush(); 
    561                 styleSheetWriter.close(); 
    562             } 
    563             catch (Exception e) 
    564             { 
    565                 System.err.println("*** Exception when trying to write out stylesheet to " + styleFile.getAbsolutePath()); 
    566             } 
    567  
    568             if (this.source != null) 
    569             { // ErrorListener was set on a Transformer object 
    570                 try 
     411         
     412        //  Receive notification of a recoverable error. 
     413        public void error(TransformerException exception) { 
     414        handleError("Error:\n", exception); 
     415        } 
     416         
     417        // Receive notification of a non-recoverable error. 
     418        public void fatalError(TransformerException exception) { 
     419        handleError("Fatal Error:\n", exception); 
     420        } 
     421         
     422        // Receive notification of a warning. 
     423        public void warning(TransformerException exception) { 
     424        handleError("Warning:\n", exception); 
     425        } 
     426         
     427        public String toString(TransformerException e) { 
     428        String msg = "Exception encountered was:\n\t"; 
     429        String location = e.getLocationAsString(); 
     430        if(location != null) {           
     431            msg = msg + "Location: " + location + "\n\t"; 
     432        }  
     433 
     434        return msg + "Message: " + e.getMessage(); 
     435        } 
     436         
     437        // clears the errorPage variable after the first call to this method 
     438        public String getErrorMessage() { 
     439        String errMsg = this.errorMessage; 
     440        if(this.errorMessage != null) { 
     441            this.errorMessage = null; 
     442        } 
     443        return errMsg; 
     444        } 
     445         
     446        // sets the errorMessage member variable to the data stored in the exception 
     447        // and writes the errorMessage to the logger and tomcat's System.err 
     448        protected void handleError(String errorType, TransformerException exception) { 
     449 
     450        this.errorMessage = errorType + toString(exception); 
     451 
     452        // If either the stylesheet or the source to be transformed with it were not files, 
     453        // so that the transformation was performed in-memory, then the "location" information 
     454        // during the error handling (if any) wouldn't have been helpful. 
     455        // To allow proper debugging, we write both stylesheet and source out as physical files 
     456        // and perform the same transformation again, so that when a transformation error does  
     457        // occur, the files are not in-memory but can be viewed, and any location information 
     458        // for the error given by the ErrorListener will be sensible (instead of the unhelpful 
     459        // "line#0 column#0 in file://somewhere/dummy.xsl"). 
     460        // Note that if the stylesheet and the source it is to transform were both physical  
     461        // files to start off with, we will not need to perform the same transformation again 
     462        // since the error reporting would have provided accurate locations for those. 
     463        if(debugAsFile) { 
     464             
     465            performTransformWithPhysicalFiles(); // will give accurate line numbers 
     466         
     467            // No need to print out the current error message (seen in the Else statement below),  
     468            // as the recursive call to XMLTransformer.transform(File, File, false) in method 
     469            // performTransformWithPhysicalFiles() will do this for us. 
     470        } 
     471        else {  
     472            // printing out the error message 
     473            // since !debugAsFile, we are dealing with physical files,  
     474            // variable stylesheet would have stored the filename instead of contents 
     475            this.errorMessage = this.errorMessage + "\nstylesheet filename: " + stylesheet; 
     476             
     477            this.errorMessage += "\nException CAUSE:\n" + exception.getCause(); 
     478            System.err.println("\n****Error transforming xml:\n" + this.errorMessage + "\n****\n"); 
     479            //System.err.println("Stylesheet was:\n + this.stylesheet + "************END STYLESHEET***********\n\n");            
     480             
     481            logger.error(this.errorMessage); 
     482             
     483            // now print out the source to a file, and run the stylesheet on it using a transform() 
     484            // then any error will be referring to one of these two input files. 
     485        } 
     486        } 
     487 
     488        // This method will redo the transformation that went wrong with *real* files:  
     489        // it writes out the stylesheet and source XML to files first, then performs the transformation 
     490        // to get the actual line location of where things went wrong (instead of "line#0 column#0 in dummy.xsl") 
     491        protected void performTransformWithPhysicalFiles() { 
     492        File webLogsTmpFolder = new File(GlobalProperties.getGSDL3Home() + File.separator + "logs" + File.separator + "tmp"); 
     493        if(!webLogsTmpFolder.exists()) { 
     494            webLogsTmpFolder.mkdirs(); // create any necessary folders 
     495        } 
     496        File styleFile = new File(webLogsTmpFolder + File.separator + "stylesheet" + XMLTransformer.debugFileCount + ".xml"); 
     497        File sourceFile = new File(webLogsTmpFolder + File.separator + "source" + XMLTransformer.debugFileCount + ".xml"); 
     498         
     499        try { 
     500            // write stylesheet to a file called stylesheet_systemID in tmp 
     501            FileWriter styleSheetWriter = new FileWriter(styleFile); 
     502            styleSheetWriter.write(stylesheet, 0, stylesheet.length()); 
     503            styleSheetWriter.flush(); 
     504            styleSheetWriter.close(); 
     505        } catch(Exception e) { 
     506            System.err.println("*** Exception when trying to write out stylesheet to " + styleFile.getAbsolutePath()); 
     507        }    
     508         
     509        if (this.source != null) { // ErrorListener was set on a Transformer object 
     510        try { 
     511            FileWriter srcWriter = new FileWriter(sourceFile); 
     512            String contents = ""; 
     513            if(source instanceof DOMSource) { 
     514            DOMSource domSource = (DOMSource)source; 
     515            Document doc = (Document)domSource.getNode(); 
     516            contents = GSXML.elementToString(doc.getDocumentElement(), true); 
     517            //contents = GSXML.xmlNodeToXMLString(domSource.getNode()); 
     518            } else if (source instanceof StreamSource) { 
     519            StreamSource streamSource = (StreamSource)source; 
     520            BufferedReader reader = new BufferedReader(streamSource.getReader()); 
     521            String line = ""; 
     522            while((line = reader.readLine()) != null) { 
     523                contents = contents + line + "\n"; 
     524            }            
     525            } 
     526            srcWriter.write(contents, 0, contents.length()); 
     527            srcWriter.flush(); 
     528            srcWriter.close();       
     529        } catch(Exception e) { 
     530            System.err.println("*** Exception when trying to write out stylesheet to " + sourceFile.getAbsolutePath()); 
     531        } 
     532        } 
     533         
     534        System.err.println("*****************************************"); 
     535        System.err.println("Look for stylesheet in: " + styleFile.getAbsolutePath()); 
     536        if (this.source != null) { // ErrorListener was set on a Transformer object 
     537            System.err.println("Look for source XML in: " + sourceFile.getAbsolutePath()); 
     538        }    
     539         
     540        // now perform the transform again, which will assign another TransformErrorListener 
     541        // but since debuggingAsFile is turned off, we won't recurse into this section of 
     542        // handling the error again 
     543        if (this.source != null) { // ErrorListener was set on a Transformer object 
     544            XMLTransformer.this.transform(styleFile, sourceFile); // calls the File, File version, so debugAsFile will be false      
     545        } 
     546         
     547        else { // ErrorListener was set on a TransformerFactory object 
     548 
     549            // The recursive step in this case is to perform the instantiation  
     550            // of the Transformer object again. 
     551            // Only one TransformerFactory object per XMLTransformer,  
     552            // and only one TransformerHandler object set on any TransformerFactory 
     553            // But the stylesheet used to create a Transformer from that TransformerFactory 
     554            // object changes each time, by calls to setStylesheet(),  
     555            // Therefore, the debugAsFile state for the single TransformerFactory's  
     556            // TransformerHandler changes each time also. 
     557 
     558            try { 
     559                debugAsFile = false; 
     560                this.stylesheet = styleFile.getAbsolutePath(); 
     561                //TransformErrorListener transformerErrorListener = (TransformErrorListener)XMLTransformer.this.t_factory.getErrorListener(); 
     562                //transformerErrorListener.setStylesheet(styleFile); 
     563                Transformer transformer = XMLTransformer.this.t_factory.newTransformer(new StreamSource(styleFile)); 
     564                if (transformer == null) 
    571565                { 
    572                     FileWriter srcWriter = new FileWriter(sourceFile); 
    573                     String contents = ""; 
    574                     if (source instanceof DOMSource) 
    575                     { 
    576                         DOMSource domSource = (DOMSource) source; 
    577                         Document doc = (Document) domSource.getNode(); 
    578                         contents = GSXML.elementToString(doc.getDocumentElement(), true); 
    579                         //contents = GSXML.xmlNodeToXMLString(domSource.getNode()); 
    580                     } 
    581                     else if (source instanceof StreamSource) 
    582                     { 
    583                         StreamSource streamSource = (StreamSource) source; 
    584                         BufferedReader reader = new BufferedReader(streamSource.getReader()); 
    585                         String line = ""; 
    586                         while ((line = reader.readLine()) != null) 
    587                         { 
    588                             contents = contents + line + "\n"; 
    589                         } 
    590                     } 
    591                     srcWriter.write(contents, 0, contents.length()); 
    592                     srcWriter.flush(); 
    593                     srcWriter.close(); 
    594                 } 
    595                 catch (Exception e) 
    596                 { 
    597                     System.err.println("*** Exception when trying to write out stylesheet to " + sourceFile.getAbsolutePath()); 
     566                    String msg = "XMLTransformer transformer is " + transformer; 
     567                    logger.info(msg); 
     568                    System.out.println(msg + "\n****\n"); 
    598569                } 
    599570            } 
    600  
    601             System.err.println("*****************************************"); 
    602             System.err.println("Look for stylesheet in: " + styleFile.getAbsolutePath()); 
    603             if (this.source != null) 
    604             { // ErrorListener was set on a Transformer object 
    605                 System.err.println("Look for source XML in: " + sourceFile.getAbsolutePath()); 
     571            catch (TransformerConfigurationException e) 
     572            { 
     573                String message = "Couldn't create transformer object: " + e.getMessageAndLocation(); 
     574                logger.error(message); 
     575                logger.error(e.getLocationAsString()); 
     576                System.out.println(message); 
    606577            } 
    607  
    608             // now perform the transform again, which will assign another TransformErrorListener 
    609             // but since debuggingAsFile is turned off, we won't recurse into this section of 
    610             // handling the error again 
    611             if (this.source != null) 
    612             { // ErrorListener was set on a Transformer object 
    613                 XMLTransformer.this.transform(styleFile, sourceFile); // calls the File, File version, so debugAsFile will be false 
     578            catch (TransformerException e) 
     579            { 
     580                String message = "Couldn't transform the source: " + e.getMessageAndLocation(); 
     581                logger.error(message); 
     582                System.out.println(message); 
    614583            } 
    615  
    616             else 
    617             { // ErrorListener was set on a TransformerFactory object 
    618  
    619                 // The recursive step in this case is to perform the instantiation  
    620                 // of the Transformer object again. 
    621                 // Only one TransformerFactory object per XMLTransformer,  
    622                 // and only one TransformerHandler object set on any TransformerFactory 
    623                 // But the stylesheet used to create a Transformer from that TransformerFactory 
    624                 // object changes each time, by calls to setStylesheet(),  
    625                 // Therefore, the debugAsFile state for the single TransformerFactory's  
    626                 // TransformerHandler changes each time also. 
    627  
    628                 try 
    629                 { 
    630                     debugAsFile = false; 
    631                     this.stylesheet = styleFile.getAbsolutePath(); 
    632                     //TransformErrorListener transformerErrorListener = (TransformErrorListener)XMLTransformer.this.t_factory.getErrorListener(); 
    633                     //transformerErrorListener.setStylesheet(styleFile); 
    634                     Transformer transformer = XMLTransformer.this.t_factory.newTransformer(new StreamSource(styleFile)); 
    635                     if (transformer == null) 
    636                     { 
    637                         String msg = "XMLTransformer transformer is " + transformer; 
    638                         logger.info(msg); 
    639                         System.out.println(msg + "\n****\n"); 
    640                     } 
    641                 } 
    642                 catch (TransformerConfigurationException e) 
    643                 { 
    644                     String message = "Couldn't create transformer object: " + e.getMessageAndLocation(); 
    645                     logger.error(message); 
    646                     logger.error(e.getLocationAsString()); 
    647                     System.out.println(message); 
    648                 } 
    649                 catch (TransformerException e) 
    650                 { 
    651                     String message = "Couldn't transform the source: " + e.getMessageAndLocation(); 
    652                     logger.error(message); 
    653                     System.out.println(message); 
    654                 } 
    655             } 
    656  
    657         } 
     584        } 
     585         
     586        } 
    658587    } 
    659588}