1 /*
   2  * Copyright (c) 1999, 2011, 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 
  26 package javax.naming;
  27 
  28 import java.util.Vector;
  29 import java.util.Enumeration;
  30 
  31 /**
  32   * This class represents a reference to an object that is found outside of
  33   * the naming/directory system.
  34   *<p>
  35   * Reference provides a way of recording address information about
  36   * objects which themselves are not directly bound to the naming/directory system.
  37   *<p>
  38   * A Reference consists of an ordered list of addresses and class information
  39   * about the object being referenced.
  40   * Each address in the list identifies a communications endpoint
  41   * for the same conceptual object.  The "communications endpoint"
  42   * is information that indicates how to contact the object. It could
  43   * be, for example, a network address, a location in memory on the
  44   * local machine, another process on the same machine, etc.
  45   * The order of the addresses in the list may be of significance
  46   * to object factories that interpret the reference.
  47   *<p>
  48   * Multiple addresses may arise for
  49   * various reasons, such as replication or the object offering interfaces
  50   * over more than one communication mechanism.  The addresses are indexed
  51   * starting with zero.
  52   *<p>
  53   * A Reference also contains information to assist in creating an instance
  54   * of the object to which this Reference refers.  It contains the class name
  55   * of that object, and the class name and location of the factory to be used
  56   * to create the object.
  57   * The class factory location is a space-separated list of URLs representing
  58   * the class path used to load the factory.  When the factory class (or
  59   * any class or resource upon which it depends) needs to be loaded,
  60   * each URL is used (in order) to attempt to load the class.
  61   *<p>
  62   * A Reference instance is not synchronized against concurrent access by multiple
  63   * threads. Threads that need to access a single Reference concurrently should
  64   * synchronize amongst themselves and provide the necessary locking.
  65   *
  66   * @author Rosanna Lee
  67   * @author Scott Seligman
  68   *
  69   * @see RefAddr
  70   * @see StringRefAddr
  71   * @see BinaryRefAddr
  72   * @since 1.3
  73   */
  74 
  75   /*<p>
  76   * The serialized form of a Reference object consists of the class
  77   * name of the object being referenced (a String), a Vector of the
  78   * addresses (each a RefAddr), the name of the class factory (a
  79   * String), and the location of the class factory (a String).
  80 */
  81 
  82 
  83 public class Reference implements Cloneable, java.io.Serializable {
  84     /**
  85      * Contains the fully-qualified name of the class of the object to which
  86      * this Reference refers.
  87      * @serial
  88      * @see java.lang.Class#getName
  89      */
  90     protected String className;
  91     /**
  92      * Contains the addresses contained in this Reference.
  93      * Initialized by constructor.
  94      * @serial
  95      */
  96     protected Vector<RefAddr> addrs = null;
  97 
  98     /**
  99      * Contains the name of the factory class for creating
 100      * an instance of the object to which this Reference refers.
 101      * Initialized to null.
 102      * @serial
 103      */
 104     protected String classFactory = null;
 105 
 106     /**
 107      * Contains the location of the factory class.
 108      * Initialized to null.
 109      * @serial
 110      */
 111     protected String classFactoryLocation = null;
 112 
 113     /**
 114       * Constructs a new reference for an object with class name 'className'.
 115       * Class factory and class factory location are set to null.
 116       * The newly created reference contains zero addresses.
 117       *
 118       * @param className The non-null class name of the object to which
 119       * this reference refers.
 120       */
 121     public Reference(String className) {
 122         this.className  = className;
 123         addrs = new Vector<>();
 124     }
 125 
 126     /**
 127       * Constructs a new reference for an object with class name 'className' and
 128       * an address.
 129       * Class factory and class factory location are set to null.
 130       *
 131       * @param className The non-null class name of the object to
 132       * which this reference refers.
 133       * @param addr The non-null address of the object.
 134       */
 135     public Reference(String className, RefAddr addr) {
 136         this.className = className;
 137         addrs = new Vector<>();
 138         addrs.addElement(addr);
 139     }
 140 
 141     /**
 142       * Constructs a new reference for an object with class name 'className',
 143       * and the class name and location of the object's factory.
 144       *
 145       * @param className The non-null class name of the object to which
 146       *                         this reference refers.
 147       * @param factory  The possibly null class name of the object's factory.
 148       * @param factoryLocation
 149       *         The possibly null location from which to load
 150       *         the factory (e.g. URL)
 151       * @see javax.naming.spi.ObjectFactory
 152       * @see javax.naming.spi.NamingManager#getObjectInstance
 153       */
 154     public Reference(String className, String factory, String factoryLocation) {
 155         this(className);
 156         classFactory = factory;
 157         classFactoryLocation = factoryLocation;
 158     }
 159 
 160     /**
 161       * Constructs a new reference for an object with class name 'className',
 162       * the class name and location of the object's factory, and the address for
 163       * the object.
 164       *
 165       * @param className The non-null class name of the object to
 166       *         which this reference refers.
 167       * @param factory  The possibly null class name of the object's factory.
 168       * @param factoryLocation  The possibly null location from which
 169       *                         to load the factory (e.g. URL)
 170       * @param addr     The non-null address of the object.
 171       * @see javax.naming.spi.ObjectFactory
 172       * @see javax.naming.spi.NamingManager#getObjectInstance
 173       */
 174     public Reference(String className, RefAddr addr,
 175                      String factory, String factoryLocation) {
 176         this(className, addr);
 177         classFactory = factory;
 178         classFactoryLocation = factoryLocation;
 179     }
 180 
 181     /**
 182       * Retrieves the class name of the object to which this reference refers.
 183       *
 184       * @return The non-null fully-qualified class name of the object.
 185       *         (e.g. "java.lang.String")
 186       */
 187     public String getClassName() {
 188         return className;
 189     }
 190 
 191     /**
 192       * Retrieves the class name of the factory of the object
 193       * to which this reference refers.
 194       *
 195       * @return The possibly null fully-qualified class name of the factory.
 196       *         (e.g. "java.lang.String")
 197       */
 198     public String getFactoryClassName() {
 199         return classFactory;
 200     }
 201 
 202     /**
 203       * Retrieves the location of the factory of the object
 204       * to which this reference refers.
 205       * If it is a codebase, then it is an ordered list of URLs,
 206       * separated by spaces, listing locations from where the factory
 207       * class definition should be loaded.
 208       *
 209       * @return The possibly null string containing the
 210       *                 location for loading in the factory's class.
 211       */
 212     public String getFactoryClassLocation() {
 213         return classFactoryLocation;
 214     }
 215 
 216     /**
 217       * Retrieves the first address that has the address type 'addrType'.
 218       * String.compareTo() is used to test the equality of the address types.
 219       *
 220       * @param addrType The non-null address type for which to find the address.
 221       * @return The address in this reference with address type 'addrType';
 222       *         null if no such address exists.
 223       */
 224     public RefAddr get(String addrType) {
 225         int len = addrs.size();
 226         RefAddr addr;
 227         for (int i = 0; i < len; i++) {
 228             addr = addrs.elementAt(i);
 229             if (addr.getType().compareTo(addrType) == 0)
 230                 return addr;
 231         }
 232         return null;
 233     }
 234 
 235     /**
 236       * Retrieves the address at index posn.
 237       * @param posn The index of the address to retrieve.
 238       * @return The address at the 0-based index posn. It must be in the
 239       *         range [0,getAddressCount()).
 240       * @exception ArrayIndexOutOfBoundsException If posn not in the specified
 241       *         range.
 242       */
 243     public RefAddr get(int posn) {
 244         return addrs.elementAt(posn);
 245     }
 246 
 247     /**
 248       * Retrieves an enumeration of the addresses in this reference.
 249       * When addresses are added, changed or removed from this reference,
 250       * its effects on this enumeration are undefined.
 251       *
 252       * @return An non-null enumeration of the addresses
 253       *         (<tt>RefAddr</tt>) in this reference.
 254       *         If this reference has zero addresses, an enumeration with
 255       *         zero elements is returned.
 256       */
 257     public Enumeration<RefAddr> getAll() {
 258         return addrs.elements();
 259     }
 260 
 261     /**
 262       * Retrieves the number of addresses in this reference.
 263       *
 264       * @return The nonnegative number of addresses in this reference.
 265       */
 266     public int size() {
 267         return addrs.size();
 268     }
 269 
 270     /**
 271       * Adds an address to the end of the list of addresses.
 272       *
 273       * @param addr The non-null address to add.
 274       */
 275     public void add(RefAddr addr) {
 276         addrs.addElement(addr);
 277     }
 278 
 279     /**
 280       * Adds an address to the list of addresses at index posn.
 281       * All addresses at index posn or greater are shifted up
 282       * the list by one (away from index 0).
 283       *
 284       * @param posn The 0-based index of the list to insert addr.
 285       * @param addr The non-null address to add.
 286       * @exception ArrayIndexOutOfBoundsException If posn not in the specified
 287       *         range.
 288       */
 289     public void add(int posn, RefAddr addr) {
 290         addrs.insertElementAt(addr, posn);
 291     }
 292 
 293     /**
 294       * Deletes the address at index posn from the list of addresses.
 295       * All addresses at index greater than posn are shifted down
 296       * the list by one (towards index 0).
 297       *
 298       * @param posn The 0-based index of in address to delete.
 299       * @return The address removed.
 300       * @exception ArrayIndexOutOfBoundsException If posn not in the specified
 301       *         range.
 302       */
 303     public Object remove(int posn) {
 304         Object r = addrs.elementAt(posn);
 305         addrs.removeElementAt(posn);
 306         return r;
 307     }
 308 
 309     /**
 310       * Deletes all addresses from this reference.
 311       */
 312     public void clear() {
 313         addrs.setSize(0);
 314     }
 315 
 316     /**
 317       * Determines whether obj is a reference with the same addresses
 318       * (in same order) as this reference.
 319       * The addresses are checked using RefAddr.equals().
 320       * In addition to having the same addresses, the Reference also needs to
 321       * have the same class name as this reference.
 322       * The class factory and class factory location are not checked.
 323       * If obj is null or not an instance of Reference, null is returned.
 324       *
 325       * @param obj The possibly null object to check.
 326       * @return true if obj is equal to this reference; false otherwise.
 327       */
 328     public boolean equals(Object obj) {
 329         if ((obj != null) && (obj instanceof Reference)) {
 330             Reference target = (Reference)obj;
 331             // ignore factory information
 332             if (target.className.equals(this.className) &&
 333                 target.size() ==  this.size()) {
 334                 Enumeration<RefAddr> mycomps = getAll();
 335                 Enumeration<RefAddr> comps = target.getAll();
 336                 while (mycomps.hasMoreElements())
 337                     if (!(mycomps.nextElement().equals(comps.nextElement())))
 338                         return false;
 339                 return true;
 340             }
 341         }
 342         return false;
 343     }
 344 
 345     /**
 346       * Computes the hash code of this reference.
 347       * The hash code is the sum of the hash code of its addresses.
 348       *
 349       * @return A hash code of this reference as an int.
 350       */
 351     public int hashCode() {
 352         int hash = className.hashCode();
 353         for (Enumeration<RefAddr> e = getAll(); e.hasMoreElements();)
 354             hash += e.nextElement().hashCode();
 355         return hash;
 356     }
 357 
 358     /**
 359       * Generates the string representation of this reference.
 360       * The string consists of the class name to which this reference refers,
 361       * and the string representation of each of its addresses.
 362       * This representation is intended for display only and not to be parsed.
 363       *
 364       * @return The non-null string representation of this reference.
 365       */
 366     public String toString() {
 367         StringBuilder sb = new StringBuilder();
 368         sb.append("Reference Class Name: ");
 369         sb.append(className).append('\n');
 370         int len = addrs.size();
 371         for (int i = 0; i < len; i++)
 372             sb.append(get(i).toString());
 373 
 374         return sb.toString();
 375     }
 376 
 377     /**
 378      * Makes a copy of this reference using its class name
 379      * list of addresses, class factory name and class factory location.
 380      * Changes to the newly created copy does not affect this Reference
 381      * and vice versa.
 382      */
 383     public Object clone() {
 384         Reference r = new Reference(className, classFactory, classFactoryLocation);
 385         Enumeration<RefAddr> a = getAll();
 386         r.addrs = new Vector<>();
 387 
 388         while (a.hasMoreElements())
 389             r.addrs.addElement(a.nextElement());
 390         return r;
 391     }
 392     /**
 393      * Use serialVersionUID from JNDI 1.1.1 for interoperability
 394      */
 395     private static final long serialVersionUID = -1673475790065791735L;
 396 };