/*
* 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-2010 Sun Microsystems, Inc.
*/
package org.opends.server.core;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
import org.opends.server.core.networkgroups.NetworkGroupNamingContexts;
import org.opends.server.types.*;
/**
* This class implements the workflow node that handles the root DSE entry.
* As opposed to the WorkflowTopologyNode class, the root DSE node has no
* parent node nor subordinate nodes. Instead, the root DSE node has a set
* of naming contexts, each of which is a WorkflowTopologyNode object with
* no parent.
*/
public class RootDseWorkflowTopology extends WorkflowTopology
{
// The naming contexts known by the root DSE. These naming contexts
// are defined in the scope of a network group.
private NetworkGroupNamingContexts namingContexts = null;
/**
* Creates a workflow node to handle the root DSE entry.
*
* @param workflowImpl the workflow which contains the processing for
* the root DSE backend
* @param namingContexts the list of naming contexts being registered
* with the network group the root DSE belongs to
*/
public RootDseWorkflowTopology(
WorkflowImpl workflowImpl,
NetworkGroupNamingContexts namingContexts
)
{
super(workflowImpl);
this.namingContexts = namingContexts;
}
/**
* Executes an operation on the root DSE entry.
*
* @param operation the operation to execute
*
* @throws CanceledOperationException if this operation should
* be cancelled.
*/
public void execute(Operation operation)
throws CanceledOperationException {
// Execute the operation.
OperationType operationType = operation.getOperationType();
if (operationType != OperationType.SEARCH)
{
// Execute the operation
getWorkflowImpl().execute(operation);
}
else
{
// Execute the SEARCH operation
executeSearch((SearchOperation) operation);
}
}
/**
* Executes a search operation on the the root DSE entry.
*
* @param searchOp the operation to execute
*
* @throws CanceledOperationException if this operation should
* be cancelled.
*/
private void executeSearch(SearchOperation searchOp)
throws CanceledOperationException {
// Keep a the original search scope because we will alter it in the
// operation.
SearchScope originalScope = searchOp.getScope();
// Search base?
// The root DSE entry itself is never returned unless the operation
// is a search base on the null suffix.
if (originalScope == SearchScope.BASE_OBJECT)
{
getWorkflowImpl().execute(searchOp);
return;
}
// Create a workflow result code in case we need to perform search in
// subordinate workflows.
WorkflowResultCode workflowResultCode = new WorkflowResultCode(
searchOp.getResultCode(), searchOp.getErrorMessage());
// The search scope is not 'base', so let's do a search on all the public
// naming contexts with appropriate new search scope and new base DN.
SearchScope newScope = elaborateScopeForSearchInSubordinates(originalScope);
searchOp.setScope(newScope);
DN originalBaseDN = searchOp.getBaseDN();
Iterable<WorkflowTopologyNode> ncToSearch =
DirectoryServer.getRootDSEBackend().getSubordinateNamingContexts(
namingContexts.getPublicNamingContexts());
for (WorkflowTopologyNode namingContext: ncToSearch)
{
// We have to change the operation request base DN to match the
// subordinate workflow base DN. Otherwise the workflow will
// return a no such entry result code as the operation request
// base DN is a superior of the workflow base DN!
DN ncDN = namingContext.getBaseDN();
// Set the new request base DN then do execute the operation
// in the naming context workflow.
searchOp.setBaseDN(ncDN);
namingContext.execute(searchOp);
boolean sendReferenceEntry =
workflowResultCode.elaborateGlobalResultCode(
searchOp.getResultCode(), searchOp.getErrorMessage());
if (sendReferenceEntry)
{
// TODO jdemendi - turn a referral result code into a reference entry
// and send the reference entry to the client application
}
}
// Now restore the original request base DN and original search scope
searchOp.setBaseDN(originalBaseDN);
searchOp.setScope(originalScope);
// If the result code is still uninitialized (ie no naming context),
// we should return NO_SUCH_OBJECT
workflowResultCode.elaborateGlobalResultCode(
ResultCode.NO_SUCH_OBJECT, new MessageBuilder(Message.EMPTY));
// Set the operation result code and error message
searchOp.setResultCode(workflowResultCode.resultCode());
searchOp.setErrorMessage(workflowResultCode.errorMessage());
}
/**
* Dumps info from the current workflow for debug purpose.
*
* @param leftMargin white spaces used to indent the traces
* @return a string buffer that contains trace information
*/
public StringBuilder toString(String leftMargin)
{
StringBuilder sb = new StringBuilder();
// display the identifier and baseDN
String workflowID = this.getWorkflowImpl().getWorkflowId();
sb.append(leftMargin + "Workflow ID = " + workflowID + "\n");
sb.append(leftMargin + " baseDN:[ \"\" ]\n");
return sb;
}
}