Summary: Fixed javadoc comments that were causing warnings at build time. git-svn-id: svn://10.0.0.236/trunk@226263 18797224-902f-48f8-a5cc-f745e15eee43
492 lines
16 KiB
Java
492 lines
16 KiB
Java
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla 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/MPL/
|
|
*
|
|
* 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 the Initial Developer are Copyright (C) 1999
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
package netscape.ldap.util;
|
|
|
|
import java.util.*;
|
|
|
|
/**
|
|
* Objects of this class represent the components of a distinguished
|
|
* name (DN). (In some situations, these components are referred to
|
|
* as relative distinguished names, or RDNs.) For example, the
|
|
* DN "uid=bjensen, ou=People, o=Airius.com" has three components:
|
|
* "uid=bjensen", "ou=People", and "o=Airius.com".
|
|
* <P>
|
|
*
|
|
* Each DN component consists of an attribute type and a value.
|
|
* For example, in "o=Airius.com", the attribute type is "o"
|
|
* and the value is "Airius.com".
|
|
* <P>
|
|
*
|
|
* You can use objects of this class to add components to an
|
|
* existing <CODE>DN</CODE> object.
|
|
* <P>
|
|
*
|
|
* @version 1.0
|
|
* @see netscape.ldap.util.DN
|
|
*/
|
|
public final class RDN implements java.io.Serializable {
|
|
|
|
static final long serialVersionUID = 7895454691174650321L;
|
|
|
|
/**
|
|
* List of RDNs. DN consists of one or more RDNs.
|
|
*/
|
|
private String[] m_type = null;
|
|
private String[] m_value = null;
|
|
private boolean m_ismultivalued = false;
|
|
|
|
/**
|
|
* Hash table of case sensitive attributes
|
|
*/
|
|
private static Hashtable m_attributehash = new Hashtable();
|
|
|
|
/**
|
|
* Constructs a new <CODE>RDN</CODE> object from the specified
|
|
* DN component.
|
|
* @param rdn DN component
|
|
*/
|
|
public RDN( String rdn ) {
|
|
String neutralRDN = neutralizeEscapes(rdn);
|
|
if (neutralRDN == null) {
|
|
return; // malformed RDN
|
|
}
|
|
int index = neutralRDN.indexOf( "=" );
|
|
int next_plus;
|
|
|
|
// if the rdn doesnt have = or = positions right at the beginning of the rdn
|
|
if (index <= 0)
|
|
return;
|
|
|
|
Vector values = new Vector();
|
|
Vector types = new Vector();
|
|
|
|
types.addElement( rdn.substring( 0, index ).trim() );
|
|
next_plus = neutralRDN.indexOf( '+', index );
|
|
while ( next_plus != -1 ) {
|
|
m_ismultivalued = true;
|
|
values.addElement( rdn.substring( index + 1, next_plus).trim() );
|
|
index = neutralRDN.indexOf( "=", next_plus + 1 );
|
|
if ( index == -1 ) {
|
|
// malformed RDN?
|
|
return;
|
|
}
|
|
types.addElement( rdn.substring( next_plus + 1, index ).trim() );
|
|
next_plus = neutralRDN.indexOf('+', index );
|
|
}
|
|
values.addElement( rdn.substring( index + 1 ).trim() );
|
|
|
|
m_type = new String[types.size()];
|
|
m_value = new String[values.size()];
|
|
|
|
for( int i = 0; i < types.size(); i++ ) {
|
|
m_type[i] = (String)types.elementAt( i );
|
|
if (!isValidType(m_type[i])) {
|
|
m_type = m_value = null;
|
|
return; // malformed
|
|
}
|
|
m_value[i] = (String)values.elementAt( i );
|
|
if (!isValidValue(m_value[i])) {
|
|
m_type = m_value = null;
|
|
return; // malformed
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Neutralize backslash escapes and quoted sequences for easy parsing.
|
|
* @return rdn string with disabled escapes or null if malformed rdn
|
|
*/
|
|
static String neutralizeEscapes(String rdn) {
|
|
if (rdn == null) {
|
|
return null;
|
|
}
|
|
StringBuffer sb = new StringBuffer(rdn);
|
|
boolean quoteOn = false;
|
|
// first pass, disable backslash escapes
|
|
for (int i=0; i < sb.length(); i++) {
|
|
if (sb.charAt(i) =='\\') {
|
|
sb.setCharAt(i, 'x');
|
|
if (i < sb.length()-1) {
|
|
sb.setCharAt(i+1, 'x');
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
// second pass, disable quoted sequences
|
|
for (int i=0; i < sb.length(); i++) {
|
|
if (sb.charAt(i) == '"') {
|
|
quoteOn = !quoteOn;
|
|
continue;
|
|
}
|
|
if (quoteOn) {
|
|
sb.setCharAt(i, 'x');
|
|
}
|
|
}
|
|
return quoteOn ? null : sb.toString();
|
|
}
|
|
|
|
/**
|
|
* Type names can not contain any DN special characters
|
|
*/
|
|
private boolean isValidType(String type) {
|
|
if (type == null || type.length() < 1) {
|
|
return false;
|
|
}
|
|
for (int i=0; i< type.length(); i++) {
|
|
for (int j=0; j < DN.ESCAPED_CHAR.length; j++) {
|
|
if (type.charAt(i) == DN.ESCAPED_CHAR[j]) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Values can contain only single quote sequence, where quotes are
|
|
* at the beginning and the end of the sequence
|
|
*/
|
|
private boolean isValidValue(String val) {
|
|
if (val == null || val.length() < 1) {
|
|
return false;
|
|
}
|
|
// count unescaped '"'
|
|
int cnt=0, i=0;
|
|
while (i >=0 && i < val.length()) {
|
|
i = val.indexOf('"', i);
|
|
if (i >= 0) {
|
|
if (i==0 || (val.charAt(i-1) != '\\')) {
|
|
cnt++;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
if (cnt == 0) {
|
|
return true;
|
|
}
|
|
else if (cnt != 2) { // can have only two of them surrounding the value
|
|
return false;
|
|
}
|
|
else if (val.charAt(0) != '"' || val.charAt(val.length()-1) != '"') {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns the DN component as the first element in an
|
|
* array of strings.
|
|
* @param noType specify <code>true</code> to ignore the attribute type and
|
|
* equals sign (for example, "cn=") and return only the value
|
|
* @return an array of strings representing the DN component.
|
|
* @deprecated use <code>toString</code> or <code>getValues</code> instead.
|
|
*/
|
|
public String[] explodeRDN(boolean noType) {
|
|
if (m_type == null)
|
|
return null;
|
|
String str[] = new String[1];
|
|
if (noType) {
|
|
str[0] = getValue();
|
|
} else {
|
|
str[0] = toString();
|
|
}
|
|
return str;
|
|
}
|
|
|
|
/**
|
|
* Returns the attribute type of the DN component.
|
|
* @return rdn the attribute type of the DN component.
|
|
* @deprecated use <code>getTypes()</code> instead.
|
|
*/
|
|
public String getType() {
|
|
if (m_type != null && m_type.length > 0) {
|
|
return m_type[0];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns the attribute types of the DN component.
|
|
* @return rdn the attribute types of the DN component.
|
|
*/
|
|
public String[] getTypes() {
|
|
return m_type;
|
|
}
|
|
|
|
/**
|
|
* Returns the value of the DN component.
|
|
* @return rdn the value of the DN component.
|
|
* @deprecated use <code>getValues()</code> instead.
|
|
*/
|
|
public String getValue() {
|
|
if (m_value != null && m_value.length > 0) {
|
|
return m_value[0];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns the values of the DN component.
|
|
* @return rdn the values of the DN component.
|
|
*/
|
|
public String[] getValues() {
|
|
return m_value;
|
|
}
|
|
|
|
/**
|
|
* Returns <code>true</code> if the RDN is multi-valued.
|
|
* @return <code>true</code> if the RDN is multi-valued.
|
|
*/
|
|
public boolean isMultivalued() {
|
|
return m_ismultivalued;
|
|
}
|
|
|
|
/**
|
|
* Returns the string representation of the DN component.
|
|
* @return the string representation of the DN component.
|
|
*/
|
|
public String toString() {
|
|
StringBuffer buf = new StringBuffer();
|
|
|
|
for ( int i = 0; m_type != null && i < m_type.length; i++ ) {
|
|
if ( i != 0) {
|
|
buf.append(" + ");
|
|
}
|
|
buf.append( m_type[i] + "=" + m_value[i]);
|
|
}
|
|
|
|
return buf.toString();
|
|
}
|
|
|
|
/**
|
|
* Determines if the specified string is a distinguished name component.
|
|
* @param rdn the string to check
|
|
* @return <code>true</code> if the string is a distinguished name component.
|
|
*/
|
|
public static boolean isRDN(String rdn) {
|
|
RDN newrdn = new RDN(rdn);
|
|
return ((newrdn.getTypes() != null) && (newrdn.getValues() != null));
|
|
}
|
|
|
|
/**
|
|
* Determines if the current DN component is equal to the specified
|
|
* DN component. Uses an internal table of ces (case exact string)
|
|
* attributes to determine how the attributes should be compared.
|
|
* @param rdn the DN component to compare against the
|
|
* current DN component.
|
|
* @return <code>true</code> if the two DN components are equal.
|
|
* @see netscape.ldap.util.RDN#registerAttributeSyntax
|
|
* @see netscape.ldap.util.RDN#getAttributeSyntax
|
|
*/
|
|
public boolean equals(RDN rdn) {
|
|
String[] this_types = (String[])getTypes().clone();
|
|
String[] this_values = (String[])getValues().clone();
|
|
String[] rdn_types = (String[])rdn.getTypes().clone();
|
|
String[] rdn_values = (String[])rdn.getValues().clone();
|
|
|
|
if ( this_types.length != rdn_types.length ) {
|
|
return false;
|
|
}
|
|
|
|
sortTypesAndValues( this_types, this_values );
|
|
sortTypesAndValues( rdn_types, rdn_values );
|
|
|
|
for (int i = 0; i < this_types.length; i++ ) {
|
|
|
|
if ( !this_types[i].equalsIgnoreCase( rdn_types[i] ) ) {
|
|
return false;
|
|
}
|
|
|
|
if ( CES_SYNTAX.equals( getAttributeSyntax( this_types[i] ) ) ) {
|
|
if ( !this_values[i].equals( rdn_values[i] ) ) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if ( !this_values[i].equalsIgnoreCase( rdn_values[i] ) ) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/* sorts the rdn components by attribute to make comparison easier */
|
|
void sortTypesAndValues( String[] types, String[] values ) {
|
|
boolean no_changes;
|
|
do {
|
|
no_changes = true;
|
|
for ( int i = 0; i < types.length - 1; i++ ) {
|
|
if ( types[i].toLowerCase().compareTo( types[i + 1].toLowerCase() ) > 0 ) {
|
|
String tmp_type = types[i];
|
|
String tmp_value = values[i];
|
|
types[i] = types[i + 1];
|
|
values[i] = values[i + 1];
|
|
types[i + 1] = tmp_type;
|
|
values[i + 1] = tmp_value;
|
|
no_changes = false;
|
|
}
|
|
}
|
|
} while ( no_changes = false );
|
|
}
|
|
|
|
/**
|
|
* Registers the the given attribute for the given syntax in an
|
|
* internal table. This table is used for attribute comparison in the
|
|
* <code>equals()</code> method.
|
|
* @param attr the attribute to register.
|
|
* @param oid the syntax to register with the attribute.
|
|
* @see netscape.ldap.util.RDN#equals
|
|
* @see netscape.ldap.util.RDN#unregisterAttributeSyntax
|
|
* @see netscape.ldap.util.RDN#getAttributeSyntax
|
|
* @see netscape.ldap.util.RDN#getAttributesForSyntax
|
|
*/
|
|
public static void registerAttributeSyntax( String attr, String oid ) {
|
|
m_attributehash.put( attr.toLowerCase(), oid );
|
|
}
|
|
|
|
/**
|
|
* Removes the the given attribute from the attribute syntax table.
|
|
* @param attr the attribute to remove.
|
|
* @see netscape.ldap.util.RDN#registerAttributeSyntax
|
|
* @see netscape.ldap.util.RDN#getAttributeSyntax
|
|
* @see netscape.ldap.util.RDN#getAttributesForSyntax
|
|
*/
|
|
public static void unregisterAttributeSyntax( String attr ) {
|
|
m_attributehash.remove( attr.toLowerCase() );
|
|
}
|
|
|
|
/**
|
|
* Returns the syntax for the attribute if the given attribute is registered
|
|
* in the internal attribute table.
|
|
* @param attr the attribute to lookup in the table.
|
|
* @return the syntax of the attribute if found, null otherwise.
|
|
* @see netscape.ldap.util.RDN#unregisterAttributeSyntax
|
|
* @see netscape.ldap.util.RDN#registerAttributeSyntax
|
|
* @see netscape.ldap.util.RDN#getAttributesForSyntax
|
|
*/
|
|
public static String getAttributeSyntax( String attr ) {
|
|
return (String)m_attributehash.get( attr.toLowerCase() );
|
|
}
|
|
|
|
/**
|
|
* Returns all attributes registered for the given syntax as a
|
|
* <code>String</code> Array.
|
|
* @param oid the syntax to look up in the table.
|
|
* @return all attributes for the given syntax as a <code>String[]</code>
|
|
* @see netscape.ldap.util.RDN#unregisterAttributeSyntax
|
|
* @see netscape.ldap.util.RDN#registerAttributeSyntax
|
|
* @see netscape.ldap.util.RDN#getAttributeSyntax
|
|
*/
|
|
public static String[] getAttributesForSyntax( String oid ) {
|
|
Enumeration itr = m_attributehash.keys();
|
|
Vector key_v = new Vector();
|
|
String tmp_str = null;
|
|
|
|
while ( itr.hasMoreElements() ) {
|
|
tmp_str = (String)itr.nextElement();
|
|
if ( oid.equals( (String)m_attributehash.get( tmp_str ) ) ) {
|
|
key_v.addElement( tmp_str );
|
|
}
|
|
}
|
|
|
|
String[] str = new String[key_v.size()];
|
|
for ( int i = 0; i < str.length; i++ ) {
|
|
str[i] = new String( (String)key_v.elementAt( i ) );
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
public static final String[] _cesAttributes = {
|
|
"adminurl",
|
|
"altserver",
|
|
"automountinformation",
|
|
"bootfile",
|
|
"bootparameter",
|
|
"cirbindcredentials",
|
|
"generation",
|
|
"homedirectory",
|
|
"internationalisdnnumber",
|
|
"labeleduri",
|
|
"membercertificatedescription",
|
|
"membernisnetgroup",
|
|
"memberuid",
|
|
"memberurl",
|
|
"nismapentry",
|
|
"nisnetgrouptriple",
|
|
"nsaddressbooksyncurl",
|
|
"presentationaddress",
|
|
"ref",
|
|
"replicaentryfilter",
|
|
"searchguide",
|
|
"subtreeaci",
|
|
"vlvfilter",
|
|
"vlvname",
|
|
"x121address"
|
|
};
|
|
|
|
public static final String CES_SYNTAX = "1.3.6.1.4.1.1466.115.121.1.26";
|
|
|
|
static {
|
|
/* static initializer to fill the ces attribute hash
|
|
* this list was generated from the slapd.at.conf that
|
|
* ships with Netscape Directory Server 4.1
|
|
*/
|
|
for ( int i = 0; i < _cesAttributes.length; i++ ) {
|
|
registerAttributeSyntax( _cesAttributes[i], CES_SYNTAX );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|