Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 434   Methods: 19
NCLOC: 232   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
TraXLiaison.java 50% 78.7% 84.2% 71.7%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 
 55   
 package org.apache.tools.ant.taskdefs.optional;
 56   
 
 57   
 import java.io.BufferedInputStream;
 58   
 import java.io.BufferedOutputStream;
 59   
 import java.io.File;
 60   
 import java.io.FileInputStream;
 61   
 import java.io.FileOutputStream;
 62   
 import java.io.IOException;
 63   
 import java.io.InputStream;
 64   
 import java.io.OutputStream;
 65   
 import java.util.Vector;
 66   
 import javax.xml.parsers.SAXParserFactory;
 67   
 import javax.xml.transform.ErrorListener;
 68   
 import javax.xml.transform.Source;
 69   
 import javax.xml.transform.SourceLocator;
 70   
 import javax.xml.transform.Templates;
 71   
 import javax.xml.transform.Transformer;
 72   
 import javax.xml.transform.TransformerException;
 73   
 import javax.xml.transform.TransformerFactory;
 74   
 import javax.xml.transform.URIResolver;
 75   
 import javax.xml.transform.sax.SAXSource;
 76   
 import javax.xml.transform.stream.StreamResult;
 77   
 import javax.xml.transform.stream.StreamSource;
 78   
 import javax.xml.transform.TransformerConfigurationException;
 79   
 import org.apache.tools.ant.BuildException;
 80   
 import org.apache.tools.ant.taskdefs.XSLTLiaison;
 81   
 import org.apache.tools.ant.taskdefs.XSLTLogger;
 82   
 import org.apache.tools.ant.taskdefs.XSLTLoggerAware;
 83   
 import org.apache.tools.ant.util.JAXPUtils;
 84   
 import org.xml.sax.EntityResolver;
 85   
 import org.xml.sax.InputSource;
 86   
 import org.xml.sax.XMLReader;
 87   
 
 88   
 /**
 89   
  * Concrete liaison for XSLT processor implementing TraX. (ie JAXP 1.1)
 90   
  *
 91   
  * @author <a href="mailto:rubys@us.ibm.com">Sam Ruby</a>
 92   
  * @author <a href="mailto:dims@yahoo.com">Davanum Srinivas</a>
 93   
  * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
 94   
  * @since Ant 1.3
 95   
  */
 96   
 public class TraXLiaison implements XSLTLiaison, ErrorListener, XSLTLoggerAware {
 97   
 
 98   
     /**
 99   
      * the name of the factory implementation class to use
 100   
      * or null for default JAXP lookup.
 101   
      */
 102   
     private String factoryName = null;
 103   
 
 104   
     /** The trax TransformerFactory */
 105   
     private TransformerFactory tfactory = null;
 106   
 
 107   
     /** stylesheet to use for transformation */
 108   
     private File stylesheet;
 109   
 
 110   
     private XSLTLogger logger;
 111   
 
 112   
     /** possible resolver for publicIds */
 113   
     private EntityResolver entityResolver;
 114   
 
 115   
     /** transformer to use for processing files */
 116   
     private Transformer transformer;
 117   
 
 118   
     /** The In memory version of the stylesheet */
 119   
     private Templates templates;
 120   
 
 121   
     /** 
 122   
      * The modification time of the stylesheet from which the templates 
 123   
      * are read 
 124   
      */
 125   
     private long templatesModTime;
 126   
         
 127   
     /** possible resolver for URIs */
 128   
     private URIResolver uriResolver;
 129   
 
 130   
     /** transformer output properties */
 131   
     private Vector outputProperties = new Vector();
 132   
 
 133   
     /** stylesheet parameters */
 134   
     private Vector params = new Vector();
 135   
 
 136   
     /** factory attributes */
 137   
     private Vector attributes = new Vector();
 138   
 
 139  9
     public TraXLiaison() throws Exception {
 140   
     }
 141   
 
 142  8
     public void setStylesheet(File stylesheet) throws Exception {
 143  8
         if (this.stylesheet != null) {
 144   
             // resetting the stylesheet - reset transformer
 145  0
             transformer = null;
 146   
             
 147   
             // do we need to reset templates as well
 148  0
             if (!this.stylesheet.equals(stylesheet)
 149   
                 || (stylesheet.lastModified() != templatesModTime)) { 
 150  0
                 templates = null;
 151   
             }
 152   
         }
 153  8
         this.stylesheet = stylesheet;
 154   
     }
 155   
 
 156  8
     public void transform(File infile, File outfile) throws Exception {
 157  8
         if (transformer == null) {
 158  8
             createTransformer();
 159   
         }
 160   
 
 161  8
         InputStream fis = null;
 162  8
         OutputStream fos = null;
 163  8
         try {
 164  8
             fis = new BufferedInputStream(new FileInputStream(infile));
 165  8
             fos = new BufferedOutputStream(new FileOutputStream(outfile));
 166  8
             StreamResult res = new StreamResult(fos);
 167   
             // not sure what could be the need of this...
 168  8
             res.setSystemId(JAXPUtils.getSystemId(outfile));
 169  8
             Source src = getSource(fis, infile);
 170  8
             transformer.transform(src, res);
 171   
         } finally {
 172   
             // make sure to close all handles, otherwise the garbage
 173   
             // collector will close them...whenever possible and
 174   
             // Windows may complain about not being able to delete files.
 175  8
             try {
 176  8
                 if (fis != null) {
 177  8
                     fis.close();
 178   
                 }
 179   
             } catch (IOException ignored) {
 180   
                 // ignore
 181   
             }
 182  8
             try {
 183  8
                 if (fos != null) {
 184  8
                     fos.close();
 185   
                 }
 186   
             } catch (IOException ignored) {
 187   
                 // ignore
 188   
             }
 189   
         }
 190   
     }
 191   
 
 192   
     /**
 193   
      * Get the source instance from the stream and id of the file.
 194   
      * @param is the stream containing the stylesheet data.
 195   
      * @param infile the file that will be used for the systemid.
 196   
      * @return the configured source instance matching the stylesheet.
 197   
      * @throws Exception if there is a problem creating the source.
 198   
      */
 199  8
     private Source getSource(InputStream is, File infile) throws Exception {
 200   
         // todo: is this comment still relevant ??
 201   
         // FIXME: need to use a SAXSource as the source for the transform
 202   
         // so we can plug in our own entity resolver
 203  8
         Source src = null;
 204  8
         if (entityResolver != null) {
 205  8
             if (getFactory().getFeature(SAXSource.FEATURE)) {
 206  8
                 SAXParserFactory spFactory = SAXParserFactory.newInstance();
 207  8
                 spFactory.setNamespaceAware(true);
 208  8
                 XMLReader reader = spFactory.newSAXParser().getXMLReader();
 209  8
                 reader.setEntityResolver(entityResolver);
 210  8
                 src = new SAXSource(reader, new InputSource(is));
 211   
             } else {
 212  0
                 throw new IllegalStateException("xcatalog specified, but " +
 213   
                         "parser doesn't support SAX");
 214   
             }
 215   
         } else {
 216  0
             src = new StreamSource(is);
 217   
         }
 218  8
         src.setSystemId(JAXPUtils.getSystemId(infile));
 219  8
         return src;
 220   
     }
 221   
 
 222   
     /**
 223   
      * Read in templates from the stylsheet
 224   
      */
 225  8
     private void readTemplates() 
 226   
         throws IOException, TransformerConfigurationException {
 227   
         // WARN: Don't use the StreamSource(File) ctor. It won't work with
 228   
         // xalan prior to 2.2 because of systemid bugs.
 229   
 
 230   
         // Use a stream so that you can close it yourself quickly
 231   
         // and avoid keeping the handle until the object is garbaged.
 232   
         // (always keep control), otherwise you won't be able to delete
 233   
         // the file quickly on windows.
 234  8
         InputStream xslStream = null;
 235  8
         try {
 236  8
             xslStream 
 237   
                 = new BufferedInputStream(new FileInputStream(stylesheet));
 238  8
             templatesModTime = stylesheet.lastModified();
 239  8
             StreamSource src = new StreamSource(xslStream);
 240   
             // Always set the systemid to the source for imports, includes...
 241   
             // in xsl and xml...
 242  8
             src.setSystemId(JAXPUtils.getSystemId(stylesheet));
 243  8
             templates = getFactory().newTemplates(src);
 244   
         } finally {
 245  8
             if (xslStream != null) {
 246  8
                 xslStream.close();
 247   
             }
 248   
         }
 249   
     }
 250   
     
 251   
     /**
 252   
      * Create a new transformer based on the liaison settings
 253   
      * @return the newly created and configured transformer.
 254   
      * @throws Exception thrown if there is an error during creation.
 255   
      * @see #setStylesheet(java.io.File)
 256   
      * @see #addParam(java.lang.String, java.lang.String)
 257   
      * @see #setOutputProperty(java.lang.String, java.lang.String)
 258   
      */
 259  8
     private void createTransformer() throws Exception {
 260  8
         if (templates == null) {
 261  8
             readTemplates();
 262   
         }
 263   
 
 264  8
         transformer = templates.newTransformer();
 265   
 
 266   
         // configure the transformer...
 267  8
         transformer.setErrorListener(this);
 268  8
         if (uriResolver != null) {
 269  8
             transformer.setURIResolver(uriResolver);
 270   
         }
 271  8
         for (int i = 0; i < params.size(); i++) {
 272  4
             final String[] pair = (String[]) params.elementAt(i);
 273  4
             transformer.setParameter(pair[0], pair[1]);
 274   
         }
 275  8
         for (int i = 0; i < outputProperties.size(); i++) {
 276  4
             final String[] pair = (String[]) outputProperties.elementAt(i);
 277  4
             transformer.setOutputProperty(pair[0], pair[1]);
 278   
         }
 279   
     }
 280   
 
 281   
     /**
 282   
      * return the Transformer factory associated to this liaison.
 283   
      * @return the Transformer factory associated to this liaison.
 284   
      * @throws BuildException thrown if there is a problem creating
 285   
      * the factory.
 286   
      * @see #setFactory(String)
 287   
      * @since Ant 1.5.2
 288   
      */
 289  16
     private TransformerFactory getFactory() throws BuildException {
 290  16
         if (tfactory != null) {
 291  8
             return tfactory;
 292   
         }
 293   
         // not initialized yet, so create the factory
 294  8
         if (factoryName == null) {
 295  6
             tfactory = TransformerFactory.newInstance();
 296   
         } else {
 297  2
             try {
 298  2
                 Class clazz = Class.forName(factoryName);
 299  2
                 tfactory = (TransformerFactory) clazz.newInstance();
 300   
             } catch (Exception e) {
 301  0
                 throw new BuildException(e);
 302   
             }
 303   
         }
 304  8
         tfactory.setErrorListener(this);
 305   
 
 306   
         // specific attributes for the transformer
 307  8
         for (int i = 0; i < attributes.size(); i++) {
 308  1
             final Object[] pair = (Object[])attributes.elementAt(i);
 309  1
             tfactory.setAttribute((String)pair[0], pair[1]);
 310   
         }
 311   
 
 312  8
         if (uriResolver != null) {
 313  8
             tfactory.setURIResolver(uriResolver);
 314   
         }
 315  8
         return tfactory;
 316   
     }
 317   
 
 318   
 
 319   
     /**
 320   
      * Set the factory name to use instead of JAXP default lookup.
 321   
      * @param name the fully qualified class name of the factory to use
 322   
      * or null for the default JAXP look up mechanism.
 323   
      * @since Ant 1.6
 324   
      */
 325  2
     public void setFactory(String name) {
 326  2
         factoryName = name;
 327   
     }
 328   
 
 329   
     /**
 330   
      * Set a custom attribute for the JAXP factory implementation.
 331   
      * @param name the attribute name.
 332   
      * @param value the value of the attribute, usually a boolean
 333   
      * string or object.
 334   
      * @since Ant 1.6
 335   
      */
 336  1
     public void setAttribute(String name, Object value){
 337  1
         final Object[] pair = new Object[]{name, value};
 338  1
         attributes.addElement(pair);
 339   
     }
 340   
 
 341   
     /**
 342   
      * Set the output property for the current transformer.
 343   
      * Note that the stylesheet must be set prior to calling
 344   
      * this method.
 345   
      * @param name the output property name.
 346   
      * @param value the output property value.
 347   
      * @since Ant 1.5
 348   
      * @since Ant 1.5
 349   
      */
 350  4
     public void setOutputProperty(String name, String value) {
 351  4
         final String[] pair = new String[]{name, value};
 352  4
         outputProperties.addElement(pair);
 353   
     }
 354   
 
 355   
     /** Set the class to resolve entities during the transformation
 356   
      */
 357  8
     public void setEntityResolver(EntityResolver aResolver) {
 358  8
         entityResolver = aResolver;
 359   
     }
 360   
 
 361   
     /** Set the class to resolve URIs during the transformation
 362   
      */
 363  8
     public void setURIResolver(URIResolver aResolver) {
 364  8
         uriResolver = aResolver;
 365   
     }
 366   
 
 367  4
     public void addParam(String name, String value) {
 368  4
         final String[] pair = new String[]{name, value};
 369  4
         params.addElement(pair);
 370   
     }
 371   
 
 372  9
     public void setLogger(XSLTLogger l) {
 373  9
         logger = l;
 374   
     }
 375   
 
 376  0
     public void error(TransformerException e) {
 377  0
         logError(e, "Error");
 378   
     }
 379   
 
 380  1
     public void fatalError(TransformerException e) {
 381  1
         logError(e, "Fatal Error");
 382  1
         throw new BuildException("Fatal error during transformation", e);
 383   
     }
 384   
 
 385  0
     public void warning(TransformerException e) {
 386  0
         logError(e, "Warning");
 387   
     }
 388   
 
 389  1
     private void logError(TransformerException e, String type) {
 390  1
         if (logger == null) {
 391  0
             return;
 392   
         }
 393   
 
 394  1
         StringBuffer msg = new StringBuffer();
 395  1
         SourceLocator locator = e.getLocator();
 396  1
         if (locator != null) {
 397  0
             String systemid = locator.getSystemId();
 398  0
             if (systemid != null) {
 399  0
                 String url = systemid;
 400  0
                 if (url.startsWith("file:///")) {
 401  0
                     url = url.substring(8);
 402   
                 }
 403  0
                 msg.append(url);
 404   
             } else {
 405  0
                 msg.append("Unknown file");
 406   
             }
 407  0
             int line = locator.getLineNumber();
 408  0
             if (line != -1) {
 409  0
                 msg.append(":" + line);
 410  0
                 int column = locator.getColumnNumber();
 411  0
                 if (column != -1) {
 412  0
                     msg.append(":" + column);
 413   
                 }
 414   
             }
 415   
         }
 416  1
         msg.append(": " + type + "! ");
 417  1
         msg.append(e.getMessage());
 418  1
         if (e.getCause() != null) {
 419  1
             msg.append(" Cause: " + e.getCause());
 420   
         }
 421   
 
 422  1
         logger.log(msg.toString());
 423   
     }
 424   
 
 425   
     // kept for backwards compatibility
 426   
     /**
 427   
      * @deprecated use org.apache.tools.ant.util.JAXPUtils#getSystemId instead
 428   
      */
 429  0
     protected String getSystemId(File file) {
 430  0
         return JAXPUtils.getSystemId(file);
 431   
     }
 432   
 
 433   
 } //-- TraXLiaison
 434