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: */package org.apache.openejb.server.axis.assembler;
018:
019: import org.apache.openejb.OpenEJBException;
020: import org.apache.openejb.jee.JavaWsdlMapping;
021: import org.apache.openejb.jee.PortComponent;
022: import org.apache.openejb.jee.ServiceEndpointInterfaceMapping;
023: import org.apache.openejb.jee.ServiceEndpointMethodMapping;
024:
025: import javax.wsdl.Binding;
026: import javax.wsdl.BindingInput;
027: import javax.wsdl.BindingOperation;
028: import javax.wsdl.Port;
029: import javax.wsdl.extensions.soap.SOAPAddress;
030: import javax.wsdl.extensions.soap.SOAPBinding;
031: import javax.wsdl.extensions.soap.SOAPBody;
032: import javax.wsdl.extensions.ExtensibilityElement;
033: import javax.xml.namespace.QName;
034: import java.lang.reflect.Method;
035: import java.util.Collection;
036: import java.util.HashSet;
037: import java.util.List;
038: import java.util.Set;
039:
040: public class JaxRpcServiceInfoBuilder {
041: private final JavaWsdlMapping javaWsdlMapping;
042: private final XmlSchemaInfo schemaInfo;
043: private final PortComponent portComponent;
044: private final Port port;
045: private final String wsdlFile;
046: private final ClassLoader classLoader;
047: private JaxRpcServiceInfo serviceInfo;
048:
049: public JaxRpcServiceInfoBuilder(JavaWsdlMapping javaWsdlMapping,
050: XmlSchemaInfo schemaInfo, PortComponent portComponent,
051: Port port, String wsdlFile, ClassLoader classLoader) {
052: this .javaWsdlMapping = javaWsdlMapping;
053: this .schemaInfo = schemaInfo;
054: this .portComponent = portComponent;
055: this .port = port;
056: this .wsdlFile = wsdlFile;
057: this .classLoader = classLoader;
058: }
059:
060: public JaxRpcServiceInfo createServiceInfo()
061: throws OpenEJBException {
062: Class serviceEndpointInterface;
063: try {
064: serviceEndpointInterface = classLoader
065: .loadClass(portComponent
066: .getServiceEndpointInterface());
067: } catch (ClassNotFoundException e) {
068: throw new OpenEJBException(
069: "Unable to load the service-endpoint interface for port-component "
070: + portComponent.getPortComponentName(), e);
071: }
072:
073: serviceInfo = new JaxRpcServiceInfo();
074: serviceInfo.name = portComponent.getWsdlPort().toString();
075: serviceInfo.serviceEndpointInterface = portComponent
076: .getServiceEndpointInterface();
077: serviceInfo.endpointURL = getAddressLocation(port
078: .getExtensibilityElements());
079: serviceInfo.wsdlFile = wsdlFile;
080: serviceInfo.defaultBindingStyle = getStyle(port.getBinding());
081:
082: // The service is using lightweight mappings if there are no Java to XML service mappings
083: boolean isLightweight = javaWsdlMapping
084: .getServiceEndpointInterfaceMapping().isEmpty();
085:
086: //
087: // Map Operations
088: //
089: Set wrapperElementQNames = buildOperations(port.getBinding(),
090: serviceEndpointInterface, isLightweight);
091:
092: //
093: // Map Types
094: //
095: Collection<JaxRpcTypeInfo> types;
096: if (isLightweight) {
097: LightweightTypeInfoBuilder builder = new LightweightTypeInfoBuilder(
098: javaWsdlMapping, schemaInfo, classLoader);
099: types = builder.buildTypeInfo();
100: } else {
101: HeavyweightTypeInfoBuilder builder = new HeavyweightTypeInfoBuilder(
102: javaWsdlMapping, schemaInfo, classLoader,
103: wrapperElementQNames, serviceInfo.operations,
104: serviceInfo.defaultBindingStyle.isEncoded());
105: types = builder.buildTypeInfo();
106: }
107: serviceInfo.types.addAll(types);
108:
109: return serviceInfo;
110: }
111:
112: private Set<QName> buildOperations(Binding binding,
113: Class serviceEndpointInterface, boolean lightweight)
114: throws OpenEJBException {
115: Set<QName> wrappedElementQNames = new HashSet<QName>();
116:
117: for (Object op : binding.getBindingOperations()) {
118: BindingOperation bindingOperation = (BindingOperation) op;
119: String operationName = bindingOperation.getOperation()
120: .getName();
121:
122: if (lightweight) {
123: // Lightweight mappings are solely based on the Java method
124: Method method = getMethodForOperation(operationName,
125: serviceEndpointInterface);
126:
127: // Build the operation info using the method
128: LightweightOperationInfoBuilder operationInfoBuilder = new LightweightOperationInfoBuilder(
129: bindingOperation, method);
130: JaxRpcOperationInfo operationInfo = operationInfoBuilder
131: .buildOperationInfo();
132: serviceInfo.operations.add(operationInfo);
133: } else {
134: // Heavyweight mappings are solely based on the Java to XML mapping declarations
135: ServiceEndpointMethodMapping methodMapping = getMethodMappingForOperation(
136: operationName, serviceEndpointInterface);
137:
138: // Build the operation info using the Java to XML method mapping
139: HeavyweightOperationInfoBuilder operationInfoBuilder = new HeavyweightOperationInfoBuilder(
140: bindingOperation, methodMapping,
141: javaWsdlMapping, schemaInfo);
142: JaxRpcOperationInfo operationInfo = operationInfoBuilder
143: .buildOperationInfo();
144: serviceInfo.operations.add(operationInfo);
145:
146: // remember wrapped elements for type mapping
147: Set<QName> wrappedElementQNamesForOper = operationInfoBuilder
148: .getWrapperElementQNames();
149: wrappedElementQNames
150: .addAll(wrappedElementQNamesForOper);
151: }
152: }
153:
154: return wrappedElementQNames;
155: }
156:
157: private BindingStyle getStyle(Binding binding)
158: throws OpenEJBException {
159: SOAPBinding soapBinding = getExtensibilityElement(
160: SOAPBinding.class, binding.getExtensibilityElements());
161: String styleString = soapBinding.getStyle();
162:
163: BindingInput bindingInput = ((BindingOperation) binding
164: .getBindingOperations().get(0)).getBindingInput();
165: SOAPBody soapBody = getExtensibilityElement(SOAPBody.class,
166: bindingInput.getExtensibilityElements());
167: String useString = soapBody.getUse();
168:
169: BindingStyle bindingStyle = BindingStyle.getBindingStyle(
170: styleString, useString);
171: return bindingStyle;
172: }
173:
174: private String getAddressLocation(List extensibilityElements)
175: throws OpenEJBException {
176: SOAPAddress soapAddress = getExtensibilityElement(
177: SOAPAddress.class, extensibilityElements);
178: String locationURIString = soapAddress.getLocationURI();
179: return locationURIString;
180: }
181:
182: private Method getMethodForOperation(String operationName,
183: Class serviceEndpointInterface) throws OpenEJBException {
184: Method found = null;
185: for (Method method : serviceEndpointInterface.getMethods()) {
186: if (method.getName().equals(operationName)) {
187: if (found != null) {
188: throw new OpenEJBException(
189: "Overloaded methods are not allowed in lightweight mappings");
190: }
191: found = method;
192: }
193: }
194: if (found == null) {
195: throw new OpenEJBException(
196: "No method found for operation named "
197: + operationName);
198: }
199: return found;
200: }
201:
202: private ServiceEndpointMethodMapping getMethodMappingForOperation(
203: String operationName, Class serviceEndpointInterface)
204: throws OpenEJBException {
205: // get mapping for service endpoint interface
206: ServiceEndpointInterfaceMapping interfaceMapping = javaWsdlMapping
207: .getServiceEndpointInterfaceMappingMap().get(
208: serviceEndpointInterface.getName());
209: if (interfaceMapping == null) {
210: throw new OpenEJBException(
211: "No java-wsdl mapping found for the service interface "
212: + serviceEndpointInterface);
213: }
214:
215: // match by operation name
216: for (ServiceEndpointMethodMapping methodMapping : interfaceMapping
217: .getServiceEndpointMethodMapping()) {
218: if (operationName.equals(methodMapping.getWsdlOperation())) {
219: return methodMapping;
220: }
221: }
222:
223: // failed - throw nice exception message
224: StringBuffer availOps = new StringBuffer(128);
225: for (ServiceEndpointMethodMapping methodMapping : interfaceMapping
226: .getServiceEndpointMethodMapping()) {
227: if (availOps.length() > 0)
228: availOps.append(",");
229: availOps.append(methodMapping.getWsdlOperation());
230: }
231: throw new OpenEJBException(
232: "No method found for operation named '" + operationName
233: + "'. Available operations: " + availOps);
234: }
235:
236: public static <T extends ExtensibilityElement> T getExtensibilityElement(
237: Class<T> clazz, List extensibilityElements)
238: throws OpenEJBException {
239: for (Object o : extensibilityElements) {
240: ExtensibilityElement extensibilityElement = (ExtensibilityElement) o;
241: if (clazz.isAssignableFrom(extensibilityElement.getClass())) {
242: return clazz.cast(extensibilityElement);
243: }
244: }
245: throw new OpenEJBException("No element of class "
246: + clazz.getName() + " found");
247: }
248: }
|