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 }