/* * 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 2009 Sun Microsystems, Inc. * Portions Copyright 2012 ForgeRock AS */ package org.opends.server.workflowelement.externalchangelog; import static org.opends.server.loggers.debug.DebugLogger.getTracer; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.opends.server.admin.std.server.WorkflowElementCfg; import org.opends.server.core.DirectoryServer; import org.opends.server.core.PersistentSearch; import org.opends.server.core.SearchOperation; import org.opends.server.loggers.debug.DebugTracer; import org.opends.server.replication.server.ReplicationServer; import org.opends.server.types.CanceledOperationException; import org.opends.server.types.DirectoryException; import org.opends.server.types.Operation; import org.opends.server.workflowelement.LeafWorkflowElement; /** * This class defines a workflow element for the external changelog (ECL); * e-g an entity that handles the processing of an operation against the ECL. */ public class ECLWorkflowElement extends LeafWorkflowElement<WorkflowElementCfg> { /** * The tracer object for the debug logger. */ private static final DebugTracer TRACER = getTracer(); /** *The set of persistent searches registered with this work flow element. */ private final List<PersistentSearch> persistentSearches = new CopyOnWriteArrayList<PersistentSearch>(); /** * A string indicating the type of the workflow element. */ public static final String ECL_WORKFLOW_ELEMENT = "EXTERNAL CHANGE LOG"; /** * The replication server object to which we will submits request * on the ECL. Retrieved from the local DirectoryServer. */ private ReplicationServer replicationServer; /** * Creates a new instance of the External Change Log workflow element. * @param rs the provided replication server * @throws DirectoryException If the ECL workflow is already registered. */ public ECLWorkflowElement(ReplicationServer rs) throws DirectoryException { this.replicationServer =rs; super.initialize(ECL_WORKFLOW_ELEMENT, ECL_WORKFLOW_ELEMENT); super.setPrivate(true); DirectoryServer.registerWorkflowElement(this); } /** * {@inheritDoc} */ @Override public void finalizeWorkflowElement() { // null all fields so that any use of the finalized object will raise // an NPE super.initialize(ECL_WORKFLOW_ELEMENT, null); // Cancel all persistent searches. for (PersistentSearch psearch : persistentSearches) { psearch.cancel(); } persistentSearches.clear(); } /** * {@inheritDoc} */ public void execute(Operation operation) throws CanceledOperationException { switch (operation.getOperationType()) { case SEARCH: ECLSearchOperation searchOperation = new ECLSearchOperation((SearchOperation) operation); searchOperation.processECLSearch(this); break; case ABANDON: // There is no processing for an abandon operation. break; case BIND: case ADD: case DELETE: case MODIFY: case MODIFY_DN: case COMPARE: 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 <O> subtype of Operation * @param <L> 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 <O extends Operation,L> void attachLocalOperation (O globalOperation, L currentLocalOperation) { List<?> existingAttachment = (List<?>) globalOperation.getAttachment(Operation.LOCALBACKENDOPERATIONS); List<L> newAttachment = new ArrayList<L>(); 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<L>) existingAttachment); } newAttachment.add (currentLocalOperation); globalOperation.setAttachment(Operation.LOCALBACKENDOPERATIONS, newAttachment); } /** * Registers the provided persistent search operation with this * workflow element so that it will be notified of any * add, delete, modify, or modify DN operations that are performed. * * @param persistentSearch * The persistent search operation to register with this * workflow element. */ void registerPersistentSearch(PersistentSearch persistentSearch) { PersistentSearch.CancellationCallback callback = new PersistentSearch.CancellationCallback() { public void persistentSearchCancelled(PersistentSearch psearch) { psearch.getSearchOperation().cancel(null); persistentSearches.remove(psearch); } }; persistentSearches.add(persistentSearch); persistentSearch.registerCancellationCallback(callback); } /** * Gets the list of persistent searches currently active against * this workflow element. * * @return The list of persistent searches currently active against * this workflow element. */ public List<PersistentSearch> getPersistentSearches() { return persistentSearches; } /** * Returns the associated replication server. * @return the rs. */ public ReplicationServer getReplicationServer() { return this.replicationServer; } }