package jeffaschenk.commons.frameworks.cnxidx.utility.ldap; import java.io.BufferedWriter; import javax.naming.CompoundName; import javax.naming.NameNotFoundException; import javax.naming.NamingEnumeration; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.DirContext; import javax.naming.directory.ModificationItem; import javax.naming.directory.NoSuchAttributeException; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; /** * Java class for supporting utility functions, such as Copy, Move and * deletion of Entries. Can be called from EJB or standard JVM environment. * * @author jeff.schenk * @version 1.0 $Revision * Developed 2001 */ public class idxIRRutil { private static String MP = "idxIRRutil: "; public static String[] OpAttrIDs = {"CreateTimeStamp", "CreatorsName", "ModifyTimeStamp", "ModifiersName", "*"}; public static String[] NO_Attributes = {"1.1"}; public static String[] OC_Attribute = {"objectclass"}; private boolean VERBOSE = false; private boolean DEBUG = false; private idxIRRschema SCHEMA = null; // IRR Directory Schema. private boolean schemaAvailable = false; private idxStatus STATUS = null; // Internal Status. // ***************************************************** // Initial Constructor used when no argument supplied. public idxIRRutil() { STATUS = new idxStatus("idxIRRutil"); } // end of Constructor // ***************************************************** // Initial Constructor used when arguments supplied. public idxIRRutil(idxIRRschema _SCHEMA) { SCHEMA = _SCHEMA; schemaAvailable = true; STATUS = new idxStatus("idxIRRutil"); } // end of Constructor // ***************************************************** // Method to Set VERBOSE Indicator. public void setVerbose(boolean _verbose) { VERBOSE = _verbose; } // end of Method // ***************************************************** // Method to Set DEBUG Indicator. public void setDebug(boolean _debug) { DEBUG = _debug; } // end of Method /** * Set the correct Message Prefix for this instance of the Function Utility. * * @param _mp Name of Message Prefix. */ public void setMP(String _mp) { if (_mp != null) { MP = _mp + ": "; } } // End of setMP Method. /** * Deletes Entry from IRR Directory. Performs a JNDI unbind operation * for the specified DN. * * @param _ctxSource current established JNDI Directory Context * @param _DNSource DN to be deleted. * @param _Status Status Class. * @throws idxIRRException if any non-recoverable errors encountered. */ public void DeleteEntry(DirContext _ctxSource, String _DNSource, idxStatus _Status) throws idxIRRException { // ***************************************** // Now Delete Entry. // _Status.setLastOp("DeleteEntry"); _Status.setLastOpResource(_DNSource); _Status.setLastOpStatus(-1); try { if (canEntryBeDeleted(_DNSource)) { idxParseDN Naming_Dest = new idxParseDN(_DNSource); _DNSource = Naming_Dest.getDNwithQuotes(); _ctxSource.unbind(_DNSource); _Status.AccumCounter("DeletedEntries"); _Status.setLastOpStatus(1); if (VERBOSE) { System.out.println(MP + "DeleteEntry:[" + _DNSource + "], Successful."); } } else { if (VERBOSE) { System.out.println(MP + "DeleteEntry:[" + _DNSource + "], Not Allowed to be Deleted."); } _Status.AccumCounter("NonDeletableEntries"); _Status.setLastOpStatus(2); return; } // End of Else. } catch (NameNotFoundException e) { if (VERBOSE) { System.err.println(MP + "DeleteEntry: DN Entry was Not Found for Delete, " + e); } _Status.AccumCounter("DeleteErrors"); _Status.setLastOpStatus(3); return; } // End of exception catch (Exception e) { _Status.setLastOpStatus(0); _Status.AccumCounter("OtherErrors"); throw new idxIRRException("DeleteEntry() Error Performing IRR Delete,\n" + e); } // End of exception } // End of DeleteEntry /** * Obtains all of an Entry's children DNs contained in the IRR. * * @param ctxSource current established JNDI Directory Context * @param DNSource DN for which children are to be discovered. * @param dnLevelList used to supply returned children for entry. * @throws idxIRRException if any non-recoverable errors encountered. */ public void AcquireChildren(DirContext ctxSource, String DNSource, idxDNLinkList dnLevelList) throws Exception { // *************************** // Create my Internal List. idxDNLinkList myChildrenList = new idxDNLinkList(); // *************************** // Obtain First Level try { addChildrentoList(ctxSource, DNSource, myChildrenList, true); } catch (Exception e) { throw e; // Re-throw the exception. } // End of exception // ******************************** // Obtain all Subsequent Levels // Pop it off and save it and then // obtain next level. while (myChildrenList.IsNotEmpty()) { String poppedDN = myChildrenList.popfirst(); // ***************************** // Now place the Childs DN in // the Queue to process it's // Children on the next iteration. // dnLevelList.addLast(poppedDN); try { addChildrentoList(ctxSource, poppedDN, myChildrenList, false); } catch (Exception e) { throw e; // Re-throw Exception. } // End of exception } // End of While Loop. } // End of AcquireChildren /** * Copies an entry from one Directory Context to another as well as * to a different container. * * @param ctxSource current established Source JNDI Directory Context * @param DNSource DN of source entry. * @param ctxDest current established Destination JNDI Directory Context * @param DNDest DN of Destination entry. * @param OVERWRITE_DESTINATION_ENTRY indicator to determine if existing destination entry * should be deleted or not. * @param entryattrs JNDI Attributes Object for Entry to be copied. * @param _StatusSource Source Common Status Object. * @param _StatusDest Destination Common Status Object. * @throws idxIRRException if any non-recoverable errors encountered. */ public void CopyEntry(DirContext ctxSource, String DNSource, DirContext ctxDest, String DNDest, boolean OVERWRITE_DESTINATION_ENTRY, Attributes entryattrs, idxStatus _StatusSource, idxStatus _StatusDest) throws idxIRRException { _StatusSource.setLastOp("CopyEntry"); _StatusSource.setLastOpResource(DNSource); _StatusSource.setLastOpStatus(-1); _StatusDest.setLastOp("CopyEntry"); _StatusDest.setLastOpResource(DNDest); _StatusDest.setLastOpStatus(-1); String[] ALL_AttrIDs = {"*"}; SearchControls OS_ctls = new SearchControls(); OS_ctls.setReturningAttributes(ALL_AttrIDs); OS_ctls.setSearchScope(SearchControls.OBJECT_SCOPE); // ***************************************** // Parse the Destination Entry DN to be sure // we have any Quotes.... idxParseDN Naming_Source = new idxParseDN(DNSource); DNSource = Naming_Source.getDNwithQuotes(); // ***************************************** // Now obtain the Source Entry. // try { if (entryattrs == null) { NamingEnumeration nes = ctxSource.search(DNSource, "(objectclass=*)", OS_ctls); SearchResult srs = (SearchResult) nes.next(); entryattrs = srs.getAttributes(); } _StatusSource.AccumCounter("ReadEntries"); _StatusSource.setLastOpStatus(1); // ***************************************** // Now remove the Naming Attribute Values. if (!"".equals(Naming_Source.getNamingAttribute())) { entryattrs.remove(Naming_Source.getNamingAttribute()); } // ***************************************** // Parse the Destination Entry DN to be sure // we have any Quotes.... idxParseDN Naming_Dest = new idxParseDN(DNDest); DNDest = Naming_Dest.getDNwithQuotes(); // ***************************************** // If schema is Available then, perform a // check for Entry DN Attributes that may // Need to change. // if ((schemaAvailable) && (SCHEMA != null)) { try { checkforFluidDNs(ctxSource, DNSource, ctxDest, DNDest, entryattrs, _StatusDest); } catch (Exception e_FluidDNs) { _StatusDest.AccumCounter("FluidDNErrors"); } // End of exception _StatusDest.setLastOp("CopyEntry"); } // End of If Schema Available. // ***************************************** // Now write out the new Destination Entry. if (VERBOSE) { System.out.println(MP + "Processing Destination Write of Entry:[" + DNDest + "]"); } try { if (entryattrs.size() == 0) { if (VERBOSE) { System.out.println(MP + "Bind of Destination entry invalid, since entry is a Glue Node."); } // End of Verbose If. // Force User to Clean up the Source Directory. throw new idxIRRException("Entry detected as a Glue Node (No Attributes) in CopyEntry()" + "\n...Source DN:[" + DNSource + "]" + "\n.....Dest DN:[" + DNDest + "]"); } // end of If. // Proceed with Bind of Entry to Directory. ctxDest.bind(DNDest, null, entryattrs); _StatusDest.AccumCounter("AddedEntries"); _StatusDest.setLastOpStatus(1); } catch (javax.naming.NameAlreadyBoundException e) { // **************************************************** // Ok, we caught ourselves adding an existing entry. // If our OVERWRITE Flag is Set, simple Rebind the Entry. if (OVERWRITE_DESTINATION_ENTRY) { if (VERBOSE) { System.out.println(MP + "...Existing entry detected, attempting modification of Destination Entry"); } try { ctxDest.rebind(DNDest, null, entryattrs); _StatusDest.AccumCounter("ReboundEntries"); _StatusDest.setLastOpStatus(1); } catch (javax.naming.ContextNotEmptyException e_rebind) { _StatusDest.AccumCounter("NonReboundableEntries"); _StatusDest.setLastOpStatus(1); if (VERBOSE) { System.out.println(MP + "...Unable to rebind Destination entry, since entry is a non-leaf entry."); } // End of Verbose If. return; // This is really Ok, So return ok. } catch (Exception e_rebind) { _StatusDest.AccumCounter("ReboundErrors"); _StatusDest.setLastOpStatus(-1); throw new idxIRRException("Error Performing IRR Rebind, in CopyEntry()" + "\n...Source DN:[" + DNSource + "]" + "\n.....Dest DN:[" + DNDest + "]" + "\n" + e_rebind); } // End of exception } else { if (VERBOSE) { System.out.println(MP + "Unable to Rebind Destination entry, since Overwrite flag was not set."); } // End of Verbose If. return; // This is really ok, So return ok. } // End of Else. } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error Performing IRR Write, in CopyEntry()," + "\n...Source DN:[" + DNSource + "]" + "\n.....Dest DN:[" + DNDest + "]" + "\n" + e); } // End of exception } catch (NameNotFoundException e) { _StatusSource.AccumCounter("ReadErrors"); _StatusSource.setLastOpStatus(-1); System.out.println(MP + "Source DN Entry was Not Found," + "\n...Source DN:[" + DNSource + "]" + "\n.....Dest DN:[" + DNDest + "]" + "\n" + e); return; } // End of exception catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error Performing IRR Function, in CopyEntry()," + "\n...Source DN:[" + DNSource + "]" + "\n.....Dest DN:[" + DNDest + "]" + "\n" + e); } // End of exception return; } // End of CopyEntry /** * Copies all children entries from one Directory Context to another as well as * to a different container. * * @param ctxSource current established Source JNDI Directory Context * @param DNSource DN of source entry. * @param ctxDest current established Destination JNDI Directory Context * @param DNDest DN of Destination entry. * @param OVERWRITE_DESTINATION_ENTRY indicator to determine if existing destination entry * should be deleted or not. * @param dnLevelList DN Level Linked List containing elements to be copied. * @param _StatusSource Source Common Status Object. * @param _StatusDest Destination Common Status Object. * @throws idxIRRException if any non-recoverable errors encountered. */ public void CopyChildren(DirContext ctxSource, String DNSource, DirContext ctxDest, String DNDest, boolean OVERWRITE_DESTINATION_ENTRY, idxDNLinkList dnLevelList, idxStatus _StatusSource, idxStatus _StatusDest) throws idxIRRException { SearchControls OL_ctls = new SearchControls(); OL_ctls.setReturningAttributes(NO_Attributes); OL_ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE); // ***************************************** // Parse the Destination Entry DN to be sure // we have any Quotes.... idxParseDN Naming_Source = new idxParseDN(DNSource); DNSource = Naming_Source.getDNwithQuotes(); // ***************************************** // Now obtain the Source Entry. // try { NamingEnumeration nes = ctxSource.search(DNSource, "(objectclass=*)", OL_ctls); while (nes.hasMore()) { SearchResult srs = (SearchResult) nes.next(); String RDN = srs.getName(); // ******************************* // Acquire the correct Source DNs. String ThisSourceDN = null; if ((DNSource != null) && (!"".equals(DNSource))) { ThisSourceDN = RDN + "," + DNSource; } else { ThisSourceDN = RDN; } // ******************************* // Acquire the correct Source DNs. String ThisDestDN = null; if ((DNDest != null) && (!"".equals(DNDest))) { ThisDestDN = RDN + "," + DNDest; } else { ThisDestDN = RDN; } // ***************************** // Perform the Child Copy // Let the CopyEntry Method // Obtain the entire Object // Entry. CopyEntry(ctxSource, ThisSourceDN, ctxDest, ThisDestDN, OVERWRITE_DESTINATION_ENTRY, null, _StatusSource, _StatusDest); // ***************************** // Now place the Childs DN in // the Queue to process it's // Children on the next iteration. // dnLevelList.addLast(ThisSourceDN); } // End of While. } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error Performing IRR Search for Children, in CopyChildren()"); } // End of exception return; } // End of CopyChildren /** * Determines if an Entry already Exists in the IRR Directory or not. * * @param ctx current established Source JNDI Directory Context * @param EntryDN DN of entry to be check for existence. * @return boolean indication of entry exists or not. * @throws idxIRRException if any non-recoverable errors encountered. */ public boolean DoesEntryExist(DirContext ctx, String EntryDN) throws idxIRRException { // ***************************************** // Parse the Destination Entry DN to be sure // we have any Quotes.... idxParseDN Naming_Source = new idxParseDN(EntryDN); EntryDN = Naming_Source.getDNwithQuotes(); try { ctx.lookup(EntryDN); } catch (javax.naming.NamingException e) { return (false); } // End of Exception. catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error Performing IRR Lookup, in DoesEntryExist(),\n" + e); } // End of Exception return (true); } // End of DoesEntryExist class. /** * Deletes Existing entries from the IRR Directory. * This is a prepartory step for a Copy or Move. * * @param ctxSource current established Source JNDI Directory Context * @param ENTRY_SOURCE_DN DN of entry to be Deleted. * @param DELETE_WITH_CHILDREN Indicator for Child Entries are to be deleted. * @param _Status Status Class. * @throws idxIRRException if any non-recoverable errors encountered. */ public void DeleteExistingEntries(DirContext ctxSource, String ENTRY_SOURCE_DN, boolean DELETE_WITH_CHILDREN, idxStatus _Status) throws idxIRRException { // ******************************************* // Now Delete our Source Entry, if no children // are to be deleted. if (!DELETE_WITH_CHILDREN) { try { DeleteEntry(ctxSource, ENTRY_SOURCE_DN, _Status); } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error IRR Deleting Child Entry,in DeleteExistingEntries(),\n" + e); } // End of exception } // End of if // **************************************** // Delete Children // else { idxDNLinkList myChildrenList = new idxDNLinkList(); // ******************************* // Acquire all Children Entries try { AcquireChildren(ctxSource, ENTRY_SOURCE_DN, myChildrenList); } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error IRR Deleting Child Entry,in DeleteExistingEntries(),\n" + e); } // End of exception // *************************** // Delete All Children in // reverse order. while (myChildrenList.IsNotEmpty()) { String RDN = myChildrenList.poplast(); try { DeleteEntry(ctxSource, RDN, _Status); } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error IRR Deleting Child Entry,in DeleteExistingEntries(),\n" + e); } // End of exception } // End of While Loop. } // End of Else. // ************************************* // Return to Caller. return; } ///: End of DeleteExistingEntries Class. /** * Determines if an Entry can be deleted. Some entries can not without * causing disruption in the DIT as well as part of the internal Access * control which is not exposed via LDAP. Access Control is only * accessible from the X.500 or from DAP. * * @param EntryDN DN of entry can be deleted or not. * @return boolean indication entry can be deleted or not. * @throws idxIRRException if any non-recoverable errors encountered. */ public boolean canEntryBeDeleted(String EntryDN) throws idxIRRException { // **************************************** // Now that we have a compound name // Determine if we can delete the Entry... idxParseDN pDN = new idxParseDN(EntryDN); // Is this Entry the ICOSDSA Organization? // If so, do not allow the delete. if ((!"".equals(pDN.getNamingAttribute())) && ("o".equalsIgnoreCase(pDN.getNamingAttribute())) && ("icosdsa".equalsIgnoreCase(pDN.getNamingValue()))) { return (false); } // Is this Entry start with a domain Container? // If so, do not allow the delete. if ((!"".equals(pDN.getNamingAttribute())) && ("dc".equalsIgnoreCase(pDN.getNamingAttribute()))) { return (false); } // Is this Entry the Framework Organizational Unit? // If so, do not allow the delete. if ((!"".equals(pDN.getNamingAttribute())) && ("ou".equalsIgnoreCase(pDN.getNamingAttribute())) && ("framework".equalsIgnoreCase(pDN.getNamingValue()))) { return (false); } // Is this Entry an Framework hidden Security Entry? // These are named "cn=framework....,ou=framework,... // If so, do not allow the delete. if ((!"".equals(pDN.getNamingAttribute())) && ("cn".equalsIgnoreCase(pDN.getNamingAttribute()))) { String CommonName = pDN.getNamingValue(); CommonName = CommonName.toLowerCase(); String PDN = pDN.getPDN(); CompoundName pName = null; CompoundName tName = null; idxNameParser myParser = new idxNameParser(); try { pName = myParser.parse(PDN); tName = myParser.parse("ou=framework"); } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error Formulating Compound Name in canEntryBeDeleted(),\n" + e); } // End of exception if ((CommonName.equals("framework user")) && (pName.startsWith(tName))) { return (false); } else if ((CommonName.equals("framework process master")) && (pName.startsWith(tName))) { return (false); } } // End of If CommonName // Is this Entry the ICOSDSA IRRADMIN Admin Entry? // This is named "cn=irradmin,o=icosdsa // If so, do not allow the delete. if ((!"".equals(pDN.getNamingAttribute())) && ("cn".equalsIgnoreCase(pDN.getNamingAttribute()))) { String CommonName = pDN.getNamingValue(); CommonName = CommonName.toLowerCase(); String PDN = pDN.getPDN(); CompoundName pName = null; CompoundName tName = null; idxNameParser myParser = new idxNameParser(); try { pName = myParser.parse(PDN); tName = myParser.parse("o=icosdsa"); } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error Formulating Compound Name in canEntryBeDeleted(),\n" + e); } // End of exception if ((CommonName.equals("irradmin")) && (pName.startsWith(tName))) { return (false); } } // End of If CommonName for IRRADMIN. // ******************************* // Falling through indicates the // Entry can be deleted. return (true); } // End of canEntryBeDeleted class. /** * Determines if the any of the Attributes are of FluidDN or DN Syntax * and then attempts to properly resolve those values. * * @param ctxSource current established Source JNDI Directory Context * @param DNSource DN of source entry. * @param ctxDest current established Destination JNDI Directory Context * @param DNDest DN of Destination entry. * @param entryattrs JNDI Attributes Object for Entry to be copied. * @param _StatusDest Destination Common Status Object. * @throws idxIRRException if any non-recoverable errors encountered. */ public void checkforFluidDNs(DirContext ctxSource, String DNSource, DirContext ctxDest, String DNDest, Attributes entryattrs, idxStatus _StatusDest) throws idxIRRException { _StatusDest.setLastOp("checkforFluidDNs"); _StatusDest.setLastOpResource(DNDest); _StatusDest.setLastOpStatus(-1); // ******************************************** // Now check each attribute for syntax and // if the syntax is a DN, then we need to // perform further processing. // try { // **************************************** // Now parse out the incoming DNs. idxParseDN sDN = new idxParseDN(DNSource); idxParseDN dDN = new idxParseDN(DNDest); for (NamingEnumeration ea = entryattrs.getAll(); ea.hasMore(); ) { Attribute attr = (Attribute) ea.next(); String Syntax = SCHEMA.getAttributeSyntaxName(attr.getID()); if (!"DN".equalsIgnoreCase(Syntax)) { continue; } // ******************************************************** // Create new Attribute to contain Destination Changes. // boolean fixed = false; Attribute newFvalues = new BasicAttribute(attr.getID()); // ******************************************************** // Yes we do have an Attribute with DN Syntax. // Now determine if DN needs or can be fixed to properly // reflect the entries new destination. // for (NamingEnumeration ev = attr.getAll(); ev.hasMore(); ) { String currentfDN = (String) ev.next(); idxParseDN fDN = new idxParseDN(currentfDN); _StatusDest.AccumCounter("FluidDNDetections"); if (VERBOSE) { System.out.println(MP + "Fluid DN Found for " + attr.getID() + " (Syntax=" + Syntax + ")" + ": [" + fDN.getDN() + "]"); } // End of Verbose. // ************************************************************************ // First Fix Domain Traversal. // Set up Compound names for tests. // fName will be CompoundName Attribute Contents which was a DN. // dName will be CompoundName of the Destination DN, which was formulated. // sName will be CompoundName of the Source DN, which was read. // CompoundName fName = null; CompoundName dName = null; CompoundName sName = null; idxNameParser myParser = new idxNameParser(); // *************************************************************** // Create a CompoundName from the Attribute Contents we detected. // Using Only the Domain. try { fName = myParser.parse(fDN.getDomain()); } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } _StatusDest.AccumCounter("FluidDNErrors"); throw new idxIRRException("Error Formulating fName Compound Name in checkforFluidDNs(),\n" + e); } // End of exception // *************************************************************** // Create a CompoundName from the Destination DN of the new Entry. // Using Only the Domain. try { dName = myParser.parse(dDN.getDomain()); } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } _StatusDest.AccumCounter("FluidDNErrors"); throw new idxIRRException("Error Formulating dName Compound Name in checkforFluidDNs(),\n" + e); } // End of exception // *************************************************************** // Create a CompoundName from the Source DN of the Current Entry. // Using Only the Domain. try { sName = myParser.parse(sDN.getDomain()); } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } _StatusDest.AccumCounter("FluidDNErrors"); throw new idxIRRException("Error Formulating sName Compound Name in checkforFluidDNs(),\n" + e); } // End of exception // *********************************************** // Is the Domain of the Source the same as // the Domain of the Attribute DN and // Source and Destination Domains are different? // if ((fName.equals(sName)) && (!sName.equals(dName))) { // ******************* // Yes, now fix it. fixed = true; _StatusDest.AccumCounter("FluidDNDomainTraversals"); if ((!"".equals(fDN.getDNLessDomain())) && (!"".equals(dDN.getDomain()))) { currentfDN = fDN.getDNLessDomain() + "," + dDN.getDomain(); } else if (("".equals(fDN.getDNLessDomain())) && (!"".equals(dDN.getDomain()))) { currentfDN = dDN.getDomain(); } else { currentfDN = fDN.getDNLessDomain(); } if (VERBOSE) { System.out.println(MP + "Fixed Domain Traversal for " + attr.getID() + ": [" + currentfDN + "]"); } // End of Verbose. } // End of If. // ********************************** // Second Fix child entry Traversal. // Set up Compound names for tests. // fDN = new idxParseDN(currentfDN); try { fName = myParser.parse(fDN.getDNLessDomain()); dName = myParser.parse(dDN.getDNLessDomain()); sName = myParser.parse(sDN.getDNLessDomain()); } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } _StatusDest.AccumCounter("FluidDNErrors"); throw new idxIRRException("Error Formulating Compound Name in checkforFluidDNs(),\n" + e); } // End of exception if ((fName.endsWith(sName)) && (!sName.equals(dName))) { // ******************* // Yes, now fix it. int x = currentfDN.toLowerCase().indexOf(sDN.getDNLessDomain().toLowerCase()); if (x != -1) { fixed = true; _StatusDest.AccumCounter("FluidDNChildTraversals"); if ((!"".equals(dDN.getDNLessDomain())) && (!"".equals(fDN.getDomain()))) { currentfDN = currentfDN.substring(0, x) + dDN.getDNLessDomain() + "," + fDN.getDomain(); } else if (("".equals(dDN.getDNLessDomain())) && (!"".equals(fDN.getDomain()))) { currentfDN = currentfDN.substring(0, x) + "," + fDN.getDomain(); } else { currentfDN = currentfDN.substring(0, x); } if (VERBOSE) { System.out.println(MP + "Fixed Child Traversal for " + attr.getID() + ": [" + currentfDN + "]"); } // End of Verbose. } /// End of Inner If. } // End of outer if. // ********************************** // Finally stuff attribute into new // Attribute context. // newFvalues.add(currentfDN); } // End of Inner For Loop. // ********************************** // Now remove existing Attribute // and Replace with the new value set. // entryattrs.remove(newFvalues.getID()); entryattrs.put(newFvalues); if (fixed) { _StatusDest.AccumCounter("FluidDNModifications"); } } // End of Outer For Loop } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } _StatusDest.AccumCounter("FluidDNErrors"); throw new idxIRRException("Exception in checkforFluidDNs(),\n" + e); } // End of Exception. _StatusDest.setLastOpStatus(1); } // End of checkforFluidDNs Method. /** * Obtains Entry from Directory Context and lets an Output Write Class * write the data out. Usually to a file or Standard output. * * @param ctxSource current established Source JNDI Directory Context * @param DNSource DN of source entry. * @param SearchFilter Search Filter. * @param LDIFOUT Output Writer class search results sent. * @param _NICE NICE DN Output Indicator. * @param _StatusSource Source Common Status Object. * @throws idxIRRException if any non-recoverable errors encountered. */ public void ObtainEntryForOutput(DirContext ctxSource, String DNSource, String SearchFilter, BufferedWriter LDIFOUT, boolean _NICE, idxStatus _StatusSource) throws idxIRRException { //****************************************** // Initialize Status Counter. _StatusSource.setLastOp("ObtainEntryforOutput"); _StatusSource.setLastOpResource(DNSource); _StatusSource.setLastOpStatus(-1); //****************************************** // Make sure we have a valid DN. // If the Source Entry is Blank or caller // trying to obtain ROOT, just ignore and // return gracefully. // if (("".equals(DNSource)) || (DNSource == null)) { return; } //****************************************** // Set up our Search Filter. if (SearchFilter == null) { SearchFilter = "(objectclass=*)"; } //****************************************** // Set up our Search Controls. String[] ALL_AttrIDs = {"*"}; SearchControls OS_ctls = new SearchControls(); OS_ctls.setReturningAttributes(ALL_AttrIDs); OS_ctls.setSearchScope(SearchControls.OBJECT_SCOPE); // ***************************************** // Parse the Destination Entry DN to be sure // we have any Quotes.... idxParseDN Naming_Source = new idxParseDN(DNSource); DNSource = Naming_Source.getDNwithQuotes(); // ***************************************** // Obtain the Namespace. String NameSpace = null; try { NameSpace = ctxSource.getNameInNamespace(); if (NameSpace.equals("")) { NameSpace = DNSource; } } catch (Exception e) { { NameSpace = DNSource; } } // End of exception // ***************************************** // Now obtain the Source Entry. // try { int Count = idxIRROutput.LDIFSearchList( ctxSource.search(DNSource, SearchFilter, OS_ctls), NameSpace, LDIFOUT, _NICE); for (; Count > 0; Count--) { _StatusSource.AccumCounter("ReadEntries"); } _StatusSource.setLastOpStatus(1); } catch (NameNotFoundException e) { _StatusSource.AccumCounter("ReadErrors"); _StatusSource.setLastOpStatus(-1); throw new idxIRRException("Source DN was not found, in ObtainEntryForOutput()"); } // End of exception catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error Performing IRR Function, in ObtainEntryForOutput(),\n" + e); } // End of exception } // End of ObtainEntryForOutput /** * Obtains Children Entries from the IRR Directory for output * one level at a time for speed, such as a used in a Backup. * This class will only obtain entries one level at a time and * objectclass attributes to speed up the search. Almost simulates * a paged results control, but this does have more overhead, * since we are obtaining the entry twice. But this allows us to * apply a secondary filter. We are only gettting the DN and * objectclass on the first call, which should provide for a very quick * access. * * @param ctxSource current established Source JNDI Directory Context * @param DNSource Source DN of the base entry to be read. * @param _SearchFilter Filter to be used to acquire entries. * @param LDIFOUT Output Writer class search results sent. * @param _NICE NICE LDIF Output Indicator. * @param dnLevelList containing all children DNs to be copied. * @param _StatusSource Status Class. * @throws idxIRRException if any non-recoverable errors encountered. */ public void ObtainChildrenForOutput(DirContext ctxSource, String DNSource, String _SearchFilter, BufferedWriter LDIFOUT, boolean _NICE, idxDNLinkList dnLevelList, idxStatus _StatusSource) throws idxIRRException { // **************************************** // Obtain Children // SearchControls OL_ctls = new SearchControls(); OL_ctls.setReturningAttributes(NO_Attributes); OL_ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE); // ***************************************** // Parse the Destination Entry DN to be sure // we have any Quotes.... idxParseDN Naming_Source = new idxParseDN(DNSource); DNSource = Naming_Source.getDNwithQuotes(); // ***************************************** // Now obtain the Source Entry. // try { NamingEnumeration nes = ctxSource.search(DNSource, "(objectclass=*)", OL_ctls); while (nes.hasMore()) { SearchResult srs = (SearchResult) nes.next(); String RDN = srs.getName(); // ***************************** // Acquire the correct DNs. String ThisSourceDN = null; if ((DNSource != null) && (!"".equals(DNSource))) { ThisSourceDN = RDN + "," + DNSource; } else { ThisSourceDN = RDN; } // ***************************** // Object the Child Entry ObtainEntryForOutput(ctxSource, ThisSourceDN, _SearchFilter, LDIFOUT, _NICE, _StatusSource); // ***************************** // Now place the Childs DN in // the Queue to process it's // Children on the next iteration. // dnLevelList.addLast(ThisSourceDN); } // End of While. } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error Performing IRR Search for Children, in ObtainChildrenForOutput(),\n" + e); } // End of exception } ///: End of ObtainChildrenForOutput Class. /** * Obtains Children Entries from the IRR Directory for Queuing * one level at a time for speed, such as a used in a Backup. * This class will only obtain entries one level at a time and * objectclass attributes to speed up the search. Almost simulates * a paged results control, but this does have more overhead, * since we are obtaining the entry twice. But this allows us to * apply a secondary filter. We are only gettting the DN and * objectclass on the first call, which should provide for a very quick * access. * * @param ctxSource current established Source JNDI Directory Context * @param DNSource Source DN of the base entry to be read. * @param _SearchFilter Filter to be used to acquire entries. * @param dnLevelList containing all children DNs to be copied. * @param _StatusSource Status Class. * @throws idxIRRException if any non-recoverable errors encountered. */ public void ObtainChildrenForQueue(DirContext ctxSource, String DNSource, String _SearchFilter, idxDNLinkList dnLevelList, idxStatus _StatusSource) throws idxIRRException { // **************************************** // Obtain Children // SearchControls OL_ctls = new SearchControls(); OL_ctls.setReturningAttributes(NO_Attributes); OL_ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE); // ***************************************** // Parse the Destination Entry DN to be sure // we have any Quotes.... idxParseDN Naming_Source = new idxParseDN(DNSource); DNSource = Naming_Source.getDNwithQuotes(); // ***************************************** // Now obtain the Source Entry. // try { NamingEnumeration nes = ctxSource.search(DNSource, "(objectclass=*)", OL_ctls); while (nes.hasMore()) { SearchResult srs = (SearchResult) nes.next(); String RDN = srs.getName(); // ***************************** // Acquire the correct DNs. String ThisSourceDN = null; if ((DNSource != null) && (!"".equals(DNSource))) { ThisSourceDN = RDN + "," + DNSource; } else { ThisSourceDN = RDN; } // ***************************** // Now place the Childs DN in // the Queue to process it's // Children on the next iteration. // dnLevelList.addLast(ThisSourceDN); } // End of While. } catch (Exception e) { if (DEBUG) { e.printStackTrace(); } throw new idxIRRException("Error Performing IRR Search for Children, in ObtainChildrenForQueue(),\n" + e); } // End of exception } ///: End of ObtainChildrenForQueue Class. /** * Obtains Children Entries from the IRR Directory by walking * one level at a time for speed, such as a used in a Backup. * This class will only obtain entries one level at a time and * objectclass attributes to speed up the search. Almost simulates * a paged results control, but this does have more overhead, * since we are obtaining the entry twice. But this allows us to * apply a secondary filter. We are only gettting the DN and * objectclass on the first call, which should provide for a very quick * access. * * @param ctxSource current established Source JNDI Directory Context * @param DNSource Source DN of the base entry to be read. * @param dnLevelList containing all children DNs to be copied. * @param _IgnoreNotFound indicates whether or not to ignore a note found condition. * @throws idxIRRException if any non-recoverable errors encountered. */ public void addChildrentoList(DirContext ctxSource, String DNSource, idxDNLinkList dnLevelList, boolean _IgnoreNotFound) throws idxIRRException { // **************************************** // Obtain Children // SearchControls OL_ctls = new SearchControls(); OL_ctls.setReturningAttributes(NO_Attributes); OL_ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE); // ***************************************** // Parse the Destination Entry DN to be sure // we have any Quotes.... idxParseDN Naming_Source = new idxParseDN(DNSource); DNSource = Naming_Source.getDNwithQuotes(); // ********************************************* // Now obtain the Source Entries at this level. // try { NamingEnumeration nes = ctxSource.search(DNSource, "(objectclass=*)", OL_ctls); while (nes.hasMore()) { SearchResult srs = (SearchResult) nes.next(); String RDN = srs.getName(); // ***************************** // Acquire the correct DNs. String ThisSourceDN = null; if ((DNSource != null) && (!"".equals(DNSource))) { ThisSourceDN = RDN + "," + DNSource; } else { ThisSourceDN = RDN; } // ***************************** // Now place the Childs DN in // the Queue to process it's // Children on the next iteration. // dnLevelList.addLast(ThisSourceDN); } // End of While. } catch (NameNotFoundException e) { if (!_IgnoreNotFound) { throw new idxIRRException("NameNotFoundException for entry of [" + DNSource + "] while performing IRR Search for Children, in addChildrentoList()"); } } catch (Exception e) { throw new idxIRRException("Exception Performing IRR Search for Children, in addChildrentoList(),\n" + e); } // End of exception } ///: End of addChildrentoList Class. /** * Removes a Attribute from a Directory Entry. * * @param ctxSource current established Source JNDI Directory Context * @param SourceDN current DN of Entry which is to be removed. * @param AttributeName current Attribute Name to be removed. * @param _IgnoreNoSuchAttribute indicates whether or not to ignore a NoSuchAttribute Exception. * @throws idxIRRException if any non-recoverable errors encountered. */ public void RemoveAttribute(DirContext ctxSource, String SourceDN, String AttributeName, boolean _IgnoreNoSuchAttribute) throws idxIRRException { ; try { ModificationItem[] irrmods = new ModificationItem[1]; irrmods[0] = new ModificationItem( DirContext.REMOVE_ATTRIBUTE, new BasicAttribute(AttributeName)); ctxSource.modifyAttributes(SourceDN, irrmods); } catch (NoSuchAttributeException nsae) { if (_IgnoreNoSuchAttribute) { return; } throw new idxIRRException("Exception Performing IRR Removal of Attribute[" + AttributeName + "], from Entry[" + SourceDN + "],\n" + nsae); } catch (Exception e) { throw new idxIRRException("Exception Performing IRR Removal of Attribute[" + AttributeName + "], from Entry[" + SourceDN + "],\n" + e); } // End of Exception. } ///: End of RemoveAttribute. } ///:~ End of idxIRRutil Class