mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noel Rouvignac
23.18.2013 ff99696311668f339200080a826bbc6efc708291
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
 * 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
 * or http://forgerock.org/license/CDDLv1.0.html.
 * 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-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;
  }
 
}