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.client;
017:
018: import org.apache.openejb.client.proxy.ProxyManager;
019:
020: import javax.ejb.EJBException;
021: import javax.ejb.EJBObject;
022: import java.lang.reflect.Method;
023: import java.rmi.RemoteException;
024: import java.util.ArrayList;
025: import java.util.List;
026:
027: public abstract class EJBObjectHandler extends EJBInvocationHandler {
028:
029: protected static final Method GETEJBHOME = getMethod(
030: EJBObject.class, "getEJBHome", null);
031: protected static final Method GETHANDLE = getMethod(
032: EJBObject.class, "getHandle", null);
033: protected static final Method GETPRIMARYKEY = getMethod(
034: EJBObject.class, "getPrimaryKey", null);
035: protected static final Method ISIDENTICAL = getMethod(
036: EJBObject.class, "isIdentical",
037: new Class[] { EJBObject.class });
038: protected static final Method REMOVE = getMethod(EJBObject.class,
039: "remove", null);
040:
041: protected static final Method GETHANDLER = getMethod(
042: EJBObjectProxy.class, "getEJBObjectHandler", null);
043:
044: /*
045: * The registryId is a logical identifier that is used as a key when placing EntityEJBObjectHandler into
046: * the BaseEjbProxyHanlder's liveHandleRegistry. EntityEJBObjectHandlers that represent the same
047: * bean identity (keyed by the registry id) will be stored together so that they can be removed together
048: * when the EJBInvocationHandler.invalidateAllHandlers is invoked. The EntityEJBObjectHandler uses a
049: * compound key composed of the entity bean's primary key, deployment id, and
050: * container id. This uniquely identifies the bean identity that is proxied by this handler allowing it
051: * to be removed with other handlers bound to the same registry id.
052: */
053: public Object registryId;
054:
055: EJBHomeProxy ejbHome = null;
056:
057: public EJBObjectHandler() {
058: }
059:
060: public EJBObjectHandler(EJBMetaDataImpl ejb, ServerMetaData server,
061: ClientMetaData client) {
062: super (ejb, server, client);
063: }
064:
065: public EJBObjectHandler(EJBMetaDataImpl ejb, ServerMetaData server,
066: ClientMetaData client, Object primaryKey) {
067: super (ejb, server, client, primaryKey);
068: }
069:
070: protected void setEJBHomeProxy(EJBHomeProxy ejbHome) {
071: this .ejbHome = ejbHome;
072: }
073:
074: public static EJBObjectHandler createEJBObjectHandler(
075: EJBMetaDataImpl ejb, ServerMetaData server,
076: ClientMetaData client, Object primaryKey) {
077:
078: switch (ejb.type) {
079: case EJBMetaDataImpl.BMP_ENTITY:
080: case EJBMetaDataImpl.CMP_ENTITY:
081:
082: return new EntityEJBObjectHandler(ejb, server, client,
083: primaryKey);
084:
085: case EJBMetaDataImpl.STATEFUL:
086:
087: return new StatefulEJBObjectHandler(ejb, server, client,
088: primaryKey);
089:
090: case EJBMetaDataImpl.STATELESS:
091:
092: return new StatelessEJBObjectHandler(ejb, server, client,
093: primaryKey);
094: }
095: return null;
096: }
097:
098: public abstract Object getRegistryId();
099:
100: public EJBObjectProxy createEJBObjectProxy() {
101:
102: EJBObjectProxy ejbObject = null;
103:
104: try {
105: List<Class> interfaces = new ArrayList<Class>();
106: // Interface class must be listed first, before EJBObjectProxy,
107: // otherwise the proxy code will selectï the openejb system class
108: // loader for proxy creation instead of the application class loader
109: if (ejb.remoteClass != null) {
110: interfaces.add(ejb.remoteClass);
111: } else if (ejb.businessClasses.size() > 0) {
112: interfaces.addAll(ejb.businessClasses);
113: }
114: interfaces.add(EJBObjectProxy.class);
115: ejbObject = (EJBObjectProxy) ProxyManager.newProxyInstance(
116: interfaces.toArray(new Class[] {}), this );
117:
118: } catch (IllegalAccessException e) {
119:
120: e.printStackTrace();
121: }
122: return ejbObject;
123: }
124:
125: public synchronized Object _invoke(Object p, Method m, Object[] a)
126: throws Throwable {
127:
128: Object retValue = null;
129: /*
130: * This section is to be replaced by a more appropriate solution.
131: * This code is very temporary.
132: */
133:
134: try {
135: String methodName = m.getName();
136: if (m.getDeclaringClass().equals(Object.class)) {
137: if (m.equals(TOSTRING)) {
138: return "proxy=" + this ;
139: } else if (m.equals(EQUALS)) {
140:
141: return equals(m, a, p);
142:
143: } else if (m.equals(HASHCODE)) {
144: return new Integer(this .hashCode());
145: } else {
146: throw new UnsupportedOperationException(
147: "Unkown method: " + m);
148: }
149: } else if (m.getDeclaringClass() == EJBObjectProxy.class) {
150: if (m.equals(GETHANDLER)) {
151: return this ;
152: } else if (methodName.equals("writeReplace")) {
153: return new EJBObjectProxyHandle(this );
154: } else if (methodName.equals("readResolve")) {
155:
156: } else {
157: throw new UnsupportedOperationException(
158: "Unkown method: " + m);
159: }
160: } else if (m.getDeclaringClass() == javax.ejb.EJBObject.class) {
161: if (m.equals(GETHANDLE))
162: retValue = getHandle(m, a, p);
163: else if (m.equals(GETPRIMARYKEY))
164: retValue = getPrimaryKey(m, a, p);
165: else if (m.equals(ISIDENTICAL))
166: retValue = isIdentical(m, a, p);
167: else if (m.equals(GETEJBHOME))
168: retValue = getEJBHome(m, a, p);
169: else if (m.equals(REMOVE))
170: retValue = remove(m, a, p);
171: else
172: throw new UnsupportedOperationException(
173: "Unkown method: " + m);
174: } else {
175: retValue = businessMethod(m, a, p);
176: }
177:
178: } catch (SystemException e) {
179: invalidateAllHandlers(getRegistryId());
180: throw convertException(e.getCause(), m);
181: /*
182: * Application exceptions must be reported dirctly to the client. They
183: * do not impact the viability of the proxy.
184: */
185: } catch (ApplicationException ae) {
186: throw convertException(ae.getCause(), m);
187: /*
188: * A system exception would be highly unusual and would indicate a sever
189: * problem with the container system.
190: */
191: } catch (SystemError se) {
192: invalidateReference();
193: if (remote) {
194: throw new RemoteException(
195: "Container has suffered a SystemException", se
196: .getCause());
197: } else {
198: throw new EJBException(
199: "Container has suffered a SystemException")
200: .initCause(se.getCause());
201: }
202: } catch (Throwable oe) {
203: if (remote) {
204: throw new RemoteException(
205: "Unknown Container Exception: "
206: + oe.getClass().getName() + ": "
207: + oe.getMessage(), oe.getCause());
208: } else {
209: throw new EJBException("Unknown Container Exception: "
210: + oe.getClass().getName() + ": "
211: + oe.getMessage()).initCause(oe.getCause());
212: }
213: }
214: return retValue;
215: }
216:
217: protected Object getEJBHome(Method method, Object[] args,
218: Object proxy) throws Throwable {
219: if (ejbHome == null) {
220: ejbHome = EJBHomeHandler.createEJBHomeHandler(ejb, server,
221: client).createEJBHomeProxy();
222: }
223: return ejbHome;
224: }
225:
226: protected Object getHandle(Method method, Object[] args,
227: Object proxy) throws Throwable {
228: return new EJBObjectHandle((EJBObjectProxy) proxy);
229: }
230:
231: protected abstract Object getPrimaryKey(Method method,
232: Object[] args, Object proxy) throws Throwable;
233:
234: protected abstract Object isIdentical(Method method, Object[] args,
235: Object proxy) throws Throwable;
236:
237: protected abstract Object equals(Method method, Object[] args,
238: Object proxy) throws Throwable;
239:
240: protected abstract Object remove(Method method, Object[] args,
241: Object proxy) throws Throwable;
242:
243: protected Object businessMethod(Method method, Object[] args,
244: Object proxy) throws Throwable {
245: // checkAuthorization(method);
246: // return container.invoke(deploymentID, method, args, primaryKey, getThreadSpecificSecurityIdentity());
247:
248: EJBRequest req = new EJBRequest(
249: RequestMethodConstants.EJB_OBJECT_BUSINESS_METHOD, ejb,
250: method, args, primaryKey);
251:
252: EJBResponse res = request(req);
253:
254: // if (method.getName().equals("test36_returnEJBHome2")) {
255: // System.out.println("\n\n----------------------------------------------------------");
256: // System.out.println(method.getName());
257: // Object obj = res.getResult();
258: // System.out.println("obj="+(obj==null));
259: // System.out.println("obj="+(obj.getClass()));
260: // System.out.println("obj="+(obj.getClass().getDeclaringClass()));
261: // Class[] ifs = obj.getClass().getInterfaces();
262: // for (int i=0; i < ifs.length; i++){
263: // System.out.println("ifs["+i+"] "+ifs[i]);
264: // }
265: // }
266: switch (res.getResponseCode()) {
267: case ResponseCodes.EJB_ERROR:
268: throw new SystemError((ThrowableArtifact) res.getResult());
269: case ResponseCodes.EJB_SYS_EXCEPTION:
270: throw new SystemException((ThrowableArtifact) res
271: .getResult());
272: case ResponseCodes.EJB_APP_EXCEPTION:
273: throw new ApplicationException((ThrowableArtifact) res
274: .getResult());
275: case ResponseCodes.EJB_OK:
276: return res.getResult();
277: default:
278: throw new RemoteException(
279: "Received invalid response code from server: "
280: + res.getResponseCode());
281: }
282: }
283:
284: }
|