| | |
| | | * |
| | | * |
| | | * Copyright 2006-2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2012 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.backends; |
| | | |
| | | |
| | | |
| | | import static org.opends.messages.BackendMessages.*; |
| | | import static org.opends.messages.ConfigMessages.*; |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import static org.opends.server.loggers.debug.DebugLogger.getTracer; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | import static org.opends.server.util.StaticUtils.getExceptionMessage; |
| | | import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.*; |
| | | |
| | | import java.util.Set; |
| | | import org.opends.messages.Message; |
| | | import org.opends.server.admin.Configuration; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.server.MonitorBackendCfg; |
| | | import org.opends.server.admin.std.server.MonitorProviderCfg; |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.MonitorProvider; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.AddOperation; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ModifyDNOperation; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.core.SearchOperation; |
| | | import org.opends.server.core.*; |
| | | import org.opends.server.loggers.debug.DebugTracer; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.Attributes; |
| | | import org.opends.server.types.BackupConfig; |
| | | import org.opends.server.types.BackupDirectory; |
| | | import org.opends.server.types.ConditionResult; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.IndexType; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.LDIFExportConfig; |
| | | import org.opends.server.types.LDIFImportConfig; |
| | | import org.opends.server.types.LDIFImportResult; |
| | | import org.opends.server.types.ObjectClass; |
| | | import org.opends.server.types.RDN; |
| | | import org.opends.server.types.RestoreConfig; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.SearchScope; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.util.DynamicConstants; |
| | | import org.opends.server.util.LDIFWriter; |
| | | import org.opends.server.util.TimeThread; |
| | |
| | | /** |
| | | * This class defines a backend to hold Directory Server monitor entries. It |
| | | * will not actually store anything, but upon request will retrieve the |
| | | * requested monitor and dynamically generate the associated entry. It will |
| | | * also construct a base monitor entry with some useful server-wide data. |
| | | * requested monitor and dynamically generate the associated entry. It will also |
| | | * construct a base monitor entry with some useful server-wide data. |
| | | */ |
| | | public class MonitorBackend |
| | | extends Backend |
| | | implements ConfigurationChangeListener<MonitorBackendCfg> |
| | | public class MonitorBackend extends Backend implements |
| | | ConfigurationChangeListener<MonitorBackendCfg> |
| | | { |
| | | /** |
| | | * The tracer object for the debug logger. |
| | |
| | | // The set of supported features for this backend. |
| | | private HashSet<String> supportedFeatures; |
| | | |
| | | // The mapping between entry DNs and the corresponding entries. |
| | | private LinkedHashMap<DN,Entry> entryMap; |
| | | // The mapping between parent DNs and their immediate children. |
| | | private HashMap<DN,HashSet<DN>> childDNs; |
| | | |
| | | |
| | | /** |
| | | * Creates a new backend with the provided information. All backend |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void configureBackend(Configuration config) |
| | | public void addEntry(final Entry entry, final AddOperation addOperation) |
| | | throws DirectoryException |
| | | { |
| | | final Message message = ERR_MONITOR_ADD_NOT_SUPPORTED.get(String |
| | | .valueOf(entry.getDN())); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | final MonitorBackendCfg backendCfg) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | final boolean adminActionRequired = false; |
| | | final ArrayList<Message> messages = new ArrayList<Message>(); |
| | | |
| | | // Check to see if there is a new set of user-defined attributes. |
| | | final ArrayList<Attribute> userAttrs = new ArrayList<Attribute>(); |
| | | try |
| | | { |
| | | final ConfigEntry configEntry = DirectoryServer |
| | | .getConfigEntry(configEntryDN); |
| | | for (final List<Attribute> attrs : configEntry.getEntry() |
| | | .getUserAttributes().values()) |
| | | { |
| | | for (final Attribute a : attrs) |
| | | { |
| | | if (!isMonitorConfigAttribute(a)) |
| | | { |
| | | userAttrs.add(a); |
| | | } |
| | | } |
| | | } |
| | | for (final List<Attribute> attrs : configEntry.getEntry() |
| | | .getOperationalAttributes().values()) |
| | | { |
| | | for (final Attribute a : attrs) |
| | | { |
| | | if (!isMonitorConfigAttribute(a)) |
| | | { |
| | | userAttrs.add(a); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (final Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | messages.add(ERR_CONFIG_BACKEND_ERROR_INTERACTING_WITH_BACKEND_ENTRY.get( |
| | | String.valueOf(configEntryDN), stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | |
| | | userDefinedAttributes = userAttrs; |
| | | |
| | | final Message message = INFO_MONITOR_USING_NEW_USER_ATTRS.get(); |
| | | messages.add(message); |
| | | |
| | | currentConfig = backendCfg; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void configureBackend(final Configuration config) |
| | | throws ConfigException |
| | | { |
| | | Validator.ensureNotNull(config); |
| | | Validator.ensureTrue(config instanceof MonitorBackendCfg); |
| | | |
| | | MonitorBackendCfg cfg = (MonitorBackendCfg)config; |
| | | ConfigEntry configEntry = DirectoryServer.getConfigEntry(cfg.dn()); |
| | | |
| | | final MonitorBackendCfg cfg = (MonitorBackendCfg) config; |
| | | final ConfigEntry configEntry = DirectoryServer.getConfigEntry(cfg.dn()); |
| | | |
| | | // Make sure that a configuration entry was provided. If not, then we will |
| | | // not be able to complete initialization. |
| | | if (configEntry == null) |
| | | { |
| | | Message message = ERR_MONITOR_CONFIG_ENTRY_NULL.get(); |
| | | final Message message = ERR_MONITOR_CONFIG_ENTRY_NULL.get(); |
| | | throw new ConfigException(message); |
| | | } |
| | | |
| | | configEntryDN = configEntry.getDN(); |
| | | |
| | | |
| | | // Get the set of user-defined attributes for the configuration entry. Any |
| | | // attributes that we don't recognize will be included directly in the base |
| | | // monitor entry. |
| | | userDefinedAttributes = new ArrayList<Attribute>(); |
| | | for (List<Attribute> attrs : |
| | | configEntry.getEntry().getUserAttributes().values()) |
| | | for (final List<Attribute> attrs : configEntry.getEntry() |
| | | .getUserAttributes().values()) |
| | | { |
| | | for (Attribute a : attrs) |
| | | for (final Attribute a : attrs) |
| | | { |
| | | if (! isMonitorConfigAttribute(a)) |
| | | { |
| | |
| | | } |
| | | } |
| | | } |
| | | for (List<Attribute> attrs : |
| | | configEntry.getEntry().getOperationalAttributes().values()) |
| | | for (final List<Attribute> attrs : configEntry.getEntry() |
| | | .getOperationalAttributes().values()) |
| | | { |
| | | for (Attribute a : attrs) |
| | | for (final Attribute a : attrs) |
| | | { |
| | | if (! isMonitorConfigAttribute(a)) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Construct the set of objectclasses to include in the base monitor entry. |
| | | monitorObjectClasses = new LinkedHashMap<ObjectClass,String>(2); |
| | | ObjectClass topOC = DirectoryServer.getObjectClass(OC_TOP, true); |
| | | final ObjectClass topOC = DirectoryServer.getObjectClass(OC_TOP, true); |
| | | monitorObjectClasses.put(topOC, OC_TOP); |
| | | |
| | | ObjectClass monitorOC = DirectoryServer.getObjectClass(OC_MONITOR_ENTRY, |
| | | true); |
| | | final ObjectClass monitorOC = DirectoryServer.getObjectClass( |
| | | OC_MONITOR_ENTRY, true); |
| | | monitorObjectClasses.put(monitorOC, OC_MONITOR_ENTRY); |
| | | |
| | | |
| | | // Define an empty sets for the supported controls and features. |
| | | supportedControls = new HashSet<String>(0); |
| | | supportedFeatures = new HashSet<String>(0); |
| | |
| | | { |
| | | baseMonitorDN = DN.decode(DN_MONITOR_ROOT); |
| | | } |
| | | catch (Exception e) |
| | | catch (final Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | Message message = |
| | | ERR_MONITOR_CANNOT_DECODE_MONITOR_ROOT_DN.get(getExceptionMessage(e)); |
| | | final Message message = ERR_MONITOR_CANNOT_DECODE_MONITOR_ROOT_DN |
| | | .get(getExceptionMessage(e)); |
| | | throw new ConfigException(message, e); |
| | | } |
| | | |
| | | // FIXME -- Deal with this more correctly. |
| | | this.baseDNs = new DN[] { baseMonitorDN }; |
| | | |
| | | |
| | | currentConfig = cfg; |
| | | } |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializeBackend() |
| | | throws ConfigException, InitializationException |
| | | public void createBackup(final BackupConfig backupConfig) |
| | | throws DirectoryException |
| | | { |
| | | // Register with the Directory Server as a configurable component. |
| | | currentConfig.addMonitorChangeListener(this); |
| | | // This backend does not provide a backup/restore mechanism. |
| | | final Message message = ERR_MONITOR_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | entryMap = new LinkedHashMap<DN,Entry>(); |
| | | childDNs = new HashMap<DN,HashSet<DN>>(); |
| | | |
| | | this.initEntryMaps(); |
| | | |
| | | // Register the monitor base as a private suffix. |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void deleteEntry(final DN entryDN, |
| | | final DeleteOperation deleteOperation) throws DirectoryException |
| | | { |
| | | final Message message = ERR_MONITOR_DELETE_NOT_SUPPORTED.get(String |
| | | .valueOf(entryDN)); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean entryExists(final DN entryDN) throws DirectoryException |
| | | { |
| | | return getDIT().containsKey(entryDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void exportLDIF(final LDIFExportConfig exportConfig) |
| | | throws DirectoryException |
| | | { |
| | | // TODO export-ldif reports nonsense for upTime etc. |
| | | |
| | | // Create the LDIF writer. |
| | | LDIFWriter ldifWriter; |
| | | try |
| | | { |
| | | DirectoryServer.registerBaseDN(baseMonitorDN, this, true); |
| | | ldifWriter = new LDIFWriter(exportConfig); |
| | | } |
| | | catch (Exception e) |
| | | catch (final Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | Message message = ERR_BACKEND_CANNOT_REGISTER_BASEDN.get( |
| | | baseMonitorDN.toString(), getExceptionMessage(e)); |
| | | throw new InitializationException(message, e); |
| | | final Message message = ERR_ROOTDSE_UNABLE_TO_CREATE_LDIF_WRITER |
| | | .get(stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | } |
| | | |
| | | // Write the base monitor entry to the LDIF. |
| | | try |
| | | { |
| | | ldifWriter.writeEntry(getBaseMonitorEntry()); |
| | | } |
| | | catch (final Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | try |
| | | { |
| | | ldifWriter.close(); |
| | | } |
| | | catch (final Exception e2) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e2); |
| | | } |
| | | } |
| | | |
| | | final Message message = ERR_MONITOR_UNABLE_TO_EXPORT_BASE |
| | | .get(stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | } |
| | | |
| | | // Get all the monitor providers, convert them to entries, and write them to |
| | | // LDIF. |
| | | for (final MonitorProvider<?> monitorProvider : DirectoryServer |
| | | .getMonitorProviders().values()) |
| | | { |
| | | try |
| | | { |
| | | // TODO implementation of export is incomplete |
| | | } |
| | | catch (final Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | try |
| | | { |
| | | ldifWriter.close(); |
| | | } |
| | | catch (final Exception e2) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e2); |
| | | } |
| | | } |
| | | |
| | | final Message message = ERR_MONITOR_UNABLE_TO_EXPORT_PROVIDER_ENTRY |
| | | .get(monitorProvider.getMonitorInstanceName(), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException( |
| | | DirectoryServer.getServerErrorResultCode(), message); |
| | | } |
| | | } |
| | | |
| | | // Close the monitor provider and return. |
| | | try |
| | | { |
| | | ldifWriter.close(); |
| | | } |
| | | catch (final Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | @Override() |
| | | public void finalizeBackend() |
| | | { |
| | | entryMap.clear(); |
| | | childDNs.clear(); |
| | | currentConfig.removeMonitorChangeListener(this); |
| | | |
| | | try |
| | | { |
| | | DirectoryServer.deregisterBaseDN(baseMonitorDN); |
| | | } |
| | | catch (Exception e) |
| | | catch (final Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided attribute is one that is used in the |
| | | * configuration of this backend. |
| | | * |
| | | * @param attribute The attribute for which to make the determination. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided attribute is one that is used in |
| | | * the configuration of this backend, <CODE>false</CODE> if not. |
| | | */ |
| | | private boolean isMonitorConfigAttribute(Attribute attribute) |
| | | { |
| | | AttributeType attrType = attribute.getAttributeType(); |
| | | if (attrType.hasName(ATTR_COMMON_NAME) || |
| | | attrType.hasName(ATTR_BACKEND_ENABLED.toLowerCase()) || |
| | | attrType.hasName(ATTR_BACKEND_CLASS.toLowerCase()) || |
| | | attrType.hasName(ATTR_BACKEND_BASE_DN.toLowerCase()) || |
| | | attrType.hasName(ATTR_BACKEND_ID.toLowerCase()) || |
| | | attrType.hasName(ATTR_BACKEND_WRITABILITY_MODE.toLowerCase())) |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public Entry getEntry(final DN entryDN) throws DirectoryException |
| | | { |
| | | // If the requested entry was null, then throw an exception. |
| | | if (entryDN == null) |
| | | { |
| | | final Message message = ERR_MONITOR_GET_ENTRY_NULL.get(); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | } |
| | | |
| | | // If the requested entry was the monitor base entry, then retrieve it |
| | | // without constructing the DIT. |
| | | if (entryDN.equals(baseMonitorDN)) |
| | | { |
| | | return getBaseMonitorEntry(); |
| | | } |
| | | |
| | | // From now on we'll need the DIT. |
| | | final Map<DN, MonitorProvider<?>> dit = getDIT(); |
| | | if (!dit.containsKey(entryDN)) |
| | | { |
| | | final Message message = ERR_MONITOR_INVALID_BASE.get( |
| | | String.valueOf(entryDN), String.valueOf(baseMonitorDN)); |
| | | throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message); |
| | | } |
| | | |
| | | // The DN is associated with a valid monitor/glue entry. |
| | | return getEntry(entryDN, dit); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public long getEntryCount() |
| | | { |
| | | if (entryMap != null) { |
| | | return entryMap.size(); |
| | | return getDIT().size(); |
| | | } |
| | | return -1; |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public HashSet<String> getSupportedControls() |
| | | { |
| | | return supportedControls; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public HashSet<String> getSupportedFeatures() |
| | | { |
| | | return supportedFeatures; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult hasSubordinates(final DN entryDN) |
| | | throws DirectoryException |
| | | { |
| | | final NavigableMap<DN, MonitorProvider<?>> dit = getDIT(); |
| | | if (!dit.containsKey(entryDN)) |
| | | { |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | else |
| | | { |
| | | final DN nextDN = dit.higherKey(entryDN); |
| | | if (nextDN == null || !nextDN.isDescendantOf(entryDN)) |
| | | { |
| | | return ConditionResult.FALSE; |
| | | } |
| | | else |
| | | { |
| | | return ConditionResult.TRUE; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public LDIFImportResult importLDIF(final LDIFImportConfig importConfig) |
| | | throws DirectoryException |
| | | { |
| | | // This backend does not support LDIF imports. |
| | | final Message message = ERR_MONITOR_IMPORT_NOT_SUPPORTED.get(); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializeBackend() throws ConfigException, |
| | | InitializationException |
| | | { |
| | | // Register with the Directory Server as a configurable component. |
| | | currentConfig.addMonitorChangeListener(this); |
| | | |
| | | // Register the monitor base as a private suffix. |
| | | try |
| | | { |
| | | DirectoryServer.registerBaseDN(baseMonitorDN, this, true); |
| | | } |
| | | catch (final Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | final Message message = ERR_BACKEND_CANNOT_REGISTER_BASEDN.get( |
| | | baseMonitorDN.toString(), getExceptionMessage(e)); |
| | | throw new InitializationException(message, e); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | final MonitorBackendCfg backendCfg, |
| | | final List<Message> unacceptableReasons) |
| | | { |
| | | // We'll pretty much accept anything here as long as it isn't one of our |
| | | // private attributes. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean isIndexed(final AttributeType attributeType, |
| | | final IndexType indexType) |
| | | { |
| | | // All searches in this backend will always be considered indexed. |
| | | return true; |
| | | } |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean isIndexed(AttributeType attributeType, IndexType indexType) |
| | | { |
| | | // All searches in this backend will always be considered indexed. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult hasSubordinates(DN entryDN) |
| | | public long numSubordinates(final DN entryDN, final boolean subtree) |
| | | throws DirectoryException |
| | | { |
| | | long ret = numSubordinates(entryDN, false); |
| | | if(ret < 0) |
| | | final NavigableMap<DN, MonitorProvider<?>> dit = getDIT(); |
| | | if (!dit.containsKey(entryDN)) |
| | | { |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | else if(ret == 0) |
| | | { |
| | | return ConditionResult.FALSE; |
| | | } |
| | | else |
| | | { |
| | | return ConditionResult.TRUE; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public long numSubordinates(DN entryDN, boolean subtree) |
| | | throws DirectoryException { |
| | | |
| | | Set<DN> children = childDNs.get(entryDN); |
| | | if (children == null) |
| | | { |
| | | if(entryMap.get(entryDN) != null) |
| | | { |
| | | // The entry does exist but just no children. |
| | | return 0; |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | if(!subtree) |
| | | { |
| | | return children.size(); |
| | | return -1L; |
| | | } |
| | | else |
| | | { |
| | | long count = 0; |
| | | for(DN child : children) |
| | | final int childDNSize = entryDN.getNumComponents() + 1; |
| | | for (final DN dn : dit.tailMap(entryDN, false).navigableKeySet()) |
| | | { |
| | | count += numSubordinates(child, true); |
| | | if (!dn.isDescendantOf(entryDN)) |
| | | { |
| | | break; |
| | | } |
| | | else if (subtree || dn.getNumComponents() == childDNSize) |
| | | { |
| | | count++; |
| | | } |
| | | } |
| | | return count; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public Entry getEntry(DN entryDN) |
| | | throws DirectoryException |
| | | @Override |
| | | public void preloadEntryCache() throws UnsupportedOperationException |
| | | { |
| | | // If the requested entry was null, then throw an exception. |
| | | if (entryDN == null) |
| | | { |
| | | Message message = ERR_MONITOR_GET_ENTRY_NULL.get(); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | } |
| | | |
| | | |
| | | // If the requested entry was the monitor base entry, then retrieve it. |
| | | if (entryDN.equals(baseMonitorDN)) |
| | | { |
| | | return getBaseMonitorEntry(); |
| | | } |
| | | |
| | | if (!isATreeNode(entryDN)) { |
| | | Message message = ERR_MONITOR_INVALID_BASE.get( |
| | | String.valueOf(entryDN), String.valueOf(baseMonitorDN)); |
| | | throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message); |
| | | } |
| | | |
| | | |
| | | // Get the RDN for the requested DN and make sure it is single-valued. |
| | | RDN entryRDN = entryDN.getRDN(); |
| | | if (entryRDN.isMultiValued()) |
| | | { |
| | | Message message = |
| | | ERR_MONITOR_MULTIVALUED_RDN.get(String.valueOf(entryDN)); |
| | | throw new DirectoryException( |
| | | ResultCode.NO_SUCH_OBJECT, message, baseMonitorDN, null); |
| | | } |
| | | |
| | | String rdnValue = getRdns(entryDN); |
| | | MonitorProvider<? extends MonitorProviderCfg> monitorProvider = |
| | | DirectoryServer.getMonitorProvider(rdnValue.toLowerCase()); |
| | | |
| | | // Could be a monitor branch |
| | | if (monitorProvider == null) { |
| | | return getBranchMonitorEntry(entryDN); |
| | | } |
| | | |
| | | // Take the data from the monitor provider and stuff it into an entry. |
| | | return getMonitorEntry(entryDN, monitorProvider); |
| | | throw new UnsupportedOperationException("Operation not supported."); |
| | | } |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean entryExists(DN entryDN) |
| | | public void removeBackup(final BackupDirectory backupDirectory, |
| | | final String backupID) throws DirectoryException |
| | | { |
| | | // This backend does not provide a backup/restore mechanism. |
| | | final Message message = ERR_MONITOR_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void renameEntry(final DN currentDN, final Entry entry, |
| | | final ModifyDNOperation modifyDNOperation) throws DirectoryException |
| | | { |
| | | final Message message = ERR_MONITOR_MODIFY_DN_NOT_SUPPORTED.get(String |
| | | .valueOf(currentDN)); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void replaceEntry(final Entry oldEntry, final Entry newEntry, |
| | | final ModifyOperation modifyOperation) throws DirectoryException |
| | | { |
| | | final Message message = ERR_MONITOR_MODIFY_NOT_SUPPORTED.get( |
| | | String.valueOf(newEntry.getDN()), String.valueOf(configEntryDN)); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void restoreBackup(final RestoreConfig restoreConfig) |
| | | throws DirectoryException |
| | | { |
| | | return this.isATreeNode(entryDN); |
| | | // This backend does not provide a backup/restore mechanism. |
| | | final Message message = ERR_MONITOR_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void search(final SearchOperation searchOperation) |
| | | throws DirectoryException |
| | | { |
| | | // Get the base DN, scope, and filter for the search. |
| | | final DN baseDN = searchOperation.getBaseDN(); |
| | | final SearchScope scope = searchOperation.getScope(); |
| | | final SearchFilter filter = searchOperation.getFilter(); |
| | | |
| | | // Compute the current monitor DIT. |
| | | final NavigableMap<DN, MonitorProvider<?>> dit = getDIT(); |
| | | |
| | | // Resolve the base entry and return no such object if it does not exist. |
| | | if (!dit.containsKey(baseDN)) |
| | | { |
| | | // Not found, so find the nearest match. |
| | | DN matchedDN = baseDN.getParent(); |
| | | while (matchedDN != null) |
| | | { |
| | | if (dit.containsKey(matchedDN)) |
| | | { |
| | | break; |
| | | } |
| | | matchedDN = matchedDN.getParent(); |
| | | } |
| | | final Message message = ERR_MEMORYBACKEND_ENTRY_DOESNT_EXIST.get(String |
| | | .valueOf(baseDN)); |
| | | throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message, |
| | | matchedDN, null); |
| | | } |
| | | |
| | | // Walk through all entries and send the ones that match. |
| | | for (final Map.Entry<DN, MonitorProvider<?>> e : dit.tailMap(baseDN) |
| | | .entrySet()) |
| | | { |
| | | final DN dn = e.getKey(); |
| | | if (dn.matchesBaseAndScope(baseDN, scope)) |
| | | { |
| | | final Entry entry = getEntry(dn, dit); |
| | | if (filter.matchesEntry(entry)) |
| | | { |
| | | searchOperation.returnEntry(entry, null); |
| | | } |
| | | } |
| | | else if (scope == SearchScope.BASE_OBJECT || !dn.isDescendantOf(baseDN)) |
| | | { |
| | | // No more entries will be in scope. |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean supportsBackup() |
| | | { |
| | | // This backend does not provide a backup/restore mechanism. |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean supportsBackup(final BackupConfig backupConfig, |
| | | final StringBuilder unsupportedReason) |
| | | { |
| | | // This backend does not provide a backup/restore mechanism. |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean supportsLDIFExport() |
| | | { |
| | | // We can export all the monitor entries as a point-in-time snapshot. |
| | | // TODO implementation of export is incomplete |
| | | // TODO export-ldif reports nonsense for upTime etc. |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean supportsLDIFImport() |
| | | { |
| | | // This backend does not support LDIF imports. |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean supportsRestore() |
| | | { |
| | | // This backend does not provide a backup/restore mechanism. |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates an attribute for a monitor entry with the following criteria. |
| | | * |
| | | * @param name |
| | | * The name for the attribute. |
| | | * @param lowerName |
| | | * The name for the attribute formatted in all lowercase characters. |
| | | * @param value |
| | | * The value to use for the attribute. |
| | | * @return The constructed attribute. |
| | | */ |
| | | private Attribute createAttribute(final String name, final String lowerName, |
| | | final String value) |
| | | { |
| | | return Attributes.create(name, value); |
| | | } |
| | | |
| | | |
| | |
| | | * |
| | | * @return The base monitor entry for the Directory Server. |
| | | */ |
| | | public Entry getBaseMonitorEntry() |
| | | private Entry getBaseMonitorEntry() |
| | | { |
| | | HashMap<ObjectClass,String> monitorClasses = |
| | | final HashMap<ObjectClass, String> monitorClasses = |
| | | new LinkedHashMap<ObjectClass,String>(3); |
| | | monitorClasses.putAll(monitorObjectClasses); |
| | | |
| | | ObjectClass extensibleObjectOC = |
| | | DirectoryServer.getObjectClass(OC_EXTENSIBLE_OBJECT_LC, true); |
| | | final ObjectClass extensibleObjectOC = DirectoryServer.getObjectClass( |
| | | OC_EXTENSIBLE_OBJECT_LC, true); |
| | | monitorClasses.put(extensibleObjectOC, OC_EXTENSIBLE_OBJECT); |
| | | |
| | | HashMap<AttributeType,List<Attribute>> monitorUserAttrs = |
| | | final HashMap<AttributeType, List<Attribute>> monitorUserAttrs = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(); |
| | | |
| | | HashMap<AttributeType,List<Attribute>> monitorOperationalAttrs = |
| | | final HashMap<AttributeType, List<Attribute>> monitorOperationalAttrs = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(); |
| | | |
| | | |
| | | // Add the "cn" attribute. |
| | | Attribute cnAttr = createAttribute(ATTR_COMMON_NAME, ATTR_COMMON_NAME, |
| | | "monitor"); |
| | | ArrayList<Attribute> cnList = new ArrayList<Attribute>(1); |
| | | final Attribute cnAttr = createAttribute(ATTR_COMMON_NAME, |
| | | ATTR_COMMON_NAME, "monitor"); |
| | | final ArrayList<Attribute> cnList = new ArrayList<Attribute>(1); |
| | | cnList.add(cnAttr); |
| | | monitorUserAttrs.put(cnAttr.getAttributeType(), cnList); |
| | | |
| | | |
| | | // Add the server product name. |
| | | Attribute productNameAttr = createAttribute(ATTR_PRODUCT_NAME, |
| | | ATTR_PRODUCT_NAME_LC, |
| | | DynamicConstants.PRODUCT_NAME); |
| | | ArrayList<Attribute> productNameList = new ArrayList<Attribute>(1); |
| | | final Attribute productNameAttr = createAttribute(ATTR_PRODUCT_NAME, |
| | | ATTR_PRODUCT_NAME_LC, DynamicConstants.PRODUCT_NAME); |
| | | final ArrayList<Attribute> productNameList = new ArrayList<Attribute>(1); |
| | | productNameList.add(productNameAttr); |
| | | monitorUserAttrs.put(productNameAttr.getAttributeType(), productNameList); |
| | | |
| | | |
| | | // Add the vendor name. |
| | | Attribute vendorNameAttr = createAttribute(ATTR_VENDOR_NAME, |
| | | ATTR_VENDOR_NAME_LC, |
| | | SERVER_VENDOR_NAME); |
| | | ArrayList<Attribute> vendorNameList = new ArrayList<Attribute>(1); |
| | | final Attribute vendorNameAttr = createAttribute(ATTR_VENDOR_NAME, |
| | | ATTR_VENDOR_NAME_LC, SERVER_VENDOR_NAME); |
| | | final ArrayList<Attribute> vendorNameList = new ArrayList<Attribute>(1); |
| | | vendorNameList.add(vendorNameAttr); |
| | | monitorUserAttrs.put(vendorNameAttr.getAttributeType(), vendorNameList); |
| | | |
| | | |
| | | // Add the vendor version. |
| | | Attribute versionAttr = createAttribute(ATTR_VENDOR_VERSION, |
| | | ATTR_VENDOR_VERSION_LC, |
| | | DirectoryServer.getVersionString()); |
| | | ArrayList<Attribute> versionList = new ArrayList<Attribute>(1); |
| | | final Attribute versionAttr = createAttribute(ATTR_VENDOR_VERSION, |
| | | ATTR_VENDOR_VERSION_LC, DirectoryServer.getVersionString()); |
| | | final ArrayList<Attribute> versionList = new ArrayList<Attribute>(1); |
| | | versionList.add(versionAttr); |
| | | monitorUserAttrs.put(versionAttr.getAttributeType(), versionList); |
| | | |
| | | |
| | | // Add the server startup time. |
| | | Attribute startTimeAttr = |
| | | createAttribute(ATTR_START_TIME, ATTR_START_TIME_LC, |
| | | DirectoryServer.getStartTimeUTC()); |
| | | ArrayList<Attribute> startTimeList = new ArrayList<Attribute>(1); |
| | | final Attribute startTimeAttr = createAttribute(ATTR_START_TIME, |
| | | ATTR_START_TIME_LC, DirectoryServer.getStartTimeUTC()); |
| | | final ArrayList<Attribute> startTimeList = new ArrayList<Attribute>(1); |
| | | startTimeList.add(startTimeAttr); |
| | | monitorUserAttrs.put(startTimeAttr.getAttributeType(), startTimeList); |
| | | |
| | | |
| | | // Add the current time. |
| | | Attribute currentTimeAttr = |
| | | createAttribute(ATTR_CURRENT_TIME, ATTR_CURRENT_TIME_LC, |
| | | TimeThread.getGMTTime()); |
| | | ArrayList<Attribute> currentTimeList = new ArrayList<Attribute>(1); |
| | | final Attribute currentTimeAttr = createAttribute(ATTR_CURRENT_TIME, |
| | | ATTR_CURRENT_TIME_LC, TimeThread.getGMTTime()); |
| | | final ArrayList<Attribute> currentTimeList = new ArrayList<Attribute>(1); |
| | | currentTimeList.add(currentTimeAttr); |
| | | monitorUserAttrs.put(currentTimeAttr.getAttributeType(), currentTimeList); |
| | | |
| | | |
| | | // Add the uptime as a human-readable string. |
| | | long upSeconds = |
| | | ((System.currentTimeMillis() - DirectoryServer.getStartTime()) / 1000); |
| | | long upDays = (upSeconds / 86400); |
| | | long upSeconds = ((System.currentTimeMillis() - DirectoryServer |
| | | .getStartTime()) / 1000); |
| | | final long upDays = (upSeconds / 86400); |
| | | upSeconds %= 86400; |
| | | long upHours = (upSeconds / 3600); |
| | | final long upHours = (upSeconds / 3600); |
| | | upSeconds %= 3600; |
| | | long upMinutes = (upSeconds / 60); |
| | | final long upMinutes = (upSeconds / 60); |
| | | upSeconds %= 60; |
| | | Message upTimeStr = |
| | | INFO_MONITOR_UPTIME.get(upDays, upHours, upMinutes, upSeconds); |
| | | Attribute upTimeAttr = createAttribute(ATTR_UP_TIME, ATTR_UP_TIME_LC, |
| | | final Message upTimeStr = INFO_MONITOR_UPTIME.get(upDays, upHours, |
| | | upMinutes, upSeconds); |
| | | final Attribute upTimeAttr = createAttribute(ATTR_UP_TIME, ATTR_UP_TIME_LC, |
| | | upTimeStr.toString()); |
| | | ArrayList<Attribute> upTimeList = new ArrayList<Attribute>(1); |
| | | final ArrayList<Attribute> upTimeList = new ArrayList<Attribute>(1); |
| | | upTimeList.add(upTimeAttr); |
| | | monitorUserAttrs.put(upTimeAttr.getAttributeType(), upTimeList); |
| | | |
| | | |
| | | // Add the number of connections currently established. |
| | | long currentConns = DirectoryServer.getCurrentConnections(); |
| | | Attribute currentConnsAttr = createAttribute(ATTR_CURRENT_CONNS, |
| | | ATTR_CURRENT_CONNS_LC, |
| | | String.valueOf(currentConns)); |
| | | ArrayList<Attribute> currentConnsList = new ArrayList<Attribute>(1); |
| | | final long currentConns = DirectoryServer.getCurrentConnections(); |
| | | final Attribute currentConnsAttr = createAttribute(ATTR_CURRENT_CONNS, |
| | | ATTR_CURRENT_CONNS_LC, String.valueOf(currentConns)); |
| | | final ArrayList<Attribute> currentConnsList = new ArrayList<Attribute>(1); |
| | | currentConnsList.add(currentConnsAttr); |
| | | monitorUserAttrs.put(currentConnsAttr.getAttributeType(), currentConnsList); |
| | | |
| | | |
| | | // Add the maximum number of connections established at one time. |
| | | long maxConns = DirectoryServer.getMaxConnections(); |
| | | Attribute maxConnsAttr = createAttribute(ATTR_MAX_CONNS, |
| | | ATTR_MAX_CONNS_LC, |
| | | String.valueOf(maxConns)); |
| | | ArrayList<Attribute> maxConnsList = new ArrayList<Attribute>(1); |
| | | final long maxConns = DirectoryServer.getMaxConnections(); |
| | | final Attribute maxConnsAttr = createAttribute(ATTR_MAX_CONNS, |
| | | ATTR_MAX_CONNS_LC, String.valueOf(maxConns)); |
| | | final ArrayList<Attribute> maxConnsList = new ArrayList<Attribute>(1); |
| | | maxConnsList.add(maxConnsAttr); |
| | | monitorUserAttrs.put(maxConnsAttr.getAttributeType(), maxConnsList); |
| | | |
| | | |
| | | // Add the total number of connections the server has accepted. |
| | | long totalConns = DirectoryServer.getTotalConnections(); |
| | | Attribute totalConnsAttr = createAttribute(ATTR_TOTAL_CONNS, |
| | | ATTR_TOTAL_CONNS_LC, |
| | | String.valueOf(totalConns)); |
| | | ArrayList<Attribute> totalConnsList = new ArrayList<Attribute>(1); |
| | | final long totalConns = DirectoryServer.getTotalConnections(); |
| | | final Attribute totalConnsAttr = createAttribute(ATTR_TOTAL_CONNS, |
| | | ATTR_TOTAL_CONNS_LC, String.valueOf(totalConns)); |
| | | final ArrayList<Attribute> totalConnsList = new ArrayList<Attribute>(1); |
| | | totalConnsList.add(totalConnsAttr); |
| | | monitorUserAttrs.put(totalConnsAttr.getAttributeType(), totalConnsList); |
| | | |
| | | |
| | | // Add all the user-defined attributes. |
| | | for (Attribute a : userDefinedAttributes) |
| | | for (final Attribute a : userDefinedAttributes) |
| | | { |
| | | AttributeType type = a.getAttributeType(); |
| | | final AttributeType type = a.getAttributeType(); |
| | | |
| | | if (type.isOperational()) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Construct and return the entry. |
| | | Entry e = new Entry(baseMonitorDN, monitorClasses, monitorUserAttrs, |
| | | final Entry e = new Entry(baseMonitorDN, monitorClasses, monitorUserAttrs, |
| | | monitorOperationalAttrs); |
| | | e.processVirtualAttributes(); |
| | | return e; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the branch monitor entry for the Directory Server. |
| | | * @param dn to get. |
| | | * |
| | | * @param dn |
| | | * to get. |
| | | * @return The branch monitor entry for the Directory Server. |
| | | */ |
| | | public Entry getBranchMonitorEntry(DN dn) { |
| | | private Entry getBranchMonitorEntry(final DN dn) |
| | | { |
| | | |
| | | HashMap<ObjectClass,String> monitorClasses = |
| | | final HashMap<ObjectClass, String> monitorClasses = |
| | | new LinkedHashMap<ObjectClass,String>(3); |
| | | monitorClasses.putAll(monitorObjectClasses); |
| | | ObjectClass monitorOC = DirectoryServer.getObjectClass(OC_MONITOR_BRANCH, |
| | | true); |
| | | final ObjectClass monitorOC = DirectoryServer.getObjectClass( |
| | | OC_MONITOR_BRANCH, true); |
| | | monitorClasses.put(monitorOC, OC_MONITOR_BRANCH); |
| | | |
| | | HashMap<AttributeType,List<Attribute>> monitorUserAttrs = |
| | | final HashMap<AttributeType, List<Attribute>> monitorUserAttrs = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(); |
| | | |
| | | RDN rdn = dn.getRDN(); |
| | | final RDN rdn = dn.getRDN(); |
| | | if (rdn != null) |
| | | { |
| | | // Add the RDN values |
| | | for (int i=0; i<rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attributeType = rdn.getAttributeType(i); |
| | | AttributeValue value = rdn.getAttributeValue(attributeType); |
| | | Attribute attr = Attributes.create(attributeType, value); |
| | | List<Attribute> attrList = new ArrayList<Attribute>(1); |
| | | final AttributeType attributeType = rdn.getAttributeType(i); |
| | | final AttributeValue value = rdn.getAttributeValue(attributeType); |
| | | final Attribute attr = Attributes.create(attributeType, value); |
| | | final List<Attribute> attrList = new ArrayList<Attribute>(1); |
| | | attrList.add(attr); |
| | | monitorUserAttrs.put(attributeType, attrList); |
| | | } |
| | | } |
| | | |
| | | // Construct and return the entry. |
| | | Entry e = new Entry(dn, monitorClasses, monitorUserAttrs, null); |
| | | final Entry e = new Entry(dn, monitorClasses, monitorUserAttrs, null); |
| | | e.processVirtualAttributes(); |
| | | return e; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Generates and returns a monitor entry based on the contents of the |
| | | * provided monitor provider. |
| | | * Returns a map containing records for each DN in the monitor backend's DIT. |
| | | * Each record maps the entry DN to the associated monitor provider, or |
| | | * {@code null} if the entry is a glue (branch) entry. |
| | | * |
| | | * @param entryDN The DN to use for the entry. |
| | | * @param monitorProvider The monitor provider to use to obtain the |
| | | * information for the entry. |
| | | * @return A map containing records for each DN in the monitor backend's DIT. |
| | | */ |
| | | private NavigableMap<DN, MonitorProvider<?>> getDIT() |
| | | { |
| | | final NavigableMap<DN, MonitorProvider<?>> dit = |
| | | new TreeMap<DN, MonitorProvider<?>>(); |
| | | for (final MonitorProvider<?> monitorProvider : DirectoryServer |
| | | .getMonitorProviders().values()) |
| | | { |
| | | DN dn = DirectoryServer.getMonitorProviderDN(monitorProvider); |
| | | dit.put(dn, monitorProvider); |
| | | |
| | | // Added glue records. |
| | | for (dn = dn.getParent(); dn != null; dn = dn.getParent()) |
| | | { |
| | | if (dit.containsKey(dn)) |
| | | { |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | dit.put(dn, null); |
| | | } |
| | | } |
| | | } |
| | | return dit; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates the monitor entry having the specified DN. |
| | | * |
| | | * @param entryDN |
| | | * The name of the monitor entry. |
| | | * @param dit |
| | | * The monitor DIT. |
| | | * @return Returns the monitor entry having the specified DN. |
| | | */ |
| | | private Entry getEntry(final DN entryDN, |
| | | final Map<DN, MonitorProvider<?>> dit) |
| | | { |
| | | // Get the monitor provider. |
| | | final MonitorProvider<?> monitorProvider = dit.get(entryDN); |
| | | if (monitorProvider != null) |
| | | { |
| | | return getMonitorEntry(entryDN, monitorProvider); |
| | | } |
| | | else if (entryDN.equals(baseMonitorDN)) |
| | | { |
| | | // The monitor base entry needs special treatment. |
| | | return getBaseMonitorEntry(); |
| | | } |
| | | else |
| | | { |
| | | // Create a generic glue branch entry. |
| | | return getBranchMonitorEntry(entryDN); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Generates and returns a monitor entry based on the contents of the provided |
| | | * monitor provider. |
| | | * |
| | | * @param entryDN |
| | | * The DN to use for the entry. |
| | | * @param monitorProvider |
| | | * The monitor provider to use to obtain the information for the |
| | | * entry. |
| | | * @return The monitor entry generated from the information in the provided |
| | | * monitor provider. |
| | | */ |
| | | private Entry getMonitorEntry(DN entryDN, |
| | | MonitorProvider<? extends MonitorProviderCfg> |
| | | monitorProvider) |
| | | private Entry getMonitorEntry(final DN entryDN, |
| | | final MonitorProvider<?> monitorProvider) |
| | | { |
| | | HashMap<ObjectClass,String> monitorClasses = |
| | | new LinkedHashMap<ObjectClass,String>(3); |
| | | final HashMap<ObjectClass, String> monitorClasses = |
| | | new LinkedHashMap<ObjectClass, String>( |
| | | 3); |
| | | monitorClasses.putAll(monitorObjectClasses); |
| | | |
| | | ObjectClass monitorOC = monitorProvider.getMonitorObjectClass(); |
| | | final ObjectClass monitorOC = monitorProvider.getMonitorObjectClass(); |
| | | monitorClasses.put(monitorOC, monitorOC.getPrimaryName()); |
| | | |
| | | List<Attribute> monitorAttrs = monitorProvider.getMonitorData(); |
| | | HashMap<AttributeType,List<Attribute>> attrMap = |
| | | final List<Attribute> monitorAttrs = monitorProvider.getMonitorData(); |
| | | final HashMap<AttributeType, List<Attribute>> attrMap = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>( |
| | | monitorAttrs.size()+1); |
| | | |
| | | |
| | | // Make sure to include the RDN attribute. |
| | | RDN entryRDN = entryDN.getRDN(); |
| | | AttributeType rdnType = entryRDN.getAttributeType(0); |
| | | AttributeValue rdnValue = entryRDN.getAttributeValue(0); |
| | | final RDN entryRDN = entryDN.getRDN(); |
| | | final AttributeType rdnType = entryRDN.getAttributeType(0); |
| | | final AttributeValue rdnValue = entryRDN.getAttributeValue(0); |
| | | |
| | | Attribute rdnAttr = Attributes.create(rdnType, rdnValue); |
| | | ArrayList<Attribute> rdnList = new ArrayList<Attribute>(1); |
| | | final Attribute rdnAttr = Attributes.create(rdnType, rdnValue); |
| | | final ArrayList<Attribute> rdnList = new ArrayList<Attribute>(1); |
| | | rdnList.add(rdnAttr); |
| | | attrMap.put(rdnType, rdnList); |
| | | |
| | | |
| | | // Take the rest of the information from the monitor data. |
| | | for (Attribute a : monitorAttrs) |
| | | for (final Attribute a : monitorAttrs) |
| | | { |
| | | AttributeType type = a.getAttributeType(); |
| | | final AttributeType type = a.getAttributeType(); |
| | | |
| | | List<Attribute> attrs = attrMap.get(type); |
| | | if (attrs == null) |
| | |
| | | } |
| | | } |
| | | |
| | | Entry e = new Entry(entryDN, monitorClasses, attrMap, |
| | | final Entry e = new Entry(entryDN, monitorClasses, attrMap, |
| | | new HashMap<AttributeType,List<Attribute>>(0)); |
| | | e.processVirtualAttributes(); |
| | | return e; |
| | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | * Indicates whether the provided attribute is one that is used in the |
| | | * configuration of this backend. |
| | | * |
| | | * @param attribute |
| | | * The attribute for which to make the determination. |
| | | * @return <CODE>true</CODE> if the provided attribute is one that is used in |
| | | * the configuration of this backend, <CODE>false</CODE> if not. |
| | | */ |
| | | @Override() |
| | | public void addEntry(Entry entry, AddOperation addOperation) |
| | | throws DirectoryException |
| | | private boolean isMonitorConfigAttribute(final Attribute attribute) |
| | | { |
| | | Message message = |
| | | ERR_MONITOR_ADD_NOT_SUPPORTED.get(String.valueOf(entry.getDN())); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void deleteEntry(DN entryDN, DeleteOperation deleteOperation) |
| | | throws DirectoryException |
| | | final AttributeType attrType = attribute.getAttributeType(); |
| | | if (attrType.hasName(ATTR_COMMON_NAME) |
| | | || attrType.hasName(ATTR_BACKEND_ENABLED.toLowerCase()) |
| | | || attrType.hasName(ATTR_BACKEND_CLASS.toLowerCase()) |
| | | || attrType.hasName(ATTR_BACKEND_BASE_DN.toLowerCase()) |
| | | || attrType.hasName(ATTR_BACKEND_ID.toLowerCase()) |
| | | || attrType.hasName(ATTR_BACKEND_WRITABILITY_MODE.toLowerCase())) |
| | | { |
| | | Message message = |
| | | ERR_MONITOR_DELETE_NOT_SUPPORTED.get(String.valueOf(entryDN)); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void replaceEntry(Entry oldEntry, Entry newEntry, |
| | | ModifyOperation modifyOperation) throws DirectoryException |
| | | { |
| | | Message message = ERR_MONITOR_MODIFY_NOT_SUPPORTED.get( |
| | | String.valueOf(newEntry.getDN()), String.valueOf(configEntryDN)); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void renameEntry(DN currentDN, Entry entry, |
| | | ModifyDNOperation modifyDNOperation) |
| | | throws DirectoryException |
| | | { |
| | | Message message = |
| | | ERR_MONITOR_MODIFY_DN_NOT_SUPPORTED.get(String.valueOf(currentDN)); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public synchronized void search(SearchOperation searchOperation) |
| | | throws DirectoryException |
| | | { |
| | | |
| | | // Get the base DN, scope, and filter for the search. |
| | | DN baseDN = searchOperation.getBaseDN(); |
| | | SearchScope scope = searchOperation.getScope(); |
| | | SearchFilter filter = searchOperation.getFilter(); |
| | | |
| | | |
| | | // Make sure the base entry exists if it's supposed to be in this backend. |
| | | this.initEntryMaps(); |
| | | Entry baseEntry = entryMap.get(baseDN); |
| | | if ((baseEntry == null) && handlesEntry(baseDN)) |
| | | { |
| | | DN matchedDN = baseDN.getParentDNInSuffix(); |
| | | while (matchedDN != null) |
| | | { |
| | | if (entryMap.containsKey(matchedDN)) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | matchedDN = matchedDN.getParentDNInSuffix(); |
| | | } |
| | | |
| | | Message message = |
| | | ERR_MEMORYBACKEND_ENTRY_DOESNT_EXIST.get(String.valueOf(baseDN)); |
| | | throw new DirectoryException( |
| | | ResultCode.NO_SUCH_OBJECT, message, matchedDN, null); |
| | | } |
| | | |
| | | if (baseEntry != null) |
| | | { |
| | | baseEntry = baseEntry.duplicate(true); |
| | | } |
| | | |
| | | |
| | | // If it's a base-level search, then just get that entry and return it if it |
| | | // matches the filter. |
| | | if (scope == SearchScope.BASE_OBJECT) |
| | | { |
| | | if (filter.matchesEntry(baseEntry)) |
| | | { |
| | | searchOperation.returnEntry(baseEntry, null); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // Walk through all entries and send the ones that match. |
| | | for (Entry e : entryMap.values()) { |
| | | boolean matched = filter.matchesEntry(e); |
| | | if (matched) { |
| | | if (e.matchesBaseAndScope(baseDN, scope)==true) { |
| | | searchOperation.returnEntry(e, null); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Build the internal monitor tree (entries, and children) |
| | | private synchronized void initEntryMaps() { |
| | | this.entryMap.clear(); |
| | | this.childDNs.clear(); |
| | | for (MonitorProvider<? extends MonitorProviderCfg> monitorProvider : |
| | | DirectoryServer.getMonitorProviders().values()) { |
| | | try { |
| | | DN providerdn = |
| | | DirectoryServer.getMonitorProviderDN(monitorProvider); |
| | | if (!entryMap.containsKey(providerdn)) { |
| | | getAndAddParentInMaps(providerdn); |
| | | Entry entry = getEntry(providerdn); |
| | | entryMap.put(providerdn, entry); |
| | | } |
| | | } catch (Exception ex) { |
| | | if (debugEnabled()) { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, ex); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Recursively builds the entryMap and the childDN Map. |
| | | */ |
| | | private void getAndAddParentInMaps(DN providerDN) |
| | | { |
| | | try |
| | | { |
| | | DN parentdn = providerDN.getParentDNInSuffix(); |
| | | DN child = providerDN; |
| | | |
| | | if ((parentdn != null) && (!entryMap.containsKey(parentdn))) |
| | | { |
| | | getAndAddParentInMaps(parentdn); |
| | | entryMap.put(parentdn, getEntry(parentdn)); |
| | | } |
| | | |
| | | if (childDNs.containsKey(parentdn)) |
| | | { |
| | | HashSet<DN> children = childDNs.get(parentdn); |
| | | children.add(child); |
| | | childDNs.put(parentdn, children); |
| | | } |
| | | else |
| | | { |
| | | HashSet<DN> children = new HashSet<DN>(); |
| | | children.add(child); |
| | | childDNs.put(parentdn, children); |
| | | } |
| | | } catch (Exception e) { |
| | | if (debugEnabled()) { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public HashSet<String> getSupportedControls() |
| | | { |
| | | return supportedControls; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public HashSet<String> getSupportedFeatures() |
| | | { |
| | | return supportedFeatures; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean supportsLDIFExport() |
| | | { |
| | | // We can export all the monitor entries as a point-in-time snapshot. |
| | | // TODO implementation of export is incomplete |
| | | // TODO export-ldif reports nonsense for upTime etc. |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void exportLDIF(LDIFExportConfig exportConfig) |
| | | throws DirectoryException |
| | | { |
| | | // TODO export-ldif reports nonsense for upTime etc. |
| | | |
| | | // Create the LDIF writer. |
| | | LDIFWriter ldifWriter; |
| | | try |
| | | { |
| | | ldifWriter = new LDIFWriter(exportConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | Message message = ERR_ROOTDSE_UNABLE_TO_CREATE_LDIF_WRITER.get( |
| | | stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | } |
| | | |
| | | |
| | | // Write the base monitor entry to the LDIF. |
| | | try |
| | | { |
| | | ldifWriter.writeEntry(getBaseMonitorEntry()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | try |
| | | { |
| | | ldifWriter.close(); |
| | | } |
| | | catch (Exception e2) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e2); |
| | | } |
| | | } |
| | | |
| | | Message message = ERR_MONITOR_UNABLE_TO_EXPORT_BASE.get( |
| | | stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | } |
| | | |
| | | |
| | | // Get all the monitor providers, convert them to entries, and write them to |
| | | // LDIF. |
| | | for (MonitorProvider<?> monitorProvider : |
| | | DirectoryServer.getMonitorProviders().values()) |
| | | { |
| | | try |
| | | { |
| | | // TODO implementation of export is incomplete |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | try |
| | | { |
| | | ldifWriter.close(); |
| | | } |
| | | catch (Exception e2) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e2); |
| | | } |
| | | } |
| | | |
| | | Message message = ERR_MONITOR_UNABLE_TO_EXPORT_PROVIDER_ENTRY. |
| | | get(monitorProvider.getMonitorInstanceName(), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | } |
| | | } |
| | | |
| | | |
| | | // Close the monitor provider and return. |
| | | try |
| | | { |
| | | ldifWriter.close(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean supportsLDIFImport() |
| | | { |
| | | // This backend does not support LDIF imports. |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public LDIFImportResult importLDIF(LDIFImportConfig importConfig) |
| | | throws DirectoryException |
| | | { |
| | | // This backend does not support LDIF imports. |
| | | Message message = ERR_MONITOR_IMPORT_NOT_SUPPORTED.get(); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean supportsBackup() |
| | | { |
| | | // This backend does not provide a backup/restore mechanism. |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean supportsBackup(BackupConfig backupConfig, |
| | | StringBuilder unsupportedReason) |
| | | { |
| | | // This backend does not provide a backup/restore mechanism. |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void createBackup(BackupConfig backupConfig) |
| | | throws DirectoryException |
| | | { |
| | | // This backend does not provide a backup/restore mechanism. |
| | | Message message = ERR_MONITOR_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void removeBackup(BackupDirectory backupDirectory, |
| | | String backupID) |
| | | throws DirectoryException |
| | | { |
| | | // This backend does not provide a backup/restore mechanism. |
| | | Message message = ERR_MONITOR_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean supportsRestore() |
| | | { |
| | | // This backend does not provide a backup/restore mechanism. |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void restoreBackup(RestoreConfig restoreConfig) |
| | | throws DirectoryException |
| | | { |
| | | // This backend does not provide a backup/restore mechanism. |
| | | Message message = ERR_MONITOR_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | MonitorBackendCfg backendCfg, |
| | | List<Message> unacceptableReasons) |
| | | { |
| | | // We'll pretty much accept anything here as long as it isn't one of our |
| | | // private attributes. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | MonitorBackendCfg backendCfg) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<Message> messages = new ArrayList<Message>(); |
| | | |
| | | |
| | | // Check to see if there is a new set of user-defined attributes. |
| | | ArrayList<Attribute> userAttrs = new ArrayList<Attribute>(); |
| | | try |
| | | { |
| | | ConfigEntry configEntry = DirectoryServer.getConfigEntry(configEntryDN); |
| | | for (List<Attribute> attrs : |
| | | configEntry.getEntry().getUserAttributes().values()) |
| | | { |
| | | for (Attribute a : attrs) |
| | | { |
| | | if (! isMonitorConfigAttribute(a)) |
| | | { |
| | | userAttrs.add(a); |
| | | } |
| | | } |
| | | } |
| | | for (List<Attribute> attrs : |
| | | configEntry.getEntry().getOperationalAttributes().values()) |
| | | { |
| | | for (Attribute a : attrs) |
| | | { |
| | | if (! isMonitorConfigAttribute(a)) |
| | | { |
| | | userAttrs.add(a); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | |
| | | messages.add(ERR_CONFIG_BACKEND_ERROR_INTERACTING_WITH_BACKEND_ENTRY.get( |
| | | String.valueOf(configEntryDN), |
| | | stackTraceToSingleLineString(e))); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | } |
| | | |
| | | |
| | | userDefinedAttributes = userAttrs; |
| | | |
| | | Message message = INFO_MONITOR_USING_NEW_USER_ATTRS.get(); |
| | | messages.add(message); |
| | | |
| | | |
| | | currentConfig = backendCfg; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void preloadEntryCache() throws UnsupportedOperationException { |
| | | throw new UnsupportedOperationException("Operation not supported."); |
| | | } |
| | | |
| | | // Private Methods |
| | | private boolean isATreeNode(DN dn) { |
| | | boolean found=false; |
| | | |
| | | if (dn.equals(baseMonitorDN)) { |
| | | return true; |
| | | } |
| | | for (MonitorProvider<? extends MonitorProviderCfg> monitorProvider : |
| | | DirectoryServer.getMonitorProviders().values()) { |
| | | DN providerDN = DirectoryServer.getMonitorProviderDN(monitorProvider); |
| | | if ((dn.isAncestorOf(providerDN)) || |
| | | (dn.equals(providerDN))) { |
| | | found=true; |
| | | return (found); |
| | | } |
| | | } |
| | | return (found); |
| | | } |
| | | |
| | | private String getRdns(DN dn) { |
| | | int index = dn.toString().lastIndexOf(","); |
| | | return dn.toString().substring(3, index); |
| | | } |
| | | |
| | | /** |
| | | * Creates an attribute for a monitor entry with the following criteria. |
| | | * |
| | | * @param name The name for the attribute. |
| | | * @param lowerName The name for the attribute formatted in all lowercase |
| | | * characters. |
| | | * @param value The value to use for the attribute. |
| | | * |
| | | * @return The constructed attribute. |
| | | */ |
| | | private Attribute createAttribute(String name, String lowerName, |
| | | String value) { |
| | | return Attributes.create(name, value); |
| | | return false; |
| | | } |
| | | |
| | | } |