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