001/* 002 * Copyright 2008-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2018 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.sdk.unboundidds.tasks; 022 023 024 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.Collections; 028import java.util.Date; 029import java.util.LinkedHashMap; 030import java.util.List; 031import java.util.Map; 032 033import com.unboundid.ldap.sdk.Attribute; 034import com.unboundid.ldap.sdk.Entry; 035import com.unboundid.util.NotMutable; 036import com.unboundid.util.ThreadSafety; 037import com.unboundid.util.ThreadSafetyLevel; 038 039import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*; 040import static com.unboundid.util.Validator.*; 041 042 043 044/** 045 * This class defines a Directory Server task that can be used to invoke a task 046 * written as a Groovy script using the UnboundID Server SDK. 047 * <BR> 048 * <BLOCKQUOTE> 049 * <B>NOTE:</B> This class, and other classes within the 050 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 051 * supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661 052 * server products. These classes provide support for proprietary 053 * functionality or for external specifications that are not considered stable 054 * or mature enough to be guaranteed to work in an interoperable way with 055 * other types of LDAP servers. 056 * </BLOCKQUOTE> 057 * <BR> 058 * The properties that are available for use with this type of task include: 059 * <UL> 060 * <LI>The fully-qualified name of the Groovy class providing the logic for 061 * the scripted task. This must be provided.</LI> 062 * <LI>A list of the arguments to use for the task.</LI> 063 * </UL> 064 */ 065@NotMutable() 066@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 067public final class GroovyScriptedTask 068 extends Task 069{ 070 /** 071 * The fully-qualified name of the Java class that is used for the core 072 * Groovy-scripted task. 073 */ 074 static final String GROOVY_SCRIPTED_TASK_CLASS = 075 "com.unboundid.directory.sdk.extensions.GroovyScriptedTask"; 076 077 078 079 /** 080 * The name of the attribute used to specify the fully-qualified name of the 081 * Groovy class providing the logic for the scripted task. 082 */ 083 private static final String ATTR_GROOVY_SCRIPTED_TASK_CLASS = 084 "ds-scripted-task-class"; 085 086 087 088 /** 089 * The name of the attribute used to provide arguments to the script. 090 */ 091 private static final String ATTR_GROOVY_SCRIPTED_TASK_ARGUMENT = 092 "ds-scripted-task-argument"; 093 094 095 096 /** 097 * The name of the object class used in Groovy-scripted task entries. 098 */ 099 private static final String OC_GROOVY_SCRIPTED_TASK = 100 "ds-groovy-scripted-task"; 101 102 103 104 /** 105 * The task property that will be used for the task class. 106 */ 107 static final TaskProperty PROPERTY_TASK_CLASS = 108 new TaskProperty(ATTR_GROOVY_SCRIPTED_TASK_CLASS, 109 INFO_DISPLAY_NAME_GROOVY_SCRIPTED_TASK_CLASS.get(), 110 INFO_DESCRIPTION_GROOVY_SCRIPTED_TASK_CLASS.get(), String.class, true, 111 false, false); 112 113 114 115 /** 116 * The task property that will be used for the task arguments. 117 */ 118 static final TaskProperty PROPERTY_TASK_ARG = 119 new TaskProperty(ATTR_GROOVY_SCRIPTED_TASK_ARGUMENT, 120 INFO_DISPLAY_NAME_GROOVY_SCRIPTED_TASK_ARG.get(), 121 INFO_DESCRIPTION_GROOVY_SCRIPTED_TASK_ARG.get(), String.class, false, 122 true, false); 123 124 125 126 /** 127 * The serial version UID for this serializable class. 128 */ 129 private static final long serialVersionUID = -1354970323227263273L; 130 131 132 133 // A list of the arguments for the task. 134 private final List<String> taskArguments; 135 136 // The name of the Groovy class providing the logic for the scripted task. 137 private final String taskClassName; 138 139 140 141 /** 142 * Creates a new uninitialized Groovy-scripted task instance which should only 143 * be used for obtaining general information about this task, including the 144 * task name, description, and supported properties. Attempts to use a task 145 * created with this constructor for any other reason will likely fail. 146 */ 147 public GroovyScriptedTask() 148 { 149 taskArguments = null; 150 taskClassName = null; 151 } 152 153 154 155 156 /** 157 * Creates a new Groovy-scripted task with the provided information. 158 * 159 * @param taskID The task ID to use for this task. If it is 160 * {@code null} then a UUID will be generated for use 161 * as the task ID. 162 * @param taskClassName The fully-qualified name of the Groovy class 163 * providing the logic for the task. It must not be 164 * {@code null}. 165 * @param taskArguments A list of the arguments for the task, in the form 166 * name=value. It may be {@code null} or empty if 167 * there should not be any arguments. 168 */ 169 public GroovyScriptedTask(final String taskID, final String taskClassName, 170 final List<String> taskArguments) 171 { 172 this(taskID, taskClassName, taskArguments, null, null, null, null, null); 173 } 174 175 176 177 /** 178 * Creates a new Groovy-scripted task with the provided information. 179 * 180 * @param taskID The task ID to use for this task. If it is 181 * {@code null} then a UUID will be generated 182 * for use as the task ID. 183 * @param taskClassName The fully-qualified name of the Groovy 184 * class providing the logic for the task. It 185 * must not be {@code null}. 186 * @param taskArguments A list of the arguments for the task, in 187 * the form name=value. It may be 188 * {@code null} or empty if there should not 189 * be any arguments. 190 * @param scheduledStartTime The time that this task should start 191 * running. 192 * @param dependencyIDs The list of task IDs that will be required 193 * to complete before this task will be 194 * eligible to start. 195 * @param failedDependencyAction Indicates what action should be taken if 196 * any of the dependencies for this task do 197 * not complete successfully. 198 * @param notifyOnCompletion The list of e-mail addresses of individuals 199 * that should be notified when this task 200 * completes. 201 * @param notifyOnError The list of e-mail addresses of individuals 202 * that should be notified if this task does 203 * not complete successfully. 204 */ 205 public GroovyScriptedTask(final String taskID, final String taskClassName, 206 final List<String> taskArguments, 207 final Date scheduledStartTime, 208 final List<String> dependencyIDs, 209 final FailedDependencyAction failedDependencyAction, 210 final List<String> notifyOnCompletion, 211 final List<String> notifyOnError) 212 { 213 super(taskID, GROOVY_SCRIPTED_TASK_CLASS, scheduledStartTime, 214 dependencyIDs, failedDependencyAction, notifyOnCompletion, 215 notifyOnError); 216 217 ensureNotNull(taskClassName); 218 219 this.taskClassName = taskClassName; 220 221 if (taskArguments == null) 222 { 223 this.taskArguments = Collections.emptyList(); 224 } 225 else 226 { 227 this.taskArguments = Collections.unmodifiableList(taskArguments); 228 } 229 } 230 231 232 233 /** 234 * Creates a new Groovy-scripted task from the provided entry. 235 * 236 * @param entry The entry to use to create this Groovy-scripted task. 237 * 238 * @throws TaskException If the provided entry cannot be parsed as a 239 * Groovy-scripted task entry. 240 */ 241 public GroovyScriptedTask(final Entry entry) 242 throws TaskException 243 { 244 super(entry); 245 246 247 // Get the task class name. It must be present. 248 taskClassName = entry.getAttributeValue(ATTR_GROOVY_SCRIPTED_TASK_CLASS); 249 if (taskClassName == null) 250 { 251 throw new TaskException(ERR_GROOVY_SCRIPTED_TASK_NO_CLASS.get( 252 getTaskEntryDN())); 253 } 254 255 256 // Get the task arguments. It may be absent. 257 final String[] args = 258 entry.getAttributeValues(ATTR_GROOVY_SCRIPTED_TASK_ARGUMENT); 259 if ((args == null) || (args.length == 0)) 260 { 261 taskArguments = Collections.emptyList(); 262 } 263 else 264 { 265 taskArguments = Collections.unmodifiableList(Arrays.asList(args)); 266 } 267 } 268 269 270 271 /** 272 * Creates a new Groovy-scripted task from the provided set of task 273 * properties. 274 * 275 * @param properties The set of task properties and their corresponding 276 * values to use for the task. It must not be 277 * {@code null}. 278 * 279 * @throws TaskException If the provided set of properties cannot be used to 280 * create a valid Groovy-scripted task. 281 */ 282 public GroovyScriptedTask(final Map<TaskProperty,List<Object>> properties) 283 throws TaskException 284 { 285 super(GROOVY_SCRIPTED_TASK_CLASS, properties); 286 287 String className = null; 288 String[] args = null; 289 for (final Map.Entry<TaskProperty,List<Object>> entry : 290 properties.entrySet()) 291 { 292 final TaskProperty p = entry.getKey(); 293 final String attrName = p.getAttributeName(); 294 final List<Object> values = entry.getValue(); 295 296 if (attrName.equalsIgnoreCase(ATTR_GROOVY_SCRIPTED_TASK_CLASS)) 297 { 298 className = parseString(p, values, null); 299 } 300 else if (attrName.equalsIgnoreCase(ATTR_GROOVY_SCRIPTED_TASK_ARGUMENT)) 301 { 302 args = parseStrings(p, values, null); 303 } 304 } 305 306 if (className == null) 307 { 308 throw new TaskException(ERR_GROOVY_SCRIPTED_TASK_NO_CLASS.get( 309 getTaskEntryDN())); 310 } 311 312 taskClassName = className; 313 314 if (args == null) 315 { 316 taskArguments = Collections.emptyList(); 317 } 318 else 319 { 320 taskArguments = Collections.unmodifiableList(Arrays.asList(args)); 321 } 322 } 323 324 325 326 /** 327 * {@inheritDoc} 328 */ 329 @Override() 330 public String getTaskName() 331 { 332 return INFO_TASK_NAME_GROOVY_SCRIPTED_TASK.get(); 333 } 334 335 336 337 /** 338 * {@inheritDoc} 339 */ 340 @Override() 341 public String getTaskDescription() 342 { 343 return INFO_TASK_DESCRIPTION_GROOVY_SCRIPTED_TASK.get(); 344 } 345 346 347 348 /** 349 * Retrieves the fully-qualified name of the Groovy class providing the logic 350 * for the scripted task. 351 * 352 * @return The fully-qualified name of the Groovy class providing the logic 353 * for the scripted task. 354 */ 355 public String getGroovyScriptedTaskClassName() 356 { 357 return taskClassName; 358 } 359 360 361 362 /** 363 * Retrieves a list of the arguments to provide to the Groovy-scripted task. 364 * 365 * @return A list of the arguments to provide to the Groovy-scripted task, or 366 * an empty list if there are no arguments. 367 */ 368 public List<String> getGroovyScriptedTaskArguments() 369 { 370 return taskArguments; 371 } 372 373 374 375 /** 376 * {@inheritDoc} 377 */ 378 @Override() 379 protected List<String> getAdditionalObjectClasses() 380 { 381 return Arrays.asList(OC_GROOVY_SCRIPTED_TASK); 382 } 383 384 385 386 /** 387 * {@inheritDoc} 388 */ 389 @Override() 390 protected List<Attribute> getAdditionalAttributes() 391 { 392 final ArrayList<Attribute> attrList = new ArrayList<Attribute>(2); 393 attrList.add(new Attribute(ATTR_GROOVY_SCRIPTED_TASK_CLASS, taskClassName)); 394 395 if (! taskArguments.isEmpty()) 396 { 397 attrList.add(new Attribute(ATTR_GROOVY_SCRIPTED_TASK_ARGUMENT, 398 taskArguments)); 399 } 400 401 return attrList; 402 } 403 404 405 406 /** 407 * {@inheritDoc} 408 */ 409 @Override() 410 public List<TaskProperty> getTaskSpecificProperties() 411 { 412 return Collections.unmodifiableList(Arrays.asList( 413 PROPERTY_TASK_CLASS, 414 PROPERTY_TASK_ARG)); 415 } 416 417 418 419 /** 420 * {@inheritDoc} 421 */ 422 @Override() 423 public Map<TaskProperty,List<Object>> getTaskPropertyValues() 424 { 425 final LinkedHashMap<TaskProperty,List<Object>> props = 426 new LinkedHashMap<TaskProperty,List<Object>>(2); 427 428 props.put(PROPERTY_TASK_CLASS, 429 Collections.<Object>unmodifiableList(Arrays.asList(taskClassName))); 430 431 props.put(PROPERTY_TASK_ARG, 432 Collections.<Object>unmodifiableList(taskArguments)); 433 434 props.putAll(super.getTaskPropertyValues()); 435 return Collections.unmodifiableMap(props); 436 } 437}