From b565f3d7b15411e46a1de481da6d3d66b6d551c5 Mon Sep 17 00:00:00 2001
From: abobrov <abobrov@localhost>
Date: Wed, 24 Dec 2008 01:52:52 +0000
Subject: [PATCH] - land NULL Backend implementation.
---
opends/src/server/org/opends/server/backends/NullBackend.java | 665 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 665 insertions(+), 0 deletions(-)
diff --git a/opends/src/server/org/opends/server/backends/NullBackend.java b/opends/src/server/org/opends/server/backends/NullBackend.java
new file mode 100644
index 0000000..70561dc
--- /dev/null
+++ b/opends/src/server/org/opends/server/backends/NullBackend.java
@@ -0,0 +1,665 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.backends;
+
+
+
+import java.util.HashMap;
+import java.util.HashSet;
+
+import java.util.List;
+import java.util.Map;
+import org.opends.messages.Category;
+import org.opends.messages.Message;
+import org.opends.messages.Severity;
+import org.opends.server.admin.Configuration;
+import org.opends.server.admin.std.server.BackendCfg;
+import org.opends.server.api.Backend;
+import org.opends.server.config.ConfigException;
+import org.opends.server.controls.PagedResultsControl;
+import org.opends.server.core.AddOperation;
+import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.SearchOperation;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.BackupConfig;
+import org.opends.server.types.BackupDirectory;
+import org.opends.server.types.ConditionResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DN;
+import org.opends.server.types.Entry;
+import org.opends.server.types.IndexType;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.LDAPException;
+import org.opends.server.types.LDIFExportConfig;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.LDIFImportResult;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.RestoreConfig;
+import org.opends.server.types.ResultCode;
+import org.opends.server.util.LDIFException;
+import org.opends.server.util.LDIFReader;
+import org.opends.server.util.LDIFWriter;
+import org.opends.server.util.Validator;
+
+import static org.opends.messages.BackendMessages.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.*;
+
+
+
+/**
+ * This class implements /dev/null like backend for development and testing.
+ *
+ * The following behaviors of this backend implementation should be noted:
+ *
+ * * All read operations return success but no data.
+ *
+ * * All write operations return success but do nothing.
+ *
+ * * Bind operations fail with invalid credentials.
+ *
+ * * Compare operations are only possible on objectclass and returns true
+ * for the following objeclasses only: top, nullbackendobject,
+ * extensibleobject. Otherwise comparison result is false or comparison
+ * fails altogether.
+ *
+ * * Controls are supported although this implementation does not provide
+ * any specific emulation for controls. Generally known request controls
+ * are accepted and default response controls returned where applicable.
+ *
+ * * Searches withing this backend are always considered as indexed.
+ *
+ * * Backend Import is supported by iterating over ldif reader on a single
+ * thread and issuing add operations which essentially do nothing at all.
+ *
+ * * Backend Export is supported but does nothing producing an empty ldif.
+ *
+ * * Backend Backup and Restore are not supported.
+ *
+ * This backend implementation is for development and testing only, does
+ * not represent a complete and stable API, should be considered private
+ * and subject to change without notice.
+ */
+public class NullBackend extends Backend
+{
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = getTracer();
+
+
+
+ // The base DNs for this backend.
+ private DN[] baseDNs;
+
+ // The base DNs for this backend, in a hash set.
+ private HashSet<DN> baseDNSet;
+
+ // The set of supported controls for this backend.
+ private HashSet<String> supportedControls;
+
+ // The set of supported features for this backend.
+ private HashSet<String> supportedFeatures;
+
+ // The map of null entry object classes.
+ private Map<ObjectClass,String> objectClasses;
+
+
+
+ /**
+ * Creates a new backend with the provided information. All backend
+ * implementations must implement a default constructor that use
+ * <CODE>super()</CODE> to invoke this constructor.
+ */
+ public NullBackend()
+ {
+ super();
+
+ // 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
+ * object when initializing the backend.
+ * @param baseDNs The set of base DNs to be served by this memory backend.
+ */
+ public void setBaseDNs(DN[] baseDNs)
+ {
+ this.baseDNs = baseDNs;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void configureBackend(Configuration config)
+ throws ConfigException
+ {
+ if (config != null)
+ {
+ Validator.ensureTrue(config instanceof BackendCfg);
+ BackendCfg cfg = (BackendCfg)config;
+ DN[] cfgBaseDNs = new DN[cfg.getBaseDN().size()];
+ cfg.getBaseDN().toArray(cfgBaseDNs);
+ setBaseDNs(cfgBaseDNs);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public synchronized void initializeBackend()
+ throws ConfigException, InitializationException
+ {
+ baseDNSet = new HashSet<DN>();
+ for (DN dn : baseDNs)
+ {
+ baseDNSet.add(dn);
+ }
+
+ // Add supported controls.
+ supportedControls = new HashSet<String>();
+ supportedControls.add(OID_SUBTREE_DELETE_CONTROL);
+ supportedControls.add(OID_PAGED_RESULTS_CONTROL);
+ supportedControls.add(OID_MANAGE_DSAIT_CONTROL);
+ supportedControls.add(OID_SERVER_SIDE_SORT_REQUEST_CONTROL);
+ supportedControls.add(OID_VLV_REQUEST_CONTROL);
+
+ // Add supported features.
+ supportedFeatures = new HashSet<String>();
+
+ // Register base DNs.
+ for (DN dn : baseDNs)
+ {
+ try
+ {
+ DirectoryServer.registerBaseDN(dn, this, false);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ Message message = ERR_BACKEND_CANNOT_REGISTER_BASEDN.get(
+ dn.toString(), getExceptionMessage(e));
+ throw new InitializationException(message, e);
+ }
+ }
+
+ // Initialize null entry object classes.
+ objectClasses = new HashMap<ObjectClass,String>();
+
+ String topOCName = "top";
+ ObjectClass topOC = DirectoryServer.getObjectClass(topOCName);
+ if (topOC == null) {
+ throw new InitializationException(Message.raw(
+ Category.BACKEND, Severity.FATAL_ERROR,
+ "Unable to locate " + topOCName +
+ " objectclass in the current server schema"));
+ }
+ objectClasses.put(topOC, topOCName);
+
+ String nulOCName = "nullbackendobject";
+ ObjectClass nulOC = DirectoryServer.getDefaultObjectClass(nulOCName);
+ try {
+ DirectoryServer.registerObjectClass(nulOC, false);
+ } catch (DirectoryException de) {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+ throw new InitializationException(de.getMessageObject());
+ }
+ objectClasses.put(nulOC, nulOCName);
+
+ String extOCName = "extensibleobject";
+ ObjectClass extOC = DirectoryServer.getObjectClass(extOCName);
+ if (extOC == null) {
+ throw new InitializationException(Message.raw(
+ Category.BACKEND, Severity.FATAL_ERROR,
+ "Unable to locate " + extOCName +
+ " objectclass in the current server schema"));
+ }
+ objectClasses.put(extOC, extOCName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public synchronized void finalizeBackend()
+ {
+ for (DN dn : baseDNs)
+ {
+ try
+ {
+ DirectoryServer.deregisterBaseDN(dn);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public DN[] getBaseDNs()
+ {
+ return baseDNs;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public long getEntryCount()
+ {
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean isLocal()
+ {
+ // For the purposes of this method, this is a local backend.
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean isIndexed(AttributeType attributeType, IndexType indexType)
+ {
+ // All searches in this backend will always be considered indexed.
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ConditionResult hasSubordinates(DN entryDN)
+ throws DirectoryException
+ {
+ return ConditionResult.UNDEFINED;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public long numSubordinates(DN entryDN, boolean subtree)
+ throws DirectoryException
+ {
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public Entry getEntry(DN entryDN)
+ {
+ return new Entry(null, objectClasses, null, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean entryExists(DN entryDN)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void addEntry(Entry entry, AddOperation addOperation)
+ throws DirectoryException
+ {
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void deleteEntry(DN entryDN, DeleteOperation deleteOperation)
+ throws DirectoryException
+ {
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void replaceEntry(Entry oldEntry, Entry newEntry,
+ ModifyOperation modifyOperation) throws DirectoryException
+ {
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void renameEntry(DN currentDN, Entry entry,
+ ModifyDNOperation modifyDNOperation)
+ throws DirectoryException
+ {
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void search(SearchOperation searchOperation)
+ throws DirectoryException
+ {
+ List<Control> controls = searchOperation.getRequestControls();
+ PagedResultsControl pageRequest = null;
+
+ if (controls != null) {
+ for (Control control : controls) {
+ if (control.getOID().equals(OID_PAGED_RESULTS_CONTROL)) {
+ // Ignore all but the first paged results control.
+ if (pageRequest == null) {
+ try {
+ pageRequest = new PagedResultsControl(control.isCritical(),
+ control.getValue());
+ } catch (LDAPException e) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ throw new DirectoryException(ResultCode.PROTOCOL_ERROR,
+ e.getMessageObject(), e);
+ }
+ }
+ }
+ }
+ }
+
+ if (pageRequest != null) {
+ // Indicate no more pages.
+ PagedResultsControl control;
+ control = new PagedResultsControl(pageRequest.isCritical(), 0,
+ new ASN1OctetString());
+ searchOperation.getResponseControls().add(control);
+ }
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public HashSet<String> getSupportedControls()
+ {
+ return supportedControls;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public HashSet<String> getSupportedFeatures()
+ {
+ return supportedFeatures;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean supportsLDIFExport()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void exportLDIF(LDIFExportConfig exportConfig)
+ throws DirectoryException
+ {
+ LDIFWriter ldifWriter;
+
+ try {
+ ldifWriter = new LDIFWriter(exportConfig);
+ } catch (Exception e) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ Message message = Message.raw(
+ Category.BACKEND, Severity.SEVERE_ERROR, e.getMessage());
+ throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+ message);
+ }
+
+ try {
+ ldifWriter.close();
+ } catch (Exception e) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean supportsLDIFImport()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public LDIFImportResult importLDIF(LDIFImportConfig importConfig)
+ throws DirectoryException
+ {
+ LDIFReader reader;
+ try
+ {
+ reader = new LDIFReader(importConfig);
+ }
+ catch (Exception e)
+ {
+ Message message = Message.raw(
+ Category.BACKEND, Severity.SEVERE_ERROR, e.getMessage());
+ throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+ message);
+ }
+
+ try
+ {
+ while (true)
+ {
+ Entry e = null;
+ try
+ {
+ e = reader.readEntry();
+ if (e == null)
+ {
+ break;
+ }
+ }
+ catch (LDIFException le)
+ {
+ if (! le.canContinueReading())
+ {
+ Message message = Message.raw(
+ Category.BACKEND, Severity.SEVERE_ERROR, le.getMessage());
+ throw new DirectoryException(
+ DirectoryServer.getServerErrorResultCode(),message);
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ try
+ {
+ addEntry(e, null);
+ }
+ catch (DirectoryException de)
+ {
+ reader.rejectLastEntry(de.getMessageObject());
+ }
+ }
+
+ return new LDIFImportResult(reader.getEntriesRead(),
+ reader.getEntriesRejected(),
+ reader.getEntriesIgnored());
+ }
+ catch (DirectoryException de)
+ {
+ throw de;
+ }
+ catch (Exception e)
+ {
+ Message message = Message.raw(
+ Category.BACKEND, Severity.SEVERE_ERROR, e.getMessage());
+ throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+ message);
+ }
+ finally
+ {
+ reader.close();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean supportsBackup()
+ {
+ // This backend does not provide a backup/restore mechanism.
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean supportsBackup(BackupConfig backupConfig,
+ StringBuilder unsupportedReason)
+ {
+ // This backend does not provide a backup/restore mechanism.
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void createBackup(BackupConfig backupConfig)
+ throws DirectoryException
+ {
+ Message message = Message.raw(
+ Category.BACKEND, Severity.SEVERE_ERROR,
+ "The null backend does not support backup operation");
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void removeBackup(BackupDirectory backupDirectory,
+ String backupID)
+ throws DirectoryException
+ {
+ Message message = Message.raw(
+ Category.BACKEND, Severity.SEVERE_ERROR,
+ "The null backend does not support remove backup operation");
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean supportsRestore()
+ {
+ // This backend does not provide a backup/restore mechanism.
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void restoreBackup(RestoreConfig restoreConfig)
+ throws DirectoryException
+ {
+ Message message = Message.raw(
+ Category.BACKEND, Severity.SEVERE_ERROR,
+ "The null backend does not support restore operation");
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void preloadEntryCache() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Operation not supported.");
+ }
+}
--
Gitblit v1.10.0