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 sc...@apache.org on 2007/10/24 11:37:26 UTC

svn commit: r587834 - in /webservices/commons/trunk/modules/axiom/modules: axiom-api/src/main/java/org/apache/axiom/om/ds/custombuilder/ axiom-api/src/main/java/org/apache/axiom/om/impl/builder/ axiom-api/src/main/java/org/apache/axiom/om/impl/serializ...

Author: scheu
Date: Wed Oct 24 02:37:25 2007
New Revision: 587834

URL: http://svn.apache.org/viewvc?rev=587834&view=rev
Log:
WSCOMMONS-263
Contributor:Rich Scheuerle
Adding CustomBuilder plugin to StAXBuilder.
A consumer of Axiom can provide CustomBuilder(s) to construct efficient OMSourcedElements.

Added:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/ds/custombuilder/
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/ds/custombuilder/ByteArrayCustomBuilder.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/CustomBuilder.java
    webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/CustomBuilderTest.java
Modified:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/serialize/StreamingOMSerializer.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/MTOMStAXSOAPModelBuilder.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/SOAP11BuilderHelper.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/StAXSOAPModelBuilder.java
    webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/util/CopyUtilsTest.java

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/ds/custombuilder/ByteArrayCustomBuilder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/ds/custombuilder/ByteArrayCustomBuilder.java?rev=587834&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/ds/custombuilder/ByteArrayCustomBuilder.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/ds/custombuilder/ByteArrayCustomBuilder.java Wed Oct 24 02:37:25 2007
@@ -0,0 +1,96 @@
+/*
+ * 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.ds.custombuilder;
+
+import org.apache.axiom.om.OMContainer;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMException;
+import org.apache.axiom.om.OMFactory;
+import org.apache.axiom.om.OMNamespace;
+import org.apache.axiom.om.ds.ByteArrayDataSource;
+import org.apache.axiom.om.impl.builder.CustomBuilder;
+import org.apache.axiom.om.impl.serialize.StreamingOMSerializer;
+import org.apache.axiom.om.util.StAXUtils;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import java.io.ByteArrayOutputStream;
+
+
+/**
+ * CustomBuilder that creates an OMSourcedElement backed by a ByteArrayDataSource.
+ * If you have a payload or header that will consume a lot of space, it 
+ * may be beneficial to plug in this CustomBuilder.
+ * 
+ * Use this CustomBuilder as a pattern for other CustomBuilders.
+ */
+public class ByteArrayCustomBuilder implements CustomBuilder {
+    private String encoding = null;
+    
+    /**
+     * Constructor
+     * @param encoding 
+     */
+    public ByteArrayCustomBuilder(String encoding) {
+        this.encoding = (encoding == null) ? "utf-8" :encoding;
+    }
+
+    /* 
+     * Create an OMSourcedElement back by a ByteArrayDataSource
+     */
+    public OMElement create(String namespace, 
+                            String localPart, 
+                            OMContainer parent, 
+                            XMLStreamReader reader,
+                            OMFactory factory) throws OMException {
+        try {
+            // Get the prefix of the start tag
+            String prefix = reader.getPrefix();
+            
+            // Stream the events to a writer starting with the current event
+            StreamingOMSerializer ser = new StreamingOMSerializer();
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            XMLStreamWriter writer = StAXUtils.createXMLStreamWriter(baos, encoding);
+            ser.serialize(reader, writer, false);
+            writer.flush();
+            
+            // Capture the written byte array as a ByteArrayDataSource
+            byte[] bytes = baos.toByteArray();
+            String text = new String(bytes, "utf-8");
+            ByteArrayDataSource ds = new ByteArrayDataSource(bytes, encoding);
+            
+            // Create an OMSourcedElement backed by the ByteArrayDataSource
+            OMNamespace ns = factory.createOMNamespace(namespace, prefix);
+            OMElement om = factory.createOMElement(ds, localPart, ns);
+            
+            // Add the new OMSourcedElement ot the parent
+            parent.addChild(om);
+            return om;
+        } catch (XMLStreamException e) {
+            throw new OMException(e);
+        } catch (OMException e) {
+            throw e;
+        } catch (Throwable t) {
+            throw new OMException(t);
+        }
+    }
+
+}

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/CustomBuilder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/CustomBuilder.java?rev=587834&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/CustomBuilder.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/CustomBuilder.java Wed Oct 24 02:37:25 2007
@@ -0,0 +1,54 @@
+/*
+ * 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.builder;
+
+import org.apache.axiom.om.OMContainer;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMException;
+import org.apache.axiom.om.OMFactory;
+import org.apache.axiom.om.OMNamespace;
+
+import javax.xml.stream.XMLStreamReader;
+
+
+
+/**
+ * A Custom Builder is registered on the StAXBuilder for a particular QName or payload.
+ * When the QName or payload is encountered, the CustomBuilder will build the OMElement
+ * or OMSourcedElement for the StAXBuilder.  
+ *
+ * @See StAXBuilder.registerCustomBuilder()
+ */
+public interface CustomBuilder {
+    /**
+     * Create an OMElement for this whole subtree.
+     * A null is returned if the default StAXBuilder behavior should be used.
+     * @param namespace
+     * @param localPart
+     * @param parent
+     * @param reader
+     * @return null or OMElement
+     */
+    public OMElement create(String namespace, 
+                            String localPart, 
+                            OMContainer parent, 
+                            XMLStreamReader reader,
+                            OMFactory factory)
+        throws OMException;
+}

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java?rev=587834&r1=587833&r2=587834&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java Wed Oct 24 02:37:25 2007
@@ -19,12 +19,6 @@
 
 package org.apache.axiom.om.impl.builder;
 
-import java.io.InputStream;
-
-import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-
 import org.apache.axiom.om.OMAbstractFactory;
 import org.apache.axiom.om.OMConstants;
 import org.apache.axiom.om.OMContainer;
@@ -41,6 +35,15 @@
 import org.apache.axiom.om.impl.util.OMSerializerUtil;
 import org.apache.axiom.om.util.StAXUtils;
 
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * OM should be able to be built from any data source. And the model it builds may be a SOAP
  * specific one or just an XML model. This class will give some common functionality of OM Building
@@ -79,6 +82,16 @@
     protected boolean _isClosed = false;              // Indicate if parser is closed
     protected boolean _releaseParserOnClose = false;  // Defaults to legacy behavior, which is keep the reference
 
+    // Fields for Custom Builder implementation
+    protected CustomBuilder customBuilderForPayload = null;
+    protected Map customBuilders = null;
+    protected int maxDepthForCustomBuilders = -1;
+    
+    /**
+     * Element level is the depth of the element. 
+     * The root element (i.e. envelope) is defined as 1.
+     */
+    protected int elementLevel = 0;
     
     /**
      * Constructor StAXBuilder.
@@ -117,7 +130,7 @@
         this.parser = parser;
         omfactory = ombuilderFactory;
         charEncoding = characterEncoding;
-
+        
         if (parser instanceof BuilderAwareReader) {
             ((BuilderAwareReader) parser).setBuilder(this);
         }
@@ -314,7 +327,10 @@
             throw e;
         } catch (Exception e) {
             throw new OMException(e);
-        }
+        } 
+        // when an element is discarded the element index that was incremented
+        //at creation needs to be decremented !
+        elementLevel--;
     }
 
     /**
@@ -503,6 +519,56 @@
      * @throws OMException
      */
     public abstract int next() throws OMException;
+    
+    /**
+     * Register a CustomBuilder associated with the indicated QName.
+     * The CustomBuilder will be used when an element of that qname is encountered.
+     * @param qName
+     * @param maxDepth indicate the maximum depth that this qname will be found. (root = 0)
+     * @param customBuilder
+     * @return replaced CustomBuilder or null
+     */
+    public CustomBuilder registerCustomBuilder(QName qName, int maxDepth, CustomBuilder customBuilder) {
+        CustomBuilder old = null;
+        if (customBuilders == null) {
+            customBuilders = new HashMap();
+        } else {
+            old = (CustomBuilder) customBuilders.get(qName);
+        }
+        maxDepthForCustomBuilders = 
+                (maxDepthForCustomBuilders > maxDepth) ?
+                        maxDepthForCustomBuilders: maxDepth;
+        customBuilders.put(qName, customBuilder);
+        return old;
+    }
+    
+    
+    /**
+     * Register a CustomBuilder for a payload.
+     * The payload is defined as the elements inside a SOAPBody or the 
+     * document element of a REST message.
+     * @param customBuilder
+     * @return replaced CustomBuilder or null
+     */
+    public CustomBuilder registerCustomBuilderForPayload(CustomBuilder customBuilder) {
+        CustomBuilder old = null;
+        this.customBuilderForPayload = customBuilder;
+        return old;
+    }
+    
+    /**
+     * Return CustomBuilder associated with the namespace/localPart
+     * @param namespace
+     * @param localPart
+     * @return CustomBuilder or null
+     */ 
+    protected CustomBuilder getCustomBuilder(String namespace, String localPart) {
+        if (customBuilders == null) {
+            return null;
+        }
+        QName qName = new QName(namespace, localPart);
+        return (CustomBuilder) customBuilders.get(qName);
+    }
 
     /** @return Returns short. */
     public short getBuilderType() {

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java?rev=587834&r1=587833&r2=587834&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java Wed Oct 24 02:37:25 2007
@@ -160,7 +160,8 @@
                         log.trace(
                                 "START_ELEMENT: " + parser.getName() + ":" + parser.getLocalName());
                     }
-                    lastNode = createOMElement();
+                    elementLevel++;
+                    lastNode = createNextOMElement();
                     break;
                 case XMLStreamConstants.START_DOCUMENT:
                     // Document has already being created.
@@ -189,6 +190,7 @@
                         log.trace("END_ELEMENT: " + parser.getName() + ":" + parser.getLocalName());
                     }
                     endElement();
+                    elementLevel--;
                     break;
                 case XMLStreamConstants.END_DOCUMENT:
                     if (doTrace) {
@@ -238,6 +240,45 @@
         } catch (Exception e) {
             throw new OMException(e);
         }
+    }
+    
+    /**
+     * Creates a new OMElement using either a CustomBuilder or 
+     * the default Builder mechanism.
+     * @return
+     */
+    protected OMNode createNextOMElement() {
+        OMNode newElement = null;
+        if (elementLevel == 1 && this.customBuilderForPayload != null) {
+            newElement = createWithCustomBuilder(customBuilderForPayload);
+        } else if (customBuilders != null && elementLevel <= this.maxDepthForCustomBuilders) {
+            String namespace = parser.getNamespaceURI();
+            String localPart = parser.getLocalName();
+            CustomBuilder customBuilder = getCustomBuilder(namespace, localPart);
+            if (customBuilder != null) {
+                createWithCustomBuilder(customBuilder);
+            }
+        }
+        if (newElement == null) {
+            newElement = createOMElement();
+        }
+        return newElement;
+    }
+    
+    protected OMNode createWithCustomBuilder(CustomBuilder customBuilder) {
+        String namespace = parser.getNamespaceURI();
+        String localPart = parser.getLocalName();
+        OMContainer parent = null;
+        if (lastNode != null) {
+            if (lastNode.isComplete()) {
+                parent = lastNode.getParent();
+            } else {
+                parent = (OMContainer)lastNode;
+            }
+                
+        }
+        return customBuilder.create(namespace, localPart, parent, parser, omfactory);
+        
     }
 
     /**

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/serialize/StreamingOMSerializer.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/serialize/StreamingOMSerializer.java?rev=587834&r1=587833&r2=587834&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/serialize/StreamingOMSerializer.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/serialize/StreamingOMSerializer.java Wed Oct 24 02:37:25 2007
@@ -54,7 +54,18 @@
      */
     public void serialize(XMLStreamReader node, XMLStreamWriter writer)
             throws XMLStreamException {
-        serializeNode(node, writer);
+        serialize(node, writer, true);
+    }
+    
+    /**
+     * @param node
+     * @param writer
+     * @param startAtNext indicate if reading should start at next event or current event
+     * @throws XMLStreamException
+     */
+    public void serialize(XMLStreamReader node, XMLStreamWriter writer, boolean startAtNext)
+            throws XMLStreamException {
+        serializeNode(node, writer, startAtNext);
     }
 
     /**
@@ -64,12 +75,31 @@
      * @param writer
      * @throws XMLStreamException
      */
-    protected void serializeNode(XMLStreamReader reader, XMLStreamWriter writer)
+    protected void serializeNode(XMLStreamReader reader, XMLStreamWriter writer) 
+        throws XMLStreamException {
+        serializeNode(reader, writer, true);
+    }
+    protected void serializeNode(XMLStreamReader reader, 
+                                 XMLStreamWriter writer, 
+                                 boolean startAtNext)
             throws XMLStreamException {
-        //TODO We get the StAXWriter at this point and uses it hereafter assuming that this is the only entry point to this class.
-        // If there can be other classes calling methodes of this we might need to change methode signatures to OMOutputer
-        while (reader.hasNext()) {
-            int event = reader.next();
+        // TODO We get the StAXWriter at this point and uses it hereafter 
+        // assuming that this is the only entry point to this class.
+        // If there can be other classes calling methodes of this we might 
+        // need to change methode signatures to OMOutputer
+        
+        // If not startAtNext, then seed the processing with the current element.
+        boolean useCurrentEvent = !startAtNext;
+        
+        while (reader.hasNext() || useCurrentEvent) {
+            int event = 0;
+            if (useCurrentEvent) {
+                event = reader.getEventType();
+                useCurrentEvent = false;
+            } else {
+                event = reader.next();
+            }
+            
             if (event == START_ELEMENT) {
                 serializeElement(reader, writer);
                 depth++;

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/MTOMStAXSOAPModelBuilder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/MTOMStAXSOAPModelBuilder.java?rev=587834&r1=587833&r2=587834&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/MTOMStAXSOAPModelBuilder.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/MTOMStAXSOAPModelBuilder.java Wed Oct 24 02:37:25 2007
@@ -72,7 +72,6 @@
 
         // create an OMBlob if the element is an <xop:Include>
         if (XOP_INCLUDE.equals(elementName) && XOP_NAMESPACE_URI.equals(namespaceURI)) {
-            elementLevel++;
             OMText node;
             String contentID = ElementHelper.getContentID(parser, getDocument()
                     .getCharsetEncoding());

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/SOAP11BuilderHelper.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/SOAP11BuilderHelper.java?rev=587834&r1=587833&r2=587834&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/SOAP11BuilderHelper.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/SOAP11BuilderHelper.java Wed Oct 24 02:37:25 2007
@@ -63,7 +63,7 @@
                 processText(parser, code);
                 ((OMNodeEx) code).setComplete(true);
                 element = code;
-                builder.elementLevel--;
+                ((StAXSOAPModelBuilder) builder).adjustElementLevel(-1);
 
                 faultcodePresent = true;
             } else if (SOAP_FAULT_STRING_LOCAL_NAME.equals(localName)) {
@@ -76,7 +76,7 @@
                 processText(parser, reason);
                 ((OMNodeEx) reason).setComplete(true);
                 element = reason;
-                builder.elementLevel--;
+                ((StAXSOAPModelBuilder) builder).adjustElementLevel(-1);
 
 
                 faultstringPresent = true;

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/StAXSOAPModelBuilder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/StAXSOAPModelBuilder.java?rev=587834&r1=587833&r2=587834&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/StAXSOAPModelBuilder.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/StAXSOAPModelBuilder.java Wed Oct 24 02:37:25 2007
@@ -20,6 +20,7 @@
 package org.apache.axiom.soap.impl.builder;
 
 import org.apache.axiom.om.OMAbstractFactory;
+import org.apache.axiom.om.OMContainer;
 import org.apache.axiom.om.OMDocument;
 import org.apache.axiom.om.OMElement;
 import org.apache.axiom.om.OMException;
@@ -27,6 +28,7 @@
 import org.apache.axiom.om.OMNode;
 import org.apache.axiom.om.impl.OMContainerEx;
 import org.apache.axiom.om.impl.OMNodeEx;
+import org.apache.axiom.om.impl.builder.CustomBuilder;
 import org.apache.axiom.om.impl.builder.StAXOMBuilder;
 import org.apache.axiom.soap.SOAP11Constants;
 import org.apache.axiom.soap.SOAP12Constants;
@@ -63,12 +65,6 @@
     /** Field log */
     private static final Log log = LogFactory.getLog(StAXSOAPModelBuilder.class);
 
-    /**
-     * element level 1 = envelope level element level 2 = Header or Body level element level 3 =
-     * HeaderElement or BodyElement level
-     */
-    protected int elementLevel = 0;
-
     private boolean processingFault = false;
 
 
@@ -163,14 +159,39 @@
         return envelope;
     }
 
-
-    public void discard(OMElement element) throws OMException {
-        super.discard(element);
-        //when an element is discarded the element index that was incremented
-        //at creation needs to be decremented !
-        elementLevel--;
+    /**
+     * Creates a new OMElement using either a CustomBuilder or 
+     * the default Builder mechanism.
+     * @return
+     */
+    protected OMNode createNextOMElement() {
+        OMNode newElement = null;
+        if (elementLevel == 3 && 
+            customBuilderForPayload != null) {
+            
+            OMNode parent = lastNode;
+            if (parent != null && parent.isComplete()) {
+                parent = (OMNode) lastNode.getParent();
+            }
+            if (parent instanceof SOAPBody) {
+                newElement = createWithCustomBuilder(customBuilderForPayload);
+            }
+        } 
+        if (newElement == null && customBuilders != null && 
+                elementLevel <= maxDepthForCustomBuilders) {
+            String namespace = parser.getNamespaceURI();
+            String localPart = parser.getLocalName();
+            CustomBuilder customBuilder = getCustomBuilder(namespace, localPart);
+            if (customBuilder != null) {
+                createWithCustomBuilder(customBuilder);
+            }
+        }
+        if (newElement == null) {
+            newElement = createOMElement();
+        }
+        return newElement;
     }
-
+    
     /**
      * Method createOMElement.
      *
@@ -178,7 +199,6 @@
      * @throws OMException
      */
     protected OMNode createOMElement() throws OMException {
-        elementLevel++;
         OMElement node;
         String elementName = parser.getLocalName();
         if (lastNode == null) {
@@ -379,7 +399,6 @@
             OMNode e = lastNode;
             ((OMNodeEx) e).setComplete(true);
         }
-        elementLevel--;
     }
 
     /** Method createDTD. Overriding the default behaviour as a SOAPMessage should not have a DTD. */
@@ -454,4 +473,13 @@
         return soapFactory;
     }
 
+    /**
+     * Increase or decrease the element level by the desired amount.
+     * This is needed by the SOAP11BuilderHelper to account for the different
+     * depths for the SOAP fault sytax.
+     * @param value
+     */
+    void adjustElementLevel(int value) {
+        elementLevel = elementLevel + value;
+    }
 }

Added: webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/CustomBuilderTest.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/CustomBuilderTest.java?rev=587834&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/CustomBuilderTest.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/CustomBuilderTest.java Wed Oct 24 02:37:25 2007
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2004,2007 The Apache Software Foundation.
+ *
+ * Licensed 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.builder;
+
+import org.apache.axiom.om.AbstractTestCase;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMNamespace;
+import org.apache.axiom.om.OMNode;
+import org.apache.axiom.om.OMSourcedElement;
+import org.apache.axiom.om.OMXMLParserWrapper;
+import org.apache.axiom.om.TestConstants;
+import org.apache.axiom.om.ds.ByteArrayDataSource;
+import org.apache.axiom.om.ds.custombuilder.ByteArrayCustomBuilder;
+import org.apache.axiom.om.util.CopyUtils;
+import org.apache.axiom.soap.SOAPBody;
+import org.apache.axiom.soap.SOAPEnvelope;
+import org.apache.axiom.soap.SOAPFactory;
+import org.apache.axiom.soap.SOAPHeader;
+import org.apache.axiom.soap.SOAPHeaderBlock;
+import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+
+import java.io.File;
+import java.io.FileReader;
+import java.util.Iterator;
+
+/**
+ * Validates CopyUtils utility
+ */
+/**
+ * @author scheu
+ *
+ */
+public class CustomBuilderTest extends AbstractTestCase {
+
+    public CustomBuilderTest(String testName) {
+        super(testName);
+    }
+    
+    public void testSample1() throws Exception {
+        File file = getTestResourceFile(TestConstants.SAMPLE1);
+        copyAndCheck(createEnvelope(file), true);
+    }
+    
+    public void testSOAPMESSAGE() throws Exception {
+        File file = getTestResourceFile(TestConstants.SOAP_SOAPMESSAGE);
+        copyAndCheck(createEnvelope(file), true);
+    }
+    
+    public void testSOAPMESSAGE1() throws Exception {
+        File file = getTestResourceFile(TestConstants.SOAP_SOAPMESSAGE1);
+        copyAndCheck(createEnvelope(file), false);  // Ignore the serialization comparison
+    }
+    
+    public void testWHITESPACE_MESSAGE() throws Exception {
+        File file = getTestResourceFile(TestConstants.WHITESPACE_MESSAGE);
+        copyAndCheck(createEnvelope(file), true);
+    }
+    
+    public void testREALLY_BIG_MESSAGE() throws Exception {
+        File file = getTestResourceFile(TestConstants.REALLY_BIG_MESSAGE);
+        copyAndCheck(createEnvelope(file), false);  // Ignore the serialization comparison
+    }
+    public void testOMSE() throws Exception {
+        File file = getTestResourceFile(TestConstants.EMPTY_BODY_MESSAGE);
+        SOAPEnvelope sourceEnv = createEnvelope(file);
+        SOAPBody body = sourceEnv.getBody();
+        
+        // Create a payload
+        String text = "<tns:payload xmlns:tns=\"urn://test\">Hello World</tns:payload>";
+        String encoding = "UTF-8";
+        ByteArrayDataSource bads = new ByteArrayDataSource(text.getBytes(encoding), encoding);
+        OMNamespace ns = body.getOMFactory().createOMNamespace("urn://test", "tns");
+        OMSourcedElement omse =body.getOMFactory().createOMElement(bads, "payload", ns);
+        body.addChild(omse);
+        copyAndCheck(sourceEnv, true);
+    }
+    
+    public void testOMSE2() throws Exception {
+        File file = getTestResourceFile(TestConstants.EMPTY_BODY_MESSAGE);
+        SOAPEnvelope sourceEnv = createEnvelope(file);
+        SOAPBody body = sourceEnv.getBody();
+        SOAPHeader header = sourceEnv.getHeader();
+        String encoding = "UTF-8";
+        
+        // Create a header OMSE
+        String hdrText = "<hdr:myheader xmlns:hdr=\"urn://test\">Hello World</hdr:myheader>";
+        ByteArrayDataSource badsHdr = 
+            new ByteArrayDataSource(hdrText.getBytes(encoding), encoding);
+        OMNamespace hdrNS = header.getOMFactory().createOMNamespace("urn://test", "hdr");
+        SOAPFactory sf = (SOAPFactory) header.getOMFactory();
+        SOAPHeaderBlock shb = sf.createSOAPHeaderBlock("myheader", hdrNS, badsHdr);
+        shb.setProcessed();  // test setting processing flag
+        header.addChild(shb);
+        
+        // Create a payload
+        String text = "<tns:payload xmlns:tns=\"urn://test\">Hello World</tns:payload>";
+        ByteArrayDataSource bads = new ByteArrayDataSource(text.getBytes(encoding), encoding);
+        OMNamespace ns = body.getOMFactory().createOMNamespace("urn://test", "tns");
+        OMSourcedElement omse =body.getOMFactory().createOMElement(bads, "payload", ns);
+        body.addChild(omse);
+        
+        copyAndCheck(sourceEnv, true);
+        
+        // The source SOAPHeaderBlock should not be expanded in the process
+        assertTrue(shb.isExpanded() == false);
+        
+    }
+    
+    /**
+     * Create SOAPEnvelope from the test in the indicated file
+     * @param file
+     * @return
+     * @throws Exception
+     */
+    protected SOAPEnvelope createEnvelope(File file) throws Exception {
+        XMLStreamReader parser =
+            XMLInputFactory.newInstance().createXMLStreamReader(new FileReader(file));
+        StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(parser, null);
+        builder.registerCustomBuilderForPayload(new ByteArrayCustomBuilder("utf-8"));
+        SOAPEnvelope sourceEnv = (SOAPEnvelope) builder.getDocumentElement();
+        return sourceEnv;
+    }
+    
+    /**
+     * Make a copy of the source envelope and validate the target tree
+     * @param sourceEnv
+     * @param checkText (if true, check the serialization of the source and target tree)
+     * @throws Exception
+     */
+    protected void copyAndCheck(SOAPEnvelope sourceEnv, boolean checkText) throws Exception {
+        SOAPEnvelope targetEnv = CopyUtils.copy(sourceEnv);
+        
+        identityCheck(sourceEnv, targetEnv, "");
+        
+        String sourceText = sourceEnv.toString();
+        String targetText = targetEnv.toString();
+        
+        // In some cases the serialization code or internal hashmaps cause
+        // attributes or namespaces to be in a different order...accept this for now.
+        if (checkText) {
+            assertTrue("\nSource=" + sourceText +
+                   "\nTarget=" + targetText,
+                   sourceText.equals(targetText));
+        }
+        SOAPBody body = sourceEnv.getBody();
+        OMElement payload = body.getFirstElement();
+        
+        assertTrue("Expected OMSourcedElement payload", payload instanceof OMSourcedElement);
+        assertTrue("Expected unexpanded payload", !((OMSourcedElement)payload).isExpanded());
+        
+    }
+    
+    /**
+     * Check the identity of each object in the tree
+     * @param source
+     * @param target
+     * @param depth
+     */
+    protected void identityCheck(OMNode source, OMNode target, String depth) {
+        // System.out.println(depth + source.getClass().getName());
+        if (source instanceof OMElement) {
+            
+            if (source instanceof OMSourcedElement) {
+                assertTrue("Source = " + source.getClass().getName() + 
+                           "Target = " + target.getClass().getName(),
+                           target instanceof OMSourcedElement);
+                assertTrue("Source Expansion = " +((OMSourcedElement)source).isExpanded() +
+                           "Target Expansion = " + ((OMSourcedElement)target).isExpanded(),
+                           ((OMSourcedElement)source).isExpanded() ==
+                               ((OMSourcedElement)target).isExpanded());
+                if (((OMSourcedElement)source).isExpanded()) {
+                    Iterator i = ((OMElement) source).getChildren();
+                    Iterator j = ((OMElement) target).getChildren();
+                    while(i.hasNext() && j.hasNext()) {
+                        OMNode sourceChild = (OMNode) i.next();
+                        OMNode targetChild = (OMNode) j.next();
+                        identityCheck(sourceChild, targetChild, depth + "  ");
+                    }
+                    assertTrue("Source and Target have different number of children",
+                               i.hasNext() == j.hasNext());
+                }
+            } else {
+                assertTrue("Source = " + source.getClass().getName() + 
+                           "Target = " + target.getClass().getName(),
+                           source.getClass().getName().equals(
+                           target.getClass().getName()));
+                Iterator i = ((OMElement) source).getChildren();
+                Iterator j = ((OMElement) target).getChildren();
+                while(i.hasNext() && j.hasNext()) {
+                    OMNode sourceChild = (OMNode) i.next();
+                    OMNode targetChild = (OMNode) j.next();
+                    identityCheck(sourceChild, targetChild, depth + "  ");
+                }
+                assertTrue("Source and Target have different number of children",
+                           i.hasNext() == j.hasNext());
+            }
+        } else {
+            assertTrue("Source = " + source.getClass().getName() + 
+                   "Target = " + target.getClass().getName(),
+                   source.getClass().getName().equals(
+                   target.getClass().getName()));
+        }
+    }
+}

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/util/CopyUtilsTest.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/util/CopyUtilsTest.java?rev=587834&r1=587833&r2=587834&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/util/CopyUtilsTest.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/util/CopyUtilsTest.java Wed Oct 24 02:37:25 2007
@@ -40,10 +40,6 @@
 /**
  * Validates CopyUtils utility
  */
-/**
- * @author scheu
- *
- */
 public class CopyUtilsTest extends AbstractTestCase {
 
     public CopyUtilsTest(String testName) {



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: commons-dev-help@ws.apache.org