001 /**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.geronimo.axis.builder;
019
020 import java.io.ByteArrayOutputStream;
021 import java.io.IOException;
022 import java.lang.reflect.Method;
023 import java.net.URI;
024 import java.net.URISyntaxException;
025 import java.util.ArrayList;
026 import java.util.Collection;
027 import java.util.HashMap;
028 import java.util.HashSet;
029 import java.util.Iterator;
030 import java.util.List;
031 import java.util.Map;
032 import java.util.Set;
033 import javax.wsdl.Binding;
034 import javax.wsdl.BindingInput;
035 import javax.wsdl.BindingOperation;
036 import javax.wsdl.Port;
037 import javax.wsdl.extensions.soap.SOAPAddress;
038 import javax.wsdl.extensions.soap.SOAPBinding;
039 import javax.wsdl.extensions.soap.SOAPBody;
040 import javax.xml.namespace.QName;
041
042 import org.apache.axis.constants.Style;
043 import org.apache.axis.constants.Use;
044 import org.apache.axis.description.JavaServiceDesc;
045 import org.apache.axis.description.OperationDesc;
046 import org.apache.axis.encoding.TypeMapping;
047 import org.apache.axis.encoding.TypeMappingRegistryImpl;
048 import org.apache.geronimo.axis.client.TypeInfo;
049 import org.apache.geronimo.axis.server.ReadOnlyServiceDesc;
050 import org.apache.geronimo.axis.server.ServiceInfo;
051 import org.apache.geronimo.common.DeploymentException;
052 import org.apache.geronimo.xbeans.j2ee.JavaXmlTypeMappingType;
053 import org.apache.geronimo.xbeans.j2ee.ServiceEndpointMethodMappingType;
054 import org.apache.geronimo.xbeans.wsdl.DefinitionsDocument;
055 import org.apache.geronimo.xbeans.wsdl.TDefinitions;
056 import org.apache.geronimo.xbeans.wsdl.TImport;
057 import org.apache.geronimo.xbeans.wsdl.TTypes;
058 import org.apache.geronimo.webservices.builder.PortInfo;
059 import org.apache.geronimo.webservices.builder.SchemaInfoBuilder;
060 import org.apache.geronimo.webservices.builder.WSDescriptorParser;
061 import org.apache.xmlbeans.XmlCursor;
062 import org.apache.xmlbeans.XmlObject;
063 import org.apache.xmlbeans.impl.xb.xsdschema.ImportDocument;
064 import org.apache.xmlbeans.impl.xb.xsdschema.IncludeDocument;
065 import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
066
067 /**
068 * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
069 */
070 public class AxisServiceBuilder {
071
072 public static final String XSD_NS = "http://www.w3.org/2001/XMLSchema";
073 public static final QName SCHEMA_QNAME = new QName(XSD_NS, "schema");
074
075
076 public static ServiceInfo createServiceInfo(PortInfo portInfo, ClassLoader classLoader) throws DeploymentException {
077 JavaServiceDesc serviceDesc = createServiceDesc(portInfo, classLoader);
078 List handlerInfos = WSDescriptorParser.createHandlerInfoList(portInfo.getHandlers(), classLoader);
079 SchemaInfoBuilder schemaInfoBuilder = portInfo.getSchemaInfoBuilder();
080 Map rawWsdlMap = schemaInfoBuilder.getWsdlMap();
081 Map wsdlMap = rewriteWsdlMap(portInfo, rawWsdlMap);
082 return new ServiceInfo(serviceDesc, handlerInfos, wsdlMap);
083 }
084
085 public static JavaServiceDesc createServiceDesc(PortInfo portInfo, ClassLoader classLoader) throws DeploymentException {
086
087 Port port = portInfo.getPort();
088
089 Class serviceEndpointInterface = null;
090 try {
091 serviceEndpointInterface = classLoader.loadClass(portInfo.getServiceEndpointInterfaceName());
092 } catch (ClassNotFoundException e) {
093 throw (DeploymentException) new DeploymentException("Unable to load the service-endpoint interface for port-component " + portInfo.getPortComponentName()).initCause(e);
094 }
095
096 Map exceptionMap = WSDescriptorParser.getExceptionMap(portInfo.getJavaWsdlMapping());
097 SchemaInfoBuilder schemaInfoBuilder = portInfo.getSchemaInfoBuilder();
098 Map schemaTypeKeyToSchemaTypeMap = schemaInfoBuilder.getSchemaTypeKeyToSchemaTypeMap();
099
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 }