You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by da...@apache.org on 2007/12/04 01:35:47 UTC

svn commit: r600745 [2/3] - in /openejb/trunk/openejb3: container/openejb-jee/src/main/java/org/apache/openejb/jee/ server/openejb-axis/ server/openejb-axis/src/main/java/org/apache/openejb/server/axis/ server/openejb-axis/src/main/java/org/apache/open...

Added: openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/HeavyweightTypeInfoBuilder.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/HeavyweightTypeInfoBuilder.java?rev=600745&view=auto
==============================================================================
--- openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/HeavyweightTypeInfoBuilder.java (added)
+++ openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/HeavyweightTypeInfoBuilder.java Mon Dec  3 16:35:45 2007
@@ -0,0 +1,473 @@
+/**
+ *
+ * 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.openejb.server.axis.assembler;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.jee.JavaWsdlMapping;
+import org.apache.openejb.jee.JavaXmlTypeMapping;
+import org.apache.openejb.jee.VariableMapping;
+import static org.apache.openejb.server.axis.assembler.JaxRpcTypeInfo.SerializerType;
+import org.apache.xmlbeans.SchemaLocalAttribute;
+import org.apache.xmlbeans.SchemaParticle;
+import org.apache.xmlbeans.SchemaProperty;
+import org.apache.xmlbeans.SchemaType;
+import org.apache.xmlbeans.soap.SOAPArrayType;
+import org.apache.xmlbeans.soap.SchemaWSDLArrayType;
+
+import javax.xml.namespace.QName;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class HeavyweightTypeInfoBuilder {
+    private static final String SOAP_ENCODING_NS = "http://schemas.xmlsoap.org/soap/encoding/";
+    private static final String XML_SCHEMA_NS = "http://www.w3.org/2001/XMLSchema";
+
+    private static final Log log = LogFactory.getLog(HeavyweightTypeInfoBuilder.class);
+
+    private final JavaWsdlMapping mapping;
+    private final ClassLoader classLoader;
+    private final Map<SchemaTypeKey, SchemaType> schemaTypeKeyToSchemaTypeMap;
+    private final Set wrapperElementQNames;
+    private final Collection<JaxRpcOperationInfo> operations;
+    private final boolean hasEncoded;
+
+    public HeavyweightTypeInfoBuilder(JavaWsdlMapping mapping, Map<SchemaTypeKey, SchemaType> schemaTypeKeyToSchemaTypeMap, ClassLoader classLoader, Set wrapperElementQNames, Collection<JaxRpcOperationInfo> operations, boolean hasEncoded) {
+        this.mapping = mapping;
+        this.classLoader = classLoader;
+        this.schemaTypeKeyToSchemaTypeMap = schemaTypeKeyToSchemaTypeMap;
+        this.wrapperElementQNames = wrapperElementQNames;
+        this.operations = operations;
+        this.hasEncoded = hasEncoded;
+    }
+
+    public List<JaxRpcTypeInfo>  buildTypeInfo() throws OpenEJBException {
+        List<JaxRpcTypeInfo> typeInfos = new ArrayList<JaxRpcTypeInfo>();
+
+        Set<QName> mappedTypeQNames = new HashSet<QName>();
+
+        //
+        // Map types with explicity Java to XML mappings
+        //
+        for (JavaXmlTypeMapping javaXmlTypeMapping : mapping.getJavaXmlTypeMapping()) {
+            SchemaTypeKey key;
+            if (javaXmlTypeMapping.getRootTypeQname() != null) {
+                QName typeQName = javaXmlTypeMapping.getRootTypeQname();
+
+                // Skip the wrapper elements.
+                if (wrapperElementQNames.contains(typeQName)) {
+                    continue;
+                }
+
+                key = new SchemaTypeKey(typeQName, javaXmlTypeMapping.isElement(), javaXmlTypeMapping.isSimpleType(), false, null);
+            } else if (javaXmlTypeMapping != null) {
+                String anonTypeQNameString = javaXmlTypeMapping.getAnonymousTypeQname();
+
+                // this appears to be ignored...
+                int pos = anonTypeQNameString.lastIndexOf(":");
+                if (pos == -1) {
+                    throw new OpenEJBException("anon QName is invalid, no final ':' " + anonTypeQNameString);
+                }
+                QName typeQName = new QName(anonTypeQNameString.substring(0, pos), anonTypeQNameString.substring(pos + 1));
+
+                // Skip the wrapper elements.
+                // todo why is this +2
+                if (wrapperElementQNames.contains(new QName(anonTypeQNameString.substring(0, pos), anonTypeQNameString.substring(pos + 2)))) {
+                    continue;
+                }
+
+                key = new SchemaTypeKey(typeQName, javaXmlTypeMapping.isElement(), javaXmlTypeMapping.isSimpleType(), true, null);
+            } else {
+                throw new OpenEJBException("either root type qname or anonymous type qname must be set");
+            }
+
+            SchemaType schemaType = schemaTypeKeyToSchemaTypeMap.get(key);
+            if (schemaType == null) {
+                // if this is a built in type then assume this is a redundant mapping
+                if (WebserviceNameSpaces.contains(key.getQName().getNamespaceURI())) {
+                    continue;
+                }
+                log.warn("Schema type key " + key + " not found in analyzed schema: " + schemaTypeKeyToSchemaTypeMap);
+                continue;
+            }
+            mappedTypeQNames.add(key.getQName());
+
+            Class clazz;
+            try {
+                clazz = Class.forName(javaXmlTypeMapping.getJavaType(), false, classLoader);
+            } catch (ClassNotFoundException e) {
+                throw new OpenEJBException("Could not load java type " + javaXmlTypeMapping.getJavaType(), e);
+            }
+
+            JaxRpcTypeInfo typeInfo = createTypeInfo(schemaType, clazz);
+
+            typeInfo.qname = key.getElementQName();
+            if (typeInfo.qname == null) {
+                typeInfo.qname = key.getQName();
+            }
+
+            mapFields(clazz, key, schemaType, javaXmlTypeMapping, typeInfo);
+
+            typeInfos.add(typeInfo);
+        }
+
+        Map<QName, SchemaTypeKey> qnameToKey = new HashMap<QName, SchemaTypeKey>();
+        for (SchemaTypeKey key : schemaTypeKeyToSchemaTypeMap.keySet()) {
+            qnameToKey.put(key.getQName(), key);
+        }
+
+        //
+        // Map types used in operations
+        //
+        for (JaxRpcOperationInfo operationInfo : operations) {
+            List<JaxRpcParameterInfo> parameters = new ArrayList<JaxRpcParameterInfo>(operationInfo.parameters);
+
+            // add the return type to the parameters so it is processed below
+            if (operationInfo.returnXmlType != null) {
+                JaxRpcParameterInfo returnParameter = new JaxRpcParameterInfo();
+                returnParameter.xmlType = operationInfo.returnXmlType;
+                returnParameter.javaType = operationInfo.returnJavaType;
+                parameters.add(returnParameter);
+            }
+
+            // add type mappings for each parameter (including the return type)
+            for (JaxRpcParameterInfo parameterInfo : parameters) {
+                QName xmlType = parameterInfo.xmlType;
+
+                // skip types that have already been mapped or are built in types
+                if (xmlType == null ||
+                        mappedTypeQNames.contains(xmlType) ||
+                        xmlType.getNamespaceURI().equals(XML_SCHEMA_NS) ||
+                        xmlType.getNamespaceURI().equals(SOAP_ENCODING_NS)) {
+                    continue;
+                }
+
+                SchemaTypeKey key = qnameToKey.get(xmlType);
+                if (key == null) {
+                    log.warn("Type QName [" + xmlType + "] defined by operation [" + operationInfo + "] has not been found in schema: " + schemaTypeKeyToSchemaTypeMap);
+                    continue;
+                }
+                SchemaType schemaType = schemaTypeKeyToSchemaTypeMap.get(key);
+                mappedTypeQNames.add(key.getQName());
+
+                Class<?> javaType;
+                try {
+                    javaType = classLoader.loadClass(parameterInfo.javaType);
+                } catch (ClassNotFoundException e) {
+                    throw new OpenEJBException("Could not load paramter");
+                }
+
+                if (!schemaType.isSimpleType() && !javaType.isArray()) {
+                    if (!mappedTypeQNames.contains(schemaType.getName())) {
+                        // TODO: this lookup is not enough: the jaxrpc mapping file may define an anonymous mapping
+                        log.warn("Operation " + operationInfo.name + "] uses XML type [" + schemaType + "], whose mapping is not declared by the jaxrpc mapping file.\n Continuing deployment; " + "yet, the deployment is not-portable.");
+                    }
+                    continue;
+                }
+
+                JaxRpcTypeInfo typeInfo = createTypeInfo(schemaType, javaType);
+                typeInfo.qname = key.getElementQName();
+                if (typeInfo.qname == null) {
+                    typeInfo.qname = key.getQName();
+                }
+
+                typeInfos.add(typeInfo);
+            }
+        }
+
+        return typeInfos;
+    }
+
+    /**
+     * Creates a JaxRpcTypeInfo based on the information contained in the XML Schema Type and Java Class.
+     * @param schemaType the xml schema for the type
+     * @param clazz the java class for the type
+     * @return the JaxRpcTypeInfo object
+     * @throws OpenEJBException if the schema is invalid
+     */
+    private JaxRpcTypeInfo createTypeInfo(SchemaType schemaType, Class clazz) throws OpenEJBException {
+        SerializerType serializerType;
+        QName xmlType = null;
+        if (schemaType.isSimpleType()) {
+            if (schemaType.getSimpleVariety() == SchemaType.ATOMIC) {
+                if (clazz.isArray()) {
+                    serializerType = SerializerType.ARRAY;
+                } else if (schemaType.getEnumerationValues() != null) {
+                    serializerType = SerializerType.ENUM;
+                } else {
+                    serializerType = SerializerType.OTHER;
+                    xmlType = schemaType.getPrimitiveType().getName();
+                }
+            } else if (schemaType.getSimpleVariety() == SchemaType.LIST) {
+                serializerType = SerializerType.LIST;
+            } else {
+                throw new OpenEJBException("Schema type [" + schemaType + "] is invalid.");
+            }
+        } else {
+            if (clazz.isArray()) {
+                serializerType = SerializerType.ARRAY;
+            } else {
+                serializerType = SerializerType.OTHER;
+                if (SchemaType.SIMPLE_CONTENT == schemaType.getContentType()) {
+                    xmlType = schemaType.getBaseType().getName();
+                } else if (SchemaType.EMPTY_CONTENT == schemaType.getContentType() ||
+                        SchemaType.ELEMENT_CONTENT == schemaType.getContentType() ||
+                        SchemaType.MIXED_CONTENT == schemaType.getContentType()) {
+                    xmlType = schemaType.getName();
+                } else {
+                    throw new OpenEJBException("Schema type [" + schemaType + "] is invalid.");
+                }
+            }
+        }
+
+        JaxRpcTypeInfo typeInfo = new JaxRpcTypeInfo();
+        typeInfo.javaType = clazz.getName();
+        typeInfo.serializerType = serializerType;
+        typeInfo.xmlType = xmlType;
+        typeInfo.canSearchParents = schemaType.getDerivationType() == SchemaType.DT_RESTRICTION;
+
+        // If we understand the axis comments correctly, componentQName is never set for j2ee ws.
+        if (serializerType == SerializerType.ARRAY) {
+            typeInfo.componentType = getArrayComponentType(schemaType);
+        }
+
+        return typeInfo;
+    }
+
+    /**
+     * Extract the nested component type of an Array from the XML Schema Type.
+     * @param schemaType the XML Schema Type to inspect
+     * @return the QName of the nested component type or null if the schema type can not be determined
+     * @throws OpenEJBException if the XML Schema Type can not represent an Array
+     */
+    private QName getArrayComponentType(SchemaType schemaType) throws OpenEJBException {
+        //First, handle case that looks like this:
+        // <complexType name="ArrayOfstring">
+        //     <complexContent>
+        //         <restriction base="soapenc:Array">
+        //             <attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
+        //         </restriction>
+        //     </complexContent>
+        // </complexType>
+        SchemaLocalAttribute arrayTypeAttribute =  schemaType.getAttributeModel().getAttribute(new QName(SOAP_ENCODING_NS, "arrayType"));
+        if (arrayTypeAttribute != null) {
+            SchemaWSDLArrayType wsdlArrayType = (SchemaWSDLArrayType) arrayTypeAttribute;
+            SOAPArrayType soapArrayType = wsdlArrayType.getWSDLArrayType();
+            if (soapArrayType != null) {
+                QName componentType = soapArrayType.getQName();
+                log.debug("Extracted componentType " + componentType + " from schemaType " + schemaType);
+                return componentType;
+            } else {
+                log.info("No SOAPArrayType for component from schemaType " + schemaType);
+            }
+        } else {
+            log.warn("No soap array info for schematype: " + schemaType);
+        }
+
+        // If that didn't work, try to handle case like this:
+        // <complexType name="ArrayOfstring1">
+        //     <complexContent>
+        //         <restriction base="soapenc:Array">
+        //             <sequence>
+        //                 <element name="string1" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
+        //             </sequence>
+        //         </restriction>
+        //     </complexContent>
+        // </complexType>
+        if (schemaType.getBaseType().getName().equals(new QName(SOAP_ENCODING_NS, "Array"))) {
+            SchemaProperty[] properties = schemaType.getDerivedProperties();
+            if (properties.length != 1) {
+                throw new OpenEJBException("more than one element inside array definition: " + schemaType);
+            }
+            QName componentType = properties[0].getType().getName();
+            log.debug("determined component type from element type");
+            return componentType;
+        }
+
+        return null;
+    }
+
+    /**
+     * Map the (nested) fields of a XML Schema Type to Java Beans properties or public fields of the specified Java Class.
+     * @param javaClass the java class to map
+     * @param key
+     * @param schemaType
+     * @param javaXmlTypeMapping the java to xml type mapping metadata
+     * @param typeInfo the JaxRpcTypeInfo for this type
+     * @throws OpenEJBException if the XML Schema Type can not be mapped to the Java Class
+     */
+    private void mapFields(Class javaClass, SchemaTypeKey key, SchemaType schemaType, JavaXmlTypeMapping javaXmlTypeMapping, JaxRpcTypeInfo typeInfo) throws OpenEJBException {
+        // Skip arrays since they can't define a variable-mapping element
+        if (!javaClass.isArray()) {
+            // if there is a variable-mapping, log a warning
+            if (!javaXmlTypeMapping.getVariableMapping().isEmpty()) {
+                log.warn("Ignoring variable-mapping defined for class " + javaClass + " which is an array.");
+            }
+            return;
+        }
+
+        // Index particles by name
+        Map<QName,SchemaParticle> paramNameToType = new HashMap<QName,SchemaParticle>();
+        if (schemaType.getContentModel() != null) {
+            int particleType = schemaType.getContentModel().getParticleType();
+            if (SchemaParticle.ELEMENT == particleType) {
+                SchemaParticle parameter = schemaType.getContentModel();
+                paramNameToType.put(parameter.getName(), parameter);
+            } else if (particleType == SchemaParticle.SEQUENCE || particleType == SchemaParticle.ALL) {
+                SchemaParticle[] properties = schemaType.getContentModel().getParticleChildren();
+                for (SchemaParticle parameter : properties) {
+                    paramNameToType.put(parameter.getName(), parameter);
+                }
+            } else {
+                throw new OpenEJBException("Only element, sequence, and all particle types are supported. SchemaType name =" + schemaType.getName());
+            }
+        }
+
+        // Index attributes by name
+        Map<String,SchemaLocalAttribute> attNameToType = new HashMap<String,SchemaLocalAttribute>();
+        if (schemaType.getAttributeModel() != null) {
+            SchemaLocalAttribute[] attributes = schemaType.getAttributeModel().getAttributes();
+            for (SchemaLocalAttribute attribute : attributes) {
+                Object old = attNameToType.put(attribute.getName().getLocalPart(), attribute);
+                if (old != null) {
+                    throw new OpenEJBException("Complain to your expert group member, spec does not support attributes with the same local name and differing namespaces: original: " + old + ", duplicate local name: " + attribute);
+                }
+            }
+        }
+
+        // Index Java bean properties by name
+        Map<String,Class> properties = new HashMap<String,Class>();
+        try {
+            PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(javaClass).getPropertyDescriptors();
+            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
+                properties.put(propertyDescriptor.getName(), propertyDescriptor.getPropertyType());
+            }
+        } catch (IntrospectionException e) {
+            throw new OpenEJBException("Class " + javaClass + " is not a valid javabean", e);
+        }
+
+        for (VariableMapping variableMapping : javaXmlTypeMapping.getVariableMapping()) {
+            String fieldName = variableMapping.getJavaVariableName();
+
+            if (variableMapping.getXmlAttributeName() != null) {
+                JaxRpcFieldInfo fieldInfo = new JaxRpcFieldInfo();
+                fieldInfo.name = fieldName;
+
+                // verify that the property exists on the java class
+                Class javaType = properties.get(fieldName);
+                if (javaType == null) {
+                    throw new OpenEJBException("field name " + fieldName + " not found in " + properties);
+                }
+
+                String attributeLocalName = variableMapping.getXmlAttributeName();
+                QName xmlName = new QName("", attributeLocalName);
+                fieldInfo.xmlName = xmlName;
+
+                SchemaLocalAttribute attribute = attNameToType.get(attributeLocalName);
+                if (null == attribute) {
+                    throw new OpenEJBException("attribute " + xmlName + " not found in schema " + schemaType.getName());
+                }
+                fieldInfo.xmlType = attribute.getType().getName();
+
+                typeInfo.fields.add(fieldInfo);
+            } else {
+                JaxRpcFieldInfo fieldInfo = new JaxRpcFieldInfo();
+                fieldInfo.isElement = true;
+                fieldInfo.name = fieldName;
+
+                // verify that the property exists on the java class or there is a public field
+                Class javaType = properties.get(fieldName);
+                if (javaType == null) {
+                    //see if it is a public field
+                    try {
+                        Field field = javaClass.getField(fieldName);
+                        javaType = field.getType();
+                    } catch (NoSuchFieldException e) {
+                        throw new OpenEJBException("field name " + fieldName + " not found in " + properties, e);
+                    }
+                }
+
+
+                QName xmlName = new QName("", variableMapping.getXmlElementName());
+                SchemaParticle particle = paramNameToType.get(xmlName);
+                if (particle == null) {
+                    String ns = key.getQName().getNamespaceURI();
+                    xmlName = new QName(ns, variableMapping.getXmlElementName());
+                    particle = paramNameToType.get(xmlName);
+                    if (particle == null) {
+                        throw new OpenEJBException("element " + xmlName + " not found in schema " + schemaType.getName());
+                    }
+                } else if (SchemaParticle.ELEMENT != particle.getParticleType()) {
+                    throw new OpenEJBException(xmlName + " is not an element in schema " + schemaType.getName());
+                }
+                fieldInfo.isNillable = particle.isNillable() || hasEncoded;
+                fieldInfo.xmlName = xmlName;
+
+                // xml type
+                if (particle.getType().getName() != null) {
+                    fieldInfo.xmlType = particle.getType().getName();
+                } else {
+                    QName anonymousName;
+                    if (key.isAnonymous()) {
+                        anonymousName = new QName(key.getQName().getNamespaceURI(), key.getQName().getLocalPart() +
+                                ">" + particle.getName().getLocalPart());
+                    } else {
+                        anonymousName = new QName(key.getQName().getNamespaceURI(),
+                                ">" + key.getQName().getLocalPart() + ">" + particle.getName().getLocalPart());
+                    }
+                    fieldInfo.xmlType = anonymousName;
+                }
+
+                if (javaType.isArray()) {
+                    fieldInfo.minOccurs = particle.getIntMinOccurs();
+                    fieldInfo.maxOccurs = particle.getIntMaxOccurs();
+                    //TODO axis seems to have the wrong name for this property based on how it is used
+                    fieldInfo.maxOccursUnbounded = particle.getIntMaxOccurs() > 1;
+                }
+
+                typeInfo.fields.add(fieldInfo);
+            }
+        }
+    }
+
+    /**
+     * All of the known built in XML Schemas used by webservices.  This is used to supress unknown type exceptions
+     */
+    private static final Set<String> WebserviceNameSpaces = Collections.unmodifiableSet(new LinkedHashSet<String>(Arrays.asList(
+            "http://schemas.xmlsoap.org/soap/encoding/", // SOAP 1.1
+            "http://www.w3.org/2003/05/soap-encoding",   // SOAP 1.2
+            "http://xml.apache.org/xml-soap",            // Apache XMLSOAP
+            "http://www.w3.org/1999/XMLSchema",          // XSD 1999
+            "http://www.w3.org/2000/10/XMLSchema",       // XSD 2000
+            "http://www.w3.org/2001/XMLSchema",          // XSD 2001
+            "http://www.w3.org/XML/1998/namespace"       // XML (for xml-any)
+    )));
+}

Added: openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcFaultInfo.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcFaultInfo.java?rev=600745&view=auto
==============================================================================
--- openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcFaultInfo.java (added)
+++ openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcFaultInfo.java Mon Dec  3 16:35:45 2007
@@ -0,0 +1,30 @@
+/**
+ *
+ * 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.openejb.server.axis.assembler;
+
+import javax.xml.namespace.QName;
+import java.util.List;
+import java.util.ArrayList;
+
+public class JaxRpcFaultInfo {
+    public QName qname;
+    public QName xmlType;
+    public String javaType;
+    public boolean complex;
+    public List<JaxRpcParameterInfo> parameters = new ArrayList<JaxRpcParameterInfo>();
+}

Added: openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcFieldInfo.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcFieldInfo.java?rev=600745&view=auto
==============================================================================
--- openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcFieldInfo.java (added)
+++ openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcFieldInfo.java Mon Dec  3 16:35:45 2007
@@ -0,0 +1,33 @@
+/**
+ *
+ * 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.openejb.server.axis.assembler;
+
+import javax.xml.namespace.QName;
+
+public class JaxRpcFieldInfo {
+    public String name;
+    public boolean isElement;
+    public QName xmlName;
+    public QName xmlType;
+
+    public boolean isNillable;
+
+    public int minOccurs;
+    public int maxOccurs;
+    public boolean maxOccursUnbounded;
+}
\ No newline at end of file

Added: openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcOperationInfo.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcOperationInfo.java?rev=600745&view=auto
==============================================================================
--- openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcOperationInfo.java (added)
+++ openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcOperationInfo.java Mon Dec  3 16:35:45 2007
@@ -0,0 +1,44 @@
+/**
+ *
+ * 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.openejb.server.axis.assembler;
+
+import javax.xml.namespace.QName;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class JaxRpcOperationInfo {
+    public String name;
+    public BindingStyle bindingStyle;
+    public boolean wrapped;
+    public OperationStyle operationStyle;
+
+    public String javaMethodName;
+
+    public List<JaxRpcParameterInfo> parameters = new ArrayList<JaxRpcParameterInfo>();
+
+    public QName returnQName;
+    public QName returnXmlType;
+    public String returnJavaType;
+
+    public Collection<JaxRpcFaultInfo> faults = new ArrayList<JaxRpcFaultInfo>();
+
+    public static enum OperationStyle {
+        ONE_WAY, REQUEST_RESPONSE, SOLICIT_RESPONSE, NOTIFICATION
+    }
+}

Added: openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcParameterInfo.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcParameterInfo.java?rev=600745&view=auto
==============================================================================
--- openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcParameterInfo.java (added)
+++ openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcParameterInfo.java Mon Dec  3 16:35:45 2007
@@ -0,0 +1,58 @@
+/**
+ *
+ * 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.openejb.server.axis.assembler;
+
+import javax.xml.namespace.QName;
+
+public class JaxRpcParameterInfo {
+    public QName qname;
+    public Mode mode;
+    public boolean soapHeader;
+    public QName xmlType;
+    public String javaType;
+
+    public static enum Mode {
+        IN(true, false),
+        OUT(false, true),
+        INOUT(true, true);
+
+        private boolean in;
+        private boolean out;
+
+        Mode(boolean in, boolean out) {
+            this.in = in;
+            this.out = out;
+        }
+
+        public boolean isIn() {
+            return in;
+        }
+
+        public void setIn(boolean in) {
+            this.in = in;
+        }
+
+        public boolean isOut() {
+            return out;
+        }
+
+        public void setOut(boolean out) {
+            this.out = out;
+        }
+    }
+}

Added: openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcServiceInfo.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcServiceInfo.java?rev=600745&view=auto
==============================================================================
--- openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcServiceInfo.java (added)
+++ openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcServiceInfo.java Mon Dec  3 16:35:45 2007
@@ -0,0 +1,32 @@
+/**
+ *
+ * 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.openejb.server.axis.assembler;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class JaxRpcServiceInfo {
+    public String name;
+    public String endpointURL;
+    public String wsdlFile;
+
+    public String serviceEndpointInterface;
+    public BindingStyle defaultBindingStyle;
+    public final Collection<JaxRpcOperationInfo> operations = new ArrayList<JaxRpcOperationInfo>();
+    public final Collection<JaxRpcTypeInfo> types = new ArrayList<JaxRpcTypeInfo>();
+}

Added: openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcServiceInfoBuilder.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcServiceInfoBuilder.java?rev=600745&view=auto
==============================================================================
--- openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcServiceInfoBuilder.java (added)
+++ openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcServiceInfoBuilder.java Mon Dec  3 16:35:45 2007
@@ -0,0 +1,191 @@
+/**
+ *
+ * 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.openejb.server.axis.assembler;
+
+import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.jee.JavaWsdlMapping;
+import org.apache.openejb.jee.PortComponent;
+import org.apache.openejb.jee.ServiceEndpointInterfaceMapping;
+import org.apache.openejb.jee.ServiceEndpointMethodMapping;
+import org.apache.xmlbeans.SchemaType;
+
+import javax.wsdl.Binding;
+import javax.wsdl.BindingInput;
+import javax.wsdl.BindingOperation;
+import javax.wsdl.Port;
+import javax.wsdl.extensions.soap.SOAPAddress;
+import javax.wsdl.extensions.soap.SOAPBinding;
+import javax.wsdl.extensions.soap.SOAPBody;
+import javax.xml.namespace.QName;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class JaxRpcServiceInfoBuilder {
+    private final JavaWsdlMapping javaWsdlMapping;
+    private final SchemaInfoBuilder schemaInfoBuilder;
+    private final PortComponent portComponent;
+    private final Port port;
+    private final String wsdlFile;
+    private final ClassLoader classLoader;
+    private JaxRpcServiceInfo serviceInfo;
+
+    public JaxRpcServiceInfoBuilder(JavaWsdlMapping javaWsdlMapping, SchemaInfoBuilder schemaInfoBuilder, PortComponent portComponent, Port port, String wsdlFile, ClassLoader classLoader) {
+        this.javaWsdlMapping = javaWsdlMapping;
+        this.schemaInfoBuilder = schemaInfoBuilder;
+        this.portComponent = portComponent;
+        this.port = port;
+        this.wsdlFile = wsdlFile;
+        this.classLoader = classLoader;
+    }
+
+    public JaxRpcServiceInfo createServiceDesc() throws OpenEJBException {
+        Class serviceEndpointInterface;
+        try {
+            serviceEndpointInterface = classLoader.loadClass(portComponent.getServiceEndpointInterface());
+        } catch (ClassNotFoundException e) {
+            throw new OpenEJBException("Unable to load the service-endpoint interface for port-component " + portComponent.getPortComponentName(), e);
+        }
+
+        Map<SchemaTypeKey, SchemaType> schemaTypeKeyToSchemaTypeMap = schemaInfoBuilder.getSchemaTypeKeyToSchemaTypeMap();
+
+        serviceInfo = new JaxRpcServiceInfo();
+        serviceInfo.name = portComponent.getWsdlPort().toString();
+        serviceInfo.serviceEndpointInterface = portComponent.getServiceEndpointInterface();
+        serviceInfo.endpointURL = getAddressLocation(port.getExtensibilityElements());
+        serviceInfo.wsdlFile = wsdlFile;
+        serviceInfo.defaultBindingStyle = getStyle(port.getBinding());
+
+        // The service is using lightweight mappings if there are no Java to XML service mappings
+        boolean isLightweight = javaWsdlMapping.getServiceEndpointInterfaceMapping().isEmpty();
+
+        //
+        // Map Operations
+        //
+        Set wrapperElementQNames = buildOperations(port.getBinding(), serviceEndpointInterface, isLightweight);
+
+        //
+        // Map Types
+        //
+        Collection<JaxRpcTypeInfo> types;
+        if (isLightweight) {
+            LightweightTypeInfoBuilder builder = new LightweightTypeInfoBuilder(javaWsdlMapping, schemaTypeKeyToSchemaTypeMap, classLoader);
+            types = builder.buildTypeInfo();
+        } else {
+            HeavyweightTypeInfoBuilder builder = new HeavyweightTypeInfoBuilder(javaWsdlMapping, schemaTypeKeyToSchemaTypeMap, classLoader, wrapperElementQNames, serviceInfo.operations, serviceInfo.defaultBindingStyle.isEncoded());
+            types = builder.buildTypeInfo();
+        }
+        serviceInfo.types.addAll(types);
+
+        return serviceInfo;
+    }
+
+    private Set<QName> buildOperations(Binding binding, Class serviceEndpointInterface, boolean lightweight) throws OpenEJBException {
+        Set<QName> wrappedElementQNames = new HashSet<QName>();
+
+
+        for (Object op : binding.getBindingOperations()) {
+            BindingOperation bindingOperation = (BindingOperation) op;
+            String operationName = bindingOperation.getOperation().getName();
+
+            if (lightweight) {
+                // Lightweight mappings are solely based on the Java method
+                Method method = getMethodForOperation(operationName, serviceEndpointInterface);
+
+                // Build the operation info using the method
+                LightweightOperationInfoBuilder operationInfoBuilder = new LightweightOperationInfoBuilder(bindingOperation, method);
+                JaxRpcOperationInfo operationInfo = operationInfoBuilder.buildOperationInfo();
+                serviceInfo.operations.add(operationInfo);
+            } else {
+                // Heavyweight mappings are solely based on the Java to XML mapping declarations
+                ServiceEndpointMethodMapping methodMapping = getMethodMappingForOperation(operationName, serviceEndpointInterface);
+
+                // Build the operation info using the Java to XML method mapping
+                HeavyweightOperationInfoBuilder operationInfoBuilder = new HeavyweightOperationInfoBuilder(bindingOperation, methodMapping, javaWsdlMapping, schemaInfoBuilder);
+                JaxRpcOperationInfo operationInfo = operationInfoBuilder.buildOperationInfo();
+                serviceInfo.operations.add(operationInfo);
+
+                // remember wrapped elements for type mapping
+                Set<QName> wrappedElementQNamesForOper = operationInfoBuilder.getWrapperElementQNames();
+                wrappedElementQNames.addAll(wrappedElementQNamesForOper);
+            }
+        }
+
+        return wrappedElementQNames;
+    }
+
+    private BindingStyle getStyle(Binding binding) throws OpenEJBException {
+        SOAPBinding soapBinding = SchemaInfoBuilder.getExtensibilityElement(SOAPBinding.class, binding.getExtensibilityElements());
+        String styleString = soapBinding.getStyle();
+
+        BindingInput bindingInput = ((BindingOperation) binding.getBindingOperations().get(0)).getBindingInput();
+        SOAPBody soapBody = SchemaInfoBuilder.getExtensibilityElement(SOAPBody.class, bindingInput.getExtensibilityElements());
+        String useString = soapBody.getUse();
+
+        BindingStyle bindingStyle = BindingStyle.getBindingStyle(styleString, useString);
+        return bindingStyle;
+    }
+
+    private String getAddressLocation(List extensibilityElements) throws OpenEJBException {
+        SOAPAddress soapAddress = SchemaInfoBuilder.getExtensibilityElement(SOAPAddress.class, extensibilityElements);
+        String locationURIString = soapAddress.getLocationURI();
+        return locationURIString;
+    }
+
+    private Method getMethodForOperation(String operationName, Class serviceEndpointInterface) throws OpenEJBException {
+        Method found = null;
+        for (Method method : serviceEndpointInterface.getMethods()) {
+            if (method.getName().equals(operationName)) {
+                if (found != null) {
+                    throw new OpenEJBException("Overloaded methods are not allowed in lightweight mappings");
+                }
+                found = method;
+            }
+        }
+        if (found == null) {
+            throw new OpenEJBException("No method found for operation named " + operationName);
+        }
+        return found;
+    }
+
+    private ServiceEndpointMethodMapping getMethodMappingForOperation(String operationName, Class serviceEndpointInterface) throws OpenEJBException {
+        // get mapping for service endpoint interface
+        ServiceEndpointInterfaceMapping interfaceMapping = javaWsdlMapping.getServiceEndpointInterfaceMappingMap().get(serviceEndpointInterface.getName());
+        if (interfaceMapping == null) {
+            throw new OpenEJBException("No java-wsdl mapping found for the service interface " + serviceEndpointInterface);
+        }
+
+        // match by operation name
+        for (ServiceEndpointMethodMapping methodMapping : interfaceMapping.getServiceEndpointMethodMapping()) {
+            if (operationName.equals(methodMapping.getWsdlOperation())) {
+                return methodMapping;
+            }
+        }
+
+        // failed - throw nice exception message
+        StringBuffer availOps = new StringBuffer(128);
+        for (ServiceEndpointMethodMapping methodMapping : interfaceMapping.getServiceEndpointMethodMapping()) {
+            if (availOps.length() > 0) availOps.append(",");
+            availOps.append(methodMapping.getWsdlOperation());
+        }
+        throw new OpenEJBException("No method found for operation named '" + operationName + "'. Available operations: " + availOps);
+    }
+}
\ No newline at end of file

Added: openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcTypeInfo.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcTypeInfo.java?rev=600745&view=auto
==============================================================================
--- openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcTypeInfo.java (added)
+++ openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/JaxRpcTypeInfo.java Mon Dec  3 16:35:45 2007
@@ -0,0 +1,43 @@
+/**
+ *
+ * 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.openejb.server.axis.assembler;
+
+import javax.xml.namespace.QName;
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class JaxRpcTypeInfo {
+    //
+    // QName is either the real QName or the generated anonymous name
+    //
+    public QName qname;
+    public boolean canSearchParents;
+
+    // this is the actual qname used to select the serializer and deserializer
+    public QName xmlType;
+    public String javaType;
+
+    public SerializerType serializerType;
+    public QName componentType;
+
+    public final Collection<JaxRpcFieldInfo> fields = new ArrayList<JaxRpcFieldInfo>();
+
+    public static enum SerializerType {
+        ARRAY, ENUM, LIST, OTHER
+    }
+}
\ No newline at end of file

Added: openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/LightweightOperationInfoBuilder.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/LightweightOperationInfoBuilder.java?rev=600745&view=auto
==============================================================================
--- openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/LightweightOperationInfoBuilder.java (added)
+++ openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/LightweightOperationInfoBuilder.java Mon Dec  3 16:35:45 2007
@@ -0,0 +1,127 @@
+/**
+ *
+ * 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.openejb.server.axis.assembler;
+
+import org.apache.openejb.OpenEJBException;
+
+import javax.wsdl.BindingOperation;
+import javax.wsdl.Message;
+import javax.wsdl.Operation;
+import javax.wsdl.Part;
+import javax.xml.namespace.QName;
+import java.lang.reflect.Method;
+import java.util.List;
+
+public class LightweightOperationInfoBuilder {
+    private final String operationName;
+    private final Message inputMessage;
+    private final Message outputMessage;
+    private final Method method;
+
+    private JaxRpcOperationInfo operationInfo;
+
+    public LightweightOperationInfoBuilder(BindingOperation bindingOperation, Method method) throws OpenEJBException{
+        if (bindingOperation == null) {
+            throw new OpenEJBException("No BindingOperation supplied for method " + method.getName());
+        }
+
+        Operation operation = bindingOperation.getOperation();
+        this.operationName = operation.getName();
+        this.inputMessage = operation.getInput().getMessage();
+        this.outputMessage = operation.getOutput() == null ? null : operation.getOutput().getMessage();
+        this.method = method;
+    }
+
+    public JaxRpcOperationInfo buildOperationInfo() throws OpenEJBException {
+        if (operationInfo != null) {
+            return operationInfo;
+        }
+
+        operationInfo = new JaxRpcOperationInfo();
+        operationInfo.name = operationName;
+        operationInfo.bindingStyle = BindingStyle.RPC_ENCODED;
+        operationInfo.javaMethodName = method.getName();
+
+        // Verify we have the right number of args for this method
+        Class[] methodParamTypes = method.getParameterTypes();
+        List inputParts = inputMessage.getOrderedParts(null);
+        if (methodParamTypes.length != inputParts.size()) {
+            throw new OpenEJBException("mismatch in parameter counts: method has " + methodParamTypes.length + " whereas the input message has " + inputParts.size());
+        }
+
+        // Map parameters
+        int i = 0;
+        for (Object inputPart : inputParts) {
+            Part part = (Part) inputPart;
+
+            JaxRpcParameterInfo parameter = new JaxRpcParameterInfo();
+            parameter.qname = new QName("", part.getName());
+            parameter.mode = JaxRpcParameterInfo.Mode.IN;
+
+            if (part.getTypeName() == null) {
+                parameter.xmlType = part.getElementName();
+            } else {
+                parameter.xmlType = part.getTypeName();
+            }
+
+            parameter.javaType = methodParamTypes[i++].getName();
+            parameter.soapHeader = false;
+
+            operationInfo.parameters.add(parameter);
+        }
+
+        // Lightweight can't have multiple return values
+        if (outputMessage != null && outputMessage.getParts().size() > 1) {
+            throw new OpenEJBException("Lightweight mapping has at most one part in the (optional) output message, not: " + outputMessage.getParts().size());
+        }
+
+        // Map return type mapping
+        if (outputMessage != null && outputMessage.getParts().size() == 1) {
+            Part part = (Part) outputMessage.getParts().values().iterator().next();
+
+            // return qname
+            if (part.getElementName() == null) {
+                operationInfo.returnQName = new QName(part.getName());
+            } else {
+                operationInfo.returnQName = part.getElementName();
+            }
+
+            // return xml schema type
+            if (part.getTypeName() == null) {
+                operationInfo.returnXmlType = part.getElementName();
+            } else {
+                operationInfo.returnXmlType = part.getTypeName();
+            }
+
+            // return java type
+            operationInfo.returnJavaType = method.getReturnType().getName();
+        }
+
+        //TODO add faults
+//        TFault[] faults = tOperation.getFaultArray();
+//        for (int i = 0; i < faults.length; i++) {
+//            TFault fault = faults[i];
+//            QName faultQName = new QName("", fault.getName());
+//            String className = ;
+//            QName faultTypeQName = ;
+//            boolean isComplex = ;
+//            FaultDesc faultDesc = new FaultDesc(faultQName, className, faultTypeQName, isComplex)
+//        }
+        return operationInfo;
+    }
+}
\ No newline at end of file

Added: openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/LightweightTypeInfoBuilder.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/LightweightTypeInfoBuilder.java?rev=600745&view=auto
==============================================================================
--- openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/LightweightTypeInfoBuilder.java (added)
+++ openejb/trunk/openejb3/server/openejb-axis/src/main/java/org/apache/openejb/server/axis/assembler/LightweightTypeInfoBuilder.java Mon Dec  3 16:35:45 2007
@@ -0,0 +1,153 @@
+/**
+ *
+ * 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.openejb.server.axis.assembler;
+
+import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.jee.JavaWsdlMapping;
+import org.apache.openejb.jee.PackageMapping;
+import org.apache.xmlbeans.SchemaParticle;
+import org.apache.xmlbeans.SchemaType;
+
+import javax.xml.namespace.QName;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class LightweightTypeInfoBuilder {
+    private final JavaWsdlMapping mapping;
+    private final Map<SchemaTypeKey, SchemaType> schemaTypeKeyToSchemaTypeMap;
+    private final ClassLoader classLoader;
+
+    public LightweightTypeInfoBuilder(JavaWsdlMapping mapping, Map<SchemaTypeKey, SchemaType> schemaTypeKeyToSchemaTypeMap, ClassLoader classLoader) {
+        this.mapping = mapping;
+        this.classLoader = classLoader;
+        this.schemaTypeKeyToSchemaTypeMap = schemaTypeKeyToSchemaTypeMap;
+    }
+
+    public List<JaxRpcTypeInfo> buildTypeInfo() throws OpenEJBException {
+        List<JaxRpcTypeInfo> typeInfoList = new ArrayList<JaxRpcTypeInfo>();
+
+        for (Map.Entry<SchemaTypeKey, SchemaType> entry : schemaTypeKeyToSchemaTypeMap.entrySet()) {
+            SchemaTypeKey key = entry.getKey();
+            SchemaType schemaType = entry.getValue();
+
+            if (!key.isElement() && !key.isAnonymous()) {
+                QName typeQName = key.getQName();
+                Class clazz = loadClass(typeQName, mapping);
+
+                JaxRpcTypeInfo.SerializerType serializerType = JaxRpcTypeInfo.SerializerType.OTHER;
+                if (clazz.isArray()) {
+                    serializerType = JaxRpcTypeInfo.SerializerType.ARRAY;
+                }
+
+                JaxRpcTypeInfo typeInfo = new JaxRpcTypeInfo();
+                typeInfo.qname = typeQName;
+                typeInfo.javaType = clazz.getName();
+                typeInfo.serializerType = serializerType;
+                typeInfo.xmlType = typeQName;
+                typeInfo.canSearchParents = schemaType.getDerivationType() == SchemaType.DT_RESTRICTION;
+
+                mapFields(clazz, schemaType, typeInfo);
+
+                typeInfoList.add(typeInfo);
+            }
+        }
+
+        return typeInfoList;
+    }
+
+    private void mapFields(Class javaClass, SchemaType schemaType, JaxRpcTypeInfo typeInfo) throws OpenEJBException {
+        // Map type QName to declaration (including nested types)
+        Map<QName, SchemaParticle> paramNameToType = new HashMap<QName, SchemaParticle>();
+        if (schemaType.getContentModel() != null) {
+            int particleType = schemaType.getContentModel().getParticleType();
+            if (SchemaParticle.ELEMENT == particleType) {
+                SchemaParticle parameter = schemaType.getContentModel();
+                paramNameToType.put(parameter.getName(), parameter);
+            } else if (particleType == SchemaParticle.SEQUENCE || particleType == SchemaParticle.ALL) {
+                SchemaParticle[] properties = schemaType.getContentModel().getParticleChildren();
+                for (SchemaParticle parameter : properties) {
+                    paramNameToType.put(parameter.getName(), parameter);
+                }
+            } else  {
+                throw new OpenEJBException("Only all, choice and sequence particle types are supported." + " SchemaType name =" + schemaType.getName());
+            }
+        }
+
+        // Map JavaBean property name to propertyType
+        Map<String, Class> propertyToClass = new HashMap<String, Class>();
+        try {
+            for (PropertyDescriptor descriptor : Introspector.getBeanInfo(javaClass).getPropertyDescriptors()) {
+                propertyToClass.put(descriptor.getName(), descriptor.getPropertyType());
+            }
+        } catch (IntrospectionException e) {
+            throw new OpenEJBException("Class " + javaClass + " is not a valid javabean", e);
+        }
+
+        // Map the elements nexted in the XML Schema Type
+        for (Map.Entry<QName, SchemaParticle> entry : paramNameToType.entrySet()) {
+            QName fieldQName = entry.getKey();
+            SchemaParticle particle = entry.getValue();
+
+            String fieldName = fieldQName.getLocalPart();
+            Class javaType = propertyToClass.get(fieldName);
+            if (javaType == null) {
+                throw new OpenEJBException("Field " + fieldName + " is not defined by class " + javaClass.getName());
+            }
+
+            JaxRpcFieldInfo fieldInfo = new JaxRpcFieldInfo();
+            fieldInfo.name = fieldName;
+            fieldInfo.isNillable = particle.isNillable();
+            fieldInfo.xmlName = fieldQName;
+            fieldInfo.xmlType = particle.getType().getName();
+
+            if (javaType.isArray()) {
+                fieldInfo.minOccurs = particle.getIntMinOccurs();
+                fieldInfo.maxOccurs = particle.getIntMaxOccurs();
+                fieldInfo.maxOccursUnbounded = particle.getIntMaxOccurs() > 1;
+            }
+
+            typeInfo.fields.add(fieldInfo);
+        }
+    }
+
+    private Class loadClass(QName typeQName, JavaWsdlMapping mapping) throws OpenEJBException {
+        String namespace = typeQName.getNamespaceURI();
+
+        // package name comes from the package mapping
+        PackageMapping packageMapping = mapping.getPackageMappingMap().get(namespace);
+        if (packageMapping == null) {
+            throw new OpenEJBException("Namespace " + namespace + " was not mapped in jaxrpc mapping file");
+        }
+        String packageName = packageMapping.getPackageType();
+
+        // class name is package + type local part
+        String className = packageName + "." + typeQName.getLocalPart();
+
+        try {
+            Class clazz = Class.forName(className, false, classLoader);
+            return clazz;
+        } catch (ClassNotFoundException e) {
+            throw new OpenEJBException("Could not load java type " + className, e);
+        }
+    }
+}