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.io.ByteArrayOutputStream;
020 import java.io.IOException;
021 import java.lang.reflect.Method;
022 import java.net.URI;
023 import java.net.URISyntaxException;
024 import java.util.ArrayList;
025 import java.util.Collection;
026 import java.util.HashMap;
027 import java.util.HashSet;
028 import java.util.Iterator;
029 import java.util.List;
030 import java.util.Map;
031 import java.util.Set;
032 import javax.wsdl.Binding;
033 import javax.wsdl.BindingInput;
034 import javax.wsdl.BindingOperation;
035 import javax.wsdl.Port;
036 import javax.wsdl.extensions.soap.SOAPAddress;
037 import javax.wsdl.extensions.soap.SOAPBinding;
038 import javax.wsdl.extensions.soap.SOAPBody;
039 import javax.xml.namespace.QName;
040
041 import org.apache.axis.constants.Style;
042 import org.apache.axis.constants.Use;
043 import org.apache.axis.description.JavaServiceDesc;
044 import org.apache.axis.description.OperationDesc;
045 import org.apache.axis.encoding.TypeMapping;
046 import org.apache.axis.encoding.TypeMappingRegistryImpl;
047 import org.apache.geronimo.axis.client.TypeInfo;
048 import org.apache.geronimo.axis.server.ReadOnlyServiceDesc;
049 import org.apache.geronimo.axis.server.ServiceInfo;
050 import org.apache.geronimo.common.DeploymentException;
051 import org.apache.geronimo.xbeans.j2ee.JavaXmlTypeMappingType;
052 import org.apache.geronimo.xbeans.j2ee.ServiceEndpointMethodMappingType;
053 import org.apache.geronimo.xbeans.wsdl.DefinitionsDocument;
054 import org.apache.geronimo.xbeans.wsdl.TDefinitions;
055 import org.apache.geronimo.xbeans.wsdl.TImport;
056 import org.apache.geronimo.xbeans.wsdl.TTypes;
057 import org.apache.geronimo.webservices.builder.PortInfo;
058 import org.apache.geronimo.webservices.builder.SchemaInfoBuilder;
059 import org.apache.geronimo.webservices.builder.WSDescriptorParser;
060 import org.apache.xmlbeans.XmlCursor;
061 import org.apache.xmlbeans.XmlObject;
062 import org.apache.xmlbeans.impl.xb.xsdschema.ImportDocument;
063 import org.apache.xmlbeans.impl.xb.xsdschema.IncludeDocument;
064 import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
065
066 /**
067 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
068 */
069 public class AxisServiceBuilder {
070
071 public static final String XSD_NS = "http://www.w3.org/2001/XMLSchema";
072 public static final QName SCHEMA_QNAME = new QName(XSD_NS, "schema");
073
074
075 public static ServiceInfo createServiceInfo(PortInfo portInfo, ClassLoader classLoader) throws DeploymentException {
076 JavaServiceDesc serviceDesc = createServiceDesc(portInfo, classLoader);
077 List handlerInfos = WSDescriptorParser.createHandlerInfoList(portInfo.getHandlers(), classLoader);
078 SchemaInfoBuilder schemaInfoBuilder = portInfo.getSchemaInfoBuilder();
079 Map rawWsdlMap = schemaInfoBuilder.getWsdlMap();
080 Map wsdlMap = rewriteWsdlMap(portInfo, rawWsdlMap);
081 return new ServiceInfo(serviceDesc, handlerInfos, wsdlMap);
082 }
083
084 public static JavaServiceDesc createServiceDesc(PortInfo portInfo, ClassLoader classLoader) throws DeploymentException {
085
086 Port port = portInfo.getPort();
087
088 Class serviceEndpointInterface = null;
089 try {
090 serviceEndpointInterface = classLoader.loadClass(portInfo.getServiceEndpointInterfaceName());
091 } catch (ClassNotFoundException e) {
092 throw (DeploymentException) new DeploymentException("Unable to load the service-endpoint interface for port-component " + portInfo.getPortComponentName()).initCause(e);
093 }
094
095 Map exceptionMap = WSDescriptorParser.getExceptionMap(portInfo.getJavaWsdlMapping());
096 SchemaInfoBuilder schemaInfoBuilder = portInfo.getSchemaInfoBuilder();
097 Map schemaTypeKeyToSchemaTypeMap = schemaInfoBuilder.getSchemaTypeKeyToSchemaTypeMap();
098
099 JavaServiceDesc serviceDesc = new JavaServiceDesc();
100 String serviceName = portInfo.getPortQName().toString();
101 String location = getAddressLocation(port);
102 serviceDesc.setName(serviceName);
103 serviceDesc.setEndpointURL(location);
104 serviceDesc.setWSDLFile(portInfo.getWsdlLocation());
105 Binding binding = port.getBinding();
106
107 serviceDesc.setStyle(getStyle(binding));
108
109
110 BindingInput bindingInput = ((BindingOperation) binding.getBindingOperations().get(0)).getBindingInput();
111 SOAPBody soapBody = (SOAPBody) SchemaInfoBuilder.getExtensibilityElement(SOAPBody.class, bindingInput.getExtensibilityElements());
112
113 if (soapBody.getUse() != null) {
114 Use use = Use.getUse(soapBody.getUse());
115 serviceDesc.setUse(use);
116 } else {
117 serviceDesc.setUse(Use.ENCODED);
118 }
119 boolean hasEncoded = serviceDesc.getUse() == Use.ENCODED;
120
121 boolean isLightweight = portInfo.getServiceEndpointInterfaceMapping() == null;
122
123 // if (isLightweight) {
124 // validateLightweightMapping(portInfo.getDefinition());
125 // }
126
127 Collection operations = new ArrayList();
128 Set wrapperElementQNames = buildOperations(binding, serviceEndpointInterface, isLightweight, portInfo, exceptionMap, classLoader, operations);
129 for (Iterator iter = operations.iterator(); iter.hasNext();) {
130 OperationDesc operation = (OperationDesc) iter.next();
131 serviceDesc.addOperationDesc(operation);
132 }
133
134 TypeMappingRegistryImpl tmr = new TypeMappingRegistryImpl();
135 tmr.doRegisterFromVersion("1.3");
136
137 TypeMapping typeMapping = tmr.getOrMakeTypeMapping(serviceDesc.getUse().getEncoding());
138
139 serviceDesc.setTypeMappingRegistry(tmr);
140 serviceDesc.setTypeMapping(typeMapping);
141
142 List typeInfo;
143 if (isLightweight) {
144 LightweightTypeInfoBuilder builder = new LightweightTypeInfoBuilder(classLoader, schemaTypeKeyToSchemaTypeMap, wrapperElementQNames);
145 typeInfo = builder.buildTypeInfo(portInfo.getJavaWsdlMapping());
146 } else {
147 HeavyweightTypeInfoBuilder builder = new HeavyweightTypeInfoBuilder(classLoader, schemaTypeKeyToSchemaTypeMap, wrapperElementQNames, operations, hasEncoded);
148 typeInfo = builder.buildTypeInfo(portInfo.getJavaWsdlMapping());
149 }
150
151 // We register type mappings and invoke serviceDesc.getOperations to trigger an introspection of the
152 // operations. By doing these operations during deployment, no introspection is required during runtime.
153 TypeInfo.register(typeInfo, typeMapping);
154 serviceDesc.getOperations();
155
156 return new ReadOnlyServiceDesc(serviceDesc, typeInfo);
157 }
158
159 private static Set buildOperations(Binding binding, Class serviceEndpointInterface, boolean lightweight, PortInfo portInfo, Map exceptionMap, ClassLoader classLoader, Collection operations) throws DeploymentException {
160 Set wrappedElementQNames = new HashSet();
161
162 SOAPBinding soapBinding = (SOAPBinding) SchemaInfoBuilder.getExtensibilityElement(SOAPBinding.class, binding.getExtensibilityElements());
163 String portStyleString = soapBinding.getStyle();
164 Style portStyle = Style.getStyle(portStyleString);
165
166 List bindingOperations = binding.getBindingOperations();
167 for (int i = 0; i < bindingOperations.size(); i++) {
168 BindingOperation bindingOperation = (BindingOperation) bindingOperations.get(i);
169
170 OperationDescBuilder operationDescBuilder;
171 if (lightweight) {
172 Method method = WSDescriptorParser.getMethodForOperation(serviceEndpointInterface, bindingOperation.getOperation());
173 operationDescBuilder = new LightweightOperationDescBuilder(bindingOperation, method);
174 } else {
175 String operationName = bindingOperation.getOperation().getName();
176 ServiceEndpointMethodMappingType[] methodMappings = portInfo.getServiceEndpointInterfaceMapping().getServiceEndpointMethodMappingArray();
177 ServiceEndpointMethodMappingType methodMapping = WSDescriptorParser.getMethodMappingForOperation(operationName, methodMappings);
178 JavaXmlTypeMappingType[] javaXmlTypeMappingTypes = portInfo.getJavaWsdlMapping().getJavaXmlTypeMappingArray();
179 operationDescBuilder = new HeavyweightOperationDescBuilder(bindingOperation, portInfo.getJavaWsdlMapping(), methodMapping, portStyle, exceptionMap, portInfo.getSchemaInfoBuilder(), javaXmlTypeMappingTypes, classLoader, serviceEndpointInterface);
180 Set wrappedElementQNamesForOper = ((HeavyweightOperationDescBuilder) operationDescBuilder).getWrapperElementQNames();
181 wrappedElementQNames.addAll(wrappedElementQNamesForOper);
182 }
183
184 operations.add(operationDescBuilder.buildOperationDesc());
185 }
186
187 return wrappedElementQNames;
188 }
189
190
191 private static Style getStyle(Binding binding) throws DeploymentException {
192 SOAPBinding soapBinding = (SOAPBinding) SchemaInfoBuilder.getExtensibilityElement(SOAPBinding.class, binding.getExtensibilityElements());
193 String portStyleString = soapBinding.getStyle();
194 Style portStyle = Style.getStyle(portStyleString);
195 return portStyle;
196 }
197
198 private static String getAddressLocation(Port port) throws DeploymentException {
199 SOAPAddress soapAddress = (SOAPAddress) SchemaInfoBuilder.getExtensibilityElement(SOAPAddress.class, port.getExtensibilityElements());
200 String locationURIString = soapAddress.getLocationURI();
201 return locationURIString;
202 }
203
204 private static Map rewriteWsdlMap(PortInfo portInfo, Map rawWsdlMap) throws DeploymentException {
205 URI contextURI = portInfo.getContextURI();
206 Map wsdlMap = new HashMap();
207 for (Iterator iterator = rawWsdlMap.entrySet().iterator(); iterator.hasNext();) {
208 Map.Entry entry = (Map.Entry) iterator.next();
209 URI key = (URI) entry.getKey();
210 Object value = entry.getValue();
211 if (value instanceof SchemaDocument) {
212 SchemaDocument schemaDocument = (SchemaDocument) ((SchemaDocument) value).copy();
213 SchemaDocument.Schema schema = schemaDocument.getSchema();
214 rewriteSchema(schema, contextURI, key);
215 String schemaString = xmlObjectToString(schemaDocument);
216 wsdlMap.put(key.toString(), schemaString);
217 } else if (value instanceof DefinitionsDocument) {
218 DefinitionsDocument doc = (DefinitionsDocument) ((DefinitionsDocument) value).copy();
219 TDefinitions definitions = doc.getDefinitions();
220 TImport[] imports = definitions.getImportArray();
221 for (int i = 0; i < imports.length; i++) {
222 TImport anImport = imports[i];
223 String importLocation = anImport.getLocation().trim();
224 if (!importLocation.startsWith("http://")) {
225 URI updated = buildQueryURI(contextURI, key, importLocation);
226 anImport.setLocation(updated.toString());
227 }
228 }
229 TTypes[] types = definitions.getTypesArray();
230 for (int i = 0; i < types.length; i++) {
231 TTypes type = types[i];
232 XmlCursor typeCursor = type.newCursor();
233 try {
234 if (typeCursor.toChild(SCHEMA_QNAME)) {
235 do {
236 SchemaDocument.Schema schema = (SchemaDocument.Schema) typeCursor.getObject();
237 rewriteSchema(schema, contextURI, key);
238 } while (typeCursor.toNextSibling(SCHEMA_QNAME));
239 }
240 } finally {
241 typeCursor.dispose();
242 }
243 }
244 String docString = xmlObjectToString(doc);
245 wsdlMap.put(key.toString(), docString);
246 } else {
247 throw new DeploymentException("Unexpected element in wsdlMap at location: " + key + ", value: " + value);
248 }
249 }
250 return wsdlMap;
251 }
252
253 static String xmlObjectToString(XmlObject xmlObject) throws DeploymentException {
254 ByteArrayOutputStream baos = new ByteArrayOutputStream();
255 try {
256 xmlObject.save(baos);
257 baos.flush();
258 String result = new String(baos.toByteArray());
259 return result;
260 } catch (IOException e) {
261 throw new DeploymentException("Could not write xml object to string", e);
262 }
263 }
264
265 private static void rewriteSchema(SchemaDocument.Schema schema, URI contextURI, URI key) throws DeploymentException {
266 ImportDocument.Import[] imports = schema.getImportArray();
267 for (int i = 0; i < imports.length; i++) {
268 ImportDocument.Import anImport = imports[i];
269 if (anImport.isSetSchemaLocation()) {
270 String schemaLocation = anImport.getSchemaLocation();
271 URI absoluteSchemLocation = buildQueryURI(contextURI, key, schemaLocation);
272 anImport.setSchemaLocation(absoluteSchemLocation.toString());
273 }
274 }
275 IncludeDocument.Include[] includes = schema.getIncludeArray();
276 for (int i = 0; i < includes.length; i++) {
277 IncludeDocument.Include include = includes[i];
278 String schemaLocation = include.getSchemaLocation();
279 URI absoluteSchemLocation = buildQueryURI(contextURI, key, schemaLocation);
280 include.setSchemaLocation(absoluteSchemLocation.toString());
281 }
282 }
283
284 private static URI buildQueryURI(URI contextURI, URI key, String importLocation) throws DeploymentException {
285 try {
286 URI importLocationURI = new URI(importLocation);
287 if (importLocationURI.isAbsolute() || importLocationURI.getPath().startsWith("/")) {
288 return importLocationURI;
289 }
290 URI queryURI = new URI(null,
291 null,
292 contextURI.getPath(),
293 "wsdl=" + key.resolve(importLocationURI),
294 null);
295 return queryURI;
296 } catch (URISyntaxException e) {
297 throw new DeploymentException("Could not construct wsdl location URI", e);
298 }
299 }
300
301
302 }