376 lines · 12.6 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.Hashtable;import java.util.Enumeration; import javax.naming.NamingException;import javax.naming.NamingEnumeration; /**  * This class provides a basic implementation  * of the Attributes interface.  *<p>  * BasicAttributes is either case-sensitive or case-insensitive (case-ignore).  * This property is determined at the time the BasicAttributes constructor  * is called.  * In a case-insensitive BasicAttributes, the case of its attribute identifiers  * is ignored when searching for an attribute, or adding attributes.  * In a case-sensitive BasicAttributes, the case is significant.  *<p>  * When the BasicAttributes class needs to create an Attribute, it  * uses BasicAttribute. There is no other dependency on BasicAttribute.  *<p>  * Note that updates to BasicAttributes (such as adding or removing an attribute)  * does not affect the corresponding representation in the directory.  * Updates to the directory can only be effected  * using operations in the DirContext interface.  *<p>  * A BasicAttributes instance is not synchronized against concurrent  * multithreaded access. Multiple threads trying to access and modify  * a single BasicAttributes instance should lock the object.  *  * @author Rosanna Lee  * @author Scott Seligman  *  * @see DirContext#getAttributes  * @see DirContext#modifyAttributes  * @see DirContext#bind  * @see DirContext#rebind  * @see DirContext#createSubcontext  * @see DirContext#search  * @since 1.3  */ public class BasicAttributes implements Attributes {    /**     * Indicates whether case of attribute ids is ignored.     * @serial     */    private boolean ignoreCase = false;     // The 'key' in attrs is stored in the 'right case'.    // If ignoreCase is true, key is aways lowercase.    // If ignoreCase is false, key is stored as supplied by put().    // %%% Not declared "private" due to bug 4064984.    transient Hashtable attrs = new Hashtable(11);     /**      * Constructs a new instance of Attributes.      * The character case of attribute identifiers      * is significant when subsequently retrieving or adding attributes.      */    public BasicAttributes() {    }     /**      * Constructs a new instance of Attributes.      * If <code>ignoreCase</code> is true, the character case of attribute      * identifiers is ignored; otherwise the case is significant.      * @param ignoreCase true means this attribute set will ignore      *                   the case of its attribute identifiers      *                   when retrieving or adding attributes;      *                   false means case is respected.      */    public BasicAttributes(boolean ignoreCase) {        this.ignoreCase = ignoreCase;    }     /**      * Constructs a new instance of Attributes with one attribute.      * The attribute specified by attrID and val are added to the newly      * created attribute.      * The character case of attribute identifiers      * is significant when subsequently retrieving or adding attributes.      * @param attrID   non-null The id of the attribute to add.      * @param val The value of the attribute to add. If null, a null      *        value is added to the attribute.      */    public BasicAttributes(String attrID, Object val) {        this();        this.put(new BasicAttribute(attrID, val));    }     /**      * Constructs a new instance of Attributes with one attribute.      * The attribute specified by attrID and val are added to the newly      * created attribute.      * If <code>ignoreCase</code> is true, the character case of attribute      * identifiers is ignored; otherwise the case is significant.      * @param attrID   non-null The id of the attribute to add.      *           If this attribute set ignores the character      *           case of its attribute ids, the case of attrID      *           is ignored.      * @param val The value of the attribute to add. If null, a null      *        value is added to the attribute.      * @param ignoreCase true means this attribute set will ignore      *                   the case of its attribute identifiers      *                   when retrieving or adding attributes;      *                   false means case is respected.      */    public BasicAttributes(String attrID, Object val, boolean ignoreCase) {        this(ignoreCase);        this.put(new BasicAttribute(attrID, val));    }     public Object clone() {        BasicAttributes attrset;        try {            attrset = (BasicAttributes)super.clone();        } catch (CloneNotSupportedException e) {            attrset = new BasicAttributes(ignoreCase);        }        attrset.attrs = (Hashtable)attrs.clone();        return attrset;    }     public boolean isCaseIgnored() {        return ignoreCase;    }     public int size() {        return attrs.size();    }     public Attribute get(String attrID) {        Attribute attr = (Attribute) attrs.get(                ignoreCase ? attrID.toLowerCase() : attrID);        return (attr);    }     public NamingEnumeration<Attribute> getAll() {        return new AttrEnumImpl();    }     public NamingEnumeration<String> getIDs() {        return new IDEnumImpl();    }     public Attribute put(String attrID, Object val) {        return this.put(new BasicAttribute(attrID, val));    }     public Attribute put(Attribute attr) {        String id = attr.getID();        if (ignoreCase) {            id = id.toLowerCase();        }        return (Attribute)attrs.put(id, attr);    }     public Attribute remove(String attrID) {        String id = (ignoreCase ? attrID.toLowerCase() : attrID);        return (Attribute)attrs.remove(id);    }     /**     * Generates the string representation of this attribute set.     * The string consists of each attribute identifier and the contents     * of each attribute. The contents of this string is useful     * for debugging and is not meant to be interpreted programmatically.     *     * @return A non-null string listing the contents of this attribute set.     */    public String toString() {        if (attrs.size() == 0) {            return("No attributes");        } else {            return attrs.toString();        }    }     /**     * Determines whether this <tt>BasicAttributes</tt> is equal to another     * <tt>Attributes</tt>     * Two <tt>Attributes</tt> are equal if they are both instances of     * <tt>Attributes</tt>,     * treat the case of attribute IDs the same way, and contain the     * same attributes. Each <tt>Attribute</tt> in this <tt>BasicAttributes</tt>     * is checked for equality using <tt>Object.equals()</tt>, which may have     * be overridden by implementations of <tt>Attribute</tt>).     * If a subclass overrides <tt>equals()</tt>,     * it should override <tt>hashCode()</tt>     * as well so that two <tt>Attributes</tt> instances that are equal     * have the same hash code.     * @param obj the possibly null object to compare against.     *     * @return true If obj is equal to this BasicAttributes.     * @see #hashCode     */    public boolean equals(Object obj) {        if ((obj != null) && (obj instanceof Attributes)) {            Attributes target = (Attributes)obj;             // Check case first            if (ignoreCase != target.isCaseIgnored()) {                return false;            }             if (size() == target.size()) {                Attribute their, mine;                try {                    NamingEnumeration theirs = target.getAll();                    while (theirs.hasMore()) {                        their = (Attribute)theirs.next();                        mine = get(their.getID());                        if (!their.equals(mine)) {                            return false;                        }                    }                } catch (NamingException e) {                    return false;                }                return true;            }        }        return false;    }     /**     * Calculates the hash code of this BasicAttributes.     *<p>     * The hash code is computed by adding the hash code of     * the attributes of this object. If this BasicAttributes     * ignores case of its attribute IDs, one is added to the hash code.     * If a subclass overrides <tt>hashCode()</tt>,     * it should override <tt>equals()</tt>     * as well so that two <tt>Attributes</tt> instances that are equal     * have the same hash code.     *     * @return an int representing the hash code of this BasicAttributes instance.     * @see #equals     */    public int hashCode() {        int hash = (ignoreCase ? 1 : 0);        try {            NamingEnumeration all = getAll();            while (all.hasMore()) {                hash += all.next().hashCode();            }        } catch (NamingException e) {}        return hash;    }     /**     * Overridden to avoid exposing implementation details.     * @serialData Default field (ignoreCase flag -- a boolean), followed by     * the number of attributes in the set     * (an int), and then the individual Attribute objects.     */    private void writeObject(java.io.ObjectOutputStream s)            throws java.io.IOException {        s.defaultWriteObject(); // write out the ignoreCase flag        s.writeInt(attrs.size());        Enumeration attrEnum = attrs.elements();        while (attrEnum.hasMoreElements()) {            s.writeObject(attrEnum.nextElement());        }    }     /**     * Overridden to avoid exposing implementation details.     */    private void readObject(java.io.ObjectInputStream s)            throws java.io.IOException, ClassNotFoundException {        s.defaultReadObject();  // read in the ignoreCase flag        int n = s.readInt();    // number of attributes        attrs = (n >= 1)            ? new Hashtable(n * 2)            : new Hashtable(2); // can't have initial size of 0 (grrr...)        while (--n >= 0) {            put((Attribute)s.readObject());        }    }  class AttrEnumImpl implements NamingEnumeration<Attribute> {     Enumeration<Attribute> elements;     public AttrEnumImpl() {        this.elements = attrs.elements();    }     public boolean hasMoreElements() {        return elements.hasMoreElements();    }     public Attribute nextElement() {        return elements.nextElement();    }     public boolean hasMore() throws NamingException {        return hasMoreElements();    }     public Attribute next() throws NamingException {        return nextElement();    }     public void close() throws NamingException {        elements = null;    }} class IDEnumImpl implements NamingEnumeration<String> {     Enumeration<Attribute> elements;     public IDEnumImpl() {        // Walking through the elements, rather than the keys, gives        // us attribute IDs that have not been converted to lowercase.        this.elements = attrs.elements();    }     public boolean hasMoreElements() {        return elements.hasMoreElements();    }     public String nextElement() {        Attribute attr = elements.nextElement();        return attr.getID();    }     public boolean hasMore() throws NamingException {        return hasMoreElements();    }     public String next() throws NamingException {        return nextElement();    }     public void close() throws NamingException {        elements = null;    }}     /**     * Use serialVersionUID from JNDI 1.1.1 for interoperability.     */    private static final long serialVersionUID = 4980164073184639448L;}