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.workflowelement;
028
029 import static org.opends.server.util.Validator.ensureNotNull;
030 import static org.opends.messages.ConfigMessages.*;
031
032 import java.util.List;
033 import java.util.TreeMap;
034
035 import org.opends.messages.Message;
036 import org.opends.server.admin.std.server.WorkflowElementCfg;
037 import org.opends.server.config.ConfigException;
038 import org.opends.server.types.Operation;
039 import org.opends.server.types.CanceledOperationException;
040
041
042 /**
043 * This class defines the super class for all the workflow elements. A workflow
044 * element is a task in a workflow. A workflow element can wrap a physical
045 * repository such as a local backend, a remote LDAP server or a local ldif
046 * file. A workflow element can also be used to route operations. This is the
047 * case for load balancing and distribution. And workflow element can be used
048 * in a virtual environment to transform data (DN and attribute renaming,
049 * attribute value renaming...).
050 *
051 * @param <T> The type of configuration handled by this workflow elelemnt.
052 */
053 public abstract class WorkflowElement
054 <T extends WorkflowElementCfg>
055 {
056 // Indicates whether the workflow element encapsulates a private local
057 // backend.
058 private boolean isPrivate = false;
059
060
061 // The workflow element identifier.
062 private String workflowElementID = null;
063
064
065 // The set of workflow elements registered with the server.
066 // The workflow element identifier is used as a key in the map.
067 private static TreeMap<String, WorkflowElement> registeredWorkflowElements =
068 new TreeMap<String, WorkflowElement>();
069
070
071 // A lock to protect access to the registered workflow elements.
072 private static Object registeredWorkflowElementsLock = new Object();
073
074
075 // The parent of the workflow element (null if the workflow element is
076 // the root of the processing tree).
077 private WorkflowElement<?> parent = null;
078
079
080 /**
081 * Creates a new instance of the workflow element.
082 */
083 public WorkflowElement()
084 {
085 // There is nothing to do in the constructor.
086 }
087
088
089 /**
090 * Initializes the instance of the workflow element.
091 *
092 * @param workflowElementID the workflow element identifier as defined
093 * in the configuration.
094 */
095 public void initialize(String workflowElementID)
096 {
097 this.workflowElementID = workflowElementID;
098 }
099
100
101 /**
102 * Set the parent of the current workflow element.
103 *
104 * @param parent the parent of the workflow element
105 */
106 protected void setParent(WorkflowElement<?> parent)
107 {
108 this.parent = parent;
109 }
110
111
112 /**
113 * Indicates whether the provided configuration is acceptable for
114 * this workflow elelement.
115 *
116 * @param configuration The workflow element configuration for
117 * which to make the determination.
118 * @param unacceptableReasons A list that may be used to hold the
119 * reasons that the provided
120 * configuration is not acceptable.
121 *
122 * @return {@code true} if the provided configuration is acceptable
123 * for this workflow element, or {@code false} if not.
124 */
125 public boolean isConfigurationAcceptable(
126 WorkflowElementCfg configuration,
127 List<String> unacceptableReasons)
128 {
129 // This default implementation does not perform any special
130 // validation. It should be overridden by workflow element
131 // implementations that wish to perform more detailed validation.
132 return true;
133 }
134
135
136 /**
137 * Performs any finalization that might be required when this
138 * workflow element is unloaded. No action is taken in the default
139 * implementation.
140 */
141 public void finalizeWorkflowElement()
142 {
143 // No action is required by default.
144 }
145
146
147 /**
148 * Executes the workflow element for an operation.
149 *
150 * @param operation the operation to execute
151 *
152 * @throws CanceledOperationException if this operation should be
153 * cancelled
154 */
155 public abstract void execute(Operation operation)
156 throws CanceledOperationException;
157
158
159 /**
160 * Indicates whether the workflow element encapsulates a private
161 * local backend.
162 *
163 * @return <code>true</code> if the workflow element encapsulates a private
164 * local backend, <code>false</code> otherwise
165 */
166 public boolean isPrivate()
167 {
168 return isPrivate;
169 }
170
171
172 /**
173 * Specifies whether the workflow element encapsulates a private local
174 * backend.
175 *
176 * @param isPrivate Indicates whether the workflow element encapsulates a
177 * private local backend.
178 */
179 protected void setPrivate(boolean isPrivate)
180 {
181 this.isPrivate = isPrivate;
182 }
183
184
185 /**
186 * Provides the workflow element identifier.
187 *
188 * @return the worflow element identifier
189 */
190 public String getWorkflowElementID()
191 {
192 return workflowElementID;
193 }
194
195
196 /**
197 * Registers the workflow element (this) with the server.
198 *
199 * @throws ConfigException If the workflow element ID for the provided
200 * workflow element conflicts with the workflow
201 * element ID of an existing workflow element.
202 */
203 public void register()
204 throws ConfigException
205 {
206 ensureNotNull(workflowElementID);
207
208 synchronized (registeredWorkflowElementsLock)
209 {
210 // the workflow element must not be already registered
211 if (registeredWorkflowElements.containsKey(workflowElementID))
212 {
213 Message message = ERR_CONFIG_WORKFLOW_ELEMENT_ALREADY_REGISTERED.get(
214 workflowElementID);
215 throw new ConfigException(message);
216 }
217
218 TreeMap<String, WorkflowElement> newWorkflowElements =
219 new TreeMap<String, WorkflowElement>(registeredWorkflowElements);
220 newWorkflowElements.put(workflowElementID, this);
221 registeredWorkflowElements = newWorkflowElements;
222 }
223 }
224
225
226 /**
227 * Deregisters the workflow element (this) with the server.
228 */
229 public void deregister()
230 {
231 ensureNotNull(workflowElementID);
232
233 synchronized (registeredWorkflowElementsLock)
234 {
235 TreeMap<String, WorkflowElement> newWorkflowElements =
236 new TreeMap<String, WorkflowElement>(registeredWorkflowElements);
237 newWorkflowElements.remove(workflowElementID);
238 registeredWorkflowElements = newWorkflowElements;
239 }
240 }
241
242
243 /**
244 * Gets a workflow element that was registered with the server.
245 *
246 * @param workflowElementID the ID of the workflow element to get
247 * @return the requested workflow element
248 */
249 public static WorkflowElement getWorkflowElement(
250 String workflowElementID)
251 {
252 return registeredWorkflowElements.get(workflowElementID);
253 }
254
255
256 /**
257 * Resets all the registered workflows.
258 */
259 public static void resetConfig()
260 {
261 synchronized (registeredWorkflowElementsLock)
262 {
263 registeredWorkflowElements = new TreeMap<String, WorkflowElement>();
264 }
265 }
266
267 }
268