- Timestamp:
- 2012-05-17T14:55:09+12:00 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/XMLTransformer.java
r25613 r25617 58 58 import org.apache.log4j.*; 59 59 60 /** XMLTransformer - utility class for greenstone 61 * 60 /** 61 * XMLTransformer - utility class for greenstone 62 * 62 63 * transforms xml using xslt 63 * 64 * 64 65 * @author <a href="mailto:[email protected]">Katherine Don</a> 65 66 * @version $Revision$ 66 67 */ 67 public 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()); 109 } 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 ""; 178 } 179 } 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 } 116 } 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 } 155 } 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 } 180 203 181 204 /** … … 183 206 * whose node should be set to the Document donated by resultNode 184 207 */ 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 { 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 { 203 232 // Use the TransformerFactory to process the stylesheet Source and generate a Transformer. 204 233 TransformErrorListener transformerErrorListener = (TransformErrorListener) this.t_factory.getErrorListener(); 205 234 transformerErrorListener.setStylesheet(stylesheet); 206 235 Transformer transformer = this.t_factory.newTransformer(new DOMSource(stylesheet)); 207 //logger.info("XMLTransformer transformer is " + transformer); //done in ErrorListener 208 209 if (parameters != null) { 236 //logger.info("XMLTransformer transformer is " + transformer); //done in ErrorListener 237 238 if (parameters != null) 239 { 210 240 Set params = parameters.entrySet(); 211 241 Iterator i = params.iterator(); 212 while (i.hasNext()) { 213 Map.Entry m = (Map.Entry)i.next(); 214 transformer.setParameter((String)m.getKey(), m.getValue()); 242 while (i.hasNext()) 243 { 244 Map.Entry m = (Map.Entry) i.next(); 245 transformer.setParameter((String) m.getKey(), m.getValue()); 215 246 } 216 247 } … … 222 253 // that does not contain any doctype (like we use to do before). 223 254 DOMResult result = docDocType == null ? new DOMResult() : new DOMResult(docDocType); 224 if(resultNode != null) { 225 result.setNode(resultNode); 255 if (resultNode != null) 256 { 257 result.setNode(resultNode); 226 258 } 227 259 DOMSource domSource = new DOMSource(source); … … 229 261 transformer.transform(domSource, result); 230 262 return result.getNode(); // pass the entire document 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 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 275 309 // Given a heading string on the sort of transformation error that occurred and the exception object itself, 276 310 // this method prints the exception to the tomcat window (system.err) and the greenstone log and then returns 277 311 // an xhtml error page that is constructed from it. 278 protected Node transformError(String heading, TransformerException e) { 312 protected Node transformError(String heading, TransformerException e) 313 { 279 314 String message = heading + "\n" + e.getMessage(); 280 315 logger.error(heading + ": " + e.getMessage()); 281 282 String location = e.getLocationAsString(); 283 if(location != null) { 316 317 String location = e.getLocationAsString(); 318 if (location != null) 319 { 284 320 logger.error(location); 285 321 message = message + "\n" + location; … … 288 324 return constructErrorXHTMLPage(message); 289 325 } 290 326 291 327 // Given an error message, splits it into separate lines based on any newlines present and generates an xhtml page 292 328 // (xml Element) with paragraphs for each line. This is then returned so that it can be displayed in the browser. 293 public static Element constructErrorXHTMLPage(String message) { 294 try{ 329 public static Element constructErrorXHTMLPage(String message) 330 { 331 try 332 { 295 333 String[] lines = message.split("\n"); 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++) { 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 { 324 363 Node pNode = xhtmlDoc.createElement("p"); 325 364 Node textNode = xhtmlDoc.createTextNode(lines[i]); … … 327 366 bodyNode.appendChild(pNode); 328 367 } 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 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 341 381 // ErrorListener class for both Transformer objects and TransformerFactory objects. 342 382 // This class can be used to register a handler for any fatal errors, errors and warnings that … … 351 391 // tomcat console (System.err), and the error message is stored in the errorMessage variable so that 352 392 // it can be retrieved and be used to generate an xhtml error page. 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 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 359 400 // *********** METHODS TO BE CALLED WHEN SETTING AN ERROR LISTENER ON TRANSFORMERFACTORY OBJECTS 360 401 // The default constructor is only for when setting an ErrorListener on TransformerFactory objects … … 389 430 // *********** METHODS TO BE CALLED WHEN SETTING AN ERROR LISTENER ON TRANSFORMERFACTORY OBJECTS 390 431 // 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 } 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 } 409 453 410 454 // *********** METHODS CALLED AUTOMATICALLY ON ERROR 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) 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 565 571 { 566 String msg = "XMLTransformer transformer is " + transformer; 567 logger.info(msg); 568 System.out.println(msg + "\n****\n"); 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(); 569 594 } 570 } 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); 577 } 578 catch (TransformerException e) 579 { 580 String message = "Couldn't transform the source: " + e.getMessageAndLocation(); 581 logger.error(message); 582 System.out.println(message); 583 } 584 } 585 586 } 595 catch (Exception e) 596 { 597 System.err.println("*** Exception when trying to write out stylesheet to " + sourceFile.getAbsolutePath()); 598 } 599 } 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()); 606 } 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 614 } 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 } 650 } 587 651 } 588 652 }
Note:
See TracChangeset
for help on using the changeset viewer.