/* -*- 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.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ package netscape.ldap.util; import java.util.*; import java.io.*; import java.util.StringTokenizer; /** * Objects of this class represent distinguished names (DN). A * distinguished name is used to identify an entry in a directory. *

* * The netscape.ldap.LDAPDN class uses this class * internally. In most cases, when working with DNs in the * LDAP Java classes, you should use the * netscape.ldap.LDAPDN class. *

* * The following DNs are examples of the different formats * for DNs that may appear: *

*

* * @version 1.0 * @see netscape.ldap.LDAPDN */ public final class DN { /** * List of RDNs. DN consists of one or more RDNs. * RDNs follow RFC1485 order. */ Vector m_rdns = new Vector(); /** * Type specifying a DN in the RFC format. *

* * @see netscape.ldap.util.DN#getDNType * @see netscape.ldap.util.DN#setDNType */ public static int RFC = 0; /** * Type specifying a DN in the OSF format. *

* * @see netscape.ldap.util.DN#getDNType * @see netscape.ldap.util.DN#setDNType */ public static int OSF = 1; private int m_dnType = RFC; /** * Constructs an empty DN object. */ public DN() { } /** * Constructs a DN object from the specified * distinguished name. The string representation of the DN * can be in RFC 1485 or OSF format. *

* * @param dn String representation of the distinguished name. */ public DN(String dn) { if (dn == null) return; int index; // RFC1485 if (isRFC(dn)) { StringBuffer buffer = new StringBuffer(dn); int i=0; StringBuffer rbuffer = new StringBuffer(); boolean openQuotes = false; while (i < buffer.length()) { rbuffer.append(buffer.charAt(i)); if (buffer.charAt(i) == '\\') { char c = buffer.charAt(i+1); for (int j=0; j= 0; i--) { m_rdns.addElement(rdns.elementAt(i)); } } else if (RDN.isRDN(dn)) { m_rdns.addElement(new RDN(dn)); } } /** * Adds the specified relative distinguished name (RDN) to the * beginning of the current DN. *

* * @param rdn The relative distinguished name that you want * to add to the beginning of the current DN. * @see netscape.ldap.utils.RDN */ public void addRDNToFront(RDN rdn) { m_rdns.insertElementAt(rdn, 0); } /** * Adds the specified relative distinguished name (RDN) to the * end of the current DN. *

* * @param rdn The relative distinguished name that you want * to append to the current DN. * @see netscape.ldap.utils.RDN */ public void addRDNToBack(RDN rdn) { m_rdns.addElement(rdn); } /** * Adds the specified relative distinguished name (RDN) to the current DN. * If the DN is in RFC 1485 format, the RDN is added to the beginning * of the DN. If the DN is in OSF format, the RDN is appended to the * end of the DN. *

* * @param rdn The relative distinguished name that you want to add to * the current DN. * @see netscape.ldap.utils.RDN */ public void addRDN(RDN rdn) { if (m_dnType == RFC) { addRDNToFront(rdn); } else { addRDNToBack(rdn); } } /** * Sets the type of format used for the DN (RFC format or OSF format). *

* * @param type One of the following constants: DN.RFC * (to use the RFC format) or DN.OSF (to use the OSF format). * @see netscape.ldap.util.DN#getDNType * @see netscape.ldap.util.DN#RFC * @see netscape.ldap.util.DN#OSF */ public void setDNType(int type) { m_dnType = type; } /** * Gets the type of format used for the DN (RFC format or OSF format). *

* * @return One of the following constants: DN.RFC * (if the DN is in RFC format) or DN.OSF * (if the DN is in OSF format). * @see netscape.ldap.util.DN#setDNType * @see netscape.ldap.util.DN#RFC * @see netscape.ldap.util.DN#OSF */ public int getDNType() { return m_dnType; } /** * Returns the number of components that make up the current DN. * @return The number of components in this DN. */ public int countRDNs() { return m_rdns.size(); } /** * Returns a list of the components (RDN objects) * that make up the current DN. * @return A list of the components of this DN. * @see netscape.ldap.utils.RDN */ public Vector getRDNs() { return m_rdns; } /** * Returns an array of the individual components that make up * the current distinguished name. * @param noTypes Specify true to remove the attribute type * and equals sign (for example, "cn=") from each component. */ public String[] explodeDN(boolean noTypes) { if (m_rdns.size() == 0) return null; String str[] = new String[m_rdns.size()]; for (int i = 0; i < m_rdns.size(); i++) { if (noTypes) str[i] = ((RDN)m_rdns.elementAt(i)).getValue(); else str[i] = ((RDN)m_rdns.elementAt(i)).toString(); } return str; } /** * Determines if the DN is in RFC 1485 format. * @return true if the DN is in RFC 1485 format. */ public boolean isRFC() { return (m_dnType == RFC); } /** * Returns the DN in RFC 1485 format. * @return The DN in RFC 1485 format. */ public String toRFCString() { String dn = ""; for (int i = 0; i < m_rdns.size(); i++) { if (i != 0) dn += ","; dn = dn + ((RDN)m_rdns.elementAt(i)).toString(); } return dn; } /** * Returns the DN in OSF format. * @return The DN in OSF format. */ public String toOSFString() { String dn = ""; for (int i = 0; i < m_rdns.size(); i++) { if (i != 0) { dn = "/" + dn; } RDN rdn = (RDN)m_rdns.elementAt(i); dn = rdn.toString() + dn; } return dn; } /** * Returns the string representation of the DN * in its original format. (For example, if the * DN object was constructed from a DN * in RFC 1485 format, this method returns the DN * in RFC 1485 format. * @return The string representation of the DN. */ public String toString() { if (m_dnType == RFC) return toRFCString(); else return toOSFString(); } /** * Determines if the given string is an distinguished name or * not. * @param dn distinguished name * @return true or false */ public static boolean isDN(String dn) { DN newdn = new DN(dn); return (newdn.countRDNs() > 0); } /** * Determines if the current DN is equal to the specified DN. * @param dn DN that you want to compare against the current DN. * @return true if the two DNs are the same. */ public boolean equals(DN dn) { return (dn.toRFCString().toUpperCase().equals(toRFCString().toUpperCase())); } /** * Gets the parent DN for this DN. *

* * For example, the following section of code gets the * parent DN of "uid=bjensen, ou=People, o=Airius.com." *

     *    DN dn = new DN("uid=bjensen, ou=People, o=Airius.com");
     *    DN parent = dn.getParent();
     * 
* The parent DN in this example is "ou=People, o=Airius.com". *

* * @return DN of the parent of this DN. */ public DN getParent() { DN newdn = new DN(); for (int i = m_rdns.size() - 1; i > 0; i--) { newdn.addRDN((RDN)m_rdns.elementAt(i)); } return newdn; } /** * Determines if the given DN is under the subtree defined by this DN. *

* * For example, the following section of code determines if the * DN specified by dn1 is under the subtree specified * by dn2. *

     *    DN dn1 = new DN("uid=bjensen, ou=People, o=Airius.com");
     *    DN dn2 = new DN("ou=People, o=Airius.com");
     *
     *    boolean isContain = dn1.contains(dn2)
     * 
* In this case, since "uid=bjensen, ou=People, o=Airius.com" * is an entry under the subtree "ou=People, o=Airius.com", * the value of isContain is true. *

* * @param dn The DN of a subtree that you want to check. * @return true if the current DN belongs to the subtree * specified by dn. */ public boolean contains(DN dn) { Vector rdns1 = dn.m_rdns; Vector rdns2 = this.m_rdns; for (int i=rdns1.size()-1,j=rdns2.size()-1; i>=0 && j>=0; i--, j--) { RDN rdn1 = (RDN)rdns1.elementAt(i); RDN rdn2 = (RDN)rdns2.elementAt(j); if (!rdn2.equals(rdn1)) { return false; } } return true; } private boolean isRFC(String dn) { int index =dn.indexOf(','); /* Can't have the first or last character be the first unescaped comma */ while ((index > 0) && (index < (dn.length() -1))) { /* Found an unescaped comma */ if (dn.charAt(index-1) != '\\') { return true; } /* Found an escaped comma, keep searching */ index=dn.indexOf(',',index+1); } return false; } private boolean appendRDN(StringBuffer buffer) { String rdn = new String(buffer); if (RDN.isRDN(rdn)) { m_rdns.addElement(new RDN(rdn)); return true; } m_rdns.removeAllElements(); return false; } /** * Array of the characters that may be escaped in a DN. */ public static final char[] ESCAPED_CHAR = {',', '+', '"', '\\', ';'}; }