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 }