code cleanup
Use try-with-resources
Removed {@inheritDoc}
Removed code duplication
| | |
| | | { |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | |
| | | |
| | | /** The current configuration state. */ |
| | | private BackupBackendCfg currentConfig; |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Creates a new backend with the provided information. All backend |
| | | * implementations must implement a default constructor that use |
| | |
| | | // Perform all initialization in initializeBackend. |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void configureBackend(BackupBackendCfg config, ServerContext serverContext) throws ConfigException |
| | | { |
| | |
| | | currentConfig = config; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void openBackend() |
| | | throws ConfigException, InitializationException |
| | |
| | | |
| | | this.baseDNs = Collections.singleton(backupBaseDN); |
| | | |
| | | |
| | | // Determine the set of backup directories that we will use by default. |
| | | Set<String> values = currentConfig.getBackupDirectory(); |
| | | backupDirectories = new LinkedHashMap<>(values.size()); |
| | |
| | | backupDirectories.put(dir, new CachedBackupDirectory(dir)); |
| | | } |
| | | |
| | | |
| | | // Construct the backup base entry. |
| | | LinkedHashMap<ObjectClass,String> objectClasses = new LinkedHashMap<>(2); |
| | | objectClasses.put(DirectoryServer.getTopObjectClass(), OC_TOP); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void closeBackend() |
| | | { |
| | |
| | | return numEntries; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isIndexed(AttributeType attributeType, IndexType indexType) |
| | | { |
| | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConditionResult hasSubordinates(DN entryDN) throws DirectoryException |
| | | { |
| | |
| | | return ConditionResult.valueOf(ret != 0); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfEntriesInBaseDN(DN baseDN) throws DirectoryException { |
| | | checkNotNull(baseDN, "baseDN must not be null"); |
| | | return getNumberOfSubordinates(baseDN, true) + 1; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfChildren(DN parentDN) throws DirectoryException { |
| | | checkNotNull(parentDN, "parentDN must not be null"); |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Entry getEntry(DN entryDN) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_GET_ENTRY_NULL.get(getBackendID())); |
| | | } |
| | | |
| | | |
| | | // If the requested entry was the backend base entry, then retrieve it. |
| | | if (entryDN.equals(backupBaseDN)) |
| | | { |
| | | return backupBaseEntry.duplicate(true); |
| | | } |
| | | |
| | | |
| | | // See if the requested entry was one level below the backend base entry. |
| | | // If so, then it must point to a backup directory. Otherwise, it must be |
| | | // two levels below the backup base entry and must point to a specific |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Generates an entry for a backup directory based on the provided DN. The |
| | | * DN must contain an RDN component that specifies the path to the backup |
| | |
| | | backupBaseDN, null); |
| | | } |
| | | |
| | | |
| | | // Get a handle to the backup directory and the information that it |
| | | // contains. |
| | | BackupDirectory backupDirectory; |
| | |
| | | message); |
| | | } |
| | | |
| | | |
| | | // Construct the backup directory entry to return. |
| | | LinkedHashMap<ObjectClass,String> ocMap = new LinkedHashMap<>(2); |
| | | ocMap.put(DirectoryServer.getTopObjectClass(), OC_TOP); |
| | |
| | | return e; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Generates an entry for a backup based on the provided DN. The DN must |
| | | * have an RDN component that specifies the backup ID, and the parent DN must |
| | |
| | | return new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void addEntry(Entry entry, AddOperation addOperation) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_ADD_NOT_SUPPORTED.get(entry.getName(), getBackendID())); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void deleteEntry(DN entryDN, DeleteOperation deleteOperation) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_DELETE_NOT_SUPPORTED.get(entryDN, getBackendID())); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void replaceEntry(Entry oldEntry, Entry newEntry, |
| | | ModifyOperation modifyOperation) throws DirectoryException |
| | |
| | | ERR_BACKEND_MODIFY_NOT_SUPPORTED.get(oldEntry.getName(), getBackendID())); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void renameEntry(DN currentDN, Entry entry, |
| | | ModifyDNOperation modifyDNOperation) |
| | |
| | | ERR_BACKEND_MODIFY_DN_NOT_SUPPORTED.get(currentDN, getBackendID())); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void search(SearchOperation searchOperation) |
| | | throws DirectoryException |
| | |
| | | DN baseDN = searchOperation.getBaseDN(); |
| | | Entry baseEntry = getEntry(baseDN); |
| | | |
| | | |
| | | // Look at the base DN and see if it's the backup base DN, a backup |
| | | // directory entry DN, or a backup entry DN. |
| | | DN parentDN; |
| | |
| | | continue; |
| | | } |
| | | |
| | | |
| | | DN backupDirDN = makeChildDN(backupBaseDN, backupPathType, |
| | | dir.getAbsolutePath()); |
| | | |
| | |
| | | searchOperation.returnEntry(backupDirEntry, null); |
| | | } |
| | | |
| | | |
| | | if (scope != SearchScope.BASE_OBJECT) |
| | | { |
| | | AttributeType t = |
| | |
| | | ERR_BACKEND_IMPORT_AND_EXPORT_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext serverContext) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_IMPORT_AND_EXPORT_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void createBackup(BackupConfig backupConfig) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void removeBackup(BackupDirectory backupDirectory, |
| | | String backupID) |
| | |
| | | ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void restoreBackup(RestoreConfig restoreConfig) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isConfigurationChangeAcceptable( |
| | | BackupBackendCfg cfg, List<LocalizableMessage> unacceptableReasons) |
| | |
| | | return true; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConfigChangeResult applyConfigurationChange(BackupBackendCfg cfg) |
| | | { |
| | |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.config.server.ConfigChangeResult; |
| | | import org.forgerock.opendj.config.server.ConfigException; |
| | | import org.forgerock.opendj.config.server.ConfigurationChangeListener; |
| | | import org.forgerock.opendj.ldap.ConditionResult; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.SearchScope; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | | import org.forgerock.opendj.config.server.ConfigurationChangeListener; |
| | | import org.forgerock.opendj.server.config.server.LDIFBackendCfg; |
| | | import org.opends.server.api.AlertGenerator; |
| | | import org.opends.server.api.Backend; |
| | |
| | | { |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | |
| | | |
| | | /** The base DNs for this backend. */ |
| | | private Set<DN> baseDNs; |
| | | |
| | |
| | | { |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void openBackend() |
| | | throws ConfigException, InitializationException |
| | |
| | | readLDIF(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Reads the contents of the LDIF backing file into memory. |
| | | * |
| | |
| | | return; |
| | | } |
| | | |
| | | |
| | | try |
| | | { |
| | | importLDIF(new LDIFImportConfig(ldifFile.getAbsolutePath()), false); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Writes the current set of entries to the target LDIF file. The new LDIF |
| | | * will first be created as a temporary file and then renamed into place. The |
| | |
| | | File tempFile = new File(ldifFile.getAbsolutePath() + ".new"); |
| | | File oldFile = new File(ldifFile.getAbsolutePath() + ".old"); |
| | | |
| | | |
| | | // Write the new data to a temporary file. |
| | | LDIFWriter writer; |
| | | try |
| | |
| | | m, e); |
| | | } |
| | | |
| | | |
| | | for (Entry entry : entryMap.values()) |
| | | { |
| | | try |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void closeBackend() |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isIndexed(AttributeType attributeType, IndexType indexType) |
| | | { |
| | |
| | | return true; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConditionResult hasSubordinates(DN entryDN) |
| | | throws DirectoryException |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfChildren(DN parentDN) throws DirectoryException |
| | | { |
| | |
| | | return getNumberOfSubordinates(parentDN, false); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfEntriesInBaseDN(DN baseDN) throws DirectoryException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Entry getEntry(DN entryDN) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean entryExists(DN entryDN) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void addEntry(Entry entry, AddOperation addOperation) |
| | | throws DirectoryException |
| | |
| | | } |
| | | else |
| | | { |
| | | DN matchedDN = null; |
| | | if (parentDN != null) |
| | | { |
| | | while (true) |
| | | { |
| | | parentDN = DirectoryServer.getParentDNInSuffix(parentDN); |
| | | if (parentDN == null) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | if (entryMap.containsKey(parentDN)) |
| | | { |
| | | matchedDN = parentDN; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | LocalizableMessage m = ERR_LDIF_BACKEND_ADD_MISSING_PARENT.get(entryDN); |
| | | throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, m, matchedDN, null); |
| | | throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, m, findMatchedDN(parentDN), null); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | private DN findMatchedDN(DN parentDN) |
| | | { |
| | | if (parentDN != null) |
| | | { |
| | | while (true) |
| | | { |
| | | parentDN = DirectoryServer.getParentDNInSuffix(parentDN); |
| | | if (parentDN == null) |
| | | { |
| | | return null; |
| | | } |
| | | else if (entryMap.containsKey(parentDN)) |
| | | { |
| | | return parentDN; |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public void deleteEntry(DN entryDN, DeleteOperation deleteOperation) |
| | | throws DirectoryException |
| | |
| | | throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, m, matchedDN, null); |
| | | } |
| | | |
| | | |
| | | // 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). |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Removes the specified entry and any subordinates that it may have from |
| | | * the backend. This method assumes that the caller holds the backend write |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void replaceEntry(Entry oldEntry, Entry newEntry, |
| | | ModifyOperation modifyOperation) throws DirectoryException |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void renameEntry(DN currentDN, Entry entry, |
| | | ModifyDNOperation modifyDNOperation) |
| | |
| | | } |
| | | parentChildDNs.add(newDN); |
| | | |
| | | |
| | | // 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); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Moves the specified entry and all of its children so that they are |
| | | * appropriately placed below the given new parent DN. This method assumes |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void search(SearchOperation searchOperation) |
| | | throws DirectoryException |
| | |
| | | SearchScope scope = searchOperation.getScope(); |
| | | SearchFilter filter = searchOperation.getFilter(); |
| | | |
| | | |
| | | // 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)) |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedControls() |
| | | { |
| | | return supportedControls; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedFeatures() |
| | | { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean supports(BackendOperation backendOperation) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void exportLDIF(LDIFExportConfig exportConfig) |
| | | throws DirectoryException |
| | | { |
| | | backendLock.readLock().lock(); |
| | | |
| | | try |
| | | try (LDIFWriter ldifWriter = newLDIFWriter(exportConfig)) |
| | | { |
| | | // Create the LDIF writer. |
| | | LDIFWriter ldifWriter; |
| | | try |
| | | { |
| | | ldifWriter = new LDIFWriter(exportConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | LocalizableMessage m = ERR_LDIF_BACKEND_CANNOT_CREATE_LDIF_WRITER.get( |
| | | stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | m, e); |
| | | } |
| | | |
| | | |
| | | // Walk through all the entries and write them to LDIF. |
| | | DN entryDN = null; |
| | | try |
| | | for (Entry entry : entryMap.values()) |
| | | { |
| | | for (Entry entry : entryMap.values()) |
| | | DN entryDN = entry.getName(); |
| | | try |
| | | { |
| | | entryDN = entry.getName(); |
| | | ldifWriter.writeEntry(entry); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | LocalizableMessage m = |
| | | ERR_LDIF_BACKEND_CANNOT_WRITE_ENTRY_TO_LDIF.get(entryDN, stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), m, e); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | LocalizableMessage m = ERR_LDIF_BACKEND_CANNOT_WRITE_ENTRY_TO_LDIF.get( |
| | | entryDN, stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | m, e); |
| | | } |
| | | finally |
| | | { |
| | | StaticUtils.close(ldifWriter); |
| | | } |
| | | } |
| | | catch (IOException ignoreOnClose) |
| | | { |
| | | logger.traceException(ignoreOnClose); |
| | | } |
| | | finally |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | private LDIFWriter newLDIFWriter(LDIFExportConfig exportConfig) throws DirectoryException |
| | | { |
| | | try |
| | | { |
| | | return new LDIFWriter(exportConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | logger.traceException(e); |
| | | LocalizableMessage m = ERR_LDIF_BACKEND_CANNOT_CREATE_LDIF_WRITER.get(stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), m, e); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext serverContext) |
| | | throws DirectoryException |
| | |
| | | { |
| | | backendLock.writeLock().lock(); |
| | | |
| | | try |
| | | try (LDIFReader reader = newLDIFReader(importConfig)) |
| | | { |
| | | LDIFReader reader; |
| | | try |
| | | { |
| | | reader = new LDIFReader(importConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | LocalizableMessage m = ERR_LDIF_BACKEND_CANNOT_CREATE_LDIF_READER.get( |
| | | stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | m, e); |
| | | } |
| | | |
| | | entryMap.clear(); |
| | | childDNs.clear(); |
| | | |
| | | |
| | | try |
| | | { |
| | | while (true) |
| | |
| | | throw new DirectoryException( |
| | | DirectoryServer.getServerErrorResultCode(), m, le); |
| | | } |
| | | else |
| | | { |
| | | continue; |
| | | } |
| | | continue; |
| | | } |
| | | |
| | | // Make sure that we don't already have an entry with the same DN. If |
| | |
| | | continue; |
| | | } |
| | | |
| | | |
| | | // If the entry DN is a base DN, then add it with no more processing. |
| | | if (baseDNs.contains(entryDN)) |
| | | { |
| | |
| | | continue; |
| | | } |
| | | |
| | | |
| | | // Make sure that the parent exists. If not, then reject the entry. |
| | | boolean isBelowBaseDN = false; |
| | | for (DN baseDN : baseDNs) |
| | | { |
| | | if (baseDN.isSuperiorOrEqualTo(entryDN)) |
| | | { |
| | | isBelowBaseDN = true; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (! isBelowBaseDN) |
| | | if (!isBelowBaseDN(entryDN)) |
| | | { |
| | | LocalizableMessage m = ERR_LDIF_BACKEND_ENTRY_OUT_OF_SCOPE.get( |
| | | ldifFilePath, currentConfig.dn(), entryDN); |
| | |
| | | continue; |
| | | } |
| | | |
| | | |
| | | // The entry does not exist but its parent does, so add it and update |
| | | // the set of children for the parent. |
| | | entryMap.put(entryDN, e); |
| | |
| | | childDNSet.add(entryDN); |
| | | } |
| | | |
| | | |
| | | if (writeLDIF) |
| | | { |
| | | writeLDIF(); |
| | |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | LocalizableMessage m = ERR_LDIF_BACKEND_ERROR_READING_LDIF.get( |
| | | stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | m, e); |
| | | } |
| | | finally |
| | | { |
| | | StaticUtils.close(reader); |
| | | LocalizableMessage m = ERR_LDIF_BACKEND_ERROR_READING_LDIF.get(stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), m, e); |
| | | } |
| | | } |
| | | finally |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | private boolean isBelowBaseDN(DN entryDN) |
| | | { |
| | | for (DN baseDN : baseDNs) |
| | | { |
| | | if (baseDN.isSuperiorOrEqualTo(entryDN)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private LDIFReader newLDIFReader(LDIFImportConfig importConfig) throws DirectoryException |
| | | { |
| | | try |
| | | { |
| | | return new LDIFReader(importConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | LocalizableMessage m = ERR_LDIF_BACKEND_CANNOT_CREATE_LDIF_READER.get(stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), m, e); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void createBackup(BackupConfig backupConfig) |
| | | throws DirectoryException |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void removeBackup(BackupDirectory backupDirectory, String backupID) |
| | | throws DirectoryException |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void restoreBackup(RestoreConfig restoreConfig) |
| | | throws DirectoryException |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void configureBackend(LDIFBackendCfg config, ServerContext serverContext) throws ConfigException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isConfigurationChangeAcceptable(LDIFBackendCfg configuration, |
| | | List<LocalizableMessage> unacceptableReasons) |
| | |
| | | return configAcceptable; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | LDIFBackendCfg configuration) |
| | |
| | | return ccr; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public DN getComponentEntryDN() |
| | | { |
| | | return currentConfig.dn(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String getClassName() |
| | | { |
| | | return LDIFBackend.class.getName(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Map<String,String> getAlerts() |
| | | { |
| | |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedList; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.config.server.ConfigException; |
| | | import org.forgerock.opendj.ldap.ConditionResult; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.SearchScope; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | |
| | | import org.opends.server.types.BackupConfig; |
| | | import org.opends.server.types.BackupDirectory; |
| | | import org.opends.server.types.Control; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.IndexType; |
| | |
| | | { |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | |
| | | /** The set of supported controls for this backend. */ |
| | | private static final Set<String> supportedControls = Collections.singleton(OID_SUBTREE_DELETE_CONTROL); |
| | | |
| | | /** The base DNs for this backend. */ |
| | | private Set<DN> baseDNs; |
| | | |
| | | /** The mapping between parent DNs and their immediate children. */ |
| | | private HashMap<DN,HashSet<DN>> childDNs; |
| | | |
| | | /** The set of supported controls for this backend. */ |
| | | private final Set<String> supportedControls = |
| | | Collections.singleton(OID_SUBTREE_DELETE_CONTROL); |
| | | |
| | | private Map<DN, HashSet<DN>> childDNs; |
| | | /** The mapping between entry DNs and the corresponding entries. */ |
| | | private LinkedHashMap<DN,Entry> entryMap; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new backend with the provided information. All backend |
| | | * implementations must implement a default constructor that use |
| | |
| | | // Perform all initialization in initializeBackend. |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Set the base DNs for this backend. This is used by the unit tests |
| | | * to set the base DNs without having to provide a configuration |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Removes any data that may have been stored in this backend. |
| | | */ |
| | | /** Removes any data that may have been stored in this backend. */ |
| | | public synchronized void clearMemoryBackend() |
| | | { |
| | | entryMap.clear(); |
| | | childDNs.clear(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public synchronized void closeBackend() |
| | | { |
| | |
| | | return -1; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isIndexed(AttributeType attributeType, IndexType indexType) |
| | | { |
| | |
| | | return true; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public synchronized ConditionResult hasSubordinates(DN entryDN) |
| | | throws DirectoryException |
| | |
| | | return ConditionResult.valueOf(ret != 0); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfEntriesInBaseDN(DN baseDN) throws DirectoryException { |
| | | checkNotNull(baseDN, "baseDN must not be null"); |
| | | return getNumberOfSubordinates(baseDN, true) + 1; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfChildren(DN parentDN) throws DirectoryException { |
| | | checkNotNull(parentDN, "parentDN must not be null"); |
| | |
| | | return count; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public synchronized Entry getEntry(DN entryDN) |
| | | { |
| | |
| | | return entry; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public synchronized boolean entryExists(DN entryDN) |
| | | { |
| | | return entryMap.containsKey(entryDN); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public synchronized void addEntry(Entry entry, AddOperation addOperation) |
| | | throws DirectoryException |
| | |
| | | ERR_MEMORYBACKEND_ENTRY_ALREADY_EXISTS.get(entryDN)); |
| | | } |
| | | |
| | | |
| | | // If the entry is one of the base DNs, then add it. |
| | | if (baseDNs.contains(entryDN)) |
| | | { |
| | |
| | | return; |
| | | } |
| | | |
| | | |
| | | // Get the parent DN and ensure that it exists in the backend. |
| | | DN parentDN = DirectoryServer.getParentDNInSuffix(entryDN); |
| | | if (parentDN == null) |
| | |
| | | children.add(entryDN); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public synchronized void deleteEntry(DN entryDN, |
| | | DeleteOperation deleteOperation) |
| | |
| | | ERR_BACKEND_ENTRY_DOESNT_EXIST.get(entryDN, getBackendID())); |
| | | } |
| | | |
| | | |
| | | // Check to see if the entry contains a subtree delete control. |
| | | boolean subtreeDelete = deleteOperation != null |
| | | && deleteOperation.getRequestControl(SubtreeDeleteControl.DECODER) != null; |
| | | |
| | | HashSet<DN> children = childDNs.get(entryDN); |
| | | if (subtreeDelete) |
| | | Set<DN> children = childDNs.get(entryDN); |
| | | if (children != null && !children.isEmpty()) |
| | | { |
| | | if (children != null) |
| | | { |
| | | HashSet<DN> childrenCopy = new HashSet<>(children); |
| | | for (DN childDN : childrenCopy) |
| | | { |
| | | try |
| | | { |
| | | deleteEntry(childDN, null); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | // This shouldn't happen, but we want the delete to continue anyway |
| | | // so just ignore it if it does for some reason. |
| | | logger.traceException(e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // Make sure the entry doesn't have any children. If it does, then throw |
| | | // an exception. |
| | | if (children != null && !children.isEmpty()) |
| | | // children exist |
| | | if (!subtreeDelete) |
| | | { |
| | | throw new DirectoryException(ResultCode.NOT_ALLOWED_ON_NONLEAF, |
| | | ERR_MEMORYBACKEND_CANNOT_DELETE_ENTRY_WITH_CHILDREN.get(entryDN)); |
| | | } |
| | | |
| | | Set<DN> childrenCopy = new HashSet<>(children); |
| | | for (DN childDN : childrenCopy) |
| | | { |
| | | try |
| | | { |
| | | deleteEntry(childDN, null); |
| | | } |
| | | catch (Exception ignore) |
| | | { |
| | | // This shouldn't happen, but we want the delete to continue anyway |
| | | // so just ignore it if it does for some reason. |
| | | logger.traceException(ignore); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public synchronized void replaceEntry(Entry oldEntry, Entry newEntry, |
| | | ModifyOperation modifyOperation) throws DirectoryException |
| | |
| | | ERR_BACKEND_ENTRY_DOESNT_EXIST.get(entryDN, getBackendID())); |
| | | } |
| | | |
| | | |
| | | // Replace the old entry with the new one. |
| | | entryMap.put(entryDN, e); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public synchronized void renameEntry(DN currentDN, Entry entry, |
| | | ModifyDNOperation modifyDNOperation) |
| | |
| | | ERR_BACKEND_ENTRY_DOESNT_EXIST.get(currentDN, getBackendID())); |
| | | } |
| | | |
| | | |
| | | // Make sure that the target entry doesn't have any children. |
| | | HashSet<DN> children = childDNs.get(currentDN); |
| | | Set<DN> children = childDNs.get(currentDN); |
| | | if (children != null) |
| | | { |
| | | if (children.isEmpty()) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Make sure that no entry exists with the new DN. |
| | | if (entryMap.containsKey(e.getName())) |
| | | { |
| | |
| | | ERR_MEMORYBACKEND_ENTRY_ALREADY_EXISTS.get(e.getName())); |
| | | } |
| | | |
| | | |
| | | // Make sure that the new DN is in this backend. |
| | | boolean matchFound = false; |
| | | for (DN dn : baseDNs) |
| | | { |
| | | if (dn.isSuperiorOrEqualTo(e.getName())) |
| | | { |
| | | matchFound = true; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (! matchFound) |
| | | if (!superiorExistsInBackend(e.getName())) |
| | | { |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, |
| | | ERR_MEMORYBACKEND_CANNOT_RENAME_TO_ANOTHER_BACKEND.get(currentDN)); |
| | | } |
| | | |
| | | |
| | | // Make sure that the parent of the new entry exists. |
| | | DN parentDN = DirectoryServer.getParentDNInSuffix(e.getName()); |
| | | if (parentDN == null || !entryMap.containsKey(parentDN)) |
| | |
| | | ERR_MEMORYBACKEND_RENAME_PARENT_DOESNT_EXIST.get(currentDN, parentDN)); |
| | | } |
| | | |
| | | |
| | | // Delete the current entry and add the new one. |
| | | deleteEntry(currentDN, null); |
| | | addEntry(e, null); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | private boolean superiorExistsInBackend(DN dnToFind) |
| | | { |
| | | for (DN dn : baseDNs) |
| | | { |
| | | if (dn.isSuperiorOrEqualTo(dnToFind)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public synchronized void search(SearchOperation searchOperation) |
| | | throws DirectoryException |
| | |
| | | SearchScope scope = searchOperation.getScope(); |
| | | SearchFilter filter = searchOperation.getFilter(); |
| | | |
| | | |
| | | // 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)) |
| | |
| | | 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) |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedControls() |
| | | { |
| | | return supportedControls; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedFeatures() |
| | | { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean supports(BackendOperation backendOperation) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public synchronized void exportLDIF(LDIFExportConfig exportConfig) |
| | | throws DirectoryException |
| | |
| | | ERR_MEMORYBACKEND_CANNOT_CREATE_LDIF_WRITER.get(e), e); |
| | | } |
| | | |
| | | |
| | | // Walk through all the entries and write them to LDIF. |
| | | DN entryDN = null; |
| | | try |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public synchronized LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext serverContext) |
| | | throws DirectoryException |
| | | { |
| | | clearMemoryBackend(); |
| | | |
| | | LDIFReader reader; |
| | | try |
| | | { |
| | | reader = new LDIFReader(importConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | ERR_MEMORYBACKEND_CANNOT_CREATE_LDIF_READER.get(e), e); |
| | | } |
| | | |
| | | |
| | | try |
| | | try (LDIFReader reader = newLDIFReader(importConfig)) |
| | | { |
| | | while (true) |
| | | { |
| | |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | ERR_MEMORYBACKEND_ERROR_READING_LDIF.get(e), le); |
| | | } |
| | | else |
| | | { |
| | | continue; |
| | | } |
| | | continue; |
| | | } |
| | | |
| | | try |
| | |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | ERR_MEMORYBACKEND_ERROR_DURING_IMPORT.get(e), e); |
| | | } |
| | | finally |
| | | } |
| | | |
| | | private LDIFReader newLDIFReader(LDIFImportConfig importConfig) throws DirectoryException |
| | | { |
| | | try |
| | | { |
| | | reader.close(); |
| | | return new LDIFReader(importConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | ERR_MEMORYBACKEND_CANNOT_CREATE_LDIF_READER.get(e), e); |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void createBackup(BackupConfig backupConfig) |
| | | throws DirectoryException |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void removeBackup(BackupDirectory backupDirectory, |
| | | String backupID) |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void restoreBackup(RestoreConfig restoreConfig) |
| | | throws DirectoryException |
| | |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | |
| | | { |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | /** The set of user-defined attributes that will be included in the base monitor entry. */ |
| | | /** The set of user-defined attributes that will be included in the base monitor entry. */ |
| | | private ArrayList<Attribute> userDefinedAttributes; |
| | | /** The set of objectclasses that will be used in monitor entries. */ |
| | | private final HashMap<ObjectClass, String> monitorObjectClasses = new LinkedHashMap<>(2); |
| | |
| | | super(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void addEntry(final Entry entry, final AddOperation addOperation) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_ADD_NOT_SUPPORTED.get(entry.getName(), getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | final MonitorBackendCfg backendCfg) |
| | |
| | | addAllNonMonitorConfigAttributes(attributes, attributesToAdd); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void createBackup(final BackupConfig backupConfig) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void deleteEntry(final DN entryDN, |
| | | final DeleteOperation deleteOperation) throws DirectoryException |
| | |
| | | ERR_BACKEND_DELETE_NOT_SUPPORTED.get(entryDN, getBackendID())); |
| | | } |
| | | |
| | | /** {@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 |
| | | try (LDIFWriter ldifWriter = newLDIFWriter(exportConfig)) |
| | | { |
| | | ldifWriter = new LDIFWriter(exportConfig); |
| | | } |
| | | catch (final Exception e) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | final LocalizableMessage 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) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | close(ldifWriter); |
| | | |
| | | final LocalizableMessage 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()) |
| | | { |
| | | // Write the base monitor entry to the LDIF. |
| | | try |
| | | { |
| | | // TODO implementation of export is incomplete |
| | | ldifWriter.writeEntry(getBaseMonitorEntry()); |
| | | } |
| | | catch (final Exception e) |
| | | { |
| | | logger.traceException(e); |
| | | final LocalizableMessage message = ERR_MONITOR_UNABLE_TO_EXPORT_BASE.get(stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); |
| | | } |
| | | |
| | | close(ldifWriter); |
| | | |
| | | final LocalizableMessage message = ERR_MONITOR_UNABLE_TO_EXPORT_PROVIDER_ENTRY |
| | | .get(monitorProvider.getMonitorInstanceName(), 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) |
| | | { |
| | | logger.traceException(e); |
| | | final LocalizableMessage message = |
| | | ERR_MONITOR_UNABLE_TO_EXPORT_PROVIDER_ENTRY.get(monitorProvider.getMonitorInstanceName(), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); |
| | | } |
| | | } |
| | | } |
| | | |
| | | close(ldifWriter); |
| | | catch (IOException ignoreOnClose) |
| | | { |
| | | logger.traceException(ignoreOnClose); |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | private LDIFWriter newLDIFWriter(final LDIFExportConfig exportConfig) throws DirectoryException |
| | | { |
| | | try |
| | | { |
| | | return new LDIFWriter(exportConfig); |
| | | } |
| | | catch (final Exception e) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | final LocalizableMessage message = ERR_ROOTDSE_UNABLE_TO_CREATE_LDIF_WRITER.get(stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void closeBackend() |
| | | { |
| | |
| | | return getEntry(entryDN, dit); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getEntryCount() |
| | | { |
| | | return getDIT().size(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedControls() |
| | | { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedFeatures() |
| | | { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConditionResult hasSubordinates(final DN entryDN) |
| | | throws DirectoryException |
| | |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public LDIFImportResult importLDIF(final LDIFImportConfig importConfig, ServerContext serverContext) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_IMPORT_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void openBackend() throws ConfigException, InitializationException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isConfigurationChangeAcceptable( |
| | | final MonitorBackendCfg backendCfg, |
| | |
| | | return true; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isIndexed(final AttributeType attributeType, |
| | | final IndexType indexType) |
| | |
| | | return true; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfEntriesInBaseDN(final DN baseDN) throws DirectoryException { |
| | | checkNotNull(baseDN, "baseDN must not be null"); |
| | | return getNumberOfSubordinates(baseDN, true) + 1; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfChildren(final DN parentDN) throws DirectoryException { |
| | | checkNotNull(parentDN, "parentDN must not be null"); |
| | |
| | | return count; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void removeBackup(final BackupDirectory backupDirectory, |
| | | final String backupID) throws DirectoryException |
| | |
| | | ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void renameEntry(final DN currentDN, final Entry entry, |
| | | final ModifyDNOperation modifyDNOperation) throws DirectoryException |
| | |
| | | ERR_BACKEND_MODIFY_DN_NOT_SUPPORTED.get(currentDN, getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void replaceEntry(final Entry oldEntry, final Entry newEntry, |
| | | final ModifyOperation modifyOperation) throws DirectoryException |
| | |
| | | ERR_MONITOR_MODIFY_NOT_SUPPORTED.get(newEntry.getName(), configEntryDN)); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void restoreBackup(final RestoreConfig restoreConfig) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void search(final SearchOperation searchOperation) |
| | | throws DirectoryException |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean supports(BackendOperation backendOperation) |
| | | { |
| | |
| | | return dit; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates the monitor entry having the specified DN. |
| | | * |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Generates and returns a monitor entry based on the contents of the provided |
| | | * monitor provider. |
| | |
| | | */ |
| | | private ConcurrentHashMap<DN, Backend<?>> subordinateBaseDNs; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new backend with the provided information. All backend |
| | | * implementations must implement a default constructor that use |
| | |
| | | userDefinedAttributes = new ArrayList<>(); |
| | | addAllUserDefinedAttrs(userDefinedAttributes, configEntry); |
| | | |
| | | |
| | | // Create the set of base DNs that we will handle. In this case, it's just |
| | | // the root DSE. |
| | | rootDSEDN = DN.rootDN(); |
| | | baseDNs = Collections.singleton(rootDSEDN); |
| | | |
| | | |
| | | // Create the set of subordinate base DNs. If this is specified in the |
| | | // configuration, then use that set. Otherwise, use the set of non-private |
| | | // backends defined in the server. |
| | |
| | | for (DN baseDN : subDNs) |
| | | { |
| | | Backend<?> backend = DirectoryServer.getBackend(baseDN); |
| | | if (backend == null) |
| | | if (backend != null) |
| | | { |
| | | logger.warn(WARN_ROOTDSE_NO_BACKEND_FOR_SUBORDINATE_BASE, baseDN); |
| | | subordinateBaseDNs.put(baseDN, backend); |
| | | } |
| | | else |
| | | { |
| | | subordinateBaseDNs.put(baseDN, backend); |
| | | logger.warn(WARN_ROOTDSE_NO_BACKEND_FOR_SUBORDINATE_BASE, baseDN); |
| | | } |
| | | } |
| | | } |
| | |
| | | throw new InitializationException(message, e); |
| | | } |
| | | |
| | | |
| | | // Determine whether all root DSE attributes should be treated as user |
| | | // attributes. |
| | | showAllAttributes = currentConfig.isShowAllAttributes(); |
| | | |
| | | |
| | | // Construct the set of "static" attributes that will always be present in |
| | | // the root DSE. |
| | | staticDSEAttributes = new ArrayList<>(); |
| | |
| | | } |
| | | dseObjectClasses.put(rootDSEOC, OC_ROOT_DSE); |
| | | |
| | | |
| | | // Set the backend ID for this backend. The identifier needs to be |
| | | // specific enough to avoid conflict with user backend identifiers. |
| | | setBackendID("__root.dse__"); |
| | | |
| | | |
| | | // Register as a change listener. |
| | | currentConfig.addChangeListener(this); |
| | | } |
| | |
| | | currentConfig.removeChangeListener(this); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided attribute is one that is used in the |
| | | * configuration of this backend. |
| | |
| | | return getRootDSE(); |
| | | } |
| | | |
| | | |
| | | // This method should never be used to get anything other than the root DSE. |
| | | // If we got here, then that appears to be the case, so log a message. |
| | | logger.warn(WARN_ROOTDSE_GET_ENTRY_NONROOT, entryDN); |
| | | |
| | | |
| | | // Go ahead and check the subordinate backends to see if we can find the |
| | | // entry there. Note that in order to avoid potential loop conditions, this |
| | | // will only work if the set of subordinate bases has been explicitly |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then we couldn't find the entry so return null. |
| | | return null; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the root DSE entry for the Directory Server. |
| | | * |
| | |
| | | return getRootDSE(null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the root DSE entry for the Directory Server. |
| | | * |
| | |
| | | ATTR_SUPPORTED_AUTH_PW_SCHEMES, DirectoryServer.getAuthPasswordStorageSchemes().keySet()); |
| | | addAttribute(supportedAuthPWSchemesAttr, dseUserAttrs, dseOperationalAttrs); |
| | | |
| | | |
| | | // Obtain TLS protocol and cipher support. |
| | | Collection<String> supportedTlsProtocols; |
| | | Collection<String> supportedTlsCiphers; |
| | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | // If it was not the null DN, then iterate through the associated |
| | | // subordinate backends to make the determination. |
| | | for (Map.Entry<DN, Backend<?>> entry : getSubordinateBaseDNs().entrySet()) |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | SearchFilter filter = searchOperation.getFilter(); |
| | | switch (searchOperation.getScope().asEnum()) |
| | | { |
| | |
| | | } |
| | | break; |
| | | |
| | | |
| | | case SINGLE_LEVEL: |
| | | for (Map.Entry<DN, Backend<?>> entry : getSubordinateBaseDNs().entrySet()) |
| | | { |
| | |
| | | } |
| | | break; |
| | | |
| | | |
| | | case WHOLE_SUBTREE: |
| | | case SUBORDINATES: |
| | | try |
| | |
| | | public boolean supports(BackendOperation backendOperation) |
| | | { |
| | | // We will only export the DSE entry itself. |
| | | return backendOperation.equals(BackendOperation.LDIF_EXPORT); |
| | | return BackendOperation.LDIF_EXPORT.equals(backendOperation); |
| | | } |
| | | |
| | | @Override |
| | |
| | | message); |
| | | } |
| | | |
| | | |
| | | // Write the root DSE entry itself to it. Make sure to close the LDIF |
| | | // writer when we're done. |
| | | try |
| | |
| | | { |
| | | boolean configIsAcceptable = true; |
| | | |
| | | |
| | | try |
| | | { |
| | | Set<DN> subDNs = cfg.getSubordinateBaseDN(); |
| | |
| | | configIsAcceptable = false; |
| | | } |
| | | |
| | | |
| | | return configIsAcceptable; |
| | | } |
| | | |
| | |
| | | { |
| | | final ConfigChangeResult ccr = new ConfigChangeResult(); |
| | | |
| | | |
| | | // Check to see if we should apply a new set of base DNs. |
| | | ConcurrentHashMap<DN, Backend<?>> subBases; |
| | | try |
| | |
| | | subBases = null; |
| | | } |
| | | |
| | | |
| | | boolean newShowAll = cfg.isShowAllAttributes(); |
| | | |
| | | |
| | | // Check to see if there is a new set of user-defined attributes. |
| | | ArrayList<Attribute> userAttrs = new ArrayList<>(); |
| | | try |
| | |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | } |
| | | |
| | | |
| | | if (ccr.getResultCode() == ResultCode.SUCCESS) |
| | | { |
| | | subordinateBaseDNs = subBases; |
| | |
| | | ccr.addMessage(INFO_ROOTDSE_USING_NEW_SUBORDINATE_BASE_DNS.get(basesStr)); |
| | | } |
| | | |
| | | |
| | | if (showAllAttributes != newShowAll) |
| | | { |
| | | showAllAttributes = newShowAll; |
| | |
| | | ATTR_ROOTDSE_SHOW_ALL_ATTRIBUTES, showAllAttributes)); |
| | | } |
| | | |
| | | |
| | | userDefinedAttributes = userAttrs; |
| | | ccr.addMessage(INFO_ROOTDSE_USING_NEW_USER_ATTRS.get()); |
| | | } |
| | | |
| | | |
| | | return ccr; |
| | | } |
| | | } |
| | |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.config.server.ConfigChangeResult; |
| | | import org.forgerock.opendj.config.server.ConfigException; |
| | | import org.forgerock.opendj.config.server.ConfigurationChangeListener; |
| | | import org.forgerock.opendj.ldap.AVA; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ConditionResult; |
| | |
| | | import org.forgerock.opendj.ldap.schema.CoreSchema; |
| | | import org.forgerock.opendj.ldap.schema.MatchingRule; |
| | | import org.forgerock.opendj.ldap.schema.ObjectClassType; |
| | | import org.forgerock.opendj.config.server.ConfigurationChangeListener; |
| | | import org.forgerock.opendj.server.config.server.SchemaBackendCfg; |
| | | import org.opends.server.api.AlertGenerator; |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.Backupable; |
| | | import org.opends.server.api.ClientConnection; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.core.AddOperation; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | |
| | | import org.opends.server.types.DITContentRule; |
| | | import org.opends.server.types.DITStructureRule; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.ExistingFileBehavior; |
| | | import org.opends.server.types.IndexType; |
| | | import org.opends.server.types.InitializationException; |
| | |
| | | ObjectClass subschemaOC = DirectoryServer.getObjectClass(OC_SUBSCHEMA, true); |
| | | schemaObjectClasses.put(subschemaOC, OC_SUBSCHEMA); |
| | | |
| | | |
| | | configEntryDN = configEntry.getName(); |
| | | baseDNs = cfg.getBaseDN(); |
| | | |
| | |
| | | modifyTimestamp = |
| | | GeneralizedTimeSyntax.createGeneralizedTimeValue(newModifyTime); |
| | | |
| | | |
| | | // Get the set of user-defined attributes for the configuration entry. Any |
| | | // attributes that we don't recognize will be included directly in the |
| | | // schema entry. |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Identify any differences that may exist between the concatenated schema |
| | | // file from the last online modification and the current schema files. If |
| | | // there are any differences, then they should be from making changes to the |
| | |
| | | logger.error(ERR_SCHEMA_ERROR_DETERMINING_SCHEMA_CHANGES, getExceptionMessage(e)); |
| | | } |
| | | |
| | | |
| | | // Register with the Directory Server as a configurable component. |
| | | currentConfig.addSchemaChangeListener(this); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided attribute is one that is used in the |
| | | * configuration of this backend. |
| | |
| | | return null; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Generates and returns a schema entry for the Directory Server. |
| | | * |
| | |
| | | } |
| | | } |
| | | |
| | | /* |
| | | * Add the schema definition attributes. |
| | | */ |
| | | /* Add the schema definition attributes. */ |
| | | Schema schema = DirectoryServer.getSchema(); |
| | | buildSchemaAttribute(schema.getAttributeTypes(), userAttrs, |
| | | operationalAttrs, attributeTypesType, includeSchemaFile, |
| | |
| | | return e; |
| | | } |
| | | |
| | | |
| | | |
| | | private void addAttributeToSchemaEntry(Attribute attribute, |
| | | Map<AttributeType, List<Attribute>> userAttrs, |
| | | Map<AttributeType, List<Attribute>> operationalAttrs) |
| | |
| | | attrs.add(attribute); |
| | | } |
| | | |
| | | |
| | | |
| | | private void buildSchemaAttribute(Collection<?> elements, |
| | | Map<AttributeType, List<Attribute>> userAttrs, |
| | | Map<AttributeType, List<Attribute>> operationalAttrs, |
| | |
| | | AttributeBuilder builder = new AttributeBuilder(schemaAttributeType); |
| | | for (Object element : elements) |
| | | { |
| | | /* |
| | | * Add the file name to the description of the element if this was |
| | | * requested by the caller. |
| | | */ |
| | | /* Add the file name to the description of the element if this was requested by the caller. */ |
| | | String value; |
| | | if (includeSchemaFile && element instanceof CommonSchemaElements) |
| | | { |
| | |
| | | message); |
| | | } |
| | | |
| | | |
| | | ArrayList<Modification> mods = new ArrayList<>(modifyOperation.getModifications()); |
| | | if (mods.isEmpty()) |
| | | { |
| | |
| | | |
| | | break; |
| | | |
| | | |
| | | case DELETE: |
| | | if (a.isEmpty()) |
| | | { |
| | |
| | | |
| | | break; |
| | | |
| | | |
| | | case REPLACE: |
| | | if (!m.isInternal() |
| | | && !modifyOperation.isSynchronizationOperation()) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then everything looks OK, re-write all the |
| | | // modified Schema Files. |
| | | updateSchemaFiles(newSchema, modifiedSchemaFiles); |
| | |
| | | // Finally set DirectoryServer to use the new Schema. |
| | | DirectoryServer.setSchema(newSchema); |
| | | |
| | | |
| | | DN authzDN = modifyOperation.getAuthorizationDN(); |
| | | if (authzDN == null) |
| | | { |
| | |
| | | System.currentTimeMillis()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Re-write all schema files using the provided new Schema and list of |
| | | * modified files. |
| | |
| | | cleanUpTempSchemaFiles(tempSchemaFiles); |
| | | } |
| | | |
| | | |
| | | // Create a single file with all of the concatenated schema information |
| | | // that we can use on startup to detect whether the schema files have been |
| | | // edited with the server offline. |
| | | Schema.writeConcatenatedSchema(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Handles all processing required for adding the provided attribute type to |
| | | * the given schema, replacing an existing type if necessary, and ensuring all |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Handles all processing required for adding the provided objectclass to the |
| | | * given schema, replacing an existing class if necessary, and ensuring |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Make sure that the new objectclass doesn't reference an undefined |
| | | // superior class, or an undefined required or optional attribute type, |
| | | // and that none of them are OBSOLETE. |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If there is no existing class, then we're adding a new objectclass. |
| | | // Otherwise, we're replacing an existing one. |
| | | if (existingClass == null) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Handles all processing required to remove the provided objectclass from the |
| | | * server schema, ensuring all other metadata is properly updated. Note that |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | // See if there is another modification later to add the objectclass back |
| | | // into the schema. If so, then it's a replace and we should ignore the |
| | | // remove because adding it back will handle the replace. |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Make sure that the objectclass isn't used as the superior class for any |
| | | // other objectclass. |
| | | for (ObjectClass oc : schema.getObjectClasses().values()) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Make sure that the objectclass isn't used as the structural class for |
| | | // any name form. |
| | | List<NameForm> mappedForms = schema.getNameForm(removeClass); |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | // Make sure that the objectclass isn't used as a structural or auxiliary |
| | | // class for any DIT content rule. |
| | | for (DITContentRule dcr : schema.getDITContentRules().values()) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then it's OK to remove the objectclass from the |
| | | // schema. |
| | | schema.deregisterObjectClass(removeClass); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Handles all processing required for adding the provided name form to the |
| | | * the given schema, replacing an existing name form if necessary, and |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Make sure that the new name form doesn't reference an undefined |
| | | // structural class, or an undefined required or optional attribute type, or |
| | | // that any of them are marked OBSOLETE. |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If there is no existing class, then we're adding a new name form. |
| | | // Otherwise, we're replacing an existing one. |
| | | if (existingNF == null) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Handles all processing required to remove the provided name form from the |
| | | * server schema, ensuring all other metadata is properly updated. Note that |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | // See if there is another modification later to add the name form back |
| | | // into the schema. If so, then it's a replace and we should ignore the |
| | | // remove because adding it back will handle the replace. |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Make sure that the name form isn't referenced by any DIT structure |
| | | // rule. |
| | | DITStructureRule dsr = schema.getDITStructureRule(removeNF); |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then it's OK to remove the name form from the |
| | | // schema. |
| | | schema.deregisterNameForm(removeNF); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Handles all processing required for adding the provided DIT content rule to |
| | | * the given schema, replacing an existing rule if necessary, and ensuring |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Get the structural class for the new DIT content rule and see if there's |
| | | // already an existing rule that is associated with that class. If there |
| | | // is, then it will only be acceptable if it's the DIT content rule that we |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | // Make sure that the new DIT content rule doesn't reference an undefined |
| | | // structural or auxiliary class, or an undefined required, optional, or |
| | | // prohibited attribute type. |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If there is no existing rule, then we're adding a new DIT content rule. |
| | | // Otherwise, we're replacing an existing one. |
| | | if (existingDCR == null) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Handles all processing required to remove the provided DIT content rule |
| | | * from the server schema, ensuring all other metadata is properly updated. |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | // Since DIT content rules don't have any dependencies, then we don't need |
| | | // to worry about the difference between a remove or a replace. We can |
| | | // just remove the DIT content rule now, and if it is added back later then |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Handles all processing required for adding the provided DIT structure rule |
| | | * to the given schema, replacing an existing rule if necessary, and ensuring |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | // Make sure that the new DIT structure rule doesn't reference an undefined |
| | | // name form or superior DIT structure rule. |
| | | if (! schema.hasNameForm(nameForm.getOID())) |
| | |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message); |
| | | } |
| | | |
| | | |
| | | // If there are any superior rules, then make sure none of them are marked |
| | | // OBSOLETE. |
| | | for (DITStructureRule dsr : ditStructureRule.getSuperiorRules()) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If there is no existing rule, then we're adding a new DIT structure rule. |
| | | // Otherwise, we're replacing an existing one. |
| | | if (existingDSR == null) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Handles all processing required to remove the provided DIT structure rule |
| | | * from the server schema, ensuring all other metadata is properly updated. |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | // See if there is another modification later to add the DIT structure rule |
| | | // back into the schema. If so, then it's a replace and we should ignore |
| | | // the remove because adding it back will handle the replace. |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Make sure that the DIT structure rule isn't the superior for any other |
| | | // DIT structure rule. |
| | | for (DITStructureRule dsr : schema.getDITStructureRulesByID().values()) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then it's OK to remove the DIT structure rule from |
| | | // the schema. |
| | | schema.deregisterDITStructureRule(removeDSR); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Handles all processing required for adding the provided matching rule use |
| | | * to the given schema, replacing an existing use if necessary, and ensuring |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Get the matching rule for the new matching rule use and see if there's |
| | | // already an existing matching rule use that is associated with that |
| | | // matching rule. If there is, then it will only be acceptable if it's the |
| | |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message); |
| | | } |
| | | |
| | | |
| | | // Make sure that the new matching rule use doesn't reference an undefined |
| | | // attribute type. |
| | | for (AttributeType at : matchingRuleUse.getAttributes()) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If there is no existing matching rule use, then we're adding a new one. |
| | | // Otherwise, we're replacing an existing matching rule use. |
| | | if (existingMRU == null) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Handles all processing required to remove the provided matching rule use |
| | | * from the server schema, ensuring all other metadata is properly updated. |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | // Since matching rule uses don't have any dependencies, then we don't need |
| | | // to worry about the difference between a remove or a replace. We can |
| | | // just remove the DIT content rule now, and if it is added back later then |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** Gets rid of the ldap syntax description. */ |
| | | private void removeLdapSyntaxDescription(String definition, Schema schema, Set<String> modifiedSchemaFiles) |
| | | throws DirectoryException |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates an empty entry that may be used as the basis for a new schema file. |
| | | * |
| | |
| | | return new Entry(dn, objectClasses, userAttributes, operationalAttributes); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * Writes a temporary version of the specified schema file. |
| | | * |
| | |
| | | schemaEntry.putAttribute(attributeTypesType, newArrayList(builder.toAttribute())); |
| | | } |
| | | |
| | | |
| | | // Add all of the appropriate objectclasses to the schema entry. We need |
| | | // to be careful of the ordering to ensure that any superior classes in the |
| | | // same file are written before the subordinate classes. |
| | |
| | | schemaEntry.putAttribute(objectClassesType, newArrayList(builder.toAttribute())); |
| | | } |
| | | |
| | | |
| | | // Add all of the appropriate name forms to the schema entry. Since there |
| | | // is no hierarchical relationship between name forms, we don't need to |
| | | // worry about ordering. |
| | |
| | | schemaEntry.putAttribute(nameFormsType, newArrayList(builder.toAttribute())); |
| | | } |
| | | |
| | | |
| | | // Add all of the appropriate DIT content rules to the schema entry. Since |
| | | // there is no hierarchical relationship between DIT content rules, we don't |
| | | // need to worry about ordering. |
| | |
| | | schemaEntry.putAttribute(ditContentRulesType, newArrayList(builder.toAttribute())); |
| | | } |
| | | |
| | | |
| | | // Add all of the appropriate DIT structure rules to the schema entry. We |
| | | // need to be careful of the ordering to ensure that any superior rules in |
| | | // the same file are written before the subordinate rules. |
| | |
| | | schemaEntry.putAttribute(ditStructureRulesType, newArrayList(builder.toAttribute())); |
| | | } |
| | | |
| | | |
| | | // Add all of the appropriate matching rule uses to the schema entry. Since |
| | | // there is no hierarchical relationship between matching rule uses, we |
| | | // don't need to worry about ordering. |
| | |
| | | schemaEntry.putAttribute(matchingRuleUsesType, newArrayList(builder.toAttribute())); |
| | | } |
| | | |
| | | |
| | | if (FILE_USER_SCHEMA_ELEMENTS.equals(schemaFile)) |
| | | { |
| | | Map<String, Attribute> attributes = schema.getExtraAttributes(); |
| | |
| | | LDIFExportConfig exportConfig = |
| | | new LDIFExportConfig(tempFile.getAbsolutePath(), |
| | | ExistingFileBehavior.OVERWRITE); |
| | | LDIFWriter ldifWriter = new LDIFWriter(exportConfig); |
| | | ldifWriter.writeEntry(schemaEntry); |
| | | ldifWriter.close(); |
| | | try (LDIFWriter ldifWriter = new LDIFWriter(exportConfig)) |
| | | { |
| | | ldifWriter.writeEntry(schemaEntry); |
| | | } |
| | | |
| | | return tempFile; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Adds the definition for the specified attribute type to the provided set of |
| | | * attribute values, recursively adding superior types as appropriate. |
| | |
| | | addedTypes.add(attributeType); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Adds the definition for the specified objectclass to the provided set of |
| | | * attribute values, recursively adding superior classes as appropriate. |
| | |
| | | addedClasses.add(objectClass); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Adds the definition for the specified DIT structure rule to the provided |
| | | * set of attribute values, recursively adding superior rules as appropriate. |
| | |
| | | addedDSRs.add(ditStructureRule); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Moves the specified temporary schema files in place of the active versions. |
| | | * If an error occurs in the process, then this method will attempt to restore |
| | |
| | | origFileList.add(new File(schemaInstanceDir, name + ".orig")); |
| | | } |
| | | |
| | | |
| | | // If there are any old ".orig" files laying around from a previous |
| | | // attempt, then try to clean them up. |
| | | for (File f : origFileList) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Copy all of the currently-installed files with a ".orig" extension. If |
| | | // this fails, then try to clean up the copies. |
| | | try |
| | |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message, e); |
| | | } |
| | | |
| | | |
| | | // Try to copy all of the temporary files into place over the installed |
| | | // files. If this fails, then try to restore the originals. |
| | | try |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a copy of the specified file. |
| | | * |
| | |
| | | */ |
| | | private void copyFile(File from, File to) throws IOException |
| | | { |
| | | byte[] buffer = new byte[4096]; |
| | | FileInputStream inputStream = null; |
| | | FileOutputStream outputStream = null; |
| | | try |
| | | try (FileInputStream inputStream = new FileInputStream(from); |
| | | FileOutputStream outputStream = new FileOutputStream(to, false)) |
| | | { |
| | | inputStream = new FileInputStream(from); |
| | | outputStream = new FileOutputStream(to, false); |
| | | |
| | | byte[] buffer = new byte[4096]; |
| | | int bytesRead = inputStream.read(buffer); |
| | | while (bytesRead > 0) |
| | | { |
| | |
| | | bytesRead = inputStream.read(buffer); |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | close(inputStream, outputStream); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs any necessary cleanup in an attempt to delete any temporary schema |
| | | * files that may have been left over after trying to install the new schema. |
| | |
| | | matchedDN, null); |
| | | } |
| | | |
| | | |
| | | // If it's a onelevel or subordinate subtree search, then we will never |
| | | // match anything since there isn't anything below the schema. |
| | | SearchScope scope = searchOperation.getScope(); |
| | |
| | | return; |
| | | } |
| | | |
| | | |
| | | // Get the schema entry and see if it matches the filter. If so, then send |
| | | // it to the client. |
| | | Entry schemaEntry = getSchemaEntry(baseDN, false); |
| | |
| | | message); |
| | | } |
| | | |
| | | |
| | | // Write the root schema entry to it. Make sure to close the LDIF |
| | | // writer when we're done. |
| | | try |
| | |
| | | public LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext serverContext) |
| | | throws DirectoryException |
| | | { |
| | | LDIFReader reader; |
| | | try |
| | | { |
| | | reader = new LDIFReader(importConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | ERR_MEMORYBACKEND_CANNOT_CREATE_LDIF_READER.get(e), e); |
| | | } |
| | | |
| | | |
| | | try |
| | | try (LDIFReader reader = newLDIFReader(importConfig)) |
| | | { |
| | | while (true) |
| | | { |
| | |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | ERR_MEMORYBACKEND_ERROR_DURING_IMPORT.get(e), e); |
| | | } |
| | | finally |
| | | { |
| | | close(reader); |
| | | } |
| | | } |
| | | |
| | | private LDIFReader newLDIFReader(LDIFImportConfig importConfig) throws DirectoryException |
| | | { |
| | | try |
| | | { |
| | | return new LDIFReader(importConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | ERR_MEMORYBACKEND_CANNOT_CREATE_LDIF_READER.get(e), e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Import an entry in a new schema by : |
| | |
| | | { |
| | | final ConfigChangeResult ccr = new ConfigChangeResult(); |
| | | |
| | | |
| | | // Check to see if we should apply a new set of base DNs. |
| | | Set<DN> newBaseDNs; |
| | | try |
| | |
| | | newBaseDNs = null; |
| | | } |
| | | |
| | | |
| | | // Check to see if we should change the behavior regarding whether to show |
| | | // all schema attributes. |
| | | boolean newShowAllAttributes = backendCfg.isShowAllAttributes(); |
| | | |
| | | |
| | | // Check to see if there is a new set of user-defined attributes. |
| | | ArrayList<Attribute> newUserAttrs = new ArrayList<>(); |
| | | try |
| | |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | } |
| | | |
| | | |
| | | if (ccr.getResultCode() == ResultCode.SUCCESS) |
| | | { |
| | | // Determine the set of DNs to add and delete. When this is done, the |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | showAllAttributes = newShowAllAttributes; |
| | | |
| | | |
| | | userDefinedAttributes = newUserAttrs; |
| | | LocalizableMessage message = INFO_SCHEMA_USING_NEW_USER_ATTRS.get(); |
| | | ccr.addMessage(message); |
| | | } |
| | | |
| | | |
| | | currentConfig = backendCfg; |
| | | return ccr; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether to treat common schema attributes like user attributes |
| | | * rather than operational attributes. |
| | |
| | | return showAllAttributes; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Specifies whether to treat common schema attributes like user attributes |
| | | * rather than operational attributes. |
| | |
| | | { |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | |
| | | |
| | | /** The current configuration state. */ |
| | | private TrustStoreBackendCfg configuration; |
| | | |
| | | /** The set of base DNs for this backend. */ |
| | | private SortedSet<DN> baseDNs; |
| | | |
| | | /** The base entry. */ |
| | | private Entry baseEntry; |
| | | |
| | | /** The PIN needed to access the trust store backing file. */ |
| | | private char[] trustStorePIN; |
| | | |
| | | /** The path to the trust store backing file. */ |
| | | private String trustStoreFile; |
| | | |
| | | /** The type of trust store backing file to use. */ |
| | | private String trustStoreType; |
| | | |
| | | /** The certificate manager for the trust store. */ |
| | | private CertificateManager certificateManager; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new backend. All backend |
| | | * implementations must implement a default constructor that use |
| | |
| | | trustStoreType, configEntryDN, getExceptionMessage(kse))); |
| | | } |
| | | |
| | | trustStorePIN = getTrustStorePIN(configEntryDN); |
| | | |
| | | // Get the PIN needed to access the contents of the trust store file. We |
| | | // will offer several places to look for the PIN, and we will do so in the |
| | | // following order: |
| | | // - In a specified Java property |
| | | // - In a specified environment variable |
| | | // - In a specified file on the server filesystem. |
| | | // - As the value of a configuration attribute. |
| | | // In any case, the PIN must be in the clear. If no PIN is provided, then |
| | | // it will be assumed that none is required to access the information in the |
| | | // trust store. |
| | | String pinProperty = configuration.getTrustStorePinProperty(); |
| | | if (pinProperty == null) |
| | | { |
| | | String pinEnVar = configuration.getTrustStorePinEnvironmentVariable(); |
| | | if (pinEnVar == null) |
| | | { |
| | | String pinFilePath = configuration.getTrustStorePinFile(); |
| | | if (pinFilePath == null) |
| | | { |
| | | String pinStr = configuration.getTrustStorePin(); |
| | | if (pinStr == null) |
| | | { |
| | | // This should be an Error. Otherwise, programs fails. |
| | | // Is there a Unit Test? |
| | | trustStorePIN = null; |
| | | } |
| | | else |
| | | { |
| | | trustStorePIN = pinStr.toCharArray(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | File pinFile = getFileForPath(pinFilePath); |
| | | if (! pinFile.exists()) |
| | | { |
| | | try |
| | | { |
| | | // Generate a PIN. |
| | | trustStorePIN = createKeystorePassword(); |
| | | |
| | | // Store the PIN in the pin file. |
| | | createPINFile(pinFile.getPath(), new String(trustStorePIN)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | throw new InitializationException( |
| | | ERR_TRUSTSTORE_PIN_FILE_CANNOT_CREATE.get(pinFilePath, configEntryDN)); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | String pinStr; |
| | | |
| | | BufferedReader br = null; |
| | | try |
| | | { |
| | | br = new BufferedReader(new FileReader(pinFile)); |
| | | pinStr = br.readLine(); |
| | | } |
| | | catch (IOException ioe) |
| | | { |
| | | LocalizableMessage message = ERR_TRUSTSTORE_PIN_FILE_CANNOT_READ. |
| | | get(pinFilePath, configEntryDN, getExceptionMessage(ioe)); |
| | | throw new InitializationException(message, ioe); |
| | | } |
| | | finally |
| | | { |
| | | close(br); |
| | | } |
| | | |
| | | if (pinStr == null) |
| | | { |
| | | throw new InitializationException( |
| | | ERR_TRUSTSTORE_PIN_FILE_EMPTY.get(pinFilePath, configEntryDN)); |
| | | } |
| | | trustStorePIN = pinStr.toCharArray(); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | String pinStr = System.getenv(pinEnVar); |
| | | if (pinStr == null) |
| | | { |
| | | throw new InitializationException( |
| | | ERR_TRUSTSTORE_PIN_ENVAR_NOT_SET.get(pinProperty, configEntryDN)); |
| | | } |
| | | trustStorePIN = pinStr.toCharArray(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | String pinStr = System.getProperty(pinProperty); |
| | | if (pinStr == null) |
| | | { |
| | | throw new InitializationException(ERR_TRUSTSTORE_PIN_PROPERTY_NOT_SET.get(pinProperty, configEntryDN)); |
| | | } |
| | | trustStorePIN = pinStr.toCharArray(); |
| | | } |
| | | |
| | | // Create a certificate manager. |
| | | certificateManager = |
| | | new CertificateManager(getFileForPath(trustStoreFile).getPath(), |
| | | trustStoreType, |
| | |
| | | // Register this as a change listener. |
| | | configuration.addTrustStoreChangeListener(this); |
| | | |
| | | |
| | | // Register the trust store base as a private suffix. |
| | | try |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | /** |
| | | * Get the PIN needed to access the contents of the trust store file. We will offer several places |
| | | * to look for the PIN, and we will do so in the following order: |
| | | * <ol> |
| | | * <li>In a specified Java property</li> |
| | | * <li>In a specified environment variable</li> |
| | | * <li>In a specified file on the server filesystem</li> |
| | | * <li>As the value of a configuration attribute</li> |
| | | * </ol> |
| | | * In any case, the PIN must be in the clear. If no PIN is provided, then it will be assumed that |
| | | * none is required to access the information in the trust store. |
| | | */ |
| | | private char[] getTrustStorePIN(DN configEntryDN) throws InitializationException |
| | | { |
| | | final String pinProperty = configuration.getTrustStorePinProperty(); |
| | | if (pinProperty != null) |
| | | { |
| | | String pinStr = System.getProperty(pinProperty); |
| | | if (pinStr == null) |
| | | { |
| | | throw new InitializationException(ERR_TRUSTSTORE_PIN_PROPERTY_NOT_SET.get(pinProperty, configEntryDN)); |
| | | } |
| | | return pinStr.toCharArray(); |
| | | } |
| | | |
| | | final String pinEnVar = configuration.getTrustStorePinEnvironmentVariable(); |
| | | if (pinEnVar != null) |
| | | { |
| | | String pinStr = System.getenv(pinEnVar); |
| | | if (pinStr == null) |
| | | { |
| | | throw new InitializationException(ERR_TRUSTSTORE_PIN_ENVAR_NOT_SET.get(pinProperty, configEntryDN)); |
| | | } |
| | | return pinStr.toCharArray(); |
| | | } |
| | | |
| | | final String pinFilePath = configuration.getTrustStorePinFile(); |
| | | if (pinFilePath != null) |
| | | { |
| | | File pinFile = getFileForPath(pinFilePath); |
| | | if (pinFile.exists()) |
| | | { |
| | | String pinStr = readPinFromFile(pinFile, configEntryDN); |
| | | if (pinStr == null) |
| | | { |
| | | throw new InitializationException(ERR_TRUSTSTORE_PIN_FILE_EMPTY.get(pinFilePath, configEntryDN)); |
| | | } |
| | | return pinStr.toCharArray(); |
| | | } |
| | | |
| | | try |
| | | { |
| | | // Generate and store the PIN in the pin file. |
| | | final char[] trustStorePIN = createKeystorePassword(); |
| | | createPINFile(pinFile.getPath(), new String(trustStorePIN)); |
| | | return trustStorePIN; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | throw new InitializationException(ERR_TRUSTSTORE_PIN_FILE_CANNOT_CREATE.get(pinFilePath, configEntryDN)); |
| | | } |
| | | } |
| | | |
| | | String pinStr = configuration.getTrustStorePin(); |
| | | // else branch should be an Error. Otherwise, programs fails. Is there a Unit Test? |
| | | return pinStr != null ? pinStr.toCharArray() : null; |
| | | } |
| | | |
| | | @Override |
| | | public void closeBackend() |
| | | { |
| | |
| | | return numEntries; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isIndexed(AttributeType attributeType, IndexType indexType) |
| | | { |
| | |
| | | return true; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Entry getEntry(DN entryDN) throws DirectoryException |
| | | { |
| | |
| | | ERR_BACKEND_GET_ENTRY_NULL.get(getBackendID())); |
| | | } |
| | | |
| | | |
| | | // If the requested entry was the backend base entry, then retrieve it. |
| | | if (entryDN.equals(getBaseDN())) |
| | | { |
| | | return baseEntry.duplicate(true); |
| | | } |
| | | |
| | | |
| | | // See if the requested entry was one level below the backend base entry. |
| | | // If so, then it must point to a trust store entry. |
| | | DN parentDN = DirectoryServer.getParentDNInSuffix(entryDN); |
| | |
| | | return null; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Generates an entry for a certificate based on the provided DN. The |
| | | * DN must contain an RDN component that specifies the alias of the |
| | |
| | | |
| | | userAttrs.put(t, Attributes.createAsList(t, v)); |
| | | |
| | | |
| | | t = DirectoryServer.getAttributeType(ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE); |
| | | AttributeBuilder builder = new AttributeBuilder(t); |
| | | builder.setOption("binary"); |
| | | builder.add(certValue); |
| | | userAttrs.put(t, builder.toAttributeList()); |
| | | |
| | | |
| | | Entry e = new Entry(entryDN, ocMap, userAttrs, opAttrs); |
| | | e.processVirtualAttributes(); |
| | | return e; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void addEntry(Entry entry, AddOperation addOperation) |
| | | throws DirectoryException |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void deleteEntry(DN entryDN, DeleteOperation deleteOperation) |
| | | throws DirectoryException |
| | |
| | | deleteCertificate(entryDN); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void replaceEntry(Entry oldEntry, Entry newEntry, |
| | | ModifyOperation modifyOperation) throws DirectoryException |
| | |
| | | ERR_BACKEND_MODIFY_NOT_SUPPORTED.get(oldEntry.getName(), getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void renameEntry(DN currentDN, Entry entry, |
| | | ModifyDNOperation modifyDNOperation) |
| | |
| | | ERR_BACKEND_MODIFY_DN_NOT_SUPPORTED.get(currentDN, getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void search(SearchOperation searchOperation) |
| | | throws DirectoryException |
| | |
| | | DN baseDN = searchOperation.getBaseDN(); |
| | | Entry baseEntry = getEntry(baseDN); |
| | | |
| | | |
| | | // Look at the base DN and see if it's the trust store base DN, or a |
| | | // trust store entry DN. |
| | | SearchScope scope = searchOperation.getScope(); |
| | |
| | | AttributeType certAliasType = DirectoryServer.getAttributeType(ATTR_CRYPTO_KEY_ID); |
| | | for (String alias : aliases) |
| | | { |
| | | DN certDN = makeChildDN(this.getBaseDN(), certAliasType, alias); |
| | | DN certDN = makeChildDN(getBaseDN(), certAliasType, alias); |
| | | |
| | | Entry certEntry; |
| | | try |
| | |
| | | } |
| | | } |
| | | } |
| | | else if (this.getBaseDN().equals(DirectoryServer.getParentDNInSuffix(baseDN))) |
| | | else if (getBaseDN().equals(DirectoryServer.getParentDNInSuffix(baseDN))) |
| | | { |
| | | Entry certEntry = getCertEntry(baseDN); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedControls() |
| | | { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedFeatures() |
| | | { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean supports(BackendOperation backendOperation) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void exportLDIF(LDIFExportConfig exportConfig) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_IMPORT_AND_EXPORT_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext serverContext) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_IMPORT_AND_EXPORT_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void createBackup(BackupConfig backupConfig) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void removeBackup(BackupDirectory backupDirectory, |
| | | String backupID) |
| | |
| | | ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void restoreBackup(RestoreConfig restoreConfig) |
| | | throws DirectoryException |
| | |
| | | ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConditionResult hasSubordinates(DN entryDN) |
| | | throws DirectoryException |
| | |
| | | ERR_HAS_SUBORDINATES_NOT_SUPPORTED.get()); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfEntriesInBaseDN(DN baseDN) throws DirectoryException |
| | | { |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, ERR_NUM_SUBORDINATES_NOT_SUPPORTED.get()); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfChildren(DN parentDN) throws DirectoryException |
| | | { |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, ERR_NUM_SUBORDINATES_NOT_SUPPORTED.get()); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isConfigurationChangeAcceptable( |
| | | TrustStoreBackendCfg configuration, List<LocalizableMessage> unacceptableReasons) |
| | | { |
| | | boolean configAcceptable = true; |
| | | DN cfgEntryDN = configuration.dn(); |
| | | |
| | | final ConfigChangeResult ccr = new ConfigChangeResult(); |
| | | final DN cfgEntryDN = configuration.dn(); |
| | | |
| | | // Get the path to the trust store file. |
| | | String newTrustStoreFile = configuration.getTrustStoreFile(); |
| | |
| | | File f = getFileForPath(newTrustStoreFile); |
| | | if (!f.exists() || !f.isFile()) |
| | | { |
| | | unacceptableReasons.add(ERR_TRUSTSTORE_NO_SUCH_FILE.get(newTrustStoreFile, cfgEntryDN)); |
| | | configAcceptable = false; |
| | | ccr.addMessage(ERR_TRUSTSTORE_NO_SUCH_FILE.get(newTrustStoreFile, cfgEntryDN)); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | unacceptableReasons.add(ERR_TRUSTSTORE_CANNOT_DETERMINE_FILE.get(cfgEntryDN, getExceptionMessage(e))); |
| | | configAcceptable = false; |
| | | ccr.addMessage(ERR_TRUSTSTORE_CANNOT_DETERMINE_FILE.get(cfgEntryDN, getExceptionMessage(e))); |
| | | } |
| | | |
| | | |
| | | // Check to see if the trust store type is acceptable. |
| | | String storeType = configuration.getTrustStoreType(); |
| | | if (storeType != null) |
| | |
| | | { |
| | | logger.traceException(kse); |
| | | |
| | | unacceptableReasons.add(ERR_TRUSTSTORE_INVALID_TYPE.get( |
| | | storeType, cfgEntryDN, getExceptionMessage(kse))); |
| | | configAcceptable = false; |
| | | ccr.addMessage(ERR_TRUSTSTORE_INVALID_TYPE.get(storeType, cfgEntryDN, getExceptionMessage(kse))); |
| | | } |
| | | } |
| | | |
| | | |
| | | // If there is a PIN property, then make sure the corresponding |
| | | // property is set. |
| | | String pinProp = configuration.getTrustStorePinProperty(); |
| | | if (pinProp != null && System.getProperty(pinProp) == null) |
| | | { |
| | | unacceptableReasons.add(ERR_TRUSTSTORE_PIN_PROPERTY_NOT_SET.get(pinProp, cfgEntryDN)); |
| | | configAcceptable = false; |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_PROPERTY_NOT_SET.get(pinProp, cfgEntryDN)); |
| | | } |
| | | |
| | | |
| | | // If there is a PIN environment variable, then make sure the corresponding |
| | | // environment variable is set. |
| | | String pinEnVar = configuration.getTrustStorePinEnvironmentVariable(); |
| | | if (pinEnVar != null && System.getenv(pinEnVar) == null) |
| | | { |
| | | unacceptableReasons.add(ERR_TRUSTSTORE_PIN_ENVAR_NOT_SET.get(pinEnVar, cfgEntryDN)); |
| | | configAcceptable = false; |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_ENVAR_NOT_SET.get(pinEnVar, cfgEntryDN)); |
| | | } |
| | | |
| | | |
| | | // If there is a PIN file, then make sure the file is readable if it exists. |
| | | String pinFile = configuration.getTrustStorePinFile(); |
| | | if (pinFile != null) |
| | |
| | | File f = new File(pinFile); |
| | | if (f.exists()) |
| | | { |
| | | String pinStr = null; |
| | | |
| | | BufferedReader br = null; |
| | | try |
| | | { |
| | | br = new BufferedReader(new FileReader(pinFile)); |
| | | pinStr = br.readLine(); |
| | | } |
| | | catch (IOException ioe) |
| | | { |
| | | unacceptableReasons.add(ERR_TRUSTSTORE_PIN_FILE_CANNOT_READ.get( |
| | | pinFile, cfgEntryDN, getExceptionMessage(ioe))); |
| | | configAcceptable = false; |
| | | } |
| | | finally |
| | | { |
| | | close(br); |
| | | } |
| | | |
| | | String pinStr = readPinFromFile2(f, cfgEntryDN, ccr); |
| | | if (pinStr == null) |
| | | { |
| | | unacceptableReasons.add(ERR_TRUSTSTORE_PIN_FILE_EMPTY.get(pinFile, cfgEntryDN)); |
| | | configAcceptable = false; |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_FILE_EMPTY.get(pinFile, cfgEntryDN)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | return configAcceptable; |
| | | final List<LocalizableMessage> messages = ccr.getMessages(); |
| | | unacceptableReasons.addAll(messages); |
| | | return messages.isEmpty(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConfigChangeResult applyConfigurationChange(TrustStoreBackendCfg cfg) |
| | | { |
| | |
| | | ccr.addMessage(ERR_TRUSTSTORE_NO_SUCH_FILE.get(newTrustStoreFile, configEntryDN)); |
| | | } |
| | | |
| | | |
| | | // Get the trust store type. If none is specified, then use the default |
| | | // type. |
| | | String newTrustStoreType = cfg.getTrustStoreType(); |
| | |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | } |
| | | |
| | | |
| | | // Get the PIN needed to access the contents of the trust store file. We |
| | | // will offer several places to look for the PIN, and we will do so in the |
| | | // following order: |
| | | // - In a specified Java property |
| | | // - In a specified environment variable |
| | | // - In a specified file on the server filesystem. |
| | | // - As the value of a configuration attribute. |
| | | // In any case, the PIN must be in the clear. If no PIN is provided, then |
| | | // it will be assumed that none is required to access the information in the |
| | | // trust store. |
| | | char[] newPIN = null; |
| | | String newPINProperty = cfg.getTrustStorePinProperty(); |
| | | if (newPINProperty == null) |
| | | { |
| | | String newPINEnVar = cfg.getTrustStorePinEnvironmentVariable(); |
| | | if (newPINEnVar == null) |
| | | { |
| | | String newPINFile = cfg.getTrustStorePinFile(); |
| | | if (newPINFile == null) |
| | | { |
| | | String pinStr = cfg.getTrustStorePin(); |
| | | if (pinStr == null) |
| | | { |
| | | newPIN = null; |
| | | } |
| | | else |
| | | { |
| | | newPIN = pinStr.toCharArray(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | File pinFile = getFileForPath(newPINFile); |
| | | if (! pinFile.exists()) |
| | | { |
| | | try |
| | | { |
| | | // Generate a PIN. |
| | | newPIN = createKeystorePassword(); |
| | | |
| | | // Store the PIN in the pin file. |
| | | createPINFile(pinFile.getPath(), new String(newPIN)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_FILE_CANNOT_CREATE.get(newPINFile, configEntryDN)); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | String pinStr = null; |
| | | |
| | | BufferedReader br = null; |
| | | try |
| | | { |
| | | br = new BufferedReader(new FileReader(pinFile)); |
| | | pinStr = br.readLine(); |
| | | } |
| | | catch (IOException ioe) |
| | | { |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_FILE_CANNOT_READ.get( |
| | | newPINFile, configEntryDN, getExceptionMessage(ioe))); |
| | | } |
| | | finally |
| | | { |
| | | close(br); |
| | | } |
| | | |
| | | if (pinStr == null) |
| | | { |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_FILE_EMPTY.get(newPINFile, configEntryDN)); |
| | | } |
| | | else |
| | | { |
| | | newPIN = pinStr.toCharArray(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | String pinStr = System.getenv(newPINEnVar); |
| | | if (pinStr == null) |
| | | { |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_ENVAR_NOT_SET.get(newPINEnVar, configEntryDN)); |
| | | } |
| | | else |
| | | { |
| | | newPIN = pinStr.toCharArray(); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | String pinStr = System.getProperty(newPINProperty); |
| | | if (pinStr == null) |
| | | { |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_PROPERTY_NOT_SET.get(newPINProperty, configEntryDN)); |
| | | } |
| | | else |
| | | { |
| | | newPIN = pinStr.toCharArray(); |
| | | } |
| | | } |
| | | |
| | | char[] newPIN = getTrustStorePIN2(cfg, ccr); |
| | | |
| | | if (ccr.getResultCode() == ResultCode.SUCCESS) |
| | | { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Get the PIN needed to access the contents of the trust store file. We will offer several places |
| | | * to look for the PIN, and we will do so in the following order: |
| | | * <ol> |
| | | * <li>In a specified Java property</li> |
| | | * <li>In a specified environment variable</li> |
| | | * <li>In a specified file on the server filesystem.</li> |
| | | * <li>As the value of a configuration attribute.</li> |
| | | * </ol> |
| | | * In any case, the PIN must be in the clear. If no PIN is provided, then it will be assumed that |
| | | * none is required to access the information in the trust store. |
| | | */ |
| | | private char[] getTrustStorePIN2(TrustStoreBackendCfg cfg, ConfigChangeResult ccr) |
| | | { |
| | | String newPINProperty = cfg.getTrustStorePinProperty(); |
| | | if (newPINProperty == null) |
| | | { |
| | | String newPINEnVar = cfg.getTrustStorePinEnvironmentVariable(); |
| | | if (newPINEnVar == null) |
| | | { |
| | | String newPINFile = cfg.getTrustStorePinFile(); |
| | | if (newPINFile == null) |
| | | { |
| | | String pinStr = cfg.getTrustStorePin(); |
| | | return pinStr != null ? pinStr.toCharArray() : null; |
| | | } |
| | | else |
| | | { |
| | | File pinFile = getFileForPath(newPINFile); |
| | | if (! pinFile.exists()) |
| | | { |
| | | try |
| | | { |
| | | // Generate and store a PIN in the pin file. |
| | | final char[] newPIN = createKeystorePassword(); |
| | | createPINFile(pinFile.getPath(), new String(newPIN)); |
| | | return newPIN; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_FILE_CANNOT_CREATE.get(newPINFile, cfg.dn())); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | String pinStr = readPinFromFile2(pinFile, cfg.dn(), ccr); |
| | | if (pinStr == null) |
| | | { |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_FILE_EMPTY.get(newPINFile, cfg.dn())); |
| | | } |
| | | else |
| | | { |
| | | return pinStr.toCharArray(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | String pinStr = System.getenv(newPINEnVar); |
| | | if (pinStr == null) |
| | | { |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_ENVAR_NOT_SET.get(newPINEnVar, cfg.dn())); |
| | | } |
| | | else |
| | | { |
| | | return pinStr.toCharArray(); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | String pinStr = System.getProperty(newPINProperty); |
| | | if (pinStr == null) |
| | | { |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_PROPERTY_NOT_SET.get(newPINProperty, cfg.dn())); |
| | | } |
| | | else |
| | | { |
| | | return pinStr.toCharArray(); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private String readPinFromFile(File pinFile, DN cfgEntryDN) throws InitializationException |
| | | { |
| | | try (BufferedReader br = new BufferedReader(new FileReader(pinFile))) |
| | | { |
| | | return br.readLine(); |
| | | } |
| | | catch (IOException ioe) |
| | | { |
| | | LocalizableMessage message = |
| | | ERR_TRUSTSTORE_PIN_FILE_CANNOT_READ.get(pinFile, cfgEntryDN, getExceptionMessage(ioe)); |
| | | throw new InitializationException(message, ioe); |
| | | } |
| | | } |
| | | |
| | | private String readPinFromFile2(File pinFile, DN cfgEntryDN, ConfigChangeResult ccr) |
| | | { |
| | | try (BufferedReader br = new BufferedReader(new FileReader(pinFile))) |
| | | { |
| | | return br.readLine(); |
| | | } |
| | | catch (IOException ioe) |
| | | { |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | ccr.addMessage(ERR_TRUSTSTORE_PIN_FILE_CANNOT_READ.get(pinFile, cfgEntryDN, getExceptionMessage(ioe))); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Create a new child DN from a given parent DN. The child RDN is formed |
| | | * from a given attribute type and string value. |
| | | * @param parentDN The DN of the parent. |
| | |
| | | return parentDN.child(new RDN(rdnAttrType, attrValue)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of <CODE>KeyManager</CODE> objects that may be used for |
| | | * interactions requiring access to a key manager. |
| | |
| | | public KeyManager[] getKeyManagers() |
| | | throws DirectoryException |
| | | { |
| | | final KeyStore keyStore; |
| | | try (final FileInputStream inputStream = new FileInputStream(getFileForPath(trustStoreFile))) |
| | | { |
| | | keyStore = KeyStore.getInstance(trustStoreType); |
| | | keyStore.load(inputStream, trustStorePIN); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_LOAD.get( |
| | | trustStoreFile, getExceptionMessage(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message, e); |
| | | } |
| | | final KeyStore keyStore = loadKeyStore(); |
| | | |
| | | try |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | private KeyStore loadKeyStore() throws DirectoryException |
| | | { |
| | | try (FileInputStream inputStream = new FileInputStream(getFileForPath(trustStoreFile))) |
| | | { |
| | | final KeyStore keyStore = KeyStore.getInstance(trustStoreType); |
| | | keyStore.load(inputStream, trustStorePIN); |
| | | return keyStore; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_LOAD.get(trustStoreFile, getExceptionMessage(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message, e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Retrieves a set of {@code TrustManager} objects that may be used |
| | |
| | | public TrustManager[] getTrustManagers() |
| | | throws DirectoryException |
| | | { |
| | | KeyStore trustStore; |
| | | FileInputStream inputStream = null; |
| | | try |
| | | { |
| | | trustStore = KeyStore.getInstance(trustStoreType); |
| | | |
| | | inputStream = |
| | | new FileInputStream(getFileForPath(trustStoreFile)); |
| | | trustStore.load(inputStream, trustStorePIN); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_LOAD.get( |
| | | trustStoreFile, getExceptionMessage(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message, e); |
| | | } |
| | | finally |
| | | { |
| | | close(inputStream); |
| | | } |
| | | |
| | | KeyStore trustStore = loadKeyStore(); |
| | | |
| | | try |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the key associated with the given alias, using the trust |
| | | * store pin to recover it. |
| | |
| | | public Key getKey(String alias) |
| | | throws DirectoryException |
| | | { |
| | | KeyStore trustStore; |
| | | FileInputStream inputStream = null; |
| | | try |
| | | { |
| | | trustStore = KeyStore.getInstance(trustStoreType); |
| | | |
| | | inputStream = |
| | | new FileInputStream(getFileForPath(trustStoreFile)); |
| | | trustStore.load(inputStream, trustStorePIN); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_LOAD.get( |
| | | trustStoreFile, getExceptionMessage(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message, e); |
| | | } |
| | | finally |
| | | { |
| | | close(inputStream); |
| | | } |
| | | KeyStore trustStore = loadKeyStore(); |
| | | |
| | | try |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | private void addCertificate(Entry entry) |
| | | throws DirectoryException |
| | | { |
| | |
| | | certAlias, tempDir); |
| | | try |
| | | { |
| | | FileOutputStream outputStream = |
| | | new FileOutputStream(tempFile.getPath(), false); |
| | | try |
| | | try (FileOutputStream outputStream = new FileOutputStream(tempFile.getPath(), false)) |
| | | { |
| | | certBytes.copyTo(outputStream); |
| | | } |
| | | finally |
| | | { |
| | | outputStream.close(); |
| | | } |
| | | |
| | | certificateManager.addCertificate(certAlias, tempFile); |
| | | } |
| | |
| | | throw new DirectoryException( |
| | | DirectoryServer.getServerErrorResultCode(), message, e); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | private void deleteCertificate(DN entryDN) |
| | | throws DirectoryException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the validity period to be used to generate the ADS certificate. |
| | | * @return The validity period to be used to generate the ADS certificate. |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void configureBackend(C cfg, ServerContext serverContext) throws ConfigException |
| | | { |
| | |
| | | storage = new TracedStorage(configureStorage(cfg, serverContext), cfg.getBackendId()); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void openBackend() throws ConfigException, InitializationException |
| | | { |
| | |
| | | cfg.addPluggableChangeListener(this); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void closeBackend() |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean supports(BackendOperation backendOperation) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedFeatures() |
| | | { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedControls() |
| | | { |
| | |
| | | return baseDNs; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getEntryCount() |
| | | { |
| | |
| | | return -1; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConditionResult hasSubordinates(DN entryDN) throws DirectoryException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfEntriesInBaseDN(DN baseDN) throws DirectoryException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfChildren(DN parentDN) throws DirectoryException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean entryExists(final DN entryDN) throws DirectoryException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Entry getEntry(DN entryDN) throws DirectoryException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void addEntry(Entry entry, AddOperation addOperation) throws DirectoryException, CanceledOperationException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void deleteEntry(DN entryDN, DeleteOperation deleteOperation) |
| | | throws DirectoryException, CanceledOperationException |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void replaceEntry(Entry oldEntry, Entry newEntry, ModifyOperation modifyOperation) |
| | | throws DirectoryException, CanceledOperationException |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void renameEntry(DN currentDN, Entry entry, ModifyDNOperation modifyDNOperation) |
| | | throws DirectoryException, CanceledOperationException |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void search(SearchOperation searchOperation) throws DirectoryException, CanceledOperationException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void exportLDIF(LDIFExportConfig exportConfig) |
| | | throws DirectoryException |
| | |
| | | return rootContainer == null; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext serverContext) |
| | | throws DirectoryException |
| | |
| | | return new OnDiskMergeImporter.StrategyImpl(serverContext, rootContainer, cfg); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long verifyBackend(VerifyConfig verifyConfig) |
| | | throws InitializationException, ConfigException, DirectoryException |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void rebuildBackend(RebuildConfig rebuildConfig, ServerContext serverContext) |
| | | throws InitializationException, ConfigException, DirectoryException |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void createBackup(BackupConfig backupConfig) throws DirectoryException |
| | | { |
| | | storage.createBackup(backupConfig); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void removeBackup(BackupDirectory backupDirectory, String backupID) |
| | | throws DirectoryException |
| | |
| | | storage.removeBackup(backupDirectory, backupID); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void restoreBackup(RestoreConfig restoreConfig) throws DirectoryException |
| | | { |
| | |
| | | */ |
| | | protected abstract Storage configureStorage(C cfg, ServerContext serverContext) throws ConfigException; |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isConfigurationAcceptable(C config, List<LocalizableMessage> unacceptableReasons, |
| | | ServerContext serverContext) |
| | |
| | | return isConfigurationChangeAcceptable(config, unacceptableReasons); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isConfigurationChangeAcceptable(PluggableBackendCfg cfg, List<LocalizableMessage> unacceptableReasons) |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConfigChangeResult applyConfigurationChange(final PluggableBackendCfg newCfg) |
| | | { |
| | |
| | | throw new InitializationException(ERR_OPEN_ENV_FAIL.get(e.getMessage()), e); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.opends.server.api.MonitorData; |
| | | import org.forgerock.opendj.server.config.server.MonitorProviderCfg; |
| | | import org.opends.server.api.MonitorData; |
| | | import org.opends.server.api.MonitorProvider; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.util.TimeThread; |
| | |
| | | MonitorData monitorAttrs = new MonitorData(5); |
| | | |
| | | Collection<String> needReindexValues = createNeedReindexValues(); |
| | | if (needReindexValues.size() > 0) |
| | | if (!needReindexValues.isEmpty()) |
| | | { |
| | | monitorAttrs.add("need-reindex", needReindexValues); |
| | | } |
| | |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.config.server.ConfigChangeResult; |
| | | import org.forgerock.opendj.config.server.ConfigException; |
| | | import org.forgerock.opendj.config.server.ConfigurationChangeListener; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ConditionResult; |
| | | import org.forgerock.opendj.ldap.DN; |
| | |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.SearchScope; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | | import org.forgerock.util.Reject; |
| | | import org.forgerock.opendj.config.server.ConfigurationChangeListener; |
| | | import org.forgerock.opendj.server.config.server.TaskBackendCfg; |
| | | import org.forgerock.util.Reject; |
| | | import org.opends.server.api.Backend; |
| | | import org.opends.server.api.Backupable; |
| | | import org.opends.server.core.AddOperation; |
| | |
| | | extends Backend<TaskBackendCfg> |
| | | implements ConfigurationChangeListener<TaskBackendCfg>, Backupable |
| | | { |
| | | |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | |
| | | |
| | | /** The current configuration state. */ |
| | | private TaskBackendCfg currentConfig; |
| | | |
| | | /** The DN of the configuration entry for this backend. */ |
| | | private DN configEntryDN; |
| | | |
| | | /** |
| | | * The DN of the entry that will serve as the parent for all recurring task |
| | | * entries. |
| | | */ |
| | | /** The DN of the entry that will serve as the parent for all recurring task entries. */ |
| | | private DN recurringTaskParentDN; |
| | | |
| | | /** |
| | | * The DN of the entry that will serve as the parent for all scheduled task |
| | | * entries. |
| | | */ |
| | | /** The DN of the entry that will serve as the parent for all scheduled task entries. */ |
| | | private DN scheduledTaskParentDN; |
| | | |
| | | /** The DN of the entry that will serve as the root for all task entries. */ |
| | | private DN taskRootDN; |
| | | |
| | |
| | | |
| | | /** The path to the task backing file. */ |
| | | private String taskBackingFile; |
| | | |
| | | /** |
| | | * The task scheduler that will be responsible for actually invoking scheduled |
| | | * tasks. |
| | | */ |
| | | /** The task scheduler that will be responsible for actually invoking scheduled tasks. */ |
| | | private TaskScheduler taskScheduler; |
| | | |
| | | private ServerContext serverContext; |
| | |
| | | // Perform all initialization in initializeBackend. |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public void configureBackend(TaskBackendCfg cfg, ServerContext serverContext) throws ConfigException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Get the retention time that will be used to determine how long task |
| | | // information stays around once the associated task is completed. |
| | | retentionTime = cfg.getTaskRetentionTime(); |
| | | |
| | | |
| | | // Get the notification sender address. |
| | | notificationSenderAddress = cfg.getNotificationSenderAddress(); |
| | | if (notificationSenderAddress == null) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Get the path to the task data backing file. |
| | | taskBackingFile = cfg.getTaskBackingFile(); |
| | | |
| | | currentConfig = cfg; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void openBackend() |
| | | throws ConfigException, InitializationException |
| | |
| | | taskScheduler = new TaskScheduler(serverContext, this); |
| | | taskScheduler.start(); |
| | | |
| | | |
| | | // Register with the Directory Server as a configurable component. |
| | | currentConfig.addTaskChangeListener(this); |
| | | |
| | | |
| | | // Register the task base as a private suffix. |
| | | try |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void closeBackend() |
| | | { |
| | |
| | | return -1; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isIndexed(AttributeType attributeType, IndexType indexType) |
| | | { |
| | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConditionResult hasSubordinates(DN entryDN) |
| | | throws DirectoryException |
| | |
| | | return ConditionResult.valueOf(ret != 0); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfEntriesInBaseDN(DN baseDN) throws DirectoryException { |
| | | checkNotNull(baseDN, "baseDN must not be null"); |
| | | return numSubordinates(baseDN, true) + 1; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public long getNumberOfChildren(DN parentDN) throws DirectoryException { |
| | | checkNotNull(parentDN, "parentDN must not be null"); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Entry getEntry(DN entryDN) |
| | | throws DirectoryException |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void addEntry(Entry entry, AddOperation addOperation) |
| | | throws DirectoryException |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void deleteEntry(DN entryDN, DeleteOperation deleteOperation) |
| | | throws DirectoryException |
| | |
| | | throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message); |
| | | } |
| | | |
| | | |
| | | // Look at the state of the task. We will allow pending and completed |
| | | // tasks to be removed, but not running tasks. |
| | | TaskState state = t.getTaskState(); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void replaceEntry(Entry oldEntry, Entry newEntry, |
| | | ModifyOperation modifyOperation) throws DirectoryException |
| | |
| | | LocalizableMessage message = INFO_TASKBE_RUNNING_TASK_CANCELLED.get(); |
| | | t.interruptTask(TaskState.STOPPED_BY_ADMINISTRATOR, message); |
| | | } |
| | | return; |
| | | return; |
| | | } |
| | | else |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Helper to determine if requested modifications are acceptable. |
| | | * @param modifyOperation associated with requested modifications. |
| | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void renameEntry(DN currentDN, Entry entry, |
| | | ModifyDNOperation modifyDNOperation) |
| | |
| | | ERR_BACKEND_MODIFY_DN_NOT_SUPPORTED.get(currentDN, getBackendID())); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void search(SearchOperation searchOperation) |
| | | throws DirectoryException, CanceledOperationException { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | if (searchRoot) |
| | | { |
| | | Entry e = taskScheduler.getTaskRootEntry(); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | if (searchScheduledParent) |
| | | { |
| | | Entry e = taskScheduler.getScheduledTaskParentEntry(); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | if (searchScheduledTasks |
| | | && !taskScheduler.searchScheduledTasks(searchOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | |
| | | if (searchRecurringParent) |
| | | { |
| | | Entry e = taskScheduler.getRecurringTaskParentEntry(); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | if (searchRecurringTasks |
| | | && !taskScheduler.searchRecurringTasks(searchOperation)) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedControls() |
| | | { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Set<String> getSupportedFeatures() |
| | | { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean supports(BackendOperation backendOperation) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void exportLDIF(LDIFExportConfig exportConfig) |
| | | throws DirectoryException |
| | | public void exportLDIF(LDIFExportConfig exportConfig) throws DirectoryException |
| | | { |
| | | File taskFile = getFileForPath(taskBackingFile); |
| | | |
| | | // Read from. |
| | | LDIFReader ldifReader; |
| | | try |
| | | try (LDIFReader ldifReader = newLDIFReader(taskFile); |
| | | LDIFWriter ldifWriter = newLDIFWriter(exportConfig)) |
| | | { |
| | | ldifReader = new LDIFReader(new LDIFImportConfig(taskFile.getPath())); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | LocalizableMessage message = ERR_TASKS_CANNOT_EXPORT_TO_FILE.get(e); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message, e); |
| | | } |
| | | |
| | | // Write to. |
| | | LDIFWriter ldifWriter; |
| | | try |
| | | { |
| | | ldifWriter = new LDIFWriter(exportConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | logger.traceException(e); |
| | | |
| | | LocalizableMessage message = ERR_TASKS_CANNOT_EXPORT_TO_FILE.get( |
| | | stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | } |
| | | |
| | | // Copy record by record. |
| | | try |
| | | { |
| | | // Copy record by record. |
| | | while (true) |
| | | { |
| | | Entry e = null; |
| | |
| | | } |
| | | catch (LDIFException le) |
| | | { |
| | | if (! le.canContinueReading()) |
| | | if (!le.canContinueReading()) |
| | | { |
| | | LocalizableMessage message = ERR_TASKS_CANNOT_EXPORT_TO_FILE.get(e); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message, le); |
| | |
| | | { |
| | | logger.traceException(e); |
| | | } |
| | | finally |
| | | } |
| | | |
| | | private LDIFReader newLDIFReader(File taskFile) throws DirectoryException |
| | | { |
| | | try |
| | | { |
| | | close(ldifWriter, ldifReader); |
| | | return new LDIFReader(new LDIFImportConfig(taskFile.getPath())); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | LocalizableMessage message = ERR_TASKS_CANNOT_EXPORT_TO_FILE.get(e); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message, e); |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | private LDIFWriter newLDIFWriter(LDIFExportConfig exportConfig) throws DirectoryException |
| | | { |
| | | try |
| | | { |
| | | return new LDIFWriter(exportConfig); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | logger.traceException(e); |
| | | LocalizableMessage message = ERR_TASKS_CANNOT_EXPORT_TO_FILE.get(stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext sContext) throws DirectoryException |
| | | { |
| | |
| | | ERR_BACKEND_IMPORT_NOT_SUPPORTED.get(getBackendID())); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void createBackup(BackupConfig backupConfig) throws DirectoryException |
| | | { |
| | | new BackupManager(getBackendID()).createBackup(this, backupConfig); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void removeBackup(BackupDirectory backupDirectory, String backupID) throws DirectoryException |
| | | { |
| | | new BackupManager(getBackendID()).removeBackup(backupDirectory, backupID); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void restoreBackup(RestoreConfig restoreConfig) throws DirectoryException |
| | | { |
| | | new BackupManager(getBackendID()).restoreBackup(this, restoreConfig); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isConfigurationAcceptable(TaskBackendCfg config, |
| | | List<LocalizableMessage> unacceptableReasons, |
| | |
| | | return isConfigAcceptable(config, unacceptableReasons, null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isConfigurationChangeAcceptable(TaskBackendCfg configEntry, |
| | | List<LocalizableMessage> unacceptableReasons) |
| | |
| | | taskBackingFile); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration is acceptable for this task |
| | | * backend. |
| | |
| | | { |
| | | boolean configIsAcceptable = true; |
| | | |
| | | |
| | | try |
| | | { |
| | | String tmpBackingFile = config.getTaskBackingFile(); |
| | |
| | | return configIsAcceptable; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ConfigChangeResult applyConfigurationChange(TaskBackendCfg configEntry) |
| | | { |
| | | final ConfigChangeResult ccr = new ConfigChangeResult(); |
| | | |
| | | |
| | | String tmpBackingFile = taskBackingFile; |
| | | try |
| | | { |
| | |
| | | ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | } |
| | | |
| | | |
| | | long tmpRetentionTime = configEntry.getTaskRetentionTime(); |
| | | |
| | | |
| | | if (ccr.getResultCode() == ResultCode.SUCCESS) |
| | | { |
| | | // Everything looks OK, so apply the changes. |
| | |
| | | ccr.addMessage(INFO_TASKBE_UPDATED_RETENTION_TIME.get(retentionTime)); |
| | | } |
| | | |
| | | |
| | | if (! taskBackingFile.equals(tmpBackingFile)) |
| | | { |
| | | taskBackingFile = tmpBackingFile; |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | String tmpNotificationAddress = configEntry.getNotificationSenderAddress(); |
| | | if (tmpNotificationAddress == null) |
| | | { |
| | |
| | | } |
| | | notificationSenderAddress = tmpNotificationAddress; |
| | | |
| | | |
| | | currentConfig = configEntry; |
| | | return ccr; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry for this task backend. |
| | | * |
| | |
| | | return configEntryDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the path to the backing file that will hold the scheduled and |
| | | * recurring task definitions. |
| | |
| | | return f.getPath(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the sender address that should be used for e-mail notifications |
| | | * of task completion. |
| | |
| | | return notificationSenderAddress; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the length of time in seconds that information for a task should |
| | | * be retained after processing on it has completed. |
| | |
| | | return retentionTime; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the entry that is the root for all task information in |
| | | * the Directory Server. |
| | |
| | | return taskRootDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the entry that is the immediate parent for all |
| | | * recurring task information in the Directory Server. |
| | |
| | | return recurringTaskParentDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the entry that is the immediate parent for all |
| | | * scheduled task information in the Directory Server. |
| | |
| | | return scheduledTaskParentDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the scheduled task for the entry with the provided DN. |
| | | * |
| | |
| | | return taskScheduler.getScheduledTask(taskEntryDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the recurring task for the entry with the provided DN. |
| | | * |
| | |
| | | return taskScheduler.getRecurringTask(taskEntryDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public File getDirectory() |
| | | { |
| | |
| | | }; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ListIterator<Path> getFilesToBackup() throws DirectoryException |
| | | { |
| | | return BackupManager.getFiles(getDirectory(), getFilesToBackupFilter(), getBackendID()).listIterator(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isDirectRestore() |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public Path beforeRestore() throws DirectoryException |
| | | { |
| | |
| | | return BackupManager.saveCurrentFilesToDirectory(this, getBackendID()); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void afterRestore(Path restoreDirectory, Path saveDirectory) throws DirectoryException |
| | | { |
| | | // restore was successful, delete the save directory |
| | | StaticUtils.recursiveDelete(saveDirectory.toFile()); |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | */ |
| | | public class ExportTask extends Task |
| | | { |
| | | |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | |
| | | /** Stores mapping between configuration attribute name and its label. */ |
| | | private static Map<String,LocalizableMessage> argDisplayMap = new HashMap<>(); |
| | | static { |
| | |
| | | |
| | | private LDIFExportConfig exportConfig; |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public LocalizableMessage getDisplayName() { |
| | | return INFO_TASK_EXPORT_NAME.get(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public LocalizableMessage getAttributeDisplayName(String name) { |
| | | return argDisplayMap.get(name); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void initializeTask() throws DirectoryException |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | Entry taskEntry = getTaskEntry(); |
| | | AttributeType typeWrapColumn = getAttributeType(ATTR_TASK_EXPORT_WRAP_COLUMN); |
| | | |
| | |
| | | return TaskUtils.getSingleValueString(attrs); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void interruptTask(TaskState interruptState, LocalizableMessage interruptReason) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isInterruptable() { |
| | | return true; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | protected TaskState runTask() |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | ArrayList<DN> includeBranches; |
| | | if (!includeBranchStrings.isEmpty()) |
| | | { |
| | |
| | | includeBranches = defaultIncludeBranches; |
| | | } |
| | | |
| | | |
| | | // Create the LDIF export configuration to use when reading the LDIF. |
| | | ExistingFileBehavior existingBehavior; |
| | | if (appendToLDIF) |
| | |
| | | // FIXME -- Should this be conditional? |
| | | exportConfig.setInvokeExportPlugins(true); |
| | | |
| | | |
| | | // Get the set of base DNs for the backend as an array. |
| | | DN[] baseDNs = new DN[defaultIncludeBranches.size()]; |
| | | defaultIncludeBranches.toArray(baseDNs); |
| | | |
| | | |
| | | // From here we must make sure we close the export config. |
| | | try |
| | | { |
| | |
| | | return TaskState.STOPPED_BY_ERROR; |
| | | } |
| | | |
| | | |
| | | // From here we must make sure we release the shared backend lock. |
| | | try |
| | | { |
| | |
| | | argDisplayMap.put(ATTR_IMPORT_CLEAR_BACKEND, INFO_IMPORT_ARG_CLEAR_BACKEND.get()); |
| | | } |
| | | |
| | | |
| | | private boolean isCompressed; |
| | | private boolean isEncrypted; |
| | | private boolean overwrite; |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | Entry taskEntry = getTaskEntry(); |
| | | |
| | | AttributeType typeLdifFile = getAttributeType(ATTR_IMPORT_LDIF_FILE); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Get the backend into which the LDIF should be imported. |
| | | Backend<?> backend = null; |
| | | HashSet<DN> defaultIncludeBranches; |
| | |
| | | return TaskState.STOPPED_BY_ERROR; |
| | | } |
| | | |
| | | |
| | | try |
| | | { |
| | | // Acquire an exclusive lock for the backend. |
| | |
| | | return TaskState.STOPPED_BY_ERROR; |
| | | } |
| | | |
| | | |
| | | // Launch the import. |
| | | try |
| | | { |
| | |
| | | logger.warn(WARN_LDIFIMPORT_CANNOT_UNLOCK_BACKEND, backend.getBackendID(), getExceptionMessage(e)); |
| | | return TaskState.COMPLETED_WITH_ERRORS; |
| | | } |
| | | |
| | | } |
| | | } |
| | | finally |
| | |
| | | DirectoryServer.notifyImportEnded(backend, importConfig, true); |
| | | } |
| | | |
| | | |
| | | // Clean up after the import by closing the import config. |
| | | importConfig.close(); |
| | | return getFinalTaskState(); |