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 2007-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.core; 028 029 030 031 import java.util.ArrayList; 032 import java.util.List; 033 import java.util.concurrent.ConcurrentHashMap; 034 035 import org.opends.messages.Message; 036 import org.opends.server.admin.server.ConfigurationAddListener; 037 import org.opends.server.admin.server.ConfigurationChangeListener; 038 import org.opends.server.admin.server.ConfigurationDeleteListener; 039 import org.opends.server.admin.server.ServerManagementContext; 040 import org.opends.server.admin.std.server.RootCfg; 041 import org.opends.server.admin.std.server.WorkflowCfg; 042 import org.opends.server.config.ConfigException; 043 import org.opends.server.types.ConfigChangeResult; 044 import org.opends.server.types.DN; 045 import org.opends.server.types.DirectoryException; 046 import org.opends.server.types.ResultCode; 047 import org.opends.server.workflowelement.WorkflowElement; 048 049 050 /** 051 * This class defines a utility that will be used to manage the configuration 052 * for the set of workflows defined in the Directory Server. It will perform 053 * the necessary initialization of those workflows when the server is first 054 * started, and then will manage any changes to them while the server is 055 * running. 056 */ 057 public class WorkflowConfigManager 058 implements ConfigurationChangeListener<WorkflowCfg>, 059 ConfigurationAddListener<WorkflowCfg>, 060 ConfigurationDeleteListener<WorkflowCfg> 061 062 { 063 // A mapping between the DNs of the config entries and the associated 064 // workflows. 065 private ConcurrentHashMap<DN, WorkflowImpl> workflows; 066 067 068 069 /** 070 * Creates a new instance of this workflow config manager. 071 */ 072 public WorkflowConfigManager() 073 { 074 workflows = new ConcurrentHashMap<DN, WorkflowImpl>(); 075 } 076 077 078 079 /** 080 * Initializes all workflows currently defined in the Directory 081 * Server configuration. This should only be called at Directory Server 082 * startup. 083 * 084 * @throws ConfigException If a configuration problem causes the workflow 085 * initialization process to fail. 086 */ 087 public void initializeWorkflows() 088 throws ConfigException 089 { 090 // Get the root configuration object. 091 ServerManagementContext managementContext = 092 ServerManagementContext.getInstance(); 093 RootCfg rootConfiguration = 094 managementContext.getRootConfiguration(); 095 096 097 // Register as an add and delete listener with the root configuration so we 098 // can be notified if any workflow entries are added or removed. 099 rootConfiguration.addWorkflowAddListener(this); 100 rootConfiguration.addWorkflowDeleteListener(this); 101 102 103 //Initialize the existing workflows. 104 for (String workflowName : rootConfiguration.listWorkflows()) 105 { 106 WorkflowCfg workflowConfiguration = 107 rootConfiguration.getWorkflow(workflowName); 108 workflowConfiguration.addChangeListener(this); 109 110 if (workflowConfiguration.isEnabled()) 111 { 112 try 113 { 114 createAndRegisterWorkflow(workflowConfiguration); 115 } 116 catch (DirectoryException de) 117 { 118 throw new ConfigException(de.getMessageObject()); 119 } 120 } 121 } 122 } 123 124 125 126 /** 127 * {@inheritDoc} 128 */ 129 public boolean isConfigurationAddAcceptable( 130 WorkflowCfg configuration, 131 List<Message> unacceptableReasons) 132 { 133 // Nothing to check. 134 return true; 135 } 136 137 138 139 /** 140 * {@inheritDoc} 141 */ 142 public ConfigChangeResult applyConfigurationAdd( 143 WorkflowCfg configuration) 144 { 145 ResultCode resultCode = ResultCode.SUCCESS; 146 boolean adminActionRequired = false; 147 ArrayList<Message> messages = new ArrayList<Message>(); 148 149 configuration.addChangeListener(this); 150 151 // If the new network group is enabled then create it and register it. 152 if (configuration.isEnabled()) 153 { 154 try 155 { 156 createAndRegisterWorkflow(configuration); 157 } 158 catch (DirectoryException de) 159 { 160 if (resultCode == ResultCode.SUCCESS) 161 { 162 resultCode = DirectoryServer.getServerErrorResultCode(); 163 } 164 165 messages.add(de.getMessageObject()); 166 } 167 } 168 169 return new ConfigChangeResult(resultCode, adminActionRequired, messages); 170 } 171 172 173 174 /** 175 * {@inheritDoc} 176 */ 177 public boolean isConfigurationDeleteAcceptable( 178 WorkflowCfg configuration, 179 List<Message> unacceptableReasons) 180 { 181 return true; 182 } 183 184 185 186 /** 187 * {@inheritDoc} 188 */ 189 public ConfigChangeResult applyConfigurationDelete( 190 WorkflowCfg configuration) 191 { 192 ResultCode resultCode = ResultCode.SUCCESS; 193 boolean adminActionRequired = false; 194 ArrayList<Message> messages = new ArrayList<Message>(); 195 196 197 WorkflowImpl workflow = workflows.remove(configuration.dn()); 198 if (workflow != null) 199 { 200 workflow.deregister(); 201 workflow.finalizeWorkflow(); 202 } 203 204 return new ConfigChangeResult(resultCode, adminActionRequired, messages); 205 } 206 207 208 209 /** 210 * {@inheritDoc} 211 */ 212 public boolean isConfigurationChangeAcceptable( 213 WorkflowCfg configuration, 214 List<Message> unacceptableReasons) 215 { 216 // Nothing to check. 217 return true; 218 } 219 220 221 222 /** 223 * {@inheritDoc} 224 */ 225 public ConfigChangeResult applyConfigurationChange( 226 WorkflowCfg configuration) 227 { 228 ResultCode resultCode = ResultCode.SUCCESS; 229 boolean adminActionRequired = false; 230 ArrayList<Message> messages = new ArrayList<Message>(); 231 232 ConfigChangeResult configChangeResult = 233 new ConfigChangeResult(resultCode, adminActionRequired, messages); 234 235 236 // Get the existing network group if it's already enabled. 237 WorkflowImpl existingWorkflow = workflows.get(configuration.dn()); 238 239 // If the new configuration has the validator disabled, then disable it if 240 // it is enabled, or do nothing if it's already disabled. 241 if (! configuration.isEnabled()) 242 { 243 if (existingWorkflow != null) 244 { 245 workflows.remove(configuration.dn()); 246 existingWorkflow.deregister(); 247 existingWorkflow.finalizeWorkflow(); 248 } 249 250 return configChangeResult; 251 } 252 253 // If the network group is disabled then create and register it. 254 if (existingWorkflow == null) 255 { 256 try 257 { 258 createAndRegisterWorkflow(configuration); 259 } 260 catch (DirectoryException de) 261 { 262 if (resultCode == ResultCode.SUCCESS) 263 { 264 resultCode = DirectoryServer.getServerErrorResultCode(); 265 } 266 267 messages.add(de.getMessageObject()); 268 } 269 } 270 271 return configChangeResult; 272 } 273 274 275 /** 276 * Creates a workflow, registers the workflow with the server 277 * and registers the workflow with the default network group. 278 * 279 * @param workflowCfg the workflow configuration 280 * 281 * @throws DirectoryException If a problem occurs while trying to 282 * decode a provided string as a DN or if 283 * the workflow ID for a provided workflow 284 * conflicts with the workflow ID of an existing 285 * workflow during workflow registration. 286 */ 287 private void createAndRegisterWorkflow( 288 WorkflowCfg workflowCfg 289 ) throws DirectoryException 290 { 291 // The ID of the workflow to create 292 String workflowId = workflowCfg.getWorkflowId(); 293 294 // Create the root workflow element to associate with the workflow 295 String rootWorkflowElementID = workflowCfg.getWorkflowElement(); 296 WorkflowElement rootWorkflowElement = 297 WorkflowElement.getWorkflowElement(rootWorkflowElementID); 298 299 // Get the base DN targeted by the workflow 300 DN baseDN = workflowCfg.getBaseDN(); 301 302 // Create the workflow and register it with the server 303 WorkflowImpl workflowImpl = 304 new WorkflowImpl(workflowId, baseDN, rootWorkflowElement); 305 workflows.put(workflowCfg.dn(), workflowImpl); 306 workflowImpl.register(); 307 308 // Register the workflow with the default network group 309 NetworkGroup.getDefaultNetworkGroup().registerWorkflow(workflowImpl); 310 } 311 312 } 313