001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with 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,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.axis2.jaxws.server.dispatcher;
020:
021: import org.apache.axis2.jaxws.ExceptionFactory;
022: import org.apache.axis2.jaxws.context.utils.ContextUtils;
023: import org.apache.axis2.jaxws.core.MessageContext;
024: import org.apache.axis2.jaxws.core.util.MessageContextUtils;
025: import org.apache.axis2.jaxws.description.EndpointDescription;
026: import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
027: import org.apache.axis2.jaxws.description.OperationDescription;
028: import org.apache.axis2.jaxws.i18n.Messages;
029: import org.apache.axis2.jaxws.marshaller.MethodMarshaller;
030: import org.apache.axis2.jaxws.marshaller.factory.MethodMarshallerFactory;
031: import org.apache.axis2.jaxws.message.Message;
032: import org.apache.axis2.jaxws.message.Protocol;
033: import org.apache.commons.logging.Log;
034: import org.apache.commons.logging.LogFactory;
035:
036: import javax.xml.ws.soap.SOAPBinding;
037: import org.apache.axis2.AxisFault;
038: import java.lang.reflect.Method;
039:
040: /**
041: * The JavaBeanDispatcher is used to manage creating an instance of a JAX-WS service implementation
042: * bean and dispatching the inbound request to that instance.
043: */
044: public class JavaBeanDispatcher extends JavaDispatcher {
045:
046: private static final Log log = LogFactory
047: .getLog(JavaBeanDispatcher.class);
048:
049: private EndpointDescription endpointDesc = null;
050:
051: public JavaBeanDispatcher(Class implClass, Object serviceInstance) {
052: super (implClass, serviceInstance);
053: }
054:
055: /*
056: * (non-Javadoc)
057: * @see org.apache.axis2.jaxws.server.EndpointDispatcher#invoke(org.apache.axis2.jaxws.core.MessageContext)
058: */
059: public MessageContext invoke(MessageContext mc) throws Exception {
060: if (log.isDebugEnabled()) {
061: log
062: .debug("Preparing to invoke service endpoint implementation "
063: + "class: " + serviceImplClass.getName());
064: }
065:
066: initialize(mc);
067: OperationDescription operationDesc = getOperationDescription(mc); //mc.getOperationDescription();
068: //Set SOAP Operation Related properties in SOAPMessageContext.
069: ContextUtils.addWSDLProperties(mc);
070: Protocol requestProtocol = mc.getMessage().getProtocol();
071: MethodMarshaller methodMarshaller = getMethodMarshaller(mc
072: .getMessage().getProtocol(), mc
073: .getOperationDescription());
074: Object[] methodInputParams = methodMarshaller.demarshalRequest(
075: mc.getMessage(), mc.getOperationDescription());
076: Method target = getJavaMethod(mc, serviceImplClass);
077: if (log.isDebugEnabled()) {
078: // At this point, the OpDesc includes everything we know, including the actual method
079: // on the service impl we will delegate to; it was set by getJavaMethod(...) above.
080: log
081: .debug("JavaBeanDispatcher about to invoke using OperationDesc: "
082: + operationDesc.toString());
083: }
084:
085: //At this point, we have the method that is going to be invoked and
086: //the parameter data to invoke it with, so we use the instance and
087: //do the invoke.
088: //Passing method input params to grab holder values, if any.
089: boolean faultThrown = false;
090: Throwable fault = null;
091: Object response = null;
092: try {
093: response = invokeService(mc, target, serviceInstance,
094: methodInputParams);
095: } catch (Exception e) {
096: faultThrown = true;
097: fault = e;
098: if (log.isDebugEnabled()) {
099: log.debug("Exception invoking a method of "
100: + serviceImplClass.toString() + " of instance "
101: + serviceInstance.toString());
102: log.debug("Exception type thrown: "
103: + e.getClass().getName());
104: log.debug("Method = " + target.toGenericString());
105: for (int i = 0; i < methodInputParams.length; i++) {
106: String value = (methodInputParams[i] == null) ? "null"
107: : methodInputParams[i].getClass()
108: .toString();
109: log.debug(" Argument[" + i + "] is " + value);
110: }
111: }
112: }
113:
114: Message message = null;
115: if (operationDesc.isOneWay()) {
116: // If the operation is one-way, then we can just return null because
117: // we cannot create a MessageContext for one-way responses.
118: return null;
119: } else if (faultThrown) {
120: message = methodMarshaller.marshalFaultResponse(fault, mc
121: .getOperationDescription(), requestProtocol); // Send the response using the same protocol as the request
122: } else if (target.getReturnType().getName().equals("void")) {
123: message = methodMarshaller.marshalResponse(null,
124: methodInputParams, mc.getOperationDescription(),
125: requestProtocol); // Send the response using the same protocol as the request
126: } else {
127: message = methodMarshaller.marshalResponse(response,
128: methodInputParams, mc.getOperationDescription(),
129: requestProtocol); // Send the response using the same protocol as the request
130: }
131:
132: MessageContext responseMsgCtx = null;
133: if (faultThrown) {
134: responseMsgCtx = MessageContextUtils
135: .createFaultMessageContext(mc);
136: responseMsgCtx.setMessage(message);
137:
138: AxisFault axisFault = new AxisFault(
139: "An error was detected during JAXWS processing",
140: responseMsgCtx.getAxisMessageContext(), fault);
141:
142: responseMsgCtx.setCausedByException(axisFault);
143:
144: } else {
145: responseMsgCtx = MessageContextUtils
146: .createResponseMessageContext(mc);
147: responseMsgCtx.setMessage(message);
148: }
149:
150: //Enable MTOM if necessary
151: EndpointInterfaceDescription epInterfaceDesc = operationDesc
152: .getEndpointInterfaceDescription();
153: EndpointDescription epDesc = epInterfaceDesc
154: .getEndpointDescription();
155:
156: String bindingType = epDesc.getBindingType();
157: if (bindingType != null) {
158: if (bindingType.equals(SOAPBinding.SOAP11HTTP_MTOM_BINDING)
159: || bindingType
160: .equals(SOAPBinding.SOAP12HTTP_MTOM_BINDING)) {
161: message.setMTOMEnabled(true);
162: }
163: }
164:
165: return responseMsgCtx;
166: }
167:
168: protected Object invokeService(MessageContext ctx, Method method,
169: Object obj, Object args[]) throws Exception {
170: return method.invoke(obj, args);
171: }
172:
173: private void initialize(MessageContext mc) {
174: mc.setOperationName(mc.getAxisMessageContext()
175: .getAxisOperation().getName());
176: endpointDesc = mc.getEndpointDescription();
177: mc.setOperationDescription(getOperationDescription(mc));
178: String bindingType = endpointDesc.getBindingType();
179: if (bindingType != null) {
180: if (bindingType.equals(SOAPBinding.SOAP11HTTP_MTOM_BINDING)
181: || bindingType
182: .equals(SOAPBinding.SOAP12HTTP_MTOM_BINDING)) {
183: mc.getMessage().setMTOMEnabled(true);
184: }
185: }
186: }
187:
188: /*
189: * Gets the OperationDescription associated with the request that is currently
190: * being processed.
191: *
192: * Note that this is not done in the EndpointController since operations are only relevant
193: * to Endpoint-based implementation (i.e. not to Proxy-based ones)s
194: */
195: private OperationDescription getOperationDescription(
196: MessageContext mc) {
197: EndpointDescription ed = mc.getEndpointDescription();
198: EndpointInterfaceDescription eid = ed
199: .getEndpointInterfaceDescription();
200:
201: OperationDescription[] ops = eid.getDispatchableOperation(mc
202: .getOperationName());
203: // TODO: Implement signature matching. Currently only matching on the wsdl:OperationName is supported.
204: // That means that overloading of wsdl operations is not supported (although that's not supported in
205: // WSDL 1.1 anyway).
206: if (ops == null || ops.length == 0) {
207: // TODO: RAS & NLS
208: throw ExceptionFactory
209: .makeWebServiceException("No operation found. WSDL Operation name: "
210: + mc.getOperationName());
211: }
212: if (ops.length > 1) {
213: // TODO: RAS & NLS
214: throw ExceptionFactory
215: .makeWebServiceException("More than one operation found. Overloaded WSDL operations are not supported. WSDL Operation name: "
216: + mc.getOperationName());
217: }
218: OperationDescription op = ops[0];
219: if (log.isDebugEnabled()) {
220: log.debug("wsdl operation: " + op.getName());
221: log.debug(" java method: " + op.getJavaMethodName());
222: }
223:
224: return op;
225: }
226:
227: private MethodMarshaller getMethodMarshaller(Protocol protocol,
228: OperationDescription operationDesc) {
229: javax.jws.soap.SOAPBinding.Style styleOnSEI = endpointDesc
230: .getEndpointInterfaceDescription()
231: .getSoapBindingStyle();
232: javax.jws.soap.SOAPBinding.Style styleOnMethod = operationDesc
233: .getSoapBindingStyle();
234: if (styleOnMethod != null && styleOnSEI != styleOnMethod) {
235: throw ExceptionFactory.makeWebServiceException(Messages
236: .getMessage("proxyErr2"));
237: }
238: return MethodMarshallerFactory.getMarshaller(operationDesc,
239: false);
240: }
241:
242: private Method getJavaMethod(MessageContext mc,
243: Class serviceImplClass) {
244:
245: OperationDescription opDesc = mc.getOperationDescription();
246: if (opDesc == null) {
247: // TODO: NLS
248: throw ExceptionFactory
249: .makeWebServiceException("Operation Description was not set");
250: }
251:
252: Method returnMethod = opDesc
253: .getMethodFromServiceImpl(serviceImplClass);
254: if (returnMethod == null) {
255: throw ExceptionFactory.makeWebServiceException(Messages
256: .getMessage("JavaBeanDispatcherErr1"));
257: }
258:
259: return returnMethod;
260: }
261: /*
262: protected boolean isDocLitBare(EndpointDescription endpointDesc, OperationDescription operationDesc){
263: javax.jws.soap.SOAPBinding.ParameterStyle methodParamStyle = operationDesc.getSoapBindingParameterStyle();
264: if(methodParamStyle!=null){
265: return methodParamStyle == javax.jws.soap.SOAPBinding.ParameterStyle.BARE;
266: }
267: else{
268: javax.jws.soap.SOAPBinding.ParameterStyle SEIParamStyle = endpointDesc.getEndpointInterfaceDescription().getSoapBindingParameterStyle();
269: return SEIParamStyle == javax.jws.soap.SOAPBinding.ParameterStyle.BARE;
270: }
271: }
272:
273: protected boolean isDocLitWrapped(EndpointDescription endpointDesc, OperationDescription operationDesc){
274: javax.jws.soap.SOAPBinding.ParameterStyle methodParamStyle = operationDesc.getSoapBindingParameterStyle();
275: if(methodParamStyle!=null){
276: return methodParamStyle == javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED;
277: }
278: else{
279: javax.jws.soap.SOAPBinding.ParameterStyle SEIParamStyle = endpointDesc.getEndpointInterfaceDescription().getSoapBindingParameterStyle();
280: return SEIParamStyle == javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED;
281: }
282: }
283: */
284:
285: }
|