/* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.workflowelement.localbackend; import java.util.ArrayList; import java.util.List; import java.util.TreeMap; import org.opends.server.api.Backend; import org.opends.server.core.AddOperation; import org.opends.server.core.BindOperation; import org.opends.server.core.CompareOperation; import org.opends.server.core.DeleteOperation; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyOperation; import org.opends.server.core.SearchOperation; import org.opends.server.types.Operation; import org.opends.server.workflowelement.LeafWorkflowElement; /** * This class defines a local backend workflow element; e-g an entity that * handle the processing of an operation aginst a local backend. */ public class LocalBackendWorkflowElement extends LeafWorkflowElement { // the backend associated with the local workflow element private Backend backend; // the set of local backend workflow elements registered with the server private static TreeMap registeredLocalBackends = new TreeMap(); // a lock to guarantee safe concurrent access to the registeredLocalBackends // variable private static Object registeredLocalBackendsLock = new Object(); /** * Creates a new instance of the local backend workflow element. * * @param workflowElementID the workflow element identifier * @param backend the backend associated to that workflow element */ private LocalBackendWorkflowElement(String workflowElementID, Backend backend) { super(workflowElementID); this.backend = backend; setPrivate(backend.isPrivateBackend()); } /** * Creates and registers a local backend with the server. * * @param workflowElementID the identifier of the workflow element to create * @param backend the backend to associate with the local backend * workflow element * * @return the existing local backend workflow element if it was * already created or a newly created local backend workflow * element. */ public static LocalBackendWorkflowElement create(String workflowElementID, Backend backend) { LocalBackendWorkflowElement localBackend = null; // If the requested workflow element does not exist then create one. localBackend = registeredLocalBackends.get(workflowElementID); if (localBackend == null) { localBackend = new LocalBackendWorkflowElement(workflowElementID, backend); // store the new local backend in the list of registered backends registerLocalBackend(localBackend); } return localBackend; } /** * Removes a local backend that was registered with the server. * * @param workflowElementID the identifier of the workflow element to remove */ public static void remove(String workflowElementID) { deregisterLocalBackend(workflowElementID); } /** * Removes all the local backends that were registered with the server. * This function is intended to be called when the server is shutting down. */ public static void removeAll() { synchronized (registeredLocalBackendsLock) { for (LocalBackendWorkflowElement localBackend: registeredLocalBackends.values()) { deregisterLocalBackend(localBackend.getWorkflowElementID()); } } } /** * Registers a local backend with the server. * * @param localBackend the local backend to register with the server */ private static void registerLocalBackend( LocalBackendWorkflowElement localBackend) { synchronized (registeredLocalBackendsLock) { String localBackendID = localBackend.getWorkflowElementID(); LocalBackendWorkflowElement existingLocalBackend = registeredLocalBackends.get(localBackendID); if (existingLocalBackend == null) { TreeMap newLocalBackends = new TreeMap (registeredLocalBackends); newLocalBackends.put(localBackendID, localBackend); registeredLocalBackends = newLocalBackends; } } } /** * Deregisters a local backend with the server. * * @param workflowElementID the identifier of the workflow element to remove */ private static void deregisterLocalBackend(String workflowElementID) { synchronized (registeredLocalBackendsLock) { LocalBackendWorkflowElement existingLocalBackend = registeredLocalBackends.get(workflowElementID); if (existingLocalBackend != null) { TreeMap newLocalBackends = new TreeMap( registeredLocalBackends); newLocalBackends.remove(workflowElementID); registeredLocalBackends = newLocalBackends; } } } /** * {@inheritDoc} */ public void execute(Operation operation) { switch (operation.getOperationType()) { case BIND: LocalBackendBindOperation bindOperation = new LocalBackendBindOperation((BindOperation) operation); bindOperation.processLocalBind(backend); break; case SEARCH: LocalBackendSearchOperation searchOperation = new LocalBackendSearchOperation((SearchOperation) operation); searchOperation.processLocalSearch(backend); break; case ADD: LocalBackendAddOperation addOperation = new LocalBackendAddOperation((AddOperation) operation); addOperation.processLocalAdd(backend); break; case DELETE: LocalBackendDeleteOperation deleteOperation = new LocalBackendDeleteOperation((DeleteOperation) operation); deleteOperation.processLocalDelete(backend); break; case MODIFY: LocalBackendModifyOperation modifyOperation = new LocalBackendModifyOperation((ModifyOperation) operation); modifyOperation.processLocalModify(backend); break; case MODIFY_DN: LocalBackendModifyDNOperation modifyDNOperation = new LocalBackendModifyDNOperation((ModifyDNOperation) operation); modifyDNOperation.processLocalModifyDN(backend); break; case COMPARE: LocalBackendCompareOperation compareOperation = new LocalBackendCompareOperation((CompareOperation) operation); compareOperation.processLocalCompare(backend); break; case ABANDON: // There is no processing for an abandon operation. break; default: throw new AssertionError("Attempted to execute an invalid operation " + "type: " + operation.getOperationType() + " (" + operation + ")"); } } /** * Attaches the current local operation to the global operation so that * operation runner can execute local operation post response later on. * * @param subtype of Operation * @param subtype of LocalBackendOperation * @param globalOperation the global operation to which local operation * should be attached to * @param currentLocalOperation the local operation to attach to the global * operation */ @SuppressWarnings("unchecked") public static final void attachLocalOperation (O globalOperation, L currentLocalOperation) { List existingAttachment = (List) globalOperation.getAttachment(Operation.LOCALBACKENDOPERATIONS); List newAttachment = new ArrayList(); if (existingAttachment != null) { // This line raises an unchecked conversion warning. // There is nothing we can do to prevent this warning // so let's get rid of it since we know the cast is safe. newAttachment.addAll ((List) existingAttachment); } newAttachment.add (currentLocalOperation); globalOperation.setAttachment(Operation.LOCALBACKENDOPERATIONS, newAttachment); } }