package jeffaschenk.commons.frameworks.cnxidx.utility.ldap; import java.util.Hashtable; import java.util.Properties; import javax.naming.Context; /** * Java Class which provides the common utility function to obtain an LDAP * Directory Context. Used throughout the IRR utility and Admin Functions. * * @author jeff.schenk * @version 1.0 $Revision * Developed 2001 */ public class idxManageContext implements DataMappingConstants, idxCMDReturnCodes { private Hashtable<String,String> irrenv = null; public IcosDirContext irrctx = null; private String IRRHost = null; private String IRRPrincipal = null; private String IRRCredentials = null; private String IRRSecurityMethod = null; private String IRRContextName = null; private boolean ExitOnException = false; private boolean Available = false; private boolean VERBOSE = false; private static String MP = "idxManageContext: "; private int retryCount; private long retrySleepMillis; private static final int DEFAULT_RETRY_COUNT = 10; private static final long DEFAULT_RETRY_SLEEP_MILLIS = 150; /** * Basic Contructor with Principal and Credentials. * The Standard Default Host of localhost will be used. * * @param _principal Principal (DN) to be used for Context. * @param _credentials Credentials (password) to be used for Context. */ public idxManageContext(String _principal, String _credentials) { // ******************************************* // Initialize our Private Variables. IRRHost = "ldap://localhost"; IRRPrincipal = _principal; IRRCredentials = _credentials; IRRSecurityMethod = "simple"; IRRContextName = "IRRContext"; // ******************************************* // Initialize our Environment. setirrenv(); } // End of idxManageContext Constructor. /** * Basic Contructor with LDAP Host, Principal and Credentials. * * @param _hosturl LDAP Host URL to be used for Context. * @param _principal Principal (DN) to be used for Context. * @param _credentials Credentials (password) to be used for Context. */ public idxManageContext(String _hosturl, String _principal, String _credentials) { // ******************************************* // Initialize our Private Variables. IRRHost = _hosturl; IRRPrincipal = _principal; IRRCredentials = _credentials; IRRSecurityMethod = "simple"; IRRContextName = "IRRContext"; // ******************************************* // Initialize our Environment. setirrenv(); } // End of idxManageContext Constructor. /** * Basic Contructor with LDAP Host, Principal and Credentials. * * @param _hosturl LDAP Host URL to be used for Context. * @param _principal Principal (DN) to be used for Context. * @param _credentials Credentials (password) to be used for Context. * @param _contextname Internal Context Name to be used for Context. */ public idxManageContext(String _hosturl, String _principal, String _credentials, String _contextname) { // ******************************************* // Initialize our Private Variables. IRRHost = _hosturl; IRRPrincipal = _principal; IRRCredentials = _credentials; IRRSecurityMethod = "simple"; IRRContextName = _contextname; // ******************************************* // Initialize our Environment. setirrenv(); } // End of idxManageContext Constructor. /** * Full Primary Contructor with all Options Specified. * * @param _hosturl LDAP Host URL to be used for Context. * @param _principal Principal (DN) to be used for Context. * @param _credentials Credentials (password) to be used for Context. * @param _securitymethod Security Method to be used for Context. * @param _contextname Internal Context Name for Message Display. */ public idxManageContext(String _hosturl, String _principal, String _credentials, String _securitymethod, String _contextname) { // ******************************************* // Initialize our Private Variables. IRRHost = _hosturl; IRRPrincipal = _principal; IRRCredentials = _credentials; IRRSecurityMethod = _securitymethod; IRRContextName = _contextname; // ******************************************* // Initialize our Environment. setirrenv(); } // End of idxManageContext Constructor. /** * Basic Contructor with properties Specified to obtain LDAP Host, Principal and Credentials. * * @param _props Properties To Obtain and load Variables. */ public idxManageContext(Properties _props) { // ******************************************* // Initialize our Private Variables. String key = "LDAPHost"; IRRHost = _props.getProperty(key); if (!IRRHost.startsWith("ldap://")) { IRRHost = "ldap://" + IRRHost; } key = "LDAPPort"; if (_props.containsKey(key)) { IRRHost = IRRHost + ":" + _props.getProperty(key); } key = "LDAPUser"; IRRPrincipal = _props.getProperty(key); key = "LDAPPassword"; IRRCredentials = _props.getProperty(key); IRRSecurityMethod = "simple"; IRRContextName = "IRRContext"; // ******************************************* // Initialize our Environment for the Context. setirrenv(); } // end of idxManageContext Constructor. /** * Basic Contructor with properties Specified to obtain LDAP Host, Principal and Credentials. * * @param _props To Obtain and load Variables. * @param _ContextName Context Name. */ public idxManageContext(Properties _props, String _ContextName) { // ******************************************* // Initialize our Private Variables. String key = "LDAPHost"; IRRHost = _props.getProperty(key); if (!IRRHost.startsWith("ldap://")) { IRRHost = "ldap://" + IRRHost; } key = "LDAPPort"; if (_props.containsKey(key)) { IRRHost = IRRHost + ":" + _props.getProperty(key); } key = "LDAPUser"; IRRPrincipal = _props.getProperty(key); key = "LDAPPassword"; IRRCredentials = _props.getProperty(key); IRRSecurityMethod = "simple"; IRRContextName = _ContextName; // ******************************************* // Initialize our Environment for the Context. setirrenv(); } // End of idxManageContext Constructor. // *************************************************** // TODO Apply Change for SSL Protocol Support. // Create a new Constructor that will create an // SSL socket to the correct SSL socket on the // Directory. // *************************************************** /** * setExitOnException method to set ExitOnException boolean indicator. * * @param _flag Indicator value to set ExitOnException. */ public void setExitOnException(boolean _flag) { ExitOnException = _flag; } // End of setExitOnException. /** * isExitOnException method to return ExitOnException boolean indicator. * * @return boolean current setting of ExitOnException. */ public boolean isExitOnException() { return (ExitOnException); } // End of isExitOnException. /** * isAvailable method to return Available boolean indicator. * * @return boolean current setting of Available. */ public boolean isAvailable() { return (Available); } // End of isAvailable. /** * setVerbose method to set VERBOSE boolean indicator. * * @param _flag Indicator value to set VERBOSE. */ public void setVerbose(boolean _flag) { VERBOSE = _flag; } // End of setVerbose. /** * setRetryCount method to set RetryCount. * * @param _retryCount RetryCount. */ public void setRetryCount(int _retryCount) { retryCount = _retryCount; } // End of setRetryCount. /** * setRetryWaitTime method to set WaitTime. * * @param _WaitTime WaitTime Milliseconds. */ public void setRetryWaitTime(long _WaitTime) { retrySleepMillis = _WaitTime; } // End of setRetryCount. /** * setirrenv method to initialize and set environment properties. */ private void setirrenv() { // ******************************************* // Indicate the Context is not Available yet. Available = false; // ******************************************* // Assume No Retries. retryCount = 0; retrySleepMillis = 0; // ******************************************* // Assume we will not exit on Exception, let // Object Owner perform Exception. setExitOnException(false); // ******************************************* // Acquire System Properties. irrenv = new Hashtable<>(); // ******************************************* // Initialize Environment Properties. irrenv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); irrenv.put(Context.PROVIDER_URL, IRRHost); irrenv.put(Context.SECURITY_PRINCIPAL, IRRPrincipal); irrenv.put(Context.SECURITY_AUTHENTICATION, IRRSecurityMethod); irrenv.put(Context.SECURITY_CREDENTIALS, IRRCredentials); // ******************************************* // Initialize Additional LDAP Properties. // ******************************************* // Specify any non-String Attributes not in // Standard supplied JNDI specification. // The property must be in sync with // idxIRRSchema class as well as our // Directory Schema. // // Specify Each attribute deliminted by a space. // See DataMappingContants. // irrenv.put("java.naming.ldap.attributes.binary", BIN_ATTRIBUTE_NAMES); // ******************************************* // Specify LDAP Version 3 Protocol. // This is the default for JNDI. irrenv.put("java.naming.ldap.version", "3"); // ******************************************* // Specify deleteRDN on a Rename. // // java.naming.ldap.deleterdn: // When a JNDI Rename occurs, take the default // and remove the RDN attribute of the old // naming attribute. // irrenv.put("java.naming.ldap.deleterdn", "true"); // ******************************************* // Specify our DeReferencing Alias Property. // // java.naming.ldap.derefAliases: // Specifies DeReferencing Rule: // always = Always Dereference Aliases, DEFAULT. // never = Never Dereference Aliases. // finding = Dereferences Aliases only during name resolution. // searching = Dereferences Aliases only after name resolution. // irrenv.put("java.naming.ldap.derefAliases", System.getProperty("java.naming.ldap.derefAliases", "always")); // ******************************************* // Initialize Additional Naming Properties. // ******************************************* // Specify BatchSize. // // java.naming.batchsize (Context.BATCHSIZE): // Sets the recommended size limit for the number of search results // held by a returned NamingEnumeration. // If not specified then the default batchsize is 1. // This helps to ensure the smallest memory footprint possible // by the class library. // A value of 0 disables batchsize and indicates that a // search will block until all results are collected. // irrenv.put("java.naming.batchsize", "0"); // ******************************************* // Specify REFERRAL. // // java.naming.referral (Context.REFERRAL): // Sets how the application will handle REFERRALS // when provided from the Directory Server. // // Since the DCL Directory implementation // specifies that REFERRALS will be chained, // then if we receive a referral, there is a // potential that a Realm or subordinate // Directory instance is not running or down. // // If we set this to "follow", and a // Directory Instance is down, then response // time for all Search operations will be // very long. // // Currently this is set to Ignore. // Meaning, if a REFERRAL is received from // a request, than the REFERRAL Entity is // Simple Ignored and normal processing will // continue. // We will rely on the DCL Directory Implementation // to provide automatic following of the // Referrals, before we get information returned // to us. // // Otherwise the default is to throw the // Exception which is not correct in our // environment. // Another option is to "follow" the // Referral, but in our case if a Referral // is received we know a Directory Instance // is down. // irrenv.put("java.naming.referral", System.getProperty("java.naming.referral", "ignore")); // ******************************************* // Specify our Object Factories. // // java.naming.factory.object: // specified Classes must implement // the ObjectFactory or DirObjectFactory interface. // irrenv.put("java.naming.factory.object", System.getProperty("java.naming.factory.object", "")); // ******************************************* // Specify our State Factories. // // java.naming.factory.state: // specified Classes must implement // the StateFactory or DirStateFactory interface. // irrenv.put("java.naming.factory.state", System.getProperty("java.naming.factory.state", "")); // ******************************************* // Specify our Control Factories. // // java.naming.factory.control: // specified Classes must implement // the ControlFactory interface. // irrenv.put("java.naming.factory.control", System.getProperty("java.naming.factory.control", "")); // ************************************************** // Obtain Other Parameters from the Incoming System // Properties. try { retryCount = Integer.parseInt( System.getProperty("user.dcl.dcd.retrycount", "0")); } catch (Exception e) { retryCount = DEFAULT_RETRY_COUNT; } // End of Exception. try { retrySleepMillis = Integer.parseInt( System.getProperty("user.dcl.dcd.retrysleepmillis", "0")); } catch (Exception e) { retrySleepMillis = DEFAULT_RETRY_SLEEP_MILLIS; } // End of Exception. if (retryCount == 0) { retryCount = DEFAULT_RETRY_COUNT; } if (retrySleepMillis == 0) { retrySleepMillis = DEFAULT_RETRY_SLEEP_MILLIS; } } // End of setirrenv Method. /** * open method to initialize and obtain new IRR Directory Context. * * @throws idxIRRException if unable to obtain Context. */ public void open() throws idxIRRException { // *************************************************** // Make sure we do not already have a context. if ((irrctx != null) || (Available)) { throw new idxIRRException(MP + "IRR Context Already exists or Available for " + IRRContextName + "."); } // End of If. // *************************************************** // Try and Obtain a new Context. try { // ******************************************* // Obtain a new Directory Context. //irrctx = new InitialDirContext(irrenv); irrctx = new IcosDirContext(irrenv, retryCount, retrySleepMillis); Available = true; // Indicate Available. } catch (javax.naming.CommunicationException e) { // ******************************************** // Ok, this is way to generic, let us get to // Root Cause. String rootcause = getRootCause(e, VERBOSE); if (rootcause.indexOf("java.net.connectexception: connection refused") >= 0) { if (ExitOnException) { System.err.println(MP + "IRR Connection Refused to Host " + IRRHost + " for " + IRRContextName + " Directory Context."); System.exit(EXIT_IRR_CONNECTION_REFUSED); } else { throw new idxIRRException(MP + "IRR Connection Refused to Host " + IRRHost + " for " + IRRContextName + " Directory Context."); } // end of ExitOnException Else } // End of If. else if (rootcause.indexOf("java.net.unknownhostexception") >= 0) { if (ExitOnException) { System.err.println(MP + "IRR Unknown Host " + IRRHost + " specified for " + IRRContextName + " Directory Context."); System.exit(EXIT_IRR_UNKNOWN_HOST); } else { throw new idxIRRException(""); } // end of ExitOnException Else } // End of Else if. else { if (ExitOnException) { System.err.println(MP + "IRR Communication Exception to Host " + IRRHost + " specified for " + IRRContextName + " Directory Context," + e); System.exit(EXIT_IRR_GENERIC_COMMUNICATION_EXCEPTION); } else { e.printStackTrace(); throw new idxIRRException(MP + "IRR Communication Exception to Host " + IRRHost + " specified for " + IRRContextName + " Directory Context," + e); } // end of ExitOnException Else } // End of Else. } catch (javax.naming.AuthenticationException e) { // ******************************************* // Can not Authenticate. if (ExitOnException) { System.err.println(MP + "IRR Unable to Authenticate to Host " + IRRHost + " specified for " + IRRContextName + " Directory Context."); System.exit(EXIT_IRR_UNABLE_TO_AUTHENTICATE); } else { throw new idxIRRException(MP + "IRR Unable to Authenticate to Host " + IRRHost + " specified for " + IRRContextName + " Directory Context."); } // end of ExitOnException Else } catch (Exception e) { // ******************************************* // Something Else Happened. if (ExitOnException) { System.err.println(MP + "IRR Exception Obtaining Context for Host " + IRRHost + " specified for " + IRRContextName + " Directory Context.\n" + e); System.exit(EXIT_IRR_UNABLE_TO_OBTAIN_CONTEXT); } else { throw new idxIRRException(MP + "IRR Exception Obtaining Context for Host " + IRRHost + " specified for " + IRRContextName + " Directory Context. " + e); } // end of ExitOnException Else } // End of exception processing. } // End of open Method. /** * close method to close existing IRR Directory Context. * * @throws idxIRRException if unable to obtain Context. */ public void close() throws idxIRRException { // *************************************************** // Make sure we already have a context. if ((irrctx == null) || (!Available) || (!(irrctx instanceof IcosDirContext))) { throw new idxIRRException(MP + "IRR Context does not exist or Available for " + IRRContextName + "."); } // End of If. // *************************************************** // Perform the Close. try { ((IcosDirContext) irrctx).close(); } catch (Exception e) { // ******************************************* // Something Else Happened. if (ExitOnException) { System.err.println(MP + "IRR Exception Closing Context for Host " + IRRHost + " specified for " + IRRContextName + " Directory Context.\n" + e); System.exit(EXIT_IRR_CLOSE_FAILURE); } else { throw new idxIRRException(MP + "IRR Exception Closing Context for Host " + IRRHost + " specified for " + IRRContextName + " Directory Context. " + e); } // end of ExitOnException Else } // End of exception Available = false; // Indicate is not Available. irrctx = null; // Finalize the Context. } // End of close method. /** * disableAliasDereferencing method to override default or obtained * property to NEVER Dereference Alias Entries. * * @throws idxIRRException if unable to perform. */ public void disableAliasDereferencing() throws idxIRRException { // *************************************************** // Make sure we already have a context. if ((irrctx == null) || (!Available) || (!(irrctx instanceof IcosDirContext))) { throw new idxIRRException(MP + "IRR Context does not exist or Available for " + IRRContextName + "."); } // End of If. // ***************************************** // Set the dereference alias property to // NEVER! // If the property already exists this will // Overwrite it. try { irrctx.addToEnvironment("java.naming.ldap.derefAliases", "never"); } catch (Exception e) { throw new idxIRRException(MP + "IRR Context Exception within disableAliasDereferencing, for " + IRRContextName + ", " + e); } // End of Exception. } // End of disableAliasDeferencing method. /** * enableAliasDereferencing method to override default or obtained * property to ALWAYS Dereference Alias Entries. * * @throws idxIRRException if unable to perform. */ public void enableAliasDereferencing() throws idxIRRException { // *************************************************** // Make sure we already have a context. if ((irrctx == null) || (!Available) || (!(irrctx instanceof IcosDirContext))) { throw new idxIRRException(MP + "IRR Context does not exist or Available for " + IRRContextName + "."); } // End of If. // ***************************************** // Set the dereference alias property to // NEVER! // If the property already exists this will // Overwrite it. try { irrctx.addToEnvironment("java.naming.ldap.derefAliases", "always"); } catch (Exception e) { throw new idxIRRException(MP + "IRR Context Exception within enableAliasDereferencing, for " + IRRContextName + ", " + e); } // End of Exception. } // End of enableAliasDeferencing method. /** * showAliasDereferencing method to simple show current * property of Dereference Alias Entries. * * @throws idxIRRException if unable to perform. */ public void showAliasDereferencing() throws idxIRRException { // *************************************************** // Make sure we already have a context. if ((irrctx == null) || (!Available) || (!(irrctx instanceof IcosDirContext))) { throw new idxIRRException(MP + "IRR Context does not exist or Available for " + IRRContextName + "."); } // End of If. // ***************************************** // Show the dereference alias property. try { Hashtable IRRproperties = irrctx.getEnvironment(); String _derefAliases = ((String) IRRproperties.get("java.naming.ldap.derefAliases")); if ((_derefAliases == null) || (_derefAliases.equals(""))) { _derefAliases = "always"; } // ********************************** // Output to Standard Output the // Setting. System.out.println(MP + "IRR Dereferenced Aliases Setting for Host:[" + IRRHost + "] Context Name:[" + IRRContextName + "] is set to:[" + _derefAliases + "]."); } catch (Exception e) { throw new idxIRRException(MP + "IRR Context Exception within showAliasDereferencing, for " + IRRContextName + ", " + e); } // End of Exception. } // End of showAliasDeferencing method. /** * disableDSAEFactories method to disable the DSAE Object and State * factories. * * @throws idxIRRException if unable to perform. */ public void disableDSAEFactories() throws idxIRRException { // *************************************************** // Make sure we already have a context. if ((irrctx == null) || (!Available) || (!(irrctx instanceof IcosDirContext))) { throw new idxIRRException(MP + "IRR Context does not exist or Available for " + IRRContextName + "."); } // End of If. // ************************************************ // Remove the State and Object Factory Properties. try { Hashtable env = irrctx.getEnvironment(); if (env.containsKey(Context.OBJECT_FACTORIES)) { irrctx.removeFromEnvironment(Context.OBJECT_FACTORIES); } if (env.containsKey(Context.STATE_FACTORIES)) { irrctx.removeFromEnvironment(Context.STATE_FACTORIES); } } catch (Exception e) { throw new idxIRRException(MP + "IRR Context Exception within disableDSAEFactories, for " + IRRContextName + ", " + e); } // End of Exception. } // End of disableDSAEFactories method. /** * enableDSAEFactories method to Enable the use of the DSAE Object and * State Factories. * * @throws idxIRRException if unable to perform. */ public void enableDSAEFactories() throws idxIRRException { // *************************************************** // Make sure we already have a context. if ((irrctx == null) || (!Available) || (!(irrctx instanceof IcosDirContext))) { throw new idxIRRException(MP + "IRR Context does not exist or Available for " + IRRContextName + "."); } // End of If. // ***************************************** // Set the State and Object Factories. // If the property already exists this will // Overwrite it. /** try { irrctx.addToEnvironment(Context.STATE_FACTORIES, FRAMEWORK_DEFAULT_STATE_FACTORY); irrctx.addToEnvironment(Context.OBJECT_FACTORIES, FRAMEWORK_DEFAULT_OBJECT_FACTORY); } catch (Exception e) { throw new idxIRRException(MP + "IRR Context Exception within enableDSAEFactories, for " + IRRContextName + ", " + e); } // End of Exception. **/ } // End of enableDSAEFactories method. /** * showDSAEFactories method to simple show current * property of DSAE Object and State Factories. * * @throws idxIRRException if unable to perform. */ public void showDSAEFactories() throws idxIRRException { // *************************************************** // Make sure we already have a context. if ((irrctx == null) || (!Available) || (!(irrctx instanceof IcosDirContext))) { throw new idxIRRException(MP + "IRR Context does not exist or Available for " + IRRContextName + "."); } // End of If. // ***************************************** // Show the JNDI Factory Settings. try { Hashtable env = irrctx.getEnvironment(); String OBJECT_FACTORY = "NOT SET"; if (env.containsKey(Context.OBJECT_FACTORIES)) { OBJECT_FACTORY = (String) env.get(Context.OBJECT_FACTORIES); } String STATE_FACTORY = "NOT SET"; if (env.containsKey(Context.STATE_FACTORIES)) { STATE_FACTORY = (String) env.get(Context.STATE_FACTORIES); } // ********************************** // Output to Standard Output the // Setting. System.out.println(MP + "IRR Factory Settings for Host:[" + IRRHost + "] Context Name:[" + IRRContextName + "] are:"); System.out.println("\tObject Factories:[" + OBJECT_FACTORY + "]"); System.out.println("\tState Factories:[" + STATE_FACTORY + "]"); } catch (Exception e) { throw new idxIRRException(MP + "IRR Context Exception within showDSAEFactories, for " + IRRContextName + ", " + e); } // End of Exception. } // End of showDSAEFactories method. /** * getRootCause method to obtain root cause within an Exception. * * @param e Object * @param _showflag Flag to indicate if Root Cause should be displayed. * @return String of Lower Case Normalized Root Cause. */ private String getRootCause(Object e, boolean _showflag) { String rootcause = e.toString(); rootcause = rootcause.toLowerCase(); if ((rootcause == null) || ("".equals(rootcause))) { return ("None"); } int rci = rootcause.indexOf("[root exception is"); if (rci >= 0) { rootcause = rootcause.substring(rci); } else { return ("None"); } if (_showflag) { System.err.println(MP + "Root Cause Found:" + rootcause); } // End of If. return (rootcause); } // End of getRootCause Method. } ///:~ End of idxManageContext Class.