001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License. You may obtain a copy of the License at
009     *
010     * http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied. See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    package org.apache.geronimo.cxf.ejb;
021    
022    import java.lang.reflect.InvocationTargetException;
023    import java.lang.reflect.Method;
024    import java.util.ArrayList;
025    import java.util.List;
026    
027    import javax.interceptor.InvocationContext;
028    import javax.xml.ws.handler.MessageContext;
029    
030    import org.apache.commons.logging.Log;
031    import org.apache.commons.logging.LogFactory;
032    import org.apache.cxf.Bus;
033    import org.apache.cxf.interceptor.Fault;
034    import org.apache.cxf.jaxws.context.WebServiceContextImpl;
035    import org.apache.cxf.jaxws.support.ContextPropertiesMapping;
036    import org.apache.cxf.message.Exchange;
037    import org.apache.cxf.message.FaultMode;
038    import org.apache.cxf.service.invoker.AbstractInvoker;
039    import org.apache.openejb.DeploymentInfo;
040    import org.apache.openejb.RpcContainer;
041    
042    public class EJBMethodInvoker extends AbstractInvoker {
043    
044        private static final Log LOG = LogFactory.getLog(EJBMethodInvoker.class);
045        
046        private DeploymentInfo deploymentInfo;
047        private Bus bus;
048        private EJBEndpoint endpoint;
049    
050        public EJBMethodInvoker(EJBEndpoint endpoint, Bus bus, DeploymentInfo deploymentInfo) {
051            this.endpoint = endpoint;
052            this.bus = bus;
053            this.deploymentInfo = deploymentInfo;
054        }
055    
056        public Object getServiceObject(Exchange context) {
057            return null;
058        }
059    
060        protected Object invoke(Exchange exchange, 
061                                Object serviceObject, 
062                                Method m, 
063                                List<Object> params) {       
064            Object result = null;
065            
066            InvocationContext invContext = exchange.get(InvocationContext.class);
067            if (invContext == null) {
068                LOG.debug("PreEJBInvoke");
069                result = preEjbInvoke(exchange, serviceObject, m, params);
070            } else {
071                LOG.debug("EJBInvoke");
072                result = ejbInvoke(exchange, serviceObject, m, params);
073            }    
074            
075            return result;
076        }
077        
078        private Object preEjbInvoke(Exchange exchange, 
079                                    Object serviceObject, 
080                                    Method method, 
081                                    List<Object> params) {           
082            
083            MessageContext ctx = ContextPropertiesMapping.createWebServiceContext(exchange);
084            WebServiceContextImpl.setMessageContext(ctx);
085    
086            try {           
087                EJBInterceptor interceptor = new EJBInterceptor(params, method, this.endpoint, this.bus, exchange);
088                Object[] arguments = { ctx, interceptor };
089    
090                RpcContainer container = (RpcContainer) this.deploymentInfo.getContainer();
091    
092                Class callInterface = this.deploymentInfo.getServiceEndpointInterface();
093                method = getMostSpecificMethod(method, callInterface);
094                Object res = container.invoke(this.deploymentInfo.getDeploymentID(), callInterface, method, arguments, null);
095    
096                if (exchange.isOneWay()) {
097                    return null;
098                }
099    
100                List<Object> retList = new ArrayList<Object>(1);
101                if (!((Class) method.getReturnType()).getName().equals("void")) {
102                    retList.add(res);
103                }
104                
105                return retList;
106            } catch (Exception e) {
107                exchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
108                throw new Fault(e);
109            } finally {
110                WebServiceContextImpl.clear();
111            }
112        }
113        
114        private Object ejbInvoke(Exchange exchange, 
115                                 Object serviceObject, 
116                                 Method m, 
117                                 List<Object> params) {         
118            try {
119                Object res = directEjbInvoke(exchange, m, params);
120                
121                if (exchange.isOneWay()) {
122                    return null;
123                }
124                
125                List<Object> retList = new ArrayList<Object>(1);
126                if (!((Class)m.getReturnType()).getName().equals("void")) {
127                    retList.add(res);
128                }
129                
130                return retList;
131            } catch (InvocationTargetException e) {
132                Throwable t = e.getCause();
133                if (t == null) {
134                    t = e;
135                }
136                exchange.getInMessage().put(FaultMode.class, FaultMode.CHECKED_APPLICATION_FAULT);
137                throw new Fault(t);
138            } catch (Exception e) {
139                exchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
140                throw new Fault(e);
141            }
142        }
143    
144        public Object directEjbInvoke(Exchange exchange, 
145                                      Method m, 
146                                      List<Object> params) throws Exception {
147            InvocationContext invContext = exchange.get(InvocationContext.class);
148            Object[] paramArray;
149            if (params != null) {
150                paramArray = params.toArray();
151            } else {
152                paramArray = new Object[]{};
153            }
154                        
155            invContext.setParameters(paramArray);
156            Object res = invContext.proceed();
157            
158            ContextPropertiesMapping.updateWebServiceContext(exchange, 
159                                                             (MessageContext)invContext.getContextData());
160                    
161            return res;
162        }
163            
164    }