001 /*
002 * Copyright 1998-2004 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025 /*
026 * Licensed Materials - Property of IBM
027 * RMI-IIOP v1.0
028 * Copyright IBM Corp. 1998 1999 All Rights Reserved
029 *
030 */
031
032 package javax.rmi;
033
034 import java.lang.reflect.Method;
035
036 import org.omg.CORBA.INITIALIZE;
037 import javax.rmi.CORBA.Util;
038
039 import java.rmi.RemoteException;
040 import java.rmi.NoSuchObjectException;
041 import java.rmi.Remote;
042 import java.io.File;
043 import java.io.FileInputStream;
044 import java.util.Properties;
045 import java.net.MalformedURLException;
046 import java.security.AccessController;
047 import java.security.PrivilegedAction;
048 import java.rmi.server.RMIClassLoader;
049
050 import com.sun.corba.se.impl.orbutil.GetPropertyAction;
051
052 /**
053 * Server implementation objects may either inherit from
054 * javax.rmi.PortableRemoteObject or they may implement a remote interface
055 * and then use the exportObject method to register themselves as a server object.
056 * The toStub method takes a server implementation and returns a stub that
057 * can be used to access that server object.
058 * The connect method makes a Remote object ready for remote communication.
059 * The unexportObject method is used to deregister a server object, allowing it to become
060 * available for garbage collection.
061 * The narrow method takes an object reference or abstract interface type and
062 * attempts to narrow it to conform to
063 * the given interface. If the operation is successful the result will be an
064 * object of the specified type, otherwise an exception will be thrown.
065 */
066 public class PortableRemoteObject {
067
068 private static javax.rmi.CORBA.PortableRemoteObjectDelegate proDelegate = null;
069
070 private static final String PortableRemoteObjectClassKey = "javax.rmi.CORBA.PortableRemoteObjectClass";
071
072 private static final String defaultPortableRemoteObjectImplName = "com.sun.corba.se.impl.javax.rmi.PortableRemoteObject";
073
074 static {
075 proDelegate = (javax.rmi.CORBA.PortableRemoteObjectDelegate) createDelegateIfSpecified(PortableRemoteObjectClassKey);
076 }
077
078 /**
079 * Initializes the object by calling <code>exportObject(this)</code>.
080 * @exception RemoteException if export fails.
081 */
082 protected PortableRemoteObject() throws RemoteException {
083 if (proDelegate != null) {
084 PortableRemoteObject.exportObject((Remote) this );
085 }
086 }
087
088 /**
089 * Makes a server object ready to receive remote calls. Note
090 * that subclasses of PortableRemoteObject do not need to call this
091 * method, as it is called by the constructor.
092 * @param obj the server object to export.
093 * @exception RemoteException if export fails.
094 */
095 public static void exportObject(Remote obj) throws RemoteException {
096
097 // Let the delegate do everything, including error handling.
098 if (proDelegate != null) {
099 proDelegate.exportObject(obj);
100 }
101 }
102
103 /**
104 * Returns a stub for the given server object.
105 * @param obj the server object for which a stub is required. Must either be a subclass
106 * of PortableRemoteObject or have been previously the target of a call to
107 * {@link #exportObject}.
108 * @return the most derived stub for the object.
109 * @exception NoSuchObjectException if a stub cannot be located for the given server object.
110 */
111 public static Remote toStub(Remote obj)
112 throws NoSuchObjectException {
113
114 if (proDelegate != null) {
115 return proDelegate.toStub(obj);
116 }
117 return null;
118 }
119
120 /**
121 * Deregisters a server object from the runtime, allowing the object to become
122 * available for garbage collection.
123 * @param obj the object to unexport.
124 * @exception NoSuchObjectException if the remote object is not
125 * currently exported.
126 */
127 public static void unexportObject(Remote obj)
128 throws NoSuchObjectException {
129
130 if (proDelegate != null) {
131 proDelegate.unexportObject(obj);
132 }
133
134 }
135
136 /**
137 * Checks to ensure that an object of a remote or abstract interface type
138 * can be cast to a desired type.
139 * @param narrowFrom the object to check.
140 * @param narrowTo the desired type.
141 * @return an object which can be cast to the desired type.
142 * @throws ClassCastException if narrowFrom cannot be cast to narrowTo.
143 */
144 public static java.lang.Object narrow(java.lang.Object narrowFrom,
145 java.lang.Class narrowTo) throws ClassCastException {
146
147 if (proDelegate != null) {
148 return proDelegate.narrow(narrowFrom, narrowTo);
149 }
150 return null;
151
152 }
153
154 /**
155 * Makes a Remote object ready for remote communication. This normally
156 * happens implicitly when the object is sent or received as an argument
157 * on a remote method call, but in some circumstances it is useful to
158 * perform this action by making an explicit call. See the
159 * {@link Stub#connect} method for more information.
160 * @param target the object to connect.
161 * @param source a previously connected object.
162 * @throws RemoteException if <code>source</code> is not connected
163 * or if <code>target</code> is already connected to a different ORB than
164 * <code>source</code>.
165 */
166 public static void connect(Remote target, Remote source)
167 throws RemoteException {
168
169 if (proDelegate != null) {
170 proDelegate.connect(target, source);
171 }
172
173 }
174
175 // Same code as in javax.rmi.CORBA.Util. Can not be shared because they
176 // are in different packages and the visibility needs to be package for
177 // security reasons. If you know a better solution how to share this code
178 // then remove it from here.
179 private static Object createDelegateIfSpecified(String classKey) {
180 String className = (String) AccessController
181 .doPrivileged(new GetPropertyAction(classKey));
182 if (className == null) {
183 Properties props = getORBPropertiesFile();
184 if (props != null) {
185 className = props.getProperty(classKey);
186 }
187 }
188 if (className == null) {
189 className = defaultPortableRemoteObjectImplName;
190 }
191
192 try {
193 return (Object) loadDelegateClass(className).newInstance();
194 } catch (ClassNotFoundException ex) {
195 INITIALIZE exc = new INITIALIZE("Cannot instantiate "
196 + className);
197 exc.initCause(ex);
198 throw exc;
199 } catch (Exception ex) {
200 INITIALIZE exc = new INITIALIZE("Error while instantiating"
201 + className);
202 exc.initCause(ex);
203 throw exc;
204 }
205
206 }
207
208 private static Class loadDelegateClass(String className)
209 throws ClassNotFoundException {
210 try {
211 ClassLoader loader = Thread.currentThread()
212 .getContextClassLoader();
213 return Class.forName(className, false, loader);
214 } catch (ClassNotFoundException e) {
215 // ignore, then try RMIClassLoader
216 }
217
218 try {
219 return RMIClassLoader.loadClass(className);
220 } catch (MalformedURLException e) {
221 String msg = "Could not load " + className + ": "
222 + e.toString();
223 ClassNotFoundException exc = new ClassNotFoundException(msg);
224 throw exc;
225 }
226 }
227
228 /**
229 * Load the orb.properties file.
230 */
231 private static Properties getORBPropertiesFile() {
232 return (Properties) AccessController
233 .doPrivileged(new GetORBPropertiesFileAction());
234 }
235 }
236
237 class GetORBPropertiesFileAction implements PrivilegedAction {
238 private boolean debug = false;
239
240 public GetORBPropertiesFileAction() {
241 }
242
243 private String getSystemProperty(final String name) {
244 // This will not throw a SecurityException because this
245 // class was loaded from rt.jar using the bootstrap classloader.
246 String propValue = (String) AccessController
247 .doPrivileged(new PrivilegedAction() {
248 public java.lang.Object run() {
249 return System.getProperty(name);
250 }
251 });
252
253 return propValue;
254 }
255
256 private void getPropertiesFromFile(Properties props, String fileName) {
257 try {
258 File file = new File(fileName);
259 if (!file.exists())
260 return;
261
262 FileInputStream in = new FileInputStream(file);
263
264 try {
265 props.load(in);
266 } finally {
267 in.close();
268 }
269 } catch (Exception exc) {
270 if (debug)
271 System.out.println("ORB properties file " + fileName
272 + " not found: " + exc);
273 }
274 }
275
276 public Object run() {
277 Properties defaults = new Properties();
278
279 String javaHome = getSystemProperty("java.home");
280 String fileName = javaHome + File.separator + "lib"
281 + File.separator + "orb.properties";
282
283 getPropertiesFromFile(defaults, fileName);
284
285 Properties results = new Properties(defaults);
286
287 String userHome = getSystemProperty("user.home");
288 fileName = userHome + File.separator + "orb.properties";
289
290 getPropertiesFromFile(results, fileName);
291 return results;
292 }
293 }
|