| | |
| | | * |
| | | * |
| | | * Copyright 2007-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011 ForgeRock AS |
| | | * Portions Copyright 2011-2013 ForgeRock AS |
| | | */ |
| | | package org.opends.server.backends; |
| | | |
| | | |
| | | |
| | | import java.io.File; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.*; |
| | | import java.util.concurrent.locks.ReentrantReadWriteLock; |
| | | |
| | | import org.opends.messages.Message; |
| | |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.controls.SubtreeDeleteControl; |
| | | import org.opends.server.core.AddOperation; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.core.ModifyDNOperation; |
| | | import org.opends.server.core.SearchOperation; |
| | | import org.opends.server.core.*; |
| | | import org.opends.server.loggers.debug.DebugTracer; |
| | | import org.opends.server.types.AttributeType; |
| | | 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.Control; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.ExistingFileBehavior; |
| | | 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.RestoreConfig; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.SearchScope; |
| | | import org.opends.server.util.LDIFException; |
| | | import org.opends.server.util.LDIFReader; |
| | | import org.opends.server.util.LDIFWriter; |
| | | import org.opends.server.util.Validator; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.util.*; |
| | | |
| | | import static org.opends.messages.BackendMessages.*; |
| | | import static org.opends.server.loggers.ErrorLogger.*; |
| | |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class provides a backend implementation that stores the underlying data |
| | | * in an LDIF file. When the backend is initialized, the contents of the |
| | |
| | | |
| | | |
| | | |
| | | // The base DNs for this backend. |
| | | /** The base DNs for this backend. */ |
| | | private DN[] baseDNs; |
| | | |
| | | // The mapping between parent DNs and their immediate children. |
| | | private final HashMap<DN,HashSet<DN>> childDNs; |
| | | /** The mapping between parent DNs and their immediate children. */ |
| | | private final Map<DN, Set<DN>> childDNs; |
| | | |
| | | // The base DNs for this backend, in a hash set. |
| | | private HashSet<DN> baseDNSet; |
| | | /** The base DNs for this backend, in a hash set. */ |
| | | private Set<DN> baseDNSet; |
| | | |
| | | // The set of supported controls for this backend. |
| | | private HashSet<String> supportedControls; |
| | | /** The set of supported controls for this backend. */ |
| | | private Set<String> supportedControls; |
| | | |
| | | // The set of supported features for this backend. |
| | | private HashSet<String> supportedFeatures; |
| | | /** The set of supported features for this backend. */ |
| | | private Set<String> supportedFeatures; |
| | | |
| | | // The current configuration for this backend. |
| | | /** The current configuration for this backend. */ |
| | | private LDIFBackendCfg currentConfig; |
| | | |
| | | // The mapping between entry DNs and the corresponding entries. |
| | | private final LinkedHashMap<DN,Entry> entryMap; |
| | | /** The mapping between entry DNs and the corresponding entries. */ |
| | | private final Map<DN, Entry> entryMap; |
| | | |
| | | // A read-write lock used to protect access to this backend. |
| | | /** A read-write lock used to protect access to this backend. */ |
| | | private final ReentrantReadWriteLock backendLock; |
| | | |
| | | // The path to the LDIF file containing the data for this backend. |
| | | /** The path to the LDIF file containing the data for this backend. */ |
| | | private String ldifFilePath; |
| | | |
| | | |
| | |
| | | super(); |
| | | |
| | | entryMap = new LinkedHashMap<DN,Entry>(); |
| | | childDNs = new HashMap<DN,HashSet<DN>>(); |
| | | childDNs = new HashMap<DN, Set<DN>>(); |
| | | |
| | | boolean useFairLocking = |
| | | DirectoryServer.getEnvironmentConfig().getLockManagerFairOrdering(); |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void initializeBackend() |
| | | throws ConfigException, InitializationException |
| | |
| | | // implementation. If we were to add such support in the future, we would |
| | | // likely want to separate the data for each base DN into a separate entry |
| | | // map. |
| | | if ((baseDNs == null) || (baseDNs.length != 1)) |
| | | if (baseDNs == null || baseDNs.length != 1) |
| | | { |
| | | Message message = ERR_LDIF_BACKEND_MULTIPLE_BASE_DNS.get( |
| | | currentConfig.dn().toString()); |
| | |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | try |
| | | { |
| | | writer.close(); |
| | | } catch (Exception e2) {} |
| | | StaticUtils.close(writer); |
| | | |
| | | Message m = ERR_LDIF_BACKEND_ERROR_WRITING_FILE.get( |
| | | tempFile.getAbsolutePath(), |
| | |
| | | } |
| | | } |
| | | |
| | | try |
| | | { |
| | | writer.close(); |
| | | } catch (Exception e) {} |
| | | StaticUtils.close(writer); |
| | | |
| | | |
| | | // Rename the existing "live" file out of the way and move the new file |
| | |
| | | { |
| | | oldFile.delete(); |
| | | } |
| | | } catch (Exception e) {} |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | |
| | | try |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void finalizeBackend() |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public DN[] getBaseDNs() |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public long getEntryCount() |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public boolean isLocal() |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public boolean isIndexed(AttributeType attributeType, IndexType indexType) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public ConditionResult hasSubordinates(DN entryDN) |
| | | throws DirectoryException |
| | |
| | | |
| | | try |
| | | { |
| | | HashSet<DN> childDNSet = childDNs.get(entryDN); |
| | | if ((childDNSet == null) || childDNSet.isEmpty()) |
| | | Set<DN> childDNSet = childDNs.get(entryDN); |
| | | if (childDNSet == null || childDNSet.isEmpty()) |
| | | { |
| | | // It could be that the entry doesn't exist, in which case we should |
| | | // throw an exception. |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public long numSubordinates(DN entryDN, boolean subtree) |
| | | throws DirectoryException |
| | |
| | | |
| | | try |
| | | { |
| | | HashSet<DN> childDNSet = childDNs.get(entryDN); |
| | | if ((childDNSet == null) || childDNSet.isEmpty()) |
| | | Set<DN> childDNSet = childDNs.get(entryDN); |
| | | if (childDNSet == null || childDNSet.isEmpty()) |
| | | { |
| | | // It could be that the entry doesn't exist, in which case we should |
| | | // throw an exception. |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public Entry getEntry(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public boolean entryExists(DN entryDN) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void addEntry(Entry entry, AddOperation addOperation) |
| | | throws DirectoryException |
| | |
| | | else |
| | | { |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if ((parentDN != null) && entryMap.containsKey(parentDN)) |
| | | if (parentDN != null && entryMap.containsKey(parentDN)) |
| | | { |
| | | entryMap.put(entryDN, entry.duplicate(false)); |
| | | |
| | | HashSet<DN> childDNSet = childDNs.get(parentDN); |
| | | Set<DN> childDNSet = childDNs.get(parentDN); |
| | | if (childDNSet == null) |
| | | { |
| | | childDNSet = new HashSet<DN>(); |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void deleteEntry(DN entryDN, DeleteOperation deleteOperation) |
| | | throws DirectoryException |
| | |
| | | // See if the target entry has any children. If so, then we'll only |
| | | // delete it if the request contains the subtree delete control (in |
| | | // which case we'll delete the entire subtree). |
| | | HashSet<DN> childDNSet = childDNs.get(entryDN); |
| | | if ((childDNSet == null) || childDNSet.isEmpty()) |
| | | Set<DN> childDNSet = childDNs.get(entryDN); |
| | | if (childDNSet == null || childDNSet.isEmpty()) |
| | | { |
| | | entryMap.remove(entryDN); |
| | | childDNs.remove(entryDN); |
| | | |
| | | if (parentDN != null) |
| | | { |
| | | HashSet<DN> parentChildren = childDNs.get(parentDN); |
| | | Set<DN> parentChildren = childDNs.get(parentDN); |
| | | if (parentChildren != null) |
| | | { |
| | | parentChildren.remove(entryDN); |
| | |
| | | } |
| | | else |
| | | { |
| | | boolean subtreeDelete = false; |
| | | |
| | | if (deleteOperation != null |
| | | boolean subtreeDelete = deleteOperation != null |
| | | && deleteOperation |
| | | .getRequestControl(SubtreeDeleteControl.DECODER) != null) |
| | | { |
| | | subtreeDelete = true; |
| | | } |
| | | .getRequestControl(SubtreeDeleteControl.DECODER) != null; |
| | | |
| | | if (! subtreeDelete) |
| | | { |
| | |
| | | |
| | | if (parentDN != null) |
| | | { |
| | | HashSet<DN> parentChildren = childDNs.get(parentDN); |
| | | Set<DN> parentChildren = childDNs.get(parentDN); |
| | | if (parentChildren != null) |
| | | { |
| | | parentChildren.remove(entryDN); |
| | |
| | | private void subtreeDelete(DN entryDN) |
| | | { |
| | | entryMap.remove(entryDN); |
| | | HashSet<DN> childDNSet = childDNs.remove(entryDN); |
| | | Set<DN> childDNSet = childDNs.remove(entryDN); |
| | | if (childDNSet != null) |
| | | { |
| | | for (DN childDN : childDNSet) |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void replaceEntry(Entry oldEntry, Entry newEntry, |
| | | ModifyOperation modifyOperation) throws DirectoryException |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void renameEntry(DN currentDN, Entry entry, |
| | | ModifyDNOperation modifyDNOperation) |
| | |
| | | // Remove the entry from the list of children for the old parent and |
| | | // add the new entry DN to the set of children for the new parent. |
| | | DN oldParentDN = currentDN.getParentDNInSuffix(); |
| | | HashSet<DN> parentChildDNs = childDNs.get(oldParentDN); |
| | | Set<DN> parentChildDNs = childDNs.get(oldParentDN); |
| | | if (parentChildDNs != null) |
| | | { |
| | | parentChildDNs.remove(currentDN); |
| | | if (parentChildDNs.isEmpty() && |
| | | (modifyDNOperation.getNewSuperior() != null)) |
| | | if (parentChildDNs.isEmpty() |
| | | && modifyDNOperation.getNewSuperior() != null) |
| | | { |
| | | childDNs.remove(oldParentDN); |
| | | } |
| | |
| | | // If the entry has children, then we'll need to work on the whole |
| | | // subtree. Otherwise, just work on the target entry. |
| | | Set<DN> childDNSet = childDNs.remove(currentDN); |
| | | if ((childDNSet == null) || childDNSet.isEmpty()) |
| | | entryMap.remove(currentDN); |
| | | entryMap.put(newDN, entry.duplicate(false)); |
| | | if (childDNSet != null && !childDNSet.isEmpty()) |
| | | { |
| | | entryMap.remove(currentDN); |
| | | entryMap.put(newDN, entry.duplicate(false)); |
| | | writeLDIF(); |
| | | return; |
| | | } |
| | | else |
| | | { |
| | | entryMap.remove(currentDN); |
| | | entryMap.put(newDN, entry.duplicate(false)); |
| | | for (DN childDN : childDNSet) |
| | | { |
| | | subtreeRename(childDN, newDN); |
| | | } |
| | | writeLDIF(); |
| | | return; |
| | | } |
| | | writeLDIF(); |
| | | } |
| | | finally |
| | | { |
| | |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugWarning("Subtree rename encountered entry DN " + |
| | | entryDN.toString() + " for nonexistent entry."); |
| | | entryDN + " for nonexistent entry."); |
| | | } |
| | | return; |
| | | } |
| | |
| | | newEntry.setDN(newEntryDN); |
| | | entryMap.put(newEntryDN, newEntry); |
| | | |
| | | HashSet<DN> parentChildren = childDNs.get(newParentDN); |
| | | Set<DN> parentChildren = childDNs.get(newParentDN); |
| | | if (parentChildren == null) |
| | | { |
| | | parentChildren = new HashSet<DN>(); |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void search(SearchOperation searchOperation) |
| | | throws DirectoryException |
| | |
| | | |
| | | // Make sure the base entry exists if it's supposed to be in this backend. |
| | | Entry baseEntry = entryMap.get(baseDN); |
| | | if ((baseEntry == null) && handlesEntry(baseDN)) |
| | | if (baseEntry == null && handlesEntry(baseDN)) |
| | | { |
| | | DN matchedDN = baseDN.getParentDNInSuffix(); |
| | | while (matchedDN != null) |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public HashSet<String> getSupportedControls() |
| | | public Set<String> getSupportedControls() |
| | | { |
| | | return supportedControls; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public HashSet<String> getSupportedFeatures() |
| | | public Set<String> getSupportedFeatures() |
| | | { |
| | | return supportedFeatures; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public boolean supportsLDIFExport() |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void exportLDIF(LDIFExportConfig exportConfig) |
| | | throws DirectoryException |
| | |
| | | } |
| | | finally |
| | | { |
| | | try |
| | | { |
| | | ldifWriter.close(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | StaticUtils.close(ldifWriter); |
| | | } |
| | | } |
| | | finally |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public boolean supportsLDIFImport() |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public LDIFImportResult importLDIF(LDIFImportConfig importConfig) |
| | | throws DirectoryException |
| | |
| | | } |
| | | |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if ((parentDN == null) || (! entryMap.containsKey(parentDN))) |
| | | if (parentDN == null || !entryMap.containsKey(parentDN)) |
| | | { |
| | | Message m = ERR_LDIF_BACKEND_MISSING_PARENT.get(ldifFilePath, |
| | | currentConfig.dn().toString(), entryDN.toString()); |
| | |
| | | // the set of children for the parent. |
| | | entryMap.put(entryDN, e); |
| | | |
| | | HashSet<DN> childDNSet = childDNs.get(parentDN); |
| | | Set<DN> childDNSet = childDNs.get(parentDN); |
| | | if (childDNSet == null) |
| | | { |
| | | childDNSet = new HashSet<DN>(); |
| | |
| | | } |
| | | finally |
| | | { |
| | | reader.close(); |
| | | StaticUtils.close(reader); |
| | | } |
| | | } |
| | | finally |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public boolean supportsBackup() |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public boolean supportsBackup(BackupConfig backupConfig, |
| | | StringBuilder unsupportedReason) |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void createBackup(BackupConfig backupConfig) |
| | | throws DirectoryException |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void removeBackup(BackupDirectory backupDirectory, String backupID) |
| | | throws DirectoryException |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public boolean supportsRestore() |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void restoreBackup(RestoreConfig restoreConfig) |
| | | throws DirectoryException |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override() |
| | | public void configureBackend(Configuration config) |
| | | throws ConfigException |
| | |
| | | } |
| | | |
| | | baseDNSet = new HashSet<DN>(); |
| | | for (DN dn : baseDNs) |
| | | { |
| | | baseDNSet.add(dn); |
| | | } |
| | | Collections.addAll(baseDNSet, baseDNs); |
| | | |
| | | supportedControls = new HashSet<String>(1); |
| | | supportedControls.add(OID_SUBTREE_DELETE_CONTROL); |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isConfigurationChangeAcceptable(LDIFBackendCfg configuration, |
| | | List<Message> unacceptableReasons) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | LDIFBackendCfg configuration) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | if (baseDNSet != null) |
| | | if (baseDNSet != null && !baseDNSet.equals(configuration.getBaseDN())) |
| | | { |
| | | if (! baseDNSet.equals(configuration.getBaseDN())) |
| | | { |
| | | messages.add(INFO_LDIF_BACKEND_BASE_DN_CHANGED.get()); |
| | | adminActionRequired = true; |
| | | } |
| | | messages.add(INFO_LDIF_BACKEND_BASE_DN_CHANGED.get()); |
| | | adminActionRequired = true; |
| | | } |
| | | |
| | | currentConfig = configuration; |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public DN getComponentEntryDN() |
| | | { |
| | | return currentConfig.dn(); |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String getClassName() |
| | | { |
| | | return LDIFBackend.class.getName(); |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public LinkedHashMap<String,String> getAlerts() |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Map<String,String> getAlerts() |
| | | { |
| | | LinkedHashMap<String,String> alerts = new LinkedHashMap<String,String>(); |
| | | Map<String,String> alerts = new LinkedHashMap<String,String>(); |
| | | |
| | | alerts.put(ALERT_TYPE_LDIF_BACKEND_CANNOT_WRITE_UPDATE, |
| | | ALERT_DESCRIPTION_LDIF_BACKEND_CANNOT_WRITE_UPDATE); |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void preloadEntryCache() throws UnsupportedOperationException { |
| | | throw new UnsupportedOperationException("Operation not supported."); |
| | | } |
| | | } |
| | | |