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