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
26package javax.naming;
27
28import java.util.Vector;
29import 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
83public 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      *         ({@code RefAddr}) 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("Reference Class Name: " +
368                                             className + "\n");
369        int len = addrs.size();
370        for (int i = 0; i < len; i++)
371            sb.append(get(i).toString());
372
373        return sb.toString();
374    }
375
376    /**
377     * Makes a copy of this reference using its class name
378     * list of addresses, class factory name and class factory location.
379     * Changes to the newly created copy does not affect this Reference
380     * and vice versa.
381     */
382    public Object clone() {
383        Reference r = new Reference(className, classFactory, classFactoryLocation);
384        Enumeration<RefAddr> a = getAll();
385        r.addrs = new Vector<>();
386
387        while (a.hasMoreElements())
388            r.addrs.addElement(a.nextElement());
389        return r;
390    }
391    /**
392     * Use serialVersionUID from JNDI 1.1.1 for interoperability
393     */
394    private static final long serialVersionUID = -1673475790065791735L;
395};
396