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.core.ivm;
017:
018: import java.io.ObjectStreamException;
019: import java.lang.reflect.Method;
020: import java.rmi.AccessException;
021: import java.rmi.RemoteException;
022: import java.util.List;
023:
024: import javax.ejb.AccessLocalException;
025: import javax.ejb.EJBAccessException;
026: import javax.ejb.EJBLocalObject;
027: import javax.ejb.EJBObject;
028:
029: import org.apache.openejb.DeploymentInfo;
030: import org.apache.openejb.InterfaceType;
031: import org.apache.openejb.core.ServerFederation;
032: import org.apache.openejb.spi.ApplicationServer;
033: import org.apache.openejb.util.LogCategory;
034: import org.apache.openejb.util.Logger;
035:
036: public abstract class EjbObjectProxyHandler extends BaseEjbProxyHandler {
037: private static final Logger logger = Logger.getInstance(
038: LogCategory.OPENEJB, "org.apache.openejb.util.resources");
039: static final java.util.HashMap dispatchTable;
040:
041: static {
042: dispatchTable = new java.util.HashMap();
043: dispatchTable.put("getHandle", new Integer(1));
044: dispatchTable.put("getPrimaryKey", new Integer(2));
045: dispatchTable.put("isIdentical", new Integer(3));
046: dispatchTable.put("remove", new Integer(4));
047: dispatchTable.put("getEJBHome", new Integer(5));
048: dispatchTable.put("getEJBLocalHome", new Integer(6));
049:
050: }
051:
052: public EjbObjectProxyHandler(DeploymentInfo deploymentInfo,
053: Object pk, InterfaceType interfaceType,
054: List<Class> interfaces) {
055: super (deploymentInfo, pk, interfaceType, interfaces);
056: }
057:
058: public abstract Object getRegistryId();
059:
060: public Object _invoke(Object p, Class interfce, Method m, Object[] a)
061: throws Throwable {
062: java.lang.Object retValue = null;
063: java.lang.Throwable exc = null;
064:
065: try {
066: if (logger.isDebugEnabled()) {
067: logger
068: .debug("invoking method " + m.getName()
069: + " on " + deploymentID
070: + " with identity " + primaryKey);
071: }
072: Integer operation = (Integer) dispatchTable
073: .get(m.getName());
074: if (operation != null) {
075: if (operation.intValue() == 3) {
076: if (m.getParameterTypes()[0] != EJBObject.class
077: && m.getParameterTypes()[0] != EJBLocalObject.class) {
078: operation = null;
079: }
080: } else {
081: operation = (m.getParameterTypes().length == 0) ? operation
082: : null;
083: }
084: }
085: if (operation == null || !interfaceType.isComponent()) {
086: retValue = businessMethod(interfce, m, a, p);
087: } else {
088: switch (operation.intValue()) {
089: case 1:
090: retValue = getHandle(m, a, p);
091: break;
092: case 2:
093: retValue = getPrimaryKey(m, a, p);
094: break;
095: case 3:
096: retValue = isIdentical(m, a, p);
097: break;
098: case 4:
099: retValue = remove(interfce, m, a, p);
100: break;
101: case 5:
102: retValue = getEJBHome(m, a, p);
103: break;
104: case 6:
105: retValue = getEJBLocalHome(m, a, p);
106: break;
107: default:
108: throw new RuntimeException(
109: "Inconsistent internal state");
110: }
111: }
112:
113: return retValue;
114:
115: /*
116: * The ire is thrown by the container system and propagated by
117: * the server to the stub.
118: */
119: } catch (org.apache.openejb.InvalidateReferenceException ire) {
120: invalidateAllHandlers(getRegistryId());
121: exc = (ire.getRootCause() != null) ? ire.getRootCause()
122: : ire;
123: throw exc;
124: /*
125: * Application exceptions must be reported dirctly to the client. They
126: * do not impact the viability of the proxy.
127: */
128: } catch (org.apache.openejb.ApplicationException ae) {
129: exc = (ae.getRootCause() != null) ? ae.getRootCause() : ae;
130: if (exc instanceof EJBAccessException) {
131: if (interfaceType.isBusiness()) {
132: throw exc;
133: } else {
134: if (interfaceType.isLocal()) {
135: throw new AccessLocalException(exc.getMessage())
136: .initCause(exc.getCause());
137: } else {
138: throw new AccessException(exc.getMessage());
139: }
140: }
141:
142: }
143: throw exc;
144:
145: /*
146: * A system exception would be highly unusual and would indicate a sever
147: * problem with the container system.
148: */
149: } catch (org.apache.openejb.SystemException se) {
150: invalidateReference();
151: exc = (se.getRootCause() != null) ? se.getRootCause() : se;
152: logger.debug(
153: "The container received an unexpected exception: ",
154: exc);
155: throw new RemoteException(
156: "Container has suffered a SystemException", exc);
157: } catch (org.apache.openejb.OpenEJBException oe) {
158: exc = (oe.getRootCause() != null) ? oe.getRootCause() : oe;
159: logger.debug(
160: "The container received an unexpected exception: ",
161: exc);
162: throw new RemoteException("Unknown Container Exception", oe
163: .getRootCause());
164: } finally {
165: if (logger.isDebugEnabled()) {
166: if (exc == null) {
167: logger.debug("finished invoking method "
168: + m.getName() + ". Return value:"
169: + retValue);
170: } else {
171: logger.debug("finished invoking method "
172: + m.getName() + " with exception " + exc);
173: }
174: }
175: }
176: }
177:
178: protected Object getEJBHome(Method method, Object[] args,
179: Object proxy) throws Throwable {
180: checkAuthorization(method);
181: return getDeploymentInfo().getEJBHome();
182: }
183:
184: protected Object getEJBLocalHome(Method method, Object[] args,
185: Object proxy) throws Throwable {
186: checkAuthorization(method);
187: return getDeploymentInfo().getEJBLocalHome();
188: }
189:
190: protected Object getHandle(Method method, Object[] args,
191: Object proxy) throws Throwable {
192: checkAuthorization(method);
193: return new IntraVmHandle(proxy);
194: }
195:
196: public org.apache.openejb.ProxyInfo getProxyInfo() {
197: return new org.apache.openejb.ProxyInfo(getDeploymentInfo(),
198: primaryKey, getInterfaces(), interfaceType);
199: }
200:
201: protected Object _writeReplace(Object proxy)
202: throws ObjectStreamException {
203: /*
204: * If the proxy is being copied between bean instances in a RPC
205: * call we use the IntraVmArtifact
206: */
207: if (IntraVmCopyMonitor.isIntraVmCopyOperation()) {
208: return new IntraVmArtifact(proxy);
209: /*
210: * If the proxy is referenced by a stateful bean that is being
211: * passivated by the container we allow this object to be serialized.
212: */
213: } else if (IntraVmCopyMonitor.isStatefulPassivationOperation()) {
214: return proxy;
215: /*
216: * If the proxy is being copied between class loaders
217: * we allow this object to be serialized.
218: */
219: } else if (IntraVmCopyMonitor.isCrossClassLoaderOperation()) {
220: return proxy;
221: /*
222: * If the proxy is serialized outside the core container system,
223: * we allow the application server to handle it.
224: */
225: } else {
226: ApplicationServer applicationServer = ServerFederation
227: .getApplicationServer();
228: if (interfaceType.isBusiness()) {
229: return applicationServer.getBusinessObject(this
230: .getProxyInfo());
231: } else {
232: return applicationServer.getEJBObject(this
233: .getProxyInfo());
234: }
235: }
236: }
237:
238: protected abstract Object getPrimaryKey(Method method,
239: Object[] args, Object proxy) throws Throwable;
240:
241: protected abstract Object isIdentical(Method method, Object[] args,
242: Object proxy) throws Throwable;
243:
244: protected abstract Object remove(Class interfce, Method method,
245: Object[] args, Object proxy) throws Throwable;
246:
247: protected Object businessMethod(Class interfce, Method method,
248: Object[] args, Object proxy) throws Throwable {
249: // checkAuthorization(method);
250: return container.invoke(deploymentID, interfce, method, args,
251: primaryKey);
252: }
253:
254: public static Object createProxy(DeploymentInfo deploymentInfo,
255: Object primaryKey, InterfaceType interfaceType) {
256: return createProxy(deploymentInfo, primaryKey, interfaceType,
257: null);
258: }
259:
260: public static Object createProxy(DeploymentInfo deploymentInfo,
261: Object primaryKey, InterfaceType interfaceType,
262: List<Class> interfaces) {
263: if (!interfaceType.isHome()) {
264: interfaceType = interfaceType.getCounterpart();
265: }
266: EjbHomeProxyHandler homeHandler = EjbHomeProxyHandler
267: .createHomeHandler(deploymentInfo, interfaceType,
268: interfaces);
269: return homeHandler.createProxy(primaryKey);
270: }
271: }
|