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