1 /** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one or more 4 * contributor license agreements. See the NOTICE file distributed with 5 * this work for additional information regarding copyright ownership. 6 * The ASF licenses this file to You under the Apache License, Version 2.0 7 * (the "License"); you may not use this file except in compliance with 8 * the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 package org.apache.openejb.server.cxf.ejb; 19 20 import java.lang.reflect.InvocationTargetException; 21 import java.lang.reflect.Method; 22 import java.util.ArrayList; 23 import java.util.List; 24 25 import javax.interceptor.InvocationContext; 26 import javax.xml.ws.WebFault; 27 import javax.xml.ws.handler.MessageContext; 28 29 import org.apache.cxf.Bus; 30 import org.apache.cxf.interceptor.Fault; 31 import org.apache.cxf.jaxws.context.WebServiceContextImpl; 32 import org.apache.cxf.jaxws.support.ContextPropertiesMapping; 33 import org.apache.cxf.message.Exchange; 34 import org.apache.cxf.message.FaultMode; 35 import org.apache.cxf.service.invoker.AbstractInvoker; 36 import org.apache.openejb.ApplicationException; 37 import org.apache.openejb.DeploymentInfo; 38 import org.apache.openejb.RpcContainer; 39 import org.apache.openejb.InterfaceType; 40 import org.apache.openejb.util.LogCategory; 41 import org.apache.openejb.util.Logger; 42 43 public class EjbMethodInvoker extends AbstractInvoker { 44 private static final Logger log = Logger.getInstance(LogCategory.CXF, EjbMethodInvoker.class); 45 46 private DeploymentInfo deploymentInfo; 47 private Bus bus; 48 49 public EjbMethodInvoker(Bus bus, DeploymentInfo deploymentInfo) { 50 this.bus = bus; 51 this.deploymentInfo = deploymentInfo; 52 } 53 54 public Object getServiceObject(Exchange context) { 55 return null; 56 } 57 58 protected Object invoke(Exchange exchange, Object serviceObject, Method m, List<Object> params) { 59 Object result = null; 60 61 InvocationContext invContext = exchange.get(InvocationContext.class); 62 if (invContext == null) { 63 log.debug("PreEJBInvoke"); 64 result = preEjbInvoke(exchange, m, params); 65 } else { 66 log.debug("EJBInvoke"); 67 result = ejbInvoke(exchange, m, params); 68 } 69 70 return result; 71 } 72 73 private Object preEjbInvoke(Exchange exchange, Method method, List<Object> params) { 74 75 MessageContext ctx = ContextPropertiesMapping.createWebServiceContext(exchange); 76 WebServiceContextImpl.setMessageContext(ctx); 77 78 try { 79 80 EjbInterceptor interceptor = new EjbInterceptor(params, method, this.bus, exchange); 81 Object[] arguments = {ctx, interceptor}; 82 83 RpcContainer container = (RpcContainer) this.deploymentInfo.getContainer(); 84 85 Class callInterface = this.deploymentInfo.getServiceEndpointInterface(); 86 method = getMostSpecificMethod(method, callInterface); 87 Object res = container.invoke(this.deploymentInfo.getDeploymentID(), InterfaceType.SERVICE_ENDPOINT, callInterface, method, arguments, null); 88 89 if (exchange.isOneWay()) { 90 return null; 91 } 92 93 List<Object> retList = new ArrayList<Object>(1); 94 if (!method.getReturnType().getName().equals("void")) { 95 retList.add(res); 96 } 97 98 return retList; 99 100 // OPENEJB-965: must check if the application exception is a web fault. 101 } catch (ApplicationException e) { 102 // when no handler is defined, EjbInterceptor will directly delegate 103 // to #directEjbInvoke. So if an application exception is thrown by 104 // the end user, when must consider the ApplicationException as a 105 // web fault if it contains the @WebFault exception 106 Throwable t = e.getCause(); 107 if (t != null) { 108 if ( t.getClass().isAssignableFrom(RuntimeException.class) && 109 t.getClass().isAnnotationPresent(javax.ejb.ApplicationException.class)) { 110 // it's not a checked exception so it can not be a WebFault 111 throw (RuntimeException)t; 112 113 } else if (!t.getClass().isAnnotationPresent(WebFault.class)) { 114 // not a web fault even if it's an EJB ApplicationException 115 exchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT); 116 throw new Fault(t); 117 } 118 119 } else { // may not occurs ... 120 t = e; 121 } 122 // TODO may be we can change to FaultMode.CHECKED_APPLICATION_FAULT 123 exchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT); 124 throw new Fault(t); 125 } catch (Exception e) { 126 exchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT); 127 throw new Fault(e); 128 } finally { 129 WebServiceContextImpl.clear(); 130 } 131 } 132 133 private Object ejbInvoke(Exchange exchange, Method m, List<Object> params) { 134 try { 135 Object res = directEjbInvoke(exchange, m, params); 136 137 if (exchange.isOneWay()) { 138 return null; 139 } 140 141 List<Object> retList = new ArrayList<Object>(1); 142 if (!m.getReturnType().getName().equals("void")) { 143 retList.add(res); 144 } 145 146 return retList; 147 } catch (InvocationTargetException e) { 148 Throwable t = e.getCause(); 149 if (t == null) { 150 t = e; 151 } 152 exchange.getInMessage().put(FaultMode.class, FaultMode.CHECKED_APPLICATION_FAULT); 153 throw new Fault(t); 154 } catch (Exception e) { 155 exchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT); 156 throw new Fault(e); 157 } 158 } 159 160 public Object directEjbInvoke(Exchange exchange, Method m, List<Object> params) throws Exception { 161 InvocationContext invContext = exchange.get(InvocationContext.class); 162 Object[] paramArray; 163 if (params != null) { 164 paramArray = params.toArray(); 165 } else { 166 paramArray = new Object[]{}; 167 } 168 169 invContext.setParameters(paramArray); 170 Object res = invContext.proceed(); 171 172 ContextPropertiesMapping.updateWebServiceContext(exchange, (MessageContext) invContext.getContextData()); 173 174 return res; 175 } 176 }