001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.ejb.burlap;
031:
032: import com.caucho.burlap.client.*;
033: import com.caucho.burlap.io.BurlapRemoteResolver;
034: import com.caucho.config.ConfigException;
035: import com.caucho.ejb.AbstractServer;
036: import com.caucho.ejb.EJBExceptionWrapper;
037: import com.caucho.ejb.protocol.EjbProtocolManager;
038: import com.caucho.ejb.protocol.HandleEncoder;
039: import com.caucho.loader.EnvironmentLocal;
040: import com.caucho.server.util.CauchoSystem;
041: import com.caucho.util.L10N;
042: import com.caucho.vfs.Path;
043: import com.caucho.vfs.Vfs;
044:
045: import javax.ejb.EJBHome;
046: import javax.ejb.EJBObject;
047: import java.io.IOException;
048: import java.util.Hashtable;
049:
050: /**
051: * Container for Burlap clients in the same JVM, but not the same
052: * class loader.
053: */
054: class BurlapClientContainer implements BurlapRemoteResolver {
055: protected static L10N L = new L10N(BurlapClientContainer.class);
056:
057: private static EnvironmentLocal _burlapClient = new EnvironmentLocal(
058: "caucho.burlap.client");
059:
060: private String _serverId;
061: private BurlapHandleEncoder _handleEncoder;
062:
063: private BurlapProxyFactory _proxyFactory;
064: // the home stub
065: EJBHome _ejbHome;
066:
067: Class _homeClass;
068: Class _remoteClass;
069: // the home stub class
070: Class _homeStubClass;
071: // the remote stub class
072: Class _remoteStubClass;
073: // the primary key class
074: Class _primaryKeyClass;
075:
076: private String _basicAuth;
077:
078: /**
079: * Creates a client container for same-JVM connections.
080: *
081: * @param _serverId the server id
082: */
083: BurlapClientContainer(String serverId) throws ConfigException {
084: _serverId = serverId;
085:
086: _proxyFactory = new BurlapProxyFactory();
087: _proxyFactory.setOverloadEnabled(true);
088: }
089:
090: static BurlapClientContainer find(String serverId) {
091: try {
092: Hashtable map = (Hashtable) _burlapClient.getLevel();
093: BurlapClientContainer client = null;
094:
095: if (map != null)
096: client = (BurlapClientContainer) map.get(serverId);
097:
098: // sync doesn't matter since it's okay to load a dup
099: if (client == null) {
100: client = new BurlapClientContainer(serverId);
101: if (map == null)
102: map = new Hashtable();
103: map.put(serverId, client);
104: _burlapClient.set(map);
105: }
106:
107: return client;
108: } catch (Exception e) {
109: throw EJBExceptionWrapper.createRuntime(e);
110: }
111: }
112:
113: /**
114: * Finds the stub corresponding to the given URL.
115: *
116: * @return the bean's home stub
117: */
118: protected EJBHome getHomeStub() throws ConfigException {
119: try {
120: return (EJBHome) _proxyFactory.create(getHomeClass(),
121: _serverId);
122: } catch (Exception e) {
123: throw ConfigException.create(e);
124: }
125: }
126:
127: /**
128: * Finds the stub for the remote object for the given Handle.
129: *
130: * @param handle the handle for the remote object
131: *
132: * @return the bean's remote stub
133: */
134: protected Object createObjectStub(String url)
135: throws ConfigException {
136: try {
137: return _proxyFactory.create(getRemoteClass(), url);
138: } catch (Exception e) {
139: throw ConfigException.create(e);
140: }
141: }
142:
143: BurlapHomeHandle getHomeHandle() {
144: return new BurlapHomeHandle(_ejbHome, _serverId);
145: }
146:
147: BurlapHandle createHandle(String url) {
148: return new BurlapHandle(url);
149: }
150:
151: public HandleEncoder getHandleEncoder() {
152: try {
153: if (_handleEncoder == null)
154: _handleEncoder = new BurlapHandleEncoder(null,
155: _serverId, getPrimaryKeyClass());
156:
157: return _handleEncoder;
158: } catch (Exception e) {
159: throw EJBExceptionWrapper.createRuntime(e);
160: }
161: }
162:
163: /**
164: * Returns the bean's home interface class. If unknown, call the server
165: * for the class name.
166: */
167: Class getHomeClass() throws ConfigException {
168: if (_homeClass != null)
169: return _homeClass;
170:
171: try {
172: synchronized (this ) {
173: if (_homeClass != null)
174: return _homeClass;
175:
176: String className = getHomeClassName();
177:
178: _homeClass = CauchoSystem.loadClass(className, false,
179: null);
180: }
181: } catch (ClassNotFoundException e) {
182: throw ConfigException.create(e);
183: }
184:
185: return _homeClass;
186: }
187:
188: /**
189: * Returns the classname of the home interface.
190: */
191: String getHomeClassName() throws ConfigException {
192: AbstractServer server = EjbProtocolManager
193: .getJVMServer(_serverId);
194:
195: if (server != null) {
196: Class cl = server.getRemoteHomeClass();
197: if (cl != null)
198: return cl.getName();
199: else
200: throw new ConfigException(L.l(
201: "'{0}' has no remote interface.", _serverId));
202: }
203:
204: try {
205: Path path = Vfs.lookup(_serverId);
206:
207: return (String) MetaStub.call(path, "_burlap_getAttribute",
208: "java.home.class");
209: } catch (Throwable e) {
210: throw ConfigException.create(e);
211: }
212: }
213:
214: /**
215: * Returns the bean's remote interface class. If unknown, call the server
216: * for the class name.
217: */
218: Class getRemoteClass() throws ConfigException {
219: if (_remoteClass != null)
220: return _remoteClass;
221:
222: try {
223: synchronized (this ) {
224: if (_remoteClass != null)
225: return _remoteClass;
226:
227: String className = getRemoteClassName();
228:
229: if (className == null || className.equals("null"))
230: return null;
231:
232: _remoteClass = CauchoSystem.loadClass(className, false,
233: null);
234: }
235: } catch (ClassNotFoundException e) {
236: throw ConfigException.create(e);
237: }
238:
239: return _remoteClass;
240: }
241:
242: /**
243: * Returns the classname of the remote interface.
244: */
245: String getRemoteClassName() throws ConfigException {
246: AbstractServer server = EjbProtocolManager
247: .getJVMServer(_serverId);
248:
249: if (server != null) {
250: Class cl = server.getRemoteObjectClass();
251: if (cl != null)
252: return cl.getName();
253: else
254: throw new ConfigException(L.l(
255: "`{0}' has no remote interface.", _serverId));
256: }
257:
258: try {
259: Path path = Vfs.lookup(_serverId);
260:
261: return (String) MetaStub.call(path, "_burlap_getAttribute",
262: "java.object.class");
263: } catch (Throwable e) {
264: throw ConfigException.create(e);
265: }
266: }
267:
268: /**
269: * Returns the bean's primary key class. If unknown, call the server
270: * for the class name.
271: */
272: Class getPrimaryKeyClass() throws ConfigException {
273: if (_primaryKeyClass != null)
274: return _primaryKeyClass;
275:
276: try {
277: synchronized (this ) {
278: if (_primaryKeyClass != null)
279: return _primaryKeyClass;
280:
281: String className = getPrimaryKeyClassName();
282:
283: _primaryKeyClass = CauchoSystem.loadClass(className,
284: false, null);
285: }
286: } catch (ClassNotFoundException e) {
287: throw ConfigException.create(e);
288: }
289:
290: return _primaryKeyClass;
291: }
292:
293: /**
294: * Returns the classname of the home interface.
295: */
296: String getPrimaryKeyClassName() throws ConfigException {
297: AbstractServer server = EjbProtocolManager
298: .getJVMServer(_serverId);
299:
300: if (server != null) {
301: Class cl = server.getPrimaryKeyClass();
302: if (cl != null)
303: return cl.getName();
304: else
305: throw new ConfigException(L.l(
306: "`{0}' has no remote interface.", _serverId));
307: }
308:
309: try {
310: Path path = Vfs.lookup(_serverId);
311:
312: return (String) MetaStub.call(path, "_burlap_getAttribute",
313: "primary-key-class");
314: } catch (Throwable e) {
315: throw ConfigException.create(e);
316: }
317: }
318:
319: /**
320: * Looks up a proxy object.
321: */
322: public Object lookup(String type, String url) throws IOException {
323: try {
324: Class api = CauchoSystem.loadClass(type);
325:
326: return create(api, url);
327: } catch (Exception e) {
328: throw new IOException(String.valueOf(e));
329: }
330: }
331:
332: /**
333: * Creates a new proxy with the specified URL. The returned object
334: * is a proxy with the interface specified by api.
335: *
336: * <pre>
337: * String url = "http://localhost:8080/ejb/hello");
338: * HelloHome hello = (HelloHome) factory.create(HelloHome.class, url);
339: * </pre>
340: *
341: * @param api the interface the proxy class needs to implement
342: * @param url the URL where the client object is located.
343: *
344: * @return a proxy to the object with the specified interface.
345: */
346: public Object create(Class api, String url) throws Exception {
347: return _proxyFactory.create(api, url);
348: }
349:
350: /**
351: * Returns the basic auth.
352: */
353: String getBasicAuthentication() {
354: return _basicAuth;
355: }
356:
357: /**
358: * Sets the basic auth.
359: */
360: void setBasicAuthentication(String auth) {
361: if (auth != null)
362: _basicAuth = "Basic " + auth;
363: else
364: _basicAuth = auth;
365: }
366:
367: /**
368: * Returns a printable version of the client container
369: */
370: public String toString() {
371: return "BurlapClientContainer[" + _serverId + "]";
372: }
373: }
|