| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS |
| | | * Portions Copyright 2014-2015 ForgeRock AS |
| | | */ |
| | | package org.opends.server.api; |
| | | |
| | |
| | | import org.opends.server.types.RestoreConfig; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.WritabilityMode; |
| | | |
| | | /** |
| | | * This class defines the set of methods and structures that must be |
| | | * implemented for a Directory Server backend. |
| | |
| | | /** The backend monitor associated with this backend. */ |
| | | private BackendMonitor backendMonitor; |
| | | |
| | | /** |
| | | * Indicates whether this is a private backend or one that holds user data. |
| | | */ |
| | | /** Indicates whether this is a private backend or one that holds user data. */ |
| | | private boolean isPrivateBackend; |
| | | |
| | | /** The unique identifier for this backend. */ |
| | |
| | | */ |
| | | public abstract void configureBackend(C cfg) throws ConfigException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided configuration is acceptable for |
| | | * this backend. It should be possible to call this method on an |
| | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Initializes this backend based on the information provided |
| | | * when the backend was configured. |
| | |
| | | public abstract void initializeBackend() |
| | | throws ConfigException, InitializationException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs any necessary work to finalize this backend, including |
| | | * closing any underlying databases or connections and deregistering |
| | |
| | | persistentSearches.clear(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of base-level DNs that may be used within this |
| | | * backend. |
| | |
| | | */ |
| | | public abstract DN[] getBaseDNs(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Attempts to pre-load all the entries stored within this backend |
| | | * into the entry cache. Note that the caller must ensure that the |
| | |
| | | * @throws UnsupportedOperationException if backend does not |
| | | * support this operation. |
| | | */ |
| | | public abstract void preloadEntryCache() |
| | | throws UnsupportedOperationException; |
| | | |
| | | |
| | | public abstract void preloadEntryCache() throws UnsupportedOperationException; |
| | | |
| | | /** |
| | | * Indicates whether the data associated with this backend may be |
| | |
| | | */ |
| | | public abstract boolean isLocal(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether search operations which target the specified |
| | | * attribute in the indicated manner would be considered indexed |
| | |
| | | * specified attribute in the indicated manner should be |
| | | * considered indexed, or {@code false} if not. |
| | | */ |
| | | public abstract boolean isIndexed(AttributeType attributeType, |
| | | IndexType indexType); |
| | | |
| | | |
| | | public abstract boolean isIndexed(AttributeType attributeType, IndexType indexType); |
| | | |
| | | /** |
| | | * Indicates whether extensible match search operations that target |
| | |
| | | return false; // FIXME This should be overridden by the JE Backend at least! |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether a subtree search using the provided filter |
| | | * would be indexed in this backend. This default implementation |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the requested entry from this backend. Note that the |
| | | * caller must hold a read or write lock on the specified DN. |
| | |
| | | * @throws DirectoryException If a problem occurs while trying to |
| | | * retrieve the entry. |
| | | */ |
| | | public abstract Entry getEntry(DN entryDN) |
| | | throws DirectoryException; |
| | | |
| | | |
| | | public abstract Entry getEntry(DN entryDN) throws DirectoryException; |
| | | |
| | | /** |
| | | * Indicates whether the requested entry has any subordinates. |
| | |
| | | * @throws DirectoryException If a problem occurs while trying to |
| | | * retrieve the entry. |
| | | */ |
| | | public abstract ConditionResult hasSubordinates(DN entryDN) |
| | | throws DirectoryException; |
| | | |
| | | |
| | | public abstract ConditionResult hasSubordinates(DN entryDN) throws DirectoryException; |
| | | |
| | | /** |
| | | * Retrieves the number of subordinates for the requested entry. |
| | |
| | | * @throws DirectoryException If a problem occurs while trying to |
| | | * retrieve the entry. |
| | | */ |
| | | public abstract long numSubordinates(DN entryDN, boolean subtree) |
| | | throws DirectoryException; |
| | | |
| | | |
| | | public abstract long numSubordinates(DN entryDN, boolean subtree) throws DirectoryException; |
| | | |
| | | /** |
| | | * Indicates whether an entry with the specified DN exists in the |
| | |
| | | * @throws DirectoryException If a problem occurs while trying to |
| | | * make the determination. |
| | | */ |
| | | public boolean entryExists(DN entryDN) |
| | | throws DirectoryException |
| | | public boolean entryExists(DN entryDN) throws DirectoryException |
| | | { |
| | | return getEntry(entryDN) != null; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Adds the provided entry to this backend. This method must ensure |
| | | * that the entry is appropriate for the backend and that no entry |
| | |
| | | * cancel or abandon the add |
| | | * operation. |
| | | */ |
| | | public abstract void addEntry(Entry entry, |
| | | AddOperation addOperation) |
| | | public abstract void addEntry(Entry entry, AddOperation addOperation) |
| | | throws DirectoryException, CanceledOperationException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Removes the specified entry from this backend. This method must |
| | | * ensure that the entry exists and that it does not have any |
| | |
| | | * cancel or abandon the |
| | | * delete operation. |
| | | */ |
| | | public abstract void deleteEntry(DN entryDN, |
| | | DeleteOperation deleteOperation) |
| | | public abstract void deleteEntry(DN entryDN, DeleteOperation deleteOperation) |
| | | throws DirectoryException, CanceledOperationException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Replaces the specified entry with the provided entry in this |
| | | * backend. The backend must ensure that an entry already exists |
| | |
| | | ModifyOperation modifyOperation) throws DirectoryException, |
| | | CanceledOperationException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Moves and/or renames the provided entry in this backend, altering |
| | | * any subordinate entries as necessary. This must ensure that an |
| | |
| | | * If this backend noticed and reacted to a request to |
| | | * cancel or abandon the modify DN operation. |
| | | */ |
| | | public abstract void renameEntry(DN currentDN, Entry entry, |
| | | ModifyDNOperation modifyDNOperation) |
| | | public abstract void renameEntry(DN currentDN, Entry entry, ModifyDNOperation modifyDNOperation) |
| | | throws DirectoryException, CanceledOperationException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Processes the specified search in this backend. Matching entries |
| | | * should be provided back to the core server using the |
| | |
| | | public abstract void search(SearchOperation searchOperation) |
| | | throws DirectoryException, CanceledOperationException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the OIDs of the controls that may be supported by this |
| | | * backend. |
| | |
| | | */ |
| | | public abstract Set<String> getSupportedControls(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this backend supports the specified control. |
| | | * |
| | |
| | | return supportedControls != null && supportedControls.contains(controlOID); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the OIDs of the features that may be supported by this |
| | | * backend. |
| | |
| | | */ |
| | | public abstract Set<String> getSupportedFeatures(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this backend supports the specified feature. |
| | | * |
| | |
| | | return supportedFeatures != null && supportedFeatures.contains(featureOID); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this backend provides a mechanism to export the |
| | | * data it contains to an LDIF file. |
| | |
| | | */ |
| | | public abstract boolean supportsLDIFExport(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Exports the contents of this backend to LDIF. This method should |
| | | * only be called if {@code supportsLDIFExport} returns |
| | |
| | | * @throws DirectoryException If a problem occurs while performing |
| | | * the LDIF export. |
| | | */ |
| | | public abstract void exportLDIF(LDIFExportConfig exportConfig) |
| | | throws DirectoryException; |
| | | |
| | | |
| | | public abstract void exportLDIF(LDIFExportConfig exportConfig) throws DirectoryException; |
| | | |
| | | /** |
| | | * Indicates whether this backend provides a mechanism to import its |
| | |
| | | */ |
| | | public abstract boolean supportsLDIFImport(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Imports information from an LDIF file into this backend. This |
| | | * method should only be called if {@code supportsLDIFImport} |
| | |
| | | * @throws DirectoryException If a problem occurs while performing |
| | | * the LDIF import. |
| | | */ |
| | | public abstract LDIFImportResult importLDIF( |
| | | LDIFImportConfig importConfig) |
| | | public abstract LDIFImportResult importLDIF(LDIFImportConfig importConfig) |
| | | throws DirectoryException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this backend provides a backup mechanism of any |
| | | * kind. This method is used by the backup process when backing up |
| | |
| | | */ |
| | | public abstract boolean supportsBackup(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this backend provides a mechanism to perform a |
| | | * backup of its contents in a form that can be restored later, |
| | |
| | | * performing backups with the provided configuration, or |
| | | * {@code false} if not. |
| | | */ |
| | | public abstract boolean supportsBackup(BackupConfig backupConfig, |
| | | StringBuilder unsupportedReason); |
| | | |
| | | |
| | | public abstract boolean supportsBackup(BackupConfig backupConfig, StringBuilder unsupportedReason); |
| | | |
| | | /** |
| | | * Creates a backup of the contents of this backend in a form that |
| | |
| | | public abstract void createBackup(BackupConfig backupConfig) |
| | | throws DirectoryException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Removes the specified backup if it is possible to do so. |
| | | * |
| | |
| | | * there are other backups that are |
| | | * dependent upon it). |
| | | */ |
| | | public abstract void removeBackup(BackupDirectory backupDirectory, |
| | | String backupID) |
| | | public abstract void removeBackup(BackupDirectory backupDirectory, String backupID) |
| | | throws DirectoryException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this backend provides a mechanism to restore a |
| | | * backup. |
| | |
| | | */ |
| | | public abstract boolean supportsRestore(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Restores a backup of the contents of this backend. This method |
| | | * should only be called if {@code supportsRestore} returns |
| | |
| | | public abstract void restoreBackup(RestoreConfig restoreConfig) |
| | | throws DirectoryException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the unique identifier for this backend. |
| | | * |
| | |
| | | return backendID; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Specifies the unique identifier for this backend. |
| | | * |
| | |
| | | this.backendID = backendID; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this backend holds private data or user data. |
| | | * |
| | |
| | | return isPrivateBackend; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Specifies whether this backend holds private data or user data. |
| | | * |
| | |
| | | this.isPrivateBackend = isPrivateBackend; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the writability mode for this backend. |
| | | * |
| | |
| | | * |
| | | * @param writabilityMode The writability mode for this backend. |
| | | */ |
| | | public final void setWritabilityMode( |
| | | WritabilityMode writabilityMode) |
| | | public final void setWritabilityMode(WritabilityMode writabilityMode) |
| | | { |
| | | this.writabilityMode = |
| | | writabilityMode != null ? writabilityMode : WritabilityMode.ENABLED; |
| | | this.writabilityMode = writabilityMode != null ? writabilityMode : WritabilityMode.ENABLED; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the backend monitor that is associated with this |
| | | * backend. |
| | |
| | | this.backendMonitor = backendMonitor; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the total number of entries contained in this backend, |
| | | * if that information is available. |
| | |
| | | */ |
| | | public abstract long getEntryCount(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the parent backend for this backend. |
| | | * |
| | |
| | | return parentBackend; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Specifies the parent backend for this backend. |
| | | * |
| | | * @param parentBackend The parent backend for this backend. |
| | | */ |
| | | public final void setParentBackend(Backend<?> parentBackend) |
| | | { |
| | | synchronized (this) |
| | | public final synchronized void setParentBackend(Backend<?> parentBackend) |
| | | { |
| | | this.parentBackend = parentBackend; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of subordinate backends for this backend. |
| | |
| | | return subordinateBackends; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Specifies the set of subordinate backends for this backend. |
| | | * |
| | | * @param subordinateBackends The set of subordinate backends for |
| | | * this backend. |
| | | */ |
| | | public final void setSubordinateBackends( |
| | | Backend<?>[] subordinateBackends) |
| | | { |
| | | synchronized (this) |
| | | public final synchronized void setSubordinateBackends(Backend<?>[] subordinateBackends) |
| | | { |
| | | this.subordinateBackends = subordinateBackends; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Adds the provided backend to the set of subordinate backends for |
| | |
| | | * subordinate backends for this |
| | | * backend. |
| | | */ |
| | | public final void addSubordinateBackend(Backend<?> subordinateBackend) |
| | | { |
| | | synchronized (this) |
| | | public final synchronized void addSubordinateBackend(Backend<?> subordinateBackend) |
| | | { |
| | | LinkedHashSet<Backend<?>> backendSet = new LinkedHashSet<Backend<?>>(); |
| | | |
| | |
| | | |
| | | if (backendSet.add(subordinateBackend)) |
| | | { |
| | | Backend<?>[] newSubordinateBackends = |
| | | new Backend[backendSet.size()]; |
| | | Backend<?>[] newSubordinateBackends = new Backend[backendSet.size()]; |
| | | backendSet.toArray(newSubordinateBackends); |
| | | subordinateBackends = newSubordinateBackends; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Removes the provided backend from the set of subordinate backends |
| | |
| | | * subordinate backends for this |
| | | * backend. |
| | | */ |
| | | public final void removeSubordinateBackend( |
| | | Backend<?> subordinateBackend) |
| | | public final synchronized void removeSubordinateBackend(Backend<?> subordinateBackend) |
| | | { |
| | | synchronized (this) |
| | | { |
| | | ArrayList<Backend<?>> backendList = |
| | | new ArrayList<Backend<?>>(subordinateBackends.length); |
| | | ArrayList<Backend<?>> backendList = new ArrayList<Backend<?>>(subordinateBackends.length); |
| | | |
| | | boolean found = false; |
| | | for (Backend<?> b : subordinateBackends) |
| | |
| | | |
| | | if (found) |
| | | { |
| | | Backend<?>[] newSubordinateBackends = |
| | | new Backend[backendList.size()]; |
| | | Backend<?>[] newSubordinateBackends = new Backend[backendList.size()]; |
| | | backendList.toArray(newSubordinateBackends); |
| | | subordinateBackends = newSubordinateBackends; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this backend should be used to handle |
| | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether a backend should be used to handle operations |
| | | * for the provided entry given the set of base DNs and exclude DNs. |
| | |
| | | * @return {@code true} if the backend should handle operations for |
| | | * the provided entry, or {@code false} if it does not. |
| | | */ |
| | | public static final boolean handlesEntry(DN entryDN, |
| | | List<DN> baseDNs, |
| | | List<DN> excludeDNs) |
| | | public static final boolean handlesEntry(DN entryDN, List<DN> baseDNs, List<DN> excludeDNs) |
| | | { |
| | | for (DN baseDN : baseDNs) |
| | | { |
| | | if (entryDN.isDescendantOf(baseDN)) |
| | | { |
| | | if (excludeDNs == null || excludeDNs.isEmpty()) |
| | | if (entryDN.isDescendantOf(baseDN) && !isExcluded(excludeDNs, entryDN)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | boolean isExcluded = false; |
| | | private static boolean isExcluded(List<DN> excludeDNs, DN entryDN) |
| | | { |
| | | if (excludeDNs == null || excludeDNs.isEmpty()) |
| | | { |
| | | return false; |
| | | } |
| | | for (DN excludeDN : excludeDNs) |
| | | { |
| | | if (entryDN.isDescendantOf(excludeDN)) |
| | | { |
| | | isExcluded = true; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (! isExcluded) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | } |