Issue #1560 - Migrate some objects to the new admin framework:
- Entry Cache
- Account Status Notification Handler
- Password Storage Scheme
7 files added
35 files modified
| | |
| | | or $value = 'ldap' or $value = 'ldaps' or $value = 'ldif' |
| | | or $value = 'jdbc' or $value = 'tcp' or $value = 'tls' |
| | | or $value = 'pkcs11' or $value = 'sasl' or $value = 'gssapi' |
| | | or $value = 'md5' or $value = 'je' or $value = 'dse' " /> |
| | | or $value = 'md5' or $value = 'je' or $value = 'dse' |
| | | or $value = 'fifo' |
| | | "/> |
| | | </xsl:template> |
| | | </xsl:stylesheet> |
| New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <adm:managed-object |
| | | name="account-status-notification-handler" |
| | | plural-name="account-status-notification-handlers" |
| | | package="org.opends.server.admin.std" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap" |
| | | > |
| | | |
| | | <adm:synopsis> |
| | | <adm:user-friendly-name /> |
| | | is invoked whenever certain types of events occur that could change |
| | | the status of a user account. The |
| | | <adm:user-friendly-name /> |
| | | may be used to notify the user and/or administrators of the change. |
| | | </adm:synopsis> |
| | | |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.75</ldap:oid> |
| | | <ldap:name>ds-cfg-account-status-notification-handler</ldap:name> |
| | | <ldap:superior>top</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | |
| | | <adm:property name="enabled" mandatory="true"> |
| | | <adm:synopsis> |
| | | Indicate whether the |
| | | <adm:user-friendly-name /> |
| | | is enabled for use. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.282</ldap:oid> |
| | | <ldap:name>ds-cfg-account-status-notification-handler-enabled</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="notification-handler-class" mandatory="true"> |
| | | <adm:synopsis> |
| | | The fully-qualified name of the Java class that provides the |
| | | <adm:user-friendly-name /> |
| | | implementation. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:java-class> |
| | | <adm:instance-of> |
| | | org.opends.server.api.AccountStatusNotificationHandler |
| | | </adm:instance-of> |
| | | </adm:java-class> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.281</ldap:oid> |
| | | <ldap:name>ds-cfg-account-status-notification-handler-class</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | </adm:managed-object> |
| | | |
| New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <adm:managed-object |
| | | name="entry-cache" |
| | | plural-name="entry-caches" |
| | | package="org.opends.server.admin.std" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap" |
| | | > |
| | | <adm:synopsis> |
| | | <adm:user-friendly-name /> |
| | | defines a Directory Server entry cache. |
| | | </adm:synopsis> |
| | | |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.15</ldap:oid> |
| | | <ldap:name>ds-cfg-entry-cache</ldap:name> |
| | | <ldap:superior>top</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | |
| | | <adm:property name="enabled" mandatory="true"> |
| | | <adm:synopsis> |
| | | Indicate whether the |
| | | <adm:user-friendly-name /> |
| | | is enabled for use. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.35</ldap:oid> |
| | | <ldap:name>ds-cfg-entry-cache-enabled</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="entry-cache-class" mandatory="true"> |
| | | <adm:synopsis> |
| | | The fully-qualified name of the Java class that provides the |
| | | <adm:user-friendly-name /> |
| | | implementation. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:java-class> |
| | | <adm:instance-of> |
| | | org.opends.server.api.EntryCache |
| | | </adm:instance-of> |
| | | </adm:java-class> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.34</ldap:oid> |
| | | <ldap:name>ds-cfg-entry-cache-class</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | </adm:managed-object> |
| New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <adm:managed-object |
| | | name="error-log-account-status-notification-handler" |
| | | plural-name="error-log-account-status-notification-handlers" |
| | | extends="account-status-notification-handler" |
| | | package="org.opends.server.admin.std" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap" |
| | | > |
| | | |
| | | <adm:synopsis> |
| | | <adm:user-friendly-name /> |
| | | is an account status notification handler that writes information |
| | | about status notifications using the Directory Server's error |
| | | logging facility. |
| | | </adm:synopsis> |
| | | |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.76</ldap:oid> |
| | | <ldap:name> |
| | | ds-cfg-error-log-account-status-notification-handler |
| | | </ldap:name> |
| | | <ldap:superior> |
| | | ds-cfg-account-status-notification-handler |
| | | </ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | |
| | | <adm:property name="account-status-notification-type" mandatory="true" |
| | | multi-valued="true"> |
| | | <adm:synopsis> |
| | | <adm:user-friendly-name /> |
| | | is a possible event type that can trigger an account status |
| | | notification. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:enumeration> |
| | | <adm:value name="account-temporarily-locked"> |
| | | <adm:synopsis> |
| | | Indicates that an account status message should be generated |
| | | whenever a user account has been temporarily locked after |
| | | too many failed attempts. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="account-permanently-locked"> |
| | | <adm:synopsis> |
| | | Indicates that an account status message should be generated |
| | | whenever a user account has been permanently locked after |
| | | too many failed attempts. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="account-unlocked"> |
| | | <adm:synopsis> |
| | | Indicates that an account status message should be generated |
| | | whenever a user account has been unlocked by an |
| | | administrator. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="account-idle-locked"> |
| | | <adm:synopsis> |
| | | Indicates that an account status message should be generated |
| | | whenever a user account has been locked because it was idle |
| | | for too long. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="account-reset-locked"> |
| | | <adm:synopsis> |
| | | Indicates that an account status message should be generated |
| | | whenever a user account has been locked because it the |
| | | password had been reset by an administrator but not changed |
| | | by the user within the required interval. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="account-disabled"> |
| | | <adm:synopsis> |
| | | Indicates that an account status message should be generated |
| | | whenever a user account has been disabled by an |
| | | administrator. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="account-enabled"> |
| | | <adm:synopsis> |
| | | Indicates that an account status message should be generated |
| | | whenever a user account has been enabled by an |
| | | administrator. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="account-expired"> |
| | | <adm:synopsis> |
| | | Indicates that an account status message should be generated |
| | | whenever a user authentication has failed because the |
| | | account has expired. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="password-expired"> |
| | | <adm:synopsis> |
| | | Indicates that an account status notification message should |
| | | be generated whenever a user authentication has failed |
| | | because the password has expired. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="password-expiring"> |
| | | <adm:synopsis> |
| | | Indicates that an account status notification message should |
| | | be generated the first time that a password expiration |
| | | warning is encountered for a user password. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="password-reset"> |
| | | <adm:synopsis> |
| | | Indicates that an account status notification message should |
| | | be generated whenever a user's password is reset by an |
| | | administrator. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="password-changed"> |
| | | <adm:synopsis> |
| | | Indicates whether an account status notification message |
| | | should be generated whenever a user changes his/her own |
| | | password. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | </adm:enumeration> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.283</ldap:oid> |
| | | <ldap:name>ds-cfg-account-status-notification-type</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | </adm:managed-object> |
| | | |
| New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <adm:managed-object |
| | | name="fifo-entry-cache" |
| | | plural-name="fifo-entry-caches" |
| | | package="org.opends.server.admin.std" |
| | | extends="entry-cache" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap" |
| | | > |
| | | |
| | | <adm:synopsis> |
| | | <adm:user-friendly-name /> |
| | | defines a Directory Server entry cache that uses a FIFO to keep |
| | | track of the entries. Entries that have been in the cache the longest are |
| | | the most likely candidates for purging if space is needed. In contrast to |
| | | other cache structures, the selection of entries to purge is not based on |
| | | how frequently or recently the entries have been accessed. This requires |
| | | significantly less locking (it will only be required when an entry is added |
| | | or removed from the cache, rather than each time an entry is accessed). |
| | | |
| | | Cache sizing is based on the percentage of free memory within the JVM, such |
| | | that if enough memory is free, then adding an entry to the cache will not |
| | | require purging, but if more than a specified percentage of the available |
| | | memory within the JVM is already consumed, then one or more entries will need |
| | | to be removed in order to make room for a new entry. It is also possible to |
| | | configure a maximum number of entries for the cache. If this is specified, |
| | | then the number of entries will not be allowed to exceed this value, but it |
| | | may not be possible to hold this many entries if the available memory fills |
| | | up first. |
| | | |
| | | Other configurable parameters for this cache include the maximum length of |
| | | time to block while waiting to acquire a lock, and a set of filters that may |
| | | be used to define criteria for determining which entries are stored in the |
| | | cache. If a filter list is provided, then only entries matching at least |
| | | one of the given filters will be stored in the cache. |
| | | </adm:synopsis> |
| | | |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.16</ldap:oid> |
| | | <ldap:name>ds-cfg-fifo-entry-cache</ldap:name> |
| | | <ldap:superior>ds-cfg-entry-cache</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | |
| | | <adm:property name="lock-timeout" mandatory="false"> |
| | | <adm:synopsis> |
| | | The length of time in milliseconds to wait while |
| | | attempting to acquire a read or write lock. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>2000.0ms</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:duration base-unit="ms" lower-limit="0" allow-unlimited="true"/> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.58</ldap:oid> |
| | | <ldap:name>ds-cfg-lock-timeout</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="max-memory-percent" mandatory="false"> |
| | | <adm:synopsis> |
| | | The maximum memory usage for the entry cache as a percentage |
| | | of the total JVM memory. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>90</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:size lower-limit="1" upper-limit="100"/> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.66</ldap:oid> |
| | | <ldap:name>ds-cfg-max-memory-percent</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="max-entries" mandatory="false"> |
| | | <adm:synopsis> |
| | | The maximum number of entries that we will allow in the cache. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>0x7fffffffffffffffL</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:size lower-limit="0" allow-unlimited="true"/> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.65</ldap:oid> |
| | | <ldap:name>ds-cfg-max-entries</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property-reference name="include-filter" /> |
| | | <adm:property-reference name="exclude-filter" /> |
| | | |
| | | </adm:managed-object> |
| | | |
| | |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="include-filter" mandatory="false" multi-valued="true"> |
| | | <adm:synopsis> |
| | | The set of filters that define the entries that should be |
| | | included in the cache. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:undefined /> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:string /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.43</ldap:oid> |
| | | <ldap:name>ds-cfg-include-filter</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="exclude-filter" mandatory="false" multi-valued="true"> |
| | | <adm:synopsis> |
| | | The set of filters that define the entries that should be |
| | | excluded from the cache. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:undefined /> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:string /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.38</ldap:oid> |
| | | <ldap:name>ds-cfg-exclude-filter</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | </adm:package> |
| New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <adm:managed-object |
| | | name="password-storage-scheme" |
| | | plural-name="password-storage-schemes" |
| | | package="org.opends.server.admin.std" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap" |
| | | > |
| | | |
| | | <adm:synopsis> |
| | | <adm:user-friendly-name /> |
| | | defines a module that implements a password storage scheme. |
| | | </adm:synopsis> |
| | | |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.35</ldap:oid> |
| | | <ldap:name>ds-cfg-password-storage-scheme</ldap:name> |
| | | <ldap:superior>top</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | |
| | | <adm:property name="enabled" mandatory="true"> |
| | | <adm:synopsis> |
| | | Indicate whether the |
| | | <adm:user-friendly-name /> |
| | | is enabled for use. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.76</ldap:oid> |
| | | <ldap:name>ds-cfg-password-storage-scheme-enabled</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="scheme-class" mandatory="true"> |
| | | <adm:synopsis> |
| | | The fully-qualified name of the Java class that provides the |
| | | <adm:user-friendly-name /> |
| | | implementation. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:java-class> |
| | | <adm:instance-of> |
| | | org.opends.server.api.PasswordStorageScheme |
| | | </adm:instance-of> |
| | | </adm:java-class> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.75</ldap:oid> |
| | | <ldap:name>ds-cfg-password-storage-scheme-class</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | </adm:managed-object> |
| | |
| | | </ldap:rdn-sequence> |
| | | </adm:profile> |
| | | </adm:relation> |
| | | <adm:relation name="entry-cache"> |
| | | <adm:one-to-one /> |
| | | <adm:profile name="ldap"> |
| | | <ldap:rdn-sequence> |
| | | cn=Entry Cache,cn=config |
| | | </ldap:rdn-sequence> |
| | | </adm:profile> |
| | | </adm:relation> |
| | | <adm:relation name="account-status-notification-handler"> |
| | | <adm:one-to-many /> |
| | | <adm:profile name="ldap"> |
| | | <ldap:rdn-sequence> |
| | | cn=Account Status Notification Handlers,cn=config |
| | | </ldap:rdn-sequence> |
| | | </adm:profile> |
| | | </adm:relation> |
| | | <adm:relation name="password-storage-scheme"> |
| | | <adm:one-to-many /> |
| | | <adm:profile name="ldap"> |
| | | <ldap:rdn-sequence> |
| | | cn=Password Storage Schemes,cn=config |
| | | </ldap:rdn-sequence> |
| | | </adm:profile> |
| | | </adm:relation> |
| | | <adm:relation name="backend"> |
| | | <adm:one-to-many /> |
| | | <adm:profile name="ldap"> |
| New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <adm:managed-object |
| | | name="soft-reference-entry-cache" |
| | | plural-name="soft-reference-entry-caches" |
| | | package="org.opends.server.admin.std" |
| | | extends="entry-cache" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap" |
| | | > |
| | | |
| | | <adm:synopsis> |
| | | <adm:user-friendly-name /> |
| | | defines a Directory Server entry cache that uses soft references |
| | | to manage objects in a way that will allow them to be freed if the JVM is |
| | | running low on memory. |
| | | </adm:synopsis> |
| | | |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.17</ldap:oid> |
| | | <ldap:name>ds-cfg-soft-reference-entry-cache</ldap:name> |
| | | <ldap:superior>ds-cfg-entry-cache</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | |
| | | <adm:property name="lock-timeout" mandatory="false"> |
| | | <adm:synopsis> |
| | | The length of time in milliseconds to wait while |
| | | attempting to acquire a read or write lock. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>3000ms</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:duration base-unit="ms" lower-limit="0" allow-unlimited="true"/> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.58</ldap:oid> |
| | | <ldap:name>ds-cfg-lock-timeout</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property-reference name="include-filter" /> |
| | | <adm:property-reference name="exclude-filter" /> |
| | | |
| | | </adm:managed-object> |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.admin.std.server. |
| | | AccountStatusNotificationHandlerCfg; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.types.AccountStatusNotification; |
| | | import org.opends.server.types.AccountStatusNotificationType; |
| | |
| | | * the status of a user account. The account status notification |
| | | * handler may be used to notify the user and/or administrators of the |
| | | * change. |
| | | * |
| | | * @param <T> The type of configuration handled by this notification |
| | | * handler. |
| | | */ |
| | | public abstract class AccountStatusNotificationHandler |
| | | public abstract class |
| | | AccountStatusNotificationHandler |
| | | <T extends AccountStatusNotificationHandlerCfg> |
| | | { |
| | | /** |
| | | * Initializes this account status notification handler based on the |
| | | * information in the provided configuration entry. |
| | | * |
| | | * @param configEntry The configuration entry that contains the |
| | | * information to use to initialize this |
| | | * account status notification handler. |
| | | * @param configuration The configuration entry that contains the |
| | | * information to use to initialize this |
| | | * account status notification handler. |
| | | * |
| | | * @throws ConfigException If the provided entry does not contain |
| | | * a valid configuration for this account |
| | |
| | | * configuration. |
| | | */ |
| | | public abstract void initializeStatusNotificationHandler( |
| | | ConfigEntry configEntry) |
| | | T configuration) |
| | | throws ConfigException, InitializationException; |
| | | |
| | | |
| | |
| | | import java.util.List; |
| | | import java.util.concurrent.locks.Lock; |
| | | |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.LockType; |
| | | import org.opends.server.admin.std.server.EntryCacheCfg; |
| | | |
| | | |
| | | |
| | |
| | | * the behavior of the default cache that will be used if none |
| | | * is configured).</LI> |
| | | * </UL> |
| | | * |
| | | * @param <T> The type of configuration handled by this entry |
| | | * cache. |
| | | */ |
| | | public abstract class EntryCache |
| | | <T extends EntryCacheCfg> |
| | | { |
| | | /** |
| | | * Initializes this entry cache implementation so that it will be |
| | | * available for storing and retrieving entries. |
| | | * |
| | | * @param configEntry The configuration entry containing the |
| | | * settings to use for this entry cache. |
| | | * @param configuration The configuration to use to initialize |
| | | * the entry cache. |
| | | * |
| | | * @throws ConfigException If there is a problem with the provided |
| | | * configuration entry that would prevent |
| | |
| | | * not related to the |
| | | * configuration. |
| | | */ |
| | | public abstract void initializeEntryCache(ConfigEntry configEntry) |
| | | public abstract void initializeEntryCache(T configuration) |
| | | throws ConfigException, InitializationException; |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.DirectoryException; |
| | |
| | | * implemented by a Directory Server module that implements a password |
| | | * storage scheme. Each subclass may only implement a single password |
| | | * storage scheme type. |
| | | * |
| | | * @param <T> The type of configuration handled by this |
| | | * password storage scheme |
| | | */ |
| | | public abstract class PasswordStorageScheme |
| | | public abstract class |
| | | PasswordStorageScheme <T extends PasswordStorageSchemeCfg> |
| | | { |
| | | /** |
| | | * Initializes this password storage scheme handler based on the |
| | |
| | | * register itself with the Directory Server for the particular |
| | | * storage scheme that it will manage. |
| | | * |
| | | * @param configEntry The configuration entry that contains the |
| | | * information to use to initialize this |
| | | * password storage scheme handler. |
| | | * @param configuration The configuration entry that contains the |
| | | * information to use to initialize this |
| | | * password storage scheme handler. |
| | | * |
| | | * @throws ConfigException If an unrecoverable problem arises in |
| | | * the process of performing the |
| | |
| | | * configuration. |
| | | */ |
| | | public abstract void initializePasswordStorageScheme( |
| | | ConfigEntry configEntry) |
| | | T configuration) |
| | | throws ConfigException, InitializationException; |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | import static org.opends.server.messages.ConfigMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.getMessage; |
| | | import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.util.ArrayList; |
| | | import java.util.Iterator; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | import org.opends.server.admin.ClassPropertyDefinition; |
| | | import org.opends.server.admin.server.ConfigurationAddListener; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.server.ConfigurationDeleteListener; |
| | | import org.opends.server.admin.server.ServerManagementContext; |
| | | import org.opends.server.admin.std.meta.AccountStatusNotificationHandlerCfgDefn; |
| | | import org.opends.server.admin.std.server.AccountStatusNotificationHandlerCfg; |
| | | import org.opends.server.admin.std.server.RootCfg; |
| | | import org.opends.server.api.AccountStatusNotificationHandler; |
| | | import org.opends.server.api.ConfigAddListener; |
| | | import org.opends.server.api.ConfigChangeListener; |
| | | import org.opends.server.api.ConfigDeleteListener; |
| | | import org.opends.server.api.ConfigHandler; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.config.BooleanConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.ErrorLogCategory; |
| | | import org.opends.server.types.ErrorLogSeverity; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import static org.opends.server.loggers.Error.*; |
| | | import static org.opends.server.messages.ConfigMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | * server is running. |
| | | */ |
| | | public class AccountStatusNotificationHandlerConfigManager |
| | | implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener |
| | | implements |
| | | ConfigurationChangeListener <AccountStatusNotificationHandlerCfg>, |
| | | ConfigurationAddListener <AccountStatusNotificationHandlerCfg>, |
| | | ConfigurationDeleteListener <AccountStatusNotificationHandlerCfg> |
| | | { |
| | | |
| | | |
| | | |
| | | // A mapping between the DNs of the config entries and the associated |
| | | // notification handlers. |
| | | private ConcurrentHashMap<DN,AccountStatusNotificationHandler> |
| | | notificationHandlers; |
| | | |
| | | // The configuration handler for the Directory Server. |
| | | private ConfigHandler configHandler; |
| | | |
| | | notificationHandlers; |
| | | |
| | | |
| | | /** |
| | |
| | | */ |
| | | public AccountStatusNotificationHandlerConfigManager() |
| | | { |
| | | configHandler = DirectoryServer.getConfigHandler(); |
| | | notificationHandlers = |
| | | new ConcurrentHashMap<DN,AccountStatusNotificationHandler>(); |
| | | } |
| | |
| | | public void initializeNotificationHandlers() |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // First, get the configuration base entry. |
| | | ConfigEntry baseEntry; |
| | | try |
| | | // Get the root configuration object. |
| | | ServerManagementContext managementContext = |
| | | ServerManagementContext.getInstance(); |
| | | RootCfg rootConfiguration = |
| | | managementContext.getRootConfiguration(); |
| | | |
| | | // Register as an add and delete listener with the root configuration so |
| | | // we can be notified if any account status notification handler entry |
| | | // is added or removed. |
| | | rootConfiguration.addAccountStatusNotificationHandlerAddListener (this); |
| | | rootConfiguration.addAccountStatusNotificationHandlerDeleteListener (this); |
| | | |
| | | // Initialize existing account status notification handlers. |
| | | for (String handlerName: |
| | | rootConfiguration.listAccountStatusNotificationHandlers()) |
| | | { |
| | | DN handlerBase = DN.decode(DN_ACCT_NOTIFICATION_HANDLER_CONFIG_BASE); |
| | | baseEntry = configHandler.getConfigEntry(handlerBase); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | // Get the account status notification handler's configuration. |
| | | AccountStatusNotificationHandlerCfg config = |
| | | rootConfiguration.getAccountStatusNotificationHandler (handlerName); |
| | | |
| | | // Register as a change listener for this notification handler |
| | | // entry so that we will be notified of any changes that may be |
| | | // made to it. |
| | | config.addChangeListener (this); |
| | | |
| | | // Ignore this notification handler if it is disabled. |
| | | if (config.isEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | // Load the notification handler implementation class. |
| | | String className = config.getNotificationHandlerClass(); |
| | | loadAndInstallNotificationHandler (className, config); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_CANNOT_GET_BASE; |
| | | String message = getMessage(msgID, String.valueOf(e)); |
| | | throw new ConfigException(msgID, message, e); |
| | | } |
| | | } |
| | | |
| | | if (baseEntry == null) |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | AccountStatusNotificationHandlerCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // returned status -- all is fine by default |
| | | boolean status = true; |
| | | |
| | | if (configuration.isEnabled()) |
| | | { |
| | | // The notification handler base entry does not exist. This is not |
| | | // acceptable, so throw an exception. |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_BASE_DOES_NOT_EXIST; |
| | | String message = getMessage(msgID); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | |
| | | // Register add and delete listeners with the notification handler base |
| | | // entry. We don't care about modifications to it. |
| | | baseEntry.registerAddListener(this); |
| | | baseEntry.registerDeleteListener(this); |
| | | |
| | | |
| | | // See if the base entry has any children. If not, then we don't need to do |
| | | // anything else. |
| | | if (! baseEntry.hasChildren()) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | |
| | | // Iterate through the child entries and process them as account status |
| | | // notification handler configuration entries. |
| | | for (ConfigEntry childEntry : baseEntry.getChildren().values()) |
| | | { |
| | | childEntry.registerChangeListener(this); |
| | | |
| | | StringBuilder unacceptableReason = new StringBuilder(); |
| | | if (! configAddIsAcceptable(childEntry, unacceptableReason)) |
| | | { |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_ACCTNOTHANDLER_ENTRY_UNACCEPTABLE, |
| | | childEntry.getDN().toString(), unacceptableReason.toString()); |
| | | continue; |
| | | } |
| | | |
| | | // Get the name of the class and make sure we can instantiate it as an |
| | | // entry cache. |
| | | String className = configuration.getNotificationHandlerClass(); |
| | | try |
| | | { |
| | | ConfigChangeResult result = applyConfigurationAdd(childEntry); |
| | | if (result.getResultCode() != ResultCode.SUCCESS) |
| | | { |
| | | StringBuilder buffer = new StringBuilder(); |
| | | |
| | | List<String> resultMessages = result.getMessages(); |
| | | if ((resultMessages == null) || (resultMessages.isEmpty())) |
| | | { |
| | | buffer.append(getMessage(MSGID_CONFIG_UNKNOWN_UNACCEPTABLE_REASON)); |
| | | } |
| | | else |
| | | { |
| | | Iterator<String> iterator = resultMessages.iterator(); |
| | | |
| | | buffer.append(iterator.next()); |
| | | while (iterator.hasNext()) |
| | | { |
| | | buffer.append(EOL); |
| | | buffer.append(iterator.next()); |
| | | } |
| | | } |
| | | |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_ACCTNOTHANDLER_CANNOT_CREATE_HANDLER, |
| | | childEntry.getDN().toString(), buffer.toString()); |
| | | } |
| | | // Load the class but don't initialize it. |
| | | loadNotificationHandler(className, null); |
| | | } |
| | | catch (Exception e) |
| | | catch (InitializationException ie) |
| | | { |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_ACCTNOTHANDLER_CANNOT_CREATE_HANDLER, |
| | | childEntry.getDN().toString(), String.valueOf(e)); |
| | | unacceptableReasons.add(ie.getMessage()); |
| | | status = false; |
| | | } |
| | | } |
| | | |
| | | return status; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the configuration entry that will result from a proposed |
| | | * modification is acceptable to this change listener. |
| | | * |
| | | * @param configEntry The configuration entry that will result from |
| | | * the requested update. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed change is not acceptable. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry contains an acceptable |
| | | * configuration, or <CODE>false</CODE> if it does not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configChangeIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | AccountStatusNotificationHandlerCfg configuration |
| | | ) |
| | | { |
| | | // Make sure that the entry has an appropriate objectclass for an account |
| | | // status notification handler. |
| | | if (! configEntry.hasObjectClass(OC_ACCT_NOTIFICATION_HANDLER)) |
| | | // Returned result. |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | ResultCode.SUCCESS, false, new ArrayList<String>() |
| | | ); |
| | | |
| | | // Get the configuration entry DN and the associated handler class. |
| | | DN configEntryDN = configuration.dn(); |
| | | AccountStatusNotificationHandler handler = notificationHandlers.get( |
| | | configEntryDN |
| | | ); |
| | | |
| | | // If the new configuration has the notification handler disabled, |
| | | // then remove it from the mapping list and clean it. |
| | | if (! configuration.isEnabled()) |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_OBJECTCLASS; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // Make sure that the entry specifies the notification handler class name. |
| | | StringConfigAttribute classNameAttr; |
| | | try |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_CLASS_NAME; |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_CLASS, |
| | | getMessage(msgID), true, false, true); |
| | | classNameAttr = (StringConfigAttribute) |
| | | configEntry.getConfigAttribute(classStub); |
| | | |
| | | if (classNameAttr == null) |
| | | if (handler != null) |
| | | { |
| | | msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | uninstallNotificationHandler (configEntryDN); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | return changeResult; |
| | | } |
| | | |
| | | Class handlerClass; |
| | | try |
| | | { |
| | | handlerClass = DirectoryServer.loadClass(classNameAttr.pendingValue()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | try |
| | | { |
| | | AccountStatusNotificationHandler handler = |
| | | (AccountStatusNotificationHandler) handlerClass.newInstance(); |
| | | } |
| | | catch(Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS; |
| | | String message = getMessage(msgID, handlerClass.getName(), |
| | | String.valueOf(configEntry.getDN()), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // See if this account status notification handler should be enabled. |
| | | BooleanConfigAttribute enabledAttr; |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_ENABLED, |
| | | getMessage(MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_ENABLED), |
| | | false); |
| | | enabledAttr = (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | |
| | | if (enabledAttr == null) |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_ENABLED_ATTR; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_ENABLED_VALUE; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // If we've gotten here then the notification handler entry appears to be |
| | | // acceptable. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration to this Directory Server component |
| | | * based on the provided changed entry. |
| | | * |
| | | * @param configEntry The configuration entry that containing the updated |
| | | * configuration for this component. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry) |
| | | { |
| | | DN configEntryDN = configEntry.getDN(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | |
| | | // Make sure that the entry has an appropriate objectclass for an account |
| | | // status notification handler. |
| | | if (! configEntry.hasObjectClass(OC_ACCT_NOTIFICATION_HANDLER)) |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_OBJECTCLASS; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // Get the corresponding notification handler if it is active. |
| | | AccountStatusNotificationHandler handler = |
| | | notificationHandlers.get(configEntryDN); |
| | | |
| | | |
| | | // See if this handler should be enabled or disabled. |
| | | boolean needsEnabled = false; |
| | | BooleanConfigAttribute enabledAttr; |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_ENABLED, |
| | | getMessage(MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_ENABLED), |
| | | false); |
| | | enabledAttr = (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | |
| | | if (enabledAttr == null) |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_ENABLED_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | if (enabledAttr.activeValue()) |
| | | { |
| | | if (handler == null) |
| | | { |
| | | needsEnabled = true; |
| | | } |
| | | else |
| | | { |
| | | // The handler is already active, so no action is required. |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (handler == null) |
| | | { |
| | | // The handler is already disabled, so no action is required and we |
| | | // can short-circuit out of this processing. |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else |
| | | { |
| | | // The handler is active, so it needs to be disabled. Do this and |
| | | // return that we were successful. |
| | | notificationHandlers.remove(configEntryDN); |
| | | handler.finalizeStatusNotificationHandler(); |
| | | |
| | | DirectoryServer.deregisterAccountStatusNotificationHandler( |
| | | configEntryDN); |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_ENABLED_VALUE; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // Make sure that the entry specifies the notification handler class name. |
| | | // If it has changed, then we will not try to dynamically apply it. |
| | | String className; |
| | | try |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_CLASS_NAME; |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_CLASS, |
| | | getMessage(msgID), true, false, true); |
| | | StringConfigAttribute classNameAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(classStub); |
| | | |
| | | if (classNameAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_CLASS_NAME; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | className = classNameAttr.pendingValue(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | boolean classChanged = false; |
| | | String oldClassName = null; |
| | | // At this point, new configuration is enabled... |
| | | // If the current notification handler is already enabled then we |
| | | // don't do anything unless the class has changed in which case we |
| | | // should indicate that administrative action is required. |
| | | String newClassName = configuration.getNotificationHandlerClass(); |
| | | if (handler != null) |
| | | { |
| | | oldClassName = handler.getClass().getName(); |
| | | classChanged = (! className.equals(oldClassName)); |
| | | String curClassName = handler.getClass().getName(); |
| | | boolean classIsNew = (! newClassName.equals (curClassName)); |
| | | if (classIsNew) |
| | | { |
| | | changeResult.setAdminActionRequired (true); |
| | | } |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | if (classChanged) |
| | | // New entry cache is enabled and there were no previous one. |
| | | // Instantiate the new class and initalize it. |
| | | try |
| | | { |
| | | // This will not be applied dynamically. Add a message to the response |
| | | // and indicate that admin action is required. |
| | | adminActionRequired = true; |
| | | messages.add(getMessage(MSGID_CONFIG_ACCTNOTHANDLER_CLASS_ACTION_REQUIRED, |
| | | String.valueOf(oldClassName), |
| | | String.valueOf(className), |
| | | String.valueOf(configEntryDN))); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | loadAndInstallNotificationHandler (newClassName, configuration); |
| | | } |
| | | |
| | | |
| | | if (needsEnabled) |
| | | catch (InitializationException ie) |
| | | { |
| | | try |
| | | { |
| | | Class handlerClass = DirectoryServer.loadClass(className); |
| | | handler = (AccountStatusNotificationHandler) handlerClass.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS; |
| | | messages.add(getMessage(msgID, className, |
| | | String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | try |
| | | { |
| | | handler.initializeStatusNotificationHandler(configEntry); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INITIALIZATION_FAILED; |
| | | messages.add(getMessage(msgID, className, |
| | | String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | |
| | | notificationHandlers.put(configEntryDN, handler); |
| | | DirectoryServer.registerAccountStatusNotificationHandler(configEntryDN, |
| | | handler); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | changeResult.addMessage (ie.getMessage()); |
| | | changeResult.setResultCode (DirectoryServer.getServerErrorResultCode()); |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then there haven't been any changes to anything |
| | | // that we care about. |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the configuration entry that will result from a proposed |
| | | * add is acceptable to this add listener. |
| | | * |
| | | * @param configEntry The configuration entry that will result from |
| | | * the requested add. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed entry is not acceptable. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry contains an acceptable |
| | | * configuration, or <CODE>false</CODE> if it does not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configAddIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | public boolean isConfigurationAddAcceptable( |
| | | AccountStatusNotificationHandlerCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // returned status -- all is fine by default |
| | | boolean status = true; |
| | | |
| | | // Make sure that no entry already exists with the specified DN. |
| | | DN configEntryDN = configEntry.getDN(); |
| | | DN configEntryDN = configuration.dn(); |
| | | if (notificationHandlers.containsKey(configEntryDN)) |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_EXISTS; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | unacceptableReasons.add (message); |
| | | status = false; |
| | | } |
| | | |
| | | |
| | | // Make sure that the entry has an appropriate objectclass for an account |
| | | // status notification handler. |
| | | if (! configEntry.hasObjectClass(OC_ACCT_NOTIFICATION_HANDLER)) |
| | | // If configuration is enabled then check that notification class |
| | | // can be instantiated. |
| | | else if (configuration.isEnabled()) |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_OBJECTCLASS; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // Make sure that the entry specifies the handler class. |
| | | StringConfigAttribute classNameAttr; |
| | | try |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_CLASS_NAME; |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_CLASS, |
| | | getMessage(msgID), true, false, true); |
| | | classNameAttr = (StringConfigAttribute) |
| | | configEntry.getConfigAttribute(classStub); |
| | | |
| | | if (classNameAttr == null) |
| | | // Get the name of the class and make sure we can instantiate it as |
| | | // an entry cache. |
| | | String className = configuration.getNotificationHandlerClass(); |
| | | try |
| | | { |
| | | msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | // Load the class but don't initialize it. |
| | | loadNotificationHandler (className, null); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | catch (InitializationException ie) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | Class handlerClass; |
| | | try |
| | | { |
| | | handlerClass = DirectoryServer.loadClass(classNameAttr.pendingValue()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | AccountStatusNotificationHandler handler; |
| | | try |
| | | { |
| | | handler = (AccountStatusNotificationHandler) handlerClass.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS; |
| | | String message = getMessage(msgID, handlerClass.getName(), |
| | | String.valueOf(configEntryDN), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // If the notofication handler is a configurable component, then make sure |
| | | // that its configuration is valid. |
| | | if (handler instanceof ConfigurableComponent) |
| | | { |
| | | ConfigurableComponent cc = (ConfigurableComponent) handler; |
| | | LinkedList<String> errorMessages = new LinkedList<String>(); |
| | | if (! cc.hasAcceptableConfiguration(configEntry, errorMessages)) |
| | | { |
| | | if (errorMessages.isEmpty()) |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_UNACCEPTABLE_CONFIG; |
| | | unacceptableReason.append(getMessage(msgID, |
| | | String.valueOf(configEntryDN))); |
| | | } |
| | | else |
| | | { |
| | | Iterator<String> iterator = errorMessages.iterator(); |
| | | unacceptableReason.append(iterator.next()); |
| | | while (iterator.hasNext()) |
| | | { |
| | | unacceptableReason.append(" "); |
| | | unacceptableReason.append(iterator.next()); |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | unacceptableReasons.add (ie.getMessage()); |
| | | status = false; |
| | | } |
| | | } |
| | | |
| | | |
| | | // See if this notification handler should be enabled. |
| | | BooleanConfigAttribute enabledAttr; |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_ENABLED, |
| | | getMessage(MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_ENABLED), |
| | | false); |
| | | enabledAttr = (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | |
| | | if (enabledAttr == null) |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_ENABLED_ATTR; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_ENABLED_VALUE; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // If we've gotten here then the notification handler entry appears to be |
| | | // acceptable. |
| | | return true; |
| | | return status; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration based on the provided added entry. |
| | | * |
| | | * @param configEntry The new configuration entry that contains the |
| | | * configuration to apply. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry) |
| | | public ConfigChangeResult applyConfigurationAdd( |
| | | AccountStatusNotificationHandlerCfg configuration |
| | | ) |
| | | { |
| | | DN configEntryDN = configEntry.getDN(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | // Returned result. |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | ResultCode.SUCCESS, false, new ArrayList<String>() |
| | | ); |
| | | |
| | | // Register a change listener with it so we can be notified of changes |
| | | // to it over time. |
| | | configuration.addChangeListener(this); |
| | | |
| | | // Make sure that the entry has an appropriate objectclass for an account |
| | | // status notification handler. |
| | | if (! configEntry.hasObjectClass(OC_ACCT_NOTIFICATION_HANDLER)) |
| | | if (configuration.isEnabled()) |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_OBJECTCLASS; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // See if this notification handler should be enabled or disabled. |
| | | BooleanConfigAttribute enabledAttr; |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_ENABLED, |
| | | getMessage(MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_ENABLED), |
| | | false); |
| | | enabledAttr = (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | |
| | | if (enabledAttr == null) |
| | | // Instantiate the class as an entry cache and initialize it. |
| | | String className = configuration.getNotificationHandlerClass(); |
| | | try |
| | | { |
| | | // The attribute doesn't exist, so it will be disabled by default. |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_ENABLED_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.SUCCESS; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | loadAndInstallNotificationHandler (className, configuration); |
| | | } |
| | | else if (! enabledAttr.activeValue()) |
| | | catch (InitializationException ie) |
| | | { |
| | | // It is explicitly configured as disabled, so we don't need to do |
| | | // anything. |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | changeResult.addMessage (ie.getMessage()); |
| | | changeResult.setResultCode (DirectoryServer.getServerErrorResultCode()); |
| | | return changeResult; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_ENABLED_VALUE; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // Make sure that the entry specifies the handler class name. |
| | | String className; |
| | | try |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_DESCRIPTION_CLASS_NAME; |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_ACCT_NOTIFICATION_HANDLER_CLASS, |
| | | getMessage(msgID), true, false, true); |
| | | StringConfigAttribute classNameAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(classStub); |
| | | |
| | | if (classNameAttr == null) |
| | | { |
| | | msgID = MSGID_CONFIG_ACCTNOTHANDLER_NO_CLASS_NAME; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | className = classNameAttr.pendingValue(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS_NAME; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // Load and initialize the notificationhandler class, and register it with |
| | | // the Directory Server. |
| | | AccountStatusNotificationHandler handler; |
| | | try |
| | | { |
| | | Class handlerClass = DirectoryServer.loadClass(className); |
| | | handler = (AccountStatusNotificationHandler) handlerClass.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INVALID_CLASS; |
| | | messages.add(getMessage(msgID, className, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | try |
| | | { |
| | | handler.initializeStatusNotificationHandler(configEntry); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INITIALIZATION_FAILED; |
| | | messages.add(getMessage(msgID, className, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | notificationHandlers.put(configEntryDN, handler); |
| | | DirectoryServer.registerAccountStatusNotificationHandler(configEntryDN, |
| | | handler); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether it is acceptable to remove the provided configuration |
| | | * entry. |
| | | * |
| | | * @param configEntry The configuration entry that will be removed |
| | | * from the configuration. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed delete is not acceptable. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry may be removed from the |
| | | * configuration, or <CODE>false</CODE> if not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configDeleteIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | public boolean isConfigurationDeleteAcceptable( |
| | | AccountStatusNotificationHandlerCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // A delete should always be acceptable, so just return true. |
| | | return true; |
| | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration based on the provided deleted entry. |
| | | * |
| | | * @param configEntry The new configuration entry that has been deleted. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry) |
| | | public ConfigChangeResult applyConfigurationDelete( |
| | | AccountStatusNotificationHandlerCfg configuration |
| | | ) |
| | | { |
| | | DN configEntryDN = configEntry.getDN(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | // Returned result. |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | ResultCode.SUCCESS, false, new ArrayList<String>() |
| | | ); |
| | | |
| | | uninstallNotificationHandler (configuration.dn()); |
| | | |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | // See if the entry is registered as an account status notification handler. |
| | | // If so, deregister it and stop the handler. |
| | | /** |
| | | * Loads the specified class, instantiates it as a notification handler, |
| | | * and optionally initializes that instance. Any initialized notification |
| | | * handler is registered in the server. |
| | | * |
| | | * @param className The fully-qualified name of the notification handler |
| | | * class to load, instantiate, and initialize. |
| | | * @param configuration The configuration to use to initialize the |
| | | * notification handler, or {@code null} if the |
| | | * notification handler should not be initialized. |
| | | * |
| | | * @throws InitializationException If a problem occurred while attempting |
| | | * to initialize the notification handler. |
| | | */ |
| | | private void loadAndInstallNotificationHandler( |
| | | String className, |
| | | AccountStatusNotificationHandlerCfg configuration |
| | | ) |
| | | throws InitializationException |
| | | { |
| | | // Load the notification handler class... |
| | | AccountStatusNotificationHandler |
| | | <? extends AccountStatusNotificationHandlerCfg> handlerClass; |
| | | handlerClass = loadNotificationHandler (className, configuration); |
| | | |
| | | // ... and install the entry cache in the server. |
| | | DN configEntryDN = configuration.dn(); |
| | | notificationHandlers.put (configEntryDN, handlerClass); |
| | | DirectoryServer.registerAccountStatusNotificationHandler( |
| | | configEntryDN, |
| | | handlerClass |
| | | ); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Loads the specified class, instantiates it as a notification handler, |
| | | * and optionally initializes that instance. |
| | | * |
| | | * @param className The fully-qualified name of the notification handler |
| | | * class to load, instantiate, and initialize. |
| | | * @param configuration The configuration to use to initialize the |
| | | * notification handler, or {@code null} if the |
| | | * notification handler should not be initialized. |
| | | * |
| | | * @return The possibly initialized notification handler. |
| | | * |
| | | * @throws InitializationException If a problem occurred while attempting |
| | | * to initialize the notification handler. |
| | | */ |
| | | private |
| | | AccountStatusNotificationHandler |
| | | <? extends AccountStatusNotificationHandlerCfg> |
| | | loadNotificationHandler( |
| | | String className, |
| | | AccountStatusNotificationHandlerCfg configuration |
| | | ) |
| | | throws InitializationException |
| | | { |
| | | try |
| | | { |
| | | AccountStatusNotificationHandlerCfgDefn definition; |
| | | ClassPropertyDefinition propertyDefinition; |
| | | Class<? extends AccountStatusNotificationHandler> handlerClass; |
| | | AccountStatusNotificationHandler |
| | | <? extends AccountStatusNotificationHandlerCfg> notificationHandler; |
| | | |
| | | definition = AccountStatusNotificationHandlerCfgDefn.getInstance(); |
| | | propertyDefinition = |
| | | definition.getNotificationHandlerClassPropertyDefinition(); |
| | | handlerClass = propertyDefinition.loadClass( |
| | | className, |
| | | AccountStatusNotificationHandler.class |
| | | ); |
| | | notificationHandler = |
| | | (AccountStatusNotificationHandler |
| | | <? extends AccountStatusNotificationHandlerCfg>) |
| | | handlerClass.newInstance(); |
| | | |
| | | if (configuration != null) |
| | | { |
| | | Method method = notificationHandler.getClass().getMethod( |
| | | "initializeStatusNotificationHandler", |
| | | configuration.definition().getServerConfigurationClass() |
| | | ); |
| | | method.invoke(notificationHandler, configuration); |
| | | } |
| | | |
| | | return notificationHandler; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | int msgID = MSGID_CONFIG_ACCTNOTHANDLER_INITIALIZATION_FAILED; |
| | | String message = getMessage( |
| | | msgID, className, |
| | | String.valueOf(configuration.dn()), |
| | | stackTraceToSingleLineString(e) |
| | | ); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Remove a notification handler that has been installed in the server. |
| | | * |
| | | * @param configEntryDN the DN of the configuration enry associated to |
| | | * the notification handler to remove |
| | | */ |
| | | private void uninstallNotificationHandler( |
| | | DN configEntryDN |
| | | ) |
| | | { |
| | | AccountStatusNotificationHandler handler = |
| | | notificationHandlers.remove(configEntryDN); |
| | | notificationHandlers.remove (configEntryDN); |
| | | if (handler != null) |
| | | { |
| | | DirectoryServer.deregisterAccountStatusNotificationHandler(configEntryDN); |
| | | |
| | | DirectoryServer.deregisterAccountStatusNotificationHandler ( |
| | | configEntryDN |
| | | ); |
| | | handler.finalizeStatusNotificationHandler(); |
| | | } |
| | | |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.api.ConfigAddListener; |
| | | import org.opends.server.api.ConfigChangeListener; |
| | | import org.opends.server.api.ConfigDeleteListener; |
| | | import org.opends.server.api.EntryCache; |
| | | import org.opends.server.config.BooleanConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | | import org.opends.server.extensions.DefaultEntryCache; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.ErrorLogCategory; |
| | | import org.opends.server.types.ErrorLogSeverity; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.config.ConfigException; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.types.DebugLogLevel; |
| | |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | import org.opends.server.admin.ClassPropertyDefinition; |
| | | import org.opends.server.admin.server.ConfigurationAddListener; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.server.ConfigurationDeleteListener; |
| | | import org.opends.server.admin.server.ServerManagementContext; |
| | | import org.opends.server.admin.std.server.EntryCacheCfg; |
| | | import org.opends.server.admin.std.server.RootCfg; |
| | | import org.opends.server.admin.std.meta.EntryCacheCfgDefn; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class defines a utility that will be used to manage the configuration |
| | |
| | | * defined, but if it is absent or disabled, then a default cache will be used. |
| | | */ |
| | | public class EntryCacheConfigManager |
| | | implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener |
| | | implements |
| | | ConfigurationChangeListener <EntryCacheCfg>, |
| | | ConfigurationAddListener <EntryCacheCfg>, |
| | | ConfigurationDeleteListener <EntryCacheCfg> |
| | | { |
| | | // The current entry cache registered in the server |
| | | private EntryCache _entryCache = null; |
| | | |
| | | // The default entry cache to use when no entry cache has been configured |
| | | // or when the configured entry cache could not be initialized. |
| | | private EntryCache _defaultEntryCache = null; |
| | | |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Initializes the configuration associated with the Directory Server entry |
| | | * cache. This should only be called at Directory Server startup. If an |
| | | * error occurs, then a message will be logged and the default entry cache |
| | | * will be installed. |
| | | * |
| | | * @throws ConfigException If a configuration problem causes the entry |
| | | * cache initialization process to fail. |
| | | * |
| | | * @throws InitializationException If a problem occurs while trying to |
| | | * install the default entry cache. |
| | | */ |
| | | public void initializeEntryCache() |
| | | throws InitializationException |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // Get the root configuration object. |
| | | ServerManagementContext managementContext = |
| | | ServerManagementContext.getInstance(); |
| | | RootCfg rootConfiguration = |
| | | managementContext.getRootConfiguration(); |
| | | |
| | | // Register as an add and delete listener with the root configuration so we |
| | | // can be notified if any entry cache entry is added or removed. |
| | | // If entry cache configuration is using a one-to-zero-or-one relation |
| | | // then uncomment the lines below (see issue #1558). |
| | | /* |
| | | // rootConfiguration.addEntryCacheAddListener(this); |
| | | // rootConfiguration.addEntryCacheDeleteListener(this); |
| | | */ |
| | | |
| | | // First, install a default entry cache so that there will be one even if |
| | | // we encounter a problem later. |
| | | try |
| | |
| | | DefaultEntryCache defaultCache = new DefaultEntryCache(); |
| | | defaultCache.initializeEntryCache(null); |
| | | DirectoryServer.setEntryCache(defaultCache); |
| | | _defaultEntryCache = defaultCache; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | // If the entry cache configuration is not present then keep the |
| | | // default entry cache already installed. |
| | | // If entry cache configuration is using a one-to-zero-or-one relation |
| | | // then uncomment the lines below (see issue #1558). |
| | | /* |
| | | // if (!rootConfiguration.hasEntryCache()) |
| | | // { |
| | | // logError( |
| | | // ErrorLogCategory.CONFIGURATION, |
| | | // ErrorLogSeverity.SEVERE_WARNING, |
| | | // MSGID_CONFIG_ENTRYCACHE_NO_CONFIG_ENTRY |
| | | // ); |
| | | // return; |
| | | // } |
| | | */ |
| | | |
| | | // Get the entry cache configuration entry. If it is not present, then |
| | | // register an add listener and install the default cache. |
| | | DN configEntryDN; |
| | | ConfigEntry configEntry; |
| | | try |
| | | // Get the entry cache configuration. |
| | | EntryCacheCfg configuration = rootConfiguration.getEntryCache(); |
| | | |
| | | // At this point, we have a configuration entry. Register a change |
| | | // listener with it so we can be notified of changes to it over time. |
| | | configuration.addChangeListener(this); |
| | | |
| | | // Initialize the entry cache. |
| | | if (configuration.isEnabled()) |
| | | { |
| | | configEntryDN = DN.decode(DN_ENTRY_CACHE_CONFIG); |
| | | configEntry = DirectoryServer.getConfigEntry(configEntryDN); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_ENTRYCACHE_CANNOT_GET_CONFIG_ENTRY, |
| | | stackTraceToSingleLineString(e)); |
| | | return; |
| | | } |
| | | |
| | | if (configEntry == null) |
| | | { |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING, |
| | | MSGID_CONFIG_ENTRYCACHE_NO_CONFIG_ENTRY); |
| | | |
| | | // Load the entry cache implementation class and install the entry |
| | | // cache with the server. |
| | | String className = configuration.getEntryCacheClass(); |
| | | try |
| | | { |
| | | ConfigEntry parentEntry = DirectoryServer |
| | | .getConfigEntry(configEntryDN.getParentDNInSuffix()); |
| | | if (parentEntry != null) |
| | | { |
| | | parentEntry.registerAddListener(this); |
| | | } |
| | | loadAndInstallEntryCache (className, configuration); |
| | | } |
| | | catch (Exception e) |
| | | catch (InitializationException ie) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_ENTRYCACHE_CANNOT_REGISTER_ADD_LISTENER, |
| | | stackTraceToSingleLineString(e)); |
| | | logError( |
| | | ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | ie.getMessage(), |
| | | ie.getMessageID()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return; |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | EntryCacheCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // returned status -- all is fine by default |
| | | boolean status = true; |
| | | |
| | | if (configuration.isEnabled()) |
| | | { |
| | | // Get the name of the class and make sure we can instantiate it as an |
| | | // entry cache. |
| | | String className = configuration.getEntryCacheClass(); |
| | | try |
| | | { |
| | | // Load the class but don't initialize it. |
| | | loadEntryCache(className, null); |
| | | } |
| | | catch (InitializationException ie) |
| | | { |
| | | unacceptableReasons.add(ie.getMessage()); |
| | | status = false; |
| | | } |
| | | } |
| | | |
| | | return status; |
| | | } |
| | | |
| | | // At this point, we have a configuration entry. Register a change listener |
| | | // with it so we can be notified of changes to it over time. We will also |
| | | // want to register a delete listener with its parent to allow us to |
| | | // determine if the entry is deleted. |
| | | configEntry.registerChangeListener(this); |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | EntryCacheCfg configuration |
| | | ) |
| | | { |
| | | // Returned result. |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | ResultCode.SUCCESS, false, new ArrayList<String>() |
| | | ); |
| | | |
| | | // If the new configuration has the entry cache disabled, then install |
| | | // the default entry cache with the server. |
| | | if (! configuration.isEnabled()) |
| | | { |
| | | DirectoryServer.setEntryCache (_defaultEntryCache); |
| | | |
| | | // If an entry cache was installed then clean it. |
| | | if (_entryCache != null) |
| | | { |
| | | _entryCache.finalizeEntryCache(); |
| | | _entryCache = null; |
| | | } |
| | | return changeResult; |
| | | } |
| | | |
| | | // At this point, new configuration is enabled... |
| | | // If the current entry cache is already enabled then we don't do |
| | | // anything unless the class has changed in which case we should |
| | | // indicate that administrative action is required. |
| | | String newClassName = configuration.getEntryCacheClass(); |
| | | if (_entryCache !=null) |
| | | { |
| | | String curClassName = _entryCache.getClass().getName(); |
| | | boolean classIsNew = (! newClassName.equals (curClassName)); |
| | | if (classIsNew) |
| | | { |
| | | changeResult.setAdminActionRequired (true); |
| | | } |
| | | return changeResult; |
| | | } |
| | | |
| | | // New entry cache is enabled and there were no previous one. |
| | | // Instantiate the new class and initalize it. |
| | | try |
| | | { |
| | | DN parentDN = configEntryDN.getParentDNInSuffix(); |
| | | ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); |
| | | if (parentEntry != null) |
| | | loadAndInstallEntryCache (newClassName, configuration); |
| | | } |
| | | catch (InitializationException ie) |
| | | { |
| | | changeResult.addMessage (ie.getMessage()); |
| | | changeResult.setResultCode (DirectoryServer.getServerErrorResultCode()); |
| | | return changeResult; |
| | | } |
| | | |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationAddAcceptable( |
| | | EntryCacheCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // returned status -- all is fine by default |
| | | boolean status = true; |
| | | |
| | | if (configuration.isEnabled()) |
| | | { |
| | | // Get the name of the class and make sure we can instantiate it as |
| | | // an entry cache. |
| | | String className = configuration.getEntryCacheClass(); |
| | | try |
| | | { |
| | | parentEntry.registerDeleteListener(this); |
| | | // Load the class but don't initialize it. |
| | | loadEntryCache(className, null); |
| | | } |
| | | catch (InitializationException ie) |
| | | { |
| | | unacceptableReasons.add (ie.getMessage()); |
| | | status = false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | |
| | | return status; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd( |
| | | EntryCacheCfg configuration |
| | | ) |
| | | { |
| | | // Returned result. |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | ResultCode.SUCCESS, false, new ArrayList<String>() |
| | | ); |
| | | |
| | | // Register a change listener with it so we can be notified of changes |
| | | // to it over time. |
| | | configuration.addChangeListener(this); |
| | | |
| | | if (configuration.isEnabled()) |
| | | { |
| | | if (debugEnabled()) |
| | | // Instantiate the class as an entry cache and initialize it. |
| | | String className = configuration.getEntryCacheClass(); |
| | | try |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | loadAndInstallEntryCache (className, configuration); |
| | | } |
| | | |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_WARNING, |
| | | MSGID_CONFIG_ENTRYCACHE_CANNOT_REGISTER_DELETE_LISTENER, |
| | | stackTraceToSingleLineString(e)); |
| | | } |
| | | |
| | | |
| | | // See if the entry indicates whether the cache should be enabled. |
| | | int msgID = MSGID_CONFIG_ENTRYCACHE_DESCRIPTION_CACHE_ENABLED; |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_ENTRYCACHE_ENABLED, getMessage(msgID), |
| | | false); |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledAttr = |
| | | (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | if (enabledAttr == null) |
| | | catch (InitializationException ie) |
| | | { |
| | | // The attribute is not present, so the entry cache will be disabled. |
| | | // Log a warning message and return. |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, |
| | | MSGID_CONFIG_ENTRYCACHE_NO_ENABLED_ATTR); |
| | | return; |
| | | } |
| | | else if (! enabledAttr.activeValue()) |
| | | { |
| | | // The entry cache is explicitly disabled. Log a mild warning and |
| | | // return. |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.MILD_WARNING, |
| | | MSGID_CONFIG_ENTRYCACHE_DISABLED); |
| | | return; |
| | | changeResult.addMessage (ie.getMessage()); |
| | | changeResult.setResultCode (DirectoryServer.getServerErrorResultCode()); |
| | | return changeResult; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_ENTRYCACHE_UNABLE_TO_DETERMINE_ENABLED_STATE, |
| | | stackTraceToSingleLineString(e)); |
| | | return; |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationDeleteAcceptable( |
| | | EntryCacheCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // NYI |
| | | |
| | | // If we've gotten to this point, then it is acceptable as far as we are |
| | | // concerned. If it is unacceptable according to the configuration, then |
| | | // the entry cache itself will make that determination. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationDelete( |
| | | EntryCacheCfg configuration |
| | | ) |
| | | { |
| | | // Returned result. |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | ResultCode.SUCCESS, false, new ArrayList<String>() |
| | | ); |
| | | |
| | | // If the entry cache was installed then replace it with the |
| | | // default entry cache, and clean it. |
| | | if (_entryCache != null) |
| | | { |
| | | DirectoryServer.setEntryCache (_defaultEntryCache); |
| | | _entryCache.finalizeEntryCache(); |
| | | _entryCache = null; |
| | | } |
| | | |
| | | |
| | | // See if it specifies the class name for the entry cache implementation. |
| | | String className; |
| | | msgID = MSGID_CONFIG_ENTRYCACHE_DESCRIPTION_CACHE_CLASS; |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_ENTRYCACHE_CLASS, getMessage(msgID), |
| | | true, false, false); |
| | | try |
| | | { |
| | | StringConfigAttribute classAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(classStub); |
| | | if (classAttr == null) |
| | | { |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_ENTRYCACHE_NO_CLASS_ATTR); |
| | | return; |
| | | } |
| | | else |
| | | { |
| | | className = classAttr.activeValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_ENTRYCACHE_CANNOT_DETERMINE_CLASS, |
| | | stackTraceToSingleLineString(e)); |
| | | return; |
| | | } |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | // Try to load the class and instantiate it as an entry cache. |
| | | Class cacheClass; |
| | | try |
| | | { |
| | | cacheClass = DirectoryServer.loadClass(className); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | /** |
| | | * Loads the specified class, instantiates it as an entry cache, |
| | | * and optionally initializes that instance. Any initialize entry |
| | | * cache is registered in the server. |
| | | * |
| | | * @param className The fully-qualified name of the entry cache |
| | | * class to load, instantiate, and initialize. |
| | | * @param configuration The configuration to use to initialize the |
| | | * entry cache, or {@code null} if the |
| | | * entry cache should not be initialized. |
| | | * |
| | | * @throws InitializationException If a problem occurred while attempting |
| | | * to initialize the entry cache. |
| | | */ |
| | | private void loadAndInstallEntryCache( |
| | | String className, |
| | | EntryCacheCfg configuration |
| | | ) |
| | | throws InitializationException |
| | | { |
| | | // Load the entry cache class... |
| | | EntryCache entryCache = loadEntryCache (className, configuration); |
| | | |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_ENTRYCACHE_CANNOT_LOAD_CLASS, |
| | | String.valueOf(className), stackTraceToSingleLineString(e)); |
| | | return; |
| | | } |
| | | |
| | | EntryCache entryCache; |
| | | try |
| | | { |
| | | entryCache = (EntryCache) cacheClass.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_ENTRYCACHE_CANNOT_INSTANTIATE_CLASS, |
| | | String.valueOf(className), stackTraceToSingleLineString(e)); |
| | | return; |
| | | } |
| | | |
| | | |
| | | // Try to initialize the cache with the contents of the configuration entry. |
| | | try |
| | | { |
| | | entryCache.initializeEntryCache(configEntry); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_ENTRYCACHE_CANNOT_INITIALIZE_CACHE, |
| | | String.valueOf(className), stackTraceToSingleLineString(e)); |
| | | return; |
| | | } |
| | | |
| | | |
| | | // Install the new cache with the server. We don't need to do anything to |
| | | // get rid of the previous default cache since it doesn't consume any |
| | | // resources. |
| | | // ... and install the entry cache in the server. |
| | | DirectoryServer.setEntryCache(entryCache); |
| | | _entryCache = entryCache; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the configuration entry that will result from a proposed |
| | | * modification is acceptable to this change listener. |
| | | * Loads the specified class, instantiates it as an entry cache, |
| | | * and optionally initializes that instance. |
| | | * |
| | | * @param configEntry The configuration entry that will result from |
| | | * the requested update. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed change is not acceptable. |
| | | * @param className The fully-qualified name of the entry cache |
| | | * class to load, instantiate, and initialize. |
| | | * @param configuration The configuration to use to initialize the |
| | | * entry cache, or {@code null} if the |
| | | * entry cache should not be initialized. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry contains an acceptable |
| | | * configuration, or <CODE>false</CODE> if it does not. |
| | | * @return The possibly initialized entry cache. |
| | | * |
| | | * @throws InitializationException If a problem occurred while attempting |
| | | * to initialize the entry cache. |
| | | */ |
| | | public boolean configChangeIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | private EntryCache<? extends EntryCacheCfg> loadEntryCache( |
| | | String className, |
| | | EntryCacheCfg configuration |
| | | ) |
| | | throws InitializationException |
| | | { |
| | | // NYI |
| | | try |
| | | { |
| | | EntryCacheCfgDefn definition; |
| | | ClassPropertyDefinition propertyDefinition; |
| | | Class<? extends EntryCache> cacheClass; |
| | | EntryCache<? extends EntryCacheCfg> cache; |
| | | |
| | | definition = EntryCacheCfgDefn.getInstance(); |
| | | propertyDefinition = definition.getEntryCacheClassPropertyDefinition(); |
| | | cacheClass = propertyDefinition.loadClass(className, EntryCache.class); |
| | | cache = (EntryCache<? extends EntryCacheCfg>) cacheClass.newInstance(); |
| | | |
| | | // If we've gotten to this point, then it is acceptable as far as we are |
| | | // concerned. If it is unacceptable according to the configuration, then |
| | | // the entry cache itself will make that determination. |
| | | return true; |
| | | if (configuration != null) |
| | | { |
| | | Method method = cache.getClass().getMethod( |
| | | "initializeEntryCache", |
| | | configuration.definition().getServerConfigurationClass() |
| | | ); |
| | | method.invoke(cache, configuration); |
| | | } |
| | | |
| | | return cache; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | int msgID = MSGID_CONFIG_ENTRYCACHE_CANNOT_INITIALIZE_CACHE; |
| | | String message = getMessage( |
| | | msgID, className, |
| | | String.valueOf(configuration.dn()), |
| | | stackTraceToSingleLineString(e) |
| | | ); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration to this Directory Server component |
| | | * based on the provided changed entry. |
| | | * |
| | | * @param configEntry The configuration entry that containing the updated |
| | | * configuration for this component. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | |
| | | // NYI |
| | | |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the configuration entry that will result from a proposed |
| | | * add is acceptable to this add listener. |
| | | * |
| | | * @param configEntry The configuration entry that will result from |
| | | * the requested add. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed entry is not acceptable. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry contains an acceptable |
| | | * configuration, or <CODE>false</CODE> if it does not. |
| | | */ |
| | | public boolean configAddIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | { |
| | | // NYI |
| | | |
| | | |
| | | // If we've gotten to this point, then it is acceptable as far as we are |
| | | // concerned. If it is unacceptable according to the configuration, then |
| | | // the entry cache itself will make that determination. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration based on the provided added entry. |
| | | * |
| | | * @param configEntry The new configuration entry that contains the |
| | | * configuration to apply. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | |
| | | // NYI |
| | | |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether it is acceptable to remove the provided configuration |
| | | * entry. |
| | | * |
| | | * @param configEntry The configuration entry that will be removed |
| | | * from the configuration. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed delete is not acceptable. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry may be removed from the |
| | | * configuration, or <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean configDeleteIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | { |
| | | // NYI |
| | | |
| | | |
| | | // If we've gotten to this point, then it is acceptable as far as we are |
| | | // concerned. If it is unacceptable according to the configuration, then |
| | | // the entry cache itself will make that determination. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration based on the provided deleted entry. |
| | | * |
| | | * @param configEntry The new configuration entry that has been deleted. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | */ |
| | | public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | |
| | | // NYI |
| | | |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | import static org.opends.server.messages.ConfigMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.getMessage; |
| | | import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.util.ArrayList; |
| | | import java.util.Iterator; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | import org.opends.server.api.ConfigAddListener; |
| | | import org.opends.server.api.ConfigChangeListener; |
| | | import org.opends.server.api.ConfigDeleteListener; |
| | | import org.opends.server.api.ConfigHandler; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.admin.ClassPropertyDefinition; |
| | | import org.opends.server.admin.server.ConfigurationAddListener; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.server.ConfigurationDeleteListener; |
| | | import org.opends.server.admin.server.ServerManagementContext; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.admin.std.server.RootCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.config.BooleanConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.ErrorLogCategory; |
| | | import org.opends.server.types.ErrorLogSeverity; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import static org.opends.server.loggers.Error.*; |
| | | import static org.opends.server.messages.ConfigMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | * removals, or modifications to any schemes while the server is running. |
| | | */ |
| | | public class PasswordStorageSchemeConfigManager |
| | | implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener |
| | | implements |
| | | ConfigurationChangeListener <PasswordStorageSchemeCfg>, |
| | | ConfigurationAddListener <PasswordStorageSchemeCfg>, |
| | | ConfigurationDeleteListener <PasswordStorageSchemeCfg> |
| | | { |
| | | |
| | | |
| | | |
| | | // A mapping between the DNs of the config entries and the associated password |
| | | // storage schemes. |
| | | private ConcurrentHashMap<DN,PasswordStorageScheme> storageSchemes; |
| | | |
| | | // The configuration handler for the Directory Server. |
| | | private ConfigHandler configHandler; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this password storage scheme config manager. |
| | | */ |
| | | public PasswordStorageSchemeConfigManager() |
| | | { |
| | | configHandler = DirectoryServer.getConfigHandler(); |
| | | storageSchemes = new ConcurrentHashMap<DN,PasswordStorageScheme>(); |
| | | } |
| | | |
| | |
| | | public void initializePasswordStorageSchemes() |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // First, get the configuration base entry. |
| | | ConfigEntry baseEntry; |
| | | try |
| | | // Get the root configuration object. |
| | | ServerManagementContext managementContext = |
| | | ServerManagementContext.getInstance(); |
| | | RootCfg rootConfiguration = |
| | | managementContext.getRootConfiguration(); |
| | | |
| | | // Register as an add and delete listener with the root configuration so we |
| | | // can be notified if any entry cache entry is added or removed. |
| | | rootConfiguration.addPasswordStorageSchemeAddListener (this); |
| | | rootConfiguration.addPasswordStorageSchemeDeleteListener (this); |
| | | |
| | | // Initialize existing password storage schemes. |
| | | for (String schemeName: rootConfiguration.listPasswordStorageSchemes()) |
| | | { |
| | | DN schemeBase = DN.decode(DN_PWSCHEME_CONFIG_BASE); |
| | | baseEntry = configHandler.getConfigEntry(schemeBase); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | // Get the password storage scheme's configuration. |
| | | PasswordStorageSchemeCfg config = |
| | | rootConfiguration.getPasswordStorageScheme (schemeName); |
| | | |
| | | // Register as a change listener for this password storage scheme |
| | | // entry so that we will be notified of any changes that may be |
| | | // made to it. |
| | | config.addChangeListener (this); |
| | | |
| | | // Ignore this password storage scheme if it is disabled. |
| | | if (config.isEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_CANNOT_GET_BASE; |
| | | String message = getMessage(msgID, String.valueOf(e)); |
| | | throw new ConfigException(msgID, message, e); |
| | | } |
| | | |
| | | if (baseEntry == null) |
| | | { |
| | | // The password storage scheme base entry does not exist. This is not |
| | | // acceptable, so throw an exception. |
| | | int msgID = MSGID_CONFIG_PWSCHEME_BASE_DOES_NOT_EXIST; |
| | | String message = getMessage(msgID); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | |
| | | // Register add and delete listeners with the storage scheme base entry. We |
| | | // don't care about modifications to it. |
| | | baseEntry.registerAddListener(this); |
| | | baseEntry.registerDeleteListener(this); |
| | | |
| | | |
| | | // See if the base entry has any children. If not, then we don't need to do |
| | | // anything else. |
| | | if (! baseEntry.hasChildren()) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | |
| | | // Iterate through the child entries and process them as password storage |
| | | // scheme configuration entries. |
| | | for (ConfigEntry childEntry : baseEntry.getChildren().values()) |
| | | { |
| | | childEntry.registerChangeListener(this); |
| | | |
| | | StringBuilder unacceptableReason = new StringBuilder(); |
| | | if (! configAddIsAcceptable(childEntry, unacceptableReason)) |
| | | { |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_PWSCHEME_ENTRY_UNACCEPTABLE, |
| | | childEntry.getDN().toString(), unacceptableReason.toString()); |
| | | continue; |
| | | } |
| | | |
| | | try |
| | | { |
| | | ConfigChangeResult result = applyConfigurationAdd(childEntry); |
| | | if (result.getResultCode() != ResultCode.SUCCESS) |
| | | { |
| | | StringBuilder buffer = new StringBuilder(); |
| | | |
| | | List<String> resultMessages = result.getMessages(); |
| | | if ((resultMessages == null) || (resultMessages.isEmpty())) |
| | | { |
| | | buffer.append(getMessage(MSGID_CONFIG_UNKNOWN_UNACCEPTABLE_REASON)); |
| | | } |
| | | else |
| | | { |
| | | Iterator<String> iterator = resultMessages.iterator(); |
| | | |
| | | buffer.append(iterator.next()); |
| | | while (iterator.hasNext()) |
| | | { |
| | | buffer.append(EOL); |
| | | buffer.append(iterator.next()); |
| | | } |
| | | } |
| | | |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_PWSCHEME_CANNOT_CREATE_SCHEME, |
| | | childEntry.getDN().toString(), buffer.toString()); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_CONFIG_PWSCHEME_CANNOT_CREATE_SCHEME, |
| | | childEntry.getDN().toString(), String.valueOf(e)); |
| | | // Load the password storage scheme implementation class. |
| | | String className = config.getSchemeClass(); |
| | | loadAndInstallPasswordStorageScheme (className, config); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the configuration entry that will result from a proposed |
| | | * modification is acceptable to this change listener. |
| | | * |
| | | * @param configEntry The configuration entry that will result from |
| | | * the requested update. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed change is not acceptable. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry contains an acceptable |
| | | * configuration, or <CODE>false</CODE> if it does not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configChangeIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | public boolean isConfigurationChangeAcceptable( |
| | | PasswordStorageSchemeCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // Make sure that the entry has an appropriate objectclass for a password |
| | | // storage scheme. |
| | | if (! configEntry.hasObjectClass(OC_PASSWORD_STORAGE_SCHEME)) |
| | | // returned status -- all is fine by default |
| | | boolean status = true; |
| | | |
| | | if (configuration.isEnabled()) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_OBJECTCLASS; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // Make sure that the entry specifies the storage scheme class name. |
| | | StringConfigAttribute classNameAttr; |
| | | try |
| | | { |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_PWSCHEME_CLASS, |
| | | getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_CLASS_NAME), |
| | | true, false, true); |
| | | classNameAttr = (StringConfigAttribute) |
| | | configEntry.getConfigAttribute(classStub); |
| | | |
| | | if (classNameAttr == null) |
| | | // Get the name of the class and make sure we can instantiate it as |
| | | // a password storage scheme. |
| | | String className = configuration.getSchemeClass(); |
| | | try |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_NO_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | // Load the class but don't initialize it. |
| | | loadPasswordStorageScheme (className, null); |
| | | } |
| | | catch (InitializationException ie) |
| | | { |
| | | unacceptableReasons.add(ie.getMessage()); |
| | | status = false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | Class schemeClass; |
| | | try |
| | | { |
| | | schemeClass = DirectoryServer.loadClass(classNameAttr.pendingValue()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | try |
| | | { |
| | | PasswordStorageScheme scheme = |
| | | (PasswordStorageScheme) schemeClass.newInstance(); |
| | | } |
| | | catch(Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS; |
| | | String message = getMessage(msgID, schemeClass.getName(), |
| | | String.valueOf(configEntry.getDN()), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // See if this password storage scheme should be enabled. |
| | | BooleanConfigAttribute enabledAttr; |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_PWSCHEME_ENABLED, |
| | | getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_ENABLED), |
| | | false); |
| | | enabledAttr = (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | |
| | | if (enabledAttr == null) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_NO_ENABLED_ATTR; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_ENABLED_VALUE; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // If we've gotten here then the password storage scheme entry appears to be |
| | | // acceptable. |
| | | return true; |
| | | return status; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration to this Directory Server component |
| | | * based on the provided changed entry. |
| | | * |
| | | * @param configEntry The configuration entry that containing the updated |
| | | * configuration for this component. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry) |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | { |
| | | DN configEntryDN = configEntry.getDN(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | // Returned result. |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | ResultCode.SUCCESS, false, new ArrayList<String>() |
| | | ); |
| | | |
| | | // Get the configuration entry DN and the associated |
| | | // password storage scheme class. |
| | | DN configEntryDN = configuration.dn(); |
| | | PasswordStorageScheme storageScheme = storageSchemes.get( |
| | | configEntryDN |
| | | ); |
| | | |
| | | // Make sure that the entry has an appropriate objectclass for a password |
| | | // storage scheme. |
| | | if (! configEntry.hasObjectClass(OC_PASSWORD_STORAGE_SCHEME)) |
| | | // If the new configuration has the password storage scheme disabled, |
| | | // then remove it from the mapping list and clean it. |
| | | if (! configuration.isEnabled()) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_OBJECTCLASS; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | if (storageScheme != null) |
| | | { |
| | | uninstallPasswordStorageScheme (configEntryDN); |
| | | } |
| | | |
| | | return changeResult; |
| | | } |
| | | |
| | | // At this point, new configuration is enabled... |
| | | // If the current password storage scheme is already enabled then we |
| | | // don't do anything unless the class has changed in which case we |
| | | // should indicate that administrative action is required. |
| | | String newClassName = configuration.getSchemeClass(); |
| | | if (storageScheme != null) |
| | | { |
| | | String curClassName = storageScheme.getClass().getName(); |
| | | boolean classIsNew = (! newClassName.equals (curClassName)); |
| | | if (classIsNew) |
| | | { |
| | | changeResult.setAdminActionRequired (true); |
| | | } |
| | | return changeResult; |
| | | } |
| | | |
| | | // Get the corresponding password storage scheme if it is active. |
| | | PasswordStorageScheme scheme = storageSchemes.get(configEntryDN); |
| | | |
| | | |
| | | // See if this scheme should be enabled or disabled. |
| | | boolean needsEnabled = false; |
| | | BooleanConfigAttribute enabledAttr; |
| | | // New entry cache is enabled and there were no previous one. |
| | | // Instantiate the new class and initalize it. |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_PWSCHEME_ENABLED, |
| | | getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_ENABLED), |
| | | false); |
| | | enabledAttr = (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | |
| | | if (enabledAttr == null) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_NO_ENABLED_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | if (enabledAttr.activeValue()) |
| | | { |
| | | if (scheme == null) |
| | | { |
| | | needsEnabled = true; |
| | | } |
| | | else |
| | | { |
| | | // The scheme is already active, so no action is required. |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (scheme == null) |
| | | { |
| | | // The scheme is already disabled, so no action is required and we |
| | | // can short-circuit out of this processing. |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | else |
| | | { |
| | | // The scheme is active, so it needs to be disabled. Do this and |
| | | // return that we were successful. |
| | | storageSchemes.remove(configEntryDN); |
| | | scheme.finalizePasswordStorageScheme(); |
| | | |
| | | String lowerName = toLowerCase(scheme.getStorageSchemeName()); |
| | | DirectoryServer.deregisterPasswordStorageScheme(lowerName); |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | } |
| | | loadAndInstallPasswordStorageScheme (newClassName, configuration); |
| | | } |
| | | catch (Exception e) |
| | | catch (InitializationException ie) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_ENABLED_VALUE; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | changeResult.addMessage (ie.getMessage()); |
| | | changeResult.setResultCode (DirectoryServer.getServerErrorResultCode()); |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | // Make sure that the entry specifies the storage scheme class name. If it |
| | | // has changed, then we will not try to dynamically apply it. |
| | | String className; |
| | | try |
| | | { |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_PWSCHEME_CLASS, |
| | | getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_CLASS_NAME), |
| | | true, false, true); |
| | | StringConfigAttribute classNameAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(classStub); |
| | | |
| | | if (classNameAttr == null) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_NO_CLASS_NAME; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | className = classNameAttr.pendingValue(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | boolean classChanged = false; |
| | | String oldClassName = null; |
| | | if (scheme != null) |
| | | { |
| | | oldClassName = scheme.getClass().getName(); |
| | | classChanged = (! className.equals(oldClassName)); |
| | | } |
| | | |
| | | |
| | | if (classChanged) |
| | | { |
| | | // This will not be applied dynamically. Add a message to the response |
| | | // and indicate that admin action is required. |
| | | adminActionRequired = true; |
| | | messages.add(getMessage(MSGID_CONFIG_PWSCHEME_CLASS_ACTION_REQUIRED, |
| | | String.valueOf(oldClassName), |
| | | String.valueOf(className), |
| | | String.valueOf(configEntryDN))); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | if (needsEnabled) |
| | | { |
| | | try |
| | | { |
| | | Class schemeClass = DirectoryServer.loadClass(className); |
| | | scheme = (PasswordStorageScheme) schemeClass.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS; |
| | | messages.add(getMessage(msgID, className, |
| | | String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | try |
| | | { |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INITIALIZATION_FAILED; |
| | | messages.add(getMessage(msgID, className, |
| | | String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | |
| | | storageSchemes.put(configEntryDN, scheme); |
| | | DirectoryServer.registerPasswordStorageScheme(scheme); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then there haven't been any changes to anything |
| | | // that we care about. |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the configuration entry that will result from a proposed |
| | | * add is acceptable to this add listener. |
| | | * |
| | | * @param configEntry The configuration entry that will result from |
| | | * the requested add. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed entry is not acceptable. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry contains an acceptable |
| | | * configuration, or <CODE>false</CODE> if it does not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configAddIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | public boolean isConfigurationAddAcceptable( |
| | | PasswordStorageSchemeCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // returned status -- all is fine by default |
| | | boolean status = true; |
| | | |
| | | // Make sure that no entry already exists with the specified DN. |
| | | DN configEntryDN = configEntry.getDN(); |
| | | DN configEntryDN = configuration.dn(); |
| | | if (storageSchemes.containsKey(configEntryDN)) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_EXISTS; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | unacceptableReasons.add (message); |
| | | status = false; |
| | | } |
| | | |
| | | |
| | | // Make sure that the entry has an appropriate objectclass for a password |
| | | // storage scheme. |
| | | if (! configEntry.hasObjectClass(OC_PASSWORD_STORAGE_SCHEME)) |
| | | // If configuration is enabled then check that password storage scheme |
| | | // class can be instantiated. |
| | | else if (configuration.isEnabled()) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_OBJECTCLASS; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // Make sure that the entry specifies the password storage scheme class. |
| | | StringConfigAttribute classNameAttr; |
| | | try |
| | | { |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_PWSCHEME_CLASS, |
| | | getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_CLASS_NAME), |
| | | true, false, true); |
| | | classNameAttr = (StringConfigAttribute) |
| | | configEntry.getConfigAttribute(classStub); |
| | | |
| | | if (classNameAttr == null) |
| | | // Get the name of the class and make sure we can instantiate it as |
| | | // an entry cache. |
| | | String className = configuration.getSchemeClass(); |
| | | try |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_NO_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | // Load the class but don't initialize it. |
| | | loadPasswordStorageScheme (className, null); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | catch (InitializationException ie) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | Class schemeClass; |
| | | try |
| | | { |
| | | schemeClass = DirectoryServer.loadClass(classNameAttr.pendingValue()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | PasswordStorageScheme storageScheme; |
| | | try |
| | | { |
| | | storageScheme = (PasswordStorageScheme) schemeClass.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS; |
| | | String message = getMessage(msgID, schemeClass.getName(), |
| | | String.valueOf(configEntryDN), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // If the storage scheme is a configurable component, then make sure that |
| | | // its configuration is valid. |
| | | if (storageScheme instanceof ConfigurableComponent) |
| | | { |
| | | ConfigurableComponent cc = (ConfigurableComponent) storageScheme; |
| | | LinkedList<String> errorMessages = new LinkedList<String>(); |
| | | if (! cc.hasAcceptableConfiguration(configEntry, errorMessages)) |
| | | { |
| | | if (errorMessages.isEmpty()) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_UNACCEPTABLE_CONFIG; |
| | | unacceptableReason.append(getMessage(msgID, |
| | | String.valueOf(configEntryDN))); |
| | | } |
| | | else |
| | | { |
| | | Iterator<String> iterator = errorMessages.iterator(); |
| | | unacceptableReason.append(iterator.next()); |
| | | while (iterator.hasNext()) |
| | | { |
| | | unacceptableReason.append(" "); |
| | | unacceptableReason.append(iterator.next()); |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | unacceptableReasons.add (ie.getMessage()); |
| | | status = false; |
| | | } |
| | | } |
| | | |
| | | |
| | | // See if this storage scheme should be enabled. |
| | | BooleanConfigAttribute enabledAttr; |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_PWSCHEME_ENABLED, |
| | | getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_ENABLED), |
| | | false); |
| | | enabledAttr = (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | |
| | | if (enabledAttr == null) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_NO_ENABLED_ATTR; |
| | | String message = getMessage(msgID, configEntry.getDN().toString()); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_ENABLED_VALUE; |
| | | String message = getMessage(msgID, configEntry.getDN().toString(), |
| | | String.valueOf(e)); |
| | | unacceptableReason.append(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // If we've gotten here then the storage scheme entry appears to be |
| | | // acceptable. |
| | | return true; |
| | | return status; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration based on the provided added entry. |
| | | * |
| | | * @param configEntry The new configuration entry that contains the |
| | | * configuration to apply. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry) |
| | | public ConfigChangeResult applyConfigurationAdd( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | { |
| | | DN configEntryDN = configEntry.getDN(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | // Returned result. |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | ResultCode.SUCCESS, false, new ArrayList<String>() |
| | | ); |
| | | |
| | | // Register a change listener with it so we can be notified of changes |
| | | // to it over time. |
| | | configuration.addChangeListener(this); |
| | | |
| | | // Make sure that the entry has an appropriate objectclass for a password |
| | | // storage scheme. |
| | | if (! configEntry.hasObjectClass(OC_PASSWORD_STORAGE_SCHEME)) |
| | | if (configuration.isEnabled()) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_OBJECTCLASS; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // See if this storage scheme should be enabled or disabled. |
| | | BooleanConfigAttribute enabledAttr; |
| | | try |
| | | { |
| | | BooleanConfigAttribute enabledStub = |
| | | new BooleanConfigAttribute(ATTR_PWSCHEME_ENABLED, |
| | | getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_ENABLED), |
| | | false); |
| | | enabledAttr = (BooleanConfigAttribute) |
| | | configEntry.getConfigAttribute(enabledStub); |
| | | |
| | | if (enabledAttr == null) |
| | | // Instantiate the class as password storage scheme |
| | | // and initialize it. |
| | | String className = configuration.getSchemeClass(); |
| | | try |
| | | { |
| | | // The attribute doesn't exist, so it will be disabled by default. |
| | | int msgID = MSGID_CONFIG_PWSCHEME_NO_ENABLED_ATTR; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.SUCCESS; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | loadAndInstallPasswordStorageScheme (className, configuration); |
| | | } |
| | | else if (! enabledAttr.activeValue()) |
| | | catch (InitializationException ie) |
| | | { |
| | | // It is explicitly configured as disabled, so we don't need to do |
| | | // anything. |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | changeResult.addMessage (ie.getMessage()); |
| | | changeResult.setResultCode (DirectoryServer.getServerErrorResultCode()); |
| | | return changeResult; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_ENABLED_VALUE; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // Make sure that the entry specifies the storage scheme class name. |
| | | String className; |
| | | try |
| | | { |
| | | StringConfigAttribute classStub = |
| | | new StringConfigAttribute(ATTR_PWSCHEME_CLASS, |
| | | getMessage(MSGID_CONFIG_PWSCHEME_DESCRIPTION_CLASS_NAME), |
| | | true, false, true); |
| | | StringConfigAttribute classNameAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(classStub); |
| | | |
| | | if (classNameAttr == null) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_NO_CLASS_NAME; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN))); |
| | | resultCode = ResultCode.OBJECTCLASS_VIOLATION; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | className = classNameAttr.pendingValue(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS_NAME; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // Load and initialize the storage scheme class, and register it with the |
| | | // Directory Server. |
| | | PasswordStorageScheme storageScheme; |
| | | try |
| | | { |
| | | Class schemeClass = DirectoryServer.loadClass(className); |
| | | storageScheme = (PasswordStorageScheme) schemeClass.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INVALID_CLASS; |
| | | messages.add(getMessage(msgID, className, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | try |
| | | { |
| | | storageScheme.initializePasswordStorageScheme(configEntry); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INITIALIZATION_FAILED; |
| | | messages.add(getMessage(msgID, className, String.valueOf(configEntryDN), |
| | | String.valueOf(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | storageSchemes.put(configEntryDN, storageScheme); |
| | | DirectoryServer.registerPasswordStorageScheme(storageScheme); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether it is acceptable to remove the provided configuration |
| | | * entry. |
| | | * |
| | | * @param configEntry The configuration entry that will be removed |
| | | * from the configuration. |
| | | * @param unacceptableReason A buffer to which this method can append a |
| | | * human-readable message explaining why the |
| | | * proposed delete is not acceptable. |
| | | * |
| | | * @return <CODE>true</CODE> if the proposed entry may be removed from the |
| | | * configuration, or <CODE>false</CODE> if not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configDeleteIsAcceptable(ConfigEntry configEntry, |
| | | StringBuilder unacceptableReason) |
| | | public boolean isConfigurationDeleteAcceptable( |
| | | PasswordStorageSchemeCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // A delete should always be acceptable, so just return true. |
| | | return true; |
| | |
| | | |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration based on the provided deleted entry. |
| | | * |
| | | * @param configEntry The new configuration entry that has been deleted. |
| | | * |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry) |
| | | public ConfigChangeResult applyConfigurationDelete( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | { |
| | | DN configEntryDN = configEntry.getDN(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | // Returned result. |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | ResultCode.SUCCESS, false, new ArrayList<String>() |
| | | ); |
| | | |
| | | uninstallPasswordStorageScheme (configuration.dn()); |
| | | |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | // See if the entry is registered as a password storage scheme. If so, |
| | | // deregister it and stop the storage scheme. |
| | | PasswordStorageScheme storageScheme = storageSchemes.remove(configEntryDN); |
| | | if (storageScheme != null) |
| | | |
| | | /** |
| | | * Loads the specified class, instantiates it as a password storage scheme, |
| | | * and optionally initializes that instance. Any initialized password |
| | | * storage scheme is registered in the server. |
| | | * |
| | | * @param className The fully-qualified name of the password storage |
| | | * scheme class to load, instantiate, and initialize. |
| | | * @param configuration The configuration to use to initialize the |
| | | * password storage scheme, or {@code null} if the |
| | | * password storage scheme should not be initialized. |
| | | * |
| | | * @throws InitializationException If a problem occurred while attempting |
| | | * to initialize the class. |
| | | */ |
| | | private void loadAndInstallPasswordStorageScheme( |
| | | String className, |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | throws InitializationException |
| | | { |
| | | // Load the password storage scheme class... |
| | | PasswordStorageScheme |
| | | <? extends PasswordStorageSchemeCfg> schemeClass; |
| | | schemeClass = loadPasswordStorageScheme (className, configuration); |
| | | |
| | | // ... and install the password storage scheme in the server. |
| | | DN configEntryDN = configuration.dn(); |
| | | storageSchemes.put (configEntryDN, schemeClass); |
| | | DirectoryServer.registerPasswordStorageScheme (schemeClass); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Loads the specified class, instantiates it as a password storage scheme, |
| | | * and optionally initializes that instance. |
| | | * |
| | | * @param className The fully-qualified name of the class |
| | | * to load, instantiate, and initialize. |
| | | * @param configuration The configuration to use to initialize the |
| | | * class, or {@code null} if the |
| | | * class should not be initialized. |
| | | * |
| | | * @return The possibly initialized password storage scheme. |
| | | * |
| | | * @throws InitializationException If a problem occurred while attempting |
| | | * to initialize the class. |
| | | */ |
| | | private PasswordStorageScheme <? extends PasswordStorageSchemeCfg> |
| | | loadPasswordStorageScheme( |
| | | String className, |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | throws InitializationException |
| | | { |
| | | try |
| | | { |
| | | String lowerName = toLowerCase(storageScheme.getStorageSchemeName()); |
| | | DirectoryServer.deregisterPasswordStorageScheme(lowerName); |
| | | PasswordStorageSchemeCfgDefn definition; |
| | | ClassPropertyDefinition propertyDefinition; |
| | | Class<? extends PasswordStorageScheme> schemeClass; |
| | | PasswordStorageScheme<? extends PasswordStorageSchemeCfg> |
| | | passwordStorageScheme; |
| | | |
| | | storageScheme.finalizePasswordStorageScheme(); |
| | | definition = PasswordStorageSchemeCfgDefn.getInstance(); |
| | | propertyDefinition = definition.getSchemeClassPropertyDefinition(); |
| | | schemeClass = propertyDefinition.loadClass( |
| | | className, |
| | | PasswordStorageScheme.class |
| | | ); |
| | | passwordStorageScheme = |
| | | (PasswordStorageScheme<? extends PasswordStorageSchemeCfg>) |
| | | schemeClass.newInstance(); |
| | | |
| | | if (configuration != null) |
| | | { |
| | | Method method = passwordStorageScheme.getClass().getMethod( |
| | | "initializePasswordStorageScheme", |
| | | configuration.definition().getServerConfigurationClass() |
| | | ); |
| | | method.invoke(passwordStorageScheme, configuration); |
| | | } |
| | | |
| | | return passwordStorageScheme; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | int msgID = MSGID_CONFIG_PWSCHEME_INITIALIZATION_FAILED; |
| | | String message = getMessage( |
| | | msgID, className, |
| | | String.valueOf(configuration.dn()), |
| | | stackTraceToSingleLineString(e) |
| | | ); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | } |
| | | |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired); |
| | | /** |
| | | * Remove a password storage that has been installed in the server. |
| | | * |
| | | * @param configEntryDN the DN of the configuration enry associated to |
| | | * the password storage scheme to remove |
| | | */ |
| | | private void uninstallPasswordStorageScheme( |
| | | DN configEntryDN |
| | | ) |
| | | { |
| | | PasswordStorageScheme scheme = |
| | | storageSchemes.remove (configEntryDN); |
| | | if (scheme != null) |
| | | { |
| | | DirectoryServer.deregisterPasswordStorageScheme ( |
| | | scheme.getStorageSchemeName().toLowerCase() |
| | | ); |
| | | scheme.finalizePasswordStorageScheme(); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ByteStringFactory; |
| | |
| | | * value from the casual observer. |
| | | */ |
| | | public class Base64PasswordStorageScheme |
| | | extends PasswordStorageScheme |
| | | extends PasswordStorageScheme <PasswordStorageSchemeCfg> |
| | | { |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordStorageScheme(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializePasswordStorageScheme( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // No initialization is required. |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ByteStringFactory; |
| | |
| | | * applications. |
| | | */ |
| | | public class ClearPasswordStorageScheme |
| | | extends PasswordStorageScheme |
| | | extends PasswordStorageScheme <PasswordStorageSchemeCfg> |
| | | { |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordStorageScheme(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializePasswordStorageScheme( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // No initialization is required. |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.concurrent.locks.Lock; |
| | | |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.server.EntryCacheCfg; |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.EntryCache; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.LockType; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | |
| | | |
| | |
| | | * <CODE>putEntry</CODE> will return immediately without doing anything. |
| | | */ |
| | | public class DefaultEntryCache |
| | | extends EntryCache |
| | | extends EntryCache<EntryCacheCfg> |
| | | implements ConfigurationChangeListener<EntryCacheCfg> |
| | | { |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Initializes this entry cache implementation so that it will be available |
| | | * for storing and retrieving entries. |
| | | * |
| | | * @param configEntry The configuration entry containing the settings to use |
| | | * for this entry cache. |
| | | * |
| | | * @throws ConfigException If there is a problem with the provided |
| | | * configuration entry that would prevent this |
| | | * entry cache from being used. |
| | | * |
| | | * @throws InitializationException If a problem occurs during the |
| | | * initialization process that is not |
| | | * related to the configuration. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeEntryCache(ConfigEntry configEntry) |
| | | public void initializeEntryCache(EntryCacheCfg configEntry) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // No implementation required. |
| | |
| | | |
| | | |
| | | /** |
| | | * Performs any necessary cleanup work (e.g., flushing all cached entries and |
| | | * releasing any other held resources) that should be performed when the |
| | | * server is to be shut down or the entry cache destroyed or replaced. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void finalizeEntryCache() |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the entry cache currently contains the entry with the |
| | | * specified DN. This method may be called without holding any locks if a |
| | | * point-in-time check is all that is required. |
| | | * |
| | | * @param entryDN The DN for which to make the determination. |
| | | * |
| | | * @return <CODE>true</CODE> if the entry cache currently contains the entry |
| | | * with the specified DN, or <CODE>false</CODE> if not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean containsEntry(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the entry with the specified DN from the cache. The caller |
| | | * should have already acquired a read or write lock for the entry if such |
| | | * protection is needed. |
| | | * |
| | | * @param entryDN The DN of the entry to retrieve. |
| | | * |
| | | * @return The requested entry if it is present in the cache, or |
| | | * <CODE>null</CODE> if it is not present. |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry getEntry(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the entry ID for the entry with the specified DN from the cache. |
| | | * The caller should have already acquired a read or write lock for the entry |
| | | * if such protection is needed. |
| | | * |
| | | * @param entryDN The DN of the entry for which to retrieve the entry ID. |
| | | * |
| | | * @return The entry ID for the requested entry, or -1 if it is not present |
| | | * in the cache. |
| | | * {@inheritDoc} |
| | | */ |
| | | public long getEntryID(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the entry with the specified DN from the cache, obtaining a lock |
| | | * on the entry before it is returned. If the entry is present in the cache, |
| | | * then a lock will be obtained for that entry and appended to the provided |
| | | * list before the entry is returned. If the entry is not present, then no |
| | | * lock will be obtained. |
| | | * |
| | | * @param entryDN The DN of the entry to retrieve. |
| | | * @param lockType The type of lock to obtain (it may be <CODE>NONE</CODE>). |
| | | * @param lockList The list to which the obtained lock will be added (note |
| | | * that no lock will be added if the lock type was |
| | | * <CODE>NONE</CODE>). |
| | | * |
| | | * @return The requested entry if it is present in the cache, or |
| | | * <CODE>null</CODE> if it is not present. |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry getEntry(DN entryDN, LockType lockType, List<Lock> lockList) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the requested entry if it is present in the cache, obtaining a |
| | | * lock on the entry before it is returned. If the entry is present in the |
| | | * cache, then a lock will be obtained for that entry and appended to the |
| | | * provided list before the entry is returned. If the entry is not present, |
| | | * then no lock will be obtained. |
| | | * |
| | | * @param backend The backend associated with the entry to retrieve. |
| | | * @param entryID The entry ID within the provided backend for the |
| | | * specified entry. |
| | | * @param lockType The type of lock to obtain (it may be <CODE>NONE</CODE>). |
| | | * @param lockList The list to which the obtained lock will be added (note |
| | | * that no lock will be added if the lock type was |
| | | * <CODE>NONE</CODE>). |
| | | * |
| | | * @return The requested entry if it is present in the cache, or |
| | | * <CODE>null</CODE> if it is not present. |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry getEntry(Backend backend, long entryID, LockType lockType, |
| | | List<Lock> lockList) |
| | |
| | | |
| | | |
| | | /** |
| | | * Stores the provided entry in the cache. Note that the mechanism that it |
| | | * uses to achieve this is implementation-dependent, and it is acceptable for |
| | | * the entry to not actually be stored in any cache. |
| | | * |
| | | * @param entry The entry to store in the cache. |
| | | * @param backend The backend with which the entry is associated. |
| | | * @param entryID The entry ID within the provided backend that uniquely |
| | | * identifies the specified entry. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void putEntry(Entry entry, Backend backend, long entryID) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Stores the provided entry in the cache only if it does not conflict with an |
| | | * entry that already exists. Note that the mechanism that it uses to achieve |
| | | * this is implementation-dependent, and it is acceptable for the entry to not |
| | | * actually be stored in any cache. However, this method must not overwrite |
| | | * an existing version of the entry. |
| | | * |
| | | * @param entry The entry to store in the cache. |
| | | * @param backend The backend with which the entry is associated. |
| | | * @param entryID The entry ID within the provided backend that uniquely |
| | | * identifies the specified entry. |
| | | * |
| | | * @return <CODE>false</CODE> if an existing entry or some other problem |
| | | * prevented the method from completing successfully, or |
| | | * <CODE>true</CODE> if there was no conflict and the entry was |
| | | * either stored or the cache determined that this entry should never |
| | | * be cached for some reason. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean putEntryIfAbsent(Entry entry, Backend backend, long entryID) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes the specified entry from the cache. |
| | | * |
| | | * @param entryDN The DN of the entry to remove from the cache. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void removeEntry(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes all entries from the cache. The cache should still be available |
| | | * for future use. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void clear() |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes all entries from the cache that are associated with the provided |
| | | * backend. |
| | | * |
| | | * @param backend The backend for which to flush the associated entries. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void clearBackend(Backend backend) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes all entries from the cache that are below the provided DN. |
| | | * |
| | | * @param baseDN The base DN below which all entries should be flushed. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void clearSubtree(DN baseDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Attempts to react to a scenario in which it is determined that the system |
| | | * is running low on available memory. In this case, the entry cache should |
| | | * attempt to free some memory if possible to try to avoid out of memory |
| | | * errors. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void handleLowMemory() |
| | | { |
| | | // This implementation does not store entries, so there are no resources |
| | | // that it can free. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | EntryCacheCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // No implementation required. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | EntryCacheCfg configuration |
| | | ) |
| | | { |
| | | // No implementation required. |
| | | |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | ResultCode.SUCCESS, false, new ArrayList<String>() |
| | | ); |
| | | |
| | | return changeResult; |
| | | } |
| | | } |
| | | |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE |
| | | * or https://OpenDS.dev.java.net/OpenDS.LICENSE. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006-2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | import static org.opends.server.loggers.Error.logError; |
| | | import static org.opends.server.messages.MessageHandler.getMessage; |
| | | import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.SortedSet; |
| | | |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.ErrorLogCategory; |
| | | import org.opends.server.types.ErrorLogSeverity; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchFilter; |
| | | |
| | | |
| | | /** |
| | | * This class provides some common tools to all entry cache implementations. |
| | | */ |
| | | public class EntryCacheCommon |
| | | { |
| | | /** |
| | | * Configuration phases. Each value identifies a configuration step: |
| | | * - PHASE_INIT when invoking method initializeEntryCache() |
| | | * - PHASE_ACCEPTABLE when invoking method isConfigurationChangeAcceptable() |
| | | * - PHASE_APPLY when invoking method applyConfigurationChange() |
| | | */ |
| | | public static enum ConfigPhase |
| | | { |
| | | /** |
| | | * Indicates that entry cache is in initialization check phase. |
| | | */ |
| | | PHASE_INIT, |
| | | |
| | | /** |
| | | * Indicates that entry cache is in configuration check phase. |
| | | */ |
| | | PHASE_ACCEPTABLE, |
| | | |
| | | /** |
| | | * Indicates that entry cache is applying its configuration. |
| | | */ |
| | | PHASE_APPLY |
| | | } |
| | | |
| | | /** |
| | | * Error handler used by local methods to report configuration error. |
| | | * The error handler simplifies the code of initializeEntryCache(), |
| | | * isConfigurationChangeAcceptable() and applyConfigurationChanges() methods. |
| | | */ |
| | | public class ConfigErrorHandler |
| | | { |
| | | // Configuration phase. |
| | | private EntryCacheCommon.ConfigPhase _configPhase; |
| | | |
| | | // Unacceptable reasons. Used when _configPhase is PHASE_ACCEPTABLE. |
| | | private List<String> _unacceptableReasons; |
| | | |
| | | // Error messages. Used when _configPhase is PHASE_APPLY. |
| | | private ArrayList<String> _errorMessages; |
| | | |
| | | // Result code. Used when _configPhase is PHASE_APPLY. |
| | | private ResultCode _resultCode; |
| | | |
| | | // Acceptable Configuration ? Used when _configPhase is PHASE_ACCEPTABLE |
| | | // or PHASE_APPLY. |
| | | private boolean _isAcceptable; |
| | | |
| | | /** |
| | | * Create an error handler. |
| | | * |
| | | * @param configPhase the configuration phase for which the |
| | | * error handler is used |
| | | * @param unacceptableReasons the reasons why the configuration cannot |
| | | * be applied (during PHASE_ACCEPTABLE phase) |
| | | * @param errorMessages the errors found when applying a new |
| | | * configuration (during PHASE_APPLY phase) |
| | | */ |
| | | public ConfigErrorHandler ( |
| | | EntryCacheCommon.ConfigPhase configPhase, |
| | | List<String> unacceptableReasons, |
| | | ArrayList<String> errorMessages |
| | | ) |
| | | { |
| | | _configPhase = configPhase; |
| | | _unacceptableReasons = unacceptableReasons; |
| | | _errorMessages = errorMessages; |
| | | _resultCode = ResultCode.SUCCESS; |
| | | _isAcceptable = true; |
| | | } |
| | | |
| | | /** |
| | | * Report an error. |
| | | * |
| | | * @param category the category of the error to report |
| | | * @param severity the severity of the error to report |
| | | * @param errorID the error ID of the error to report |
| | | * @param arg1 the first argument of the error message |
| | | * @param arg2 the second argument of the error message |
| | | * @param arg3 the third argument of the error message |
| | | * @param isAcceptable <code>true</code> if the configuration is acceptable |
| | | * @param resultCode the change result for the current configuration |
| | | */ |
| | | public void reportError( |
| | | ErrorLogCategory category, |
| | | ErrorLogSeverity severity, |
| | | int errorID, |
| | | String arg1, |
| | | String arg2, |
| | | String arg3, |
| | | boolean isAcceptable, |
| | | ResultCode resultCode |
| | | ) |
| | | { |
| | | switch (_configPhase) |
| | | { |
| | | case PHASE_INIT: |
| | | { |
| | | logError (category, severity, errorID, arg1, arg2, arg3); |
| | | break; |
| | | } |
| | | case PHASE_ACCEPTABLE: |
| | | { |
| | | String message = getMessage (errorID, arg1, arg2, arg3); |
| | | _unacceptableReasons.add (message); |
| | | _isAcceptable = isAcceptable; |
| | | break; |
| | | } |
| | | case PHASE_APPLY: |
| | | { |
| | | String message = getMessage (errorID, arg1, arg2, arg3); |
| | | _errorMessages.add (message); |
| | | _isAcceptable = isAcceptable; |
| | | if (_resultCode == ResultCode.SUCCESS) |
| | | { |
| | | _resultCode = resultCode; |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Get the current result code that was elaborated right after a |
| | | * configuration has been applied. |
| | | * |
| | | * @return the current result code |
| | | */ |
| | | public ResultCode getResultCode() |
| | | { |
| | | return _resultCode; |
| | | } |
| | | |
| | | /** |
| | | * Get the current isAcceptable flag. The isAcceptable flag is elaborated |
| | | * right after the configuration was checked. |
| | | * |
| | | * @return the isAcceptable flag |
| | | */ |
| | | public boolean getIsAcceptable() |
| | | { |
| | | return _isAcceptable; |
| | | } |
| | | |
| | | /** |
| | | * Get the current unacceptable reasons. The unacceptable reasons are |
| | | * elaborated when the configuration is checked. |
| | | * |
| | | * @return the list of unacceptable reasons |
| | | */ |
| | | public List<String> getUnacceptableReasons() |
| | | { |
| | | return _unacceptableReasons; |
| | | } |
| | | |
| | | /** |
| | | * Get the current error messages. The error messages are elaborated |
| | | * when the configuration is applied. |
| | | * |
| | | * @return the list of error messages |
| | | */ |
| | | public ArrayList<String> getErrorMessages() |
| | | { |
| | | return _errorMessages; |
| | | } |
| | | |
| | | /** |
| | | * Get the current configuration phase. The configuration phase indicates |
| | | * whether the entry cache is in initialization step, or in configuration |
| | | * checking step or in configuration being applied step. |
| | | * |
| | | * @return the current configuration phase. |
| | | */ |
| | | public ConfigPhase getConfigPhase() |
| | | { |
| | | return _configPhase; |
| | | } |
| | | } // ConfigErrorHandler |
| | | |
| | | |
| | | /** |
| | | * Reads a list of string filters and convert it to a list of search |
| | | * filters. |
| | | * |
| | | * @param filters the list of string filter to convert to search filters |
| | | * @param decodeErrorMsgId the error message ID to use in case of error |
| | | * @param errorHandler an handler used to report errors |
| | | * during decoding of filter |
| | | * @param noFilterMsgId the error message ID to use when none of the |
| | | * filters was decoded properly |
| | | * @param configEntryDN the DN of the configuration entry for the |
| | | * entry cache |
| | | * |
| | | * @return the set of search filters |
| | | */ |
| | | public static HashSet<SearchFilter> getFilters ( |
| | | SortedSet<String> filters, |
| | | int decodeErrorMsgId, |
| | | int noFilterMsgId, |
| | | ConfigErrorHandler errorHandler, |
| | | DN configEntryDN |
| | | ) |
| | | { |
| | | // Returned value |
| | | HashSet<SearchFilter> searchFilters = new HashSet<SearchFilter>(); |
| | | |
| | | // Convert the string filters to search filters. |
| | | if (filters != null) |
| | | { |
| | | for (String curFilter: filters) |
| | | { |
| | | try |
| | | { |
| | | searchFilters.add (SearchFilter.createFilterFromString (curFilter)); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | // We couldn't decode this filter. Log a warning and continue. |
| | | errorHandler.reportError( |
| | | ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, |
| | | decodeErrorMsgId, |
| | | String.valueOf(configEntryDN), |
| | | curFilter, |
| | | stackTraceToSingleLineString (de), |
| | | false, |
| | | ResultCode.INVALID_ATTRIBUTE_SYNTAX |
| | | ); |
| | | } |
| | | } |
| | | |
| | | // If none of the filters was decoded properly log an error message |
| | | // (only if we are in initialize phase). |
| | | if ((errorHandler.getConfigPhase() == ConfigPhase.PHASE_INIT) |
| | | && searchFilters.isEmpty()) |
| | | { |
| | | errorHandler.reportError( |
| | | ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | noFilterMsgId, |
| | | null, |
| | | null, |
| | | null, |
| | | false, |
| | | null |
| | | ); |
| | | } |
| | | } |
| | | |
| | | // done |
| | | return searchFilters; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create a new error handler. |
| | | * |
| | | * @param configPhase the configuration phase for which the |
| | | * error handler is used |
| | | * @param unacceptableReasons the reasons why the configuration cannot |
| | | * be applied (during PHASE_ACCEPTABLE phase) |
| | | * @param errorMessages the errors found when applying a new |
| | | * configuration (during PHASE_APPLY phase) |
| | | * |
| | | * @return a new configuration error handler |
| | | */ |
| | | public static ConfigErrorHandler getConfigErrorHandler ( |
| | | EntryCacheCommon.ConfigPhase configPhase, |
| | | List<String> unacceptableReasons, |
| | | ArrayList<String> errorMessages |
| | | ) |
| | | { |
| | | ConfigErrorHandler errorHandler = null; |
| | | |
| | | EntryCacheCommon ec = new EntryCacheCommon(); |
| | | |
| | | errorHandler = ec.new ConfigErrorHandler ( |
| | | configPhase, unacceptableReasons, errorMessages |
| | | ); |
| | | return errorHandler; |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.Error.logError; |
| | | import static org.opends.server.messages.ExtensionsMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.getMessage; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.meta. |
| | | ErrorLogAccountStatusNotificationHandlerCfgDefn; |
| | | import org.opends.server.admin.std.server. |
| | | ErrorLogAccountStatusNotificationHandlerCfg; |
| | | import org.opends.server.api.AccountStatusNotificationHandler; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.MultiChoiceConfigAttribute; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.AccountStatusNotificationType; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import static org.opends.server.loggers.Error.*; |
| | | import static org.opends.server.messages.ExtensionsMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | * logging facility. |
| | | */ |
| | | public class ErrorLogAccountStatusNotificationHandler |
| | | extends AccountStatusNotificationHandler |
| | | implements ConfigurableComponent |
| | | extends |
| | | AccountStatusNotificationHandler |
| | | <ErrorLogAccountStatusNotificationHandlerCfg> |
| | | implements |
| | | ConfigurationChangeListener |
| | | <ErrorLogAccountStatusNotificationHandlerCfg> |
| | | { |
| | | |
| | | |
| | | |
| | | /** |
| | | * The set of names for the account status notification types that may be |
| | | * logged by this notification handler. |
| | |
| | | private static final HashSet<String> NOTIFICATION_TYPE_NAMES = |
| | | new HashSet<String>(); |
| | | |
| | | |
| | | |
| | | // The DN of the configuration entry for this notification handler. |
| | | private DN configEntryDN; |
| | | |
| | | // The set of notification types that should generate log messages. |
| | | private HashSet<AccountStatusNotificationType> notificationTypes; |
| | | |
| | | |
| | | |
| | | |
| | | static |
| | | { |
| | | for (AccountStatusNotificationType t : |
| | |
| | | } |
| | | |
| | | |
| | | // The DN of the configuration entry for this notification handler. |
| | | private DN configEntryDN; |
| | | |
| | | // The set of notification types that should generate log messages. |
| | | private HashSet<AccountStatusNotificationType> notificationTypes; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Initializes this account status notification handler based on the |
| | | * information in the provided configuration entry. |
| | | * |
| | | * @param configEntry The configuration entry that contains the information |
| | | * to use to initialize this account status notification |
| | | * handler. |
| | | * |
| | | * @throws ConfigException If the provided entry does not contain a valid |
| | | * configuration for this account status |
| | | * notification handler. |
| | | * |
| | | * @throws InitializationException If a problem occurs during initialization |
| | | * that is not related to the server |
| | | * configuration. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeStatusNotificationHandler(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializeStatusNotificationHandler( |
| | | ErrorLogAccountStatusNotificationHandlerCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | configEntryDN = configEntry.getDN(); |
| | | configuration.addErrorLogChangeListener (this); |
| | | configEntryDN = configuration.dn(); |
| | | |
| | | |
| | | // Initialize the set of notification types that should generate log |
| | | // messages. |
| | | int msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_DESCRIPTION_NOTIFICATION_TYPES; |
| | | MultiChoiceConfigAttribute typesStub = |
| | | new MultiChoiceConfigAttribute(ATTR_ACCT_NOTIFICATION_TYPE, |
| | | getMessage(msgID), true, true, false, |
| | | NOTIFICATION_TYPE_NAMES); |
| | | try |
| | | { |
| | | MultiChoiceConfigAttribute typesAttr = |
| | | (MultiChoiceConfigAttribute) |
| | | configEntry.getConfigAttribute(typesStub); |
| | | notificationTypes = new HashSet<AccountStatusNotificationType>(); |
| | | for (String s : typesAttr.activeValues()) |
| | | { |
| | | AccountStatusNotificationType t = |
| | | AccountStatusNotificationType.typeForName(s); |
| | | if (t == null) |
| | | { |
| | | msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_INVALID_TYPE; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), s); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | else |
| | | { |
| | | notificationTypes.add(t); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_CANNOT_GET_NOTIFICATION_TYPES; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | DirectoryServer.registerAccountStatusNotificationHandler(configEntryDN, |
| | | this); |
| | | // Read configuration and apply changes. |
| | | boolean applyChanges = true; |
| | | processNotificationHandlerConfig (configuration, applyChanges); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs any processing that may be necessary in conjunction with the |
| | | * provided account status notification type. |
| | | * |
| | | * @param notificationType The type for this account status notification. |
| | | * @param userDN The DN of the user entry to which this |
| | | * notification applies. |
| | | * @param messageID The unique ID for this notification. |
| | | * @param message The human-readable message for this notification. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void handleStatusNotification(AccountStatusNotificationType |
| | | notificationType, |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an |
| | | * acceptable configuration for this component. If it does not, |
| | | * then detailed information about the problem(s) should be added to |
| | | * the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to |
| | | * make the determination. |
| | | * @param unacceptableReasons A list that can be used to hold |
| | | * messages about why the provided |
| | | * entry does not have an acceptable |
| | | * configuration. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided entry has an |
| | | * acceptable configuration for this component, or |
| | | * <CODE>false</CODE> if not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | List<String> unacceptableReasons) |
| | | public boolean isConfigurationChangeAcceptable( |
| | | ErrorLogAccountStatusNotificationHandlerCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // Initialize the set of notification types that should generate log |
| | | // messages. |
| | | int msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_DESCRIPTION_NOTIFICATION_TYPES; |
| | | MultiChoiceConfigAttribute typesStub = |
| | | new MultiChoiceConfigAttribute(ATTR_ACCT_NOTIFICATION_TYPE, |
| | | getMessage(msgID), true, true, false, |
| | | NOTIFICATION_TYPE_NAMES); |
| | | try |
| | | { |
| | | MultiChoiceConfigAttribute typesAttr = |
| | | (MultiChoiceConfigAttribute) |
| | | configEntry.getConfigAttribute(typesStub); |
| | | HashSet<AccountStatusNotificationType> types = |
| | | new HashSet<AccountStatusNotificationType>(); |
| | | for (String s : typesAttr.activeValues()) |
| | | { |
| | | AccountStatusNotificationType t = |
| | | AccountStatusNotificationType.typeForName(s); |
| | | if (t == null) |
| | | { |
| | | msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_INVALID_TYPE; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), s); |
| | | unacceptableReasons.add(message); |
| | | return false; |
| | | } |
| | | else |
| | | { |
| | | types.add(t); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | // Make sure that we can process the defined notification handler. |
| | | // If so, then we'll accept the new configuration. |
| | | boolean applyChanges = false; |
| | | boolean isAcceptable = processNotificationHandlerConfig ( |
| | | configuration, applyChanges |
| | | ); |
| | | |
| | | msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_CANNOT_GET_NOTIFICATION_TYPES; |
| | | String message = getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e)); |
| | | unacceptableReasons.add(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then everything is OK. |
| | | return true; |
| | | return isAcceptable; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained |
| | | * in the provided entry. Information about the result of this |
| | | * processing should be added to the provided message list. |
| | | * Information should always be added to this list if a |
| | | * configuration change could not be applied. If detailed results |
| | | * are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not |
| | | * changed) should also be included. |
| | | * Makes a best-effort attempt to apply the configuration contained in the |
| | | * provided entry. Information about the result of this processing should be |
| | | * added to the provided message list. Information should always be added to |
| | | * this list if a configuration change could not be applied. If detailed |
| | | * results are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not changed) should |
| | | * also be included. |
| | | * |
| | | * @param configEntry The entry containing the new |
| | | * configuration to apply for this |
| | | * component. |
| | | * @param detailedResults Indicates whether detailed information |
| | | * about the processing should be added to |
| | | * the list. |
| | | * @param configuration The entry containing the new configuration to |
| | | * apply for this component. |
| | | * @param detailedResults Indicates whether detailed information about the |
| | | * processing should be added to the list. |
| | | * |
| | | * @return Information about the result of the configuration |
| | | * update. |
| | | * @return Information about the result of the configuration update. |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | public ConfigChangeResult applyConfigurationChange ( |
| | | ErrorLogAccountStatusNotificationHandlerCfg configuration, |
| | | boolean detailedResults |
| | | ) |
| | | { |
| | | ConfigChangeResult changeResult = applyConfigurationChange (configuration); |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange ( |
| | | ErrorLogAccountStatusNotificationHandlerCfg configuration |
| | | ) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | resultCode, adminActionRequired, messages |
| | | ); |
| | | |
| | | // Initialize the set of notification types that should generate log |
| | | // messages. |
| | | HashSet<AccountStatusNotificationType> types = |
| | | new HashSet<AccountStatusNotificationType>(); |
| | | int msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_DESCRIPTION_NOTIFICATION_TYPES; |
| | | MultiChoiceConfigAttribute typesStub = |
| | | new MultiChoiceConfigAttribute(ATTR_ACCT_NOTIFICATION_TYPE, |
| | | getMessage(msgID), true, true, false, |
| | | NOTIFICATION_TYPE_NAMES); |
| | | try |
| | | { |
| | | MultiChoiceConfigAttribute typesAttr = |
| | | (MultiChoiceConfigAttribute) |
| | | configEntry.getConfigAttribute(typesStub); |
| | | for (String s : typesAttr.activeValues()) |
| | | { |
| | | AccountStatusNotificationType t = |
| | | AccountStatusNotificationType.typeForName(s); |
| | | if (t == null) |
| | | { |
| | | resultCode = ResultCode.UNWILLING_TO_PERFORM; |
| | | boolean applyChanges = false; |
| | | processNotificationHandlerConfig ( |
| | | configuration, applyChanges |
| | | ); |
| | | |
| | | msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_INVALID_TYPE; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), s)); |
| | | } |
| | | else |
| | | { |
| | | types.add(t); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | |
| | | msgID = MSGID_ERRORLOG_ACCTNOTHANDLER_CANNOT_GET_NOTIFICATION_TYPES; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | } |
| | | |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | this.notificationTypes = types; |
| | | } |
| | | |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Parses the provided configuration and configure the notification handler. |
| | | * |
| | | * @param configuration The new configuration containing the changes. |
| | | * @param applyChanges If true then take into account the new configuration. |
| | | * |
| | | * @return The mapping between strings of character set values and the |
| | | * minimum number of characters required from those sets. |
| | | */ |
| | | public boolean processNotificationHandlerConfig( |
| | | ErrorLogAccountStatusNotificationHandlerCfg configuration, |
| | | boolean applyChanges |
| | | ) |
| | | { |
| | | // false if the configuration is not acceptable |
| | | boolean isAcceptable = true; |
| | | |
| | | // The set of notification types that should generate log messages. |
| | | HashSet<AccountStatusNotificationType> newNotificationTypes = |
| | | new HashSet<AccountStatusNotificationType>(); |
| | | |
| | | // Initialize the set of notification types that should generate log |
| | | // messages. |
| | | for (ErrorLogAccountStatusNotificationHandlerCfgDefn. |
| | | AccountStatusNotificationType configNotificationType: |
| | | configuration.getAccountStatusNotificationType()) |
| | | { |
| | | newNotificationTypes.add (getNotificationType (configNotificationType)); |
| | | } |
| | | |
| | | if (applyChanges && isAcceptable) |
| | | { |
| | | notificationTypes = newNotificationTypes; |
| | | } |
| | | |
| | | return isAcceptable; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Gets the OpenDS notification type object that corresponds to the |
| | | * configuration counterpart. |
| | | * |
| | | * @param notificationType The configuration notification type for which |
| | | * to retrieve the OpenDS notification type. |
| | | */ |
| | | private AccountStatusNotificationType getNotificationType( |
| | | ErrorLogAccountStatusNotificationHandlerCfgDefn. |
| | | AccountStatusNotificationType configNotificationType |
| | | ) |
| | | { |
| | | AccountStatusNotificationType nt = null; |
| | | |
| | | switch (configNotificationType) |
| | | { |
| | | case ACCOUNT_TEMPORARILY_LOCKED: |
| | | nt = AccountStatusNotificationType.ACCOUNT_TEMPORARILY_LOCKED; |
| | | break; |
| | | case ACCOUNT_PERMANENTLY_LOCKED: |
| | | nt = AccountStatusNotificationType.ACCOUNT_PERMANENTLY_LOCKED; |
| | | break; |
| | | case ACCOUNT_UNLOCKED: |
| | | nt = AccountStatusNotificationType.ACCOUNT_UNLOCKED; |
| | | break; |
| | | case ACCOUNT_IDLE_LOCKED: |
| | | nt = AccountStatusNotificationType.ACCOUNT_IDLE_LOCKED; |
| | | break; |
| | | case ACCOUNT_RESET_LOCKED: |
| | | nt = AccountStatusNotificationType.ACCOUNT_RESET_LOCKED; |
| | | break; |
| | | case ACCOUNT_DISABLED: |
| | | nt = AccountStatusNotificationType.ACCOUNT_DISABLED; |
| | | break; |
| | | case ACCOUNT_ENABLED: |
| | | nt = AccountStatusNotificationType.ACCOUNT_ENABLED; |
| | | break; |
| | | case ACCOUNT_EXPIRED: |
| | | nt = AccountStatusNotificationType.ACCOUNT_EXPIRED; |
| | | break; |
| | | case PASSWORD_EXPIRED: |
| | | nt = AccountStatusNotificationType.PASSWORD_EXPIRED; |
| | | break; |
| | | case PASSWORD_EXPIRING: |
| | | nt = AccountStatusNotificationType.PASSWORD_EXPIRING; |
| | | break; |
| | | case PASSWORD_RESET: |
| | | nt = AccountStatusNotificationType.PASSWORD_RESET; |
| | | break; |
| | | case PASSWORD_CHANGED: |
| | | nt = AccountStatusNotificationType.PASSWORD_CHANGED; |
| | | break; |
| | | } |
| | | |
| | | return nt; |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.api.EntryCache; |
| | | import org.opends.server.admin.std.server.FIFOEntryCacheCfg; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.IntegerConfigAttribute; |
| | | import org.opends.server.config.IntegerWithUnitConfigAttribute; |
| | |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.ErrorLogCategory; |
| | | import org.opends.server.types.ErrorLogSeverity; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.LockManager; |
| | | import org.opends.server.types.LockType; |
| | |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import static org.opends.server.loggers.Error.*; |
| | | import static org.opends.server.messages.ExtensionsMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | |
| | | * of the given filters will be stored in the cache. |
| | | */ |
| | | public class FIFOEntryCache |
| | | extends EntryCache |
| | | implements ConfigurableComponent |
| | | extends EntryCache <FIFOEntryCacheCfg> |
| | | implements ConfigurationChangeListener<FIFOEntryCacheCfg> |
| | | { |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Initializes this entry cache implementation so that it will be available |
| | | * for storing and retrieving entries. |
| | | * |
| | | * @param configEntry The configuration entry containing the settings to use |
| | | * for this entry cache. |
| | | * |
| | | * @throws ConfigException If there is a problem with the provided |
| | | * configuration entry that would prevent this |
| | | * entry cache from being used. |
| | | * |
| | | * @throws InitializationException If a problem occurs during the |
| | | * initialization process that is not |
| | | * related to the configuration. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeEntryCache(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializeEntryCache( |
| | | FIFOEntryCacheCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | configEntryDN = configEntry.getDN(); |
| | | |
| | | configuration.addFIFOChangeListener (this); |
| | | configEntryDN = configuration.dn(); |
| | | |
| | | // Initialize the cache structures. |
| | | idMap = new HashMap<Backend,HashMap<Long,CacheEntry>>(); |
| | | dnMap = new LinkedHashMap<DN,CacheEntry>(); |
| | | cacheLock = new ReentrantLock(); |
| | | runtime = Runtime.getRuntime(); |
| | | |
| | | |
| | | // Determine the maximum memory usage as a percentage of the total JVM |
| | | // memory. |
| | | maxMemoryPercent = DEFAULT_FIFOCACHE_MAX_MEMORY_PCT; |
| | | int msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_MEMORY_PCT; |
| | | IntegerConfigAttribute maxMemoryPctStub = |
| | | new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_MEMORY_PCT, |
| | | getMessage(msgID), true, false, false, true, |
| | | 1, true, 100); |
| | | try |
| | | { |
| | | IntegerConfigAttribute maxMemoryPctAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(maxMemoryPctStub); |
| | | if (maxMemoryPctAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | maxMemoryPercent = maxMemoryPctAttr.activeIntValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // Log an error message. |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_FIFOCACHE_CANNOT_DETERMINE_MAX_MEMORY_PCT, |
| | | String.valueOf(configEntryDN), getExceptionMessage(e), |
| | | maxMemoryPercent); |
| | | } |
| | | |
| | | maxAllowedMemory = runtime.maxMemory() / 100 * maxMemoryPercent; |
| | | |
| | | |
| | | // Determine the maximum number of entries that we will allow in the cache. |
| | | maxEntries = DEFAULT_FIFOCACHE_MAX_ENTRIES; |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_ENTRIES; |
| | | IntegerConfigAttribute maxEntriesStub = |
| | | new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_ENTRIES, |
| | | getMessage(msgID), true, false, false, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerConfigAttribute maxEntriesAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(maxEntriesStub); |
| | | if (maxEntriesAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | maxEntries = maxEntriesAttr.activeValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // Log an error message. |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_FIFOCACHE_CANNOT_DETERMINE_MAX_ENTRIES, |
| | | String.valueOf(configEntryDN), getExceptionMessage(e)); |
| | | } |
| | | |
| | | |
| | | // Determine the lock timeout to use when interacting with the lock manager. |
| | | lockTimeout = DEFAULT_FIFOCACHE_LOCK_TIMEOUT; |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_LOCK_TIMEOUT; |
| | | IntegerWithUnitConfigAttribute lockTimeoutStub = |
| | | new IntegerWithUnitConfigAttribute(ATTR_FIFOCACHE_LOCK_TIMEOUT, |
| | | getMessage(msgID), false, timeUnits, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerWithUnitConfigAttribute lockTimeoutAttr = |
| | | (IntegerWithUnitConfigAttribute) |
| | | configEntry.getConfigAttribute(lockTimeoutStub); |
| | | if (lockTimeoutAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | lockTimeout = lockTimeoutAttr.activeCalculatedValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // Log an error message. |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_FIFOCACHE_CANNOT_DETERMINE_LOCK_TIMEOUT, |
| | | String.valueOf(configEntryDN), getExceptionMessage(e), |
| | | lockTimeout); |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be included in the cache. |
| | | includeFilters = new HashSet<SearchFilter>(); |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_INCLUDE_FILTERS; |
| | | StringConfigAttribute includeStub = |
| | | new StringConfigAttribute(ATTR_FIFOCACHE_INCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute includeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(includeStub); |
| | | if (includeAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | List<String> filterStrings = includeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no include filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | includeFilters.add( |
| | | SearchFilter.createFilterFromString(filterString)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter. Log a warning and continue. |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, |
| | | MSGID_FIFOCACHE_CANNOT_DECODE_INCLUDE_FILTER, |
| | | String.valueOf(configEntryDN), filterString, |
| | | getExceptionMessage(e)); |
| | | } |
| | | } |
| | | |
| | | if (includeFilters.isEmpty()) |
| | | { |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_FIFOCACHE_CANNOT_DECODE_ANY_INCLUDE_FILTERS, |
| | | String.valueOf(configEntryDN)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // Log an error message. |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_FIFOCACHE_CANNOT_DETERMINE_INCLUDE_FILTERS, |
| | | String.valueOf(configEntryDN), getExceptionMessage(e)); |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be excluded from the cache. |
| | | excludeFilters = new HashSet<SearchFilter>(); |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_EXCLUDE_FILTERS; |
| | | StringConfigAttribute excludeStub = |
| | | new StringConfigAttribute(ATTR_FIFOCACHE_EXCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute excludeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub); |
| | | if (excludeAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | List<String> filterStrings = excludeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no exclude filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | excludeFilters.add( |
| | | SearchFilter.createFilterFromString(filterString)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter. Log a warning and continue. |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, |
| | | MSGID_FIFOCACHE_CANNOT_DECODE_EXCLUDE_FILTER, |
| | | String.valueOf(configEntryDN), filterString, |
| | | getExceptionMessage(e)); |
| | | } |
| | | } |
| | | |
| | | if (excludeFilters.isEmpty()) |
| | | { |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_FIFOCACHE_CANNOT_DECODE_ANY_EXCLUDE_FILTERS, |
| | | String.valueOf(configEntryDN)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // Log an error message. |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_FIFOCACHE_CANNOT_DETERMINE_EXCLUDE_FILTERS, |
| | | String.valueOf(configEntryDN), getExceptionMessage(e)); |
| | | } |
| | | // Read configuration and apply changes. |
| | | boolean applyChanges = true; |
| | | EntryCacheCommon.ConfigErrorHandler errorHandler = |
| | | EntryCacheCommon.getConfigErrorHandler ( |
| | | EntryCacheCommon.ConfigPhase.PHASE_INIT, null, null |
| | | ); |
| | | processEntryCacheConfig (configuration, applyChanges, errorHandler); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs any necessary cleanup work (e.g., flushing all cached entries and |
| | | * releasing any other held resources) that should be performed when the |
| | | * server is to be shut down or the entry cache destroyed or replaced. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void finalizeEntryCache() |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the entry cache currently contains the entry with the |
| | | * specified DN. This method may be called without holding any locks if a |
| | | * point-in-time check is all that is required. |
| | | * |
| | | * @param entryDN The DN for which to make the determination. |
| | | * |
| | | * @return <CODE>true</CODE> if the entry cache currently contains the entry |
| | | * with the specified DN, or <CODE>false</CODE> if not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean containsEntry(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the entry with the specified DN from the cache. The caller |
| | | * should have already acquired a read or write lock for the entry if such |
| | | * protection is needed. |
| | | * |
| | | * @param entryDN The DN of the entry to retrieve. |
| | | * |
| | | * @return The requested entry if it is present in the cache, or |
| | | * <CODE>null</CODE> if it is not present. |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry getEntry(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the entry ID for the entry with the specified DN from the cache. |
| | | * The caller should have already acquired a read or write lock for the entry |
| | | * if such protection is needed. |
| | | * |
| | | * @param entryDN The DN of the entry for which to retrieve the entry ID. |
| | | * |
| | | * @return The entry ID for the requested entry, or -1 if it is not present |
| | | * in the cache. |
| | | * {@inheritDoc} |
| | | */ |
| | | public long getEntryID(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the entry with the specified DN from the cache, obtaining a lock |
| | | * on the entry before it is returned. If the entry is present in the cache, |
| | | * then a lock will be obtained for that entry and appended to the provided |
| | | * list before the entry is returned. If the entry is not present, then no |
| | | * lock will be obtained. |
| | | * |
| | | * @param entryDN The DN of the entry to retrieve. |
| | | * @param lockType The type of lock to obtain (it may be <CODE>NONE</CODE>). |
| | | * @param lockList The list to which the obtained lock will be added (note |
| | | * that no lock will be added if the lock type was |
| | | * <CODE>NONE</CODE>). |
| | | * |
| | | * @return The requested entry if it is present in the cache, or |
| | | * <CODE>null</CODE> if it is not present. |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry getEntry(DN entryDN, LockType lockType, List<Lock> lockList) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the requested entry if it is present in the cache, obtaining a |
| | | * lock on the entry before it is returned. If the entry is present in the |
| | | * cache, then a lock will be obtained for that entry and appended to the |
| | | * provided list before the entry is returned. If the entry is not present, |
| | | * then no lock will be obtained. |
| | | * |
| | | * @param backend The backend associated with the entry to retrieve. |
| | | * @param entryID The entry ID within the provided backend for the |
| | | * specified entry. |
| | | * @param lockType The type of lock to obtain (it may be <CODE>NONE</CODE>). |
| | | * @param lockList The list to which the obtained lock will be added (note |
| | | * that no lock will be added if the lock type was |
| | | * <CODE>NONE</CODE>). |
| | | * |
| | | * @return The requested entry if it is present in the cache, or |
| | | * <CODE>null</CODE> if it is not present. |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry getEntry(Backend backend, long entryID, LockType lockType, |
| | | List<Lock> lockList) |
| | |
| | | |
| | | |
| | | /** |
| | | * Stores the provided entry in the cache. Note that the mechanism that it |
| | | * uses to achieve this is implementation-dependent, and it is acceptable for |
| | | * the entry to not actually be stored in any cache. |
| | | * |
| | | * @param entry The entry to store in the cache. |
| | | * @param backend The backend with which the entry is associated. |
| | | * @param entryID The entry ID within the provided backend that uniquely |
| | | * identifies the specified entry. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void putEntry(Entry entry, Backend backend, long entryID) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Stores the provided entry in the cache only if it does not conflict with an |
| | | * entry that already exists. Note that the mechanism that it uses to achieve |
| | | * this is implementation-dependent, and it is acceptable for the entry to not |
| | | * actually be stored in any cache. However, this method must not overwrite |
| | | * an existing version of the entry. |
| | | * |
| | | * @param entry The entry to store in the cache. |
| | | * @param backend The backend with which the entry is associated. |
| | | * @param entryID The entry ID within the provided backend that uniquely |
| | | * identifies the specified entry. |
| | | * |
| | | * @return <CODE>false</CODE> if an existing entry or some other problem |
| | | * prevented the method from completing successfully, or |
| | | * <CODE>true</CODE> if there was no conflict and the entry was |
| | | * either stored or the cache determined that this entry should never |
| | | * be cached for some reason. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean putEntryIfAbsent(Entry entry, Backend backend, long entryID) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes the specified entry from the cache. |
| | | * |
| | | * @param entryDN The DN of the entry to remove from the cache. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void removeEntry(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes all entries from the cache. The cache should still be available |
| | | * for future use. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void clear() |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes all entries from the cache that are associated with the provided |
| | | * backend. |
| | | * |
| | | * @param backend The backend for which to flush the associated entries. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void clearBackend(Backend backend) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes all entries from the cache that are below the provided DN. |
| | | * |
| | | * @param baseDN The base DN below which all entries should be flushed. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void clearSubtree(DN baseDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Clears all entries at or below the specified base DN that are associated |
| | | * with the given backend. The caller must already hold the cache lock. |
| | | * |
| | | * @param baseDN The base DN below which all entries should be flushed. |
| | | * @param backend The backend for which to remove the appropriate entries. |
| | | * {@inheritDoc} |
| | | */ |
| | | private void clearSubtree(DN baseDN, Backend backend) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Attempts to react to a scenario in which it is determined that the system |
| | | * is running low on available memory. In this case, the entry cache should |
| | | * attempt to free some memory if possible to try to avoid out of memory |
| | | * errors. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void handleLowMemory() |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an acceptable |
| | | * configuration for this component. If it does not, then detailed |
| | | * information about the problem(s) should be added to the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to make the |
| | | * determination. |
| | | * @param unacceptableReasons A list that can be used to hold messages about |
| | | * why the provided entry does not have an |
| | | * acceptable configuration. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided entry has an acceptable |
| | | * configuration for this component, or <CODE>false</CODE> if not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | List<String> unacceptableReasons) |
| | | public boolean isConfigurationChangeAcceptable( |
| | | FIFOEntryCacheCfg configuration, |
| | | List<String> unacceptableReasons |
| | | ) |
| | | { |
| | | // Start out assuming that the configuration is valid. |
| | | boolean configIsAcceptable = true; |
| | | // Make sure that we can process the defined character sets. If so, then |
| | | // we'll accept the new configuration. |
| | | boolean applyChanges = false; |
| | | EntryCacheCommon.ConfigErrorHandler errorHandler = |
| | | EntryCacheCommon.getConfigErrorHandler ( |
| | | EntryCacheCommon.ConfigPhase.PHASE_ACCEPTABLE, |
| | | unacceptableReasons, |
| | | null |
| | | ); |
| | | processEntryCacheConfig (configuration, applyChanges, errorHandler); |
| | | |
| | | return errorHandler.getIsAcceptable(); |
| | | } |
| | | |
| | | |
| | | // Determine the maximum memory usage as a percentage of the total JVM |
| | | // memory. |
| | | int msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_MEMORY_PCT; |
| | | IntegerConfigAttribute maxMemoryPctStub = |
| | | new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_MEMORY_PCT, |
| | | getMessage(msgID), true, false, false, true, |
| | | 1, true, 100); |
| | | try |
| | | { |
| | | IntegerConfigAttribute maxMemoryPctAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(maxMemoryPctStub); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_MAX_MEMORY_PCT; |
| | | unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | FIFOEntryCacheCfg configuration |
| | | ) |
| | | { |
| | | // Make sure that we can process the defined character sets. If so, then |
| | | // activate the new configuration. |
| | | boolean applyChanges = false; |
| | | ArrayList<String> errorMessages = new ArrayList<String>(); |
| | | EntryCacheCommon.ConfigErrorHandler errorHandler = |
| | | EntryCacheCommon.getConfigErrorHandler ( |
| | | EntryCacheCommon.ConfigPhase.PHASE_APPLY, null, errorMessages |
| | | ); |
| | | processEntryCacheConfig (configuration, applyChanges, errorHandler); |
| | | |
| | | |
| | | // Determine the maximum number of entries that we will allow in the cache. |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_ENTRIES; |
| | | IntegerConfigAttribute maxEntriesStub = |
| | | new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_ENTRIES, |
| | | getMessage(msgID), true, false, false, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerConfigAttribute maxEntriesAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(maxEntriesStub); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | boolean adminActionRequired = false; |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | errorHandler.getResultCode(), |
| | | adminActionRequired, |
| | | errorHandler.getErrorMessages() |
| | | ); |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_MAX_ENTRIES; |
| | | unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Determine the lock timeout to use when interacting with the lock manager. |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_LOCK_TIMEOUT; |
| | | IntegerWithUnitConfigAttribute lockTimeoutStub = |
| | | new IntegerWithUnitConfigAttribute(ATTR_FIFOCACHE_LOCK_TIMEOUT, |
| | | getMessage(msgID), false, timeUnits, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerWithUnitConfigAttribute lockTimeoutAttr = |
| | | (IntegerWithUnitConfigAttribute) |
| | | configEntry.getConfigAttribute(lockTimeoutStub); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_LOCK_TIMEOUT; |
| | | unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be included in the cache. |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_INCLUDE_FILTERS; |
| | | StringConfigAttribute includeStub = |
| | | new StringConfigAttribute(ATTR_FIFOCACHE_INCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute includeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(includeStub); |
| | | if (includeAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | List<String> filterStrings = includeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no include filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | SearchFilter.createFilterFromString(filterString); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter, so it isn't valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_INCLUDE_FILTER; |
| | | unacceptableReasons.add(getMessage(msgID, |
| | | String.valueOf(configEntryDN), |
| | | filterString, |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_INCLUDE_FILTERS; |
| | | unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be excluded from the cache. |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_EXCLUDE_FILTERS; |
| | | StringConfigAttribute excludeStub = |
| | | new StringConfigAttribute(ATTR_FIFOCACHE_EXCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute excludeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub); |
| | | if (excludeAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | List<String> filterStrings = excludeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no exclude filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | SearchFilter.createFilterFromString(filterString); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter, so it isn't valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_EXCLUDE_FILTER; |
| | | unacceptableReasons.add(getMessage(msgID, |
| | | String.valueOf(configEntryDN), |
| | | filterString, |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_EXCLUDE_FILTERS; |
| | | unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | return configIsAcceptable; |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | |
| | | * successfully (and optionally about parameters that were not changed) should |
| | | * also be included. |
| | | * |
| | | * @param configEntry The entry containing the new configuration to |
| | | * @param configuration The entry containing the new configuration to |
| | | * apply for this component. |
| | | * @param detailedResults Indicates whether detailed information about the |
| | | * processing should be added to the list. |
| | | * |
| | | * @return Information about the result of the configuration update. |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | public ConfigChangeResult applyNewConfiguration( |
| | | FIFOEntryCacheCfg configuration, |
| | | boolean detailedResults |
| | | ) |
| | | { |
| | | // Create a set of variables to use for the result. |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | boolean configIsAcceptable = true; |
| | | // Store the current value to detect changes. |
| | | long prevLockTimeout = lockTimeout; |
| | | long prevMaxEntries = maxEntries; |
| | | int prevMaxMemoryPercent = maxMemoryPercent; |
| | | HashSet<SearchFilter> prevIncludeFilters = includeFilters; |
| | | HashSet<SearchFilter> prevExcludeFilters = excludeFilters; |
| | | |
| | | // Activate the new configuration. |
| | | ConfigChangeResult changeResult = applyConfigurationChange(configuration); |
| | | |
| | | // Determine the maximum memory usage as a percentage of the total JVM |
| | | // memory. |
| | | int newMaxMemoryPercent = DEFAULT_FIFOCACHE_MAX_MEMORY_PCT; |
| | | int msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_MEMORY_PCT; |
| | | IntegerConfigAttribute maxMemoryPctStub = |
| | | new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_MEMORY_PCT, |
| | | getMessage(msgID), true, false, false, true, |
| | | 1, true, 100); |
| | | try |
| | | // Add detailed messages if needed. |
| | | ResultCode resultCode = changeResult.getResultCode(); |
| | | boolean configIsAcceptable = (resultCode == ResultCode.SUCCESS); |
| | | if (detailedResults && configIsAcceptable) |
| | | { |
| | | IntegerConfigAttribute maxMemoryPctAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(maxMemoryPctStub); |
| | | if (maxMemoryPctAttr != null) |
| | | if (maxMemoryPercent != prevMaxMemoryPercent) |
| | | { |
| | | newMaxMemoryPercent = maxMemoryPctAttr.pendingIntValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | changeResult.addMessage( |
| | | getMessage( |
| | | MSGID_FIFOCACHE_UPDATED_MAX_MEMORY_PCT, |
| | | maxMemoryPercent, |
| | | maxAllowedMemory)); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_MAX_MEMORY_PCT; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Determine the maximum number of entries that we will allow in the cache. |
| | | long newMaxEntries = DEFAULT_FIFOCACHE_MAX_ENTRIES; |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_MAX_ENTRIES; |
| | | IntegerConfigAttribute maxEntriesStub = |
| | | new IntegerConfigAttribute(ATTR_FIFOCACHE_MAX_ENTRIES, |
| | | getMessage(msgID), true, false, false, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerConfigAttribute maxEntriesAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(maxEntriesStub); |
| | | if (maxEntriesAttr != null) |
| | | if (maxEntries != prevMaxEntries) |
| | | { |
| | | newMaxEntries = maxEntriesAttr.pendingValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | changeResult.addMessage( |
| | | getMessage (MSGID_FIFOCACHE_UPDATED_MAX_ENTRIES, maxEntries)); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_MAX_ENTRIES; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | if (lockTimeout != prevLockTimeout) |
| | | { |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | | changeResult.addMessage( |
| | | getMessage (MSGID_FIFOCACHE_UPDATED_LOCK_TIMEOUT, lockTimeout)); |
| | | } |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Determine the lock timeout to use when interacting with the lock manager. |
| | | long newLockTimeout = DEFAULT_FIFOCACHE_LOCK_TIMEOUT; |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_LOCK_TIMEOUT; |
| | | IntegerWithUnitConfigAttribute lockTimeoutStub = |
| | | new IntegerWithUnitConfigAttribute(ATTR_FIFOCACHE_LOCK_TIMEOUT, |
| | | getMessage(msgID), false, timeUnits, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerWithUnitConfigAttribute lockTimeoutAttr = |
| | | (IntegerWithUnitConfigAttribute) |
| | | configEntry.getConfigAttribute(lockTimeoutStub); |
| | | if (lockTimeoutAttr != null) |
| | | if (!includeFilters.equals(prevIncludeFilters)) |
| | | { |
| | | newLockTimeout = lockTimeoutAttr.pendingCalculatedValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | changeResult.addMessage( |
| | | getMessage (MSGID_FIFOCACHE_UPDATED_INCLUDE_FILTERS)); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_LOCK_TIMEOUT; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | if (!excludeFilters.equals(prevExcludeFilters)) |
| | | { |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | | } |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be included in the cache. |
| | | HashSet<SearchFilter> newIncludeFilters = new HashSet<SearchFilter>(); |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_INCLUDE_FILTERS; |
| | | StringConfigAttribute includeStub = |
| | | new StringConfigAttribute(ATTR_FIFOCACHE_INCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute includeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(includeStub); |
| | | if (includeAttr != null) |
| | | { |
| | | List<String> filterStrings = includeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no include filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | newIncludeFilters.add( |
| | | SearchFilter.createFilterFromString(filterString)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter, so it isn't valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_INCLUDE_FILTER; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | filterString, |
| | | getExceptionMessage(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | } |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_INCLUDE_FILTERS; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | | } |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be exclude from the cache. |
| | | HashSet<SearchFilter> newExcludeFilters = new HashSet<SearchFilter>(); |
| | | msgID = MSGID_FIFOCACHE_DESCRIPTION_EXCLUDE_FILTERS; |
| | | StringConfigAttribute excludeStub = |
| | | new StringConfigAttribute(ATTR_FIFOCACHE_EXCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute excludeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub); |
| | | if (excludeAttr != null) |
| | | { |
| | | List<String> filterStrings = excludeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no exclude filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | newExcludeFilters.add( |
| | | SearchFilter.createFilterFromString(filterString)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter, so it isn't valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_EXCLUDE_FILTER; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | filterString, getExceptionMessage(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | } |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_FIFOCACHE_INVALID_EXCLUDE_FILTERS; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | | } |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | if (configIsAcceptable) |
| | | { |
| | | if (maxMemoryPercent != newMaxMemoryPercent) |
| | | { |
| | | maxMemoryPercent = newMaxMemoryPercent; |
| | | maxAllowedMemory = runtime.maxMemory() / 100 * maxMemoryPercent; |
| | | |
| | | if (detailedResults) |
| | | { |
| | | messages.add(getMessage(MSGID_FIFOCACHE_UPDATED_MAX_MEMORY_PCT, |
| | | maxMemoryPercent, maxAllowedMemory)); |
| | | } |
| | | } |
| | | |
| | | if (maxEntries != newMaxEntries) |
| | | { |
| | | maxEntries = newMaxEntries; |
| | | |
| | | if (detailedResults) |
| | | { |
| | | messages.add(getMessage(MSGID_FIFOCACHE_UPDATED_MAX_ENTRIES, |
| | | maxEntries)); |
| | | } |
| | | } |
| | | |
| | | if (lockTimeout != newLockTimeout) |
| | | { |
| | | lockTimeout = newLockTimeout; |
| | | |
| | | if (detailedResults) |
| | | { |
| | | messages.add(getMessage(MSGID_FIFOCACHE_UPDATED_LOCK_TIMEOUT, |
| | | lockTimeout)); |
| | | } |
| | | } |
| | | |
| | | if (!includeFilters.equals(newIncludeFilters)) |
| | | { |
| | | includeFilters = newIncludeFilters; |
| | | |
| | | if (detailedResults) |
| | | { |
| | | messages.add(getMessage(MSGID_FIFOCACHE_UPDATED_INCLUDE_FILTERS)); |
| | | } |
| | | } |
| | | |
| | | if (!excludeFilters.equals(newExcludeFilters)) |
| | | { |
| | | excludeFilters = newExcludeFilters; |
| | | |
| | | if (detailedResults) |
| | | { |
| | | messages.add(getMessage(MSGID_FIFOCACHE_UPDATED_EXCLUDE_FILTERS)); |
| | | } |
| | | changeResult.addMessage( |
| | | getMessage (MSGID_FIFOCACHE_UPDATED_EXCLUDE_FILTERS)); |
| | | } |
| | | } |
| | | |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parses the provided configuration and configure the entry cache. |
| | | * |
| | | * @param configuration The new configuration containing the changes. |
| | | * @param applyChanges If true then take into account the new configuration. |
| | | * @param errorHandler An handler used to report errors. |
| | | * |
| | | * @return The mapping between strings of character set values and the |
| | | * minimum number of characters required from those sets. |
| | | */ |
| | | public boolean processEntryCacheConfig( |
| | | FIFOEntryCacheCfg configuration, |
| | | boolean applyChanges, |
| | | EntryCacheCommon.ConfigErrorHandler errorHandler |
| | | ) |
| | | { |
| | | // Local variables to read configuration. |
| | | DN newConfigEntryDN; |
| | | long newLockTimeout; |
| | | long newMaxEntries; |
| | | int newMaxMemoryPercent; |
| | | long newMaxAllowedMemory; |
| | | HashSet<SearchFilter> newIncludeFilters = null; |
| | | HashSet<SearchFilter> newExcludeFilters = null; |
| | | |
| | | // Read configuration. |
| | | newConfigEntryDN = configuration.dn(); |
| | | newLockTimeout = configuration.getLockTimeout(); |
| | | newMaxEntries = configuration.getMaxEntries(); |
| | | |
| | | // Maximum memory the cache can use. |
| | | newMaxMemoryPercent = (int) configuration.getMaxMemoryPercent(); |
| | | long maxJvmHeapSize = Runtime.getRuntime().maxMemory(); |
| | | newMaxAllowedMemory = (maxJvmHeapSize / 100) * newMaxMemoryPercent; |
| | | |
| | | // Get include and exclude filters. |
| | | switch (errorHandler.getConfigPhase()) |
| | | { |
| | | case PHASE_INIT: |
| | | newIncludeFilters = EntryCacheCommon.getFilters ( |
| | | configuration.getIncludeFilter(), |
| | | MSGID_FIFOCACHE_INVALID_INCLUDE_FILTER, |
| | | MSGID_FIFOCACHE_CANNOT_DECODE_ANY_INCLUDE_FILTERS, |
| | | errorHandler, |
| | | configEntryDN |
| | | ); |
| | | newExcludeFilters = EntryCacheCommon.getFilters ( |
| | | configuration.getExcludeFilter(), |
| | | MSGID_FIFOCACHE_CANNOT_DECODE_EXCLUDE_FILTER, |
| | | MSGID_FIFOCACHE_CANNOT_DECODE_ANY_EXCLUDE_FILTERS, |
| | | errorHandler, |
| | | configEntryDN |
| | | ); |
| | | break; |
| | | case PHASE_ACCEPTABLE: // acceptable and apply are using the same |
| | | case PHASE_APPLY: // error ID codes |
| | | newIncludeFilters = EntryCacheCommon.getFilters ( |
| | | configuration.getIncludeFilter(), |
| | | MSGID_FIFOCACHE_INVALID_INCLUDE_FILTER, |
| | | 0, |
| | | errorHandler, |
| | | configEntryDN |
| | | ); |
| | | newExcludeFilters = EntryCacheCommon.getFilters ( |
| | | configuration.getExcludeFilter(), |
| | | MSGID_FIFOCACHE_INVALID_EXCLUDE_FILTER, |
| | | 0, |
| | | errorHandler, |
| | | configEntryDN |
| | | ); |
| | | break; |
| | | } |
| | | |
| | | if (applyChanges && errorHandler.getIsAcceptable()) |
| | | { |
| | | configEntryDN = newConfigEntryDN; |
| | | lockTimeout = newLockTimeout; |
| | | maxEntries = newMaxEntries; |
| | | maxMemoryPercent = newMaxMemoryPercent; |
| | | maxAllowedMemory = newMaxAllowedMemory; |
| | | includeFilters = newIncludeFilters; |
| | | excludeFilters = newExcludeFilters; |
| | | } |
| | | |
| | | return errorHandler.getIsAcceptable(); |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | import java.util.Arrays; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.ByteString; |
| | |
| | | * vulnerable to dictionary attacks than salted variants. |
| | | */ |
| | | public class MD5PasswordStorageScheme |
| | | extends PasswordStorageScheme |
| | | extends PasswordStorageScheme <PasswordStorageSchemeCfg> |
| | | { |
| | | /** |
| | | * The fully-qualified name of this class. |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordStorageScheme(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializePasswordStorageScheme( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | try |
| | | { |
| | |
| | | import java.util.Arrays; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.ByteString; |
| | |
| | | * vulnerable to dictionary attacks than salted variants. |
| | | */ |
| | | public class SHA1PasswordStorageScheme |
| | | extends PasswordStorageScheme |
| | | extends PasswordStorageScheme <PasswordStorageSchemeCfg> |
| | | { |
| | | /** |
| | | * The fully-qualified name of this class. |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordStorageScheme(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializePasswordStorageScheme( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | try |
| | | { |
| | |
| | | import java.util.Arrays; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.ByteString; |
| | |
| | | * appended to the hash, and then the entire value is base64-encoded. |
| | | */ |
| | | public class SaltedMD5PasswordStorageScheme |
| | | extends PasswordStorageScheme |
| | | extends PasswordStorageScheme <PasswordStorageSchemeCfg> |
| | | { |
| | | /** |
| | | * The fully-qualified name of this class. |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordStorageScheme(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializePasswordStorageScheme( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | try |
| | | { |
| | |
| | | import java.util.Arrays; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.ByteString; |
| | |
| | | * appended to the hash, and then the entire value is base64-encoded. |
| | | */ |
| | | public class SaltedSHA1PasswordStorageScheme |
| | | extends PasswordStorageScheme |
| | | extends PasswordStorageScheme <PasswordStorageSchemeCfg> |
| | | { |
| | | /** |
| | | * The fully-qualified name of this class. |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordStorageScheme(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializePasswordStorageScheme( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | try |
| | | { |
| | |
| | | import java.util.Arrays; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.ByteString; |
| | |
| | | * is appended to the hash, and then the entire value is base64-encoded. |
| | | */ |
| | | public class SaltedSHA256PasswordStorageScheme |
| | | extends PasswordStorageScheme |
| | | extends PasswordStorageScheme <PasswordStorageSchemeCfg> |
| | | { |
| | | /** |
| | | * The fully-qualified name of this class. |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordStorageScheme(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializePasswordStorageScheme( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | try |
| | | { |
| | |
| | | import java.util.Arrays; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.ByteString; |
| | |
| | | * is appended to the hash, and then the entire value is base64-encoded. |
| | | */ |
| | | public class SaltedSHA384PasswordStorageScheme |
| | | extends PasswordStorageScheme |
| | | extends PasswordStorageScheme <PasswordStorageSchemeCfg> |
| | | { |
| | | /** |
| | | * The fully-qualified name of this class. |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordStorageScheme(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializePasswordStorageScheme( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | try |
| | | { |
| | |
| | | import java.util.Arrays; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.ByteString; |
| | |
| | | * is appended to the hash, and then the entire value is base64-encoded. |
| | | */ |
| | | public class SaltedSHA512PasswordStorageScheme |
| | | extends PasswordStorageScheme |
| | | extends PasswordStorageScheme <PasswordStorageSchemeCfg> |
| | | { |
| | | /** |
| | | * The fully-qualified name of this class. |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordStorageScheme(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializePasswordStorageScheme( |
| | | PasswordStorageSchemeCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | try |
| | | { |
| | |
| | | import java.util.concurrent.locks.Lock; |
| | | |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.api.EntryCache; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.server.SoftReferenceEntryCacheCfg; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.IntegerWithUnitConfigAttribute; |
| | | import org.opends.server.config.StringConfigAttribute; |
| | |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.ErrorLogCategory; |
| | | import org.opends.server.types.ErrorLogSeverity; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.LockManager; |
| | | import org.opends.server.types.LockType; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchFilter; |
| | | |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import static org.opends.server.loggers.Error.*; |
| | | import static org.opends.server.messages.ExtensionsMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | |
| | | * running low on memory. |
| | | */ |
| | | public class SoftReferenceEntryCache |
| | | extends EntryCache |
| | | implements ConfigurableComponent, Runnable |
| | | extends EntryCache <SoftReferenceEntryCacheCfg> |
| | | implements |
| | | ConfigurationChangeListener<SoftReferenceEntryCacheCfg>, |
| | | Runnable |
| | | { |
| | | |
| | | |
| | | |
| | | /** |
| | | * The set of time units that will be used for expressing the task retention |
| | | * time. |
| | | */ |
| | | // The set of time units that will be used for expressing the task retention |
| | | // time. |
| | | private static final LinkedHashMap<String,Double> timeUnits = |
| | | new LinkedHashMap<String,Double>(); |
| | | |
| | | |
| | | |
| | | // The mapping between entry DNs and their corresponding entries. |
| | | private ConcurrentHashMap<DN,SoftReference<CacheEntry>> dnMap; |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Initializes this entry cache implementation so that it will be available |
| | | * for storing and retrieving entries. |
| | | * |
| | | * @param configEntry The configuration entry containing the settings to use |
| | | * for this entry cache. |
| | | * |
| | | * @throws ConfigException If there is a problem with the provided |
| | | * configuration entry that would prevent this |
| | | * entry cache from being used. |
| | | * |
| | | * @throws InitializationException If a problem occurs during the |
| | | * initialization process that is not |
| | | * related to the configuration. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void initializeEntryCache(ConfigEntry configEntry) |
| | | throws ConfigException, InitializationException |
| | | public void initializeEntryCache( |
| | | SoftReferenceEntryCacheCfg configuration |
| | | ) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | configuration.addSoftReferenceChangeListener (this); |
| | | configEntryDN = configuration.dn(); |
| | | |
| | | dnMap.clear(); |
| | | idMap.clear(); |
| | | |
| | | |
| | | configEntryDN = configEntry.getDN(); |
| | | |
| | | |
| | | // Determine the lock timeout to use when interacting with the lock manager. |
| | | int msgID = MSGID_SOFTREFCACHE_DESCRIPTION_LOCK_TIMEOUT; |
| | | IntegerWithUnitConfigAttribute lockTimeoutStub = |
| | | new IntegerWithUnitConfigAttribute(ATTR_SOFTREFCACHE_LOCK_TIMEOUT, |
| | | getMessage(msgID), false, timeUnits, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerWithUnitConfigAttribute lockTimeoutAttr = |
| | | (IntegerWithUnitConfigAttribute) |
| | | configEntry.getConfigAttribute(lockTimeoutStub); |
| | | if (lockTimeoutAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | lockTimeout = lockTimeoutAttr.activeCalculatedValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // Log an error message. |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_SOFTREFCACHE_CANNOT_DETERMINE_LOCK_TIMEOUT, |
| | | String.valueOf(configEntryDN), getExceptionMessage(e), |
| | | lockTimeout); |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be included in the cache. |
| | | includeFilters = new HashSet<SearchFilter>(); |
| | | msgID = MSGID_SOFTREFCACHE_DESCRIPTION_INCLUDE_FILTERS; |
| | | StringConfigAttribute includeStub = |
| | | new StringConfigAttribute(ATTR_SOFTREFCACHE_INCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute includeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(includeStub); |
| | | if (includeAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | List<String> filterStrings = includeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no include filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | includeFilters.add( |
| | | SearchFilter.createFilterFromString(filterString)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter. Log a warning and continue. |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, |
| | | MSGID_SOFTREFCACHE_CANNOT_DECODE_INCLUDE_FILTER, |
| | | String.valueOf(configEntryDN), filterString, |
| | | getExceptionMessage(e)); |
| | | } |
| | | } |
| | | |
| | | if (includeFilters.isEmpty()) |
| | | { |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_SOFTREFCACHE_CANNOT_DECODE_ANY_INCLUDE_FILTERS, |
| | | String.valueOf(configEntryDN)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // Log an error message. |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_SOFTREFCACHE_CANNOT_DETERMINE_INCLUDE_FILTERS, |
| | | String.valueOf(configEntryDN), getExceptionMessage(e)); |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be excluded from the cache. |
| | | excludeFilters = new HashSet<SearchFilter>(); |
| | | msgID = MSGID_SOFTREFCACHE_DESCRIPTION_EXCLUDE_FILTERS; |
| | | StringConfigAttribute excludeStub = |
| | | new StringConfigAttribute(ATTR_SOFTREFCACHE_EXCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute excludeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub); |
| | | if (excludeAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | List<String> filterStrings = excludeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no exclude filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | excludeFilters.add( |
| | | SearchFilter.createFilterFromString(filterString)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter. Log a warning and continue. |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_WARNING, |
| | | MSGID_SOFTREFCACHE_CANNOT_DECODE_EXCLUDE_FILTER, |
| | | String.valueOf(configEntryDN), filterString, |
| | | getExceptionMessage(e)); |
| | | } |
| | | } |
| | | |
| | | if (excludeFilters.isEmpty()) |
| | | { |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_SOFTREFCACHE_CANNOT_DECODE_ANY_EXCLUDE_FILTERS, |
| | | String.valueOf(configEntryDN)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // Log an error message. |
| | | logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR, |
| | | MSGID_SOFTREFCACHE_CANNOT_DETERMINE_EXCLUDE_FILTERS, |
| | | String.valueOf(configEntryDN), getExceptionMessage(e)); |
| | | } |
| | | // Read configuration and apply changes. |
| | | boolean applyChanges = true; |
| | | EntryCacheCommon.ConfigErrorHandler errorHandler = |
| | | EntryCacheCommon.getConfigErrorHandler ( |
| | | EntryCacheCommon.ConfigPhase.PHASE_INIT, null, null |
| | | ); |
| | | processEntryCacheConfig (configuration, applyChanges, errorHandler); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs any necessary cleanup work (e.g., flushing all cached entries and |
| | | * releasing any other held resources) that should be performed when the |
| | | * server is to be shut down or the entry cache destroyed or replaced. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void finalizeEntryCache() |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the entry cache currently contains the entry with the |
| | | * specified DN. This method may be called without holding any locks if a |
| | | * point-in-time check is all that is required. |
| | | * |
| | | * @param entryDN The DN for which to make the determination. |
| | | * |
| | | * @return <CODE>true</CODE> if the entry cache currently contains the entry |
| | | * with the specified DN, or <CODE>false</CODE> if not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean containsEntry(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the entry with the specified DN from the cache. The caller |
| | | * should have already acquired a read or write lock for the entry if such |
| | | * protection is needed. |
| | | * |
| | | * @param entryDN The DN of the entry to retrieve. |
| | | * |
| | | * @return The requested entry if it is present in the cache, or |
| | | * <CODE>null</CODE> if it is not present. |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry getEntry(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the entry ID for the entry with the specified DN from the cache. |
| | | * The caller should have already acquired a read or write lock for the entry |
| | | * if such protection is needed. |
| | | * |
| | | * @param entryDN The DN of the entry for which to retrieve the entry ID. |
| | | * |
| | | * @return The entry ID for the requested entry, or -1 if it is not present |
| | | * in the cache. |
| | | * {@inheritDoc} |
| | | */ |
| | | public long getEntryID(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the entry with the specified DN from the cache, obtaining a lock |
| | | * on the entry before it is returned. If the entry is present in the cache, |
| | | * then a lock will be obtained for that entry and appended to the provided |
| | | * list before the entry is returned. If the entry is not present, then no |
| | | * lock will be obtained. |
| | | * |
| | | * @param entryDN The DN of the entry to retrieve. |
| | | * @param lockType The type of lock to obtain (it may be <CODE>NONE</CODE>). |
| | | * @param lockList The list to which the obtained lock will be added (note |
| | | * that no lock will be added if the lock type was |
| | | * <CODE>NONE</CODE>). |
| | | * |
| | | * @return The requested entry if it is present in the cache, or |
| | | * <CODE>null</CODE> if it is not present. |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry getEntry(DN entryDN, LockType lockType, |
| | | List<Lock> lockList) |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the requested entry if it is present in the cache, obtaining a |
| | | * lock on the entry before it is returned. If the entry is present in the |
| | | * cache, then a lock will be obtained for that entry and appended to the |
| | | * provided list before the entry is returned. If the entry is not present, |
| | | * then no lock will be obtained. |
| | | * |
| | | * @param backend The backend associated with the entry to retrieve. |
| | | * @param entryID The entry ID within the provided backend for the |
| | | * specified entry. |
| | | * @param lockType The type of lock to obtain (it may be <CODE>NONE</CODE>). |
| | | * @param lockList The list to which the obtained lock will be added (note |
| | | * that no lock will be added if the lock type was |
| | | * <CODE>NONE</CODE>). |
| | | * |
| | | * @return The requested entry if it is present in the cache, or |
| | | * <CODE>null</CODE> if it is not present. |
| | | * {@inheritDoc} |
| | | */ |
| | | public Entry getEntry(Backend backend, long entryID, |
| | | LockType lockType, List<Lock> lockList) |
| | |
| | | |
| | | |
| | | /** |
| | | * Stores the provided entry in the cache. Note that the mechanism that it |
| | | * uses to achieve this is implementation-dependent, and it is acceptable for |
| | | * the entry to not actually be stored in any cache. |
| | | * |
| | | * @param entry The entry to store in the cache. |
| | | * @param backend The backend with which the entry is associated. |
| | | * @param entryID The entry ID within the provided backend that uniquely |
| | | * identifies the specified entry. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void putEntry(Entry entry, Backend backend, long entryID) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Stores the provided entry in the cache only if it does not conflict with an |
| | | * entry that already exists. Note that the mechanism that it uses to achieve |
| | | * this is implementation-dependent, and it is acceptable for the entry to not |
| | | * actually be stored in any cache. However, this method must not overwrite |
| | | * an existing version of the entry. |
| | | * |
| | | * @param entry The entry to store in the cache. |
| | | * @param backend The backend with which the entry is associated. |
| | | * @param entryID The entry ID within the provided backend that uniquely |
| | | * identifies the specified entry. |
| | | * |
| | | * @return <CODE>false</CODE> if an existing entry or some other problem |
| | | * prevented the method from completing successfully, or |
| | | * <CODE>true</CODE> if there was no conflict and the entry was |
| | | * either stored or the cache determined that this entry should never |
| | | * be cached for some reason. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean putEntryIfAbsent(Entry entry, Backend backend, |
| | | long entryID) |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes the specified entry from the cache. |
| | | * |
| | | * @param entryDN The DN of the entry to remove from the cache. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void removeEntry(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes all entries from the cache. The cache should still be available |
| | | * for future use. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void clear() |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes all entries from the cache that are associated with the provided |
| | | * backend. |
| | | * |
| | | * @param backend The backend for which to flush the associated entries. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void clearBackend(Backend backend) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Removes all entries from the cache that are below the provided DN. |
| | | * |
| | | * @param baseDN The base DN below which all entries should be flushed. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void clearSubtree(DN baseDN) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Attempts to react to a scenario in which it is determined that the system |
| | | * is running low on available memory. In this case, the entry cache should |
| | | * attempt to free some memory if possible to try to avoid out of memory |
| | | * errors. |
| | | * {@inheritDoc} |
| | | */ |
| | | public void handleLowMemory() |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration entry has an acceptable |
| | | * configuration for this component. If it does not, then detailed |
| | | * information about the problem(s) should be added to the provided list. |
| | | * |
| | | * @param configEntry The configuration entry for which to make the |
| | | * determination. |
| | | * @param unacceptableReasons A list that can be used to hold messages about |
| | | * why the provided entry does not have an |
| | | * acceptable configuration. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided entry has an acceptable |
| | | * configuration for this component, or <CODE>false</CODE> if not. |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | List<String> unacceptableReasons) |
| | | public boolean isConfigurationChangeAcceptable( |
| | | SoftReferenceEntryCacheCfg configuration, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | // Start out assuming that the configuration is valid. |
| | | boolean configIsAcceptable = true; |
| | | // Make sure that we can process the defined character sets. If so, then |
| | | // we'll accept the new configuration. |
| | | boolean applyChanges = false; |
| | | EntryCacheCommon.ConfigErrorHandler errorHandler = |
| | | EntryCacheCommon.getConfigErrorHandler ( |
| | | EntryCacheCommon.ConfigPhase.PHASE_ACCEPTABLE, |
| | | unacceptableReasons, |
| | | null |
| | | ); |
| | | processEntryCacheConfig (configuration, applyChanges, errorHandler); |
| | | |
| | | |
| | | // Determine the lock timeout to use when interacting with the lock manager. |
| | | int msgID = MSGID_SOFTREFCACHE_DESCRIPTION_LOCK_TIMEOUT; |
| | | IntegerWithUnitConfigAttribute lockTimeoutStub = |
| | | new IntegerWithUnitConfigAttribute(ATTR_SOFTREFCACHE_LOCK_TIMEOUT, |
| | | getMessage(msgID), false, timeUnits, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerWithUnitConfigAttribute lockTimeoutAttr = |
| | | (IntegerWithUnitConfigAttribute) |
| | | configEntry.getConfigAttribute(lockTimeoutStub); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_SOFTREFCACHE_INVALID_LOCK_TIMEOUT; |
| | | unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be included in the cache. |
| | | msgID = MSGID_SOFTREFCACHE_DESCRIPTION_INCLUDE_FILTERS; |
| | | StringConfigAttribute includeStub = |
| | | new StringConfigAttribute(ATTR_SOFTREFCACHE_INCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute includeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(includeStub); |
| | | if (includeAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | List<String> filterStrings = includeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no include filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | SearchFilter.createFilterFromString(filterString); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter, so it isn't valid. |
| | | msgID = MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTER; |
| | | unacceptableReasons.add(getMessage(msgID, |
| | | String.valueOf(configEntryDN), |
| | | filterString, |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTERS; |
| | | unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be excluded from the cache. |
| | | msgID = MSGID_SOFTREFCACHE_DESCRIPTION_EXCLUDE_FILTERS; |
| | | StringConfigAttribute excludeStub = |
| | | new StringConfigAttribute(ATTR_SOFTREFCACHE_EXCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute excludeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub); |
| | | if (excludeAttr == null) |
| | | { |
| | | // This is fine -- we'll just use the default. |
| | | } |
| | | else |
| | | { |
| | | List<String> filterStrings = excludeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no exclude filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | SearchFilter.createFilterFromString(filterString); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter, so it isn't valid. |
| | | msgID = MSGID_SOFTREFCACHE_INVALID_EXCLUDE_FILTER; |
| | | unacceptableReasons.add(getMessage(msgID, |
| | | String.valueOf(configEntryDN), |
| | | filterString, |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_SOFTREFCACHE_INVALID_EXCLUDE_FILTERS; |
| | | unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | return configIsAcceptable; |
| | | return errorHandler.getIsAcceptable(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes a best-effort attempt to apply the configuration contained in the |
| | | * provided entry. Information about the result of this processing should be |
| | | * added to the provided message list. Information should always be added to |
| | | * this list if a configuration change could not be applied. If detailed |
| | | * results are requested, then information about the changes applied |
| | | * successfully (and optionally about parameters that were not changed) should |
| | | * also be included. |
| | | * |
| | | * @param configEntry The entry containing the new configuration to |
| | | * apply for this component. |
| | | * @param detailedResults Indicates whether detailed information about the |
| | | * processing should be added to the list. |
| | | * |
| | | * @return Information about the result of the configuration update. |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | SoftReferenceEntryCacheCfg configuration |
| | | ) |
| | | { |
| | | // Create a set of variables to use for the result. |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | boolean configIsAcceptable = true; |
| | | // Make sure that we can process the defined character sets. If so, then |
| | | // activate the new configuration. |
| | | boolean applyChanges = false; |
| | | ArrayList<String> errorMessages = new ArrayList<String>(); |
| | | EntryCacheCommon.ConfigErrorHandler errorHandler = |
| | | EntryCacheCommon.getConfigErrorHandler ( |
| | | EntryCacheCommon.ConfigPhase.PHASE_APPLY, null, errorMessages |
| | | ); |
| | | processEntryCacheConfig (configuration, applyChanges, errorHandler); |
| | | |
| | | |
| | | // Determine the lock timeout to use when interacting with the lock manager. |
| | | long newLockTimeout = LockManager.DEFAULT_TIMEOUT; |
| | | int msgID = MSGID_SOFTREFCACHE_DESCRIPTION_LOCK_TIMEOUT; |
| | | IntegerWithUnitConfigAttribute lockTimeoutStub = |
| | | new IntegerWithUnitConfigAttribute(ATTR_SOFTREFCACHE_LOCK_TIMEOUT, |
| | | getMessage(msgID), false, timeUnits, |
| | | true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerWithUnitConfigAttribute lockTimeoutAttr = |
| | | (IntegerWithUnitConfigAttribute) |
| | | configEntry.getConfigAttribute(lockTimeoutStub); |
| | | if (lockTimeoutAttr != null) |
| | | { |
| | | newLockTimeout = lockTimeoutAttr.pendingCalculatedValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_SOFTREFCACHE_INVALID_LOCK_TIMEOUT; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | | } |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be included in the cache. |
| | | HashSet<SearchFilter> newIncludeFilters = new HashSet<SearchFilter>(); |
| | | msgID = MSGID_SOFTREFCACHE_DESCRIPTION_INCLUDE_FILTERS; |
| | | StringConfigAttribute includeStub = |
| | | new StringConfigAttribute(ATTR_SOFTREFCACHE_INCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute includeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(includeStub); |
| | | if (includeAttr != null) |
| | | { |
| | | List<String> filterStrings = includeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no include filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | newIncludeFilters.add( |
| | | SearchFilter.createFilterFromString(filterString)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter, so it isn't valid. |
| | | msgID = MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTER; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | filterString, getExceptionMessage(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | } |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTERS; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | | } |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | // Determine the set of cache filters that can be used to control the |
| | | // entries that should be exclude from the cache. |
| | | HashSet<SearchFilter> newExcludeFilters = new HashSet<SearchFilter>(); |
| | | msgID = MSGID_SOFTREFCACHE_DESCRIPTION_EXCLUDE_FILTERS; |
| | | StringConfigAttribute excludeStub = |
| | | new StringConfigAttribute(ATTR_SOFTREFCACHE_EXCLUDE_FILTER, |
| | | getMessage(msgID), false, true, false); |
| | | try |
| | | { |
| | | StringConfigAttribute excludeAttr = |
| | | (StringConfigAttribute) configEntry.getConfigAttribute(excludeStub); |
| | | if (excludeAttr != null) |
| | | { |
| | | List<String> filterStrings = excludeAttr.activeValues(); |
| | | if ((filterStrings == null) || filterStrings.isEmpty()) |
| | | { |
| | | // There are no exclude filters, so we'll allow anything by default. |
| | | } |
| | | else |
| | | { |
| | | for (String filterString : filterStrings) |
| | | { |
| | | try |
| | | { |
| | | newExcludeFilters.add( |
| | | SearchFilter.createFilterFromString(filterString)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't decode this filter, so it isn't valid. |
| | | msgID = MSGID_SOFTREFCACHE_INVALID_EXCLUDE_FILTER; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | filterString, getExceptionMessage(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | } |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // An error occurred, so the provided value must not be valid. |
| | | msgID = MSGID_SOFTREFCACHE_INVALID_EXCLUDE_FILTERS; |
| | | messages.add(getMessage(msgID, String.valueOf(configEntryDN), |
| | | getExceptionMessage(e))); |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | | } |
| | | |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | if (configIsAcceptable) |
| | | { |
| | | if (lockTimeout != newLockTimeout) |
| | | { |
| | | lockTimeout = newLockTimeout; |
| | | |
| | | if (detailedResults) |
| | | { |
| | | messages.add(getMessage(MSGID_SOFTREFCACHE_UPDATED_LOCK_TIMEOUT, |
| | | lockTimeout)); |
| | | } |
| | | } |
| | | |
| | | if (!includeFilters.equals(newIncludeFilters)) |
| | | { |
| | | includeFilters = newIncludeFilters; |
| | | |
| | | if (detailedResults) |
| | | { |
| | | messages.add(getMessage(MSGID_SOFTREFCACHE_UPDATED_INCLUDE_FILTERS)); |
| | | } |
| | | } |
| | | |
| | | if (!excludeFilters.equals(newExcludeFilters)) |
| | | { |
| | | excludeFilters = newExcludeFilters; |
| | | |
| | | if (detailedResults) |
| | | { |
| | | messages.add(getMessage(MSGID_SOFTREFCACHE_UPDATED_EXCLUDE_FILTERS)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | boolean adminActionRequired = false; |
| | | ConfigChangeResult changeResult = new ConfigChangeResult( |
| | | errorHandler.getResultCode(), |
| | | adminActionRequired, |
| | | errorHandler.getErrorMessages() |
| | | ); |
| | | return changeResult; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parses the provided configuration and configure the entry cache. |
| | | * |
| | | * @param configuration The new configuration containing the changes. |
| | | * @param applyChanges If true then take into account the new configuration. |
| | | * @param errorHandler An handler used to report errors. |
| | | * |
| | | * @return The mapping between strings of character set values and the |
| | | * minimum number of characters required from those sets. |
| | | */ |
| | | public boolean processEntryCacheConfig( |
| | | SoftReferenceEntryCacheCfg configuration, |
| | | boolean applyChanges, |
| | | EntryCacheCommon.ConfigErrorHandler errorHandler |
| | | ) |
| | | { |
| | | // Local variables to read configuration. |
| | | DN newConfigEntryDN; |
| | | long newLockTimeout; |
| | | HashSet<SearchFilter> newIncludeFilters = null; |
| | | HashSet<SearchFilter> newExcludeFilters = null; |
| | | |
| | | // Read configuration. |
| | | newConfigEntryDN = configuration.dn(); |
| | | newLockTimeout = configuration.getLockTimeout(); |
| | | |
| | | // Get include and exclude filters. |
| | | switch (errorHandler.getConfigPhase()) |
| | | { |
| | | case PHASE_INIT: |
| | | newIncludeFilters = EntryCacheCommon.getFilters ( |
| | | configuration.getIncludeFilter(), |
| | | MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTER, |
| | | MSGID_SOFTREFCACHE_CANNOT_DECODE_ANY_INCLUDE_FILTERS, |
| | | errorHandler, |
| | | configEntryDN |
| | | ); |
| | | newExcludeFilters = EntryCacheCommon.getFilters ( |
| | | configuration.getExcludeFilter(), |
| | | MSGID_SOFTREFCACHE_CANNOT_DECODE_EXCLUDE_FILTER, |
| | | MSGID_SOFTREFCACHE_CANNOT_DECODE_ANY_EXCLUDE_FILTERS, |
| | | errorHandler, |
| | | configEntryDN |
| | | ); |
| | | break; |
| | | case PHASE_ACCEPTABLE: // acceptable and apply are using the same |
| | | case PHASE_APPLY: // error ID codes |
| | | newIncludeFilters = EntryCacheCommon.getFilters ( |
| | | configuration.getIncludeFilter(), |
| | | MSGID_SOFTREFCACHE_INVALID_INCLUDE_FILTER, |
| | | 0, |
| | | errorHandler, |
| | | configEntryDN |
| | | ); |
| | | newExcludeFilters = EntryCacheCommon.getFilters ( |
| | | configuration.getExcludeFilter(), |
| | | MSGID_SOFTREFCACHE_INVALID_EXCLUDE_FILTER, |
| | | 0, |
| | | errorHandler, |
| | | configEntryDN |
| | | ); |
| | | break; |
| | | } |
| | | |
| | | if (applyChanges && errorHandler.getIsAcceptable()) |
| | | { |
| | | configEntryDN = newConfigEntryDN; |
| | | lockTimeout = newLockTimeout; |
| | | includeFilters = newIncludeFilters; |
| | | excludeFilters = newExcludeFilters; |
| | | } |
| | | |
| | | return errorHandler.getIsAcceptable(); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * Operate in a loop, receiving notification of soft references that have been |
| | | * freed and removing the corresponding entries from the cache. |
| | | */ |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | |
| | | |
| | |
| | | throws Exception |
| | | { |
| | | Base64PasswordStorageScheme scheme = new Base64PasswordStorageScheme(); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | return scheme; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | |
| | | |
| | |
| | | throws Exception |
| | | { |
| | | ClearPasswordStorageScheme scheme = new ClearPasswordStorageScheme(); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | return scheme; |
| | | } |
| | | } |
| | |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.api.AccountStatusNotificationHandler; |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta. |
| | | ErrorLogAccountStatusNotificationHandlerCfgDefn; |
| | | import org.opends.server.admin.std.server. |
| | | ErrorLogAccountStatusNotificationHandlerCfg; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | |
| | | |
| | | ErrorLogAccountStatusNotificationHandler handler = |
| | | new ErrorLogAccountStatusNotificationHandler(); |
| | | handler.initializeStatusNotificationHandler(configEntry); |
| | | ErrorLogAccountStatusNotificationHandlerCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | ErrorLogAccountStatusNotificationHandlerCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | handler.initializeStatusNotificationHandler(configuration); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | |
| | | |
| | |
| | | throws Exception |
| | | { |
| | | MD5PasswordStorageScheme scheme = new MD5PasswordStorageScheme(); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | return scheme; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | |
| | | |
| | |
| | | throws Exception |
| | | { |
| | | SHA1PasswordStorageScheme scheme = new SHA1PasswordStorageScheme(); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | return scheme; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta.ErrorLogAccountStatusNotificationHandlerCfgDefn; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.ErrorLogAccountStatusNotificationHandlerCfg; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | |
| | | |
| | |
| | | { |
| | | SaltedMD5PasswordStorageScheme scheme = |
| | | new SaltedMD5PasswordStorageScheme(); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | return scheme; |
| | | } |
| | | } |
| | |
| | | |
| | | import org.testng.annotations.Test; |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.schema.UserPasswordSyntax; |
| | |
| | | { |
| | | SaltedSHA1PasswordStorageScheme scheme = |
| | | new SaltedSHA1PasswordStorageScheme(); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | return scheme; |
| | | } |
| | | |
| | |
| | | { |
| | | SaltedSHA1PasswordStorageScheme scheme = |
| | | new SaltedSHA1PasswordStorageScheme(); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | |
| | | String passwordString = scheme.encodeOffline(plaintext.value()); |
| | | String[] pwComps = UserPasswordSyntax.decodeUserPassword(passwordString); |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | |
| | | |
| | |
| | | { |
| | | SaltedSHA256PasswordStorageScheme scheme = |
| | | new SaltedSHA256PasswordStorageScheme(); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | return scheme; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | |
| | | |
| | |
| | | { |
| | | SaltedSHA384PasswordStorageScheme scheme = |
| | | new SaltedSHA384PasswordStorageScheme(); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | return scheme; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | |
| | | |
| | |
| | | { |
| | | SaltedSHA512PasswordStorageScheme scheme = |
| | | new SaltedSHA512PasswordStorageScheme(); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | return scheme; |
| | | } |
| | | } |
| | |
| | | */ |
| | | package org.opends.server.schema; |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.EqualityMatchingRule; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.core.DirectoryServer; |
| | |
| | | SaltedMD5PasswordStorageScheme scheme = new SaltedMD5PasswordStorageScheme(); |
| | | |
| | | ConfigEntry configEntry = |
| | | DirectoryServer.getConfigEntry(DN.decode("cn=Salted MD5,cn=Password Storage Schemes,cn=config")); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | DirectoryServer.getConfigEntry( |
| | | DN.decode("cn=Salted MD5,cn=Password Storage Schemes,cn=config")); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | |
| | | ByteString encodedAuthPassword = scheme.encodeAuthPassword(bytePassword); |
| | | StringBuilder[] authPWComponents = |
| | |
| | | */ |
| | | package org.opends.server.schema; |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta.PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.EqualityMatchingRule; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.core.DirectoryServer; |
| | |
| | | ConfigEntry configEntry = |
| | | DirectoryServer.getConfigEntry( |
| | | DN.decode("cn=Salted MD5,cn=Password Storage Schemes,cn=config")); |
| | | scheme.initializePasswordStorageScheme(configEntry); |
| | | |
| | | PasswordStorageSchemeCfg configuration = |
| | | AdminTestCaseUtils.getConfiguration( |
| | | PasswordStorageSchemeCfgDefn.getInstance(), |
| | | configEntry.getEntry() |
| | | ); |
| | | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | |
| | | ByteString encodedAuthPassword = |
| | | scheme.encodePasswordWithScheme(bytePassword); |