Coverage Report - org.xmlhammer.gui.xslt.XSLTModule
 
Classes in this File Line Coverage Branch Coverage Complexity
XSLTModule
77% 
75% 
0
 
 1  
 /*
 2  
  * $Id$
 3  
  *
 4  
  * The contents of this file are subject to the Mozilla Public License 
 5  
  * Version 1.1 (the "License"); you may not use this file except in 
 6  
  * compliance with the License. You may obtain a copy of the License at 
 7  
  * http://www.mozilla.org/MPL/ 
 8  
  *
 9  
  * Software distributed under the License is distributed on an "AS IS" basis, 
 10  
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
 11  
  * for the specific language governing rights and limitations under the License.
 12  
  *
 13  
  * The Original Code is XML Hammer code. (org.xmlhammer.*)
 14  
  *
 15  
  * The Initial Developer of the Original Code is Edwin Dankert. Portions created 
 16  
  * by the Initial Developer are Copyright (C) 2005 - 2006 the Initial Developer. 
 17  
  * All Rights Reserved.
 18  
  *
 19  
  * Contributor(s): Edwin Dankert <edankert@gmail.com>
 20  
  */
 21  
 
 22  
 package org.xmlhammer.gui.xslt;
 23  
 
 24  
 import java.io.ByteArrayInputStream;
 25  
 import java.io.ByteArrayOutputStream;
 26  
 import java.io.File;
 27  
 import java.io.FileOutputStream;
 28  
 import java.io.IOException;
 29  
 import java.io.OutputStream;
 30  
 import java.io.PrintStream;
 31  
 import java.net.MalformedURLException;
 32  
 import java.net.URI;
 33  
 import java.util.ArrayList;
 34  
 import java.util.List;
 35  
 
 36  
 import javax.xml.parsers.DocumentBuilder;
 37  
 import javax.xml.parsers.DocumentBuilderFactory;
 38  
 import javax.xml.parsers.ParserConfigurationException;
 39  
 import javax.xml.parsers.SAXParser;
 40  
 import javax.xml.transform.Source;
 41  
 import javax.xml.transform.Transformer;
 42  
 import javax.xml.transform.TransformerConfigurationException;
 43  
 import javax.xml.transform.TransformerException;
 44  
 import javax.xml.transform.TransformerFactory;
 45  
 import javax.xml.transform.dom.DOMSource;
 46  
 import javax.xml.transform.sax.SAXSource;
 47  
 import javax.xml.transform.stream.StreamResult;
 48  
 import javax.xml.transform.stream.StreamSource;
 49  
 
 50  
 import org.apache.log4j.Logger;
 51  
 import org.bounce.util.URIUtils;
 52  
 import org.xml.sax.InputSource;
 53  
 import org.xml.sax.SAXException;
 54  
 import org.xml.sax.SAXParseException;
 55  
 import org.xmlhammer.DefaultErrorHandler;
 56  
 import org.xmlhammer.Module;
 57  
 import org.xmlhammer.ResultModel;
 58  
 import org.xmlhammer.DefaultErrorHandler.Error;
 59  
 import org.xmlhammer.DefaultErrorHandler.Fatal;
 60  
 import org.xmlhammer.DefaultErrorHandler.Message;
 61  
 import org.xmlhammer.DefaultErrorHandler.Problem;
 62  
 import org.xmlhammer.DefaultErrorHandler.Warning;
 63  
 import org.xmlhammer.gui.status.StatusModel;
 64  
 import org.xmlhammer.model.preferences.Preferences;
 65  
 import org.xmlhammer.model.project.Parameter;
 66  
 import org.xmlhammer.model.project.ParameterisedSource;
 67  
 import org.xmlhammer.model.project.Project;
 68  
 import org.xmlhammer.model.tools.xslt.Associated;
 69  
 import org.xmlhammer.model.tools.xslt.OutputProperty;
 70  
 import org.xmlhammer.model.tools.xslt.XSLT.Transform;
 71  
 
 72  
 /**
 73  
  * Put comment...
 74  
  * 
 75  
  * @version $Revision$, $Date$
 76  
  * @author Edwin Dankert <edankert@gmail.com>
 77  
  */
 78  
 public class XSLTModule extends Module {
 79  440
     private SAXParser parser = null;
 80  440
     private DocumentBuilder builder = null;
 81  440
     private TransformerFactory factory = null;
 82  440
     private ArrayList<Transformer> transformers = null;
 83  440
     private Associated associated = null;
 84  440
     private Transform transform = null;
 85  
 
 86  
     public XSLTModule(Preferences preferences, Project project, Logger logger, boolean logSettings) throws SAXException, ParserConfigurationException, TransformerConfigurationException, TransformerException {
 87  440
         super(preferences, project, logger, logSettings);
 88  
 
 89  440
         if ("dom".equals(getProject().getParser().getType())) {
 90  220
             DocumentBuilderFactory factory = getDocumentBuilderFactory();
 91  220
             builder = factory.newDocumentBuilder();
 92  220
         } else {
 93  220
             parser = getSAXParser();
 94  
         }
 95  
         
 96  440
         factory = getTransformerFactory();
 97  
         
 98  440
         transform = project.getXSLT().getTransform();
 99  440
         if (transform.getAssociated() != null) {
 100  132
             associated = transform.getAssociated();
 101  132
             return;
 102  
         } 
 103  
         
 104  308
         if (associated == null) {
 105  308
             transformers = getTransformers(logger);
 106  
         }
 107  264
     }
 108  
 
 109  
     /**
 110  
      * Sets-up an XML Validator Module.
 111  
      * 
 112  
      * @param preferences the global preferences.
 113  
      * @param project the project specific properties;
 114  
      * @throws ParserConfigurationException 
 115  
      * @throws SAXException 
 116  
      */
 117  
         public XSLTModule(Preferences preferences, Project project, Logger logger) throws SAXException, ParserConfigurationException, TransformerConfigurationException, TransformerException {
 118  220
         this(preferences, project, logger, true);
 119  198
         }
 120  
     
 121  
     private void setOutputProperties(Transformer transformer) {
 122  352
         if (transformer != null) {
 123  352
             List<OutputProperty> properties = getProject().getXSLT().getOutputProperties().getOutputProperty();
 124  352
             for (OutputProperty property : properties) {
 125  1760
                 if (property.isActive()) {
 126  1760
                     transformer.setOutputProperty(property.getName(), property.getValue());
 127  
                 }
 128  1760
             }
 129  
         }
 130  352
     }
 131  
     
 132  
     public boolean isResultEnabled() {
 133  396
         return true;
 134  
     }
 135  
 
 136  
     /**
 137  
      * Execute the XPath expressio.
 138  
      * @throws MalformedURLException 
 139  
      * @throws ParserConfigurationException 
 140  
      */
 141  
     @Override
 142  
     public void execute(StatusModel status, ResultModel result, URI sourceURI, URI resultURI) {
 143  396
         PrintStream err = System.err;
 144  396
         PrintStream out = System.out;
 145  396
         DefaultErrorHandler errorHandler = new DefaultErrorHandler(null);
 146  
 
 147  396
         if (sourceURI != null && resultURI != null) {
 148  
             // Tell that we're loading classes and parsing, so the time it
 149  
                         // takes to do this doesn't get confused with the time to do
 150  
                         // the actual query and serialization.
 151  396
             InputSource in = new InputSource(sourceURI.toString());
 152  
 
 153  396
             System.setErr(new PrintStream(new LogOutputStream("err", errorHandler), true));
 154  396
             System.setOut(new PrintStream(new LogOutputStream("out", errorHandler), true));
 155  
 
 156  
             try {
 157  396
                 FileOutputStream resultOuputStream = new FileOutputStream(new File(resultURI));
 158  
 
 159  
                 // TODO handle SAXTransformerFactory stuff ...
 160  396
                 if ( "dom".equals(getProject().getParser().getType())) {
 161  176
                     builder.setErrorHandler(errorHandler);
 162  176
                     builder.setEntityResolver(getCatalogResolver());
 163  176
                     DOMSource source = new DOMSource(builder.parse( in), in.getSystemId());
 164  
                     
 165  176
                     if (associated != null) {
 166  44
                         transformers = new ArrayList<Transformer>();
 167  44
                         Source style = factory.getAssociatedStylesheet(source, associated.getMedia(), associated.getTitle(), associated.getCharset());
 168  44
                         Transformer transformer = null;
 169  
                         
 170  
                         try {
 171  44
                             transformer = getTransformer(result, sourceURI, style, associated.getParameter());
 172  0
                         } catch (TransformerException e) {
 173  
                             return;
 174  44
                         }
 175  
 
 176  44
                         setOutputProperties(transformer);
 177  
 
 178  44
                         transformers.add(transformer);
 179  
                     }
 180  
                     
 181  176
                     getLogger().info( "transform: "+URIUtils.toString(sourceURI));
 182  
 
 183  176
                     for (Transformer transformer : transformers) {
 184  220
                         transformer.setErrorListener(errorHandler);
 185  220
                         StreamResult stream = null;
 186  
                         
 187  220
                         if (transformer == transformers.get(transformers.size()-1)) {
 188  176
                             stream = new StreamResult(resultOuputStream);
 189  176
                         } else {
 190  44
                             stream = new StreamResult(new ByteArrayOutputStream());
 191  
                         }
 192  
 
 193  220
                         transformer.transform(source, stream);
 194  
 
 195  220
                         if (stream.getOutputStream() instanceof ByteArrayOutputStream) {
 196  44
                             in.setByteStream(new ByteArrayInputStream(((ByteArrayOutputStream)stream.getOutputStream()).toByteArray()));
 197  44
                             source = new DOMSource(builder.parse( in), in.getSystemId());
 198  
                         }
 199  220
                     }
 200  176
                 } else { // sax is the only other one.
 201  220
                     parser.getXMLReader().setErrorHandler(errorHandler);
 202  220
                     parser.getXMLReader().setEntityResolver(getCatalogResolver());
 203  220
                     SAXSource source = new SAXSource(parser.getXMLReader(), in);
 204  
 
 205  220
                     if (associated != null) {
 206  88
                         transformers = new ArrayList<Transformer>();
 207  88
                         Source style = factory.getAssociatedStylesheet(source, associated.getMedia(), associated.getTitle(), associated.getCharset());
 208  
 
 209  88
                         Transformer transformer = null;
 210  
                         
 211  
                         try {
 212  88
                             transformer = getTransformer(result, sourceURI, style, associated.getParameter());
 213  44
                         } catch (TransformerException e) {
 214  
                             return;
 215  44
                         }
 216  
                         
 217  44
                         setOutputProperties(transformer);
 218  
 
 219  44
                         transformers.add(transformer);
 220  
                     }
 221  
 
 222  176
                     getLogger().info( "transform: "+URIUtils.toString(sourceURI));
 223  
 
 224  176
                     for (Transformer transformer : transformers) {
 225  220
                         transformer.setErrorListener(errorHandler);
 226  220
                         StreamResult stream = null;
 227  
                         
 228  220
                         if (transformer == transformers.get(transformers.size()-1)) {
 229  176
                             stream = new StreamResult(resultOuputStream);
 230  176
                         } else {
 231  44
                             stream = new StreamResult(new ByteArrayOutputStream());
 232  
                         }
 233  
                         
 234  220
                         transformer.transform(source, stream);
 235  
 
 236  220
                         if (stream.getOutputStream() instanceof ByteArrayOutputStream) {
 237  44
                             in.setByteStream(new ByteArrayInputStream(((ByteArrayOutputStream)stream.getOutputStream()).toByteArray()));
 238  
                         }
 239  220
                     }
 240  
                 }
 241  
                 
 242  272
                 resultOuputStream.flush();
 243  272
                 resultOuputStream.close();
 244  
                 
 245  0
             } catch ( SAXException e) {
 246  0
                 if ( e instanceof SAXParseException) {
 247  
                     try {
 248  0
                         errorHandler.fatalError( (SAXParseException)e);
 249  0
                     } catch ( Exception x) {}
 250  0
                 }
 251  0
             } catch (IOException e) {
 252  0
                 errorHandler.fatalError(e);
 253  90
             } catch (TransformerException e) {
 254  90
                 errorHandler.fatalError(e);
 255  90
             } finally {
 256  306
                 System.setErr(err);
 257  386
                 System.setOut(out);
 258  386
             }
 259  60
 
 260  432
             ArrayList<Problem> list = errorHandler.getProblems();
 261  432
             if ( list.size() > 0) {
 262  204
                             for (Problem problem : list) {
 263  544
                     if (problem instanceof Warning) {
 264  544
                         if (problem.getException() instanceof SAXParseException) {
 265  0
                             logWarning(sourceURI, (SAXParseException)problem.getException());
 266  0
 
 267  0
                             if (result != null) {
 268  160
                                 result.addWarning(sourceURI, (SAXParseException)problem.getException());
 269  0
                             }
 270  160
                         } else {
 271  624
                             logWarning(sourceURI, (TransformerException)problem.getException());
 272  80
 
 273  544
                             if (result != null) {
 274  272
                                 result.addWarning(sourceURI, (TransformerException)problem.getException());
 275  272
                             }
 276  0
                         }
 277  0
                     } else if (problem instanceof Error) {
 278  0
                         if (problem.getException() instanceof SAXParseException) {
 279  0
                             logError(sourceURI, (SAXParseException)problem.getException());
 280  0
 
 281  0
                             if (result != null) {
 282  0
                                 result.addError(sourceURI, (SAXParseException)problem.getException());
 283  0
                             }
 284  0
                         } else {
 285  0
                             logError(sourceURI, (TransformerException)problem.getException());
 286  0
 
 287  0
                             if (result != null) {
 288  0
                                 result.addError(sourceURI, (TransformerException)problem.getException());
 289  0
                             }
 290  
                         }
 291  0
                     } else if (problem instanceof Fatal) {
 292  0
                         logFatal(sourceURI, problem.getException());
 293  0
                         
 294  0
                         if (result != null) {
 295  0
                             Exception exception = problem.getException();
 296  0
                             if ( exception instanceof IOException) {
 297  0
                                 result.addFatal(sourceURI, (IOException)problem.getException());
 298  0
                             } else if ( exception instanceof SAXParseException) {
 299  0
                                 result.addFatal(sourceURI, (SAXParseException)problem.getException());
 300  0
                             } else {
 301  0
                                 result.addFatal(sourceURI, (TransformerException)problem.getException());
 302  0
                             }
 303  0
                         }
 304  0
                     } else if ( problem instanceof Message) {
 305  0
                         getLogger().info( "\t[message] "+((Message)problem).getMessage());
 306  
                         
 307  0
                         if (result != null) {
 308  160
                             result.addMessage(sourceURI, ((Message)problem).getType(), ((Message)problem).getMessage());
 309  60
                         }
 310  20
                     }
 311  544
                             }
 312  224
             } else {
 313  78
                 getLogger().info( "\t[processed] Document Processed");
 314  
 
 315  68
                 if (result != null) {
 316  34
                     result.addValid(sourceURI);
 317  80
                 }
 318  
             }
 319  
                 }
 320  342
         }
 321  70
     
 322  
     private ArrayList<Transformer> getTransformers(Logger logger) throws TransformerException {
 323  308
         if (transformers == null) {
 324  288
             transformers = new ArrayList<Transformer>();
 325  50
 
 326  308
             if (transform.getStylesheets() != null) {
 327  170
                 List<ParameterisedSource> stylesheets = transform.getStylesheets().getParameterisedSource();
 328  230
                 for (ParameterisedSource stylesheet: stylesheets) {
 329  298
                     Transformer transformer = getTransformer(null, null, new StreamSource(stylesheet.getSrc()), stylesheet.getParameter());
 330  
         
 331  244
                     transformers.add(transformer);
 332  244
                 }
 333  
                 
 334  156
                 setOutputProperties(transformers.get(transformers.size()-1));
 335  156
             } else {
 336  20
                 try {
 337  68
                     Transformer transformer = factory.newTransformer();
 338  68
                     transformers.add(transformer);
 339  68
                     setOutputProperties(transformer);
 340  20
                 } catch (TransformerConfigurationException e) {
 341  
                     // this should never happen but if it does, we should just report it ...
 342  0
                     e.printStackTrace();
 343  68
                 }
 344  60
             }
 345  
         }
 346  
     
 347  204
         return transformers;
 348  100
     }
 349  100
 
 350  
     private Transformer getTransformer(ResultModel result, URI base, Source source, List<Parameter> parameters) throws TransformerException {
 351  440
         Transformer transformer = null;
 352  440
         TransformerException exception = null;
 353  
         
 354  440
         if (source != null) {
 355  340
             getLogger().info( "validate stylesheet: "+source.getSystemId());
 356  
 
 357  440
             DefaultErrorHandler errorHandler = new DefaultErrorHandler(URIUtils.createURI(source.getSystemId()));
 358  100
 
 359  
             try {
 360  420
                 factory.setErrorListener(errorHandler);
 361  460
                 transformer = factory.newTransformer(source);
 362  120
 
 363  392
                 for (Parameter parameter : parameters) {
 364  408
                     if (parameter.isActive()) {
 365  528
                         getLogger().info("\t[parameter] "+parameter.getName()+" = "+parameter.getValue());
 366  428
                         transformer.setParameter(parameter.getName(), parameter.getValue());
 367  20
                     }
 368  428
                 }
 369  148
             } catch (TransformerException e) {
 370  68
                 errorHandler.fatalError(e);
 371  168
                 exception = e;
 372  372
             }
 373  20
  
 374  420
             ArrayList<Problem> list = errorHandler.getProblems();
 375  340
             if ( list.size() > 0) {
 376  68
                 for ( Problem problem : list) {
 377  272
                     if ( problem instanceof Warning) {
 378  0
                         logWarning(base, (TransformerException)problem.getException());
 379  0
                         
 380  80
                         if (result != null) {
 381  60
                             result.addWarning(base, (TransformerException)problem.getException());
 382  0
                         }
 383  332
                     } else if ( problem instanceof Error) {
 384  219
                         logError(base, (TransformerException)problem.getException());
 385  15
                         
 386  224
                         if (result != null) {
 387  71
                             result.addError(base, (TransformerException)problem.getException());
 388  51
                         }
 389  88
                     } else if ( problem instanceof Fatal) {
 390  73
                         logFatal(base, problem.getException());
 391  0
                         
 392  68
                         if (result != null) {
 393  22
                             if (problem.getException() instanceof IOException) {
 394  0
                                 result.addFatal(base, (IOException)problem.getException());
 395  0
                             } else {
 396  17
                                 result.addFatal(base, (TransformerException)problem.getException());
 397  80
                             }
 398  20
                         }
 399  80
                     }
 400  272
                 }
 401  68
             } else {
 402  272
                 getLogger().info( "\t[valid] Valid Stylesheet");
 403  100
             }
 404  20
         }
 405  
         
 406  340
         if (exception != null) {
 407  148
             throw exception;
 408  
         }
 409  
         
 410  272
         return transformer;
 411  180
     }
 412  180
 
 413  180
     class LogOutputStream extends OutputStream {
 414  612
         private StringBuffer buffer = new StringBuffer();
 415  792
         private DefaultErrorHandler handler = null;
 416  792
         private String type = null;
 417  180
         
 418  792
         public LogOutputStream(String type, DefaultErrorHandler handler) {
 419  612
             this.handler = handler;
 420  612
             this.type = type;
 421  612
         }
 422  0
 
 423  
         public void write(int b) {
 424  0
             buffer.append( (char)b);
 425  0
         }
 426  0
     
 427  0
         public void flush () {
 428  0
             String message = buffer.toString().trim();
 429  0
             if (message.length() > 0) {
 430  0
                 handler.message(type, message);
 431  0
             }
 432  
             
 433  0
             buffer = new StringBuffer();
 434  0
         }
 435  
     }
 436  
 }