001: /**
002: * EasyBeans
003: * Copyright (C) 2006 Bull S.A.S.
004: * Contact: easybeans@ow2.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: ProDelegate.java 2044 2007-11-16 15:21:54Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.ow2.easybeans.component.smartclient.spi;
025:
026: import java.rmi.NoSuchObjectException;
027: import java.rmi.Remote;
028: import java.rmi.RemoteException;
029: import java.util.logging.Level;
030: import java.util.logging.Logger;
031:
032: import javax.rmi.CORBA.PortableRemoteObjectDelegate;
033:
034: /**
035: * Implementation of the prodelegate class that will redirect to the carol class
036: * by using the correct classloader mechanism.
037: * @author Florent Benoit
038: */
039: public class ProDelegate implements PortableRemoteObjectDelegate {
040:
041: /**
042: * Use the JDK logger (to avoid any dependency).
043: */
044: private static Logger logger = Logger.getLogger(ProDelegate.class
045: .getName());
046:
047: /**
048: * Carol ProDelegate class.
049: */
050: private static final String CAROL_PRO_DELEGATE = "org.objectweb.carol.rmi.multi.MultiPRODelegate";
051:
052: /**
053: * Reference to the classloader to use. This classloader will be set by the
054: * EasyBeans smartclient factory.
055: */
056: private static ClassLoader classLoader;
057:
058: /**
059: * Wrapped reference of the carol PortableRemoteObjectDelegate class.
060: */
061: private PortableRemoteObjectDelegate wrapped = null;
062:
063: /**
064: * Gets the Carol wrapping class.
065: */
066: public ProDelegate() {
067: ClassLoader old = Thread.currentThread()
068: .getContextClassLoader();
069: Thread.currentThread().setContextClassLoader(classLoader);
070: try {
071: Class<?> clazz = null;
072: try {
073: clazz = classLoader.loadClass(CAROL_PRO_DELEGATE);
074: } catch (ClassNotFoundException e) {
075: throw new IllegalStateException("Cannot find the '"
076: + CAROL_PRO_DELEGATE + "' class.", e);
077: }
078: try {
079: wrapped = (PortableRemoteObjectDelegate) clazz
080: .newInstance();
081: } catch (InstantiationException e) {
082: throw new IllegalStateException(
083: "Cannot build an instance of the '"
084: + CAROL_PRO_DELEGATE + "' class.", e);
085: } catch (IllegalAccessException e) {
086: throw new IllegalStateException(
087: "Cannot build an instance of the '"
088: + CAROL_PRO_DELEGATE + "' class.", e);
089: }
090: } finally {
091: Thread.currentThread().setContextClassLoader(old);
092: }
093: }
094:
095: /**
096: * Check if there is a classloader.
097: */
098: private void check() {
099: if (classLoader == null) {
100: throw new IllegalStateException(
101: "No classloader was set previously. Invalid call.");
102: }
103:
104: }
105:
106: /**
107: * Makes a Remote object ready for remote communication. This normally
108: * happens implicitly when the object is sent or received as an argument on
109: * a remote method call, but in some circumstances it is useful to perform
110: * this action by making an explicit call.
111: * @param target the object to connect.
112: * @param source a previously connected object.
113: * @throws RemoteException if <code>source</code> is not connected or if
114: * <code>target</code> is already connected to a different ORB
115: * than <code>source</code>.
116: */
117: public void connect(final Remote target, final Remote source)
118: throws RemoteException {
119: check();
120: if (logger.isLoggable(Level.FINE)) {
121: logger.log(Level.FINE, "connect '" + target + "' with '"
122: + source + "'.");
123: }
124: ClassLoader old = Thread.currentThread()
125: .getContextClassLoader();
126: Thread.currentThread().setContextClassLoader(classLoader);
127: try {
128: wrapped.connect(target, source);
129: } finally {
130: Thread.currentThread().setContextClassLoader(old);
131: }
132:
133: }
134:
135: /**
136: * Makes a server object ready to receive remote calls. Note that subclasses
137: * of PortableRemoteObject do not need to call this method, as it is called
138: * by the constructor.
139: * @param obj the server object to export.
140: * @exception RemoteException if export fails.
141: */
142: public void exportObject(final Remote obj) throws RemoteException {
143: check();
144: if (logger.isLoggable(Level.FINE)) {
145: logger.log(Level.FINE, "exportObject '" + obj + "'.");
146: }
147: ClassLoader old = Thread.currentThread()
148: .getContextClassLoader();
149: Thread.currentThread().setContextClassLoader(classLoader);
150: try {
151: wrapped.exportObject(obj);
152: } finally {
153: Thread.currentThread().setContextClassLoader(old);
154: }
155:
156: }
157:
158: /**
159: * Checks to ensure that an object of a remote or abstract interface type
160: * can be cast to a desired type.
161: * @param narrowFrom the object to check.
162: * @param narrowTo the desired type.
163: * @return an object which can be cast to the desired type.
164: * @throws ClassCastException if narrowFrom cannot be cast to narrowTo.
165: */
166: @SuppressWarnings("unchecked")
167: public Object narrow(final Object narrowFrom, final Class narrowTo)
168: throws ClassCastException {
169: check();
170: if (logger.isLoggable(Level.FINE)) {
171: logger.log(Level.FINE, "Narrowing '" + narrowFrom
172: + "' to '" + narrowTo + "'.");
173: }
174: ClassLoader old = Thread.currentThread()
175: .getContextClassLoader();
176: Thread.currentThread().setContextClassLoader(classLoader);
177: try {
178: return wrapped.narrow(narrowFrom, narrowTo);
179: } finally {
180: Thread.currentThread().setContextClassLoader(old);
181: }
182: }
183:
184: /**
185: * Returns a stub for the given server object.
186: * @param obj the server object for which a stub is required. Must either be
187: * a subclass of PortableRemoteObject or have been previously the
188: * target of a call to {@link #exportObject}.
189: * @return the most derived stub for the object.
190: * @exception NoSuchObjectException if a stub cannot be located for the
191: * given server object.
192: */
193: public Remote toStub(final Remote obj) throws NoSuchObjectException {
194: check();
195: if (logger.isLoggable(Level.FINE)) {
196: logger.log(Level.FINE, "toStub '" + obj + "'.");
197: }
198: ClassLoader old = Thread.currentThread()
199: .getContextClassLoader();
200: Thread.currentThread().setContextClassLoader(classLoader);
201: try {
202: return wrapped.toStub(obj);
203: } finally {
204: Thread.currentThread().setContextClassLoader(old);
205: }
206: }
207:
208: /**
209: * Deregisters a server object from the runtime, allowing the object to
210: * become available for garbage collection.
211: * @param obj the object to unexport.
212: * @exception NoSuchObjectException if the remote object is not currently
213: * exported.
214: */
215: public void unexportObject(final Remote obj)
216: throws NoSuchObjectException {
217: check();
218: if (logger.isLoggable(Level.FINE)) {
219: logger.log(Level.FINE, "unexportObject '" + obj + "'.");
220: }
221: ClassLoader old = Thread.currentThread()
222: .getContextClassLoader();
223: Thread.currentThread().setContextClassLoader(classLoader);
224: try {
225: wrapped.unexportObject(obj);
226: } finally {
227: Thread.currentThread().setContextClassLoader(old);
228: }
229: }
230:
231: /**
232: * Sets the ClassLoader to use.
233: * @param cl the ClassLoader to use.
234: */
235: public static void setClassLoader(final ClassLoader cl) {
236: classLoader = cl;
237: }
238:
239: }
|