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 }