1 /* 2 * Copyright (c) 1996, 2017, 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 private RMIClientSocketFactory csf = null; 193 194 /** 195 * @serial server-side socket factory (if any) to use when 196 * exporting object 197 */ 198 private RMIServerSocketFactory ssf = null; 199 200 /* indicate compatibility with JDK 1.1.x version of class */ 201 private static final long serialVersionUID = 4974527148936298033L; 202 203 /** 204 * Creates and exports a new UnicastRemoteObject object using an 205 * anonymous port. 206 * 207 * <p>The object is exported with a server socket 208 * created using the {@link RMISocketFactory} class. 209 * 210 * @throws RemoteException if failed to export object 211 * @since 1.1 212 */ 213 protected UnicastRemoteObject() throws RemoteException 214 { 215 this(0); 216 } 217 218 /** 219 * Creates and exports a new UnicastRemoteObject object using the 220 * particular supplied port. 221 * 222 * <p>The object is exported with a server socket 223 * created using the {@link RMISocketFactory} class. 224 * 225 * @param port the port number on which the remote object receives calls 226 * (if <code>port</code> is zero, an anonymous port is chosen) 227 * @throws RemoteException if failed to export object 228 * @since 1.2 229 */ 230 protected UnicastRemoteObject(int port) throws RemoteException 231 { 232 this.port = port; 233 exportObject((Remote) this, port); 234 } 235 236 /** 237 * Creates and exports a new UnicastRemoteObject object using the 238 * particular supplied port and socket factories. 239 * 240 * <p>Either socket factory may be {@code null}, in which case 241 * the corresponding client or server socket creation method of 242 * {@link RMISocketFactory} is used instead. 243 * 244 * @param port the port number on which the remote object receives calls 245 * (if <code>port</code> is zero, an anonymous port is chosen) 246 * @param csf the client-side socket factory for making calls to the 247 * remote object 248 * @param ssf the server-side socket factory for receiving remote calls 249 * @throws RemoteException if failed to export object 250 * @since 1.2 251 */ 252 protected UnicastRemoteObject(int port, 253 RMIClientSocketFactory csf, 254 RMIServerSocketFactory ssf) 255 throws RemoteException 256 { 257 this.port = port; 258 this.csf = csf; 259 this.ssf = ssf; 260 exportObject((Remote) this, port, csf, ssf); 261 } 262 263 /** 264 * Re-export the remote object when it is deserialized. 265 */ 266 private void readObject(java.io.ObjectInputStream in) 267 throws java.io.IOException, java.lang.ClassNotFoundException 268 { 269 in.defaultReadObject(); 270 reexport(); 271 } 272 273 /** 274 * Returns a clone of the remote object that is distinct from 275 * the original. 276 * 277 * @exception CloneNotSupportedException if clone failed due to 278 * a RemoteException. 279 * @return the new remote object 280 * @since 1.1 281 */ 282 public Object clone() throws CloneNotSupportedException 283 { 284 try { 285 UnicastRemoteObject cloned = (UnicastRemoteObject) super.clone(); 286 cloned.reexport(); 287 return cloned; 288 } catch (RemoteException e) { 289 throw new ServerCloneException("Clone failed", e); 290 } 291 } 292 293 /* 294 * Exports this UnicastRemoteObject using its initialized fields because 295 * its creation bypassed running its constructors (via deserialization 296 * or cloning, for example). 297 */ 298 private void reexport() throws RemoteException 299 { 300 if (csf == null && ssf == null) { 301 exportObject((Remote) this, port); 302 } else { 303 exportObject((Remote) this, port, csf, ssf); 304 } 305 } 306 307 /** 308 * Exports the remote object to make it available to receive incoming 309 * calls using an anonymous port. This method will always return a 310 * statically generated stub. 311 * 312 * <p>The object is exported with a server socket 313 * created using the {@link RMISocketFactory} class. 314 * 315 * @param obj the remote object to be exported 316 * @return remote object stub 317 * @exception RemoteException if export fails 318 * @since 1.1 319 * @deprecated This method is deprecated because it supports only static stubs. 320 * Use {@link #exportObject(Remote, int) exportObject(Remote, port)} or 321 * {@link #exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory) 322 * exportObject(Remote, port, csf, ssf)} 323 * instead. 324 */ 325 @Deprecated 326 public static RemoteStub exportObject(Remote obj) 327 throws RemoteException 328 { 329 /* 330 * Use UnicastServerRef constructor passing the boolean value true 331 * to indicate that only a generated stub class should be used. A 332 * generated stub class must be used instead of a dynamic proxy 333 * because the return value of this method is RemoteStub which a 334 * dynamic proxy class cannot extend. 335 */ 336 return (RemoteStub) exportObject(obj, new UnicastServerRef(true)); 337 } 338 339 /** 340 * Exports the remote object to make it available to receive incoming 341 * calls, using the particular supplied port. 342 * 343 * <p>The object is exported with a server socket 344 * created using the {@link RMISocketFactory} class. 345 * 346 * @param obj the remote object to be exported 347 * @param port the port to export the object on 348 * @return remote object stub 349 * @exception RemoteException if export fails 350 * @since 1.2 351 */ 352 public static Remote exportObject(Remote obj, int port) 353 throws RemoteException 354 { 355 return exportObject(obj, new UnicastServerRef(port)); 356 } 357 358 /** 359 * Exports the remote object to make it available to receive incoming 360 * calls, using a transport specified by the given socket factory. 361 * 362 * <p>Either socket factory may be {@code null}, in which case 363 * the corresponding client or server socket creation method of 364 * {@link RMISocketFactory} is used instead. 365 * 366 * @param obj the remote object to be exported 367 * @param port the port to export the object on 368 * @param csf the client-side socket factory for making calls to the 369 * remote object 370 * @param ssf the server-side socket factory for receiving remote calls 371 * @return remote object stub 372 * @exception RemoteException if export fails 373 * @since 1.2 374 */ 375 public static Remote exportObject(Remote obj, int port, 376 RMIClientSocketFactory csf, 377 RMIServerSocketFactory ssf) 378 throws RemoteException 379 { 380 381 return exportObject(obj, new UnicastServerRef2(port, csf, ssf)); 382 } 383 384 /** 385 * Exports the remote object to make it available to receive incoming 386 * calls, using the particular supplied port 387 * and {@linkplain ObjectInputFilter filter}. 388 * 389 * <p>The object is exported with a server socket 390 * created using the {@link RMISocketFactory} class. 391 * 392 * @param obj the remote object to be exported 393 * @param port the port to export the object on 394 * @param filter an ObjectInputFilter applied when deserializing invocation arguments; 395 * may be {@code null} 396 * @return remote object stub 397 * @exception RemoteException if export fails 398 * @since 9 399 */ 400 public static Remote exportObject(Remote obj, int port, 401 ObjectInputFilter filter) 402 throws RemoteException 403 { 404 return exportObject(obj, new UnicastServerRef(new LiveRef(port), filter)); 405 } 406 407 /** 408 * Exports the remote object to make it available to receive incoming 409 * calls, using a transport specified by the given socket factory 410 * and {@linkplain ObjectInputFilter filter}. 411 * 412 * <p>Either socket factory may be {@code null}, in which case 413 * the corresponding client or server socket creation method of 414 * {@link RMISocketFactory} is used instead. 415 * 416 * @param obj the remote object to be exported 417 * @param port the port to export the object on 418 * @param csf the client-side socket factory for making calls to the 419 * remote object 420 * @param ssf the server-side socket factory for receiving remote calls 421 * @param filter an ObjectInputFilter applied when deserializing invocation arguments; 422 * may be {@code null} 423 * @return remote object stub 424 * @exception RemoteException if export fails 425 * @since 9 426 */ 427 public static Remote exportObject(Remote obj, int port, 428 RMIClientSocketFactory csf, 429 RMIServerSocketFactory ssf, 430 ObjectInputFilter filter) 431 throws RemoteException 432 { 433 return exportObject(obj, new UnicastServerRef2(port, csf, ssf, filter)); 434 } 435 436 /** 437 * Removes the remote object, obj, from the RMI runtime. If 438 * successful, the object can no longer accept incoming RMI calls. 439 * If the force parameter is true, the object is forcibly unexported 440 * even if there are pending calls to the remote object or the 441 * remote object still has calls in progress. If the force 442 * parameter is false, the object is only unexported if there are 443 * no pending or in progress calls to the object. 444 * 445 * @param obj the remote object to be unexported 446 * @param force if true, unexports the object even if there are 447 * pending or in-progress calls; if false, only unexports the object 448 * if there are no pending or in-progress calls 449 * @return true if operation is successful, false otherwise 450 * @exception NoSuchObjectException if the remote object is not 451 * currently exported 452 * @since 1.2 453 */ 454 public static boolean unexportObject(Remote obj, boolean force) 455 throws java.rmi.NoSuchObjectException 456 { 457 return sun.rmi.transport.ObjectTable.unexportObject(obj, force); 458 } 459 460 /** 461 * Exports the specified object using the specified server ref. 462 */ 463 private static Remote exportObject(Remote obj, UnicastServerRef sref) 464 throws RemoteException 465 { 466 // if obj extends UnicastRemoteObject, set its ref. 467 if (obj instanceof UnicastRemoteObject) { 468 ((UnicastRemoteObject) obj).ref = sref; 469 } 470 return sref.exportObject(obj, null, false); 471 } 472 }