Save This Page
Home » axiom-1.2.8-src » org.apache.axiom.om.impl » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements. See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership. The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License. You may obtain a copy of the License at
    9    *
   10    * http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied. See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.
   18    */
   19   
   20   package org.apache.axiom.om.impl;
   21   
   22   import java.io.ByteArrayOutputStream;
   23   import java.io.IOException;
   24   import java.io.OutputStream;
   25   import java.io.UnsupportedEncodingException;
   26   import java.util.LinkedList;
   27   
   28   import javax.activation.DataHandler;
   29   import javax.xml.namespace.NamespaceContext;
   30   import javax.xml.stream.FactoryConfigurationError;
   31   import javax.xml.stream.XMLStreamException;
   32   import javax.xml.stream.XMLStreamWriter;
   33   
   34   import org.apache.axiom.attachments.impl.BufferUtils;
   35   import org.apache.axiom.om.OMException;
   36   import org.apache.axiom.om.OMNode;
   37   import org.apache.axiom.om.OMOutputFormat;
   38   import org.apache.axiom.om.OMText;
   39   import org.apache.axiom.om.util.CommonUtils;
   40   import org.apache.axiom.om.util.StAXUtils;
   41   import org.apache.axiom.soap.SOAP11Constants;
   42   import org.apache.axiom.soap.SOAP12Constants;
   43   import org.apache.commons.logging.Log;
   44   import org.apache.commons.logging.LogFactory;
   45   
   46   
   47   /**
   48    * MTOMXMLStreamWriter is an XML + Attachments stream writer.
   49    * 
   50    * For the moment this assumes that transport takes the decision of whether to optimize or not by
   51    * looking at whether the MTOM optimize is enabled & also looking at the OM tree whether it has any
   52    * optimizable content.
   53    */
   54   public class MTOMXMLStreamWriter implements XMLStreamWriter {
   55       private static Log log = LogFactory.getLog(MTOMXMLStreamWriter.class);
   56       private static boolean isDebugEnabled = log.isDebugEnabled();
   57       private static boolean isTraceEnabled = log.isTraceEnabled();
   58       private final static int UNSUPPORTED = -1;
   59       private final static int EXCEED_LIMIT = 1;
   60       private XMLStreamWriter xmlWriter;
   61       private OutputStream outStream;
   62       private LinkedList binaryNodeList = new LinkedList();
   63       private ByteArrayOutputStream bufferedXML;  // XML for the SOAPPart
   64       private OMOutputFormat format = new OMOutputFormat();
   65       
   66       // State variables
   67       private boolean isEndDocument = false; // has endElement been called
   68       private boolean isComplete = false;    // have the attachments been written
   69       private int depth = 0;                 // current eleement depth
   70   
   71       public MTOMXMLStreamWriter(XMLStreamWriter xmlWriter) {
   72           this.xmlWriter = xmlWriter;
   73           if (isTraceEnabled) {
   74               log.trace("Call Stack =" + CommonUtils.callStackToString());
   75           }
   76       }
   77   
   78       /**
   79        * Creates a new MTOMXMLStreamWriter with specified encoding.
   80        *
   81        * @param outStream
   82        * @param format
   83        * @throws XMLStreamException
   84        * @throws FactoryConfigurationError
   85        * @see OMOutputFormat#DEFAULT_CHAR_SET_ENCODING
   86        */
   87       public MTOMXMLStreamWriter(OutputStream outStream, OMOutputFormat format)
   88               throws XMLStreamException, FactoryConfigurationError {
   89           if (isDebugEnabled) {
   90               log.debug("OutputStream =" + outStream.getClass());
   91               log.debug("OMFormat = " + format.toString());
   92           }
   93           if (isTraceEnabled) {
   94               log.trace("Call Stack =" + CommonUtils.callStackToString());
   95           }
   96           this.format = format;
   97           this.outStream = outStream;
   98   
   99           if (format.getCharSetEncoding() == null) //Default encoding is UTF-8
  100               format.setCharSetEncoding(OMOutputFormat.DEFAULT_CHAR_SET_ENCODING);
  101   
  102           if (format.isOptimized()) {
  103               // REVIEW If the buffered XML gets too big, should it be written out to a file 
  104               bufferedXML = new ByteArrayOutputStream();
  105               xmlWriter = StAXUtils.createXMLStreamWriter(bufferedXML,format.getCharSetEncoding());
  106           } else {
  107               xmlWriter = StAXUtils.createXMLStreamWriter(outStream,
  108                                                           format.getCharSetEncoding());
  109           }
  110       }
  111   
  112       public void writeStartElement(String string) throws XMLStreamException {
  113           xmlWriter.writeStartElement(string);
  114           depth++;
  115       }
  116   
  117       public void writeStartElement(String string, String string1) throws XMLStreamException {
  118           xmlWriter.writeStartElement(string, string1);
  119           depth++;
  120       }
  121   
  122       public void writeStartElement(String string, String string1, String string2)
  123               throws XMLStreamException {
  124           xmlWriter.writeStartElement(string, string1, string2);
  125           depth++;
  126       }
  127   
  128       public void writeEmptyElement(String string, String string1) throws XMLStreamException {
  129           xmlWriter.writeEmptyElement(string, string1);
  130       }
  131   
  132       public void writeEmptyElement(String string, String string1, String string2)
  133               throws XMLStreamException {
  134           xmlWriter.writeEmptyElement(string, string1, string2);
  135       }
  136   
  137       public void writeEmptyElement(String string) throws XMLStreamException {
  138           xmlWriter.writeEmptyElement(string);
  139       }
  140   
  141       public void writeEndElement() throws XMLStreamException {
  142           xmlWriter.writeEndElement();
  143           depth--;
  144       }
  145   
  146       public void writeEndDocument() throws XMLStreamException {
  147           if (isDebugEnabled) {
  148               log.debug("writeEndDocument");
  149           }
  150           xmlWriter.writeEndDocument();
  151           isEndDocument = true; 
  152       }
  153   
  154       public void close() throws XMLStreamException {
  155           if (isDebugEnabled) {
  156               log.debug("close");
  157           }
  158           xmlWriter.close();
  159       }
  160   
  161       /**
  162        * Flush is overridden to trigger the attachment serialization
  163        */
  164       public void flush() throws XMLStreamException {
  165           if (isDebugEnabled) {
  166               log.debug("Calling MTOMXMLStreamWriter.flush");
  167           }
  168           xmlWriter.flush();
  169           String SOAPContentType;
  170           // flush() triggers the optimized attachment writing.
  171           // If the optimized attachments are specified, and the xml
  172           // document is completed, then write out the attachments.
  173           if (format.isOptimized() && !isComplete & (isEndDocument || depth == 0)) {
  174               if (isDebugEnabled) {
  175                   log.debug("The XML writing is completed.  Now the attachments are written");
  176               }
  177               isComplete = true;
  178               if (format.isSOAP11()) {
  179                   SOAPContentType = SOAP11Constants.SOAP_11_CONTENT_TYPE;
  180               } else {
  181                   SOAPContentType = SOAP12Constants.SOAP_12_CONTENT_TYPE;
  182               }
  183               try {
  184                   MIMEOutputUtils.complete(outStream,
  185                                            bufferedXML.toByteArray(),
  186                                            binaryNodeList,
  187                                            format.getMimeBoundary(),
  188                                            format.getRootContentId(),
  189                                            format.getCharSetEncoding(),
  190                                            SOAPContentType, 
  191                                            format);
  192                   bufferedXML.close();
  193                   bufferedXML = null;
  194               } catch (UnsupportedEncodingException e) {
  195                   throw new OMException(e);
  196               } catch (IOException e) {
  197                   throw new OMException(e);
  198               }
  199           }
  200       }
  201       
  202   
  203       public void writeAttribute(String string, String string1) throws XMLStreamException {
  204           xmlWriter.writeAttribute(string, string1);
  205       }
  206   
  207       public void writeAttribute(String string, String string1, String string2, String string3)
  208               throws XMLStreamException {
  209           xmlWriter.writeAttribute(string, string1, string2, string3);
  210       }
  211   
  212       public void writeAttribute(String string, String string1, String string2)
  213               throws XMLStreamException {
  214           xmlWriter.writeAttribute(string, string1, string2);
  215       }
  216   
  217       public void writeNamespace(String string, String string1) throws XMLStreamException {
  218           xmlWriter.writeNamespace(string, string1);
  219       }
  220   
  221       public void writeDefaultNamespace(String string) throws XMLStreamException {
  222           xmlWriter.writeDefaultNamespace(string);
  223       }
  224   
  225       public void writeComment(String string) throws XMLStreamException {
  226           xmlWriter.writeComment(string);
  227       }
  228   
  229       public void writeProcessingInstruction(String string) throws XMLStreamException {
  230           xmlWriter.writeProcessingInstruction(string);
  231       }
  232   
  233       public void writeProcessingInstruction(String string, String string1)
  234               throws XMLStreamException {
  235           xmlWriter.writeProcessingInstruction(string, string1);
  236       }
  237   
  238       public void writeCData(String string) throws XMLStreamException {
  239           xmlWriter.writeCData(string);
  240       }
  241   
  242       public void writeDTD(String string) throws XMLStreamException {
  243           xmlWriter.writeDTD(string);
  244       }
  245   
  246       public void writeEntityRef(String string) throws XMLStreamException {
  247           xmlWriter.writeEntityRef(string);
  248       }
  249   
  250       public void writeStartDocument() throws XMLStreamException {
  251           xmlWriter.writeStartDocument();
  252       }
  253   
  254       public void writeStartDocument(String string) throws XMLStreamException {
  255           xmlWriter.writeStartDocument(string);
  256       }
  257   
  258       public void writeStartDocument(String string, String string1) throws XMLStreamException {
  259           xmlWriter.writeStartDocument(string, string1);
  260       }
  261   
  262       public void writeCharacters(String string) throws XMLStreamException {
  263           xmlWriter.writeCharacters(string);
  264       }
  265   
  266       public void writeCharacters(char[] chars, int i, int i1) throws XMLStreamException {
  267           xmlWriter.writeCharacters(chars, i, i1);
  268       }
  269   
  270       public String getPrefix(String string) throws XMLStreamException {
  271           return xmlWriter.getPrefix(string);
  272       }
  273   
  274       public void setPrefix(String string, String string1) throws XMLStreamException {
  275           xmlWriter.setPrefix(string, string1);
  276       }
  277   
  278       public void setDefaultNamespace(String string) throws XMLStreamException {
  279           xmlWriter.setDefaultNamespace(string);
  280       }
  281   
  282       public void setNamespaceContext(NamespaceContext namespaceContext) throws XMLStreamException {
  283           xmlWriter.setNamespaceContext(namespaceContext);
  284       }
  285   
  286       public NamespaceContext getNamespaceContext() {
  287           return xmlWriter.getNamespaceContext();
  288       }
  289   
  290       public Object getProperty(String string) throws IllegalArgumentException {
  291           return xmlWriter.getProperty(string);
  292       }
  293   
  294       public boolean isOptimized() {
  295           return format.isOptimized();
  296       }
  297   
  298       public String getContentType() {
  299           return format.getContentType();
  300       }
  301   
  302       public void writeOptimized(OMText node) {
  303           if(isDebugEnabled){
  304               log.debug("Start MTOMXMLStreamWriter.writeOptimized()");
  305           }
  306           binaryNodeList.add(node);    
  307           if(isDebugEnabled){
  308               log.debug("Exit MTOMXMLStreamWriter.writeOptimized()");
  309           }
  310       }
  311       /*
  312        * This method check if size of dataHandler exceeds the optimization Threshold
  313        * set on OMOutputFormat. 
  314        * return true is size exceeds the threshold limit.
  315        * return false otherwise.
  316        */
  317       public boolean isOptimizedThreshold(OMText node){
  318       	if(isDebugEnabled){
  319               log.debug("Start MTOMXMLStreamWriter.isOptimizedThreshold()");
  320           }
  321           DataHandler dh = (DataHandler)node.getDataHandler();
  322           int optimized = UNSUPPORTED;
  323           if(dh!=null){
  324               if(isDebugEnabled){
  325                   log.debug("DataHandler fetched, starting optimized Threshold processing");
  326               }
  327               optimized= BufferUtils.doesDataHandlerExceedLimit(dh, format.getOptimizedThreshold());
  328           }
  329           if(optimized == UNSUPPORTED || optimized == EXCEED_LIMIT){
  330               if(log.isDebugEnabled()){
  331                   log.debug("node should be added to binart NodeList for optimization");
  332               }
  333               return true;
  334           }
  335           return false;
  336       }
  337       
  338       public void setXmlStreamWriter(XMLStreamWriter xmlWriter) {
  339           this.xmlWriter = xmlWriter;
  340       }
  341   
  342       public XMLStreamWriter getXmlStreamWriter() {
  343           return xmlWriter;
  344       }
  345   
  346       public String getMimeBoundary() {
  347           return format.getMimeBoundary();
  348       }
  349   
  350       public String getRootContentId() {
  351           return format.getRootContentId();
  352       }
  353   
  354       public String getNextContentId() {
  355           return format.getNextContentId();
  356       }
  357   
  358       /**
  359        * Returns the character set encoding scheme. If the value of the charSetEncoding is not set
  360        * then the default will be returned.
  361        *
  362        * @return Returns encoding.
  363        */
  364       public String getCharSetEncoding() {
  365           return format.getCharSetEncoding();
  366       }
  367   
  368       public void setCharSetEncoding(String charSetEncoding) {
  369           format.setCharSetEncoding(charSetEncoding);
  370       }
  371   
  372       public String getXmlVersion() {
  373           return format.getXmlVersion();
  374       }
  375   
  376       public void setXmlVersion(String xmlVersion) {
  377           format.setXmlVersion(xmlVersion);
  378       }
  379   
  380       public void setSoap11(boolean b) {
  381           format.setSOAP11(b);
  382       }
  383   
  384       public boolean isIgnoreXMLDeclaration() {
  385           return format.isIgnoreXMLDeclaration();
  386       }
  387   
  388       public void setIgnoreXMLDeclaration(boolean ignoreXMLDeclaration) {
  389           format.setIgnoreXMLDeclaration(ignoreXMLDeclaration);
  390       }
  391   
  392       public void setDoOptimize(boolean b) {
  393           format.setDoOptimize(b);
  394       }
  395   
  396       /**
  397        * Get the output format used by this writer.
  398        * <p>
  399        * The caller should use the returned instance in a read-only way, i.e.
  400        * he should not modify the settings of the output format. Any attempt
  401        * to do so will lead to unpredictable results.
  402        * 
  403        * @return the output format used by this writer
  404        */
  405       public OMOutputFormat getOutputFormat() {
  406           return format;
  407       }
  408   
  409       public void setOutputFormat(OMOutputFormat format) {
  410           this.format = format;
  411       }
  412       
  413       /**
  414        * If this XMLStreamWriter is connected to an OutputStream
  415        * then the OutputStream is returned.  This allows a node
  416        * (perhaps an OMSourcedElement) to write its content
  417        * directly to the OutputStream.
  418        * @return OutputStream or null
  419        */
  420       public OutputStream getOutputStream() throws XMLStreamException {  
  421           OutputStream os = null;
  422           if (bufferedXML != null) {
  423               os = bufferedXML;
  424           } else {
  425               os = outStream;
  426           }
  427           
  428           if (isDebugEnabled) {
  429               if (os == null) {
  430                   log.debug("Direct access to the output stream is not available.");
  431               } else if (bufferedXML != null) {
  432                   log.debug("Returning access to the buffered xml stream: " + bufferedXML);
  433               } else {
  434                   log.debug("Returning access to the original output stream: " + os);
  435               }
  436           }
  437          
  438           if (os != null) {
  439               // Flush the state of the writer..Many times the 
  440               // write defers the writing of tag characters (>)
  441               // until the next write.  Flush out this character
  442               this.writeCharacters(""); 
  443               this.flush();
  444           }
  445           return os;
  446       }
  447       
  448       /**
  449        * Writes the relevant output.
  450        *
  451        * @param writer
  452        * @throws XMLStreamException
  453        */
  454       private void writeOutput(OMText textNode) throws XMLStreamException {
  455           int type = textNode.getType();
  456           if (type == OMNode.TEXT_NODE || type == OMNode.SPACE_NODE) {
  457               writeCharacters(textNode.getText());
  458           } else if (type == OMNode.CDATA_SECTION_NODE) {
  459               writeCData(textNode.getText());
  460           } else if (type == OMNode.ENTITY_REFERENCE_NODE) {
  461               writeEntityRef(textNode.getText());
  462           }
  463       }
  464   }

Save This Page
Home » axiom-1.2.8-src » org.apache.axiom.om.impl » [javadoc | source]