Changeset 18435


Ignore:
Timestamp:
2009-01-30T17:01:13+13:00 (15 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.
File:
1 edited

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  
Note: See TracChangeset for help on using the changeset viewer.