Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/rmi/activation/ActivationID.java
38918 views
/*1* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.rmi.activation;2627import java.io.IOException;28import java.io.InvalidObjectException;29import java.io.ObjectInputStream;30import java.io.ObjectOutputStream;31import java.io.Serializable;32import java.lang.reflect.InvocationHandler;33import java.lang.reflect.Proxy;34import java.rmi.MarshalledObject;35import java.rmi.Remote;36import java.rmi.RemoteException;37import java.rmi.UnmarshalException;38import java.rmi.server.RemoteObject;39import java.rmi.server.RemoteObjectInvocationHandler;40import java.rmi.server.RemoteRef;41import java.rmi.server.UID;42import java.security.AccessControlContext;43import java.security.AccessController;44import java.security.Permissions;45import java.security.PrivilegedActionException;46import java.security.PrivilegedExceptionAction;47import java.security.ProtectionDomain;4849/**50* Activation makes use of special identifiers to denote remote51* objects that can be activated over time. An activation identifier52* (an instance of the class <code>ActivationID</code>) contains several53* pieces of information needed for activating an object:54* <ul>55* <li> a remote reference to the object's activator (a {@link56* java.rmi.server.RemoteRef RemoteRef}57* instance), and58* <li> a unique identifier (a {@link java.rmi.server.UID UID}59* instance) for the object. </ul> <p>60*61* An activation identifier for an object can be obtained by registering62* an object with the activation system. Registration is accomplished63* in a few ways: <ul>64* <li>via the <code>Activatable.register</code> method65* <li>via the first <code>Activatable</code> constructor (that takes66* three arguments and both registers and exports the object, and67* <li>via the first <code>Activatable.exportObject</code> method68* that takes the activation descriptor, object and port as arguments;69* this method both registers and exports the object. </ul>70*71* @author Ann Wollrath72* @see Activatable73* @since 1.274*/75public class ActivationID implements Serializable {76/**77* the object's activator78*/79private transient Activator activator;8081/**82* the object's unique id83*/84private transient UID uid = new UID();8586/** indicate compatibility with the Java 2 SDK v1.2 version of class */87private static final long serialVersionUID = -4608673054848209235L;8889/** an AccessControlContext with no permissions */90private static final AccessControlContext NOPERMS_ACC;91static {92Permissions perms = new Permissions();93ProtectionDomain[] pd = { new ProtectionDomain(null, perms) };94NOPERMS_ACC = new AccessControlContext(pd);95}9697/**98* The constructor for <code>ActivationID</code> takes a single99* argument, activator, that specifies a remote reference to the100* activator responsible for activating the object associated with101* this identifier. An instance of <code>ActivationID</code> is globally102* unique.103*104* @param activator reference to the activator responsible for105* activating the object106* @throws UnsupportedOperationException if and only if activation is107* not supported by this implementation108* @since 1.2109*/110public ActivationID(Activator activator) {111this.activator = activator;112}113114/**115* Activate the object for this id.116*117* @param force if true, forces the activator to contact the group118* when activating the object (instead of returning a cached reference);119* if false, returning a cached value is acceptable.120* @return the reference to the active remote object121* @exception ActivationException if activation fails122* @exception UnknownObjectException if the object is unknown123* @exception RemoteException if remote call fails124* @since 1.2125*/126public Remote activate(boolean force)127throws ActivationException, UnknownObjectException, RemoteException128{129try {130MarshalledObject<? extends Remote> mobj =131activator.activate(this, force);132return AccessController.doPrivileged(133new PrivilegedExceptionAction<Remote>() {134public Remote run() throws IOException, ClassNotFoundException {135return mobj.get();136}137}, NOPERMS_ACC);138} catch (PrivilegedActionException pae) {139Exception ex = pae.getException();140if (ex instanceof RemoteException) {141throw (RemoteException) ex;142} else {143throw new UnmarshalException("activation failed", ex);144}145}146147}148149/**150* Returns a hashcode for the activation id. Two identifiers that151* refer to the same remote object will have the same hash code.152*153* @see java.util.Hashtable154* @since 1.2155*/156public int hashCode() {157return uid.hashCode();158}159160/**161* Compares two activation ids for content equality.162* Returns true if both of the following conditions are true:163* 1) the unique identifiers equivalent (by content), and164* 2) the activator specified in each identifier165* refers to the same remote object.166*167* @param obj the Object to compare with168* @return true if these Objects are equal; false otherwise.169* @see java.util.Hashtable170* @since 1.2171*/172public boolean equals(Object obj) {173if (obj instanceof ActivationID) {174ActivationID id = (ActivationID) obj;175return (uid.equals(id.uid) && activator.equals(id.activator));176} else {177return false;178}179}180181/**182* <code>writeObject</code> for custom serialization.183*184* <p>This method writes this object's serialized form for185* this class as follows:186*187* <p>The <code>writeObject</code> method is invoked on188* <code>out</code> passing this object's unique identifier189* (a {@link java.rmi.server.UID UID} instance) as the argument.190*191* <p>Next, the {@link192* java.rmi.server.RemoteRef#getRefClass(java.io.ObjectOutput)193* getRefClass} method is invoked on the activator's194* <code>RemoteRef</code> instance to obtain its external ref195* type name. Next, the <code>writeUTF</code> method is196* invoked on <code>out</code> with the value returned by197* <code>getRefClass</code>, and then the198* <code>writeExternal</code> method is invoked on the199* <code>RemoteRef</code> instance passing <code>out</code>200* as the argument.201*202* @serialData The serialized data for this class comprises a203* <code>java.rmi.server.UID</code> (written with204* <code>ObjectOutput.writeObject</code>) followed by the205* external ref type name of the activator's206* <code>RemoteRef</code> instance (a string written with207* <code>ObjectOutput.writeUTF</code>), followed by the208* external form of the <code>RemoteRef</code> instance as209* written by its <code>writeExternal</code> method.210*211* <p>The external ref type name of the212* <code>RemoteRef</Code> instance is213* determined using the definitions of external ref type214* names specified in the {@link java.rmi.server.RemoteObject215* RemoteObject} <code>writeObject</code> method216* <b>serialData</b> specification. Similarly, the data217* written by the <code>writeExternal</code> method and read218* by the <code>readExternal</code> method of219* <code>RemoteRef</code> implementation classes220* corresponding to each of the defined external ref type221* names is specified in the {@link222* java.rmi.server.RemoteObject RemoteObject}223* <code>writeObject</code> method <b>serialData</b>224* specification.225**/226private void writeObject(ObjectOutputStream out)227throws IOException, ClassNotFoundException228{229out.writeObject(uid);230231RemoteRef ref;232if (activator instanceof RemoteObject) {233ref = ((RemoteObject) activator).getRef();234} else if (Proxy.isProxyClass(activator.getClass())) {235InvocationHandler handler = Proxy.getInvocationHandler(activator);236if (!(handler instanceof RemoteObjectInvocationHandler)) {237throw new InvalidObjectException(238"unexpected invocation handler");239}240ref = ((RemoteObjectInvocationHandler) handler).getRef();241242} else {243throw new InvalidObjectException("unexpected activator type");244}245out.writeUTF(ref.getRefClass(out));246ref.writeExternal(out);247}248249/**250* <code>readObject</code> for custom serialization.251*252* <p>This method reads this object's serialized form for this253* class as follows:254*255* <p>The <code>readObject</code> method is invoked on256* <code>in</code> to read this object's unique identifier257* (a {@link java.rmi.server.UID UID} instance).258*259* <p>Next, the <code>readUTF</code> method is invoked on260* <code>in</code> to read the external ref type name of the261* <code>RemoteRef</code> instance for this object's262* activator. Next, the <code>RemoteRef</code>263* instance is created of an implementation-specific class264* corresponding to the external ref type name (returned by265* <code>readUTF</code>), and the <code>readExternal</code>266* method is invoked on that <code>RemoteRef</code> instance267* to read the external form corresponding to the external268* ref type name.269*270* <p>Note: If the external ref type name is271* <code>"UnicastRef"</code>, <code>"UnicastServerRef"</code>,272* <code>"UnicastRef2"</code>, <code>"UnicastServerRef2"</code>,273* or <code>"ActivatableRef"</code>, a corresponding274* implementation-specific class must be found, and its275* <code>readExternal</code> method must read the serial data276* for that external ref type name as specified to be written277* in the <b>serialData</b> documentation for this class.278* If the external ref type name is any other string (of non-zero279* length), a <code>ClassNotFoundException</code> will be thrown,280* unless the implementation provides an implementation-specific281* class corresponding to that external ref type name, in which282* case the <code>RemoteRef</code> will be an instance of283* that implementation-specific class.284*/285private void readObject(ObjectInputStream in)286throws IOException, ClassNotFoundException287{288uid = (UID)in.readObject();289290try {291Class<? extends RemoteRef> refClass =292Class.forName(RemoteRef.packagePrefix + "." + in.readUTF())293.asSubclass(RemoteRef.class);294RemoteRef ref = refClass.newInstance();295ref.readExternal(in);296activator = (Activator)297Proxy.newProxyInstance(null,298new Class<?>[] { Activator.class },299new RemoteObjectInvocationHandler(ref));300301} catch (InstantiationException e) {302throw (IOException)303new InvalidObjectException(304"Unable to create remote reference").initCause(e);305} catch (IllegalAccessException e) {306throw (IOException)307new InvalidObjectException(308"Unable to create remote reference").initCause(e);309}310}311}312313314