Changeset 18435

Show
Ignore:
Timestamp:
30.01.2009 17:01:13 (11 years ago)
Author:
max
Message:

1. Added a reusable ErrorListener? class for handling warnings, fatal and regular errors that may occur when transforming xml with stylesheets or other xslt files.
2. Each time a Transformer object is used, we are now registering an ErrorListener? on it to deal with any Transformation-related errors.

Files:
1 modified

Legend:

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

    r17024 r18435  
    2424import javax.xml.transform.TransformerConfigurationException; 
    2525import javax.xml.transform.TransformerException; 
     26import javax.xml.transform.ErrorListener; 
    2627 
    2728import javax.xml.transform.stream.StreamSource; 
     
    6162 
    6263    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.XMLTransformer.class.getName()); 
    63  
     64     
    6465  /** The transformer factory we're using */ 
    6566    TransformerFactory t_factory=null; 
     
    9899        // Use the TransformerFactory to process the stylesheet Source and generate a Transformer. 
    99100        Transformer transformer = this.t_factory.newTransformer(new StreamSource(stylesheet)); 
     101        transformer.setErrorListener(new TransformErrorListener()); 
    100102 
    101103        // Use the Transformer to transform an XML Source and send the output to a Result object. 
     
    109111        return ""; 
    110112    } catch (TransformerException e) { 
    111         logger.error("couldn't transform the source: " + e.getMessage()); 
     113        logger.error("couldn't transform the source: " + e.getMessageAndLocation()); 
    112114        return ""; 
    113115    }    
     
    123125        // Use the TransformerFactory to process the stylesheet Source and generate a Transformer. 
    124126        Transformer transformer = this.t_factory.newTransformer(new DOMSource(stylesheet)); 
     127        transformer.setErrorListener(new TransformErrorListener()); 
    125128        if (parameters != null) { 
    126129        Set params = parameters.entrySet(); 
     
    140143        return output.toString(); 
    141144    } catch (TransformerConfigurationException e) { 
    142         logger.error("couldn't create transformer object: "+e.getMessageAndLocation()); 
     145        logger.error("couldn't create transformer object: "+e.getMessageAndLocation()); 
    143146        logger.error(e.getLocationAsString());   
    144147        return ""; 
    145148    } catch (TransformerException e) { 
    146         logger.error("couldn't transform the source: " + e.getMessage()); 
     149        logger.error("couldn't transform the source: " + e.getMessageAndLocation()); 
    147150        return ""; 
    148     }    
    149       } 
     151    } 
     152    } 
    150153 
    151154    public Node transform(Document stylesheet, Document source) { 
    152     return transform(stylesheet, source, null); 
    153     } 
    154  
    155     public Node transform(Document stylesheet, Document source, HashMap parameters) { 
    156  
    157     try { 
    158         // Use the TransformerFactory to process the stylesheet Source and generate a Transformer. 
    159         Transformer transformer = this.t_factory.newTransformer(new DOMSource(stylesheet)); 
    160          
    161         if (parameters != null) { 
    162         Set params = parameters.entrySet(); 
    163         Iterator i = params.iterator(); 
    164         while (i.hasNext()) { 
    165             Map.Entry m = (Map.Entry)i.next(); 
    166             transformer.setParameter((String)m.getKey(), m.getValue()); 
    167         } 
    168         } 
    169  
    170         DOMResult result = new DOMResult(); 
    171         transformer.transform(new DOMSource(source), result); 
    172         return result.getNode().getFirstChild(); 
    173     } catch (TransformerConfigurationException e) { 
    174         String message = "TransformerConfigurationException: "+e.getMessageAndLocation(); 
    175         //System.err.println(message); 
    176         logger.error("couldn't create transformer object: "+e.getMessageAndLocation()); 
    177         logger.error(e.getLocationAsString());   
    178         return constructErrorXHTMLPage(message); 
    179     } catch (TransformerException e) { 
    180         String message = "TransformerException: " + e.getMessageAndLocation(); 
    181         //System.err.println(message); 
    182         logger.error("couldn't transform the source: " + e.getMessage()); 
    183         return constructErrorXHTMLPage(message); 
    184     }    
    185      
    186  
    187     } 
    188  
    189  
    190      
     155    return transform(stylesheet, source, null, null); 
     156    } 
     157 
     158    public Node transform(Document stylesheet, Document source, HashMap parameters, Document docDocType) { 
     159        try { 
     160            // Use the TransformerFactory to process the stylesheet Source and generate a Transformer. 
     161            Transformer transformer = this.t_factory.newTransformer(new DOMSource(stylesheet)); 
     162            transformer.setErrorListener(new TransformErrorListener()); 
     163            if (parameters != null) { 
     164                Set params = parameters.entrySet(); 
     165                Iterator i = params.iterator(); 
     166                while (i.hasNext()) { 
     167                    Map.Entry m = (Map.Entry)i.next(); 
     168                    transformer.setParameter((String)m.getKey(), m.getValue()); 
     169                } 
     170            } 
     171 
     172            // When we transform the DOMResult, we need to make sure the result of 
     173            // the transformation has a DocType. For that to happen, we need to create 
     174            // the DOMResult using a Document with a predefined docType. 
     175            // If we don't have a DocType then do the transformation with a DOMResult 
     176            // that does not contain any doctype (like we use to do before). 
     177            DOMResult result = docDocType == null ? new DOMResult() : new DOMResult(docDocType); 
     178            transformer.transform(new DOMSource(source), result); 
     179            return result.getNode(); // pass the entire document 
     180        }  
     181        catch (TransformerConfigurationException e) { 
     182            return transformError("couldn't create transformer object", e); 
     183        }  
     184        catch (TransformerException e) { 
     185            return transformError("couldn't transform the source", e); 
     186        } 
     187    } 
     188 
    191189    public Node transform(File stylesheet, File source) { 
    192  
    193190    try { 
    194191        Transformer transformer = this.t_factory.newTransformer(new StreamSource(stylesheet)); 
    195          
     192        transformer.setErrorListener(new TransformErrorListener()); 
    196193        DOMResult result = new DOMResult(); 
    197194        transformer.transform(new StreamSource(source), result); 
    198195        return result.getNode().getFirstChild(); 
    199196    } catch (TransformerConfigurationException e) { 
    200         logger.error("couldn't create transformer object: "+e.getMessageAndLocation()); 
    201         logger.error(e.getLocationAsString());   
    202         String message = "TransformerConfigurationException: "+e.getMessageAndLocation(); 
    203         return constructErrorXHTMLPage(message); 
    204     } catch (TransformerException e) { 
    205         logger.error("couldn't transform the source: " + e.getMessage()); 
    206         String message = "TransformerException: " + e.getMessageAndLocation(); 
    207         return constructErrorXHTMLPage(message); 
     197            return transformError("couldn't create transformer object", e); 
     198    }  
     199    catch (TransformerException e) { 
     200        return transformError("couldn't transform the source", e); 
    208201    }    
     202 } 
     203  
     204    public Node transform(File stylesheet, File source, Document docDocType) { 
     205        try { 
     206            Transformer transformer = this.t_factory.newTransformer(new StreamSource(stylesheet)); 
     207            transformer.setErrorListener(new TransformErrorListener()); 
     208            DOMResult result = new DOMResult(docDocType); 
     209            transformer.transform(new StreamSource(source), result); 
     210            return result.getNode().getFirstChild(); 
     211        } catch (TransformerConfigurationException e) { 
     212            return transformError("couldn't create transformer object", e); 
     213        }  
     214        catch (TransformerException e) { 
     215            return transformError("couldn't transform the source", e); 
     216        }    
    209217    } 
    210218     
     219    // Given a heading string on the sort of transformation error that occurred and the exception object itself,  
     220    // this method prints the exception to the tomcat window (system.err) and the greenstone log and then returns 
     221    // an xhtml error page that is constructed from it. 
     222    protected Node transformError(String heading, TransformerException e) { 
     223        String message = heading + "\n" + e.getMessage(); 
     224        logger.error(heading + ": " + e.getMessage()); 
     225         
     226        String location = e.getLocationAsString();       
     227        if(location != null) { 
     228            logger.error(location); 
     229            message = message + "\n" + location; 
     230        } 
     231        System.err.println("****\n" + message + "\n****"); 
     232        return constructErrorXHTMLPage(message); 
     233    } 
    211234     
    212     protected Element constructErrorXHTMLPage(String message) { 
     235    // Given an error message, splits it into separate lines based on any newlines present and generates an xhtml page 
     236    // (xml Element)  with paragraphs for each line. This is then returned so that it can be displayed in the browser. 
     237    public static Element constructErrorXHTMLPage(String message) { 
    213238        try{ 
     239            String[] lines = message.split("\n"); 
     240         
    214241            Document xhtmlDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 
    215242            // <html></html> 
     
    235262            h1Node.appendChild(headingString); 
    236263             
    237             Node textNode = xhtmlDoc.createTextNode(message); 
    238             bodyNode.appendChild(textNode); 
    239              
     264            //Node textNode = xhtmlDoc.createTextNode(message); 
     265            //bodyNode.appendChild(textNode); 
     266             
     267            for (int i = 0; i < lines.length; i++) { 
     268                Node pNode = xhtmlDoc.createElement("p"); 
     269                Node textNode = xhtmlDoc.createTextNode(lines[i]); 
     270                pNode.appendChild(textNode); 
     271                bodyNode.appendChild(pNode); 
     272            } 
     273             
    240274            return xhtmlDoc.getDocumentElement(); 
    241275             
     
    249283    } 
    250284     
     285    // ErrorListener class that can be used to register a handler for any fatal errors, errors and warnings that may 
     286    // occur when transforming an xml file with an xslt stylesheet. The errors are printed both to the greenstone.log and  
     287    // to the tomcat console (System.err), and the error message is stored in the errorMessage variable so that it can 
     288    // be retrieved and be used to generate an xhtml error page. 
     289    static public class TransformErrorListener implements ErrorListener { 
     290        protected String errorMessage = null; 
     291     
     292        //  Receive notification of a recoverable error. 
     293        public void error(TransformerException exception) { 
     294            handleError("Error:\n", exception); 
     295        } 
     296        //   Receive notification of a non-recoverable error. 
     297        public void fatalError(TransformerException exception) { 
     298            handleError("Fatal Error:\n", exception); 
     299        } 
     300        // Receive notification of a warning. 
     301        public void warning(TransformerException exception) { 
     302            handleError("Warning:\n", exception); 
     303        } 
     304         
     305        public String toString(TransformerException e) { 
     306            String location = e.getLocationAsString(); 
     307            if(location == null) { 
     308                return e.getMessage(); 
     309            } 
     310            return e.getMessage() + "\n" + location; 
     311        } 
     312         
     313        // clears the errorPage variable after first call to this method 
     314        public String getErrorMessage() { 
     315            String errMsg = this.errorMessage; 
     316            if(this.errorMessage != null) { 
     317                this.errorMessage = null; 
     318            } 
     319            return errMsg; 
     320        } 
     321         
     322        // sets the errorMessage member variable to the data stored in the exception 
     323        // and writes the errorMessage to the logger and tomcat's System.err 
     324        protected void handleError(String errorType, TransformerException exception) { 
     325            this.errorMessage = errorType + toString(exception);  
     326            System.err.println("\n****Error transforming xml:\n" + this.errorMessage + "\n****\n"); 
     327            logger.error(this.errorMessage); 
     328        } 
     329    } 
    251330} 
    252  
    253