src/share/classes/com/sun/xml/internal/messaging/saaj/util/transform/EfficientStreamingTransformer.java

Mon, 04 May 2009 21:10:41 -0700

author
tbell
date
Mon, 04 May 2009 21:10:41 -0700
changeset 50
42dfec6871f6
parent 45
31822b475baa
child 78
860b95cc8d1d
permissions
-rw-r--r--

6658158: Mutable statics in SAAJ (findbugs)
6658163: txw2.DatatypeWriter.BUILDIN is a mutable static (findbugs)
Reviewed-by: darcy

     1 /*
     2  * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Sun in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
    23  * have any questions.
    24  */
    27 /*
    28  * EfficientStreamingTransformer.java
    29  *
    30  * Created on July 29, 2002, 3:49 PM
    31  */
    33 package com.sun.xml.internal.messaging.saaj.util.transform;
    35 import java.io.*;
    37 import javax.xml.parsers.DocumentBuilder;
    38 import javax.xml.parsers.DocumentBuilderFactory;
    40 import javax.xml.transform.*;
    41 import javax.xml.transform.dom.DOMSource;
    42 import javax.xml.transform.dom.DOMResult;
    43 import javax.xml.transform.stream.StreamResult;
    44 import javax.xml.transform.stream.StreamSource;
    46 import org.w3c.dom.Document;
    48 import com.sun.xml.internal.messaging.saaj.util.XMLDeclarationParser;
    49 import com.sun.xml.internal.messaging.saaj.util.FastInfosetReflection;
    51 /**
    52  * This class is a proxy for a Transformer object with optimizations
    53  * for certain cases. If source and result are of type stream, then
    54  * bytes are simply copied whenever possible (note that this assumes
    55  * that the input is well formed). In addition, it provides support for
    56  * FI using native DOM parsers and serializers.
    57  *
    58  * @author Panos Kougiouris panos@acm.org
    59  * @author Santiago.PericasGeertsen@sun.com
    60  *
    61  */
    62 public class EfficientStreamingTransformer
    63     extends javax.xml.transform.Transformer {
    65   //static final String version;
    66   //static final String vendor;
    68   protected static final TransformerFactory transformerFactory = TransformerFactory.newInstance();
    70    //removing support for Java 1.4 and 1.3 : CR6658158
    71     /*static {
    72     version = System.getProperty("java.vm.version");
    73     vendor = System.getProperty("java.vm.vendor");
    74     if (vendor.startsWith("Sun") &&
    75     (version.startsWith("1.4") || version.startsWith("1.3"))) {
    76     transformerFactory =
    77     new com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl();
    78     }
    79 }
    80 */
    82     /**
    83      * TransformerFactory instance.
    84      */
    86     /**
    87      * Underlying XSLT transformer.
    88      */
    89     private Transformer m_realTransformer = null;
    91     /**
    92      * Undelying FI DOM parser.
    93      */
    94     private Object m_fiDOMDocumentParser = null;
    96     /**
    97      * Underlying FI DOM serializer.
    98      */
    99     private Object m_fiDOMDocumentSerializer = null;
   101     private EfficientStreamingTransformer() {
   102     }
   104     private void materialize() throws TransformerException {
   105         if (m_realTransformer == null) {
   106             m_realTransformer = transformerFactory.newTransformer();
   107         }
   108     }
   110     public void clearParameters() {
   111         if (m_realTransformer != null)
   112             m_realTransformer.clearParameters();
   113     }
   115     public javax.xml.transform.ErrorListener getErrorListener() {
   116         try {
   117             materialize();
   118             return m_realTransformer.getErrorListener();
   119         } catch (TransformerException e) {
   120             // will be caught later
   121         }
   122         return null;
   123     }
   125     public java.util.Properties getOutputProperties() {
   126         try {
   127             materialize();
   128             return m_realTransformer.getOutputProperties();
   129         } catch (TransformerException e) {
   130             // will be caught later
   131         }
   132         return null;
   133     }
   135     public String getOutputProperty(String str)
   136         throws java.lang.IllegalArgumentException {
   137         try {
   138             materialize();
   139             return m_realTransformer.getOutputProperty(str);
   140         } catch (TransformerException e) {
   141             // will be caught later
   142         }
   143         return null;
   144     }
   146     public Object getParameter(String str) {
   147         try {
   148             materialize();
   149             return m_realTransformer.getParameter(str);
   150         } catch (TransformerException e) {
   151             // will be caught later
   152         }
   153         return null;
   154     }
   156     public javax.xml.transform.URIResolver getURIResolver() {
   157         try {
   158             materialize();
   159             return m_realTransformer.getURIResolver();
   160         } catch (TransformerException e) {
   161             // will be caught later
   162         }
   163         return null;
   164     }
   166     public void setErrorListener(
   167         javax.xml.transform.ErrorListener errorListener)
   168         throws java.lang.IllegalArgumentException {
   169         try {
   170             materialize();
   171             m_realTransformer.setErrorListener(errorListener);
   172         } catch (TransformerException e) {
   173             // will be caught later
   174         }
   175     }
   177     public void setOutputProperties(java.util.Properties properties)
   178         throws java.lang.IllegalArgumentException {
   179         try {
   180             materialize();
   181             m_realTransformer.setOutputProperties(properties);
   182         } catch (TransformerException e) {
   183             // will be caught later
   184         }
   185     }
   187     public void setOutputProperty(String str, String str1)
   188         throws java.lang.IllegalArgumentException {
   189         try {
   190             materialize();
   191             m_realTransformer.setOutputProperty(str, str1);
   192         } catch (TransformerException e) {
   193             // will be caught later
   194         }
   195     }
   197     public void setParameter(String str, Object obj) {
   198         try {
   199             materialize();
   200             m_realTransformer.setParameter(str, obj);
   201         } catch (TransformerException e) {
   202             // will be caught later
   203         }
   204     }
   206     public void setURIResolver(javax.xml.transform.URIResolver uRIResolver) {
   207         try {
   208             materialize();
   209             m_realTransformer.setURIResolver(uRIResolver);
   210         } catch (TransformerException e) {
   211             // will be caught later
   212         }
   213     }
   215     private InputStream getInputStreamFromSource(StreamSource s)
   216         throws TransformerException {
   218         InputStream stream = s.getInputStream();
   219         if (stream != null)
   220             return stream;
   222         if (s.getReader() != null)
   223             return null;
   225         String systemId = s.getSystemId();
   226         if (systemId != null) {
   227             try {
   228                 String fileURL = systemId;
   230                 if (systemId.startsWith("file:///"))
   231                 {
   232                     /*
   233                      systemId is:
   234                      file:///<drive>:/some/path/file.xml
   235                      or
   236                      file:///some/path/file.xml
   237                     */
   239                     String absolutePath = systemId.substring(7);
   240                     /*
   241                      /<drive>:/some/path/file.xml
   242                      or
   243                      /some/path/file.xml
   244                     */
   246                     boolean hasDriveDesignator = absolutePath.indexOf(":") > 0;
   247                     if (hasDriveDesignator) {
   248                       String driveDesignatedPath = absolutePath.substring(1);
   249                       /*
   250                       <drive>:/some/path/file.xml */
   251                       fileURL = driveDesignatedPath;
   252                     }
   253                     else {
   254                       /*
   255                       /some/path/file.xml */
   256                       fileURL = absolutePath;
   257                     }
   258                 }
   259                 return new FileInputStream(fileURL);
   260             } catch (IOException e) {
   261                 throw new TransformerException(e.toString());
   262             }
   263         }
   265         throw new TransformerException("Unexpected StreamSource object");
   266     }
   268     //------------------------------------------------------------------------
   270     public void transform(
   271         javax.xml.transform.Source source,
   272         javax.xml.transform.Result result)
   273         throws javax.xml.transform.TransformerException
   274     {
   275         // StreamSource -> StreamResult
   276         if ((source instanceof StreamSource)
   277             && (result instanceof StreamResult)) {
   278             try {
   279                 StreamSource streamSource = (StreamSource) source;
   280                 InputStream is = getInputStreamFromSource(streamSource);
   282                 OutputStream os = ((StreamResult) result).getOutputStream();
   283                 if (os == null)
   284                     // TODO: We might want to fix this if it were to be used beyond
   285                     // XmlDataContentHandler that we know uses only OutputStream
   286                     throw new TransformerException("Unexpected StreamResult object contains null OutputStream");
   288                 if (is != null) {
   289                     if (is.markSupported())
   290                         is.mark(Integer.MAX_VALUE);
   291                     int num;
   292                     byte[] b = new byte[8192];
   293                     while ((num = is.read(b)) != -1) {
   294                         os.write(b, 0, num);
   295                     }
   296                     if (is.markSupported())
   297                         is.reset();
   298                     return;
   299                 }
   301                 Reader reader = streamSource.getReader();
   302                 if (reader != null) {
   304                     if (reader.markSupported())
   305                         reader.mark(Integer.MAX_VALUE);
   307                     PushbackReader pushbackReader = new PushbackReader(reader, 4096);
   308                     //some size to unread <?xml ....?>
   309                     XMLDeclarationParser ev =
   310                         new XMLDeclarationParser(pushbackReader);
   311                     try {
   312                         ev.parse();
   313                     } catch (Exception ex) {
   314                         throw new TransformerException(
   315                             "Unable to run the JAXP transformer on a stream "
   316                                 + ex.getMessage());
   317                     }
   318                     Writer writer =
   319                         new OutputStreamWriter(os /*, ev.getEncoding()*/);
   320                     ev.writeTo(writer);         // doesn't write any, if no header
   322                     int num;
   323                     char[] ac = new char[8192];
   324                     while ((num = pushbackReader.read(ac)) != -1) {
   325                         writer.write(ac, 0, num);
   326                     }
   327                     writer.flush();
   329                     if (reader.markSupported())
   330                         reader.reset();
   331                     return;
   332                 }
   333             } catch (IOException e) {
   334                 e.printStackTrace();
   335                 throw new TransformerException(e.toString());
   336             }
   338             throw new TransformerException("Unexpected StreamSource object");
   339         }
   340         // FastInfosetSource -> DOMResult
   341         else if (FastInfosetReflection.isFastInfosetSource(source)
   342                 && (result instanceof DOMResult))
   343         {
   344             try {
   345                 // Use reflection to avoid a static dep with FI
   346                 if (m_fiDOMDocumentParser == null) {
   347                     m_fiDOMDocumentParser = FastInfosetReflection.DOMDocumentParser_new();
   348                 }
   350                 // m_fiDOMDocumentParser.parse(document, source.getInputStream())
   351                 FastInfosetReflection.DOMDocumentParser_parse(
   352                     m_fiDOMDocumentParser,
   353                     (Document) ((DOMResult) result).getNode(),
   354                     FastInfosetReflection.FastInfosetSource_getInputStream(source));
   356                 // We're done!
   357                 return;
   358             }
   359             catch (Exception e) {
   360                 throw new TransformerException(e);
   361             }
   362         }
   363         // DOMSource -> FastInfosetResult
   364         else if ((source instanceof DOMSource)
   365                 && FastInfosetReflection.isFastInfosetResult(result))
   366         {
   367             try {
   368                 // Use reflection to avoid a static dep with FI
   369                 if (m_fiDOMDocumentSerializer == null) {
   370                     m_fiDOMDocumentSerializer = FastInfosetReflection.DOMDocumentSerializer_new();
   371                 }
   373                 // m_fiDOMDocumentSerializer.setOutputStream(result.getOutputStream())
   374                 FastInfosetReflection.DOMDocumentSerializer_setOutputStream(
   375                     m_fiDOMDocumentSerializer,
   376                     FastInfosetReflection.FastInfosetResult_getOutputStream(result));
   378                 // m_fiDOMDocumentSerializer.serialize(node)
   379                 FastInfosetReflection.DOMDocumentSerializer_serialize(
   380                     m_fiDOMDocumentSerializer,
   381                     ((DOMSource) source).getNode());
   383                 // We're done!
   384                 return;
   385             }
   386             catch (Exception e) {
   387                 throw new TransformerException(e);
   388             }
   389         }
   391         // All other cases -- use transformer object
   393         materialize();
   394         m_realTransformer.transform(source, result);
   395     }
   397     /**
   398      * Threadlocal to hold a Transformer instance for this thread.
   399      */
   400     private static ThreadLocal effTransformer = new ThreadLocal();
   402     /**
   403      * Return Transformer instance for this thread, allocating a new one if
   404      * necessary. Note that this method does not clear global parameters,
   405      * properties or any other data set on a previously used transformer.
   406      */
   407     public static Transformer newTransformer() {
   408         Transformer tt = (Transformer) effTransformer.get();
   409         if (tt == null) {
   410             effTransformer.set(tt = new EfficientStreamingTransformer());
   411         }
   412         return tt;
   413     }
   415 }

mercurial