package jeffaschenk.commons.frameworks.cnxidx.utility.ldap;
import java.util.StringTokenizer;
import javax.naming.CompoundName;
/**
* Java Class for proper DN parsing to acquire Naming Attribute,
* RDN Value and Parent DN.
*
* @author jeff.schenk
* @version 1.0 $Revision
* Developed 2001-2005
*/
public class idxParseDN {
// ***********************************************
// Logging Facilities.
public static final String CLASSNAME = idxParseDN.class.getName();
// *************************************************
// Version.
private static final String VERSION = "Version: 2005-05-31, " +
"FRAMEWORK, Incorporated.";
// ************************************************
// Global Fields.
private String aOriginalName = null;
private String[] aName = new String[3];
private boolean Quoted = false;
private boolean Valid = false;
/**
* Provides proper parsing and manipulation of a DN.
* This does not handle multi-part DNs and will flag the DN entry as
* not Valid.
*
* @param aDN Distingushed Name to be Parsed.
*/
public idxParseDN(String aDN) {
parse(aDN);
} // End of idxParseDN Constructor.
/**
* clear method, called to clear our existing DN.
*/
public void clear() {
aName[0] = ""; // Naming Attribute Name.
aName[1] = ""; // Naming Attribute Value.
aName[2] = ""; // Remaining DN or Parent Level DN.
Quoted = false;
Valid = false;
aOriginalName = ""; // Original Incoming valid to constructor.
} // End of Clear method.
/**
* parse method, called to parse out the DN.
*/
public void parse(String aDN) {
clear();
// *********************************
// Save our Existing incoming Value.
aOriginalName = aDN;
// *************************************
// Besure to trim before starting tests
if (aDN != null) {
aDN = aDN.trim();
}
// **********************************
// Start Parsing...
if ((!"".equals(aDN)) &&
(aDN != null)) {
// **********************************
// Remove Any Quotes.
do {
int thequote = aDN.indexOf("\042");
if (thequote == 0) {
Quoted = true;
aDN = aDN.substring(1);
} else if (thequote > 0) {
Quoted = true;
aDN = aDN.substring(0, thequote) +
aDN.substring(thequote + 1);
} // End of Else.
} while (aDN.indexOf("\042") != -1);
} // End of If.
// **********************************
// Is this infact an X500DN?
if ((!"".equals(aDN)) &&
(aDN != null) &&
(aDN.startsWith("/"))) {
aDN = convertX500NameToLDAPName(aDN);
} // End of X500DN Check.
// **********************************
// Now check again for invalid start
// and ending characters.
if ((!"".equals(aDN)) &&
(aDN != null) &&
(!aDN.startsWith(",")) &&
(!aDN.startsWith("+")) &&
(!aDN.startsWith("=")) &&
(!aDN.startsWith(">")) &&
(!aDN.startsWith("<")) &&
(!aDN.startsWith(";")) &&
(!aDN.endsWith(",")) &&
(!aDN.endsWith("+")) &&
(!aDN.endsWith("=")) &&
(!aDN.startsWith(">")) &&
(!aDN.startsWith("<")) &&
(!aDN.startsWith(";"))) {
// *********************************
// Clean up the DN.
aDN = cleanDN(aDN);
// **********************************
// Parse.
int thecomma = aDN.indexOf(",");
if (thecomma <= 0) {
aName[1] = aDN.trim();
} else {
aName[1] = aDN.substring(0, thecomma);
aName[2] = aDN.substring(thecomma + 1);
aName[2] = aName[2].trim();
} // End of Else.
int theequal = aName[1].indexOf("=");
if (theequal > 0) {
aName[0] = aName[1].substring(0, theequal);
aName[0] = aName[0].trim();
aName[1] = aName[1].substring(theequal + 1);
aName[1] = aName[1].trim();
} // End of If.
// **********************************
// Check to see if the RDN contains
// a multivalued name.
// If it does clear it, we do not
// Support this capability.
// The DC-Directory does, but
// FRAMEWORK does not!
int theplus = aName[1].indexOf("+");
if (theplus >= 0) {
clear();
}
// **********************************
// Now Set the Validity Indicator.
setValid();
} // End of If.
} // End of parse Method.
/**
* Obtains full DN.
*
* @return String full DN contained within Object.
* If incoming DN was Quoted, we will re-Quote entire DN.
*/
public String getDNwithQuotes() {
if (("".equals(aName[0])) ||
("".equals(aName[1]))) {
if (Quoted) {
return ("\042" + aName[2] + "\042");
} else {
return (aName[2]);
}
}
if ("".equals(aName[2])) {
if (Quoted) {
return ("\042" + aName[0] + "=" + aName[1] + "\042");
} else {
return (aName[0] + "=" + aName[1]);
}
} else {
if (Quoted) {
return ("\042" + aName[0] + "=" + aName[1] + "," + aName[2] + "\042");
} else {
return (aName[0] + "=" + aName[1] + "," + aName[2]);
}
}
} // End of getDN Method.
/**
* Obtains full DN, without Quotes.
*
* @return String full DN contained within Object
*/
public String getDN() {
if (("".equals(aName[0])) ||
("".equals(aName[1]))) {
return (aName[2]);
}
if ("".equals(aName[2])) {
return (aName[0] + "=" + aName[1]);
} else {
return (aName[0] + "=" + aName[1] + "," + aName[2]);
}
} // End of getDN Method.
/**
* Returns Original DN.
*
* @return Original DN.
*/
public String getOriginalDN() {
return (aOriginalName);
} // End of getDN Method.
/**
* Obtains RDN.
*
* @return String RDN contained within Object
*/
public String getRDN() {
if (("".equals(aName[0])) ||
("".equals(aName[1]))) {
return ("");
} else {
return (aName[0] + "=" + aName[1]);
}
} // End of getRDN Method.
/**
* Obtains Parent DN or PDN.
* The Parent DN could be blank,
* if this is a top Level DN,
* Such as "dc=com".
*
* @return String PDN contained within Object
*/
public String getPDN() {
return (aName[2]);
} // End of getPDN Method.
/**
* Obtains the Domain of the DN.
*
* @return String of Domain DN contained within Object
*/
public String getDomain() {
String value = getDN();
int thedomain = value.indexOf("dc=");
if (thedomain == 0) {
return (value);
} else if (thedomain > 0) {
return (value.substring(thedomain));
} // End of Else.
return ("");
} // End of getDomain Method.
/**
* Obtains everything but the Domain of the DN.
*
* @return String of DN contained within Object less Domain part.
*/
public String getDNLessDomain() {
String value = getDN();
int thedomain = value.indexOf("dc=");
if (thedomain == 0) {
return ("");
} else if (thedomain > 0) {
value = value.substring(0, thedomain);
int thecomma = value.lastIndexOf(',');
if (thecomma > 0) {
return (value.substring(0, thecomma));
}
} // End of Else.
return (value);
} // End of getDNLessDomain Method.
/**
* Obtains everything but the Domain of the DN and RDN.
*
* @return String of DN contained within Object less Domain part.
*/
public String getPDNLessDomain() {
String value = getPDN();
int thedomain = value.indexOf("dc=");
if (thedomain == 0) {
return ("");
} else if (thedomain > 0) {
value = value.substring(0, thedomain);
int thecomma = value.lastIndexOf(',');
if (thecomma > 0) {
return (value.substring(0, thecomma));
}
} // End of Else.
return (value);
} // End of getDNLessDomain Method.
/**
* Obtains the Naming Attribute for RDN.
*
* @return String Naming Attribute.
*/
public String getNamingValue() {
return (aName[1]);
} // End of getNamingValue Method.
/**
* Obtains the Naming Value of DN.
*
* @return String Naming Value of DN.
*/
public String getNamingAttribute() {
return (aName[0]);
} // End of getNamingAttribute Method.
/**
* Indicates if DN was quoted or not.
*
* @return boolean indicator.
*/
public boolean isQuoted() {
return (Quoted);
} // End of getPDN Method.
/**
* Indicates if DN was quoted or not.
*
* @return boolean indicator.
*/
public boolean isValid() {
return (Valid);
} // End of getPDN Method.
/**
* Sets the Valid indicator.
*/
private void setValid() {
if ((getDN() == null) ||
("".equals(getDN()))) {
Valid = false;
} else {
Valid = true;
}
} // End of setValid Method.
/**
* Provides the depth of the current DN.Valid indicator.
*
* @return int Depth of current RDN.
* <pre>
* (-1) Indicates invalid.
* (0) Indicates at top of Directory Structure.
* (1 or greater) Indicates level of Directory Structure.
* </pre>
*/
public int depth() {
int thedepth = 0;
// ********************
// Is current DN Valid
if (!isValid()) {
return (-1);
}
// ********************
// Are we at the TOP?
if ((getPDN() == null) ||
("".equals(getPDN()))) {
return (thedepth);
}
// ********************
// Loop to Count depth.
idxParseDN XDN = new idxParseDN(this.getDN());
do {
if ((XDN.getPDN() == null) ||
("".equals(XDN.getPDN()))) {
break;
}
thedepth++;
XDN = new idxParseDN(XDN.getPDN());
} while (true);
// ********************
// Are we at the TOP?
return (thedepth);
} // End of depth Method.
/**
* Provides X500 DN Syntax from an LDAP DN.
* TODO Check for Escaped Commas.
*
* @return String X500 DN.
*/
public String getX500Name() {
String X500dn = "";
StringTokenizer st = new StringTokenizer(this.getDN(), ",");
while (st.hasMoreTokens()) {
String ep = st.nextToken();
X500dn = "/" + ep + X500dn;
} // End of While Loop.
return (X500dn);
} // End of getX500Name Method.
/*
* convertX500NameToLDAPName
* @param String X500Name
* @return String LDAPName
**/
public String convertX500NameToLDAPName(String _x500name) {
// ***************************************
// Initialize.
String _ldapname = "";
// ***************************************
// Now Parse out the X500 Domains to
// Create the GLuE Nodes.
//
StringTokenizer NODES = new StringTokenizer(_x500name, "/");
while (NODES.hasMoreTokens()) {
String node = (String) NODES.nextToken();
if ((node == null) || (node.equals(""))) {
continue;
}
// **********************************
// Place the Node at the Begining of
// the LDAP Name.
if (_ldapname.equals("")) {
_ldapname = node;
} else {
_ldapname = node + "," + _ldapname;
}
} // End of While.
// ***************************************
// Return the LDAP Name.
return (_ldapname);
} // End of convertX500NameToLDAPName.
/**
* Returns a CompoundName from the Parsed DN.
*
* @return CompoundName based upon DN.
* @throws Exception if the DN were have is not valid.
*/
public CompoundName getCompoundName()
throws Exception {
// *********************************
// Is our Contents Valid.
if (!isValid()) {
throw new Exception("Current value of [" +
aOriginalName +
"] is not a valid DN.");
}
// *********************************
// Obtain a Compound Name.
try {
idxNameParser np = new idxNameParser();
CompoundName cName = np.parse(getDN());
return (cName);
} catch (Exception e) {
throw new Exception("Current DN[" +
getDN() +
"] could not obtain a CompoundName,:" + e);
} // End of Exception.
} // End of getCompoundName Method.
/**
* Provides clean LDAP DN with removing white space and such between seperators.
* Clean up numerous whitespace, but do not make a invalid dn into a correct dn.
*
* @param _dn Incoming DN.
* @return String Newly Cleaned DN.
* TODO Check for Escaped Commas.
*/
private String cleanDN(String _dn) {
String newDN = "";
StringTokenizer st = new StringTokenizer(_dn, ",");
while (st.hasMoreTokens()) {
String ep = st.nextToken();
if (ep == null) {
continue;
}
ep = ep.trim();
if (ep == null) {
continue;
}
if (newDN.equals("")) {
newDN = ep;
} else {
newDN = newDN + "," + ep;
}
} // End of While Loop.
return (newDN);
} // End of cleanDN Method.
/**
* Main
*
* @param args Incoming Argument Array.
* @see idxParseDN
*/
public static void main(String[] args) {
// ****************************************
// Parse the incoming Arguments and
// create objects for each entity.
//
for (int i = 0; i < args.length; i++) {
dntest(args[i]);
}
} // End of Main Method.
/**
* dntest method to test a DN Parsing from the Command Line.
*/
public static void dntest(String myDN) {
// *****************************************
// Perform some tests on the incoming DN.
idxParseDN zpDN = new idxParseDN(myDN);
// *****************************************
// Break output.
System.out.println("\n\n*****************");
// *****************************************
// Show Original String.
System.out.println(
"Original DN String:[" +
zpDN.getOriginalDN() +
"].");
// *****************************************
// Show DN.
System.out.println(
"DN:[" +
zpDN.getDN() +
"].");
// *****************************************
// Show CompoundName.
try {
System.out.println(
"CompoundName:[" +
zpDN.getCompoundName() +
"].");
} catch (Exception e) {
System.err.println("Exception performing idxParseDN.getCompoundName(),\n" + e);
} // End of Exception.
// *****************************************
// Is Parsed DN a Valid DN?
if (zpDN.isValid()) {
System.out.println(
"DN:[" + zpDN.getDN() + "], is Valid.");
} // End of If.
else {
System.out.println(
"DN:[" + zpDN.getDN() + "], is Not Valid.");
} // End of If.
// *****************************************
// Show the DN Depth.
System.out.println(
"DN Depth:[" +
zpDN.depth() +
"].");
// *****************************************
// Show Naming Attribute Name.
System.out.println(
"Naming Attribute:[" +
zpDN.getNamingAttribute() +
"].");
// *****************************************
// Show Naming Attribute Value.
System.out.println(
"Naming Value:[" +
zpDN.getNamingValue() +
"].");
// *****************************************
// Show RDN.
System.out.println(
"RDN:[" +
zpDN.getRDN() +
"].");
// *****************************************
// Show PDN.
System.out.println(
"PDN:[" +
zpDN.getPDN() +
"].");
// *****************************************
// Show Domain.
System.out.println(
"Domain:[" +
zpDN.getDomain() +
"].");
// *****************************************
// Show DN with Quotes.
System.out.println(
"DN with Quotes:[" +
zpDN.getDNwithQuotes() +
"].");
// *****************************************
// Show DN Less Domain.
System.out.println(
"DN Less Domain:[" +
zpDN.getDNLessDomain() +
"].");
// *****************************************
// Show PDN Less Domain.
System.out.println(
"PDN Less Domain:[" +
zpDN.getPDNLessDomain() +
"].");
// *****************************************
// Show X500 DN
System.out.println(
"X500 DN:[" +
zpDN.getX500Name() +
"].");
} // End of dntest method.
} ///:~ End of idxParseDN Class.