package jeffaschenk.commons.frameworks.cnxidx.admin; import jeffaschenk.commons.frameworks.cnxidx.utility.StopWatch; import jeffaschenk.commons.frameworks.cnxidx.utility.filtering.FilterString; import jeffaschenk.commons.frameworks.cnxidx.utility.ldap.*; import jeffaschenk.commons.touchpoint.model.threads.CircularObjectStack; import java.io.*; import javax.naming.*; import javax.naming.directory.*; /** * IRR Backup Walker Thread. Used to read Entries from Directory * to determine if the entries needs to be written to our Backup Thread. * * @author jeff.schenk * @version 4.4 $Revision * Developed 2005 */ /** * IRRBackupWalkerThread * Class to run Walker Thread. */ class IRRBackupWalkerThread implements Runnable, idxCMDReturnCodes { /** * IRRBackupWalkerThread * Class to provide Walker interface to Level Searches. */ Thread t; private CircularObjectStack[] cosout_readers; private IRRBackupStatusNew WalkerStatus; private static String MP = "IRRBackupWalkerThread: "; private static idxManageContext IRRSource = null; private static String ENTRY_SOURCE_DN = null; private static String SearchFilter = null; private static boolean VERBOSE = false; private static boolean DEBUG = false; private static boolean BACKUP_WITH_CHILDREN = false; private static boolean IGNORE_VENDOR_OBJECTS = false; private boolean ExitOnException = false; // ************************************************* // Reader Thread Filter private static String DN_THREAD_FILTER_CLASSIFIER_FILENAME = null; private boolean DN_THREAD_FILTER_AVAILABLE = false; private FilterString DN_THREAD_FILTER = null; private static final String THREAD = "THREAD"; // ************************************************** // Matching Filters. public static final String VENDOROBJECTS_PATTERN = "^.*ou\\s*=\\s*vendorobjects+.*"; public static final String ACTIONGROUPS_PATTERN = "^.*ou\\s*=\\s*actiongroups+.*"; public static final String FRAMEWORKDOMAIN_PATTERN = "^.*ou\\s*=\\s*framework+.*"; public static final String RECYCLEBIN_PATTERN = "^.*ou\\s*=\\s*recycle+.*"; public static final String CONTENT_PATTERN = "^.*rcu\\s*=\\s*content+.*"; /** * IRRBackupWalkerThread Contructor class driven. * * @param cosout Circular Object Stack for placing DN's on Read Queue. * @param WalkerStatus Object used for Thread Status. * @param IRRSource Managed DirContext * @param ENTRY_SOURCE_DN Specified where to begin Backup in Tree. * @param SearchFilter to be used. * @param BACKUP_WITH_CHILDREN Indicate if Children should be included in backup. * @param VERBOSE Indicate Verbosity. * @param DEBUG Indicate DEBUGGING. * @param ExitOnException Indicate Exit on Exceptions. */ IRRBackupWalkerThread(CircularObjectStack cosout, IRRBackupStatusNew WalkerStatus, idxManageContext IRRSource, String ENTRY_SOURCE_DN, String SearchFilter, boolean BACKUP_WITH_CHILDREN, boolean VERBOSE, boolean DEBUG, boolean ExitOnException) { // **************************************** // Set My Incoming Parameters. // Using only one reader. cosout_readers = new CircularObjectStack[1]; cosout_readers[0] = cosout; this.ENTRY_SOURCE_DN = ENTRY_SOURCE_DN; this.SearchFilter = SearchFilter; this.BACKUP_WITH_CHILDREN = BACKUP_WITH_CHILDREN; this.VERBOSE = VERBOSE; this.DEBUG = DEBUG; this.ExitOnException = ExitOnException; this.WalkerStatus = WalkerStatus; this.IRRSource = IRRSource; // **************************************** // Start the Thread. t = new Thread(this, "IRRbackup_LevelWalker"); t.start(); // Start the Thread. } // End of Contructor. /** * IRRBackupWalkerThread Contructor class driven. * * @param cosout Circular Object Stack for placing DN's on Read Queue. * @param WalkerStatus Object used for Thread Status. * @param IRRSource Managed DirContext * @param ENTRY_SOURCE_DN Specified where to begin Backup in Tree. * @param SearchFilter to be used. * @param BACKUP_WITH_CHILDREN Indicate if Children should be included in backup. * @param VERBOSE Indicate Verbosity. * @param DEBUG Indicate DEBUGGING. * @param ExitOnException Indicate Exit on Exceptions. */ IRRBackupWalkerThread(CircularObjectStack cosout, IRRBackupStatusNew WalkerStatus, idxManageContext IRRSource, String ENTRY_SOURCE_DN, String SearchFilter, boolean BACKUP_WITH_CHILDREN, boolean IGNORE_VENDOR_OBJECTS, String DN_THREAD_FILTER_CLASSIFIER_FILENAME, boolean VERBOSE, boolean DEBUG, boolean ExitOnException) { // **************************************** // Set My Incoming Parameters. // Using only one reader. cosout_readers = new CircularObjectStack[1]; cosout_readers[0] = cosout; this.ENTRY_SOURCE_DN = ENTRY_SOURCE_DN; this.SearchFilter = SearchFilter; this.BACKUP_WITH_CHILDREN = BACKUP_WITH_CHILDREN; this.IGNORE_VENDOR_OBJECTS = IGNORE_VENDOR_OBJECTS; this.DN_THREAD_FILTER_CLASSIFIER_FILENAME = DN_THREAD_FILTER_CLASSIFIER_FILENAME; this.VERBOSE = VERBOSE; this.DEBUG = DEBUG; this.ExitOnException = ExitOnException; this.WalkerStatus = WalkerStatus; this.IRRSource = IRRSource; // **************************************** // Start the Thread. t = new Thread(this, "IRRbackup_LevelWalker"); t.start(); // Start the Thread. } // End of Contructor. /** * IRRBackupWalkerThread Contructor class driven. * * @param cosout_readers Circular Object Stacks for placing DN's on Read Queues. * @param WalkerStatus Object used for Thread Status. * @param IRRSource Managed DirContext * @param ENTRY_SOURCE_DN Specified where to begin Backup in Tree. * @param SearchFilter to be used. * @param BACKUP_WITH_CHILDREN Indicate if Children should be included in backup. * @param VERBOSE Indicate Verbosity. * @param DEBUG Indicate DEBUGGING. * @param ExitOnException Indicate Exit on Exceptions. */ IRRBackupWalkerThread(CircularObjectStack[] cosout_readers, IRRBackupStatusNew WalkerStatus, idxManageContext IRRSource, String ENTRY_SOURCE_DN, String SearchFilter, boolean BACKUP_WITH_CHILDREN, boolean VERBOSE, boolean DEBUG, boolean ExitOnException) { // **************************************** // Set My Incoming Parameters. // this.cosout_readers = cosout_readers; this.ENTRY_SOURCE_DN = ENTRY_SOURCE_DN; this.SearchFilter = SearchFilter; this.BACKUP_WITH_CHILDREN = BACKUP_WITH_CHILDREN; this.VERBOSE = VERBOSE; this.DEBUG = DEBUG; this.ExitOnException = ExitOnException; this.WalkerStatus = WalkerStatus; this.IRRSource = IRRSource; // **************************************** // Start the Thread. t = new Thread(this, "IRRbackup_LevelWalker"); t.start(); // Start the Thread. } // End of Contructor. /** * IRRBackupWalkerThread Contructor class driven. * * @param cosout_readers Circular Object Stacks for placing DN's on Read Queues. * @param WalkerStatus Object used for Thread Status. * @param IRRSource Managed DirContext * @param ENTRY_SOURCE_DN Specified where to begin Backup in Tree. * @param SearchFilter to be used. * @param BACKUP_WITH_CHILDREN Indicate if Children should be included in backup. * @param VERBOSE Indicate Verbosity. * @param DEBUG Indicate DEBUGGING. * @param ExitOnException Indicate Exit on Exceptions. */ IRRBackupWalkerThread(CircularObjectStack[] cosout_readers, IRRBackupStatusNew WalkerStatus, idxManageContext IRRSource, String ENTRY_SOURCE_DN, String SearchFilter, boolean BACKUP_WITH_CHILDREN, boolean IGNORE_VENDOR_OBJECTS, String DN_THREAD_FILTER_CLASSIFIER_FILENAME, boolean VERBOSE, boolean DEBUG, boolean ExitOnException) { // **************************************** // Set My Incoming Parameters. // this.cosout_readers = cosout_readers; this.ENTRY_SOURCE_DN = ENTRY_SOURCE_DN; this.SearchFilter = SearchFilter; this.BACKUP_WITH_CHILDREN = BACKUP_WITH_CHILDREN; this.IGNORE_VENDOR_OBJECTS = IGNORE_VENDOR_OBJECTS; this.DN_THREAD_FILTER_CLASSIFIER_FILENAME = DN_THREAD_FILTER_CLASSIFIER_FILENAME; this.VERBOSE = VERBOSE; this.DEBUG = DEBUG; this.ExitOnException = ExitOnException; this.WalkerStatus = WalkerStatus; this.IRRSource = IRRSource; // **************************************** // Start the Thread. t = new Thread(this, "IRRbackup_LevelWalker"); t.start(); // Start the Thread. } // End of Contructor. public void run() { // *********************************************** // Initialize our StopWatch to measure Duration // of Thread. StopWatch sw = new StopWatch(); sw.start(); // *********************************************** // Initialize Thread Variables. int DNcount = 0; int DNsIgnored = 0; String tname = Thread.currentThread().getName(); System.out.println(MP + "Thread Established for:[" + tname + "]"); // *********************************************** // Initialize my LAP Timers idxLapTime LP_LEVEL_SEARCH = new idxLapTime(); idxLapTime LP_ENTRY_TO_COS = new idxLapTime(); // **************************************** // Set up our Search Controls String[] NO_Attributes = {"1.1"}; SearchControls OL_ctls = new SearchControls(); OL_ctls.setReturningAttributes(NO_Attributes); OL_ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE); // ************************************************** // Obtain Runtime Object. Runtime rt = Runtime.getRuntime(); // **************************************** // Indicate the Backup is starting. System.out.println(MP + "Starting Backup..."); // ********************************************* // Determine if we have a Reader Thread Filter? if (this.DN_THREAD_FILTER_CLASSIFIER_FILENAME != null) { System.out.println(MP + "Attempting Read of Thread Filter File Named:[" + this.DN_THREAD_FILTER_CLASSIFIER_FILENAME + "]."); try { DN_THREAD_FILTER_AVAILABLE = false; DN_THREAD_FILTER = new FilterString(new File(this.DN_THREAD_FILTER_CLASSIFIER_FILENAME), true); DN_THREAD_FILTER_AVAILABLE = true; } catch (Exception e) { System.err.println(MP + "Warning, Unable to obtain the Thread Filter File Named:[" + this.DN_THREAD_FILTER_CLASSIFIER_FILENAME + "], using Default Configuration," + e); } // End of Exception processing. } // End of Check for Read Thread Filter. // **************************************** // Obtain our initial Source Entry. if ((ENTRY_SOURCE_DN != null) && (!ENTRY_SOURCE_DN.equals(""))) { LP_ENTRY_TO_COS.Start(); cosout_readers[classifyDNtoReaderQueue(ENTRY_SOURCE_DN)].push(ENTRY_SOURCE_DN); LP_ENTRY_TO_COS.Stop(); DNcount++; } // End of If. // ***************************************** // Now obtain the IRR Entries for Backup. // idxDNLinkList myChildrenList = new idxDNLinkList(); myChildrenList.addFirst(ENTRY_SOURCE_DN); try { // ***************************** // Obtain all Subsequent Levels while (myChildrenList.IsNotEmpty()) { String myDN = myChildrenList.popfirst(); // ***************************************** // Parse the Destination Entry DN to be sure // we have any Quotes.... idxParseDN Naming_Source = new idxParseDN(myDN); LP_LEVEL_SEARCH.Start(); NamingEnumeration nes = IRRSource.irrctx.search(Naming_Source.getDNwithQuotes(), SearchFilter, OL_ctls); LP_LEVEL_SEARCH.Stop(); if (LP_LEVEL_SEARCH.getCurrentDuration() > 1000) { System.out.println(MP + "Warning ** LEVEL Search took " + LP_LEVEL_SEARCH.getElapsedtoString() + " to Complete for Level:[" + Naming_Source.getDN() + "]"); } // End of If. // ***************************************** // Loop Throught the Results... while (nes.hasMore()) { SearchResult srs = (SearchResult) nes.next(); String RDN = srs.getName(); // ***************************** // Acquire the correct DNs. String SourceDN = RDN; if ((myDN != null) && (!"".equals(myDN))) { SourceDN = RDN + "," + myDN; } // ***************************** // Check for Excluding Entries if (this.IGNORE_VENDOR_OBJECTS) { // ******************************* // Check for Ignore Vendor Objects if (SourceDN.toLowerCase().matches(VENDOROBJECTS_PATTERN)) { DNsIgnored++; continue; } } // End of Check for Ignoring any Vendor Objects. // ***************************** // Now place the Childs DN in // the Queue to process it's // Children on the next iteration. // myChildrenList.addLast(SourceDN); // ***************************** // Now Send the Search Result // Entry to our output thread. // LP_ENTRY_TO_COS.Start(); cosout_readers[classifyDNtoReaderQueue(SourceDN)].push(SourceDN); LP_ENTRY_TO_COS.Stop(); DNcount++; } // End of Inner While. // ************************************** // If we are not obtaining Children, end. if (!BACKUP_WITH_CHILDREN) { break; } } // End of Outer While. } catch (Exception e) { System.err.println(MP + "IRR Exception on Obtaining Child Entries,\n" + e); e.printStackTrace(); WalkerStatus.setError(EXIT_IRR_BACKUP_FAILURE); } // End of exception // ******************************************* // Show number of entries passed through the // Stack. if (DNcount > 0) { System.out.println(MP + "Successful Backup Walker Thread Completed with Entries Passed to Reader Stack:[" + DNcount + "]"); } else { System.out.println(MP + "Exception On Backup Walker Thread Completed with Entries Passed to Reader Stack:[" + DNcount + "]"); } // End of Else Check. // ******************************************* // Show number of entries passed through the // Stack. if (DNsIgnored > 0) { System.out.println(MP + "Entries Ignored:[" + DNsIgnored + "], Filters: Ignore Vendor Objects:[" + this.IGNORE_VENDOR_OBJECTS + "]"); } // End of Checking for Any Ignored DNs. // *************************************** // Show the Lap Timings. System.out.println(MP + "Lap Time for Level Searches: " + LP_LEVEL_SEARCH); System.out.println(MP + "Lap Time for Stack Communications: " + LP_ENTRY_TO_COS); // *************************************** // Show the Duration of Thread. sw.stop(); System.out.println(MP + "Thread Duration: " + sw.getElapsedTimeString()); // *************************************** // Done. return; } // End of run. /** * Classify DN to Reader Queue. * Stack # Usage * ------- ------------------------------- * -0- Primary and Default. * -1- Actiongroups and Framework * -2- VendorObjects if Queue Available. */ private int classifyDNtoReaderQueue(String DN) { int reader_queue = 0; if ((DN == null) || (DN.trim().equalsIgnoreCase(""))) { return reader_queue; } // ******************************* // Proceed to Classify the // DN to A Reader Queue Based upon // number of Reader Queues. if (this.cosout_readers.length <= 1) { return reader_queue; } // ************************************* // If we have an Available FilterString // Object to Group our Matches, then use // it to override our hardcoded // classifications. if (DN_THREAD_FILTER_AVAILABLE) { String groupname = DN_THREAD_FILTER.obtainGroupValueWithMatch(DN); if ((groupname != null) && (!groupname.trim().equalsIgnoreCase(FilterString.FILTER_GROUP_DEFAULT)) && (groupname.trim().toUpperCase().startsWith(this.THREAD))) { int groupthread = -1; try { groupthread = Integer.parseInt(groupname.substring(this.THREAD.length())); groupthread = (groupthread - 1); // Make it Relative to Zero. } catch (NumberFormatException nfe) { groupthread = -1; } // End of Exception. if ((groupthread >= 0) && (groupthread < cosout_readers.length)) { return groupthread; } } // End of Inner Check for a groupname hit from Filter File. } // End of Check using Overriding Thread Filter. // ************************* // When two Readers Are // Available... if (this.cosout_readers.length == 2) { // ************************** // Direct Entries // to Specific Reader Queues. if (DN.toLowerCase().matches(ACTIONGROUPS_PATTERN)) { reader_queue = 0; } if (DN.toLowerCase().matches(FRAMEWORKDOMAIN_PATTERN)) { reader_queue = 1; } if (DN.toLowerCase().matches(RECYCLEBIN_PATTERN)) { reader_queue = 1; } if (DN.toLowerCase().matches(CONTENT_PATTERN)) { reader_queue = 0; } if (!this.IGNORE_VENDOR_OBJECTS) { if (DN.toLowerCase().matches(VENDOROBJECTS_PATTERN)) { reader_queue = 1; } } // End of Check for Using Ignoring Objects. } // End of Else If. // ************************* // When the Max Readers Are // Available... else { // ************************** // Direct Entries // to Specific Reader Queues. if (DN.toLowerCase().matches(ACTIONGROUPS_PATTERN)) { reader_queue = 1; } if (DN.toLowerCase().matches(FRAMEWORKDOMAIN_PATTERN)) { reader_queue = 1; } if (DN.toLowerCase().matches(RECYCLEBIN_PATTERN)) { reader_queue = 1; } if (DN.toLowerCase().matches(CONTENT_PATTERN)) { reader_queue = 1; } // ******************** // Direct VendorObjects // to Specific Thread. if (!this.IGNORE_VENDOR_OBJECTS) { if (DN.toLowerCase().matches(VENDOROBJECTS_PATTERN)) { reader_queue = 2; } } // End of Check for Using Ignoring Objects. else { // ************************************** // Vendor Objects are Ignored so use this // Thread accordingly. // // TODO if (reader_queue != 1) { reader_queue = 2; } } // End of Else. } // End of Else. return reader_queue; } // End of classifyDNtoReaderQueue Private Method. } ///:~ End of Class IRRBackupWalkerThread