mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-14 00:14:33 +00:00
408 lines
14 KiB
Java
408 lines
14 KiB
Java
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1999 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
package netscape.ldap;
|
|
|
|
import java.util.*;
|
|
import netscape.ldap.client.*;
|
|
import netscape.ldap.client.opers.*;
|
|
|
|
/**
|
|
* Represents a set of attributes (for example, the set of attributes
|
|
* in an entry).
|
|
*
|
|
* @version 1.0
|
|
* @see netscape.ldap.LDAPAttribute
|
|
*/
|
|
public class LDAPAttributeSet implements Cloneable, java.io.Serializable {
|
|
static final long serialVersionUID = 5018474561697778100L;
|
|
Hashtable attrHash = null;
|
|
LDAPAttribute[] attrs = new LDAPAttribute[0];
|
|
/* If there are less attributes than this in the set, it's not worth
|
|
creating a Hashtable - faster and cheaper most likely to string
|
|
comparisons. Most applications fetch attributes once only, anyway */
|
|
static final int ATTR_COUNT_REQUIRES_HASH = 5;
|
|
|
|
/**
|
|
* Constructs a new set of attributes. This set is initially empty.
|
|
*/
|
|
public LDAPAttributeSet() {
|
|
}
|
|
|
|
/**
|
|
* Constructs an attribute set.
|
|
* @param attrs the list of attributes
|
|
*/
|
|
public LDAPAttributeSet( LDAPAttribute[] attrs ) {
|
|
this.attrs = attrs;
|
|
}
|
|
|
|
public synchronized Object clone() {
|
|
try {
|
|
LDAPAttributeSet attributeSet = new LDAPAttributeSet();
|
|
attributeSet.attrs = new LDAPAttribute[attrs.length];
|
|
for (int i = 0; i < attrs.length; i++) {
|
|
attributeSet.attrs[i] = new LDAPAttribute(attrs[i]);
|
|
}
|
|
return attributeSet;
|
|
} catch (Exception e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns an enumeration of the attributes in this attribute set.
|
|
* @return enumeration of the attributes in this set.
|
|
*/
|
|
public Enumeration getAttributes () {
|
|
Vector v = new Vector();
|
|
synchronized(this) {
|
|
for (int i=0; i<attrs.length; i++) {
|
|
v.addElement(attrs[i]);
|
|
}
|
|
}
|
|
return v.elements();
|
|
}
|
|
|
|
/**
|
|
* Creates a new attribute set containing only the attributes
|
|
* that have the specified subtypes.
|
|
* <P>
|
|
*
|
|
* For example, suppose an attribute set contains the following attributes:
|
|
* <P>
|
|
*
|
|
* <PRE>
|
|
* cn
|
|
* cn;lang-ja
|
|
* sn;phonetic;lang-ja
|
|
* sn;lang-us
|
|
* </PRE>
|
|
*
|
|
* If you call the <CODE>getSubset</CODE> method and pass
|
|
* <CODE>lang-ja</CODE> as the argument, the method returns
|
|
* an attribute set containing the following attributes:
|
|
* <P>
|
|
*
|
|
* <PRE>
|
|
* cn;lang-ja
|
|
* sn;phonetic;lang-ja
|
|
* </PRE>
|
|
*
|
|
* @param subtype semi-colon delimited list of subtypes
|
|
* to find within attribute names.
|
|
* For example:
|
|
* <PRE>
|
|
* "lang-ja" // Only Japanese language subtypes
|
|
* "binary" // Only binary subtypes
|
|
* "binary;lang-ja" // Only Japanese language subtypes
|
|
* which also are binary
|
|
* </PRE>
|
|
* @return attribute set containing the attributes that have
|
|
* the specified subtypes.
|
|
* @see netscape.ldap.LDAPAttribute
|
|
* @see netscape.ldap.LDAPAttributeSet#getAttribute
|
|
* @see netscape.ldap.LDAPEntry#getAttributeSet
|
|
*/
|
|
public LDAPAttributeSet getSubset(String subtype) {
|
|
LDAPAttributeSet attrs = new LDAPAttributeSet();
|
|
if ( subtype == null )
|
|
return attrs;
|
|
StringTokenizer st = new StringTokenizer(subtype, ";");
|
|
if( st.countTokens() < 1 )
|
|
return attrs;
|
|
String[] searchTypes = new String[st.countTokens()];
|
|
int i = 0;
|
|
while( st.hasMoreElements() ) {
|
|
searchTypes[i] = (String)st.nextElement();
|
|
i++;
|
|
}
|
|
Enumeration attrEnum = getAttributes();
|
|
while( attrEnum.hasMoreElements() ) {
|
|
LDAPAttribute attr = (LDAPAttribute)attrEnum.nextElement();
|
|
if( attr.hasSubtypes( searchTypes ) )
|
|
attrs.add( new LDAPAttribute( attr ) );
|
|
}
|
|
return attrs;
|
|
}
|
|
|
|
/**
|
|
* Returns a single attribute that exactly matches the specified attribute
|
|
* name.
|
|
* @param attrName name of attribute to return
|
|
* For example:
|
|
*<PRE>
|
|
* "cn" // Only a non-subtyped version of cn
|
|
* "cn;lang-ja" // Only a Japanese version of cn
|
|
*</PRE>
|
|
* @return attribute that has exactly the same name, or null
|
|
* (if no attribute in the set matches the specified name).
|
|
* @see netscape.ldap.LDAPAttribute
|
|
*/
|
|
public LDAPAttribute getAttribute( String attrName ) {
|
|
prepareHashtable();
|
|
if (attrHash != null) {
|
|
return (LDAPAttribute)attrHash.get( attrName.toLowerCase() );
|
|
} else {
|
|
for (int i = 0; i < attrs.length; i++) {
|
|
if (attrName.equalsIgnoreCase(attrs[i].getName())) {
|
|
return attrs[i];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prepares hashtable for fast attribute lookups.
|
|
*/
|
|
private void prepareHashtable() {
|
|
if ((attrHash == null) && (attrs.length >= ATTR_COUNT_REQUIRES_HASH)) {
|
|
attrHash = new Hashtable();
|
|
for (int j = 0; j < attrs.length; j++) {
|
|
attrHash.put( attrs[j].getName().toLowerCase(), attrs[j] );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the subtype that matches the attribute name specified
|
|
* by <CODE>attrName</CODE> and the language specificaton identified
|
|
* by <CODE>lang</CODE>.
|
|
* <P>
|
|
*
|
|
* If no attribute in the set has the specified name and subtype,
|
|
* the method returns <CODE>null</CODE>.
|
|
*
|
|
* Attributes containing subtypes other than <CODE>lang</CODE>
|
|
* (for example, <CODE>cn;binary</CODE>) are returned only if
|
|
* they contain the specified <CODE>lang</CODE> subtype and if
|
|
* the set contains no attribute having only the <CODE>lang</CODE>
|
|
* subtype. (For example, <CODE>getAttribute( "cn", "lang-ja" )</CODE>
|
|
* returns <CODE>cn;lang-ja;phonetic</CODE> only if the
|
|
* <CODE>cn;lang-ja</CODE> attribute does not exist.)
|
|
* <P>
|
|
*
|
|
* If null is specified for the <CODE>lang</CODE> argument,
|
|
* calling this method is the same as calling the
|
|
* <CODE>getAttribute(attrName)</CODE> method.
|
|
* <P>
|
|
*
|
|
* For example, suppose an entry contains only the following attributes:
|
|
* <P>
|
|
* <UL>
|
|
* <LI><CODE>cn;lang-en</CODE>
|
|
* <LI><CODE>cn;lang-ja-JP-kanji</CODE>
|
|
* <LI><CODE>sn</CODE>
|
|
* </UL>
|
|
* <P>
|
|
*
|
|
* Calling the following methods will return the following values:
|
|
* <P>
|
|
* <UL>
|
|
* <LI><CODE>getAttribute( "cn" )</CODE> returns <CODE>null</CODE>.
|
|
* <LI><CODE>getAttribute( "sn" )</CODE> returns the "<CODE>sn</CODE>" attribute.
|
|
* <LI><CODE>getAttribute( "cn", "lang-en-us" )</CODE> returns the "<CODE>cn;lang-en</CODE>" attribute.
|
|
* <LI><CODE>getAttribute( "cn", "lang-en" )</CODE> returns the "<CODE>cn;lang-en</CODE>" attribute.
|
|
* <LI><CODE>getAttribute( "cn", "lang-ja" )</CODE> returns <CODE>null</CODE>.
|
|
* <LI><CODE>getAttribute( "sn", "lang-en" )</CODE> returns the "<CODE>sn</CODE>" attribute.
|
|
*</UL>
|
|
* <P>
|
|
* @param attrName name of attribute to find in the entry
|
|
* @param lang a language specification
|
|
* @return the attribute that matches the base name and that best
|
|
* matches any specified language subtype.
|
|
* @see netscape.ldap.LDAPAttribute
|
|
*/
|
|
public LDAPAttribute getAttribute( String attrName, String lang ) {
|
|
if ( (lang == null) || (lang.length() < 1) )
|
|
return getAttribute( attrName );
|
|
|
|
String langLower = lang.toLowerCase();
|
|
if ((langLower.length() < 5) ||
|
|
( !langLower.substring( 0, 5 ).equals( "lang-" ) )) {
|
|
return null;
|
|
}
|
|
StringTokenizer st = new StringTokenizer( langLower, "-" );
|
|
// Skip first token, which is "lang-"
|
|
st.nextToken();
|
|
String[] langComponents = new String[st.countTokens()];
|
|
int i = 0;
|
|
while ( st.hasMoreTokens() ) {
|
|
langComponents[i] = st.nextToken();
|
|
i++;
|
|
}
|
|
|
|
String searchBasename = LDAPAttribute.getBaseName(attrName);
|
|
String[] searchTypes = LDAPAttribute.getSubtypes(attrName);
|
|
LDAPAttribute found = null;
|
|
int matchCount = 0;
|
|
for( i = 0; i < attrs.length; i++ ) {
|
|
boolean isCandidate = false;
|
|
LDAPAttribute attr = attrs[i];
|
|
// Same base name?
|
|
if ( attr.getBaseName().equalsIgnoreCase(searchBasename) ) {
|
|
// Accept any subtypes?
|
|
if( (searchTypes == null) || (searchTypes.length < 1) ) {
|
|
isCandidate = true;
|
|
} else {
|
|
// No, have to check each subtype for inclusion
|
|
if( attr.hasSubtypes( searchTypes ) )
|
|
isCandidate = true;
|
|
}
|
|
}
|
|
String attrLang = null;
|
|
if ( isCandidate ) {
|
|
attrLang = attr.getLangSubtype();
|
|
// At this point, the base name and subtypes are okay
|
|
if ( attrLang == null ) {
|
|
// If there are no language attributes, this one is okay
|
|
found = attr;
|
|
} else {
|
|
// We just have to check for language match
|
|
st = new StringTokenizer( attrLang.toLowerCase(), "-" );
|
|
// Skip first token, which is "lang-"
|
|
st.nextToken();
|
|
// No match if the attribute's language spec is longer
|
|
// than the target one
|
|
if ( st.countTokens() > langComponents.length )
|
|
continue;
|
|
|
|
// How many subcomponents of the language match?
|
|
int j = 0;
|
|
while ( st.hasMoreTokens() ) {
|
|
if ( !langComponents[j].equals( st.nextToken() ) ) {
|
|
j = 0;
|
|
break;
|
|
}
|
|
j++;
|
|
}
|
|
if ( j > matchCount ) {
|
|
found = attr;
|
|
matchCount = j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
|
|
/**
|
|
* Returns the attribute at the position specified by the index.
|
|
* For example, if you specify the index 0, the method returns the
|
|
* first attribute in the set. The index is 0-based.
|
|
*
|
|
* @param index index of the attribute to obtain
|
|
* @return attribute at the position specified by the index.
|
|
*/
|
|
public LDAPAttribute elementAt (int index) {
|
|
return attrs[index];
|
|
}
|
|
|
|
/**
|
|
* Removes the attribute at the position specified by the index.
|
|
* For example, if you specify the index 0, the method removes the
|
|
* first attribute in the set. The index is 0-based.
|
|
*
|
|
* @param index index of the attribute to remove
|
|
*/
|
|
public void removeElementAt (int index) {
|
|
if ((index >= 0) && (index < attrs.length)) {
|
|
synchronized(this) {
|
|
LDAPAttribute[] vals = new LDAPAttribute[attrs.length-1];
|
|
int j = 0;
|
|
for (int i = 0; i < attrs.length; i++) {
|
|
if (i != index) {
|
|
vals[j++] = attrs[i];
|
|
}
|
|
}
|
|
if (attrHash != null) {
|
|
attrHash.remove(attrs[index].getName().toLowerCase());
|
|
}
|
|
attrs = vals;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the number of attributes in this set.
|
|
* @return number of attributes in this attribute set.
|
|
*/
|
|
public int size () {
|
|
return attrs.length;
|
|
}
|
|
|
|
/**
|
|
* Adds the specified attribute to this attribute set.
|
|
* @param attr attribute to add to this set
|
|
*/
|
|
public synchronized void add( LDAPAttribute attr ) {
|
|
if (attr != null) {
|
|
LDAPAttribute[] vals = new LDAPAttribute[attrs.length+1];
|
|
for (int i = 0; i < attrs.length; i++)
|
|
vals[i] = attrs[i];
|
|
vals[attrs.length] = attr;
|
|
attrs = vals;
|
|
if (attrHash != null) {
|
|
attrHash.put( attr.getName().toLowerCase(), attr );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes the specified attribute from the set.
|
|
* @param name name of the attribute to remove
|
|
*/
|
|
public synchronized void remove( String name ) {
|
|
for( int i = 0; i < attrs.length; i++ ) {
|
|
if ( name.equalsIgnoreCase( attrs[i].getName() ) ) {
|
|
removeElementAt(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieves the string representation of all attributes
|
|
* in the attribute set. For example:
|
|
*
|
|
* <PRE>
|
|
* LDAPAttributeSet: LDAPAttribute {type='cn', values='Barbara Jensen,Babs
|
|
* Jensen'}LDAPAttribute {type='sn', values='Jensen'}LDAPAttribute {type='
|
|
* givenname', values='Barbara'}LDAPAttribute {type='objectclass', values=
|
|
* 'top,person,organizationalPerson,inetOrgPerson'}LDAPAttribute {type='ou',
|
|
* values='Product Development,People'}
|
|
* </PRE>
|
|
*
|
|
* @return string representation of all attributes in the set.
|
|
*/
|
|
public String toString() {
|
|
StringBuffer sb = new StringBuffer("LDAPAttributeSet: ");
|
|
for( int i = 0; i < attrs.length; i++ ) {
|
|
if (i != 0) {
|
|
sb.append(" ");
|
|
}
|
|
sb.append(attrs[i].toString());
|
|
}
|
|
return sb.toString();
|
|
}
|
|
}
|