/*
* 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 legal-notices/CDDLv1_0.txt
* 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 legal-notices/CDDLv1_0.txt.
* 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.
*/
/**
* This class implements the workflow interface. Each task in the workflow
* is implemented by a WorkflowElement. All the tasks in the workflow are
* structured in a tree of tasks and the root node of the task tree is
* stored in the Workflow class itself. To execute a workflow, one just need
* to call the execute method on the root node of the task tree. Then each
* task in turn will execute its subordinate nodes and synchronizes them
* as needed.
*/
{
// The workflow identifier used by the configuration.
// The root of the workflow task tree.
// The root workflow element identifier.
// The base DN of the data handled by the workflow.
// Flag indicating whether the workflow root node of the task tree is
// handling a private local backend.
//
// A private local backend is used by the server to store "private data"
// such as schemas, tasks, monitoring data, configuration data... Such
// private data are not returned upon a subtree search on the root DSE.
// Also it is not planned to have anything but a single node task tree
// to handle private local backend. So workflows used for proxy and
// virtual will always be made public (ie. not private). So, unless the
// rootWorkflowElement is handling a private local backend, the isPrivate
// flag will always return false.
private boolean isPrivate = false;
// The set of workflows registered with the server.
// A lock to protect concurrent access to the registeredWorkflows.
// A reference counter used to count the number of workflow nodes that
// were registered with a network group. A workflow can be disabled or
// deleted only when its reference counter value is 0.
/**
* Creates a new instance of a workflow implementation. To define a workflow
* one needs to provide a task tree root node (the rootWorkflowElement) and
* a base DN to identify the data set upon which the tasks can be applied.
*
* The rootWorkflowElement must not be null.
*
* @param workflowId workflow internal identifier
* @param baseDN identifies the data handled by the workflow
* @param rootWorkflowElementID the identifier of the root workflow element
* @param rootWorkflowElement the root node of the workflow task tree
*/
public WorkflowImpl(
)
{
this.workflowID = workflowId;
if (this.rootWorkflowElement != null)
{
// The workflow wants to be notified when the workflow element state
// is changing from enabled to disabled and vice versa.
rootWorkflowElement, null, this);
}
else
{
// The root workflow element has not been loaded, let's register
// the workflow with the list of objects that want to be notify
// when the workflow element is created.
null, rootWorkflowElementID, this);
}
}
/**
* Performs any finalization that might be required when this
* workflow is unloaded. No action is taken in the default
* implementation.
*/
public void finalizeWorkflow()
{
// No action is required by default.
}
/**
* Gets the base DN of the data set being handled by the workflow.
*
* @return the workflow base DN
*/
{
return baseDN;
}
/**
* Gets the workflow internal identifier.
*
* @return the workflow internal identifier
*/
{
return workflowID;
}
/**
* Indicates whether the root node of the workflow task tree is
* handling a private local backend.
*
* @return <code>true</code> if the workflow encapsulates a private local
* backend
*/
public boolean isPrivate()
{
return isPrivate;
}
/**
* Executes all the tasks defined by the workflow task tree for a given
* operation.
*
* @param operation the operation to execute
*
* @throws CanceledOperationException if this operation should
* be canceled.
*/
throws CanceledOperationException
{
if (rootWorkflowElement != null)
{
}
else
{
// No root workflow element? It's a configuration error.
}
}
/**
* Registers the current workflow (this) with the server.
*
* @throws DirectoryException If the workflow ID for the provided workflow
* conflicts with the workflow ID of an existing
* workflow.
*/
public void register()
throws DirectoryException
{
synchronized (registeredWorkflowsLock)
{
// The workflow must not be already registered
{
throw new DirectoryException(
}
}
}
/**
* Deregisters the current workflow (this) with the server.
*/
public void deregister()
{
// Deregister the workflow with the list of objects to notify when
// a workflow element is created or deleted.
null, rootWorkflowElementID, this);
// Deregister the workflow with the list of registered workflows.
synchronized (registeredWorkflowsLock)
{
}
}
/**
* Deregisters a workflow with the server. The workflow to deregister
* is identified with its identifier.
*
* @param workflowID the identifier of the workflow to deregister
*
* @return the workflow that has been deregistered,
* <code>null</code> if no workflow has been found.
*/
{
synchronized (registeredWorkflowsLock)
{
{
}
}
return workflowToDeregister;
}
/**
* Deregisters all Workflows that have been registered. This should be
* called when the server is shutting down.
*/
public static void deregisterAllOnShutdown()
{
synchronized (registeredWorkflowsLock)
{
}
}
/**
* Gets a workflow that was registered with the server.
*
* @param workflowID the ID of the workflow to get
* @return the requested workflow
*/
{
}
/**
* Gets all the workflows that were registered with the server.
*
* @return the list of registered workflows
*/
{
return registeredWorkflows.values();
}
/**
* Gets the root workflow element for test purpose only.
*
* @return the root workflow element.
*/
{
return rootWorkflowElement;
}
/**
* Resets all the registered workflows.
*/
public static void resetConfig()
{
synchronized (registeredWorkflowsLock)
{
}
}
/**
* Updates the workflow configuration. This method should be invoked
* whenever an existing workflow is modified.
*
* @param configuration the new workflow configuration
*/
{
// The only parameter that can be changed is the root workflow element.
// Update the ID of the new root workflow element
// and deregister the workflow with the list of objects to notify
// when the former root workflow element is created
null, previousRootWorkflowElement, this);
// Does the new root workflow element exist?
if (rootWorkflowElement == null)
{
// The new root workflow element does not exist yet then do nothing
// but register with the list of object to notify when the workflow
// element is created (and deregister first in case the workflow
// was already registered)
null, rootWorkflowElementID, this);
}
else
{
// The new root workflow element exists, let's use it and don't forget
// to register with the list of objects to notify when the workflow
// element is deleted.
rootWorkflowElement, null, this);
}
}
/**
* {@inheritDoc}
*/
{
if (observable instanceof ObservableWorkflowElementState)
{
}
}
/**
* Display the workflow object.
* @return a string identifying the workflow.
*/
{
return id;
}
/**
* Takes into account an update of the root workflow element.
* <p>
* This method is called when a workflow element is created or
* deleted. If the workflow element is the root workflow element
* then the workflow processes it as follow:
* <br>
* If the workflow element is disabled then the workflow reset
* its root workflow element (ie. the workflow has no more workflow
* element, hence the workflow cannot process requests anymore).
* <br>
* If the workflow element is enabled then the workflow adopts the
* workflow element as its new root workflow element. The workflow
* then can process requests again.
*
* @param weState the new state of the root workflow element
*/
private void updateRootWorkflowElementState(
{
// Check that the workflow element maps the root workflow element.
// If not then ignore the workflow element.
{
return;
}
// The workflow element maps the root workflow element, let's process it.
if (weState.workflowElementIsEnabled())
{
// The root workflow element is enabled, let's use it
// and don't forget to register the workflow with the list
// of objects to notify when the root workflow element
// is disabled...
rootWorkflowElement, null, this);
null, rootWorkflowElementID, this);
}
else
{
// The root workflow element has been disabled. Reset the current
// reference to the root workflow element and register the workflow
// with the list of objects to notify when new workflow elements
// are created.
}
}
/**
* Increments the workflow reference counter.
* <p>
* As long as the counter value is not 0 the workflow cannot be
* disabled nor deleted.
*/
public void incrementReferenceCounter()
{
synchronized (referenceCounterLock)
{
}
}
/**
* Decrements the workflow reference counter.
* <p>
* As long as the counter value is not 0 the workflow cannot be
* disabled nor deleted.
*/
public void decrementReferenceCounter()
{
synchronized (referenceCounterLock)
{
if (referenceCounter == 0)
{
// the counter value is 0, we should not need to decrement anymore
throw new AssertionError(
"Reference counter of the workflow " + workflowID
+ " is already set to 0, cannot decrement it anymore"
);
}
}
}
/**
* Gets the value of the reference counter of the workflow.
*
* @return the reference counter of the workflow
*/
public int getReferenceCounter()
{
return referenceCounter;
}
}