001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.core;
028
029
030 import org.opends.server.types.*;
031
032
033 /**
034 * This class implements the workflow node that handles the root DSE entry.
035 * As opposed to the WorkflowTopologyNode class, the root DSE node has no
036 * parent node nor subordinate nodes. Instead, the root DSE node has a set
037 * of naming contexts, each of which is a WorkflowTopologyNode object with
038 * no parent.
039 */
040 public class RootDseWorkflowTopology extends WorkflowTopology
041 {
042
043 // The naming contexts known by the root DSE. These naming contexts
044 // are defined in the scope of a network group.
045 private NetworkGroupNamingContexts namingContexts = null;
046
047
048 /**
049 * Creates a workflow node to handle the root DSE entry.
050 *
051 * @param workflowImpl the workflow which contains the processing for
052 * the root DSE backend
053 * @param namingContexts the list of naming contexts being registered
054 * with the network group the root DSE belongs to
055 */
056 public RootDseWorkflowTopology(
057 WorkflowImpl workflowImpl,
058 NetworkGroupNamingContexts namingContexts
059 )
060 {
061 super(workflowImpl);
062 this.namingContexts = namingContexts;
063 }
064
065
066 /**
067 * Executes an operation on the root DSE entry.
068 *
069 * @param operation the operation to execute
070 *
071 * @throws CanceledOperationException if this operation should
072 * be cancelled.
073 */
074 public void execute(Operation operation)
075 throws CanceledOperationException {
076 // Execute the operation.
077 OperationType operationType = operation.getOperationType();
078 if (operationType != OperationType.SEARCH)
079 {
080 // Execute the operation
081 getWorkflowImpl().execute(operation);
082 }
083 else
084 {
085 // Execute the SEARCH operation
086 executeSearch((SearchOperation) operation);
087 }
088 }
089
090
091 /**
092 * Executes a search operation on the the root DSE entry.
093 *
094 * @param searchOp the operation to execute
095 *
096 * @throws CanceledOperationException if this operation should
097 * be cancelled.
098 */
099 private void executeSearch(SearchOperation searchOp)
100 throws CanceledOperationException {
101 // Keep a the original search scope because we will alter it in the
102 // operation.
103 SearchScope originalScope = searchOp.getScope();
104
105 // Search base?
106 // The root DSE entry itself is never returned unless the operation
107 // is a search base on the null suffix.
108 if (originalScope == SearchScope.BASE_OBJECT)
109 {
110 getWorkflowImpl().execute(searchOp);
111 return;
112 }
113
114 // Create a workflow result code in case we need to perform search in
115 // subordinate workflows.
116 WorkflowResultCode workflowResultCode = new WorkflowResultCode(
117 searchOp.getResultCode(), searchOp.getErrorMessage());
118
119 // The search scope is not 'base', so let's do a search on all the public
120 // naming contexts with appropriate new search scope and new base DN.
121 SearchScope newScope = elaborateScopeForSearchInSubordinates(originalScope);
122 searchOp.setScope(newScope);
123 DN originalBaseDN = searchOp.getBaseDN();
124
125 for (WorkflowTopologyNode namingContext:
126 namingContexts.getPublicNamingContexts())
127 {
128 // We have to change the operation request base DN to match the
129 // subordinate workflow base DN. Otherwise the workflow will
130 // return a no such entry result code as the operation request
131 // base DN is a superior of the workflow base DN!
132 DN ncDN = namingContext.getBaseDN();
133
134 // Set the new request base DN then do execute the operation
135 // in the naming context workflow.
136 searchOp.setBaseDN(ncDN);
137 namingContext.execute(searchOp);
138 boolean sendReferenceEntry =
139 workflowResultCode.elaborateGlobalResultCode(
140 searchOp.getResultCode(), searchOp.getErrorMessage());
141 if (sendReferenceEntry)
142 {
143 // TODO jdemendi - turn a referral result code into a reference entry
144 // and send the reference entry to the client application
145 }
146 }
147
148 // Now restore the original request base DN and original search scope
149 searchOp.setBaseDN(originalBaseDN);
150 searchOp.setScope(originalScope);
151
152 // Set the operation result code and error message
153 searchOp.setResultCode(workflowResultCode.resultCode());
154 searchOp.setErrorMessage(workflowResultCode.errorMessage());
155 }
156
157
158 /**
159 * Dumps info from the current workflow for debug purpose.
160 *
161 * @param leftMargin white spaces used to indent the traces
162 * @return a string buffer that contains trace information
163 */
164 public StringBuilder toString(String leftMargin)
165 {
166 StringBuilder sb = new StringBuilder();
167
168 // display the identifier and baseDN
169 String workflowID = this.getWorkflowImpl().getWorkflowId();
170 sb.append(leftMargin + "Workflow ID = " + workflowID + "\n");
171 sb.append(leftMargin + " baseDN:[ \"\" ]\n");
172
173 return sb;
174 }
175
176 }