jaxws/src/java.xml.soap/share/classes/com/sun/xml/internal/messaging/saaj/util/transform/EfficientStreamingTransformer.java
changeset 28641 6b05689b7445
parent 28640 01e4ca94fb0d
parent 28505 7574ac3bb6c1
child 28642 a42fefc69922
equal deleted inserted replaced
28640:01e4ca94fb0d 28641:6b05689b7445
     1 /*
       
     2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 /*
       
    27  * EfficientStreamingTransformer.java
       
    28  *
       
    29  * Created on July 29, 2002, 3:49 PM
       
    30  */
       
    31 
       
    32 package com.sun.xml.internal.messaging.saaj.util.transform;
       
    33 
       
    34 import java.io.*;
       
    35 
       
    36 import java.net.URISyntaxException;
       
    37 import javax.xml.transform.dom.DOMSource;
       
    38 import javax.xml.transform.dom.DOMResult;
       
    39 import javax.xml.transform.stream.StreamResult;
       
    40 import javax.xml.transform.stream.StreamSource;
       
    41 
       
    42 import org.w3c.dom.Document;
       
    43 
       
    44 import com.sun.xml.internal.messaging.saaj.util.XMLDeclarationParser;
       
    45 import com.sun.xml.internal.messaging.saaj.util.FastInfosetReflection;
       
    46 import java.net.URI;
       
    47 import javax.xml.transform.Transformer;
       
    48 import javax.xml.transform.TransformerException;
       
    49 import javax.xml.transform.TransformerFactory;
       
    50 
       
    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 {
       
    64 
       
    65   //static final String version;
       
    66   //static final String vendor;
       
    67   // removing static : security issue : CR 6813167Z
       
    68   private final TransformerFactory transformerFactory = TransformerFactory.newInstance();
       
    69 
       
    70   /**
       
    71   removing support for Java 1.4 and 1.3 : CR6658158
       
    72   static {
       
    73         version = System.getProperty("java.vm.version");
       
    74         vendor = System.getProperty("java.vm.vendor");
       
    75         if (vendor.startsWith("Sun") &&
       
    76             (version.startsWith("1.4") || version.startsWith("1.3"))) {
       
    77             transformerFactory =
       
    78                 new com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl();
       
    79         }
       
    80   }*/
       
    81 
       
    82     /**
       
    83      * TransformerFactory instance.
       
    84      */
       
    85 
       
    86     /**
       
    87      * Underlying XSLT transformer.
       
    88      */
       
    89     private Transformer m_realTransformer = null;
       
    90 
       
    91     /**
       
    92      * Undelying FI DOM parser.
       
    93      */
       
    94     private Object m_fiDOMDocumentParser = null;
       
    95 
       
    96     /**
       
    97      * Underlying FI DOM serializer.
       
    98      */
       
    99     private Object m_fiDOMDocumentSerializer = null;
       
   100 
       
   101     private EfficientStreamingTransformer() {
       
   102     }
       
   103 
       
   104     private void materialize() throws TransformerException {
       
   105         if (m_realTransformer == null) {
       
   106             m_realTransformer = transformerFactory.newTransformer();
       
   107         }
       
   108     }
       
   109 
       
   110     public void clearParameters() {
       
   111         if (m_realTransformer != null)
       
   112             m_realTransformer.clearParameters();
       
   113     }
       
   114 
       
   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     }
       
   124 
       
   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     }
       
   134 
       
   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     }
       
   145 
       
   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     }
       
   155 
       
   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     }
       
   165 
       
   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     }
       
   176 
       
   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     }
       
   186 
       
   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     }
       
   196 
       
   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     }
       
   205 
       
   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     }
       
   214 
       
   215     private InputStream getInputStreamFromSource(StreamSource s)
       
   216         throws TransformerException {
       
   217 
       
   218         InputStream stream = s.getInputStream();
       
   219         if (stream != null)
       
   220             return stream;
       
   221 
       
   222         if (s.getReader() != null)
       
   223             return null;
       
   224 
       
   225         String systemId = s.getSystemId();
       
   226         if (systemId != null) {
       
   227             try {
       
   228                 String fileURL = systemId;
       
   229 
       
   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                     */
       
   238 
       
   239                     String absolutePath = systemId.substring(7);
       
   240                     /*
       
   241                      /<drive>:/some/path/file.xml
       
   242                      or
       
   243                      /some/path/file.xml
       
   244                     */
       
   245 
       
   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                 try {
       
   261                     return new FileInputStream(new File(new URI(fileURL)));
       
   262                 } catch (URISyntaxException ex) {
       
   263                     throw new TransformerException(ex);
       
   264                 }
       
   265             } catch (IOException e) {
       
   266                 throw new TransformerException(e.toString());
       
   267             }
       
   268         }
       
   269 
       
   270         throw new TransformerException("Unexpected StreamSource object");
       
   271     }
       
   272 
       
   273     //------------------------------------------------------------------------
       
   274 
       
   275     public void transform(
       
   276         javax.xml.transform.Source source,
       
   277         javax.xml.transform.Result result)
       
   278         throws javax.xml.transform.TransformerException
       
   279     {
       
   280         // StreamSource -> StreamResult
       
   281         if ((source instanceof StreamSource)
       
   282             && (result instanceof StreamResult)) {
       
   283             try {
       
   284                 StreamSource streamSource = (StreamSource) source;
       
   285                 InputStream is = getInputStreamFromSource(streamSource);
       
   286 
       
   287                 OutputStream os = ((StreamResult) result).getOutputStream();
       
   288                 if (os == null)
       
   289                     // TODO: We might want to fix this if it were to be used beyond
       
   290                     // XmlDataContentHandler that we know uses only OutputStream
       
   291                     throw new TransformerException("Unexpected StreamResult object contains null OutputStream");
       
   292 
       
   293                 if (is != null) {
       
   294                     if (is.markSupported())
       
   295                         is.mark(Integer.MAX_VALUE);
       
   296                     int num;
       
   297                     byte[] b = new byte[8192];
       
   298                     while ((num = is.read(b)) != -1) {
       
   299                         os.write(b, 0, num);
       
   300                     }
       
   301                     if (is.markSupported())
       
   302                         is.reset();
       
   303                     return;
       
   304                 }
       
   305 
       
   306                 Reader reader = streamSource.getReader();
       
   307                 if (reader != null) {
       
   308 
       
   309                     if (reader.markSupported())
       
   310                         reader.mark(Integer.MAX_VALUE);
       
   311 
       
   312                     PushbackReader pushbackReader = new PushbackReader(reader, 4096);
       
   313                     //some size to unread <?xml ....?>
       
   314                     XMLDeclarationParser ev =
       
   315                         new XMLDeclarationParser(pushbackReader);
       
   316                     try {
       
   317                         ev.parse();
       
   318                     } catch (Exception ex) {
       
   319                         throw new TransformerException(
       
   320                             "Unable to run the JAXP transformer on a stream "
       
   321                                 + ex.getMessage());
       
   322                     }
       
   323                     Writer writer =
       
   324                         new OutputStreamWriter(os /*, ev.getEncoding()*/);
       
   325                     ev.writeTo(writer);         // doesn't write any, if no header
       
   326 
       
   327                     int num;
       
   328                     char[] ac = new char[8192];
       
   329                     while ((num = pushbackReader.read(ac)) != -1) {
       
   330                         writer.write(ac, 0, num);
       
   331                     }
       
   332                     writer.flush();
       
   333 
       
   334                     if (reader.markSupported())
       
   335                         reader.reset();
       
   336                     return;
       
   337                 }
       
   338             } catch (IOException e) {
       
   339                 e.printStackTrace();
       
   340                 throw new TransformerException(e.toString());
       
   341             }
       
   342 
       
   343             throw new TransformerException("Unexpected StreamSource object");
       
   344         }
       
   345         // FastInfosetSource -> DOMResult
       
   346         else if (FastInfosetReflection.isFastInfosetSource(source)
       
   347                 && (result instanceof DOMResult))
       
   348         {
       
   349             try {
       
   350                 // Use reflection to avoid a static dep with FI
       
   351                 if (m_fiDOMDocumentParser == null) {
       
   352                     m_fiDOMDocumentParser = FastInfosetReflection.DOMDocumentParser_new();
       
   353                 }
       
   354 
       
   355                 // m_fiDOMDocumentParser.parse(document, source.getInputStream())
       
   356                 FastInfosetReflection.DOMDocumentParser_parse(
       
   357                     m_fiDOMDocumentParser,
       
   358                     (Document) ((DOMResult) result).getNode(),
       
   359                     FastInfosetReflection.FastInfosetSource_getInputStream(source));
       
   360 
       
   361                 // We're done!
       
   362                 return;
       
   363             }
       
   364             catch (Exception e) {
       
   365                 throw new TransformerException(e);
       
   366             }
       
   367         }
       
   368         // DOMSource -> FastInfosetResult
       
   369         else if ((source instanceof DOMSource)
       
   370                 && FastInfosetReflection.isFastInfosetResult(result))
       
   371         {
       
   372             try {
       
   373                 // Use reflection to avoid a static dep with FI
       
   374                 if (m_fiDOMDocumentSerializer == null) {
       
   375                     m_fiDOMDocumentSerializer = FastInfosetReflection.DOMDocumentSerializer_new();
       
   376                 }
       
   377 
       
   378                 // m_fiDOMDocumentSerializer.setOutputStream(result.getOutputStream())
       
   379                 FastInfosetReflection.DOMDocumentSerializer_setOutputStream(
       
   380                     m_fiDOMDocumentSerializer,
       
   381                     FastInfosetReflection.FastInfosetResult_getOutputStream(result));
       
   382 
       
   383                 // m_fiDOMDocumentSerializer.serialize(node)
       
   384                 FastInfosetReflection.DOMDocumentSerializer_serialize(
       
   385                     m_fiDOMDocumentSerializer,
       
   386                     ((DOMSource) source).getNode());
       
   387 
       
   388                 // We're done!
       
   389                 return;
       
   390             }
       
   391             catch (Exception e) {
       
   392                 throw new TransformerException(e);
       
   393             }
       
   394         }
       
   395 
       
   396         // All other cases -- use transformer object
       
   397 
       
   398         materialize();
       
   399         m_realTransformer.transform(source, result);
       
   400     }
       
   401 
       
   402     /**
       
   403      * Threadlocal to hold a Transformer instance for this thread.
       
   404      * CR : 6813167
       
   405      */
       
   406     //private static ThreadLocal effTransformer = new ThreadLocal();
       
   407 
       
   408     /**
       
   409      * Return Transformer instance for this thread, allocating a new one if
       
   410      * necessary. Note that this method does not clear global parameters,
       
   411      * properties or any other data set on a previously used transformer.
       
   412      */
       
   413     public static Transformer newTransformer() {
       
   414         //CR : 6813167
       
   415         /*Transformer tt = (Transformer) effTransformer.get();
       
   416         if (tt == null) {
       
   417             effTransformer.set(tt = new EfficientStreamingTransformer());
       
   418         }
       
   419         return tt;*/
       
   420         return new EfficientStreamingTransformer();
       
   421     }
       
   422 
       
   423 }