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/02/11 04:39:13 UTC

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

dims        2005/02/10 19:39:13

  Modified:    java/src/org/apache/axis/encoding/ser/xbeans
                        XmlBeanSerializer.java
  Log:
  fix for AXIS-1812 - XMLBeanSerialization doesn't generate correct WSDL \n from daryoush mehrtash
  
  Revision  Changes    Path
  1.3       +131 -123  ws-axis/java/src/org/apache/axis/encoding/ser/xbeans/XmlBeanSerializer.java
  
  Index: XmlBeanSerializer.java
  ===================================================================
  RCS file: /home/cvs/ws-axis/java/src/org/apache/axis/encoding/ser/xbeans/XmlBeanSerializer.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- XmlBeanSerializer.java	21 Jan 2005 20:09:48 -0000	1.2
  +++ XmlBeanSerializer.java	11 Feb 2005 03:39:13 -0000	1.3
  @@ -21,15 +21,21 @@
   
   package org.apache.axis.encoding.ser.xbeans;
   
  +import org.apache.axis.AxisFault;
   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.beehive.wsm.wsdl.Schema;
  +import org.apache.beehive.wsm.wsdl.Utilities;
  +import org.apache.xmlbeans.SchemaField;
   import org.apache.xmlbeans.SchemaType;
  +import org.apache.xmlbeans.SchemaTypeLoader;
   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.LocalElement;
   import org.w3.x2001.xmlSchema.SchemaDocument;
   import org.w3.x2001.xmlSchema.TopLevelComplexType;
   import org.w3.x2001.xmlSchema.TopLevelElement;
  @@ -44,6 +50,7 @@
   import javax.xml.namespace.QName;
   import java.io.IOException;
   import java.io.InputStream;
  +import java.lang.reflect.Array;
   import java.util.HashSet;
   import java.util.Set;
   
  @@ -92,145 +99,146 @@
       }
   
       /**
  -     * Return XML schema for the specified type, suitable for insertion into
  -     * the <types> element of a WSDL document, or underneath an
  +     * Return XML schema for the specified type, suitable for insertion into the
  +     * <types> element of a WSDL document, or underneath an
        * <element> or <attribute> 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.
  +     * 
  +     * @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)) {
  +        try {
  +            if (!XmlObject.class.isAssignableFrom(javaType)) {
  +                throw new RuntimeException(
  +                        "Invalid Object type is assigned to the XMLBeanSerialization Type: "
  +                                + javaType.getCanonicalName());
  +            }
  +
               SchemaType docType = XmlBeans.typeForClass(javaType);
  +            writeSchemaForDocType(docType, types);
  +            // assume that the writeSchemaForDocType wrote the schema
  +            // for the type and all the dependent types.
  +            return null;
  +        } catch (Exception e) {
  +            e.printStackTrace();
  +            throw e;
  +        }
  +    }
   
  -            /*
  -             * 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();
  -                    for (int j = 0; j < schemas.length; j++) {
  -                        if (stNS.equals(schemas[j].getTargetNamespace())) {
  -                            schema = schemas[j];
  -                            break;
  -                        }
  -                    }
  -                }
  -            } else {
  -                SchemaDocument schemaDoc = SchemaDocument.Factory.parse(stream);
  -                schema = schemaDoc.getSchema();
  +    /**
  +     * @param types
  +     * @param docType
  +     * @return
  +     * @throws Exception
  +     */
  +    private void writeSchemaForDocType(SchemaType docType, Types types)
  +            throws Exception {
  +        Schema mySchema = Utilities.findtSchemaDocument(docType);
  +
  +        QName q = docType.getName();
  +
  +        XmlObject typeNodeInWSDL = mySchema.getTypeNode(q);
  +
  +        if (null == typeNodeInWSDL)
  +            throw new RuntimeException(
  +                    "Type for object not found in the assigned WSDL file. "
  +                            + docType.getName() + " schema in: "
  +                            + docType.getSourceName());
  +        //        insertDependentTypes(typeNodeInWSDL, types);
  +        Node n = typeNodeInWSDL.getDomNode();
  +        Document doc = types.createElement(
  +                "element_to_get_document_useless_otherwise").getOwnerDocument();
  +        Element e = (Element) doc.importNode(n, true);
  +        try {
  +            types.writeSchemaElementDecl(q, e);
  +        } catch (AxisFault e1) {
  +            // this means the types was already in... fine!
  +            // TBD: make sure there are other types of exceptions are at least
  +            // reported
  +        }
  +        Set<QName> dependentTypes = new HashSet<QName>();
  +        getAllDependentTypes(typeNodeInWSDL, dependentTypes);
  +        for (QName nxtType : dependentTypes) {
  +            Class nxtJavaType = null;
  +            // add the class if it is an xml bean
  +            if (null != (nxtJavaType = q2UserClass(nxtType))
  +                    && XmlObject.class.isAssignableFrom(nxtJavaType)) {
  +                writeSchema(nxtJavaType, types);
               }
  +        }
  +        return;
  +    }
   
  -            /*
  -             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;
  -                }
  +    /**
  +     * @param nxtType
  +     * @return null for classes that are not found, or if they are primitive types
  +     *     * 
  +     */
  +    private Class q2UserClass(QName qname) {
  +        SchemaTypeLoader stl = XmlBeans.getContextTypeLoader();
  +        SchemaType st = stl.findType(qname);
  +        if (st == null) {
  +            SchemaField sf = stl.findElement(qname);
  +            if (sf != null)
  +                st = sf.getType();
  +        }
  +
  +        if (st != null && !st.isBuiltinType())
  +            return st.getJavaClass();
  +        else
  +            return null; // for classes that are not found, or are build in
  +
  +    }
  +
  +    /**
  +     * @param nodeInWSDL
  +     * @param dependentTypes
  +     * @return
  +     * 
  +     * Walk all the nodes under the nodeInWSDL if there is an 'element' type the
  +     * add its types or references to the dependent type.
  +     */
  +    private void getAllDependentTypes(XmlObject nodeInWSDL,
  +            Set<QName> dependentTypes) {
  +        // scan for any node under the type that has "type" or "ref" attribute
  +        XmlCursor cursor = nodeInWSDL.newCursor();
  +        if (cursor.toFirstChild()) { // has child
  +            while (true) {
  +                getAllDependentTypes(cursor.getObject(), dependentTypes);
  +                if (!cursor.toNextSibling())
  +                    break;
               }
  -            throw new Exception(javaType.getName()
  -                    + "did not specify a target namespace");
  -        } else {
  -            throw new Exception(javaType.getName()
  -                    + " must be a subclass of XmlObject");
           }
  +        if (nodeInWSDL.schemaType().getName().getLocalPart().equals(
  +                "localElement")) {
  +            LocalElement e = (LocalElement) nodeInWSDL;
  +
  +            if (e.isSetType())
  +                dependentTypes.add(e.getType());
  +            else if (e.isSetRef())
  +                dependentTypes.add(e.getRef());
  +        }
  +        return;
       }
   
  -    // NOTE jcolwell@bea.com 2004-Nov-15 -- 
  +    // 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 {
  +    private static <T extends XmlObject> T[] selectChildren(XmlObject parent,
  +            Class<T> 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());
  +        XmlObject[] kids = parent.selectChildren(st.getDocumentElementName());
  +        T[] castKids = (T[]) Array.newInstance(childClass, kids.length);
  +        for (int j = 0; j < castKids.length; j++) {
  +            castKids[j] = childClass.cast(kids[j]);
  +        }
  +        return castKids;
       }
   }