Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/naming/directory/BasicAttributes.java
38918 views
/*1* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/242526package javax.naming.directory;2728import java.util.Hashtable;29import java.util.Enumeration;30import java.util.Locale;3132import javax.naming.NamingException;33import javax.naming.NamingEnumeration;3435/**36* This class provides a basic implementation37* of the Attributes interface.38*<p>39* BasicAttributes is either case-sensitive or case-insensitive (case-ignore).40* This property is determined at the time the BasicAttributes constructor41* is called.42* In a case-insensitive BasicAttributes, the case of its attribute identifiers43* is ignored when searching for an attribute, or adding attributes.44* In a case-sensitive BasicAttributes, the case is significant.45*<p>46* When the BasicAttributes class needs to create an Attribute, it47* uses BasicAttribute. There is no other dependency on BasicAttribute.48*<p>49* Note that updates to BasicAttributes (such as adding or removing an attribute)50* does not affect the corresponding representation in the directory.51* Updates to the directory can only be effected52* using operations in the DirContext interface.53*<p>54* A BasicAttributes instance is not synchronized against concurrent55* multithreaded access. Multiple threads trying to access and modify56* a single BasicAttributes instance should lock the object.57*58* @author Rosanna Lee59* @author Scott Seligman60*61* @see DirContext#getAttributes62* @see DirContext#modifyAttributes63* @see DirContext#bind64* @see DirContext#rebind65* @see DirContext#createSubcontext66* @see DirContext#search67* @since 1.368*/6970public class BasicAttributes implements Attributes {71/**72* Indicates whether case of attribute ids is ignored.73* @serial74*/75private boolean ignoreCase = false;7677// The 'key' in attrs is stored in the 'right case'.78// If ignoreCase is true, key is aways lowercase.79// If ignoreCase is false, key is stored as supplied by put().80// %%% Not declared "private" due to bug 4064984.81transient Hashtable<String,Attribute> attrs = new Hashtable<>(11);8283/**84* Constructs a new instance of Attributes.85* The character case of attribute identifiers86* is significant when subsequently retrieving or adding attributes.87*/88public BasicAttributes() {89}9091/**92* Constructs a new instance of Attributes.93* If <code>ignoreCase</code> is true, the character case of attribute94* identifiers is ignored; otherwise the case is significant.95* @param ignoreCase true means this attribute set will ignore96* the case of its attribute identifiers97* when retrieving or adding attributes;98* false means case is respected.99*/100public BasicAttributes(boolean ignoreCase) {101this.ignoreCase = ignoreCase;102}103104/**105* Constructs a new instance of Attributes with one attribute.106* The attribute specified by attrID and val are added to the newly107* created attribute.108* The character case of attribute identifiers109* is significant when subsequently retrieving or adding attributes.110* @param attrID non-null The id of the attribute to add.111* @param val The value of the attribute to add. If null, a null112* value is added to the attribute.113*/114public BasicAttributes(String attrID, Object val) {115this();116this.put(new BasicAttribute(attrID, val));117}118119/**120* Constructs a new instance of Attributes with one attribute.121* The attribute specified by attrID and val are added to the newly122* created attribute.123* If <code>ignoreCase</code> is true, the character case of attribute124* identifiers is ignored; otherwise the case is significant.125* @param attrID non-null The id of the attribute to add.126* If this attribute set ignores the character127* case of its attribute ids, the case of attrID128* is ignored.129* @param val The value of the attribute to add. If null, a null130* value is added to the attribute.131* @param ignoreCase true means this attribute set will ignore132* the case of its attribute identifiers133* when retrieving or adding attributes;134* false means case is respected.135*/136public BasicAttributes(String attrID, Object val, boolean ignoreCase) {137this(ignoreCase);138this.put(new BasicAttribute(attrID, val));139}140141@SuppressWarnings("unchecked")142public Object clone() {143BasicAttributes attrset;144try {145attrset = (BasicAttributes)super.clone();146} catch (CloneNotSupportedException e) {147attrset = new BasicAttributes(ignoreCase);148}149attrset.attrs = (Hashtable<String,Attribute>)attrs.clone();150return attrset;151}152153public boolean isCaseIgnored() {154return ignoreCase;155}156157public int size() {158return attrs.size();159}160161public Attribute get(String attrID) {162Attribute attr = attrs.get(163ignoreCase ? attrID.toLowerCase(Locale.ENGLISH) : attrID);164return (attr);165}166167public NamingEnumeration<Attribute> getAll() {168return new AttrEnumImpl();169}170171public NamingEnumeration<String> getIDs() {172return new IDEnumImpl();173}174175public Attribute put(String attrID, Object val) {176return this.put(new BasicAttribute(attrID, val));177}178179public Attribute put(Attribute attr) {180String id = attr.getID();181if (ignoreCase) {182id = id.toLowerCase(Locale.ENGLISH);183}184return attrs.put(id, attr);185}186187public Attribute remove(String attrID) {188String id = (ignoreCase ? attrID.toLowerCase(Locale.ENGLISH) : attrID);189return attrs.remove(id);190}191192/**193* Generates the string representation of this attribute set.194* The string consists of each attribute identifier and the contents195* of each attribute. The contents of this string is useful196* for debugging and is not meant to be interpreted programmatically.197*198* @return A non-null string listing the contents of this attribute set.199*/200public String toString() {201if (attrs.size() == 0) {202return("No attributes");203} else {204return attrs.toString();205}206}207208/**209* Determines whether this <tt>BasicAttributes</tt> is equal to another210* <tt>Attributes</tt>211* Two <tt>Attributes</tt> are equal if they are both instances of212* <tt>Attributes</tt>,213* treat the case of attribute IDs the same way, and contain the214* same attributes. Each <tt>Attribute</tt> in this <tt>BasicAttributes</tt>215* is checked for equality using <tt>Object.equals()</tt>, which may have216* be overridden by implementations of <tt>Attribute</tt>).217* If a subclass overrides <tt>equals()</tt>,218* it should override <tt>hashCode()</tt>219* as well so that two <tt>Attributes</tt> instances that are equal220* have the same hash code.221* @param obj the possibly null object to compare against.222*223* @return true If obj is equal to this BasicAttributes.224* @see #hashCode225*/226public boolean equals(Object obj) {227if ((obj != null) && (obj instanceof Attributes)) {228Attributes target = (Attributes)obj;229230// Check case first231if (ignoreCase != target.isCaseIgnored()) {232return false;233}234235if (size() == target.size()) {236Attribute their, mine;237try {238NamingEnumeration<?> theirs = target.getAll();239while (theirs.hasMore()) {240their = (Attribute)theirs.next();241mine = get(their.getID());242if (!their.equals(mine)) {243return false;244}245}246} catch (NamingException e) {247return false;248}249return true;250}251}252return false;253}254255/**256* Calculates the hash code of this BasicAttributes.257*<p>258* The hash code is computed by adding the hash code of259* the attributes of this object. If this BasicAttributes260* ignores case of its attribute IDs, one is added to the hash code.261* If a subclass overrides <tt>hashCode()</tt>,262* it should override <tt>equals()</tt>263* as well so that two <tt>Attributes</tt> instances that are equal264* have the same hash code.265*266* @return an int representing the hash code of this BasicAttributes instance.267* @see #equals268*/269public int hashCode() {270int hash = (ignoreCase ? 1 : 0);271try {272NamingEnumeration<?> all = getAll();273while (all.hasMore()) {274hash += all.next().hashCode();275}276} catch (NamingException e) {}277return hash;278}279280/**281* Overridden to avoid exposing implementation details.282* @serialData Default field (ignoreCase flag -- a boolean), followed by283* the number of attributes in the set284* (an int), and then the individual Attribute objects.285*/286private void writeObject(java.io.ObjectOutputStream s)287throws java.io.IOException {288s.defaultWriteObject(); // write out the ignoreCase flag289s.writeInt(attrs.size());290Enumeration<Attribute> attrEnum = attrs.elements();291while (attrEnum.hasMoreElements()) {292s.writeObject(attrEnum.nextElement());293}294}295296/**297* Overridden to avoid exposing implementation details.298*/299private void readObject(java.io.ObjectInputStream s)300throws java.io.IOException, ClassNotFoundException {301s.defaultReadObject(); // read in the ignoreCase flag302int n = s.readInt(); // number of attributes303attrs = (n >= 1)304? new Hashtable<>(1 + (int) (Math.min(768, n) / .75f))305: new Hashtable<>(2); // can't have initial size of 0 (grrr...)306while (--n >= 0) {307put((Attribute)s.readObject());308}309}310311312class AttrEnumImpl implements NamingEnumeration<Attribute> {313314Enumeration<Attribute> elements;315316public AttrEnumImpl() {317this.elements = attrs.elements();318}319320public boolean hasMoreElements() {321return elements.hasMoreElements();322}323324public Attribute nextElement() {325return elements.nextElement();326}327328public boolean hasMore() throws NamingException {329return hasMoreElements();330}331332public Attribute next() throws NamingException {333return nextElement();334}335336public void close() throws NamingException {337elements = null;338}339}340341class IDEnumImpl implements NamingEnumeration<String> {342343Enumeration<Attribute> elements;344345public IDEnumImpl() {346// Walking through the elements, rather than the keys, gives347// us attribute IDs that have not been converted to lowercase.348this.elements = attrs.elements();349}350351public boolean hasMoreElements() {352return elements.hasMoreElements();353}354355public String nextElement() {356Attribute attr = elements.nextElement();357return attr.getID();358}359360public boolean hasMore() throws NamingException {361return hasMoreElements();362}363364public String next() throws NamingException {365return nextElement();366}367368public void close() throws NamingException {369elements = null;370}371}372373/**374* Use serialVersionUID from JNDI 1.1.1 for interoperability.375*/376private static final long serialVersionUID = 4980164073184639448L;377}378379380