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 }