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 gd...@apache.org on 2005/09/08 04:39:30 UTC

svn commit: r279491 [2/2] - in /webservices/axis2/trunk/java: ./ modules/databinding/ modules/databinding/src/ modules/databinding/src/org/ modules/databinding/src/org/apache/ modules/databinding/src/org/apache/axis2/ modules/databinding/src/org/apache...

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/metadata/TypeDesc.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/metadata/TypeDesc.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/metadata/TypeDesc.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/metadata/TypeDesc.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,109 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.databinding.metadata;
+
+import org.apache.axis2.util.MethodCache;
+
+import javax.xml.namespace.QName;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.lang.reflect.Method;
+
+/**
+ * TypeDesc
+ */
+public class TypeDesc {
+    public static final Class [] noClasses = new Class [] {};
+    public static final Object[] noObjects = new Object[] {};
+
+    /** A map of class -> TypeDesc */
+    private static Map classMap = new Hashtable();
+
+    /**
+     * Static function for centralizing access to type metadata for a
+     * given class.
+     *
+     * This checks for a static getTypeDesc() method on the
+     * class or _Helper class.
+     * Eventually we may extend this to provide for external
+     * metadata config (via files sitting in the classpath, etc).
+     *
+     */
+    public static TypeDesc getTypeDescForClass(Class cls)
+    {
+        // First see if we have one explicitly registered
+        // or cached from previous lookup
+        TypeDesc result = (TypeDesc)classMap.get(cls);
+
+        if (result == null) {
+            try {
+                Method getTypeDesc =
+                    MethodCache.getInstance().getMethod(cls,
+                                                        "getTypeDesc",
+                                                        noClasses);
+                if (getTypeDesc != null) {
+                    result = (TypeDesc)getTypeDesc.invoke(null, noObjects);
+                    if (result != null) {
+                        classMap.put(cls, result);
+                    }
+                }
+            } catch (Exception e) {
+            }
+        }
+
+        return result;
+    }
+
+    Map elements = new HashMap();
+    Map fieldsByName = new HashMap();
+    Map attrs = new HashMap();
+    Class javaClass;
+
+    public Iterator getAttributeDescs() {
+        return attrs.values().iterator();
+    }
+
+    public void addField(ElementDesc fieldDesc) {
+        elements.put(fieldDesc.getQName(), fieldDesc);
+        fieldsByName.put(fieldDesc.getFieldName(), fieldDesc);
+    }
+
+    public void addField(AttributeDesc fieldDesc) {
+        attrs.put(fieldDesc.getQName(), fieldDesc);
+    }
+
+    public ElementDesc getElementDesc(QName qname) {
+        return (ElementDesc)elements.get(qname);
+    }
+
+    public ElementDesc getElementDesc(String fieldName) {
+        return (ElementDesc)fieldsByName.get(fieldName);
+    }
+
+    public Iterator getElementDescs() {
+        return elements.values().iterator();
+    }
+
+    public Class getJavaClass() {
+        return javaClass;
+    }
+
+    public void setJavaClass(Class javaClass) {
+        this.javaClass = javaClass;
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/AbstractSerializer.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/AbstractSerializer.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/AbstractSerializer.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/AbstractSerializer.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,31 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.databinding.serializers;
+
+import org.apache.axis2.databinding.Serializer;
+import org.apache.axis2.databinding.SerializationContext;
+
+/**
+ * AbstractSerializer
+ */
+public abstract class AbstractSerializer implements Serializer {
+    public void serialize(Object object, SerializationContext context)
+            throws Exception {
+        if (!context.checkMultiref(object, this)) {
+            serializeData(object, context);
+        }
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/BeanSerializer.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/BeanSerializer.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/BeanSerializer.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/BeanSerializer.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,51 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.databinding.serializers;
+
+import org.apache.axis2.databinding.SerializationContext;
+import org.apache.axis2.databinding.Serializer;
+import org.apache.axis2.databinding.metadata.ElementDesc;
+import org.apache.axis2.databinding.metadata.TypeDesc;
+
+import javax.xml.namespace.QName;
+import java.util.Iterator;
+
+/**
+ * BeanSerializer
+ */
+public class BeanSerializer extends AbstractSerializer {
+    TypeDesc typeDesc;
+
+    public BeanSerializer(TypeDesc typeDesc) {
+        this.typeDesc = typeDesc;
+    }
+
+    public void serializeData(Object object, SerializationContext context)
+            throws Exception {
+        // Write any attributes that need writing here
+
+        Iterator elements = typeDesc.getElementDescs();
+        while (elements.hasNext()) {
+            ElementDesc desc = (ElementDesc) elements.next();
+            Object fieldValue = desc.getValue(object);
+            Serializer ser = desc.getSerializer();
+            QName qname = desc.getQName();
+            context.serializeElement(qname, fieldValue, ser);
+        }
+
+        context.getWriter().writeEndElement();
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/CollectionSerializer.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/CollectionSerializer.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/CollectionSerializer.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/CollectionSerializer.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,94 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.databinding.serializers;
+
+import org.apache.axis2.databinding.Serializer;
+import org.apache.axis2.databinding.SerializationContext;
+import org.apache.axis2.databinding.utils.Converter;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamWriter;
+import java.lang.reflect.Array;
+import java.util.Collection;
+
+/**
+ * CollectionSerializer
+ */
+public class CollectionSerializer extends AbstractSerializer {
+    public final QName DEFAULT_ITEM_QNAME = new QName("item");
+
+    boolean isWrapped;
+    QName itemQName;
+    Serializer serializer;
+
+    public CollectionSerializer(QName itemQName,
+                                boolean isWrapped,
+                                Serializer serializer) {
+        this.isWrapped = isWrapped;
+        this.itemQName = itemQName == null ? DEFAULT_ITEM_QNAME : itemQName;
+        this.serializer = serializer;
+    }
+
+    public void serialize(Object object, SerializationContext context) throws Exception {
+        if (isWrapped) {
+            // We have a wrapper element, so it's fine to do multiref checking
+            // on the actual collection object
+            super.serialize(object, context);
+            return;
+        }
+
+        // No wrapper, so need to do multiref checks on individual elements.
+        serializeData(object, context);
+    }
+
+    public void serializeData(Object object, SerializationContext context)
+            throws Exception {
+        if (object instanceof Collection) {
+            Converter.convert(object, Object[].class);
+        }
+        XMLStreamWriter writer = context.getWriter();
+        if (isWrapped) {
+            writer.writeStartElement(itemQName.getNamespaceURI(),
+                                     itemQName.getLocalPart());
+        }
+
+        int len = Array.getLength(object);
+        for (int i = 0; i < len; i++) {
+            Object item = Array.get(object, i);
+            if (i == 0) {
+                if (isWrapped) {
+                    if (!context.checkMultiref(item, serializer)) {
+                        serializer.serializeData(item, context);
+                    }
+                } else {
+                    serializer.serializeData(item, context);
+                }
+            } else {
+                context.serializeElement(itemQName, item, serializer);
+            }
+        }
+
+//        Collection coll = (Collection)object;
+//        for (Iterator i = coll.iterator(); i.hasNext();) {
+//            Object item = i.next();
+//            context.serializeElement(itemQName, item, serializer);
+//        }
+
+        if (isWrapped) {
+            writer.writeEndElement();
+        }
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/SimpleSerializer.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/SimpleSerializer.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/SimpleSerializer.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/serializers/SimpleSerializer.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,73 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.databinding.serializers;
+
+import org.apache.axis2.databinding.SerializationContext;
+
+import javax.xml.namespace.QName;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
+/**
+ * SimpleSerializer
+ */
+public class SimpleSerializer extends AbstractSerializer {
+    private static SimpleDateFormat zulu =
+       new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+                         //  0123456789 0 123456789
+
+    static {
+        zulu.setTimeZone(TimeZone.getTimeZone("GMT"));
+    }
+
+    public void serialize(Object object, SerializationContext context) throws Exception {
+        // Simple types never get multiref'd, so just write the data now.
+        serializeData(object, context);
+    }
+
+    public void serializeData(Object object, SerializationContext context)
+            throws Exception {
+        String value = object.toString();
+        context.getWriter().writeCharacters(value);
+        context.getWriter().writeEndElement();
+    }
+
+    public String getValueAsString(Object value, SerializationContext context) {
+        // We could have separate serializers/deserializers to take
+        // care of Float/Double cases, but it makes more sence to
+        // put them here with the rest of the java lang primitives.
+        if (value instanceof Float ||
+            value instanceof Double) {
+            double data = 0.0;
+            if (value instanceof Float) {
+                data = ((Float) value).doubleValue();
+            } else {
+                data = ((Double) value).doubleValue();
+            }
+            if (Double.isNaN(data)) {
+                return "NaN";
+            } else if (data == Double.POSITIVE_INFINITY) {
+                return "INF";
+            } else if (data == Double.NEGATIVE_INFINITY) {
+                return "-INF";
+            }
+        } else if (value instanceof QName) {
+            return context.qName2String((QName)value);
+        }
+
+        return value.toString();
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/typemapping/TypeMappingRegistry.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/typemapping/TypeMappingRegistry.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/typemapping/TypeMappingRegistry.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/typemapping/TypeMappingRegistry.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,127 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.databinding.typemapping;
+
+import org.apache.axis2.databinding.metadata.BeanManager;
+import org.apache.axis2.databinding.DeserializerFactory;
+import org.apache.axis2.databinding.Serializer;
+import org.apache.axis2.databinding.metadata.BeanManager;
+import org.apache.axis2.databinding.deserializers.BeanDeserializerFactory;
+import org.apache.axis2.databinding.deserializers.SimpleDeserializerFactory;
+import org.apache.axis2.databinding.serializers.BeanSerializer;
+import org.apache.axis2.databinding.serializers.SimpleSerializer;
+import org.apache.axis.xsd.Constants;
+import org.w3c.dom.Element;
+
+import javax.xml.namespace.QName;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * TypeMappingRegistry
+ */
+public class TypeMappingRegistry {
+    public static boolean isPrimitive(Object value) {
+        if (value == null) return true;
+
+        Class javaType = (value instanceof Class) ? (Class)value :
+                value.getClass();
+
+        if (javaType.isPrimitive()) return true;
+
+        if (javaType == String.class) return true;
+        if (Calendar.class.isAssignableFrom(javaType)) return true;
+        if (Date.class.isAssignableFrom(javaType)) return true;
+//        if (HexBinary.class.isAssignableFrom(javaType)) return true;
+        if (Element.class.isAssignableFrom(javaType)) return true;
+        if (javaType == byte[].class) return true;
+        if (Number.class.isAssignableFrom(javaType)) return true;
+
+        // There has been discussion as to whether arrays themselves should
+        // be regarded as multi-ref.
+        // Here are the three options:
+        //   1) Arrays are full-fledged Objects and therefore should always be
+        //      multi-ref'd  (Pro: This is like java.  Con: Some runtimes don't
+        //      support this yet, and it requires more stuff to be passed over the wire.)
+        //   2) Arrays are not full-fledged Objects and therefore should
+        //      always be passed as single ref (note the elements of the array
+        //      may be multi-ref'd.) (Pro:  This seems reasonable, if a user
+        //      wants multi-referencing put the array in a container.  Also
+        //      is more interop compatible.  Con: Not like java serialization.)
+        //   3) Arrays of primitives should be single ref, and arrays of
+        //      non-primitives should be multi-ref.  (Pro: Takes care of the
+        //      looping case.  Con: Seems like an obtuse rule.)
+        //
+        // Changing the code from (1) to (2) to see if interop fairs better.
+        if (javaType.isArray()) return true;
+
+        return false;
+    }
+
+    public DeserializerFactory getDeserializerFactory(Class cls) {
+        if (isPrimitive(cls)) {
+            return new SimpleDeserializerFactory(cls, new QName("xsd", cls.getName()));
+        }
+
+        return new BeanDeserializerFactory(BeanManager.getTypeDesc(cls));
+    }
+
+    public Serializer getSerializer(Class cls) {
+        if (isPrimitive(cls)) {
+            return new SimpleSerializer();
+        }
+
+        return new BeanSerializer(BeanManager.getTypeDesc(cls));
+    }
+    
+    public void registerMapping(Class javaType,
+                                QName xmlType,
+                                Serializer serializer,
+                                DeserializerFactory deserFactory) {
+
+    }
+
+    public void initializeSchemaTypes() {
+        myRegisterSimple(Constants.XSD_STRING, java.lang.String.class);
+        myRegisterSimple(Constants.XSD_BOOLEAN, java.lang.Boolean.class);
+        myRegisterSimple(Constants.XSD_DOUBLE, java.lang.Double.class);
+        myRegisterSimple(Constants.XSD_FLOAT, java.lang.Float.class);
+        myRegisterSimple(Constants.XSD_INT, java.lang.Integer.class);
+        myRegisterSimple(Constants.XSD_INTEGER, java.math.BigInteger.class
+        );
+        myRegisterSimple(Constants.XSD_DECIMAL, java.math.BigDecimal.class
+        );
+        myRegisterSimple(Constants.XSD_LONG, java.lang.Long.class);
+        myRegisterSimple(Constants.XSD_SHORT, java.lang.Short.class);
+        myRegisterSimple(Constants.XSD_BYTE, java.lang.Byte.class);
+
+        // The XSD Primitives are mapped to java primitives.
+        myRegisterSimple(Constants.XSD_BOOLEAN, boolean.class);
+        myRegisterSimple(Constants.XSD_DOUBLE, double.class);
+        myRegisterSimple(Constants.XSD_FLOAT, float.class);
+        myRegisterSimple(Constants.XSD_INT, int.class);
+        myRegisterSimple(Constants.XSD_LONG, long.class);
+        myRegisterSimple(Constants.XSD_SHORT, short.class);
+        myRegisterSimple(Constants.XSD_BYTE, byte.class);
+    }
+
+    private void myRegisterSimple(QName xmlType, Class javaType) {
+        DeserializerFactory dser = new SimpleDeserializerFactory(javaType,
+                                                                 xmlType);
+        Serializer ser = new SimpleSerializer();
+        registerMapping(javaType, xmlType, ser, dser);
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/utils/Converter.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/utils/Converter.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/utils/Converter.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/databinding/utils/Converter.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,225 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.databinding.utils;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Converter
+ */
+public class Converter {
+    public static Object convert(Object arg, Class destClass)
+    {
+        if (destClass == null) {
+            return arg;
+        }
+
+        Class argHeldType = null;
+        if (arg != null) {
+            argHeldType = getHolderValueType(arg.getClass());
+        }
+
+        if (arg != null && argHeldType == null && destClass.isAssignableFrom(arg.getClass())) {
+            return arg;
+        }
+
+        // See if a previously converted value is stored in the argument.
+        Object destValue = null;
+
+        // Get the destination held type or the argument held type if they exist
+        Class destHeldType = getHolderValueType(destClass);
+
+        // Convert between Axis special purpose HexBinary and byte[]
+//        if (arg instanceof HexBinary &&
+//            destClass == byte[].class) {
+//            return ((HexBinary) arg).getBytes();
+//        } else if (arg instanceof byte[] &&
+//                   destClass == HexBinary.class) {
+//            return new HexBinary((byte[]) arg);
+//        }
+
+        // Convert between Calendar and Date
+        if (arg instanceof Calendar && destClass == Date.class) {
+            return ((Calendar) arg).getTime();
+        }
+        if (arg instanceof Date && destClass == Calendar.class) {
+        	Calendar calendar = Calendar.getInstance();
+        	calendar.setTime((Date) arg);
+            return calendar;
+        }
+
+        // Convert between Calendar and java.sql.Date
+        if (arg instanceof Calendar && destClass == java.sql.Date.class) {
+            return new java.sql.Date(((Calendar) arg).getTime().getTime());
+        }
+
+        // Convert between HashMap and Hashtable
+        if (arg instanceof HashMap && destClass == Hashtable.class) {
+            return new Hashtable((HashMap)arg);
+        }
+
+        // If the destination is an array and the source
+        // is a suitable component, return an array with
+        // the single item.
+        if (arg != null &&
+            destClass.isArray() &&
+            !destClass.getComponentType().equals(Object.class) &&
+            destClass.getComponentType().isAssignableFrom(arg.getClass())) {
+            Object array =
+                Array.newInstance(destClass.getComponentType(), 1);
+            Array.set(array, 0, arg);
+            return array;
+        }
+
+        // Return if no conversion is available
+        if (!(arg instanceof Collection ||
+              (arg != null && arg.getClass().isArray())) &&
+            ((destHeldType == null && argHeldType == null) ||
+             (destHeldType != null && argHeldType != null))) {
+            return arg;
+        }
+
+        // Take care of Holder conversion
+/*
+        if (destHeldType != null) {
+            // Convert arg into Holder holding arg.
+            Object newArg = convert(arg, destHeldType);
+            Object argHolder = null;
+            try {
+                argHolder = destClass.newInstance();
+                setHolderValue(argHolder, newArg);
+                return argHolder;
+            } catch (Exception e) {
+                return arg;
+            }
+        } else if (argHeldType != null) {
+            // Convert arg into the held type
+            try {
+                Object newArg = getHolderValue(arg);
+                return convert(newArg, destClass);
+            } catch (HolderException e) {
+                return arg;
+            }
+        }
+*/
+
+        // Flow to here indicates that neither arg or destClass is a Holder
+
+        if (arg == null) {
+            return arg;
+        }
+
+        // The arg may be an array or List
+        int length = 0;
+        if (arg.getClass().isArray()) {
+            length = Array.getLength(arg);
+        } else {
+            length = ((Collection) arg).size();
+        }
+        if (destClass.isArray()) {
+            if (destClass.getComponentType().isPrimitive()) {
+
+                Object array = Array.newInstance(destClass.getComponentType(),
+                                                 length);
+                // Assign array elements
+                if (arg.getClass().isArray()) {
+                    for (int i = 0; i < length; i++) {
+                        Array.set(array, i, Array.get(arg, i));
+                    }
+                } else {
+                    int idx = 0;
+                    for (Iterator i = ((Collection)arg).iterator();
+                            i.hasNext();) {
+                        Array.set(array, idx++, i.next());
+                    }
+                }
+                destValue = array;
+
+            } else {
+                Object [] array;
+                try {
+                    array = (Object [])Array.newInstance(destClass.getComponentType(),
+                                                         length);
+                } catch (Exception e) {
+                    return arg;
+                }
+
+                // Use convert to assign array elements.
+                if (arg.getClass().isArray()) {
+                    for (int i = 0; i < length; i++) {
+                        array[i] = convert(Array.get(arg, i),
+                                           destClass.getComponentType());
+                    }
+                } else {
+                    int idx = 0;
+                    for (Iterator i = ((Collection)arg).iterator();
+                            i.hasNext();) {
+                        array[idx++] = convert(i.next(),
+                                           destClass.getComponentType());
+                    }
+                }
+                destValue = array;
+            }
+        }
+        else if (Collection.class.isAssignableFrom(destClass)) {
+            Collection newList = null;
+            try {
+                // if we are trying to create an interface, build something
+                // that implements the interface
+                if (destClass == Collection.class || destClass == java.util.List.class) {
+                    newList = new ArrayList();
+                } else if (destClass == Set.class) {
+                    newList = new HashSet();
+                } else {
+                    newList = (Collection)destClass.newInstance();
+                }
+            } catch (Exception e) {
+                // Couldn't build one for some reason... so forget it.
+                return arg;
+            }
+
+            if (arg.getClass().isArray()) {
+                for (int j = 0; j < length; j++) {
+                    newList.add(Array.get(arg, j));
+                }
+            } else {
+                for (Iterator j = ((Collection)arg).iterator();
+                            j.hasNext();) {
+                    newList.add(j.next());
+                }
+            }
+            destValue = newList;
+        }
+        else {
+            destValue = arg;
+        }
+
+        return destValue;
+    }
+
+    private static Class getHolderValueType(Class aClass) {
+        return null;
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCInOutMessageReceiver.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCInOutMessageReceiver.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCInOutMessageReceiver.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCInOutMessageReceiver.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2004,2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.axis2.rpc;
+
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.context.OperationContext;
+import org.apache.axis2.databinding.DeserializationContext;
+import org.apache.axis2.databinding.Deserializer;
+import org.apache.axis2.om.OMAbstractFactory;
+import org.apache.axis2.om.OMElement;
+import org.apache.axis2.receivers.AbstractInOutSyncMessageReceiver;
+import org.apache.axis2.soap.SOAPBody;
+import org.apache.axis2.soap.SOAPEnvelope;
+import org.apache.axis2.soap.SOAPFactory;
+
+import javax.xml.namespace.QName;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ *
+ */
+public class RPCInOutMessageReceiver extends AbstractInOutSyncMessageReceiver {
+    public static final String RPCMETHOD_PROPERTY = "rpc.method";
+
+    public RPCInOutMessageReceiver() {
+    }
+
+    public void invokeBusinessLogic(MessageContext inMessage,
+                                    MessageContext outMessage) throws AxisFault {
+        SOAPEnvelope env = inMessage.getEnvelope();
+        SOAPBody body = env.getBody();
+        OMElement rpcElement = body.getFirstElement();
+
+        /**
+         * Locate method descriptor using QName or action
+         */
+        OperationContext oc = inMessage.getOperationContext();
+        RPCMethod method = (RPCMethod)oc.getProperty(RPCMETHOD_PROPERTY);
+        if (method == null) {
+            throw new AxisFault("Couldn't find RPCMethod in OperationContext");
+        }
+
+        Method javaMethod = method.getJavaMethod();
+        Object [] arguments = null;
+        Object targetObject = this.getTheImplementationObject(inMessage);
+        DeserializationContext dserContext = new DeserializationContext();
+
+        // Run each argument (sub-element) through the appropriate deser
+        Iterator args = rpcElement.getChildElements();
+        Map elementCounts = new HashMap();
+        while (args.hasNext()) {
+            OMElement arg = (OMElement) args.next();
+            QName qname = arg.getQName();
+            RPCParameter param = method.getParameter(qname);
+            if (param == null) {
+                // unknown parameter.  Fault or continue depending on
+                // strictness configuration.
+                continue;
+            }
+            Integer count = (Integer)elementCounts.get(qname);
+            if (count == null) count = new Integer(0);
+            elementCounts.put(qname, new Integer(count.intValue() + 1));
+            Deserializer dser = param.getDeserializer(count.intValue());
+            // Got a recognized param, so feed this through the deserializer
+            try {
+                dserContext.deserialize(arg.getXMLStreamReader(), dser);
+            } catch (Exception e) {
+                throw AxisFault.makeFault(e);
+            }
+        }
+
+        // OK, now we're done with the children.  If this is SOAP 1.2, we're
+        // finished.  If it's SOAP 1.1, there may be multirefs which still
+        // need to be deserialized after the RPC element.
+        if (dserContext.isIncomplete()) {
+            try {
+                dserContext.processRest(rpcElement);
+            } catch (Exception e) {
+                throw AxisFault.makeFault(e);
+            }
+
+            if (dserContext.isIncomplete()) {
+                throw new AxisFault("Unresolved multirefs!");
+            }
+        }
+
+        arguments = new Object [method.getNumInParams()];
+        Iterator params = method.getInParams();
+        for (int i = 0; i < arguments.length; i++) {
+            arguments[i] = ((RPCParameter)params.next()).getValue();
+        }
+
+        Object returnValue = null;
+        try {
+            returnValue = javaMethod.invoke(targetObject, arguments);
+        } catch (Exception e) {
+            throw AxisFault.makeFault(e);
+        }
+
+        // The response parameter, if any, is where the return value should go
+        RPCParameter responseParam = method.getResponseParameter();
+        if (responseParam != null) {
+            responseParam.setValue(returnValue);
+        }
+
+        // Now make the response message.
+        try {
+            SOAPFactory factory = OMAbstractFactory.getSOAP11Factory();
+            SOAPEnvelope responseEnv = factory.createSOAPEnvelope();
+            SOAPBody respBody = factory.createSOAPBody(responseEnv);
+
+            // Just need to create this, since it automatically links itself
+            // to the response body and will therefore get serialize()d at
+            // the appropriate time.
+            new RPCResponseElement(method, respBody);
+
+            outMessage.setEnvelope(responseEnv);
+        } catch (Exception e) {
+            throw AxisFault.makeFault(e);
+        }
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCMethod.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCMethod.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCMethod.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCMethod.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,148 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.rpc;
+
+import org.apache.axis2.soap.SOAPEnvelope;
+import org.apache.axis2.soap.SOAPFactory;
+import org.apache.axis2.soap.SOAPBody;
+import org.apache.axis2.om.OMAbstractFactory;
+import org.apache.axis2.om.OMElement;
+
+import javax.xml.namespace.QName;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * RPCMethod
+ */
+public class RPCMethod {
+    static class Outerator implements Iterator {
+        ArrayList params;
+        RPCParameter cache = null;
+        int badMode;
+        int idx = 0;
+
+        public Outerator(ArrayList params, int badMode) {
+            this.params = params;
+            this.badMode = badMode;
+        }
+
+        public void remove() {
+
+        }
+
+        public boolean hasNext() {
+            if (cache != null) return true;
+            while (idx < params.size()) {
+                RPCParameter param = (RPCParameter)params.get(idx);
+                idx++;
+                if (param.mode != badMode) {
+                    cache = param;
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public Object next() {
+            RPCParameter ret = null;
+            if (hasNext()) {
+                ret = cache;
+                cache = null;
+            }
+            return ret;
+        }
+    }
+
+    int numInParams, numOutParams;
+    Map parameters = new HashMap();
+    ArrayList orderedParameters = new ArrayList();
+    Method javaMethod;
+
+    QName qname;
+    QName responseQName;
+
+    public RPCMethod(QName qname) {
+        this.qname = qname;
+    }
+
+    public ArrayList getParams() {
+        return orderedParameters;
+    }
+
+    public void addParameter(RPCParameter param) {
+        orderedParameters.add(param);
+        parameters.put(param.getQName(), param);
+        if (param.getMode() != RPCParameter.MODE_OUT) {
+            numInParams++;
+        }
+        if (param.getMode() != RPCParameter.MODE_IN) {
+            numOutParams++;
+        }
+    }
+
+    public RPCParameter getParameter(QName qname) {
+        return (RPCParameter)parameters.get(qname);
+    }
+
+    public Method getJavaMethod() {
+        return javaMethod;
+    }
+
+    public void setJavaMethod(Method javaMethod) {
+        this.javaMethod = javaMethod;
+    }
+
+    public QName getResponseQName() {
+        return responseQName;
+    }
+
+    public void setResponseQName(QName responseQName) {
+        this.responseQName = responseQName;
+    }
+
+    public QName getQName() {
+        return qname;
+    }
+
+    public RPCParameter getResponseParameter() {
+        for (Iterator i = orderedParameters.iterator(); i.hasNext();) {
+            RPCParameter parameter = (RPCParameter) i.next();
+            if (parameter.getMode() == RPCParameter.MODE_OUT)
+                return parameter;
+        }
+        return null;
+    }
+
+    public Iterator getOutParams() {
+        return new Outerator(orderedParameters, RPCParameter.MODE_IN);
+    }
+
+    public Iterator getInParams() {
+        return new Outerator(orderedParameters, RPCParameter.MODE_OUT);
+    }
+
+    public int getNumInParams() {
+        return numInParams;
+    }
+
+    public int getNumOutParams() {
+        return numOutParams;
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCParameter.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCParameter.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCParameter.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCParameter.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,130 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.rpc;
+
+import org.apache.axis2.databinding.DeserializationTarget;
+import org.apache.axis2.databinding.Deserializer;
+import org.apache.axis2.databinding.SerializationContext;
+import org.apache.axis2.databinding.utils.Converter;
+import org.apache.axis2.databinding.metadata.ElementDesc;
+
+import java.util.ArrayList;
+
+/**
+ * RPCParameter
+ */
+public class RPCParameter extends ElementDesc {
+    class ParamTarget implements DeserializationTarget {
+        RPCParameter param;
+
+        public ParamTarget(RPCParameter param) {
+            this.param = param;
+        }
+
+        public void setValue(Object value) throws Exception {
+            param.setValue(value);
+        }
+    }
+
+    class IndexedParamTarget implements DeserializationTarget {
+        RPCParameter param;
+        int index;
+
+        public IndexedParamTarget(RPCParameter param, int index) {
+            this.param = param;
+            this.index = index;
+        }
+
+        public void setValue(Object value) throws Exception {
+            param.setIndexedValue(index, value);
+        }
+    }
+
+    public static final int MODE_IN    = 0;
+    public static final int MODE_OUT   = 1;
+    public static final int MODE_INOUT = 2;
+
+    Object value;
+    int mode;
+    Class destClass;
+
+    public Object getValue() {
+        if (destClass != null)
+            return Converter.convert(value, destClass);
+
+        return value;
+    }
+
+    public void setValue(Object value) {
+        this.value = value;
+    }
+
+    public int getMode() {
+        return mode;
+    }
+
+    public void setMode(int mode) {
+        this.mode = mode;
+    }
+
+    public Class getDestClass() {
+        return destClass;
+    }
+
+    public void setDestClass(Class destClass) {
+        this.destClass = destClass;
+    }
+
+    public void serialize(SerializationContext context) throws Exception {
+        if (ser == null) {
+            // no serializer!
+            throw new Exception("No serializer in RPCParameter");
+        }
+        context.serializeElement(qname, value, ser);
+    }
+
+    public Deserializer getDeserializer(int i) {
+        if (i > maxOccurs && maxOccurs > -1) {
+            // fail
+            throw new RuntimeException("Too many elements");
+        }
+
+        DeserializationTarget target;
+        if (maxOccurs == -1 || maxOccurs > 1) {
+            if (value == null) value = new ArrayList();
+            target = new IndexedParamTarget(this, i);
+        } else {
+            target = new ParamTarget(this);
+        }
+
+        Deserializer dser = deserializerFactory.getDeserializer();
+        dser.setTarget(target);
+        return dser;
+    }
+
+    public void setIndexedValue(int index, Object value) {
+        ArrayList coll = (ArrayList)this.value;
+        if (coll.size() == index) {
+            coll.add(value);
+            return;
+        }
+
+        while (index + 1 > coll.size()) {
+            coll.add(null);
+        }
+        coll.set(index, value);
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCRequestElement.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCRequestElement.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCRequestElement.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCRequestElement.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,67 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.rpc;
+
+import org.apache.axis2.databinding.SerializationContext;
+import org.apache.axis2.om.OMElement;
+import org.apache.axis2.om.impl.OMOutputImpl;
+import org.apache.axis2.om.impl.llom.OMElementImpl;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.util.Iterator;
+
+/**
+ * RPCResponseElement
+ */
+public class RPCRequestElement extends OMElementImpl {
+    RPCMethod method;
+
+    public RPCRequestElement(RPCMethod method, OMElement parent) {
+        super(method.getQName(), parent);
+        this.method = method;
+    }
+
+    protected void serialize(OMOutputImpl omOutput, boolean cache)
+            throws XMLStreamException {
+        XMLStreamWriter writer = omOutput.getXmlStreamWriter();
+        SerializationContext context = new SerializationContext(writer);
+
+        // Write wrapper element
+        if (ns == null) {
+            writer.writeStartElement(localName);
+        } else {
+            writer.writeStartElement(localName, ns.getName(), ns.getPrefix());
+        }
+        Iterator inParams = method.getInParams();
+        while (inParams.hasNext()) {
+            RPCParameter parameter = (RPCParameter) inParams.next();
+            try {
+                parameter.serialize(context);
+            } catch (Exception e) {
+                throw new XMLStreamException("Couldn't serialize RPCParameter",
+                                             e);
+            }
+        }
+        writer.writeEndElement();
+
+        try {
+            context.finish();
+        } catch (Exception e) {
+            throw new XMLStreamException(e);
+        }
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCResponseElement.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCResponseElement.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCResponseElement.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/rpc/RPCResponseElement.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,67 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.rpc;
+
+import org.apache.axis2.databinding.SerializationContext;
+import org.apache.axis2.om.OMElement;
+import org.apache.axis2.om.impl.OMOutputImpl;
+import org.apache.axis2.om.impl.llom.OMElementImpl;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.util.Iterator;
+
+/**
+ * RPCResponseElement
+ */
+public class RPCResponseElement extends OMElementImpl {
+    RPCMethod method;
+
+    public RPCResponseElement(RPCMethod method, OMElement parent) {
+        super(method.getResponseQName(), parent);
+        this.method = method;
+    }
+
+    protected void serialize(OMOutputImpl omOutput, boolean cache)
+            throws XMLStreamException {
+        XMLStreamWriter writer = omOutput.getXmlStreamWriter();
+        SerializationContext context = new SerializationContext(writer);
+
+        // Write wrapper element
+        if (ns == null) {
+            writer.writeStartElement(localName);
+        } else {
+            writer.writeStartElement(localName, ns.getName(), ns.getPrefix());
+        }
+        Iterator outParams = method.getOutParams();
+        while (outParams.hasNext()) {
+            RPCParameter parameter = (RPCParameter) outParams.next();
+            try {
+                parameter.serialize(context);
+            } catch (Exception e) {
+                throw new XMLStreamException("Couldn't serialize RPCParameter",
+                                             e);
+            }
+        }
+        writer.writeEndElement();
+
+        try {
+            context.finish();
+        } catch (Exception e) {
+            throw new XMLStreamException(e);
+        }
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/util/MethodCache.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/util/MethodCache.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/util/MethodCache.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/src/org/apache/axis2/util/MethodCache.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+package org.apache.axis2.util;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A cache for methods.
+ * Used to get methods by their signature and stores them in a local
+ * cache for performance reasons.
+ * This class is a singleton - so use getInstance to get an instance of it.
+ *
+ * @author Davanum Srinivas <di...@yahoo.com>
+ * @author Sebastian Dietrich <se...@anecon.com>
+ */
+public class MethodCache {
+    /**
+     * The only instance of this class
+     */
+    transient private static MethodCache instance;
+
+    /**
+     * Cache for Methods
+     * In fact this is a map (with classes as keys) of a map (with method-names as keys)
+     */
+    transient private static ThreadLocal cache;
+
+    /**
+     * The <i>private</i> constructor for this class.
+     * Use getInstance to get an instance (the only one).
+     */
+    private MethodCache() {
+        cache = new ThreadLocal();
+    }
+
+    /**
+     * Gets the only instance of this class
+     * @return the only instance of this class
+     */
+    public static MethodCache getInstance() {
+        if (instance == null) {
+            instance = new MethodCache();
+        }
+        return instance;
+    }
+
+    /**
+     * Returns the per thread hashmap (for method caching)
+     */
+    private Map getMethodCache() {
+        Map map = (Map) cache.get();
+        if (map == null) {
+            map = new HashMap();
+            cache.set(map);
+        }
+        return map;
+    }
+
+    /**
+     * Class used as the key for the method cache table.
+     *
+     */
+    static class MethodKey {
+        /** the name of the method in the cache */
+        private final String methodName;
+        /** the list of types accepted by the method as arguments */
+        private final Class[] parameterTypes;
+
+        /**
+         * Creates a new <code>MethodKey</code> instance.
+         *
+         * @param methodName a <code>String</code> value
+         * @param parameterTypes a <code>Class[]</code> value
+         */
+        MethodKey(String methodName, Class[] parameterTypes) {
+            this.methodName = methodName;
+            this.parameterTypes = parameterTypes;
+        }
+
+        public boolean equals(Object other) {
+            MethodKey that = (MethodKey) other;
+            return this.methodName.equals(that.methodName)
+                && Arrays.equals(this.parameterTypes,
+                                 that.parameterTypes);
+        }
+
+        public int hashCode() {
+            // allow overloaded methods to collide; we'll sort it out
+            // in equals().  Note that String's implementation of
+            // hashCode already caches its value, so there's no point
+            // in doing so here.
+            return methodName.hashCode();
+        }
+    }
+
+    /** used to track methods we've sought but not found in the past */
+    private static final Object NULL_OBJECT = new Object();
+
+    /**
+     * Returns the specified method - if any.
+     *
+     * @param clazz the class to get the method from
+     * @param methodName the name of the method
+     * @param parameterTypes the parameters of the method
+     * @return the found method
+     *
+     * @throws NoSuchMethodException if the method can't be found
+     */
+    public Method getMethod(Class clazz,
+                            String methodName,
+                            Class[] parameterTypes)
+        throws NoSuchMethodException {
+        String className = clazz.getName();
+        Map cache = getMethodCache();
+        Method method = null;
+        Map methods = null;
+
+        // Strategy is as follows:
+        // construct a MethodKey to represent the name/arguments
+        // of a method's signature.
+        //
+        // use the name of the class to retrieve a map of that
+        // class' methods
+        //
+        // if a map exists, use the MethodKey to find the
+        // associated value object.  if that object is a Method
+        // instance, return it.  if that object is anything
+        // else, then it's a reference to our NULL_OBJECT
+        // instance, indicating that we've previously tried
+        // and failed to find a method meeting our requirements,
+        // so return null
+        //
+        // if the map of methods for the class doesn't exist,
+        // or if no value is associated with our key in that map,
+        // then we perform a reflection-based search for the method.
+        //
+        // if we find a method in that search, we store it in the
+        // map using the key; otherwise, we store a reference
+        // to NULL_OBJECT using the key.
+
+        // Check the cache first.
+        MethodKey key = new MethodKey(methodName, parameterTypes);
+        methods = (Map) cache.get(clazz);
+        if (methods != null) {
+            Object o = methods.get(key);
+            if (o != null) {  // cache hit
+                if (o instanceof Method) { // good cache hit
+                    return (Method) o;
+                } else {                   // bad cache hit
+                    // we hit the NULL_OBJECT, so this is a search
+                    // that previously failed; no point in doing
+                    // it again as it is a worst case search
+                    // through the entire classpath.
+                    return null;
+                }
+            } else {
+                // cache miss: fall through to reflective search
+            }
+        } else {
+            // cache miss: fall through to reflective search
+        }
+
+        try {
+            method = clazz.getMethod(methodName, parameterTypes);
+        } catch (NoSuchMethodException e1) {
+            if (!clazz.isPrimitive() && !className.startsWith("java.") && !className.startsWith("javax.")) {
+                try {
+                    Class helper = Class.forName(className + "_Helper");
+                    method = helper.getMethod(methodName, parameterTypes);
+                } catch (ClassNotFoundException e2) {
+                }
+            }
+        }
+
+        // first time we've seen this class: set up its method cache
+        if (methods == null) {
+            methods = new HashMap();
+            cache.put(clazz, methods);
+        }
+
+        // when no method is found, cache the NULL_OBJECT
+        // so that we don't have to repeat worst-case searches
+        // every time.
+
+        if (null == method) {
+            methods.put(key, NULL_OBJECT);
+        } else {
+            methods.put(key, method);
+        }
+        return method;
+    }
+}

Added: webservices/axis2/trunk/java/modules/databinding/test-resources/xmls/array1.xml
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/test-resources/xmls/array1.xml?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/test-resources/xmls/array1.xml (added)
+++ webservices/axis2/trunk/java/modules/databinding/test-resources/xmls/array1.xml Wed Sep  7 19:39:15 2005
@@ -0,0 +1,5 @@
+<wrapper>
+    <item>one</item>
+    <item>two</item>
+    <item>three</item>
+</wrapper>
\ No newline at end of file

Added: webservices/axis2/trunk/java/modules/databinding/test/org/apache/axis2/databinding/ArrayTest.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/databinding/test/org/apache/axis2/databinding/ArrayTest.java?rev=279491&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/databinding/test/org/apache/axis2/databinding/ArrayTest.java (added)
+++ webservices/axis2/trunk/java/modules/databinding/test/org/apache/axis2/databinding/ArrayTest.java Wed Sep  7 19:39:15 2005
@@ -0,0 +1,104 @@
+/*
+* Copyright 2004,2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.axis2.databinding;
+
+import junit.framework.TestCase;
+import org.apache.axis2.databinding.deserializers.BeanDeserializer;
+import org.apache.axis2.databinding.metadata.BeanManager;
+import org.apache.axis2.databinding.metadata.ElementDesc;
+import org.apache.axis2.databinding.metadata.TypeDesc;
+import org.apache.axis2.om.OMAbstractFactory;
+import org.apache.axis2.om.OMElement;
+import org.apache.axis2.om.impl.llom.builder.StAXOMBuilder;
+import org.apache.axis2.om.impl.llom.factory.OMXMLBuilderFactory;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+/**
+ * ArrayTest
+ */
+public class ArrayTest extends TestCase {
+    public static class TestBean {
+        static TypeDesc typeDesc;
+
+        public static TypeDesc getTypeDesc() {
+            if (typeDesc == null) {
+                typeDesc = new TypeDesc();
+                typeDesc.setJavaClass(ArrayTest.class);
+                ElementDesc desc = new ElementDesc();
+                desc.setFieldName("collection");
+                desc.setQName(new QName("item"));
+                desc.setMaxOccurs(-1);
+                typeDesc.addField(desc);
+            }
+            return typeDesc;
+        }
+
+        ArrayList coll;
+
+        public TestBean() {
+            coll = new ArrayList();
+        }
+
+        public String [] getCollection() {
+            return (String[])(coll.toArray(new String [coll.size()]));
+        }
+
+        public void setCollection(int index, String val) {
+            if (index + 1 > coll.size()) {
+               while (index + 1 > coll.size()) {
+                   coll.add(null);
+               }
+            }
+            coll.set(index, val);
+        }
+
+        public String getCollection(int index) {
+            return (String)coll.get(index);
+        }
+    }
+
+    public void testArray() throws Exception {
+        InputStream is = new FileInputStream("test-resources/xmls/array1.xml");
+        XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(is);
+
+        StAXOMBuilder builder = OMXMLBuilderFactory.createStAXOMBuilder(OMAbstractFactory.getOMFactory(), reader);
+        OMElement el = builder.getDocumentElement();
+        XMLStreamReader omReader = el.getXMLStreamReaderWithoutCaching();
+        omReader.next();
+        DeserializationContext context = new DeserializationContext();
+
+        TypeDesc typeDesc = BeanManager.getTypeDesc(TestBean.class);
+        BeanDeserializer dser = new BeanDeserializer(typeDesc);
+
+        dser.setTarget(new DeserializationTarget() {
+            public void setValue(Object value) {
+                assertTrue(value instanceof TestBean);
+                TestBean bean = (TestBean)value;
+                assertEquals("Wrong # of items", 3, bean.coll.size());
+                assertEquals("one", bean.getCollection(0));
+                assertEquals("two", bean.getCollection(1));
+                assertEquals("three", bean.getCollection(2));
+            }
+        });
+        dser.deserialize(omReader, context);
+    }
+}

Modified: webservices/axis2/trunk/java/modules/wsdl/project.properties
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/wsdl/project.properties?rev=279491&r1=279490&r2=279491&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/wsdl/project.properties (original)
+++ webservices/axis2/trunk/java/modules/wsdl/project.properties Wed Sep  7 19:39:15 2005
@@ -14,6 +14,5 @@
 # limitations under the License.
 # -------------------------------------------------------------------
 
-maven.repo.remote=http://cvs.apache.org/repository/,http://www.apache.org/dist/java-repository,http://www.ibiblio.org/maven,http://www.apache.org/dist/java-repository/,http://people.apache.org/~dims/maven/
+maven.repo.remote=http://cvs.apache.org/repository/,http://www.apache.org/dist/java-repository,http://www.ibiblio.org/maven,http://www.apache.org/dist/java-repository/,http://people.apache.org/~gdaniels/maven/
 maven.multiproject.type=jar
-maven.jar.XmlSchema=${basedir}/lib/XmlSchema.jar
\ No newline at end of file

Modified: webservices/axis2/trunk/java/modules/wsdl/project.xml
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/wsdl/project.xml?rev=279491&r1=279490&r2=279491&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/wsdl/project.xml (original)
+++ webservices/axis2/trunk/java/modules/wsdl/project.xml Wed Sep  7 19:39:15 2005
@@ -37,7 +37,7 @@
 		<dependency>
 			<groupId>axis</groupId>
 			<artifactId>XmlSchema</artifactId>
-			<version>0.9</version>
+			<version>SNAPSHOT</version>
 		</dependency>
 		<!-- external JARs -->
 		<dependency>

Modified: webservices/axis2/trunk/java/modules/xml/src/org/apache/axis2/om/impl/OMOutputImpl.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/xml/src/org/apache/axis2/om/impl/OMOutputImpl.java?rev=279491&r1=279490&r2=279491&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/xml/src/org/apache/axis2/om/impl/OMOutputImpl.java (original)
+++ webservices/axis2/trunk/java/modules/xml/src/org/apache/axis2/om/impl/OMOutputImpl.java Wed Sep  7 19:39:15 2005
@@ -84,18 +84,16 @@
         if (charSetEncoding == null) //Default encoding is UTF-8
             this.charSetEncoding = DEFAULT_CHAR_SET_ENCODING;
 
+        XMLOutputFactory factory = XMLOutputFactory.newInstance();
+//        factory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.TRUE);
         if (doOptimize) {
             bufferedSoapOutStream = new ByteArrayOutputStream();
-            xmlWriter =
-                XMLOutputFactory.newInstance().createXMLStreamWriter(
-                    bufferedSoapOutStream,
-                    this.charSetEncoding);
+            xmlWriter = factory.createXMLStreamWriter(bufferedSoapOutStream,
+                                                      this.charSetEncoding);
             binaryNodeList = new LinkedList();
         } else {
-            xmlWriter =
-                XMLOutputFactory.newInstance().createXMLStreamWriter(
-                    outStream,
-                    this.charSetEncoding);
+            xmlWriter = factory.createXMLStreamWriter(outStream,
+                                                      this.charSetEncoding);
         }
     }
 

Modified: webservices/axis2/trunk/java/project.properties
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/project.properties?rev=279491&r1=279490&r2=279491&view=diff
==============================================================================
--- webservices/axis2/trunk/java/project.properties (original)
+++ webservices/axis2/trunk/java/project.properties Wed Sep  7 19:39:15 2005
@@ -19,6 +19,7 @@
 maven.multiproject.includes=\
 modules/common/project.xml,\
 modules/xml/project.xml,\
+modules/databinding/project.xml,\
 modules/wsdl/project.xml,\
 modules/core/project.xml,\
 modules/addressing/project.xml,\