You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by di...@apache.org on 2005/01/21 18:41:11 UTC

cvs commit: ws-axis/java/src/org/apache/axis/encoding/ser/xbeans XmlBeanDeserializer.java XmlBeanDeserializerFactory.java XmlBeanSerializer.java XmlBeanSerializerFactory.java

dims        2005/01/21 09:41:11

  Modified:    java     build.xml
               java/xmls targets.xml
  Added:       java/src/org/apache/axis/encoding/ser/xbeans
                        XmlBeanDeserializer.java
                        XmlBeanDeserializerFactory.java
                        XmlBeanSerializer.java
                        XmlBeanSerializerFactory.java
  Log:
  Fix for  AXIS-1764 - Add an XmlBean Serializer and Deserializer to Axis
  from Jonathan Colwell (beehive@superflaco.com)
  
  Revision  Changes    Path
  1.259     +2 -0      ws-axis/java/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/ws-axis/java/build.xml,v
  retrieving revision 1.258
  retrieving revision 1.259
  diff -u -r1.258 -r1.259
  --- build.xml	29 Dec 2004 07:03:18 -0000	1.258
  +++ build.xml	21 Jan 2005 17:41:11 -0000	1.259
  @@ -37,6 +37,7 @@
      httpunit           from http://sourceforge.net/projects/httpunit/
      jms                from http://java.sun.com/products/jms/
      castor             from http://castor.exolab.org/
  +   xmlbeans           from http://xmlbeans.apache.org/
      
   j2ee.jar contains the mailapi, activation and servlet libraries   
   
  @@ -158,6 +159,7 @@
         <exclude name="**/javax/xml/rpc/server/Servlet*.java" unless="servlet.present"/>
         <exclude name="**/*TestSuite.java" unless="junit.present"/>
         <exclude name="**/org/apache/axis/encoding/ser/castor/*.java" unless="castor.present"/>
  +      <exclude name="**/org/apache/axis/encoding/ser/xbeans/*.java" unless="xmlbeans.present"/>
         <exclude name="**/org/apache/axis/test/AxisTestBase.java" unless="junit.present"/>
   
         <exclude name="**/org/apache/axis/transport/mail/*.java" unless="commons-net.present"/>
  
  
  
  1.77      +9 -0      ws-axis/java/xmls/targets.xml
  
  Index: targets.xml
  ===================================================================
  RCS file: /home/cvs/ws-axis/java/xmls/targets.xml,v
  retrieving revision 1.76
  retrieving revision 1.77
  diff -u -r1.76 -r1.77
  --- targets.xml	23 Dec 2004 00:06:28 -0000	1.76
  +++ targets.xml	21 Jan 2005 17:41:11 -0000	1.77
  @@ -234,6 +234,14 @@
         <available classname="org.exolab.castor.xml.MarshalException" classpathref="classpath" />
       </condition>
   
  +    <condition property="xmlbeans.present" >
  +      <and>
  +        <available classname="org.apache.xmlbeans.XmlObject" classpathref="classpath" />
  +        <available classname="org.xmlsoap.schemas.wsdl.DefinitionsDocument" classpathref="classpath" />
  +        <available classname="javax.xml.stream.XMLStreamReader" classpathref="classpath" />
  +      </and>
  +    </condition>
  +
       <condition property="bsf.present" >
         <available classname="org.apache.bsf.BSFManager" classpathref="classpath" />
       </condition>
  @@ -362,6 +370,7 @@
       <echo message="security.present=${security.present}" />
       <echo message="servlet.present=${servlet.present}" />
       <echo message="sun.jsse.present=${sun.jsse.present}" />
  +    <echo message="xmlbeans.present=${xmlbeans.present}" />
       <echo message=""/>
       <echo message="--- Miscellaneous (for running tests) ---" />
       <echo message="axis-ant.present=${axis-ant.present}" />
  
  
  
  1.1                  ws-axis/java/src/org/apache/axis/encoding/ser/xbeans/XmlBeanDeserializer.java
  
  Index: XmlBeanDeserializer.java
  ===================================================================
  /*
   * XmlBeanDeserializer.java
   * 
   * Copyright 2001-2004 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.
   * 
   * 
   * Original author: Jonathan Colwell
   */
  package org.apache.axis.encoding.ser.xbeans;
  
  import org.apache.axis.encoding.DeserializationContext;
  import org.apache.axis.encoding.DeserializerImpl;
  import org.apache.axis.message.MessageElement;
  import org.apache.xmlbeans.QNameSet;
  import org.apache.xmlbeans.SchemaType;
  import org.apache.xmlbeans.XmlObject;
  import org.apache.xmlbeans.XmlOptions;
  import org.xml.sax.Attributes;
  import org.xml.sax.SAXException;
  
  import javax.xml.namespace.QName;
  
  /**
   * Class XmlBeanDeserializer
   * @author Jonathan Colwell
   */
  public class XmlBeanDeserializer extends DeserializerImpl {
  
      private Class mJavaType;
      private QName mXmlType;
  
      public XmlBeanDeserializer(Class javaType, QName xmlType) {
          mJavaType = javaType;
          mXmlType = xmlType;
      }
  
      public void onStartElement(String namespace, String localName,
                                 String prefix, Attributes attributes,
                                 DeserializationContext context)
              throws SAXException {
          try {
              MessageElement me = context.getCurElement();
              XmlOptions opts = new XmlOptions()
                      .setLoadReplaceDocumentElement(null);
              XmlObject xObj = XmlObject.Factory.parse(me, opts);
              SchemaType st = xObj.schemaType();
              SchemaType jt = (SchemaType) mJavaType.getField("type").get(null);
              XmlObject converted = xObj.changeType(jt);
              if (converted != null) {
                  setValue(converted);
              } else {
                  XmlObject[] children = xObj.selectChildren(QNameSet.ALL);
                  for (int j = 0; j < children.length; j++) {
                      st = children[j].schemaType();
                      converted = xObj.changeType(jt);
                      if (converted != null) {
                          setValue(converted);
                          break;
                      }
                  }
              }
          } catch (Exception xe) {
              throw new SAXException(xe);
          }
      }
  }
  
  
  
  1.1                  ws-axis/java/src/org/apache/axis/encoding/ser/xbeans/XmlBeanDeserializerFactory.java
  
  Index: XmlBeanDeserializerFactory.java
  ===================================================================
  /*
   * XmlBeanDeserializerFactory.java
   * 
   * Copyright 2001-2004 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.
   * 
   * 
   * Original author: Jonathan Colwell
   */
  package org.apache.axis.encoding.ser.xbeans;
  
  import org.apache.axis.encoding.ser.BaseDeserializerFactory;
  
  import javax.xml.namespace.QName;
  
  /**
   * Class XmlBeanDeserializerFactory
   * @author Jonathan Colwell
   */
  public class XmlBeanDeserializerFactory extends BaseDeserializerFactory {
  
      public XmlBeanDeserializerFactory(Class javaType, QName xmlType) {
          super(XmlBeanDeserializer.class, xmlType, javaType);
      }
  }
  
  
  
  1.1                  ws-axis/java/src/org/apache/axis/encoding/ser/xbeans/XmlBeanSerializer.java
  
  Index: XmlBeanSerializer.java
  ===================================================================
  /*
   * XmlBeanSerializer.java
   * 
   * Copyright 2001-2004 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.
   * 
   * Original author: Jonathan Colwell
   */
  
  package org.apache.axis.encoding.ser.xbeans;
  
  import org.apache.axis.Constants;
  import org.apache.axis.encoding.SerializationContext;
  import org.apache.axis.encoding.Serializer;
  import org.apache.axis.wsdl.fromJava.Types;
  import org.apache.xmlbeans.SchemaType;
  import org.apache.xmlbeans.XmlBeans;
  import org.apache.xmlbeans.XmlCursor;
  import org.apache.xmlbeans.XmlObject;
  import org.apache.xmlbeans.XmlOptions;
  import org.w3.x2001.xmlSchema.SchemaDocument;
  import org.w3.x2001.xmlSchema.TopLevelComplexType;
  import org.w3.x2001.xmlSchema.TopLevelElement;
  import org.w3c.dom.Document;
  import org.w3c.dom.Element;
  import org.w3c.dom.Node;
  import org.xml.sax.Attributes;
  import org.xmlsoap.schemas.wsdl.DefinitionsDocument;
  import org.xmlsoap.schemas.wsdl.TDefinitions;
  import org.xmlsoap.schemas.wsdl.TTypes;
  
  import javax.xml.namespace.QName;
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.HashSet;
  import java.util.Set;
  
  /**
   * Class XmlBeanSerializer
   * @author Jonathan Colwell
   */
  public class XmlBeanSerializer implements Serializer {
  
      /**
       * Serialize an element named name, with the indicated attributes
       * and value.
       *
       * @param name       is the element name
       * @param attributes are the attributes...serialize is free to add more.
       * @param value      is the value
       * @param context    is the SerializationContext
       */
      public void serialize(QName name, Attributes attributes,
                            Object value, SerializationContext context)
              throws IOException {
          if (!(value instanceof XmlObject)) {
              throw new IOException(((value != null) ?
                      value.getClass().getName()
                      : "null")
                      + " is not an "
                      + XmlObject.class.getName());
          } else {
              context.setWriteXMLType(null);
              context.startElement(name, attributes);
              XmlCursor xCur = ((XmlObject) value).newCursor();
              if (xCur.toFirstContentToken() == XmlCursor.TokenType.START) {
                  do {
                      Node n = xCur.getDomNode();
                      if (n.getNodeType() == Node.ELEMENT_NODE) {
                          context.writeDOMElement((Element) n);
                      }
                  } while (xCur.toNextSibling());
              }
              context.endElement();
          }
      }
  
      public String getMechanismType() {
          return Constants.AXIS_SAX;
      }
  
      /**
       * Return XML schema for the specified type, suitable for insertion into
       * the &lt;types&gt; element of a WSDL document, or underneath an
       * &lt;element&gt; or &lt;attribute&gt; declaration.
       *
       * @param javaType the Java Class we're writing out schema for
       * @param types    the Java2WSDL Types object which holds the context
       *                 for the WSDL being generated.
       * @return a type element containing a schema simpleType/complexType
       * @see org.apache.axis.wsdl.fromJava.Types
       */
      public Element writeSchema(Class javaType, Types types) throws Exception {
          if (XmlObject.class.isAssignableFrom(javaType)) {
              SchemaType docType = XmlBeans.typeForClass(javaType);
  
              /*
               * NOTE jcolwell@bea.com 2004-Oct-18 -- 
               * This is a hack to handle node adoption.
               * I don't like it but I need to avoid a 
               * org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR
               * NOTE jcolwell@bea.com 2004-Oct-21 -- 
               * since I already use the Document I'll use it to check 
               * if a schema for the namspace is already in place.
               */
              
              Document doc = types.createElement("deleteme")
                      .getOwnerDocument();
              XmlOptions opts = new XmlOptions()
                      .setLoadReplaceDocumentElement(null);
              Element root = doc.getDocumentElement();
              String schemaSrc = docType.getSourceName();
              InputStream stream = docType.getTypeSystem()
                      .getSourceAsStream(schemaSrc);
              SchemaDocument.Schema schema = null;
              if (schemaSrc.endsWith(".wsdl") || schemaSrc.endsWith(".WSDL")) {
                  DefinitionsDocument defDoc =
                          DefinitionsDocument.Factory.parse(stream);
                  TTypes tt = defDoc.getDefinitions().getTypesArray(0);
                  XmlObject[] kids = selectChildren
                          (tt, SchemaDocument.Schema.class);
                  SchemaDocument.Schema[] schemas =
                          new SchemaDocument.Schema[kids.length];
  
                  // NOTE jcolwell@bea.com 2005-Jan-10 -- this is the part that the
                  // fancy generics saves me from having to do after each call to 
                  // selectChildren(XmlObject, Class)                
  
                  for (int j = 0; j < kids.length; j++) {
                      schemas[j] = (SchemaDocument.Schema) kids[j];
                  }
                  if (schemas.length == 1) {
                      schema = schemas[0];
                  } else {
                      String stNS = docType.getName().getNamespaceURI();
                      //System.out.println("target NS " + stNS);
                      for (int j = 0; j < schemas.length; j++) {
                          /*System.out.println("comparing schema namespace "
                            + schemas[j].getTargetNamespace());*/
                          if (stNS.equals(schemas[j].getTargetNamespace())) {
                              schema = schemas[j];
                              break;
                          }
                      }
                  }
              } else {
                  SchemaDocument schemaDoc = SchemaDocument.Factory.parse(stream);
                  schema = schemaDoc.getSchema();
              }
  
              /*
               FIXME jcolwell@bea.com 2004-Oct-21 -- it would be great if
               the Types.loadInputSchema took an input source instead of a 
               String so I could directly pass in the input stream instead of 
               providing the schema elements individually.
              */
              DefinitionsDocument defDoc = DefinitionsDocument.Factory
                      .newInstance();
              TDefinitions definitions = defDoc.addNewDefinitions();
              definitions.addNewService();
              Node defEl = definitions.newDomNode(new XmlOptions()
                      .setSaveOuter());
              Document dDoc = defEl.getOwnerDocument();
              if (null == dDoc.getDocumentElement()) {
                  dDoc.appendChild(defEl);
              }
              Set existingNameSpaces = new HashSet();
              if (dDoc != null) {
                  types.insertTypesFragment(dDoc);
                  Element e = (Element) dDoc.getFirstChild().getFirstChild()
                          .getFirstChild();
                  if (e != null) {
                      String tn = e.getAttribute("targetNamespace");
                      existingNameSpaces.add(tn);
                      while (null != (e = (Element) e.getNextSibling())) {
                          tn = e.getAttribute("targetNamespace");
                          existingNameSpaces.add(tn);
                      }
                  }
              } else {
                  throw new Exception("null document");
              }
              if (schema != null) {
                  String targetNamespace = schema.getTargetNamespace();
                  if (targetNamespace != null) {
                      if (!existingNameSpaces.contains(targetNamespace)) {
                          TopLevelComplexType[] schemaTypes = schema
                                  .getComplexTypeArray();
                          for (int j = 0; j < schemaTypes.length; j++) {
                              types.writeSchemaElement(targetNamespace,
                                      (Element) doc
                                      .importNode(schemaTypes[j].newDomNode()
                                      .getFirstChild(),
                                              true));
                          }
                          TopLevelElement[] elements = schema
                                  .getElementArray();
                          for (int j = 0; j < elements.length; j++) {
                              types.writeSchemaElement(targetNamespace,
                                      (Element) doc
                                      .importNode(elements[j].newDomNode()
                                      .getFirstChild(),
                                              true));
                          }
                      }
                      return null;
                  }
              }
              throw new Exception(javaType.getName()
                      + "did not specify a target namespace");
          } else {
              throw new Exception(javaType.getName()
                      + " must be a subclass of XmlObject");
          }
      }
  
      // NOTE jcolwell@bea.com 2004-Nov-15 -- 
      // once the WSDLProcessor is changed to an interface, remove this function
      // and use the one in the upcoming XmlBeanWSDLProcessor.
      private static XmlObject[] selectChildren(XmlObject parent,
                                                Class childClass)
              throws IllegalAccessException, NoSuchFieldException {
          // retrieve the SchemaType from the static type field
          SchemaType st = (SchemaType) childClass.getField("type").get(null);
          return parent.selectChildren(st.getDocumentElementName());
      }
  }
  
  
  
  1.1                  ws-axis/java/src/org/apache/axis/encoding/ser/xbeans/XmlBeanSerializerFactory.java
  
  Index: XmlBeanSerializerFactory.java
  ===================================================================
  /*
   * XmlBeanSerializerFactory.java
   * 
   * Copyright 2001-2004 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.
   * 
   * 
   * Original author: Jonathan Colwell
   */
  package org.apache.axis.encoding.ser.xbeans;
  
  import org.apache.axis.encoding.ser.BaseSerializerFactory;
  
  import javax.xml.namespace.QName;
  
  /**
   * Class XmlBeanSerializerFactory
   * @author Jonathan Colwell
   */
  public class XmlBeanSerializerFactory extends BaseSerializerFactory {
  
      public XmlBeanSerializerFactory(Class javaType, QName xmlType) {
          super(XmlBeanSerializer.class, xmlType, javaType);
      }
  }