View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  package org.apache.geronimo.axis.builder;
19  
20  import java.io.ByteArrayOutputStream;
21  import java.io.IOException;
22  import java.lang.reflect.Method;
23  import java.net.URI;
24  import java.net.URISyntaxException;
25  import java.util.ArrayList;
26  import java.util.Collection;
27  import java.util.HashMap;
28  import java.util.HashSet;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Set;
33  import javax.wsdl.Binding;
34  import javax.wsdl.BindingInput;
35  import javax.wsdl.BindingOperation;
36  import javax.wsdl.Port;
37  import javax.wsdl.extensions.soap.SOAPAddress;
38  import javax.wsdl.extensions.soap.SOAPBinding;
39  import javax.wsdl.extensions.soap.SOAPBody;
40  import javax.xml.namespace.QName;
41  
42  import org.apache.axis.constants.Style;
43  import org.apache.axis.constants.Use;
44  import org.apache.axis.description.JavaServiceDesc;
45  import org.apache.axis.description.OperationDesc;
46  import org.apache.axis.encoding.TypeMapping;
47  import org.apache.axis.encoding.TypeMappingRegistryImpl;
48  import org.apache.geronimo.axis.client.TypeInfo;
49  import org.apache.geronimo.axis.server.ReadOnlyServiceDesc;
50  import org.apache.geronimo.axis.server.ServiceInfo;
51  import org.apache.geronimo.common.DeploymentException;
52  import org.apache.geronimo.xbeans.j2ee.JavaXmlTypeMappingType;
53  import org.apache.geronimo.xbeans.j2ee.ServiceEndpointMethodMappingType;
54  import org.apache.geronimo.xbeans.wsdl.DefinitionsDocument;
55  import org.apache.geronimo.xbeans.wsdl.TDefinitions;
56  import org.apache.geronimo.xbeans.wsdl.TImport;
57  import org.apache.geronimo.xbeans.wsdl.TTypes;
58  import org.apache.geronimo.webservices.builder.PortInfo;
59  import org.apache.geronimo.webservices.builder.SchemaInfoBuilder;
60  import org.apache.geronimo.webservices.builder.WSDescriptorParser;
61  import org.apache.xmlbeans.XmlCursor;
62  import org.apache.xmlbeans.XmlObject;
63  import org.apache.xmlbeans.impl.xb.xsdschema.ImportDocument;
64  import org.apache.xmlbeans.impl.xb.xsdschema.IncludeDocument;
65  import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
66  
67  /**
68   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
69   */
70  public class AxisServiceBuilder {
71  
72      public static final String XSD_NS = "http://www.w3.org/2001/XMLSchema";
73      public static final QName SCHEMA_QNAME = new QName(XSD_NS, "schema");
74  
75  
76      public static ServiceInfo createServiceInfo(PortInfo portInfo, ClassLoader classLoader) throws DeploymentException {
77          JavaServiceDesc serviceDesc = createServiceDesc(portInfo, classLoader);
78          List handlerInfos = WSDescriptorParser.createHandlerInfoList(portInfo.getHandlers(), classLoader);
79          SchemaInfoBuilder schemaInfoBuilder = portInfo.getSchemaInfoBuilder();
80          Map rawWsdlMap = schemaInfoBuilder.getWsdlMap();
81          Map wsdlMap = rewriteWsdlMap(portInfo, rawWsdlMap);
82          return new ServiceInfo(serviceDesc, handlerInfos, wsdlMap);
83      }
84  
85      public static JavaServiceDesc createServiceDesc(PortInfo portInfo, ClassLoader classLoader) throws DeploymentException {
86  
87          Port port = portInfo.getPort();
88  
89          Class serviceEndpointInterface = null;
90          try {
91              serviceEndpointInterface = classLoader.loadClass(portInfo.getServiceEndpointInterfaceName());
92          } catch (ClassNotFoundException e) {
93              throw (DeploymentException) new DeploymentException("Unable to load the service-endpoint interface for port-component " + portInfo.getPortComponentName()).initCause(e);
94          }
95  
96          Map exceptionMap = WSDescriptorParser.getExceptionMap(portInfo.getJavaWsdlMapping());
97          SchemaInfoBuilder schemaInfoBuilder = portInfo.getSchemaInfoBuilder();
98          Map schemaTypeKeyToSchemaTypeMap = schemaInfoBuilder.getSchemaTypeKeyToSchemaTypeMap();
99  
100         JavaServiceDesc serviceDesc = new JavaServiceDesc();
101         String serviceName =  portInfo.getPortQName().toString();
102         String location = getAddressLocation(port);
103         serviceDesc.setName(serviceName);
104         serviceDesc.setEndpointURL(location);
105         serviceDesc.setWSDLFile(portInfo.getWsdlLocation());
106         Binding binding = port.getBinding();
107 
108         serviceDesc.setStyle(getStyle(binding));
109 
110 
111         BindingInput bindingInput = ((BindingOperation) binding.getBindingOperations().get(0)).getBindingInput();
112         SOAPBody soapBody = (SOAPBody) SchemaInfoBuilder.getExtensibilityElement(SOAPBody.class, bindingInput.getExtensibilityElements());
113 
114         if (soapBody.getUse() != null) {
115             Use use = Use.getUse(soapBody.getUse());
116             serviceDesc.setUse(use);
117         } else {
118             serviceDesc.setUse(Use.ENCODED);
119         }
120         boolean hasEncoded = serviceDesc.getUse() == Use.ENCODED;
121 
122         boolean isLightweight = portInfo.getServiceEndpointInterfaceMapping() == null;
123 
124 //        if (isLightweight) {
125 //            validateLightweightMapping(portInfo.getDefinition());
126 //        }
127 
128         Collection operations = new ArrayList();
129         Set wrapperElementQNames = buildOperations(binding, serviceEndpointInterface, isLightweight, portInfo, exceptionMap, classLoader, operations);
130         for (Iterator iter = operations.iterator(); iter.hasNext();) {
131             OperationDesc operation = (OperationDesc) iter.next();
132             serviceDesc.addOperationDesc(operation);
133         }
134 
135         TypeMappingRegistryImpl tmr = new TypeMappingRegistryImpl();
136         tmr.doRegisterFromVersion("1.3");
137 
138         TypeMapping typeMapping = tmr.getOrMakeTypeMapping(serviceDesc.getUse().getEncoding());
139 
140         serviceDesc.setTypeMappingRegistry(tmr);
141         serviceDesc.setTypeMapping(typeMapping);
142 
143         List typeInfo;
144         if (isLightweight) {
145             LightweightTypeInfoBuilder builder = new LightweightTypeInfoBuilder(classLoader, schemaTypeKeyToSchemaTypeMap, wrapperElementQNames);
146             typeInfo = builder.buildTypeInfo(portInfo.getJavaWsdlMapping());
147         } else {
148             HeavyweightTypeInfoBuilder builder = new HeavyweightTypeInfoBuilder(classLoader, schemaTypeKeyToSchemaTypeMap, wrapperElementQNames, operations, hasEncoded);
149             typeInfo = builder.buildTypeInfo(portInfo.getJavaWsdlMapping());
150         }
151 
152         // We register type mappings and invoke serviceDesc.getOperations to trigger an introspection of the
153         // operations. By doing these operations during deployment, no introspection is required during runtime.
154         TypeInfo.register(typeInfo, typeMapping);
155         serviceDesc.getOperations();
156 
157         return new ReadOnlyServiceDesc(serviceDesc, typeInfo);
158     }
159 
160     private static Set buildOperations(Binding binding, Class serviceEndpointInterface, boolean lightweight, PortInfo portInfo, Map exceptionMap, ClassLoader classLoader, Collection operations) throws DeploymentException {
161         Set wrappedElementQNames = new HashSet();
162 
163         SOAPBinding soapBinding = (SOAPBinding) SchemaInfoBuilder.getExtensibilityElement(SOAPBinding.class, binding.getExtensibilityElements());
164         String portStyleString = soapBinding.getStyle();
165         Style portStyle = Style.getStyle(portStyleString);
166 
167         List bindingOperations = binding.getBindingOperations();
168         for (int i = 0; i < bindingOperations.size(); i++) {
169             BindingOperation bindingOperation = (BindingOperation) bindingOperations.get(i);
170 
171             OperationDescBuilder operationDescBuilder;
172             if (lightweight) {
173                 Method method = WSDescriptorParser.getMethodForOperation(serviceEndpointInterface, bindingOperation.getOperation());
174                 operationDescBuilder = new LightweightOperationDescBuilder(bindingOperation, method);
175             } else {
176                 String operationName = bindingOperation.getOperation().getName();
177                 ServiceEndpointMethodMappingType[] methodMappings = portInfo.getServiceEndpointInterfaceMapping().getServiceEndpointMethodMappingArray();
178                 ServiceEndpointMethodMappingType methodMapping = WSDescriptorParser.getMethodMappingForOperation(operationName, methodMappings);
179                 JavaXmlTypeMappingType[] javaXmlTypeMappingTypes = portInfo.getJavaWsdlMapping().getJavaXmlTypeMappingArray();
180                 operationDescBuilder = new HeavyweightOperationDescBuilder(bindingOperation, portInfo.getJavaWsdlMapping(), methodMapping, portStyle, exceptionMap, portInfo.getSchemaInfoBuilder(), javaXmlTypeMappingTypes, classLoader, serviceEndpointInterface);
181                 Set wrappedElementQNamesForOper = ((HeavyweightOperationDescBuilder) operationDescBuilder).getWrapperElementQNames();
182                 wrappedElementQNames.addAll(wrappedElementQNamesForOper);
183             }
184 
185             operations.add(operationDescBuilder.buildOperationDesc());
186         }
187 
188         return wrappedElementQNames;
189     }
190 
191 
192     private static Style getStyle(Binding binding) throws DeploymentException {
193         SOAPBinding soapBinding = (SOAPBinding) SchemaInfoBuilder.getExtensibilityElement(SOAPBinding.class, binding.getExtensibilityElements());
194         String portStyleString = soapBinding.getStyle();
195         Style portStyle = Style.getStyle(portStyleString);
196         return portStyle;
197     }
198 
199     private static String getAddressLocation(Port port) throws DeploymentException {
200         SOAPAddress soapAddress = (SOAPAddress) SchemaInfoBuilder.getExtensibilityElement(SOAPAddress.class, port.getExtensibilityElements());
201         String locationURIString = soapAddress.getLocationURI();
202         return locationURIString;
203     }
204 
205     private static Map rewriteWsdlMap(PortInfo portInfo, Map rawWsdlMap) throws DeploymentException {
206         URI contextURI = portInfo.getContextURI();
207         Map wsdlMap = new HashMap();
208         for (Iterator iterator = rawWsdlMap.entrySet().iterator(); iterator.hasNext();) {
209             Map.Entry entry = (Map.Entry) iterator.next();
210             URI key = (URI) entry.getKey();
211             Object value = entry.getValue();
212             if (value instanceof SchemaDocument) {
213                 SchemaDocument schemaDocument = (SchemaDocument) ((SchemaDocument) value).copy();
214                 SchemaDocument.Schema schema = schemaDocument.getSchema();
215                 rewriteSchema(schema, contextURI, key);
216                 String schemaString = xmlObjectToString(schemaDocument);
217                 wsdlMap.put(key.toString(), schemaString);
218             } else if (value instanceof DefinitionsDocument) {
219                 DefinitionsDocument doc = (DefinitionsDocument) ((DefinitionsDocument) value).copy();
220                 TDefinitions definitions = doc.getDefinitions();
221                 TImport[] imports = definitions.getImportArray();
222                 for (int i = 0; i < imports.length; i++) {
223                     TImport anImport = imports[i];
224                     String importLocation = anImport.getLocation().trim();
225                     if (!importLocation.startsWith("http://")) {
226                         URI updated = buildQueryURI(contextURI, key, importLocation);
227                         anImport.setLocation(updated.toString());
228                     }
229                 }
230                 TTypes[] types = definitions.getTypesArray();
231                 for (int i = 0; i < types.length; i++) {
232                     TTypes type = types[i];
233                     XmlCursor typeCursor = type.newCursor();
234                     try {
235                         if (typeCursor.toChild(SCHEMA_QNAME)) {
236                             do {
237                                 SchemaDocument.Schema schema = (SchemaDocument.Schema) typeCursor.getObject();
238                                 rewriteSchema(schema, contextURI, key);
239                             } while (typeCursor.toNextSibling(SCHEMA_QNAME));
240                         }
241                     } finally {
242                         typeCursor.dispose();
243                     }
244                 }
245                 String docString = xmlObjectToString(doc);
246                 wsdlMap.put(key.toString(), docString);
247             } else {
248                 throw new DeploymentException("Unexpected element in wsdlMap at location: " + key + ", value: " + value);
249             }
250         }
251         return wsdlMap;
252     }
253 
254     static String xmlObjectToString(XmlObject xmlObject) throws DeploymentException {
255         ByteArrayOutputStream baos = new ByteArrayOutputStream();
256         try {
257             xmlObject.save(baos);
258             baos.flush();
259             String result = new String(baos.toByteArray());
260             return result;
261         } catch (IOException e) {
262             throw new DeploymentException("Could not write xml object to string", e);
263         }
264     }
265 
266     private static void rewriteSchema(SchemaDocument.Schema schema, URI contextURI, URI key) throws DeploymentException {
267         ImportDocument.Import[] imports = schema.getImportArray();
268         for (int i = 0; i < imports.length; i++) {
269             ImportDocument.Import anImport = imports[i];
270             if (anImport.isSetSchemaLocation()) {
271                 String schemaLocation = anImport.getSchemaLocation();
272                 URI absoluteSchemLocation = buildQueryURI(contextURI, key, schemaLocation);
273                 anImport.setSchemaLocation(absoluteSchemLocation.toString());
274             }
275         }
276         IncludeDocument.Include[] includes = schema.getIncludeArray();
277         for (int i = 0; i < includes.length; i++) {
278             IncludeDocument.Include include = includes[i];
279             String schemaLocation = include.getSchemaLocation();
280             URI absoluteSchemLocation = buildQueryURI(contextURI, key, schemaLocation);
281             include.setSchemaLocation(absoluteSchemLocation.toString());
282         }
283     }
284 
285     private static URI buildQueryURI(URI contextURI, URI key, String importLocation) throws DeploymentException {
286         try {
287             URI importLocationURI = new URI(importLocation);
288             if (importLocationURI.isAbsolute() || importLocationURI.getPath().startsWith("/")) {
289                 return importLocationURI;
290             }
291             URI queryURI = new URI(null,
292                     null,
293                     contextURI.getPath(),
294                     "wsdl=" + key.resolve(importLocationURI),
295                     null);
296             return queryURI;
297         } catch (URISyntaxException e) {
298             throw new DeploymentException("Could not construct wsdl location URI", e);
299         }
300     }
301 
302 
303 }