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.axis2.ejb;
017:
018: import java.lang.reflect.Method;
019: import java.lang.reflect.ParameterizedType;
020: import java.lang.reflect.Type;
021:
022: import javax.xml.ws.Provider;
023:
024: import org.apache.axis2.AxisFault;
025: import org.apache.axis2.description.AxisService;
026: import org.apache.axis2.description.Parameter;
027: import org.apache.axis2.engine.MessageReceiver;
028: import org.apache.axis2.jaxws.ExceptionFactory;
029: import org.apache.axis2.jaxws.core.MessageContext;
030: import org.apache.axis2.jaxws.description.EndpointDescription;
031: import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
032: import org.apache.axis2.jaxws.description.OperationDescription;
033: import org.apache.axis2.jaxws.handler.SoapMessageContext;
034: import org.apache.axis2.jaxws.i18n.Messages;
035: import org.apache.commons.logging.Log;
036: import org.apache.commons.logging.LogFactory;
037: import org.apache.openejb.ApplicationException;
038: import org.apache.openejb.DeploymentInfo;
039: import org.apache.openejb.RpcContainer;
040:
041: public class EJBMessageReceiver implements MessageReceiver {
042:
043: private static final Log LOG = LogFactory
044: .getLog(EJBMessageReceiver.class);
045:
046: private DeploymentInfo deploymentInfo;
047: private Class serviceImplClass;
048: private EJBWebServiceContainer container;
049:
050: public EJBMessageReceiver(EJBWebServiceContainer container,
051: Class serviceImplClass, DeploymentInfo deploymentInfo) {
052: this .container = container;
053: this .serviceImplClass = serviceImplClass;
054: this .deploymentInfo = deploymentInfo;
055: }
056:
057: public void receive(
058: org.apache.axis2.context.MessageContext axisMsgCtx)
059: throws AxisFault {
060: MessageContext requestMsgCtx = new MessageContext(axisMsgCtx);
061:
062: // init some bits
063: requestMsgCtx.setOperationName(requestMsgCtx
064: .getAxisMessageContext().getAxisOperation().getName());
065: requestMsgCtx
066: .setEndpointDescription(getEndpointDescription(requestMsgCtx));
067:
068: Method method = null;
069: if (Provider.class.isAssignableFrom(this .serviceImplClass)) {
070: method = getProviderMethod();
071: } else {
072: requestMsgCtx
073: .setOperationDescription(getOperationDescription(requestMsgCtx));
074: method = getServiceMethod(requestMsgCtx);
075: }
076:
077: if (LOG.isDebugEnabled()) {
078: LOG.debug("Invoking '" + method.getName() + "' method.");
079: }
080:
081: EJBInterceptor interceptor = new EJBInterceptor(this .container,
082: requestMsgCtx);
083:
084: SoapMessageContext jaxwsContext = new SoapMessageContext(
085: requestMsgCtx);
086: Object[] arguments = { jaxwsContext, interceptor };
087:
088: RpcContainer container = (RpcContainer) this .deploymentInfo
089: .getContainer();
090:
091: Class callInterface = this .deploymentInfo
092: .getServiceEndpointInterface();
093:
094: method = getMostSpecificMethod(method, callInterface);
095:
096: try {
097: Object res = container.invoke(this .deploymentInfo
098: .getDeploymentID(), callInterface, method,
099: arguments, null);
100: // TODO: update response message with new response value?
101: } catch (ApplicationException e) {
102: if (e.getCause() instanceof AxisFault) {
103: throw (AxisFault) e.getCause();
104: } else {
105: throw AxisFault.makeFault(e);
106: }
107: } catch (Exception e) {
108: throw AxisFault.makeFault(e);
109: }
110: }
111:
112: private static Method getMostSpecificMethod(Method method,
113: Class<?> targetClass) {
114: if (method != null && targetClass != null) {
115: try {
116: method = targetClass.getMethod(method.getName(), method
117: .getParameterTypes());
118: } catch (NoSuchMethodException ex) {
119: // Perhaps the target class doesn't implement this method:
120: // that's fine, just use the original method
121: }
122: }
123: return method;
124: }
125:
126: private Method getServiceMethod(MessageContext mc) {
127: OperationDescription opDesc = mc.getOperationDescription();
128: if (opDesc == null) {
129: throw ExceptionFactory
130: .makeWebServiceException("Operation Description was not set");
131: }
132:
133: Method returnMethod = opDesc
134: .getMethodFromServiceImpl(this .serviceImplClass);
135: if (returnMethod == null) {
136: throw ExceptionFactory.makeWebServiceException(Messages
137: .getMessage("JavaBeanDispatcherErr1"));
138: }
139:
140: return returnMethod;
141: }
142:
143: private OperationDescription getOperationDescription(
144: MessageContext mc) {
145: EndpointDescription ed = mc.getEndpointDescription();
146: EndpointInterfaceDescription eid = ed
147: .getEndpointInterfaceDescription();
148:
149: OperationDescription[] ops = eid.getDispatchableOperation(mc
150: .getOperationName());
151: if (ops == null || ops.length == 0) {
152: throw ExceptionFactory
153: .makeWebServiceException("No operation found. WSDL Operation name: "
154: + mc.getOperationName());
155: }
156: if (ops.length > 1) {
157: throw ExceptionFactory
158: .makeWebServiceException("More than one operation found. Overloaded WSDL operations are not supported. WSDL Operation name: "
159: + mc.getOperationName());
160: }
161: OperationDescription op = ops[0];
162: return op;
163: }
164:
165: private EndpointDescription getEndpointDescription(MessageContext mc) {
166: AxisService axisSvc = mc.getAxisMessageContext()
167: .getAxisService();
168:
169: Parameter param = axisSvc
170: .getParameter(EndpointDescription.AXIS_SERVICE_PARAMETER);
171:
172: EndpointDescription ed = (EndpointDescription) param.getValue();
173: return ed;
174: }
175:
176: private Method getProviderMethod() {
177: try {
178: return this .serviceImplClass.getMethod("invoke",
179: getProviderType());
180: } catch (NoSuchMethodException e) {
181: throw ExceptionFactory
182: .makeWebServiceException("Could not get Provider.invoke() method");
183: }
184: }
185:
186: private Class<?> getProviderType() {
187: Class providerType = null;
188:
189: Type[] giTypes = this .serviceImplClass.getGenericInterfaces();
190: for (Type giType : giTypes) {
191: ParameterizedType paramType = null;
192: try {
193: paramType = (ParameterizedType) giType;
194: } catch (ClassCastException e) {
195: throw ExceptionFactory
196: .makeWebServiceException("Provider based SEI Class has to implement javax.xml.ws.Provider as javax.xml.ws.Provider<String>, javax.xml.ws.Provider<SOAPMessage>, javax.xml.ws.Provider<Source> or javax.xml.ws.Provider<JAXBContext>");
197: }
198: Class interfaceName = (Class) paramType.getRawType();
199:
200: if (interfaceName == javax.xml.ws.Provider.class) {
201: if (paramType.getActualTypeArguments().length > 1) {
202: throw ExceptionFactory
203: .makeWebServiceException("Provider cannot have more than one Generic Types defined as Per JAX-WS Specification");
204: }
205: providerType = (Class) paramType
206: .getActualTypeArguments()[0];
207: }
208: }
209: return providerType;
210: }
211:
212: }
|