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 }