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