You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by ve...@apache.org on 2009/07/19 15:45:11 UTC

svn commit: r795540 - in /webservices/commons/trunk/modules/axiom/modules: axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/ axiom-api/src/main/java/org/apache/axiom/om/impl/ axiom-api/src/main/java/org/apache/axiom/util/stax/ axiom-api/sr...

Author: veithen
Date: Sun Jul 19 13:45:10 2009
New Revision: 795540

URL: http://svn.apache.org/viewvc?rev=795540&view=rev
Log:
More rework on the XOP/MTOM support:

* Defined a proper extension interface for XMLStreamWriter that allows serialization code to submit binary content (as DataHandler or DataHandlerProvider).
* Added an XOPEncodingStreamWriter class that implements the extension and that handles the XOP encoding.
* Changed MTOMXMLStreamWriter to use XOPEncodingStreamWriter. The XOPEncodingStreamWriter is configured to apply the settings defined in OMOutputFormat, in particular the MTOM threshold.
* Added utility methods that fall back to base64 if the XMLStreamWriter doesn't support the extension.

Result: MTOM is now completely transparent to serialization code. The code simply submits the binary content and lets the stream writer decide what to do with it (encode it as base64 or using xop:Include).

Also modified OMTextImpl and TextNodeImpl to use this new facility. This greatly simplifies the code in these classes. The change also improves consistency: e.g. DOOM's TextNodeImpl didn't check MTOM thresholds.

Successfully tested the change for non regression with Axis2 trunk.

Added:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/DataHandlerWriter.java   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OptimizationPolicyImpl.java   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/OptimizationPolicy.java   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWrapper.java   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWriter.java   (with props)
Modified:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/DataHandlerReader.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/package.html   (contents, props changed)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMStAXWrapper.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamWriterUtil.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPConstants.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReader.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReaderTest.java
    webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/TextNodeImpl.java
    webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMTextImpl.java

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/DataHandlerReader.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/DataHandlerReader.java?rev=795540&r1=795539&r2=795540&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/DataHandlerReader.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/DataHandlerReader.java Sun Jul 19 13:45:10 2009
@@ -26,22 +26,9 @@
  * Extension interface for {@link javax.xml.stream.XMLStreamReader} implementations that expose
  * base64 encoded binary content as {@link DataHandler} objects.
  * <p>
- * The {@link javax.xml.stream.XMLStreamReader} MAY implement this interface directly, but a
- * consumer MUST use {@link javax.xml.stream.XMLStreamReader#getProperty(String)} with the property
- * name defined by {@link #PROPERTY} to get a reference to this extension interface. The rationale
- * for this requirement is that a property based approach continues to work even if the
- * {@link javax.xml.stream.XMLStreamReader} implementing the extension is accessed indirectly
- * through a proxy implementing the {@link javax.xml.stream.XMLStreamReader} interface but unaware
- * of the extension. Note that this assumes that the proxy correctly delegates calls to the
- * {@link javax.xml.stream.XMLStreamReader#getProperty(String)} method.
- * <p>
- * The property defined by {@link #PROPERTY} MUST be available regardless of the current state of
- * the {@link javax.xml.stream.XMLStreamReader}. In addition it is assumed to be immutable, i.e.
- * its value MUST NOT not change during the lifetime of the {@link javax.xml.stream.XMLStreamReader}
- * implementation. For a consumer it is therefore sufficient to look up the extension once and to
- * continue using the reference returned by
- * {@link javax.xml.stream.XMLStreamReader#getProperty(String)} during the entire lifetime of the
- * {@link javax.xml.stream.XMLStreamReader}.
+ * A consumer MUST use {@link javax.xml.stream.XMLStreamReader#getProperty(String)} with the property
+ * name defined by {@link #PROPERTY} to get a reference to this extension interface. See
+ * the package Javadoc for additional requirements.
  * <p>
  * If the {@link javax.xml.stream.XMLStreamReader} wishes to expose base64 encoded content using
  * this extension interface, it MUST do so using a single

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/DataHandlerWriter.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/DataHandlerWriter.java?rev=795540&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/DataHandlerWriter.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/DataHandlerWriter.java Sun Jul 19 13:45:10 2009
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.ext.stax.datahandler;
+
+import java.io.IOException;
+
+import javax.activation.DataHandler;
+import javax.xml.stream.XMLStreamException;
+
+/**
+ * Extension interface for {@link javax.xml.stream.XMLStreamWriter} implementations that can
+ * receive base64 encoded binary content as {@link DataHandler} objects. A stream writer
+ * implementing this extension may write the binary data as base64 encoded character data
+ * or using some optimization such as XOP/MTOM.
+ * <p>
+ * A consumer MUST use {@link javax.xml.stream.XMLStreamWriter#getProperty(String)} with the property
+ * name defined by {@link #PROPERTY} to get a reference to this extension interface. See
+ * the package Javadoc for additional requirements.
+ * <p>
+ * The interface defines two methods to write binary content, one that takes a {@link DataHandler}
+ * argument and one with a {@link DataHandlerProvider} argument. The first should be used when
+ * the content is immediately available, while the second supports deferred loading of the data
+ * handler. The meaning of the <code>contentID</code> and <code>optimize</code> arguments is
+ * the same for both methods:
+ * <dl>
+ *   <dt><code>contentID</code>
+ *   <dd>
+ *     A content ID of the binary content, if available. The semantics of this argument are
+ *     similar to those defined for the return value of the
+ *     {@link DataHandlerReader#getContentID()} method:
+ *     <ul>
+ *       <li>This argument should only be set if a content ID has been used
+ *           previously in an interaction with another component or system.
+ *           The caller SHOULD NOT generate a new content ID solely for the
+ *           purpose of invoking the extension.
+ *       <li>The argument must be a raw content ID.
+ *       <li>The implementation MUST NOT make any assumption about the uniqueness or validity
+ *           of the content ID. It MAY ignore the supplied value.
+ *     </ul>
+ *   <dt><code>optimize</code>
+ *   <dd>
+ *     Specifies if binary content is eligible for optimization (e.g. using XOP) or if it should
+ *     be serialized as base64. This is only an indication and the implementation MAY choose
+ *     to override this value or ignore it entirely.
+ * </dl>
+ * Instead of interacting directly with this extension interface, the consumer may use the
+ * {@link org.apache.axiom.util.stax.XMLStreamWriterUtil#writeDataHandler(javax.xml.stream.XMLStreamWriter, DataHandler, String, boolean)} or
+ * {@link org.apache.axiom.util.stax.XMLStreamWriterUtil#writeDataHandler(javax.xml.stream.XMLStreamWriter, DataHandlerProvider, String, boolean)}
+ * utility methods. These methods make the processing of binary data entirely transparent for
+ * the caller.
+ */
+public interface DataHandlerWriter {
+    /**
+     * The name of the property used to look up this extension interface from a
+     * {@link javax.xml.stream.XMLStreamWriter} implementation.
+     */
+    String PROPERTY = DataHandlerWriter.class.getName();
+
+    /**
+     * Write binary content to the stream. The implementation may choose to write the data as base64
+     * encoded character data or using an optimization protocol such as XOP/MTOM.
+     * 
+     * @param dataHandler
+     *            the binary content to write
+     * @param contentID
+     *            an existing content ID for the binary data (see above)
+     * @param optimize
+     *            indicates whether the content is eligible for optimization (see above)
+     * @throws IOException
+     *             if an error occurs while reading from the data handler
+     * @throws XMLStreamException
+     *             if an error occurs while writing to the underlying stream
+     */
+    void writeDataHandler(DataHandler dataHandler, String contentID, boolean optimize)
+            throws IOException, XMLStreamException;
+
+    /**
+     * Write binary content to the stream. This method allows the implementation to defer loading of
+     * the content. More precisely, if the implementation decides to use an optimization scheme such
+     * as XOP, then the content will not be written immediately to the underlying stream, but only
+     * after the XML infoset is complete. If the caller uses this method, the implementation can
+     * defer the actual loading of the binary content.
+     * 
+     * @param dataHandlerProvider
+     *            the binary content to write
+     * @param contentID
+     *            an existing content ID for the binary data (see above)
+     * @param optimize
+     *            indicates whether the content is eligible for optimization (see above)
+     * @throws IOException
+     *             If an error occurs while reading from the data handler. Since the implementation
+     *             is free to override the supplied <code>optimize</code> argument, it may attempt
+     *             to load the binary data immediately. Because this operation may fail, the method
+     *             must declare this exception.
+     * @throws XMLStreamException
+     *             if an error occurs while writing to the underlying stream
+     */
+    void writeDataHandler(DataHandlerProvider dataHandlerProvider, String contentID,
+            boolean optimize) throws IOException, XMLStreamException;
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/DataHandlerWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/package.html
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/package.html?rev=795540&r1=795539&r2=795540&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/package.html (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/package.html Sun Jul 19 13:45:10 2009
@@ -1,5 +1,25 @@
 <html>
 <body>
-Defines an Axiom specific extension to the StAX API to work with DataHandler objects. 
+Defines an Axiom specific extension to the StAX API to work with DataHandler objects.
+<p>
+This package defines two extensions, {@link DataHandlerReader} for {@link javax.xml.stream.XMLStreamReader}
+and {@link DataHandlerWriter} for {@link javax.xml.stream.XMLStreamWriter}. The reader or writer wishing to support the
+extension MAY implement the corresponding interface directly, but a consumer MUST use
+the property mechanism to get a reference to this extension interface, i.e. it MUST call
+{@link javax.xml.stream.XMLStreamReader#getProperty(String)} or
+{@link javax.xml.stream.XMLStreamWriter#getProperty(String)}. The two extension interfaces
+define constants with for the property names.
+<p>
+The rationale for this requirement is that a property based approach continues to work even if the
+stream implementing the extension is accessed indirectly through a proxy implementing the
+{@link javax.xml.stream.XMLStreamReader} or {@link javax.xml.stream.XMLStreamWriter} interface but unaware
+of the extensions defined in this package. Note that this assumes that the proxy correctly delegates calls to the
+<code>getProperty</code> methods.
+<p>
+The property returning the extension interface MUST be available regardless of the current state of
+the stream. In addition it is assumed to be immutable, i.e. its value MUST NOT not change during the
+lifetime of the {@link javax.xml.stream.XMLStreamReader} or {@link javax.xml.stream.XMLStreamWriter}
+implementation. For a consumer it is therefore sufficient to look up the extension once and to
+continue using the obtained reference during the entire lifetime of the stream.
 </body>
 </html>
\ No newline at end of file

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/ext/stax/datahandler/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java?rev=795540&r1=795539&r2=795540&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java Sun Jul 19 13:45:10 2009
@@ -30,13 +30,16 @@
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 
-import org.apache.axiom.attachments.impl.BufferUtils;
 import org.apache.axiom.om.OMException;
 import org.apache.axiom.om.OMNode;
 import org.apache.axiom.om.OMOutputFormat;
 import org.apache.axiom.om.OMText;
 import org.apache.axiom.om.util.CommonUtils;
 import org.apache.axiom.om.util.StAXUtils;
+import org.apache.axiom.util.stax.XMLStreamWriterUtil;
+import org.apache.axiom.util.stax.xop.ContentIDGenerator;
+import org.apache.axiom.util.stax.xop.OptimizationPolicy;
+import org.apache.axiom.util.stax.xop.XOPEncodingStreamWriter;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -52,14 +55,13 @@
     private static Log log = LogFactory.getLog(MTOMXMLStreamWriter.class);
     private static boolean isDebugEnabled = log.isDebugEnabled();
     private static boolean isTraceEnabled = log.isTraceEnabled();
-    private final static int UNSUPPORTED = -1;
-    private final static int EXCEED_LIMIT = 1;
     private XMLStreamWriter xmlWriter;
     private OutputStream outStream;
     private LinkedList binaryNodeList = new LinkedList();
     private OMMultipartWriter multipartWriter;
     private OutputStream rootPartOutputStream;
     private OMOutputFormat format = new OMOutputFormat();
+    private final OptimizationPolicy optimizationPolicy;
     
     // State variables
     private boolean isEndDocument = false; // has endElement been called
@@ -71,6 +73,7 @@
         if (isTraceEnabled) {
             log.trace("Call Stack =" + CommonUtils.callStackToString());
         }
+        optimizationPolicy = new OptimizationPolicyImpl(format);
     }
 
     /**
@@ -99,6 +102,8 @@
             format.setCharSetEncoding(encoding = OMOutputFormat.DEFAULT_CHAR_SET_ENCODING);
         }
 
+        optimizationPolicy = new OptimizationPolicyImpl(format);
+        
         if (format.isOptimized()) {
             multipartWriter = new OMMultipartWriter(outStream, format);
             try {
@@ -106,7 +111,13 @@
             } catch (IOException ex) {
                 throw new XMLStreamException(ex);
             }
-            xmlWriter = StAXUtils.createXMLStreamWriter(rootPartOutputStream, encoding);
+            ContentIDGenerator contentIDGenerator = new ContentIDGenerator() {
+                public String generateContentID(String existingContentID) {
+                    return existingContentID != null ? existingContentID : getNextContentId();
+                }
+            };
+            xmlWriter = new XOPEncodingStreamWriter(StAXUtils.createXMLStreamWriter(
+                    rootPartOutputStream, encoding), contentIDGenerator, optimizationPolicy);
         } else {
             xmlWriter = StAXUtils.createXMLStreamWriter(outStream,
                                                         format.getCharSetEncoding());
@@ -180,6 +191,13 @@
             isComplete = true;
             try {
                 rootPartOutputStream.close();
+                // First write the attachments added properly through the DataHandlerWriter extension
+                XOPEncodingStreamWriter encoder = (XOPEncodingStreamWriter)xmlWriter;
+                for (Iterator it = encoder.getContentIDs().iterator(); it.hasNext(); ) {
+                    String contentID = (String)it.next();
+                    multipartWriter.writePart(encoder.getDataHandler(contentID), contentID);
+                }
+                // This is for compatibility with writeOptimized
                 for (Iterator it = binaryNodeList.iterator(); it.hasNext();) {
                     OMText text = (OMText) it.next();
                     multipartWriter.writePart((DataHandler) text.getDataHandler(),
@@ -284,6 +302,16 @@
         return xmlWriter.getProperty(string);
     }
 
+    /**
+     * @deprecated
+     * Serialization code should use
+     * {@link XMLStreamWriterUtil#writeDataHandler(XMLStreamWriter, DataHandler, String, boolean)}
+     * or {@link XMLStreamWriterUtil#writeDataHandler(XMLStreamWriter, org.apache.axiom.ext.stax.datahandler.DataHandlerProvider, String, boolean)}
+     * to submit any binary content and let this writer decide whether the content should be
+     * written as base64 encoded character data or using <tt>xop:Include</tt>.
+     * This makes optimization entirely transparent for the caller and there should be no need
+     * to check if the writer is producing MTOM.
+     */
     public boolean isOptimized() {
         return format.isOptimized();
     }
@@ -292,6 +320,14 @@
         return format.getContentType();
     }
 
+    /**
+     * @deprecated
+     * Serialization code should use
+     * {@link XMLStreamWriterUtil#writeDataHandler(XMLStreamWriter, DataHandler, String, boolean)}
+     * or {@link XMLStreamWriterUtil#writeDataHandler(XMLStreamWriter, org.apache.axiom.ext.stax.datahandler.DataHandlerProvider, String, boolean)}
+     * to submit any binary content and let this writer decide whether the content should be
+     * written as base64 encoded character data or using <tt>xop:Include</tt>.
+     */
     public void writeOptimized(OMText node) {
         if(isDebugEnabled){
             log.debug("Start MTOMXMLStreamWriter.writeOptimized()");
@@ -301,31 +337,25 @@
             log.debug("Exit MTOMXMLStreamWriter.writeOptimized()");
         }
     }
-    /*
-     * This method check if size of dataHandler exceeds the optimization Threshold
-     * set on OMOutputFormat. 
-     * return true is size exceeds the threshold limit.
-     * return false otherwise.
+
+    /**
+     * @deprecated
+     * Serialization code should use
+     * {@link XMLStreamWriterUtil#writeDataHandler(XMLStreamWriter, DataHandler, String, boolean)}
+     * or {@link XMLStreamWriterUtil#writeDataHandler(XMLStreamWriter, org.apache.axiom.ext.stax.datahandler.DataHandlerProvider, String, boolean)}
+     * to submit any binary content and let this writer decide whether the content should be
+     * written as base64 encoded character data or using <tt>xop:Include</tt>.
+     * Since the writer applies the settings defined in {@link OMOutputFormat} (including MTOM
+     * thresholds), there is not need for this method anymore.
      */
     public boolean isOptimizedThreshold(OMText node){
-    	if(isDebugEnabled){
-            log.debug("Start MTOMXMLStreamWriter.isOptimizedThreshold()");
-        }
-        DataHandler dh = (DataHandler)node.getDataHandler();
-        int optimized = UNSUPPORTED;
-        if(dh!=null){
-            if(isDebugEnabled){
-                log.debug("DataHandler fetched, starting optimized Threshold processing");
-            }
-            optimized= BufferUtils.doesDataHandlerExceedLimit(dh, format.getOptimizedThreshold());
-        }
-        if(optimized == UNSUPPORTED || optimized == EXCEED_LIMIT){
-            if(log.isDebugEnabled()){
-                log.debug("node should be added to binart NodeList for optimization");
-            }
+        // The optimize argument is set to true for compatibility. Indeed, older versions
+        // left it to the caller to check OMText#isOptimized().
+        try {
+            return optimizationPolicy.isOptimized((DataHandler)node.getDataHandler(), true);
+        } catch (IOException ex) {
             return true;
         }
-        return false;
     }
     
     public void setXmlStreamWriter(XMLStreamWriter xmlWriter) {

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMStAXWrapper.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMStAXWrapper.java?rev=795540&r1=795539&r2=795540&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMStAXWrapper.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMStAXWrapper.java Sun Jul 19 13:45:10 2009
@@ -33,6 +33,7 @@
 import org.apache.axiom.om.OMXMLStreamReader;
 import org.apache.axiom.om.util.UUIDGenerator;
 import org.apache.axiom.util.stax.xop.ContentIDGenerator;
+import org.apache.axiom.util.stax.xop.OptimizationPolicy;
 import org.apache.axiom.util.stax.xop.XOPEncodingStreamReader;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -101,8 +102,9 @@
             if (xopEncoder == null) {
                 // Since the intention is to support an efficient way to pass binary content to a
                 // consumer that is not aware of our data handler extension (see WSCOMMONS-344), we
-                // use optimizeAll=true, i.e. we ignore OMText#isOptimized().
-                xopEncoder = new XOPEncodingStreamReader(switchingWrapper, contentIDGenerator, true);
+                // use OptimizationPolicy.ALL, i.e. we ignore OMText#isOptimized().
+                xopEncoder = new XOPEncodingStreamReader(switchingWrapper, contentIDGenerator,
+                        OptimizationPolicy.ALL);
                 setParent(xopEncoder);
             }
         }

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OptimizationPolicyImpl.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OptimizationPolicyImpl.java?rev=795540&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OptimizationPolicyImpl.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OptimizationPolicyImpl.java Sun Jul 19 13:45:10 2009
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.om.impl;
+
+import java.io.IOException;
+
+import javax.activation.DataHandler;
+
+import org.apache.axiom.attachments.impl.BufferUtils;
+import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider;
+import org.apache.axiom.om.OMOutputFormat;
+import org.apache.axiom.util.stax.xop.OptimizationPolicy;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * {@link OptimizationPolicy} implementation that takes a decision based on the
+ * settings in {@link OMOutputFormat}.
+ * <p>
+ * For internal use only.
+ */
+class OptimizationPolicyImpl implements OptimizationPolicy {
+    private static Log log = LogFactory.getLog(OptimizationPolicyImpl.class);
+    private static boolean isDebugEnabled = log.isDebugEnabled();
+    
+    private final OMOutputFormat format;
+
+    public OptimizationPolicyImpl(OMOutputFormat format) {
+        this.format = format;
+    }
+
+    private final static int UNSUPPORTED = -1;
+    private final static int EXCEED_LIMIT = 1;
+    
+    public boolean isOptimized(DataHandler dataHandler, boolean optimize) {
+        if (!optimize) {
+            return false;
+        }
+        
+        // TODO: this needs review and cleanup
+        // ** START **  code from MTOMXMLStreamWriter#isOptimizedThreshold
+        if(isDebugEnabled){
+            log.debug("Start MTOMXMLStreamWriter.isOptimizedThreshold()");
+        }
+        int optimized = UNSUPPORTED;
+        if(dataHandler!=null){
+            if(isDebugEnabled){
+                log.debug("DataHandler fetched, starting optimized Threshold processing");
+            }
+            optimized= BufferUtils.doesDataHandlerExceedLimit(dataHandler, format.getOptimizedThreshold());
+        }
+        if(optimized == UNSUPPORTED || optimized == EXCEED_LIMIT){
+            if(log.isDebugEnabled()){
+                log.debug("node should be added to binart NodeList for optimization");
+            }
+            return true;
+        }
+        return false;
+        // ** END **  code from MTOMXMLStreamWriter#isOptimizedThreshold
+    }
+
+    public boolean isOptimized(DataHandlerProvider dataHandlerProvider, boolean optimize)
+            throws IOException {
+        
+        if (!optimize) {
+            return false;
+        } else {
+            // TODO: this is suboptimal because it forces loading of the data handler;
+            //       note that it is strictly the same logic as was applied in the old
+            //       MTOMXMLStreamWriter#isOptimizedThreshold method
+            return isOptimized(dataHandlerProvider.getDataHandler(), optimize);
+        }
+    }
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OptimizationPolicyImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamWriterUtil.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamWriterUtil.java?rev=795540&r1=795539&r2=795540&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamWriterUtil.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamWriterUtil.java Sun Jul 19 13:45:10 2009
@@ -25,6 +25,8 @@
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 
+import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider;
+import org.apache.axiom.ext.stax.datahandler.DataHandlerWriter;
 import org.apache.axiom.util.base64.Base64WriterOutputStream;
 
 /**
@@ -38,6 +40,12 @@
      * i.e. the data is streamed from the data handler directly to the stream writer.
      * Since no in-memory base64 representation of the entire binary data is built, this
      * method is suitable for very large amounts of data.
+     * <p>
+     * Note that this method will always serialize the data as base64 encoded character data.
+     * Serialization code should prefer using
+     * {@link #writeDataHandler(XMLStreamWriter, DataHandler, String, boolean)} or
+     * {@link #writeDataHandler(XMLStreamWriter, DataHandlerProvider, String, boolean)} to
+     * enable optimization (if supported by the {@link XMLStreamWriter}).
      * 
      * @param writer the stream writer to write the data to
      * @param dh the data handler containing the data to encode
@@ -57,4 +65,73 @@
             throw ex.getXMLStreamException();
         }
     }
+
+    private static DataHandlerWriter getDataHandlerWriter(XMLStreamWriter writer) {
+        try {
+            return (DataHandlerWriter)writer.getProperty(DataHandlerWriter.PROPERTY);
+        } catch (IllegalArgumentException ex) {
+            return null;
+        }
+    }
+
+    /**
+     * Write binary content to the stream. Depending on the supplied {@link XMLStreamWriter},
+     * the content will be written as base64 encoded character data or using an optimization
+     * scheme such as XOP/MTOM. The method attempts to submit the binary content using the
+     * {@link DataHandlerWriter} extension. If the writer doesn't expose this extension,
+     * the method will fall back to {@link #writeBase64(XMLStreamWriter, DataHandler)}.
+     * <p>
+     * Please refer to the documentation of {@link DataHandlerWriter} for a more
+     * detailed description of the semantics of the different arguments.
+     * 
+     * @param writer
+     *            the stream writer to write the data to
+     * @param dataHandler
+     *            the binary content to write
+     * @param contentID
+     *            an existing content ID for the binary data
+     * @param optimize
+     *            indicates whether the content is eligible for optimization
+     * @throws IOException
+     *             if an error occurs while reading from the data handler
+     * @throws XMLStreamException
+     *             if an error occurs while writing to the underlying stream
+     */
+    public static void writeDataHandler(XMLStreamWriter writer, DataHandler dataHandler,
+            String contentID, boolean optimize) throws IOException, XMLStreamException {
+        DataHandlerWriter dataHandlerWriter = getDataHandlerWriter(writer);
+        if (dataHandlerWriter != null) {
+            dataHandlerWriter.writeDataHandler(dataHandler, contentID, optimize);
+        } else {
+            writeBase64(writer, dataHandler);
+        }
+    }
+    
+    /**
+     * Write binary content to the stream. This method is similar to
+     * {@link #writeDataHandler(XMLStreamWriter, DataHandler, String, boolean)},
+     * but supports deferred loading of the data handler.
+     * 
+     * @param writer
+     *            the stream writer to write the data to
+     * @param dataHandlerProvider
+     *            the binary content to write
+     * @param contentID
+     *            an existing content ID for the binary data
+     * @param optimize
+     *            indicates whether the content is eligible for optimization
+     * @throws IOException
+     *             if an error occurs while reading from the data handler
+     * @throws XMLStreamException
+     *             if an error occurs while writing to the underlying stream
+     */
+    public static void writeDataHandler(XMLStreamWriter writer, DataHandlerProvider dataHandlerProvider,
+            String contentID, boolean optimize) throws IOException, XMLStreamException {
+        DataHandlerWriter dataHandlerWriter = getDataHandlerWriter(writer);
+        if (dataHandlerWriter != null) {
+            dataHandlerWriter.writeDataHandler(dataHandlerProvider, contentID, optimize);
+        } else {
+            writeBase64(writer, dataHandlerProvider.getDataHandler());
+        }
+    }
 }

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/OptimizationPolicy.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/OptimizationPolicy.java?rev=795540&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/OptimizationPolicy.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/OptimizationPolicy.java Sun Jul 19 13:45:10 2009
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.util.stax.xop;
+
+import java.io.IOException;
+
+import javax.activation.DataHandler;
+
+import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider;
+
+/**
+ * Encapsulates an algorithm that decides whether base64 encoded binary data should be optimized
+ * using XOP. The implementation takes the decision based on the submitted binary content and the
+ * "eligible for optimization" flag. Depending on the context of use, this flag is provided by the
+ * return value of {@link org.apache.axiom.ext.stax.datahandler.DataHandlerReader#isOptimized()} or
+ * the <code>optimize</code> argument of
+ * {@link org.apache.axiom.ext.stax.datahandler.DataHandlerWriter#writeDataHandler(DataHandler, String, boolean)}
+ * or
+ * {@link org.apache.axiom.ext.stax.datahandler.DataHandlerWriter#writeDataHandler(DataHandlerProvider, String, boolean)}.
+ */
+public interface OptimizationPolicy {
+    /**
+     * Policy implementation that optimizes all binary content marked as eligible for optimization.
+     */
+    OptimizationPolicy DEFAULT = new OptimizationPolicy() {
+        public boolean isOptimized(DataHandler dataHandler, boolean optimize) {
+            return optimize;
+        }
+
+        public boolean isOptimized(DataHandlerProvider dataHandlerProvider, boolean optimize) {
+            return optimize;
+        }
+    };
+    
+    /**
+     * Policy implementation that optimizes all binary content, regardless of whether is has been
+     * marked as eligible for optimization.
+     */
+    OptimizationPolicy ALL = new OptimizationPolicy() {
+        public boolean isOptimized(DataHandler dataHandler, boolean optimize) {
+            return true;
+        }
+
+        public boolean isOptimized(DataHandlerProvider dataHandlerProvider, boolean optimize) {
+            return true;
+        }
+    };
+    
+    /**
+     * Determine whether the binary content supplied by a given {@link DataHandler} should be
+     * optimized.
+     * 
+     * @param dataHandler
+     *            the binary content
+     * @param optimize
+     *            indicates whether the binary content was initially marked as eligible for
+     *            optimization (see above)
+     * @return <code>true</code> if the binary content should be optimized using XOP, i.e. encoded
+     *         using <tt>xop:Include</tt>
+     * @throws IOException
+     *             if an error occurs while reading the data handler
+     */
+    boolean isOptimized(DataHandler dataHandler, boolean optimize) throws IOException;
+    
+    /**
+     * Determine whether the binary content supplied by a given {@link DataHandlerProvider} should
+     * be optimized.
+     * 
+     * @param dataHandlerProvider
+     *            the binary content
+     * @param optimize
+     *            indicates whether the binary content was initially marked as eligible for
+     *            optimization (see above)
+     * @return <code>true</code> if the binary content should be optimized using XOP, i.e. encoded
+     *         using <tt>xop:Include</tt>
+     * @throws IOException
+     *             if an error occurs while reading the data handler
+     */
+    boolean isOptimized(DataHandlerProvider dataHandlerProvider, boolean optimize) throws IOException;
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/OptimizationPolicy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPConstants.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPConstants.java?rev=795540&r1=795539&r2=795540&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPConstants.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPConstants.java Sun Jul 19 13:45:10 2009
@@ -32,4 +32,5 @@
     String NAMESPACE_URI = "http://www.w3.org/2004/08/xop/include";
     String DEFAULT_PREFIX = "xop";
     QName INCLUDE_QNAME = new QName(NAMESPACE_URI, INCLUDE, DEFAULT_PREFIX);
+    String HREF = "href";
 }

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java?rev=795540&r1=795539&r2=795540&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java Sun Jul 19 13:45:10 2009
@@ -126,7 +126,7 @@
      */
     private String processXopInclude() throws XMLStreamException {
         if (parent.getAttributeCount() != 1 ||
-                !parent.getAttributeLocalName(0).equals("href")) {
+                !parent.getAttributeLocalName(0).equals(XOPConstants.HREF)) {
             throw new XMLStreamException("Expected xop:Include element information item with " +
                     "a (single) href attribute");
         }

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReader.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReader.java?rev=795540&r1=795539&r2=795540&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReader.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReader.java Sun Jul 19 13:45:10 2009
@@ -22,12 +22,8 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 import javax.activation.DataHandler;
 import javax.xml.namespace.NamespaceContext;
@@ -36,7 +32,6 @@
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 
-import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider;
 import org.apache.axiom.ext.stax.datahandler.DataHandlerReader;
 
 /**
@@ -49,15 +44,15 @@
  * an instance of this class can be retrieved using the {@link #getDataHandler(String)} method.
  * <p>
  * Note that the primary purpose of this class is not to serialize an XML infoset to an XOP package
- * (this is better done using a specialized {@link javax.xml.stream.XMLStreamWriter}
- * implementation), but rather to optimize interaction (by exchanging {@link DataHandler} objects
- * instead of base64 encoded representations) with databinding frameworks that understand XOP, but
- * that are not aware of the {@link DataHandlerReader} extension.
+ * (this is better done using {@link XOPEncodingStreamWriter}), but rather to optimize interaction
+ * (by exchanging {@link DataHandler} objects instead of base64 encoded representations) with
+ * databinding frameworks that understand XOP, but that are not aware of the
+ * {@link DataHandlerReader} extension.
  * <p>
  * This class defers loading of {@link DataHandler} objects until {@link #getDataHandler(String)} is
  * called, except if this is not supported by the underlying stream.
  */
-public class XOPEncodingStreamReader implements XMLStreamReader {
+public class XOPEncodingStreamReader extends XOPEncodingStreamWrapper implements XMLStreamReader {
     /**
      * Wrapper that adds the XOP namespace to another namespace context.
      */
@@ -108,12 +103,9 @@
     private static final int STATE_XOP_INCLUDE_END_ELEMENT = 2;
     
     private final XMLStreamReader parent;
-    private final ContentIDGenerator contentIDGenerator;
     private final DataHandlerReader dataHandlerReader;
-    private final boolean optimizeAll;
     private int state = STATE_PASS_THROUGH;
     private String currentContentID;
-    private Map dataHandlerObjects = new LinkedHashMap();
 
     /**
      * Constructor.
@@ -124,19 +116,17 @@
      * @param contentIDGenerator
      *            used to generate content IDs for the binary content exposed as
      *            <tt>xop:Include</tt> element information items
-     * @param optimizeAll
-     *            if set to <code>true</code>, <tt>xop:Include</tt> element information items
-     *            will be generated for all data handlers, regardless of the return value of
-     *            {@link DataHandlerReader#isOptimized()}
+     * @param optimizationPolicy
+     *            the policy to apply to decide which binary content to optimize
      * 
      * @throws IllegalArgumentException
      *             if the provided {@link XMLStreamReader} doesn't implement the extension defined
      *             by {@link DataHandlerReader}
      */
     public XOPEncodingStreamReader(XMLStreamReader parent, ContentIDGenerator contentIDGenerator,
-            boolean optimizeAll) {
+            OptimizationPolicy optimizationPolicy) {
+        super(contentIDGenerator, optimizationPolicy);
         this.parent = parent;
-        this.contentIDGenerator = contentIDGenerator;
         DataHandlerReader dataHandlerReader;
         try {
             dataHandlerReader = (DataHandlerReader)parent.getProperty(DataHandlerReader.PROPERTY);
@@ -147,42 +137,8 @@
             throw new IllegalArgumentException("The supplied XMLStreamReader doesn't implement the DataHandlerReader extension");
         }
         this.dataHandlerReader = dataHandlerReader;
-        this.optimizeAll = optimizeAll;
     }
 
-    /**
-     * Get the set of content IDs referenced in <tt>xop:Include</tt> element information items
-     * produced by this wrapper.
-     * 
-     * @return The set of content IDs in their order of appearance in the infoset. If no
-     *         <tt>xop:Include</tt> element information items have been produced yet, an empty
-     *         set will be returned.
-     */
-    public Set/*<String>*/ getContentIDs() {
-        return Collections.unmodifiableSet(dataHandlerObjects.keySet());
-    }
-
-    /**
-     * Get the data handler for a given content ID.
-     * 
-     * @param contentID a content ID previously returned by an <tt>xop:Include</tt> element
-     *                  produced by this reader
-     * @return the corresponding data handler; may not be <code>null</code>
-     * @throws XMLStreamException if the content ID is unknown or an error occurred while loading
-     *         the data handler
-     */
-    public DataHandler getDataHandler(String contentID) throws IOException {
-        Object dataHandlerObject = dataHandlerObjects.get(contentID);
-        if (dataHandlerObject == null) {
-            throw new IOException("No DataHandler object found for content ID '" +
-                    contentID + "'");
-        } else if (dataHandlerObject instanceof DataHandler) {
-            return (DataHandler)dataHandlerObject;
-        } else {
-            return ((DataHandlerProvider)dataHandlerObject).getDataHandler();
-        }
-    }
-    
     public int next() throws XMLStreamException {
         switch (state) {
             case STATE_XOP_INCLUDE_START_ELEMENT:
@@ -194,17 +150,30 @@
                 // Fall through
             default:
                 int event = parent.next();
-                if (event == CHARACTERS && dataHandlerReader.isBinary()
-                        && (optimizeAll || dataHandlerReader.isOptimized())) {
-                    String contentID = dataHandlerReader.getContentID();
-                    contentID = contentIDGenerator.generateContentID(contentID);
-                    Object dataHandlerObject = dataHandlerReader.isDeferred()
-                            ? (Object)dataHandlerReader.getDataHandlerProvider()
-                            : (Object)dataHandlerReader.getDataHandler();
-                    dataHandlerObjects.put(contentID, dataHandlerObject);
-                    currentContentID = contentID;
-                    state = STATE_XOP_INCLUDE_START_ELEMENT;
-                    return START_ELEMENT;
+                if (event == CHARACTERS && dataHandlerReader.isBinary()) {
+                    String contentID;
+                    try {
+                        if (dataHandlerReader.isDeferred()) {
+                            contentID = processDataHandler(
+                                    dataHandlerReader.getDataHandlerProvider(),
+                                    dataHandlerReader.getContentID(),
+                                    dataHandlerReader.isOptimized());
+                        } else {
+                            contentID = processDataHandler(
+                                    dataHandlerReader.getDataHandler(),
+                                    dataHandlerReader.getContentID(),
+                                    dataHandlerReader.isOptimized());
+                        }
+                    } catch (IOException ex) {
+                        throw new XMLStreamException("Error while processing data handler", ex);
+                    }
+                    if (contentID != null) {
+                        currentContentID = contentID;
+                        state = STATE_XOP_INCLUDE_START_ELEMENT;
+                        return START_ELEMENT;
+                    } else {
+                        return CHARACTERS;
+                    }
                 } else {
                     return event;
                 }
@@ -298,7 +267,7 @@
                 if (index != 0) {
                     throw new IllegalArgumentException();
                 }
-                return "href";
+                return XOPConstants.HREF;
             case STATE_XOP_INCLUDE_END_ELEMENT:
                 throw new IllegalStateException();
             default:
@@ -312,7 +281,7 @@
                 if (index != 0) {
                     throw new IllegalArgumentException();
                 }
-                return new QName("href");
+                return new QName(XOPConstants.HREF);
             case STATE_XOP_INCLUDE_END_ELEMENT:
                 throw new IllegalStateException();
             default:
@@ -398,7 +367,7 @@
         switch (state) {
             case STATE_XOP_INCLUDE_START_ELEMENT:
                 if ((namespaceURI == null || namespaceURI.length() == 0)
-                        && localName.equals("href")) {
+                        && localName.equals(XOPConstants.HREF)) {
                     return "cid:" + currentContentID;
                 } else {
                     return null;

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWrapper.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWrapper.java?rev=795540&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWrapper.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWrapper.java Sun Jul 19 13:45:10 2009
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.util.stax.xop;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.activation.DataHandler;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider;
+
+/**
+ * Base class for {@link XOPEncodingStreamReader} and {@link XOPEncodingStreamWriter}.
+ */
+public abstract class XOPEncodingStreamWrapper {
+    private final Map dataHandlerObjects = new LinkedHashMap();
+    private final ContentIDGenerator contentIDGenerator;
+    private final OptimizationPolicy optimizationPolicy;
+
+    public XOPEncodingStreamWrapper(ContentIDGenerator contentIDGenerator,
+                                    OptimizationPolicy optimizationPolicy) {
+        this.contentIDGenerator = contentIDGenerator;
+        this.optimizationPolicy = optimizationPolicy;
+    }
+
+    private String addDataHandler(Object dataHandlerObject, String existingContentID) {
+        String contentID = contentIDGenerator.generateContentID(existingContentID);
+        dataHandlerObjects.put(contentID, dataHandlerObject);
+        return contentID;
+    }
+
+    protected String processDataHandler(DataHandler dataHandler,
+                                        String existingContentID,
+                                        boolean optimize) throws IOException {
+        if (optimizationPolicy.isOptimized(dataHandler, optimize)) {
+            return addDataHandler(dataHandler, existingContentID);
+        } else {
+            return null;
+        }
+    }
+
+    protected String processDataHandler(DataHandlerProvider dataHandlerProvider,
+                                        String existingContentID,
+                                        boolean optimize) throws IOException {
+        if (optimizationPolicy.isOptimized(dataHandlerProvider, optimize)) {
+            return addDataHandler(dataHandlerProvider, existingContentID);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get the set of content IDs referenced in <tt>xop:Include</tt> element information items
+     * produced by this wrapper.
+     * 
+     * @return The set of content IDs in their order of appearance in the infoset. If no
+     *         <tt>xop:Include</tt> element information items have been produced yet, an empty
+     *         set will be returned.
+     */
+    public Set/*<String>*/ getContentIDs() {
+        return Collections.unmodifiableSet(dataHandlerObjects.keySet());
+    }
+
+    /**
+     * Get the data handler for a given content ID.
+     * 
+     * @param contentID a content ID referenced in an <tt>xop:Include</tt> element
+     *                  produced by this wrapper
+     * @return the corresponding data handler; may not be <code>null</code>
+     * @throws XMLStreamException if the content ID is unknown or an error occurred while loading
+     *         the data handler
+     */
+    public DataHandler getDataHandler(String contentID) throws IOException {
+        Object dataHandlerObject = dataHandlerObjects.get(contentID);
+        if (dataHandlerObject == null) {
+            throw new IOException("No DataHandler object found for content ID '" +
+                    contentID + "'");
+        } else if (dataHandlerObject instanceof DataHandler) {
+            return (DataHandler)dataHandlerObject;
+        } else {
+            return ((DataHandlerProvider)dataHandlerObject).getDataHandler();
+        }
+    }
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWriter.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWriter.java?rev=795540&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWriter.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWriter.java Sun Jul 19 13:45:10 2009
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.util.stax.xop;
+
+import java.io.IOException;
+
+import javax.activation.DataHandler;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider;
+import org.apache.axiom.ext.stax.datahandler.DataHandlerWriter;
+import org.apache.axiom.om.impl.util.OMSerializerUtil;
+import org.apache.axiom.util.stax.XMLStreamWriterUtil;
+
+/**
+ * {@link XMLStreamWriter} wrapper that encodes XOP. It implements the extension
+ * defined by {@link DataHandlerWriter}. The {@link DataHandler}
+ * objects for the parts referenced by <tt>xop:Include</tt> element information items produced by
+ * an instance of this class can be retrieved using the {@link #getDataHandler(String)} method.
+ */
+public class XOPEncodingStreamWriter extends XOPEncodingStreamWrapper
+                                     implements XMLStreamWriter, DataHandlerWriter {
+    private final XMLStreamWriter parent;
+    
+    /**
+     * Constructor.
+     * 
+     * @param parent
+     *            the XML stream to write the encoded infoset to
+     * @param contentIDGenerator
+     *            used to generate content IDs for the binary content encoded as
+     *            <tt>xop:Include</tt> element information items
+     * @param optimizationPolicy
+     *            the policy to apply to decide which binary content to optimize
+     */
+    public XOPEncodingStreamWriter(XMLStreamWriter parent, ContentIDGenerator contentIDGenerator,
+            OptimizationPolicy optimizationPolicy) {
+        super(contentIDGenerator, optimizationPolicy);
+        this.parent = parent;
+    }
+
+    public Object getProperty(String name) throws IllegalArgumentException {
+        if (DataHandlerWriter.PROPERTY.equals(name)) {
+            return this;
+        } else {
+            return parent.getProperty(name);
+        }
+    }
+
+    private void writeXOPInclude(String contentID) throws XMLStreamException {
+        String writerPrefix = parent.getPrefix(XOPConstants.NAMESPACE_URI);
+        if (writerPrefix != null) {
+            parent.writeStartElement(XOPConstants.NAMESPACE_URI, "Include");
+        } else {
+            // According to StAX, setPrefix must occur before writeStartElement
+            if (OMSerializerUtil.isSetPrefixBeforeStartElement(parent)) {
+                parent.setPrefix(XOPConstants.DEFAULT_PREFIX, XOPConstants.NAMESPACE_URI);
+                parent.writeStartElement(XOPConstants.DEFAULT_PREFIX, XOPConstants.INCLUDE,
+                        XOPConstants.NAMESPACE_URI);
+            } else {
+                parent.writeStartElement(XOPConstants.DEFAULT_PREFIX, XOPConstants.INCLUDE,
+                        XOPConstants.NAMESPACE_URI);
+                parent.setPrefix(XOPConstants.DEFAULT_PREFIX, XOPConstants.NAMESPACE_URI);
+            }
+            parent.writeNamespace(XOPConstants.DEFAULT_PREFIX, XOPConstants.NAMESPACE_URI);
+        }
+        parent.writeAttribute(XOPConstants.HREF, "cid:" + contentID); // TODO: wrong; need to URI encode
+        parent.writeEndElement();
+    }
+    
+    public void writeDataHandler(DataHandler dataHandler, String contentID, boolean optimize)
+            throws IOException, XMLStreamException {
+        contentID = processDataHandler(dataHandler, contentID, optimize);
+        if (contentID != null) {
+            writeXOPInclude(contentID);
+        } else {
+            XMLStreamWriterUtil.writeBase64(parent, dataHandler);
+        }
+    }
+
+    public void writeDataHandler(DataHandlerProvider dataHandlerProvider, String contentID,
+            boolean optimize) throws IOException, XMLStreamException {
+        contentID = processDataHandler(dataHandlerProvider, contentID, optimize);
+        if (contentID != null) {
+            writeXOPInclude(contentID);
+        } else {
+            XMLStreamWriterUtil.writeBase64(parent, dataHandlerProvider.getDataHandler());
+        }
+    }
+
+    public void close() throws XMLStreamException {
+        parent.close();
+    }
+
+    public void flush() throws XMLStreamException {
+        parent.flush();
+    }
+
+    public NamespaceContext getNamespaceContext() {
+        return parent.getNamespaceContext();
+    }
+
+    public String getPrefix(String uri) throws XMLStreamException {
+        return parent.getPrefix(uri);
+    }
+
+    public void setDefaultNamespace(String uri) throws XMLStreamException {
+        parent.setDefaultNamespace(uri);
+    }
+
+    public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
+        parent.setNamespaceContext(context);
+    }
+
+    public void setPrefix(String prefix, String uri) throws XMLStreamException {
+        parent.setPrefix(prefix, uri);
+    }
+
+    public void writeAttribute(String prefix, String namespaceURI, String localName, String value)
+            throws XMLStreamException {
+        parent.writeAttribute(prefix, namespaceURI, localName, value);
+    }
+
+    public void writeAttribute(String namespaceURI, String localName, String value)
+            throws XMLStreamException {
+        parent.writeAttribute(namespaceURI, localName, value);
+    }
+
+    public void writeAttribute(String localName, String value) throws XMLStreamException {
+        parent.writeAttribute(localName, value);
+    }
+
+    public void writeCData(String data) throws XMLStreamException {
+        parent.writeCData(data);
+    }
+
+    public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
+        parent.writeCharacters(text, start, len);
+    }
+
+    public void writeCharacters(String text) throws XMLStreamException {
+        parent.writeCharacters(text);
+    }
+
+    public void writeComment(String data) throws XMLStreamException {
+        parent.writeComment(data);
+    }
+
+    public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
+        parent.writeDefaultNamespace(namespaceURI);
+    }
+
+    public void writeDTD(String dtd) throws XMLStreamException {
+        parent.writeDTD(dtd);
+    }
+
+    public void writeEmptyElement(String prefix, String localName, String namespaceURI)
+            throws XMLStreamException {
+        parent.writeEmptyElement(prefix, localName, namespaceURI);
+    }
+
+    public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
+        parent.writeEmptyElement(namespaceURI, localName);
+    }
+
+    public void writeEmptyElement(String localName) throws XMLStreamException {
+        parent.writeEmptyElement(localName);
+    }
+
+    public void writeEndDocument() throws XMLStreamException {
+        parent.writeEndDocument();
+    }
+
+    public void writeEndElement() throws XMLStreamException {
+        parent.writeEndElement();
+    }
+
+    public void writeEntityRef(String name) throws XMLStreamException {
+        parent.writeEntityRef(name);
+    }
+
+    public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
+        parent.writeNamespace(prefix, namespaceURI);
+    }
+
+    public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
+        parent.writeProcessingInstruction(target, data);
+    }
+
+    public void writeProcessingInstruction(String target) throws XMLStreamException {
+        parent.writeProcessingInstruction(target);
+    }
+
+    public void writeStartDocument() throws XMLStreamException {
+        parent.writeStartDocument();
+    }
+
+    public void writeStartDocument(String encoding, String version) throws XMLStreamException {
+        parent.writeStartDocument(encoding, version);
+    }
+
+    public void writeStartDocument(String version) throws XMLStreamException {
+        parent.writeStartDocument(version);
+    }
+
+    public void writeStartElement(String prefix, String localName, String namespaceURI)
+            throws XMLStreamException {
+        parent.writeStartElement(prefix, localName, namespaceURI);
+    }
+
+    public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
+        parent.writeStartElement(namespaceURI, localName);
+    }
+
+    public void writeStartElement(String localName) throws XMLStreamException {
+        parent.writeStartElement(localName);
+    }
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReaderTest.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReaderTest.java?rev=795540&r1=795539&r2=795540&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReaderTest.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReaderTest.java Sun Jul 19 13:45:10 2009
@@ -48,7 +48,7 @@
                     TestConstants.MTOM_MESSAGE_CONTENT_TYPE);
             soapPartReader[i] = StAXUtils.createXMLStreamReader(attachments[i].getSOAPPartInputStream());
         }
-        XMLStreamReader actual = new XOPEncodingStreamReader(new XOPDecodingStreamReader(soapPartReader[1], new OMAttachmentAccessorMimePartProvider(attachments[1])), contentIDGenerator, false);
+        XMLStreamReader actual = new XOPEncodingStreamReader(new XOPDecodingStreamReader(soapPartReader[1], new OMAttachmentAccessorMimePartProvider(attachments[1])), contentIDGenerator, OptimizationPolicy.DEFAULT);
         new XMLStreamReaderComparator(soapPartReader[0], actual).compare();
     }
 

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/TextNodeImpl.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/TextNodeImpl.java?rev=795540&r1=795539&r2=795540&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/TextNodeImpl.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/TextNodeImpl.java Sun Jul 19 13:45:10 2009
@@ -21,7 +21,6 @@
 
 import org.apache.axiom.attachments.utils.DataHandlerUtils;
 import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider;
-import org.apache.axiom.om.OMAttribute;
 import org.apache.axiom.om.OMContainer;
 import org.apache.axiom.om.OMException;
 import org.apache.axiom.om.OMFactory;
@@ -29,10 +28,8 @@
 import org.apache.axiom.om.OMNode;
 import org.apache.axiom.om.OMText;
 import org.apache.axiom.om.OMXMLParserWrapper;
-import org.apache.axiom.om.impl.MTOMXMLStreamWriter;
 import org.apache.axiom.om.impl.OMNamespaceImpl;
 import org.apache.axiom.om.impl.builder.XOPBuilder;
-import org.apache.axiom.om.util.TextHelper;
 import org.apache.axiom.om.util.UUIDGenerator;
 import org.apache.axiom.util.base64.Base64Utils;
 import org.apache.axiom.util.stax.XMLStreamWriterUtil;
@@ -69,9 +66,6 @@
     /** Field nameSpace is used when serializing Binary stuff as MTOM optimized. */
     protected OMNamespace ns = null;
 
-    /** Field attribute is used when serializing Binary stuff as MTOM optimized. */
-    protected OMAttribute attribute;
-
     /** Field nameSpace used when serializing Binary stuff as MTOM optimized. */
     public static final OMNamespace XOP_NS = new OMNamespaceImpl(
             "http://www.w3.org/2004/08/xop/include", "xop");
@@ -151,11 +145,6 @@
             this.ns = new OMNamespaceImpl(source.ns.getNamespaceURI(), 
                                           source.ns.getPrefix());
         }
-        if (source.attribute != null) {
-            this.attribute = factory.createOMAttribute(source.attribute.getLocalName(),
-                                                       source.attribute.getNamespace(),
-                                                       source.attribute.getAttributeValue());
-        }
     }
 
     public TextNodeImpl(String text, String mimeType, boolean optimize,
@@ -477,100 +466,17 @@
         }
     }
 
-    private void internalSerializeLocal(XMLStreamWriter writer2)
+    private void internalSerializeLocal(XMLStreamWriter writer)
             throws XMLStreamException {
-        MTOMXMLStreamWriter writer = (MTOMXMLStreamWriter) writer2;
         if (!this.isBinary) {
             writeOutput(writer);
         } else {
-            if (writer.isOptimized()) {
-                if (contentID == null) {
-                    contentID = writer.getNextContentId();
-                }
-                // send binary as MTOM optimised
-                this.attribute = new AttrImpl(this.ownerNode, "href",
-                                              new NamespaceImpl("", ""),
-                                              "cid:" + getContentID(),
-                                              this.factory);
-                this.serializeStartpart(writer);
-                writer.writeOptimized(this);
-                writer.writeEndElement();
-            } else {
-                try {
-                    XMLStreamWriterUtil.writeBase64(writer, (DataHandler)getDataHandler());
-                } catch (IOException ex) {
-                    throw new OMException("Error reading data handler", ex);
-                }
-            }
-        }
-    }
-
-    /*
-     * Methods to copy from OMSerialize utils.
-     */
-    private void serializeStartpart(XMLStreamWriter writer)
-            throws XMLStreamException {
-        String nameSpaceName = XOP_NS.getNamespaceURI();
-        String writer_prefix = writer.getPrefix(nameSpaceName);
-        String prefix = XOP_NS.getPrefix();
-        if (writer_prefix != null) {
-            writer.writeStartElement(nameSpaceName, "Include");
-        } else {
-            writer.writeStartElement(prefix, "Include",
-                                     nameSpaceName);
-            writer.setPrefix(prefix, nameSpaceName);
-        }
-        // add the elements attribute "href"
-        serializeAttribute(this.attribute, writer);
-        // add the namespace
-        serializeNamespace(XOP_NS, writer);
-    }
-
-    /**
-     * Method serializeAttribute.
-     *
-     * @param attr
-     * @param writer
-     * @throws XMLStreamException
-     */
-    static void serializeAttribute(OMAttribute attr, XMLStreamWriter writer)
-            throws XMLStreamException {
-        // first check whether the attribute is associated with a namespace
-        OMNamespace ns = attr.getNamespace();
-        String prefix;
-        String namespaceName;
-        if (ns != null) {
-            // add the prefix if it's availble
-            prefix = ns.getPrefix();
-            namespaceName = ns.getNamespaceURI();
-            if (prefix != null) {
-                writer.writeAttribute(prefix, namespaceName, attr
-                        .getLocalName(), attr.getAttributeValue());
-            } else {
-                writer.writeAttribute(namespaceName, attr.getLocalName(), attr
-                        .getAttributeValue());
+            try {
+                XMLStreamWriterUtil.writeDataHandler(writer, (DataHandler)getDataHandler(),
+                        contentID, optimize);
+            } catch (IOException ex) {
+                throw new OMException("Error reading data handler", ex);
             }
-        } else {
-            writer
-                    .writeAttribute(attr.getLocalName(), attr
-                            .getAttributeValue());
-        }
-    }
-
-    /**
-     * Method serializeNamespace.
-     *
-     * @param namespace
-     * @param writer
-     * @throws XMLStreamException
-     */
-    static void serializeNamespace(OMNamespace namespace, XMLStreamWriter writer)
-            throws XMLStreamException {
-        if (namespace != null) {
-            String uri = namespace.getNamespaceURI();
-            String ns_prefix = namespace.getPrefix();
-            writer.writeNamespace(ns_prefix, namespace.getNamespaceURI());
-            writer.setPrefix(ns_prefix, uri);
         }
     }
 

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMTextImpl.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMTextImpl.java?rev=795540&r1=795539&r2=795540&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMTextImpl.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMTextImpl.java Sun Jul 19 13:45:10 2009
@@ -19,9 +19,7 @@
 
 package org.apache.axiom.om.impl.llom;
 
-
 import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider;
-import org.apache.axiom.om.OMAttribute;
 import org.apache.axiom.om.OMConstants;
 import org.apache.axiom.om.OMContainer;
 import org.apache.axiom.om.OMElement;
@@ -30,10 +28,8 @@
 import org.apache.axiom.om.OMNamespace;
 import org.apache.axiom.om.OMText;
 import org.apache.axiom.om.OMXMLParserWrapper;
-import org.apache.axiom.om.impl.MTOMXMLStreamWriter;
 import org.apache.axiom.om.impl.OMNamespaceImpl;
 import org.apache.axiom.om.impl.builder.XOPBuilder;
-import org.apache.axiom.om.impl.util.OMSerializerUtil;
 import org.apache.axiom.om.util.UUIDGenerator;
 import org.apache.axiom.util.base64.Base64Utils;
 import org.apache.axiom.util.stax.XMLStreamWriterUtil;
@@ -71,8 +67,6 @@
      */
     private Object dataHandlerObject = null;
 
-    /** Field attributes used when serializing Binary stuff as MTOM optimized. */
-    protected OMAttribute attribute;
     private static final String EMTPY_STRING = "";
 
     /**
@@ -135,12 +129,6 @@
         // Do we need a deep copy of the data-handler 
         this.contentID = source.contentID;
         this.dataHandlerObject = source.dataHandlerObject;
-        
-        if (source.attribute != null) {
-            this.attribute = factory.createOMAttribute(source.attribute.getLocalName(),
-                                                       source.attribute.getNamespace(),
-                                                       source.attribute.getAttributeValue());
-        }
     }
 
     public OMTextImpl(OMContainer parent, String text, int nodeType,
@@ -425,112 +413,20 @@
         internalSerializeLocal(writer);
     }
 
-    private void internalSerializeLocal(XMLStreamWriter writer2) throws XMLStreamException {
+    private void internalSerializeLocal(XMLStreamWriter writer) throws XMLStreamException {
 
         if (!this.isBinary) {
-            writeOutput(writer2);
+            writeOutput(writer);
         } else {
-            //check whether we have a MTOMXMLStreamWriter. if so
-            //we can optimize the writing!
-            if (this.isOptimized() && writer2 instanceof MTOMXMLStreamWriter) {
-                MTOMXMLStreamWriter writer = (MTOMXMLStreamWriter) writer2;
-                if (writer.isOptimized() && writer.isOptimizedThreshold(this)) {
-                    if (contentID == null) {
-                        contentID = writer.getNextContentId();
-                    }
-                    // send binary as MTOM optimised
-                    this.attribute = new OMAttributeImpl("href",
-                                                         new OMNamespaceImpl("", ""),
-                                                         "cid:" + getContentID(), this.factory);
-                    this.serializeStartpart(writer);
-                    writer.writeOptimized(this);
-                    writer.writeEndElement();
-                    return;
-                }
-            }
-            //do normal base64
             try {
-                XMLStreamWriterUtil.writeBase64(writer2, (DataHandler)getDataHandler());
+                XMLStreamWriterUtil.writeDataHandler(writer, (DataHandler)getDataHandler(),
+                        contentID, optimize);
             } catch (IOException ex) {
                 throw new OMException("Error reading data handler", ex);
             }
         }
     }
 
-    /*
-     * Methods to copy from OMSerialize utils
-     */
-    private void serializeStartpart(XMLStreamWriter writer)
-            throws XMLStreamException {
-        String nameSpaceName = XOP_NS.getNamespaceURI();
-        String writer_prefix = writer.getPrefix(nameSpaceName);
-        String prefix = XOP_NS.getPrefix();
-        if (writer_prefix != null) {
-            writer.writeStartElement(nameSpaceName, "Include");
-        } else {
-            // According to StAX, setPrefix must occur before
-            // writeStartElement
-            if (OMSerializerUtil.isSetPrefixBeforeStartElement(writer)) {
-                writer.setPrefix(prefix, nameSpaceName);
-                writer.writeStartElement(prefix, "Include",
-                                         nameSpaceName);
-            } else {
-                writer.writeStartElement(prefix, "Include",
-                                         nameSpaceName);
-                writer.setPrefix(prefix, nameSpaceName);
-            }
-        }
-        // add the elements attribute "href"
-        serializeAttribute(this.attribute, writer);
-        // add the namespace
-        serializeNamespace(XOP_NS, writer);
-    }
-
-    /**
-     * Method serializeAttribute.
-     *
-     * @param attr
-     * @throws XMLStreamException
-     */
-    static void serializeAttribute(OMAttribute attr, XMLStreamWriter writer)
-            throws XMLStreamException {
-        // first check whether the attribute is associated with a namespace
-        OMNamespace ns = attr.getNamespace();
-        String prefix;
-        String namespaceName;
-        if (ns != null) {
-            // add the prefix if it's availble
-            prefix = ns.getPrefix();
-            namespaceName = ns.getNamespaceURI();
-            if (prefix != null) {
-                writer.writeAttribute(prefix, namespaceName, attr
-                        .getLocalName(), attr.getAttributeValue());
-            } else {
-                writer.writeAttribute(namespaceName, attr.getLocalName(), attr
-                        .getAttributeValue());
-            }
-        } else {
-            writer.writeAttribute(attr.getLocalName(), attr.getAttributeValue());
-        }
-    }
-
-    /**
-     * Method serializeNamespace.
-     *
-     * @param namespace
-     * @param writer
-     * @throws XMLStreamException
-     */
-    static void serializeNamespace(OMNamespace namespace, XMLStreamWriter writer)
-            throws XMLStreamException {
-        if (namespace != null) {
-            String uri = namespace.getNamespaceURI();
-            String ns_prefix = namespace.getPrefix();
-            writer.writeNamespace(ns_prefix, namespace.getNamespaceURI());
-            writer.setPrefix(ns_prefix, uri);
-        }
-    }
-
     /**
      * A slightly different implementation of the discard method.
      *