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