1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.openejb.core.ivm;
18
19 import java.io.ObjectStreamException;
20 import java.lang.reflect.Method;
21 import java.rmi.AccessException;
22 import java.rmi.RemoteException;
23 import java.util.List;
24
25 import javax.ejb.AccessLocalException;
26 import javax.ejb.EJBAccessException;
27 import javax.ejb.EJBLocalObject;
28 import javax.ejb.EJBObject;
29
30 import org.apache.openejb.DeploymentInfo;
31 import org.apache.openejb.InterfaceType;
32 import org.apache.openejb.core.ServerFederation;
33 import org.apache.openejb.spi.ApplicationServer;
34 import org.apache.openejb.util.LogCategory;
35 import org.apache.openejb.util.Logger;
36
37 public abstract class EjbObjectProxyHandler extends BaseEjbProxyHandler {
38 private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources");
39 static final java.util.HashMap dispatchTable;
40
41 static {
42 dispatchTable = new java.util.HashMap();
43 dispatchTable.put("getHandle", new Integer(1));
44 dispatchTable.put("getPrimaryKey", new Integer(2));
45 dispatchTable.put("isIdentical", new Integer(3));
46 dispatchTable.put("remove", new Integer(4));
47 dispatchTable.put("getEJBHome", new Integer(5));
48 dispatchTable.put("getEJBLocalHome", new Integer(6));
49
50 }
51
52 public EjbObjectProxyHandler(DeploymentInfo deploymentInfo, Object pk, InterfaceType interfaceType, List<Class> interfaces) {
53 super(deploymentInfo, pk, interfaceType, interfaces);
54 }
55
56 public abstract Object getRegistryId();
57
58 public Object _invoke(Object p, Class interfce, Method m, Object[] a) throws Throwable {
59 java.lang.Object retValue = null;
60 java.lang.Throwable exc = null;
61
62 try {
63 if (logger.isDebugEnabled()) {
64 logger.debug("invoking method " + m.getName() + " on " + deploymentID + " with identity " + primaryKey);
65 }
66 Integer operation = (Integer) dispatchTable.get(m.getName());
67 if(operation != null){
68 if(operation.intValue() == 3){
69 if(m.getParameterTypes()[0] != EJBObject.class && m.getParameterTypes()[0] != EJBLocalObject.class ){
70 operation = null;
71 }
72 } else {
73 operation = (m.getParameterTypes().length == 0)?operation:null;
74 }
75 }
76 if (operation == null || !interfaceType.isComponent() ) {
77 retValue = businessMethod(interfce, m, a, p);
78 } else {
79 switch (operation.intValue()) {
80 case 1:
81 retValue = getHandle(m, a, p);
82 break;
83 case 2:
84 retValue = getPrimaryKey(m, a, p);
85 break;
86 case 3:
87 retValue = isIdentical(m, a, p);
88 break;
89 case 4:
90 retValue = remove(interfce, m, a, p);
91 break;
92 case 5:
93 retValue = getEJBHome(m, a, p);
94 break;
95 case 6:
96 retValue = getEJBLocalHome(m, a, p);
97 break;
98 default:
99 throw new RuntimeException("Inconsistent internal state");
100 }
101 }
102
103 return retValue;
104
105 /*
106 * The ire is thrown by the container system and propagated by
107 * the server to the stub.
108 */
109 } catch (org.apache.openejb.InvalidateReferenceException ire) {
110 invalidateAllHandlers(getRegistryId());
111 exc = (ire.getRootCause() != null) ? ire.getRootCause() : ire;
112 throw exc;
113 /*
114 * Application exceptions must be reported dirctly to the client. They
115 * do not impact the viability of the proxy.
116 */
117 } catch (org.apache.openejb.ApplicationException ae) {
118 exc = (ae.getRootCause() != null) ? ae.getRootCause() : ae;
119 if (exc instanceof EJBAccessException) {
120 if (interfaceType.isBusiness()) {
121 throw exc;
122 } else {
123 if (interfaceType.isLocal()) {
124 throw new AccessLocalException(exc.getMessage()).initCause(exc.getCause());
125 } else {
126 throw new AccessException(exc.getMessage());
127 }
128 }
129
130 }
131 throw exc;
132
133 /*
134 * A system exception would be highly unusual and would indicate a sever
135 * problem with the container system.
136 */
137 } catch (org.apache.openejb.SystemException se) {
138 invalidateReference();
139 exc = (se.getRootCause() != null) ? se.getRootCause() : se;
140 logger.debug("The container received an unexpected exception: ", exc);
141 throw new RemoteException("Container has suffered a SystemException", exc);
142 } catch (org.apache.openejb.OpenEJBException oe) {
143 exc = (oe.getRootCause() != null) ? oe.getRootCause() : oe;
144 logger.debug("The container received an unexpected exception: ", exc);
145 throw new RemoteException("Unknown Container Exception", oe.getRootCause());
146 } finally {
147 if (logger.isDebugEnabled()) {
148 if (exc == null) {
149 logger.debug("finished invoking method " + m.getName() + ". Return value:" + retValue);
150 } else {
151 logger.debug("finished invoking method " + m.getName() + " with exception " + exc);
152 }
153 }
154 }
155 }
156
157 protected Object getEJBHome(Method method, Object[] args, Object proxy) throws Throwable {
158 checkAuthorization(method);
159 return getDeploymentInfo().getEJBHome();
160 }
161
162 protected Object getEJBLocalHome(Method method, Object[] args, Object proxy) throws Throwable {
163 checkAuthorization(method);
164 return getDeploymentInfo().getEJBLocalHome();
165 }
166
167 protected Object getHandle(Method method, Object[] args, Object proxy) throws Throwable {
168 checkAuthorization(method);
169 return new IntraVmHandle(proxy);
170 }
171
172 public org.apache.openejb.ProxyInfo getProxyInfo() {
173 return new org.apache.openejb.ProxyInfo(getDeploymentInfo(), primaryKey, getInterfaces(), interfaceType);
174 }
175
176 protected Object _writeReplace(Object proxy) throws ObjectStreamException {
177 /*
178 * If the proxy is being copied between bean instances in a RPC
179 * call we use the IntraVmArtifact
180 */
181 if (IntraVmCopyMonitor.isIntraVmCopyOperation()) {
182 return new IntraVmArtifact(proxy);
183 /*
184 * If the proxy is referenced by a stateful bean that is being
185 * passivated by the container we allow this object to be serialized.
186 */
187 } else if (IntraVmCopyMonitor.isStatefulPassivationOperation()) {
188 return proxy;
189 /*
190 * If the proxy is being copied between class loaders
191 * we allow this object to be serialized.
192 */
193 } else if (IntraVmCopyMonitor.isCrossClassLoaderOperation()) {
194 return proxy;
195 /*
196 * If the proxy is serialized outside the core container system,
197 * we allow the application server to handle it.
198 */
199 } else {
200 ApplicationServer applicationServer = ServerFederation.getApplicationServer();
201 if (interfaceType.isBusiness()){
202 return applicationServer.getBusinessObject(this.getProxyInfo());
203 } else {
204 return applicationServer.getEJBObject(this.getProxyInfo());
205 }
206 }
207 }
208
209 protected abstract Object getPrimaryKey(Method method, Object[] args, Object proxy) throws Throwable;
210
211 protected abstract Object isIdentical(Method method, Object[] args, Object proxy) throws Throwable;
212
213 protected abstract Object remove(Class interfce, Method method, Object[] args, Object proxy) throws Throwable;
214
215 protected Object businessMethod(Class interfce, Method method, Object[] args, Object proxy) throws Throwable {
216 // checkAuthorization(method);
217 return container.invoke(deploymentID, interfce, method, args, primaryKey);
218 }
219
220 public static Object createProxy(DeploymentInfo deploymentInfo, Object primaryKey, InterfaceType interfaceType) {
221 return createProxy(deploymentInfo, primaryKey, interfaceType, null);
222 }
223
224 public static Object createProxy(DeploymentInfo deploymentInfo, Object primaryKey, InterfaceType interfaceType, List<Class> interfaces) {
225 if (!interfaceType.isHome()){
226 interfaceType = interfaceType.getCounterpart();
227 }
228 EjbHomeProxyHandler homeHandler = EjbHomeProxyHandler.createHomeHandler(deploymentInfo, interfaceType, interfaces);
229 return homeHandler.createProxy(primaryKey);
230 }
231 }