Save This Page
Home » openjdk-7 » java » rmi » activation » [javadoc | source]
    1   /*
    2    * Copyright 1997-2005 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.rmi.activation;
   27   
   28   import java.io.IOException;
   29   import java.io.InvalidObjectException;
   30   import java.io.ObjectInputStream;
   31   import java.io.ObjectOutputStream;
   32   import java.io.Serializable;
   33   import java.lang.reflect.InvocationHandler;
   34   import java.lang.reflect.Proxy;
   35   import java.rmi.MarshalledObject;
   36   import java.rmi.Remote;
   37   import java.rmi.RemoteException;
   38   import java.rmi.UnmarshalException;
   39   import java.rmi.server.RemoteObject;
   40   import java.rmi.server.RemoteObjectInvocationHandler;
   41   import java.rmi.server.RemoteRef;
   42   import java.rmi.server.UID;
   43   
   44   /**
   45    * Activation makes use of special identifiers to denote remote
   46    * objects that can be activated over time. An activation identifier
   47    * (an instance of the class <code>ActivationID</code>) contains several
   48    * pieces of information needed for activating an object:
   49    * <ul>
   50    * <li> a remote reference to the object's activator (a {@link
   51    * java.rmi.server.RemoteRef RemoteRef}
   52    * instance), and
   53    * <li> a unique identifier (a {@link java.rmi.server.UID UID}
   54    * instance) for the object. </ul> <p>
   55    *
   56    * An activation identifier for an object can be obtained by registering
   57    * an object with the activation system. Registration is accomplished
   58    * in a few ways: <ul>
   59    * <li>via the <code>Activatable.register</code> method
   60    * <li>via the first <code>Activatable</code> constructor (that takes
   61    * three arguments and both registers and exports the object, and
   62    * <li>via the first <code>Activatable.exportObject</code> method
   63    * that takes the activation descriptor, object and port as arguments;
   64    * this method both registers and exports the object. </ul>
   65    *
   66    * @author      Ann Wollrath
   67    * @see         Activatable
   68    * @since       1.2
   69    */
   70   public class ActivationID implements Serializable {
   71       /**
   72        * the object's activator
   73        */
   74       private transient Activator activator;
   75   
   76       /**
   77        * the object's unique id
   78        */
   79       private transient UID uid = new UID();
   80   
   81       /** indicate compatibility with the Java 2 SDK v1.2 version of class */
   82       private static final long serialVersionUID = -4608673054848209235L;
   83   
   84       /**
   85        * The constructor for <code>ActivationID</code> takes a single
   86        * argument, activator, that specifies a remote reference to the
   87        * activator responsible for activating the object associated with
   88        * this identifier. An instance of <code>ActivationID</code> is globally
   89        * unique.
   90        *
   91        * @param activator reference to the activator responsible for
   92        * activating the object
   93        * @since 1.2
   94        */
   95       public ActivationID(Activator activator) {
   96           this.activator = activator;
   97       }
   98   
   99       /**
  100        * Activate the object for this id.
  101        *
  102        * @param force if true, forces the activator to contact the group
  103        * when activating the object (instead of returning a cached reference);
  104        * if false, returning a cached value is acceptable.
  105        * @return the reference to the active remote object
  106        * @exception ActivationException if activation fails
  107        * @exception UnknownObjectException if the object is unknown
  108        * @exception RemoteException if remote call fails
  109        * @since 1.2
  110        */
  111       public Remote activate(boolean force)
  112           throws ActivationException, UnknownObjectException, RemoteException
  113       {
  114           try {
  115               MarshalledObject<? extends Remote> mobj =
  116                   activator.activate(this, force);
  117               return mobj.get();
  118           } catch (RemoteException e) {
  119               throw e;
  120           } catch (IOException e) {
  121               throw new UnmarshalException("activation failed", e);
  122           } catch (ClassNotFoundException e) {
  123               throw new UnmarshalException("activation failed", e);
  124           }
  125   
  126       }
  127   
  128       /**
  129        * Returns a hashcode for the activation id.  Two identifiers that
  130        * refer to the same remote object will have the same hash code.
  131        *
  132        * @see java.util.Hashtable
  133        * @since 1.2
  134        */
  135       public int hashCode() {
  136           return uid.hashCode();
  137       }
  138   
  139       /**
  140        * Compares two activation ids for content equality.
  141        * Returns true if both of the following conditions are true:
  142        * 1) the unique identifiers equivalent (by content), and
  143        * 2) the activator specified in each identifier
  144        *    refers to the same remote object.
  145        *
  146        * @param   obj     the Object to compare with
  147        * @return  true if these Objects are equal; false otherwise.
  148        * @see             java.util.Hashtable
  149        * @since 1.2
  150        */
  151       public boolean equals(Object obj) {
  152           if (obj instanceof ActivationID) {
  153               ActivationID id = (ActivationID) obj;
  154               return (uid.equals(id.uid) && activator.equals(id.activator));
  155           } else {
  156               return false;
  157           }
  158       }
  159   
  160       /**
  161        * <code>writeObject</code> for custom serialization.
  162        *
  163        * <p>This method writes this object's serialized form for
  164        * this class as follows:
  165        *
  166        * <p>The <code>writeObject</code> method is invoked on
  167        * <code>out</code> passing this object's unique identifier
  168        * (a {@link java.rmi.server.UID UID} instance) as the argument.
  169        *
  170        * <p>Next, the {@link
  171        * java.rmi.server.RemoteRef#getRefClass(java.io.ObjectOutput)
  172        * getRefClass} method is invoked on the activator's
  173        * <code>RemoteRef</code> instance to obtain its external ref
  174        * type name.  Next, the <code>writeUTF</code> method is
  175        * invoked on <code>out</code> with the value returned by
  176        * <code>getRefClass</code>, and then the
  177        * <code>writeExternal</code> method is invoked on the
  178        * <code>RemoteRef</code> instance passing <code>out</code>
  179        * as the argument.
  180        *
  181        * @serialData The serialized data for this class comprises a
  182        * <code>java.rmi.server.UID</code> (written with
  183        * <code>ObjectOutput.writeObject</code>) followed by the
  184        * external ref type name of the activator's
  185        * <code>RemoteRef</code> instance (a string written with
  186        * <code>ObjectOutput.writeUTF</code>), followed by the
  187        * external form of the <code>RemoteRef</code> instance as
  188        * written by its <code>writeExternal</code> method.
  189        *
  190        * <p>The external ref type name of the
  191        * <code>RemoteRef</Code> instance is
  192        * determined using the definitions of external ref type
  193        * names specified in the {@link java.rmi.server.RemoteObject
  194        * RemoteObject} <code>writeObject</code> method
  195        * <b>serialData</b> specification.  Similarly, the data
  196        * written by the <code>writeExternal</code> method and read
  197        * by the <code>readExternal</code> method of
  198        * <code>RemoteRef</code> implementation classes
  199        * corresponding to each of the defined external ref type
  200        * names is specified in the {@link
  201        * java.rmi.server.RemoteObject RemoteObject}
  202        * <code>writeObject</code> method <b>serialData</b>
  203        * specification.
  204        **/
  205       private void writeObject(ObjectOutputStream out)
  206           throws IOException, ClassNotFoundException
  207       {
  208           out.writeObject(uid);
  209   
  210           RemoteRef ref;
  211           if (activator instanceof RemoteObject) {
  212               ref = ((RemoteObject) activator).getRef();
  213           } else if (Proxy.isProxyClass(activator.getClass())) {
  214               InvocationHandler handler = Proxy.getInvocationHandler(activator);
  215               if (!(handler instanceof RemoteObjectInvocationHandler)) {
  216                   throw new InvalidObjectException(
  217                       "unexpected invocation handler");
  218               }
  219               ref = ((RemoteObjectInvocationHandler) handler).getRef();
  220   
  221           } else {
  222               throw new InvalidObjectException("unexpected activator type");
  223           }
  224           out.writeUTF(ref.getRefClass(out));
  225           ref.writeExternal(out);
  226       }
  227   
  228       /**
  229        * <code>readObject</code> for custom serialization.
  230        *
  231        * <p>This method reads this object's serialized form for this
  232        * class as follows:
  233        *
  234        * <p>The <code>readObject</code> method is invoked on
  235        * <code>in</code> to read this object's unique identifier
  236        * (a {@link java.rmi.server.UID UID} instance).
  237        *
  238        * <p>Next, the <code>readUTF</code> method is invoked on
  239        * <code>in</code> to read the external ref type name of the
  240        * <code>RemoteRef</code> instance for this object's
  241        * activator.  Next, the <code>RemoteRef</code>
  242        * instance is created of an implementation-specific class
  243        * corresponding to the external ref type name (returned by
  244        * <code>readUTF</code>), and the <code>readExternal</code>
  245        * method is invoked on that <code>RemoteRef</code> instance
  246        * to read the external form corresponding to the external
  247        * ref type name.
  248        *
  249        * <p>Note: If the external ref type name is
  250        * <code>"UnicastRef"</code>, <code>"UnicastServerRef"</code>,
  251        * <code>"UnicastRef2"</code>, <code>"UnicastServerRef2"</code>,
  252        * or <code>"ActivatableRef"</code>, a corresponding
  253        * implementation-specific class must be found, and its
  254        * <code>readExternal</code> method must read the serial data
  255        * for that external ref type name as specified to be written
  256        * in the <b>serialData</b> documentation for this class.
  257        * If the external ref type name is any other string (of non-zero
  258        * length), a <code>ClassNotFoundException</code> will be thrown,
  259        * unless the implementation provides an implementation-specific
  260        * class corresponding to that external ref type name, in which
  261        * case the <code>RemoteRef</code> will be an instance of
  262        * that implementation-specific class.
  263        */
  264       private void readObject(ObjectInputStream in)
  265           throws IOException, ClassNotFoundException
  266       {
  267           uid = (UID)in.readObject();
  268   
  269           try {
  270               Class<? extends RemoteRef> refClass =
  271                   Class.forName(RemoteRef.packagePrefix + "." + in.readUTF())
  272                   .asSubclass(RemoteRef.class);
  273               RemoteRef ref = refClass.newInstance();
  274               ref.readExternal(in);
  275               activator = (Activator)
  276                   Proxy.newProxyInstance(null,
  277                                          new Class<?>[] { Activator.class },
  278                                          new RemoteObjectInvocationHandler(ref));
  279   
  280           } catch (InstantiationException e) {
  281               throw (IOException)
  282                   new InvalidObjectException(
  283                       "Unable to create remote reference").initCause(e);
  284           } catch (IllegalAccessException e) {
  285               throw (IOException)
  286                   new InvalidObjectException(
  287                       "Unable to create remote reference").initCause(e);
  288           }
  289       }
  290   }

Save This Page
Home » openjdk-7 » java » rmi » activation » [javadoc | source]