001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.axis.builder;
018    
019    import java.beans.IntrospectionException;
020    import java.beans.Introspector;
021    import java.beans.PropertyDescriptor;
022    import java.util.ArrayList;
023    import java.util.HashMap;
024    import java.util.Iterator;
025    import java.util.List;
026    import java.util.Map;
027    import java.util.Set;
028    
029    import javax.xml.namespace.QName;
030    
031    import org.apache.axis.description.ElementDesc;
032    import org.apache.axis.description.FieldDesc;
033    import org.apache.axis.encoding.ser.ArrayDeserializerFactory;
034    import org.apache.axis.encoding.ser.ArraySerializerFactory;
035    import org.apache.axis.encoding.ser.BeanDeserializerFactory;
036    import org.apache.axis.encoding.ser.BeanSerializerFactory;
037    import org.apache.geronimo.axis.client.TypeInfo;
038    import org.apache.geronimo.common.DeploymentException;
039    import org.apache.geronimo.kernel.ClassLoading;
040    import org.apache.geronimo.xbeans.j2ee.JavaWsdlMappingType;
041    import org.apache.geronimo.webservices.builder.SchemaTypeKey;
042    import org.apache.geronimo.webservices.builder.WSDescriptorParser;
043    import org.apache.xmlbeans.SchemaParticle;
044    import org.apache.xmlbeans.SchemaType;
045    
046    /**
047     * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
048     */
049    public class LightweightTypeInfoBuilder implements TypeInfoBuilder {
050        private final ClassLoader cl;
051        private final Map schemaTypeKeyToSchemaTypeMap;
052        private final Set wrapperElementQNames;
053    
054        public LightweightTypeInfoBuilder(ClassLoader cl, Map schemaTypeKeyToSchemaTypeMap, Set wrapperElementQNames) {
055            this.cl = cl;
056            this.schemaTypeKeyToSchemaTypeMap = schemaTypeKeyToSchemaTypeMap;
057            this.wrapperElementQNames = wrapperElementQNames;
058        }
059    
060        public List buildTypeInfo(JavaWsdlMappingType mapping) throws DeploymentException {
061            List typeInfoList = new ArrayList();
062    
063            for (Iterator iterator = schemaTypeKeyToSchemaTypeMap.keySet().iterator(); iterator.hasNext();) {
064                SchemaTypeKey key = (SchemaTypeKey) iterator.next();
065                if (!key.isElement() && !key.isAnonymous()) {
066                    //default settings
067                    QName typeQName = key.getqName();
068                    String namespace = typeQName.getNamespaceURI();
069                    String packageName = WSDescriptorParser.getPackageFromNamespace(namespace, mapping);
070                    String classShortName = typeQName.getLocalPart();
071                    String className = packageName + "." + classShortName;
072    
073                    Class clazz = null;
074                    try {
075                        clazz = ClassLoading.loadClass(className, cl);
076                    } catch (ClassNotFoundException e) {
077                        throw new DeploymentException("Could not load java type", e);
078                    }
079    
080                    Class serializerFactoryClass = BeanSerializerFactory.class;
081                    Class deserializerFactoryClass = BeanDeserializerFactory.class;
082    
083                    if (clazz.isArray()) {
084                        serializerFactoryClass = ArraySerializerFactory.class;
085                        deserializerFactoryClass = ArrayDeserializerFactory.class;
086                    }
087    
088                    TypeInfo.UpdatableTypeInfo internalTypeInfo = new TypeInfo.UpdatableTypeInfo();
089                    internalTypeInfo.setClazz(clazz);
090                    internalTypeInfo.setQName(typeQName);
091                    internalTypeInfo.setSerializerClass(serializerFactoryClass);
092                    internalTypeInfo.setDeserializerClass(deserializerFactoryClass);
093    
094                    populateInternalTypeInfo(clazz, typeQName, key, internalTypeInfo);
095    
096                    typeInfoList.add(internalTypeInfo.buildTypeInfo());
097                }
098            }
099    
100            return typeInfoList;
101        }
102    
103        private void populateInternalTypeInfo(Class javaClass, QName typeQName, SchemaTypeKey key, TypeInfo.UpdatableTypeInfo typeInfo) throws DeploymentException {
104            SchemaType schemaType = (SchemaType) schemaTypeKeyToSchemaTypeMap.get(key);
105            if (schemaType == null) {
106                throw new DeploymentException("Schema type key " + key + " not found in analyzed schema: " + schemaTypeKeyToSchemaTypeMap);
107            }
108            typeInfo.setCanSearchParents(schemaType.getDerivationType() == SchemaType.DT_RESTRICTION);
109    
110            Map nameToType = new HashMap();
111            if (null  == schemaType.getContentModel()) {
112                ;
113            } else if (SchemaParticle.SEQUENCE == schemaType.getContentModel().getParticleType()
114                    || SchemaParticle.ALL == schemaType.getContentModel().getParticleType()) {
115                SchemaParticle[] properties = schemaType.getContentModel().getParticleChildren();
116                for (int i = 0; i < properties.length; i++) {
117                    SchemaParticle parameter = properties[i];
118    //                if (SchemaParticle.ELEMENT != parameter.getType().getContentModel().getParticleType()) {
119    //                    throw new DeploymentException(parameter.getName() + " is not an element in schema " + schemaType.getName());
120    //                }
121                    nameToType.put(parameter.getName(), parameter);
122                }
123            } else if (SchemaParticle.ELEMENT == schemaType.getContentModel().getParticleType()) {
124                SchemaParticle parameter = schemaType.getContentModel();
125                nameToType.put(parameter.getName(), parameter);
126            } else {
127                throw new DeploymentException("Only all, choice and sequence particle types are supported." +
128                        " SchemaType name =" + schemaType.getName());
129            }
130    
131            PropertyDescriptor[] descriptors;
132            try {
133                descriptors = Introspector.getBeanInfo(javaClass).getPropertyDescriptors();
134            } catch (IntrospectionException e) {
135                throw new DeploymentException("Class " + javaClass + " is not a valid javabean", e);
136            }
137            Map nameToClass = new HashMap();
138            for (int i = 0; i < descriptors.length; i++) {
139                nameToClass.put(descriptors[i].getName(), descriptors[i].getPropertyType());
140            }
141    
142            int idx = 0;
143            FieldDesc[] fields = new FieldDesc[nameToType.size()];
144            typeInfo.setFields(fields);
145            for (Iterator iter = nameToType.entrySet().iterator(); iter.hasNext();) {
146                Map.Entry entry = (Map.Entry) iter.next();
147                QName fieldQName = (QName) entry.getKey();
148                String fieldName = fieldQName.getLocalPart();
149                SchemaParticle particle = (SchemaParticle) entry.getValue();
150    
151                ElementDesc elementDesc = new ElementDesc();
152                elementDesc.setFieldName(fieldName);
153    
154                Class javaType = (Class) nameToClass.get(fieldName);
155                if (null == javaType) {
156                    throw new DeploymentException("Field " + fieldName + " is not defined by class " + javaClass.getName());
157                }
158                elementDesc.setNillable(particle.isNillable());
159                elementDesc.setXmlName(fieldQName);
160                elementDesc.setXmlType(particle.getType().getName());
161    
162                if (javaType.isArray()) {
163                    elementDesc.setMinOccurs(particle.getIntMinOccurs());
164                    elementDesc.setMaxOccurs(particle.getIntMaxOccurs());
165                    //TODO axis seems to have the wrong name for this property based on how it is used
166                    elementDesc.setMaxOccursUnbounded(particle.getIntMaxOccurs() > 1);
167                }
168    
169                fields[idx++] = elementDesc;
170            }
171        }
172    }