1 /* 2 * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.rmi.server; 26 27 import java.io.ObjectInputFilter; 28 import java.rmi.*; 29 import sun.rmi.server.UnicastServerRef; 30 import sun.rmi.server.UnicastServerRef2; 31 import sun.rmi.transport.LiveRef; 32 33 /** 34 * Used for exporting a remote object with JRMP and obtaining a stub 35 * that communicates to the remote object. Stubs are either generated 36 * at runtime using dynamic proxy objects, or they are generated statically 37 * at build time, typically using the {@code rmic} tool. 38 * 39 * <p><strong>Deprecated: Static Stubs.</strong> <em>Support for statically 40 * generated stubs is deprecated. This includes the API in this class that 41 * requires the use of static stubs, as well as the runtime support for 42 * loading static stubs. Generating stubs dynamically is preferred, using one 43 * of the non-deprecated ways of exporting objects as listed below. Do 44 * not run {@code rmic} to generate static stub classes. It is unnecessary, and 45 * it is also deprecated.</em> 46 * 47 * <p>There are eight ways to export remote objects: 48 * 49 * <ol> 50 * 51 * <li>Subclassing {@code UnicastRemoteObject} and calling the 52 * {@link #UnicastRemoteObject()} constructor. 53 * 54 * <li>Subclassing {@code UnicastRemoteObject} and calling the 55 * {@link #UnicastRemoteObject(int) UnicastRemoteObject(port)} constructor. 56 * 57 * <li>Subclassing {@code UnicastRemoteObject} and calling the 58 * {@link #UnicastRemoteObject(int, RMIClientSocketFactory, RMIServerSocketFactory) 59 * UnicastRemoteObject(port, csf, ssf)} constructor. 60 * 61 * <li>Calling the 62 * {@link #exportObject(Remote) exportObject(Remote)} method. 63 * <strong>Deprecated.</strong> 64 * 65 * <li>Calling the 66 * {@link #exportObject(Remote, int) exportObject(Remote, port)} method. 67 * 68 * <li>Calling the 69 * {@link #exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory) 70 * exportObject(Remote, port, csf, ssf)} method. 71 * 72 * <li>Calling the 73 * {@link #exportObject(Remote, int, ObjectInputFilter) exportObject(Remote, port, filter)} method. 74 * 75 * <li>Calling the 76 * {@link #exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory, ObjectInputFilter) 77 * exportObject(Remote, port, csf, ssf, filter)} method. 78 * 79 * </ol> 80 * 81 * <p>The fourth technique, {@link #exportObject(Remote)}, 82 * always uses statically generated stubs and is deprecated. 83 * 84 * <p>The other techniques all use the following approach: if the 85 * {@code java.rmi.server.ignoreStubClasses} property is {@code true} 86 * (case insensitive) or if a static stub cannot be found, stubs are generated 87 * dynamically using {@link java.lang.reflect.Proxy Proxy} objects. Otherwise, 88 * static stubs are used. 89 * 90 * <p>The default value of the 91 * {@code java.rmi.server.ignoreStubClasses} property is {@code false}. 92 * 93 * <p>Statically generated stubs are typically pregenerated from the 94 * remote object's class using the {@code rmic} tool. A static stub is 95 * loaded and an instance of that stub class is constructed as described 96 * below. 97 * 98 * <ul> 99 * 100 * <li>A "root class" is determined as follows: if the remote object's 101 * class directly implements an interface that extends {@link Remote}, then 102 * the remote object's class is the root class; otherwise, the root class is 103 * the most derived superclass of the remote object's class that directly 104 * implements an interface that extends {@code Remote}. 105 * 106 * <li>The name of the stub class to load is determined by concatenating 107 * the binary name of the root class with the suffix {@code _Stub}. 108 * 109 * <li>The stub class is loaded by name using the class loader of the root 110 * class. The stub class must be public, it must extend {@link RemoteStub}, it must 111 * reside in a package that is exported to at least the {@code java.rmi} module, and it 112 * must have a public constructor that has one parameter of type {@link RemoteRef}. 113 * 114 * <li>Finally, an instance of the stub class is constructed with a 115 * {@link RemoteRef}. 116 * 117 * <li>If the appropriate stub class could not be found, or if the stub class 118 * could not be loaded, or if a problem occurs creating the stub instance, a 119 * {@link StubNotFoundException} is thrown. 120 * 121 * </ul> 122 * 123 * <p>Stubs are dynamically generated by constructing an instance of 124 * a {@link java.lang.reflect.Proxy Proxy} with the following characteristics: 125 * 126 * <ul> 127 * 128 * <li>The proxy's class is defined according to the specifications for the 129 * <a href="{@docRoot}/java.base/java/lang/reflect/Proxy.html#membership"> 130 * {@code Proxy} 131 * </a> 132 * class, using the class loader of the remote object's class. 133 * 134 * <li>The proxy implements all the remote interfaces implemented by the 135 * remote object's class. 136 * 137 * <li>Each remote interface must either be public and reside in a package that is 138 * {@linkplain Module#isExported(String,Module) exported} 139 * to at least the {@code java.rmi} module, or it must reside in a package that is 140 * {@linkplain Module#isOpen(String,Module) open} 141 * to at least the {@code java.rmi} module. 142 * 143 * <li>The proxy's invocation handler is a {@link 144 * RemoteObjectInvocationHandler} instance constructed with a 145 * {@link RemoteRef}. 146 * 147 * <li>If the proxy could not be created, a {@link StubNotFoundException} 148 * will be thrown. 149 * 150 * </ul> 151 * 152 * <p> 153 * Exported remote objects receive method invocations from the stubs 154 * as described in the RMI specification. Each invocation's operation and 155 * parameters are unmarshaled using a custom {@link java.io.ObjectInputStream}. 156 * If an {@link ObjectInputFilter} is provided and is not {@code null} when the object 157 * is exported, it is used to filter the parameters as they are unmarshaled from the stream. 158 * The filter is used for all invocations and all parameters regardless of 159 * the method being invoked or the parameter values. 160 * If no filter is provided or is {@code null} for the exported object then the 161 * {@code ObjectInputStream} default filter, if any, is used. The default filter is 162 * configured with {@link ObjectInputFilter.Config#setSerialFilter(ObjectInputFilter) 163 * ObjectInputFilter.Config.setSerialFilter}. 164 * If the filter rejects any of the parameters, the {@code InvalidClassException} 165 * thrown by {@code ObjectInputStream} is reported as the cause of an 166 * {@link UnmarshalException}. 167 * 168 * @implNote 169 * Depending upon which constructor or static method is used for exporting an 170 * object, {@link RMISocketFactory} may be used for creating sockets. 171 * By default, server sockets created by {@link RMISocketFactory} 172 * listen on all network interfaces. See the 173 * {@link RMISocketFactory} class and the section 174 * <a href="{@docRoot}/../specs/rmi/server.html#rmi-socket-factories">RMI Socket Factories</a> 175 * in the 176 * <a href="{@docRoot}/../specs/rmi/index.html">Java RMI Specification</a>. 177 * 178 * @author Ann Wollrath 179 * @author Peter Jones 180 * @since 1.1 181 **/ 182 public class UnicastRemoteObject extends RemoteServer { 183 184 /** 185 * @serial port number on which to export object 186 */ 187 private int port = 0; 188 189 /** 190 * @serial client-side socket factory (if any) 191 */ 192 @SuppressWarnings("serial") // Not statically typed as Serializable 193 private RMIClientSocketFactory csf = null; 194 195 /** 196 * @serial server-side socket factory (if any) to use when 197 * exporting object 198 */ 199 @SuppressWarnings("serial") // Not statically typed as Serializable 200 private RMIServerSocketFactory ssf = null; 201 202 /* indicate compatibility with JDK 1.1.x version of class */ 203 private static final long serialVersionUID = 4974527148936298033L; 204 205 /** 206 * Creates and exports a new UnicastRemoteObject object using an 207 * anonymous port. 208 * 209 * <p>The object is exported with a server socket 210 * created using the {@link RMISocketFactory} class. 211 * 212 * @throws RemoteException if failed to export object 213 * @since 1.1 214 */ 215 protected UnicastRemoteObject() throws RemoteException 216 { 217 this(0); 218 } 219 220 /** 221 * Creates and exports a new UnicastRemoteObject object using the 222 * particular supplied port. 223 * 224 * <p>The object is exported with a server socket 225 * created using the {@link RMISocketFactory} class. 226 * 227 * @param port the port number on which the remote object receives calls 228 * (if <code>port</code> is zero, an anonymous port is chosen) 229 * @throws RemoteException if failed to export object 230 * @since 1.2 231 */ 232 protected UnicastRemoteObject(int port) throws RemoteException 233 { 234 this.port = port; 235 exportObject((Remote) this, port); 236 } 237 238 /** 239 * Creates and exports a new UnicastRemoteObject object using the 240 * particular supplied port and socket factories. 241 * 242 * <p>Either socket factory may be {@code null}, in which case 243 * the corresponding client or server socket creation method of 244 * {@link RMISocketFactory} is used instead. 245 * 246 * @param port the port number on which the remote object receives calls 247 * (if <code>port</code> is zero, an anonymous port is chosen) 248 * @param csf the client-side socket factory for making calls to the 249 * remote object 250 * @param ssf the server-side socket factory for receiving remote calls 251 * @throws RemoteException if failed to export object 252 * @since 1.2 253 */ 254 protected UnicastRemoteObject(int port, 255 RMIClientSocketFactory csf, 256 RMIServerSocketFactory ssf) 257 throws RemoteException 258 { 259 this.port = port; 260 this.csf = csf; 261 this.ssf = ssf; 262 exportObject((Remote) this, port, csf, ssf); 263 } 264 265 /** 266 * Re-export the remote object when it is deserialized. 267 */ 268 private void readObject(java.io.ObjectInputStream in) 269 throws java.io.IOException, java.lang.ClassNotFoundException 270 { 271 in.defaultReadObject(); 272 reexport(); 273 } 274 275 /** 276 * Returns a clone of the remote object that is distinct from 277 * the original. 278 * 279 * @exception CloneNotSupportedException if clone failed due to 280 * a RemoteException. 281 * @return the new remote object 282 * @since 1.1 283 */ 284 public Object clone() throws CloneNotSupportedException 285 { 286 try { 287 UnicastRemoteObject cloned = (UnicastRemoteObject) super.clone(); 288 cloned.reexport(); 289 return cloned; 290 } catch (RemoteException e) { 291 throw new ServerCloneException("Clone failed", e); 292 } 293 } 294 295 /* 296 * Exports this UnicastRemoteObject using its initialized fields because 297 * its creation bypassed running its constructors (via deserialization 298 * or cloning, for example). 299 */ 300 private void reexport() throws RemoteException 301 { 302 if (csf == null && ssf == null) { 303 exportObject((Remote) this, port); 304 } else { 305 exportObject((Remote) this, port, csf, ssf); 306 } 307 } 308 309 /** 310 * Exports the remote object to make it available to receive incoming 311 * calls using an anonymous port. This method will always return a 312 * statically generated stub. 313 * 314 * <p>The object is exported with a server socket 315 * created using the {@link RMISocketFactory} class. 316 * 317 * @param obj the remote object to be exported 318 * @return remote object stub 319 * @exception RemoteException if export fails 320 * @since 1.1 321 * @deprecated This method is deprecated because it supports only static stubs. 322 * Use {@link #exportObject(Remote, int) exportObject(Remote, port)} or 323 * {@link #exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory) 324 * exportObject(Remote, port, csf, ssf)} 325 * instead. 326 */ 327 @Deprecated 328 public static RemoteStub exportObject(Remote obj) 329 throws RemoteException 330 { 331 /* 332 * Use UnicastServerRef constructor passing the boolean value true 333 * to indicate that only a generated stub class should be used. A 334 * generated stub class must be used instead of a dynamic proxy 335 * because the return value of this method is RemoteStub which a 336 * dynamic proxy class cannot extend. 337 */ 338 return (RemoteStub) exportObject(obj, new UnicastServerRef(true)); 339 } 340 341 /** 342 * Exports the remote object to make it available to receive incoming 343 * calls, using the particular supplied port. 344 * 345 * <p>The object is exported with a server socket 346 * created using the {@link RMISocketFactory} class. 347 * 348 * @param obj the remote object to be exported 349 * @param port the port to export the object on 350 * @return remote object stub 351 * @exception RemoteException if export fails 352 * @since 1.2 353 */ 354 public static Remote exportObject(Remote obj, int port) 355 throws RemoteException 356 { 357 return exportObject(obj, new UnicastServerRef(port)); 358 } 359 360 /** 361 * Exports the remote object to make it available to receive incoming 362 * calls, using a transport specified by the given socket factory. 363 * 364 * <p>Either socket factory may be {@code null}, in which case 365 * the corresponding client or server socket creation method of 366 * {@link RMISocketFactory} is used instead. 367 * 368 * @param obj the remote object to be exported 369 * @param port the port to export the object on 370 * @param csf the client-side socket factory for making calls to the 371 * remote object 372 * @param ssf the server-side socket factory for receiving remote calls 373 * @return remote object stub 374 * @exception RemoteException if export fails 375 * @since 1.2 376 */ 377 public static Remote exportObject(Remote obj, int port, 378 RMIClientSocketFactory csf, 379 RMIServerSocketFactory ssf) 380 throws RemoteException 381 { 382 383 return exportObject(obj, new UnicastServerRef2(port, csf, ssf)); 384 } 385 386 /** 387 * Exports the remote object to make it available to receive incoming 388 * calls, using the particular supplied port 389 * and {@linkplain ObjectInputFilter filter}. 390 * 391 * <p>The object is exported with a server socket 392 * created using the {@link RMISocketFactory} class. 393 * 394 * @param obj the remote object to be exported 395 * @param port the port to export the object on 396 * @param filter an ObjectInputFilter applied when deserializing invocation arguments; 397 * may be {@code null} 398 * @return remote object stub 399 * @exception RemoteException if export fails 400 * @since 9 401 */ 402 public static Remote exportObject(Remote obj, int port, 403 ObjectInputFilter filter) 404 throws RemoteException 405 { 406 return exportObject(obj, new UnicastServerRef(new LiveRef(port), filter)); 407 } 408 409 /** 410 * Exports the remote object to make it available to receive incoming 411 * calls, using a transport specified by the given socket factory 412 * and {@linkplain ObjectInputFilter filter}. 413 * 414 * <p>Either socket factory may be {@code null}, in which case 415 * the corresponding client or server socket creation method of 416 * {@link RMISocketFactory} is used instead. 417 * 418 * @param obj the remote object to be exported 419 * @param port the port to export the object on 420 * @param csf the client-side socket factory for making calls to the 421 * remote object 422 * @param ssf the server-side socket factory for receiving remote calls 423 * @param filter an ObjectInputFilter applied when deserializing invocation arguments; 424 * may be {@code null} 425 * @return remote object stub 426 * @exception RemoteException if export fails 427 * @since 9 428 */ 429 public static Remote exportObject(Remote obj, int port, 430 RMIClientSocketFactory csf, 431 RMIServerSocketFactory ssf, 432 ObjectInputFilter filter) 433 throws RemoteException 434 { 435 return exportObject(obj, new UnicastServerRef2(port, csf, ssf, filter)); 436 } 437 438 /** 439 * Removes the remote object, obj, from the RMI runtime. If 440 * successful, the object can no longer accept incoming RMI calls. 441 * If the force parameter is true, the object is forcibly unexported 442 * even if there are pending calls to the remote object or the 443 * remote object still has calls in progress. If the force 444 * parameter is false, the object is only unexported if there are 445 * no pending or in progress calls to the object. 446 * 447 * @param obj the remote object to be unexported 448 * @param force if true, unexports the object even if there are 449 * pending or in-progress calls; if false, only unexports the object 450 * if there are no pending or in-progress calls 451 * @return true if operation is successful, false otherwise 452 * @exception NoSuchObjectException if the remote object is not 453 * currently exported 454 * @since 1.2 455 */ 456 public static boolean unexportObject(Remote obj, boolean force) 457 throws java.rmi.NoSuchObjectException 458 { 459 return sun.rmi.transport.ObjectTable.unexportObject(obj, force); 460 } 461 462 /** 463 * Exports the specified object using the specified server ref. 464 */ 465 private static Remote exportObject(Remote obj, UnicastServerRef sref) 466 throws RemoteException 467 { 468 // if obj extends UnicastRemoteObject, set its ref. 469 if (obj instanceof UnicastRemoteObject) { 470 ((UnicastRemoteObject) obj).ref = sref; 471 } 472 return sref.exportObject(obj, null, false); 473 } 474 }