556 lines · 18.9 KB · Java
RawDownload
/* * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.naming.directory; import java.util.Vector;import java.util.Enumeration;import java.util.NoSuchElementException;import java.lang.reflect.Array; import javax.naming.NamingException;import javax.naming.NamingEnumeration;import javax.naming.OperationNotSupportedException; /**  * This class provides a basic implementation of the <tt>Attribute</tt> interface.  *<p>  * This implementation does not support the schema methods  * <tt>getAttributeDefinition()</tt> and <tt>getAttributeSyntaxDefinition()</tt>.  * They simply throw <tt>OperationNotSupportedException</tt>.  * Subclasses of <tt>BasicAttribute</tt> should override these methods if they  * support them.  *<p>  * The <tt>BasicAttribute</tt> class by default uses <tt>Object.equals()</tt> to  * determine equality of attribute values when testing for equality or  * when searching for values, <em>except</em> when the value is an array.  * For an array, each element of the array is checked using <tt>Object.equals()</tt>.  * Subclasses of <tt>BasicAttribute</tt> can make use of schema information  * when doing similar equality checks by overriding methods  * in which such use of schema is meaningful.  * Similarly, the <tt>BasicAttribute</tt> class by default returns the values passed to its  * constructor and/or manipulated using the add/remove methods.  * Subclasses of <tt>BasicAttribute</tt> can override <tt>get()</tt> and <tt>getAll()</tt>  * to get the values dynamically from the directory (or implement  * the <tt>Attribute</tt> interface directly instead of subclassing <tt>BasicAttribute</tt>).  *<p>  * Note that updates to <tt>BasicAttribute</tt> (such as adding or removing a value)  * does not affect the corresponding representation of the attribute  * in the directory.  Updates to the directory can only be effected  * using operations in the <tt>DirContext</tt> interface.  *<p>  * A <tt>BasicAttribute</tt> instance is not synchronized against concurrent  * multithreaded access. Multiple threads trying to access and modify a  * <tt>BasicAttribute</tt> should lock the object.  *  * @author Rosanna Lee  * @author Scott Seligman  * @since 1.3  */public class BasicAttribute implements Attribute {    /**     * Holds the attribute's id. It is initialized by the public constructor and     * cannot be null unless methods in BasicAttribute that use attrID     * have been overridden.     * @serial     */    protected String attrID;     /**     * Holds the attribute's values. Initialized by public constructors.     * Cannot be null unless methods in BasicAttribute that use     * values have been overridden.     */    protected transient Vector<Object> values;     /**     * A flag for recording whether this attribute's values are ordered.     * @serial     */    protected boolean ordered = false;     public Object clone() {        BasicAttribute attr;        try {            attr = (BasicAttribute)super.clone();        } catch (CloneNotSupportedException e) {            attr = new BasicAttribute(attrID, ordered);        }        attr.values = (Vector)values.clone();        return attr;    }     /**      * Determines whether obj is equal to this attribute.      * Two attributes are equal if their attribute-ids, syntaxes      * and values are equal.      * If the attribute values are unordered, the order that the values were added      * are irrelevant. If the attribute values are ordered, then the      * order the values must match.      * If obj is null or not an Attribute, false is returned.      *<p>      * By default <tt>Object.equals()</tt> is used when comparing the attribute      * id and its values except when a value is an array. For an array,      * each element of the array is checked using <tt>Object.equals()</tt>.      * A subclass may override this to make      * use of schema syntax information and matching rules,      * which define what it means for two attributes to be equal.      * How and whether a subclass makes      * use of the schema information is determined by the subclass.      * If a subclass overrides <tt>equals()</tt>, it should also override      * <tt>hashCode()</tt>      * such that two attributes that are equal have the same hash code.      *      * @param obj      The possibly null object to check.      * @return true if obj is equal to this attribute; false otherwise.      * @see #hashCode      * @see #contains      */    public boolean equals(Object obj) {        if ((obj != null) && (obj instanceof Attribute)) {            Attribute target = (Attribute)obj;             // Check order first            if (isOrdered() != target.isOrdered()) {                return false;            }            int len;            if (attrID.equals(target.getID()) &&                (len=size()) == target.size()) {                try {                    if (isOrdered()) {                        // Go through both list of values                        for (int i = 0; i < len; i++) {                            if (!valueEquals(get(i), target.get(i))) {                                return false;                            }                        }                    } else {                        // order is not relevant; check for existence                        Enumeration theirs = target.getAll();                        while (theirs.hasMoreElements()) {                            if (find(theirs.nextElement()) < 0)                                return false;                        }                    }                } catch (NamingException e) {                    return false;                }                return true;            }        }        return false;    }     /**      * Calculates the hash code of this attribute.      *<p>      * The hash code is computed by adding the hash code of      * the attribute's id and that of all of its values except for      * values that are arrays.      * For an array, the hash code of each element of the array is summed.      * If a subclass overrides <tt>hashCode()</tt>, it should override      * <tt>equals()</tt>      * as well so that two attributes that are equal have the same hash code.      *      * @return an int representing the hash code of this attribute.      * @see #equals      */    public int hashCode() {        int hash = attrID.hashCode();        int num = values.size();        Object val;        for (int i = 0; i < num; i ++) {            val = values.elementAt(i);            if (val != null) {                if (val.getClass().isArray()) {                    Object it;                    int len = Array.getLength(val);                    for (int j = 0 ; j < len ; j++) {                        it = Array.get(val, j);                        if (it != null) {                            hash += it.hashCode();                        }                    }                } else {                    hash += val.hashCode();                }            }        }        return hash;    }     /**      * Generates the string representation of this attribute.      * The string consists of the attribute's id and its values.      * This string is meant for debugging and not meant to be      * interpreted programmatically.      * @return The non-null string representation of this attribute.      */    public String toString() {        StringBuffer answer = new StringBuffer(attrID + ": ");        if (values.size() == 0) {            answer.append("No values");        } else {            boolean start = true;            for (Enumeration e = values.elements(); e.hasMoreElements(); ) {                if (!start)                    answer.append(", ");                answer.append(e.nextElement());                start = false;            }        }        return answer.toString();    }     /**      * Constructs a new instance of an unordered attribute with no value.      *      * @param id The attribute's id. It cannot be null.      */    public BasicAttribute(String id) {        this(id, false);    }     /**      * Constructs a new instance of an unordered attribute with a single value.      *      * @param id The attribute's id. It cannot be null.      * @param value The attribute's value. If null, a null      *        value is added to the attribute.      */    public BasicAttribute(String id, Object value) {        this(id, value, false);    }     /**      * Constructs a new instance of a possibly ordered attribute with no value.      *      * @param id The attribute's id. It cannot be null.      * @param ordered true means the attribute's values will be ordered;      * false otherwise.      */    public BasicAttribute(String id, boolean ordered) {        attrID = id;        values = new Vector();        this.ordered = ordered;    }     /**      * Constructs a new instance of a possibly ordered attribute with a      * single value.      *      * @param id The attribute's id. It cannot be null.      * @param value The attribute's value. If null, a null      *        value is added to the attribute.      * @param ordered true means the attribute's values will be ordered;      * false otherwise.      */    public BasicAttribute(String id, Object value, boolean ordered) {        this(id, ordered);        values.addElement(value);    }     /**      * Retrieves an enumeration of this attribute's values.      *<p>      * By default, the values returned are those passed to the      * constructor and/or manipulated using the add/replace/remove methods.      * A subclass may override this to retrieve the values dynamically      * from the directory.      */    public NamingEnumeration<?> getAll() throws NamingException {      return new ValuesEnumImpl();    }     /**      * Retrieves one of this attribute's values.      *<p>      * By default, the value returned is one of those passed to the      * constructor and/or manipulated using the add/replace/remove methods.      * A subclass may override this to retrieve the value dynamically      * from the directory.      */    public Object get() throws NamingException {        if (values.size() == 0) {            throw new        NoSuchElementException("Attribute " + getID() + " has no value");        } else {            return values.elementAt(0);        }    }     public int size() {      return values.size();    }     public String getID() {        return attrID;    }     /**      * Determines whether a value is in this attribute.      *<p>      * By default,      * <tt>Object.equals()</tt> is used when comparing <tt>attrVal</tt>      * with this attribute's values except when <tt>attrVal</tt> is an array.      * For an array, each element of the array is checked using      * <tt>Object.equals()</tt>.      * A subclass may use schema information to determine equality.      */    public boolean contains(Object attrVal) {        return (find(attrVal) >= 0);    }     // For finding first element that has a null in JDK1.1 Vector.    // In the Java 2 platform, can just replace this with Vector.indexOf(target);    private int find(Object target) {        Class cl;        if (target == null) {            int ct = values.size();            for (int i = 0 ; i < ct ; i++) {                if (values.elementAt(i) == null)                    return i;            }        } else if ((cl=target.getClass()).isArray()) {            int ct = values.size();            Object it;            for (int i = 0 ; i < ct ; i++) {                it = values.elementAt(i);                if (it != null && cl == it.getClass()                    && arrayEquals(target, it))                    return i;            }        } else {            return values.indexOf(target, 0);        }        return -1;  // not found    }     /**     * Determines whether two attribute values are equal.     * Use arrayEquals for arrays and <tt>Object.equals()</tt> otherwise.     */    private static boolean valueEquals(Object obj1, Object obj2) {        if (obj1 == obj2) {            return true; // object references are equal        }        if (obj1 == null) {            return false; // obj2 was not false        }        if (obj1.getClass().isArray() &&            obj2.getClass().isArray()) {            return arrayEquals(obj1, obj2);        }        return (obj1.equals(obj2));    }     /**     * Determines whether two arrays are equal by comparing each of their     * elements using <tt>Object.equals()</tt>.     */    private static boolean arrayEquals(Object a1, Object a2) {        int len;        if ((len = Array.getLength(a1)) != Array.getLength(a2))            return false;         for (int j = 0; j < len; j++) {            Object i1 = Array.get(a1, j);            Object i2 = Array.get(a2, j);            if (i1 == null || i2 == null) {                if (i1 != i2)                    return false;            } else if (!i1.equals(i2)) {                return false;            }        }        return true;    }     /**      * Adds a new value to this attribute.      *<p>      * By default, <tt>Object.equals()</tt> is used when comparing <tt>attrVal</tt>      * with this attribute's values except when <tt>attrVal</tt> is an array.      * For an array, each element of the array is checked using      * <tt>Object.equals()</tt>.      * A subclass may use schema information to determine equality.      */    public boolean add(Object attrVal) {        if (isOrdered() || (find(attrVal) < 0)) {            values.addElement(attrVal);            return true;        } else {            return false;        }    }     /**      * Removes a specified value from this attribute.      *<p>      * By default, <tt>Object.equals()</tt> is used when comparing <tt>attrVal</tt>      * with this attribute's values except when <tt>attrVal</tt> is an array.      * For an array, each element of the array is checked using      * <tt>Object.equals()</tt>.      * A subclass may use schema information to determine equality.      */    public boolean remove(Object attrval) {        // For the Java 2 platform, can just use "return removeElement(attrval);"        // Need to do the following to handle null case         int i = find(attrval);        if (i >= 0) {            values.removeElementAt(i);            return true;        }        return false;    }     public void clear() {        values.setSize(0);    } //  ---- ordering methods     public boolean isOrdered() {        return ordered;    }     public Object get(int ix) throws NamingException {        return values.elementAt(ix);    }     public Object remove(int ix) {        Object answer = values.elementAt(ix);        values.removeElementAt(ix);        return answer;    }     public void add(int ix, Object attrVal) {        if (!isOrdered() && contains(attrVal)) {            throw new IllegalStateException(                "Cannot add duplicate to unordered attribute");        }        values.insertElementAt(attrVal, ix);    }     public Object set(int ix, Object attrVal) {        if (!isOrdered() && contains(attrVal)) {            throw new IllegalStateException(                "Cannot add duplicate to unordered attribute");        }         Object answer = values.elementAt(ix);        values.setElementAt(attrVal, ix);        return answer;    } // ----------------- Schema methods     /**      * Retrieves the syntax definition associated with this attribute.      *<p>      * This method by default throws OperationNotSupportedException. A subclass      * should override this method if it supports schema.      */    public DirContext getAttributeSyntaxDefinition() throws NamingException {            throw new OperationNotSupportedException("attribute syntax");    }     /**      * Retrieves this attribute's schema definition.      *<p>      * This method by default throws OperationNotSupportedException. A subclass      * should override this method if it supports schema.      */    public DirContext getAttributeDefinition() throws NamingException {        throw new OperationNotSupportedException("attribute definition");    }  //  ---- serialization methods     /**     * Overridden to avoid exposing implementation details     * @serialData Default field (the attribute ID -- a String),     * followed by the number of values (an int), and the     * individual values.     */

Lines 1–500 of 556.