0N/A/*
2362N/A * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A
0N/Apackage javax.naming.directory;
0N/A
0N/Aimport java.util.Hashtable;
0N/Aimport java.util.Enumeration;
0N/A
0N/Aimport javax.naming.NamingException;
0N/Aimport javax.naming.NamingEnumeration;
0N/A
0N/A/**
0N/A * This class provides a basic implementation
0N/A * of the Attributes interface.
0N/A *<p>
0N/A * BasicAttributes is either case-sensitive or case-insensitive (case-ignore).
0N/A * This property is determined at the time the BasicAttributes constructor
0N/A * is called.
0N/A * In a case-insensitive BasicAttributes, the case of its attribute identifiers
0N/A * is ignored when searching for an attribute, or adding attributes.
0N/A * In a case-sensitive BasicAttributes, the case is significant.
0N/A *<p>
0N/A * When the BasicAttributes class needs to create an Attribute, it
0N/A * uses BasicAttribute. There is no other dependency on BasicAttribute.
0N/A *<p>
0N/A * Note that updates to BasicAttributes (such as adding or removing an attribute)
0N/A * does not affect the corresponding representation in the directory.
0N/A * Updates to the directory can only be effected
0N/A * using operations in the DirContext interface.
0N/A *<p>
0N/A * A BasicAttributes instance is not synchronized against concurrent
0N/A * multithreaded access. Multiple threads trying to access and modify
0N/A * a single BasicAttributes instance should lock the object.
0N/A *
0N/A * @author Rosanna Lee
0N/A * @author Scott Seligman
0N/A *
0N/A * @see DirContext#getAttributes
0N/A * @see DirContext#modifyAttributes
0N/A * @see DirContext#bind
0N/A * @see DirContext#rebind
0N/A * @see DirContext#createSubcontext
0N/A * @see DirContext#search
0N/A * @since 1.3
0N/A */
0N/A
0N/Apublic class BasicAttributes implements Attributes {
0N/A /**
0N/A * Indicates whether case of attribute ids is ignored.
0N/A * @serial
0N/A */
0N/A private boolean ignoreCase = false;
0N/A
0N/A // The 'key' in attrs is stored in the 'right case'.
0N/A // If ignoreCase is true, key is aways lowercase.
0N/A // If ignoreCase is false, key is stored as supplied by put().
0N/A // %%% Not declared "private" due to bug 4064984.
0N/A transient Hashtable attrs = new Hashtable(11);
0N/A
0N/A /**
0N/A * Constructs a new instance of Attributes.
0N/A * The character case of attribute identifiers
0N/A * is significant when subsequently retrieving or adding attributes.
0N/A */
0N/A public BasicAttributes() {
0N/A }
0N/A
0N/A /**
0N/A * Constructs a new instance of Attributes.
0N/A * If <code>ignoreCase</code> is true, the character case of attribute
0N/A * identifiers is ignored; otherwise the case is significant.
0N/A * @param ignoreCase true means this attribute set will ignore
0N/A * the case of its attribute identifiers
0N/A * when retrieving or adding attributes;
0N/A * false means case is respected.
0N/A */
0N/A public BasicAttributes(boolean ignoreCase) {
0N/A this.ignoreCase = ignoreCase;
0N/A }
0N/A
0N/A /**
0N/A * Constructs a new instance of Attributes with one attribute.
0N/A * The attribute specified by attrID and val are added to the newly
0N/A * created attribute.
0N/A * The character case of attribute identifiers
0N/A * is significant when subsequently retrieving or adding attributes.
0N/A * @param attrID non-null The id of the attribute to add.
0N/A * @param val The value of the attribute to add. If null, a null
0N/A * value is added to the attribute.
0N/A */
0N/A public BasicAttributes(String attrID, Object val) {
0N/A this();
0N/A this.put(new BasicAttribute(attrID, val));
0N/A }
0N/A
0N/A /**
0N/A * Constructs a new instance of Attributes with one attribute.
0N/A * The attribute specified by attrID and val are added to the newly
0N/A * created attribute.
0N/A * If <code>ignoreCase</code> is true, the character case of attribute
0N/A * identifiers is ignored; otherwise the case is significant.
0N/A * @param attrID non-null The id of the attribute to add.
0N/A * If this attribute set ignores the character
0N/A * case of its attribute ids, the case of attrID
0N/A * is ignored.
0N/A * @param val The value of the attribute to add. If null, a null
0N/A * value is added to the attribute.
0N/A * @param ignoreCase true means this attribute set will ignore
0N/A * the case of its attribute identifiers
0N/A * when retrieving or adding attributes;
0N/A * false means case is respected.
0N/A */
0N/A public BasicAttributes(String attrID, Object val, boolean ignoreCase) {
0N/A this(ignoreCase);
0N/A this.put(new BasicAttribute(attrID, val));
0N/A }
0N/A
0N/A public Object clone() {
0N/A BasicAttributes attrset;
0N/A try {
0N/A attrset = (BasicAttributes)super.clone();
0N/A } catch (CloneNotSupportedException e) {
0N/A attrset = new BasicAttributes(ignoreCase);
0N/A }
0N/A attrset.attrs = (Hashtable)attrs.clone();
0N/A return attrset;
0N/A }
0N/A
0N/A public boolean isCaseIgnored() {
0N/A return ignoreCase;
0N/A }
0N/A
0N/A public int size() {
0N/A return attrs.size();
0N/A }
0N/A
0N/A public Attribute get(String attrID) {
0N/A Attribute attr = (Attribute) attrs.get(
0N/A ignoreCase ? attrID.toLowerCase() : attrID);
0N/A return (attr);
0N/A }
0N/A
0N/A public NamingEnumeration<Attribute> getAll() {
0N/A return new AttrEnumImpl();
0N/A }
0N/A
0N/A public NamingEnumeration<String> getIDs() {
0N/A return new IDEnumImpl();
0N/A }
0N/A
0N/A public Attribute put(String attrID, Object val) {
0N/A return this.put(new BasicAttribute(attrID, val));
0N/A }
0N/A
0N/A public Attribute put(Attribute attr) {
0N/A String id = attr.getID();
0N/A if (ignoreCase) {
0N/A id = id.toLowerCase();
0N/A }
0N/A return (Attribute)attrs.put(id, attr);
0N/A }
0N/A
0N/A public Attribute remove(String attrID) {
0N/A String id = (ignoreCase ? attrID.toLowerCase() : attrID);
0N/A return (Attribute)attrs.remove(id);
0N/A }
0N/A
0N/A /**
0N/A * Generates the string representation of this attribute set.
0N/A * The string consists of each attribute identifier and the contents
0N/A * of each attribute. The contents of this string is useful
0N/A * for debugging and is not meant to be interpreted programmatically.
0N/A *
0N/A * @return A non-null string listing the contents of this attribute set.
0N/A */
0N/A public String toString() {
0N/A if (attrs.size() == 0) {
0N/A return("No attributes");
0N/A } else {
0N/A return attrs.toString();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Determines whether this <tt>BasicAttributes</tt> is equal to another
0N/A * <tt>Attributes</tt>
0N/A * Two <tt>Attributes</tt> are equal if they are both instances of
0N/A * <tt>Attributes</tt>,
0N/A * treat the case of attribute IDs the same way, and contain the
0N/A * same attributes. Each <tt>Attribute</tt> in this <tt>BasicAttributes</tt>
0N/A * is checked for equality using <tt>Object.equals()</tt>, which may have
0N/A * be overridden by implementations of <tt>Attribute</tt>).
0N/A * If a subclass overrides <tt>equals()</tt>,
0N/A * it should override <tt>hashCode()</tt>
0N/A * as well so that two <tt>Attributes</tt> instances that are equal
0N/A * have the same hash code.
0N/A * @param obj the possibly null object to compare against.
0N/A *
0N/A * @return true If obj is equal to this BasicAttributes.
0N/A * @see #hashCode
0N/A */
0N/A public boolean equals(Object obj) {
0N/A if ((obj != null) && (obj instanceof Attributes)) {
0N/A Attributes target = (Attributes)obj;
0N/A
0N/A // Check case first
0N/A if (ignoreCase != target.isCaseIgnored()) {
0N/A return false;
0N/A }
0N/A
0N/A if (size() == target.size()) {
0N/A Attribute their, mine;
0N/A try {
0N/A NamingEnumeration theirs = target.getAll();
0N/A while (theirs.hasMore()) {
0N/A their = (Attribute)theirs.next();
0N/A mine = get(their.getID());
0N/A if (!their.equals(mine)) {
0N/A return false;
0N/A }
0N/A }
0N/A } catch (NamingException e) {
0N/A return false;
0N/A }
0N/A return true;
0N/A }
0N/A }
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Calculates the hash code of this BasicAttributes.
0N/A *<p>
0N/A * The hash code is computed by adding the hash code of
0N/A * the attributes of this object. If this BasicAttributes
0N/A * ignores case of its attribute IDs, one is added to the hash code.
0N/A * If a subclass overrides <tt>hashCode()</tt>,
0N/A * it should override <tt>equals()</tt>
0N/A * as well so that two <tt>Attributes</tt> instances that are equal
0N/A * have the same hash code.
0N/A *
0N/A * @return an int representing the hash code of this BasicAttributes instance.
0N/A * @see #equals
0N/A */
0N/A public int hashCode() {
0N/A int hash = (ignoreCase ? 1 : 0);
0N/A try {
0N/A NamingEnumeration all = getAll();
0N/A while (all.hasMore()) {
0N/A hash += all.next().hashCode();
0N/A }
0N/A } catch (NamingException e) {}
0N/A return hash;
0N/A }
0N/A
0N/A /**
0N/A * Overridden to avoid exposing implementation details.
0N/A * @serialData Default field (ignoreCase flag -- a boolean), followed by
0N/A * the number of attributes in the set
0N/A * (an int), and then the individual Attribute objects.
0N/A */
0N/A private void writeObject(java.io.ObjectOutputStream s)
0N/A throws java.io.IOException {
0N/A s.defaultWriteObject(); // write out the ignoreCase flag
0N/A s.writeInt(attrs.size());
0N/A Enumeration attrEnum = attrs.elements();
0N/A while (attrEnum.hasMoreElements()) {
0N/A s.writeObject(attrEnum.nextElement());
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Overridden to avoid exposing implementation details.
0N/A */
0N/A private void readObject(java.io.ObjectInputStream s)
0N/A throws java.io.IOException, ClassNotFoundException {
0N/A s.defaultReadObject(); // read in the ignoreCase flag
0N/A int n = s.readInt(); // number of attributes
0N/A attrs = (n >= 1)
0N/A ? new Hashtable(n * 2)
0N/A : new Hashtable(2); // can't have initial size of 0 (grrr...)
0N/A while (--n >= 0) {
0N/A put((Attribute)s.readObject());
0N/A }
0N/A }
0N/A
0N/A
0N/Aclass AttrEnumImpl implements NamingEnumeration<Attribute> {
0N/A
0N/A Enumeration<Attribute> elements;
0N/A
0N/A public AttrEnumImpl() {
0N/A this.elements = attrs.elements();
0N/A }
0N/A
0N/A public boolean hasMoreElements() {
0N/A return elements.hasMoreElements();
0N/A }
0N/A
0N/A public Attribute nextElement() {
0N/A return elements.nextElement();
0N/A }
0N/A
0N/A public boolean hasMore() throws NamingException {
0N/A return hasMoreElements();
0N/A }
0N/A
0N/A public Attribute next() throws NamingException {
0N/A return nextElement();
0N/A }
0N/A
0N/A public void close() throws NamingException {
0N/A elements = null;
0N/A }
0N/A}
0N/A
0N/Aclass IDEnumImpl implements NamingEnumeration<String> {
0N/A
0N/A Enumeration<Attribute> elements;
0N/A
0N/A public IDEnumImpl() {
0N/A // Walking through the elements, rather than the keys, gives
0N/A // us attribute IDs that have not been converted to lowercase.
0N/A this.elements = attrs.elements();
0N/A }
0N/A
0N/A public boolean hasMoreElements() {
0N/A return elements.hasMoreElements();
0N/A }
0N/A
0N/A public String nextElement() {
0N/A Attribute attr = elements.nextElement();
0N/A return attr.getID();
0N/A }
0N/A
0N/A public boolean hasMore() throws NamingException {
0N/A return hasMoreElements();
0N/A }
0N/A
0N/A public String next() throws NamingException {
0N/A return nextElement();
0N/A }
0N/A
0N/A public void close() throws NamingException {
0N/A elements = null;
0N/A }
0N/A}
0N/A
0N/A /**
0N/A * Use serialVersionUID from JNDI 1.1.1 for interoperability.
0N/A */
0N/A private static final long serialVersionUID = 4980164073184639448L;
0N/A}