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; 038import com.unboundid.util.Validator; 039 040import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*; 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 052 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 053 * for proprietary functionality or for external specifications that are not 054 * considered stable or mature enough to be guaranteed to work in an 055 * interoperable way with 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 * Creates a new Groovy-scripted task with the provided information. 157 * 158 * @param taskID The task ID to use for this task. If it is 159 * {@code null} then a UUID will be generated for use 160 * as the task ID. 161 * @param taskClassName The fully-qualified name of the Groovy class 162 * providing the logic for the task. It must not be 163 * {@code null}. 164 * @param taskArguments A list of the arguments for the task, in the form 165 * name=value. It may be {@code null} or empty if 166 * there should not be any arguments. 167 */ 168 public GroovyScriptedTask(final String taskID, final String taskClassName, 169 final List<String> taskArguments) 170 { 171 this(taskID, taskClassName, taskArguments, null, null, null, null, null); 172 } 173 174 175 176 /** 177 * Creates a new Groovy-scripted task with the provided information. 178 * 179 * @param taskID The task ID to use for this task. If it is 180 * {@code null} then a UUID will be generated 181 * for use as the task ID. 182 * @param taskClassName The fully-qualified name of the Groovy 183 * class providing the logic for the task. It 184 * must not be {@code null}. 185 * @param taskArguments A list of the arguments for the task, in 186 * the form name=value. It may be 187 * {@code null} or empty if there should not 188 * be any arguments. 189 * @param scheduledStartTime The time that this task should start 190 * running. 191 * @param dependencyIDs The list of task IDs that will be required 192 * to complete before this task will be 193 * eligible to start. 194 * @param failedDependencyAction Indicates what action should be taken if 195 * any of the dependencies for this task do 196 * not complete successfully. 197 * @param notifyOnCompletion The list of e-mail addresses of individuals 198 * that should be notified when this task 199 * completes. 200 * @param notifyOnError The list of e-mail addresses of individuals 201 * that should be notified if this task does 202 * not complete successfully. 203 */ 204 public GroovyScriptedTask(final String taskID, final String taskClassName, 205 final List<String> taskArguments, 206 final Date scheduledStartTime, 207 final List<String> dependencyIDs, 208 final FailedDependencyAction failedDependencyAction, 209 final List<String> notifyOnCompletion, 210 final List<String> notifyOnError) 211 { 212 this(taskID, taskClassName, taskArguments, scheduledStartTime, 213 dependencyIDs, failedDependencyAction, null, notifyOnCompletion, 214 null, notifyOnError, null, null, null); 215 } 216 217 218 219 /** 220 * Creates a new Groovy-scripted task with the provided information. 221 * 222 * @param taskID The task ID to use for this task. If it is 223 * {@code null} then a UUID will be generated 224 * for use as the task ID. 225 * @param taskClassName The fully-qualified name of the Groovy 226 * class providing the logic for the task. It 227 * must not be {@code null}. 228 * @param taskArguments A list of the arguments for the task, in 229 * the form name=value. It may be 230 * {@code null} or empty if there should not 231 * be any arguments. 232 * @param scheduledStartTime The time that this task should start 233 * running. 234 * @param dependencyIDs The list of task IDs that will be required 235 * to complete before this task will be 236 * eligible to start. 237 * @param failedDependencyAction Indicates what action should be taken if 238 * any of the dependencies for this task do 239 * not complete successfully. 240 * @param notifyOnStart The list of e-mail addresses of individuals 241 * that should be notified when this task 242 * starts running. 243 * @param notifyOnCompletion The list of e-mail addresses of individuals 244 * that should be notified when this task 245 * completes. 246 * @param notifyOnSuccess The list of e-mail addresses of individuals 247 * that should be notified if this task 248 * completes successfully. 249 * @param notifyOnError The list of e-mail addresses of individuals 250 * that should be notified if this task does 251 * not complete successfully. 252 * @param alertOnStart Indicates whether the server should send an 253 * alert notification when this task starts. 254 * @param alertOnSuccess Indicates whether the server should send an 255 * alert notification if this task completes 256 * successfully. 257 * @param alertOnError Indicates whether the server should send an 258 * alert notification if this task fails to 259 * complete successfully. 260 */ 261 public GroovyScriptedTask(final String taskID, final String taskClassName, 262 final List<String> taskArguments, 263 final Date scheduledStartTime, 264 final List<String> dependencyIDs, 265 final FailedDependencyAction failedDependencyAction, 266 final List<String> notifyOnStart, 267 final List<String> notifyOnCompletion, 268 final List<String> notifyOnSuccess, 269 final List<String> notifyOnError, 270 final Boolean alertOnStart, 271 final Boolean alertOnSuccess, 272 final Boolean alertOnError) 273 { 274 super(taskID, GROOVY_SCRIPTED_TASK_CLASS, scheduledStartTime, 275 dependencyIDs, failedDependencyAction, notifyOnStart, 276 notifyOnCompletion, notifyOnSuccess, notifyOnError, alertOnStart, 277 alertOnSuccess, alertOnError); 278 279 Validator.ensureNotNull(taskClassName); 280 281 this.taskClassName = taskClassName; 282 283 if (taskArguments == null) 284 { 285 this.taskArguments = Collections.emptyList(); 286 } 287 else 288 { 289 this.taskArguments = Collections.unmodifiableList(taskArguments); 290 } 291 } 292 293 294 295 /** 296 * Creates a new Groovy-scripted task from the provided entry. 297 * 298 * @param entry The entry to use to create this Groovy-scripted task. 299 * 300 * @throws TaskException If the provided entry cannot be parsed as a 301 * Groovy-scripted task entry. 302 */ 303 public GroovyScriptedTask(final Entry entry) 304 throws TaskException 305 { 306 super(entry); 307 308 309 // Get the task class name. It must be present. 310 taskClassName = entry.getAttributeValue(ATTR_GROOVY_SCRIPTED_TASK_CLASS); 311 if (taskClassName == null) 312 { 313 throw new TaskException(ERR_GROOVY_SCRIPTED_TASK_NO_CLASS.get( 314 getTaskEntryDN())); 315 } 316 317 318 // Get the task arguments. It may be absent. 319 final String[] args = 320 entry.getAttributeValues(ATTR_GROOVY_SCRIPTED_TASK_ARGUMENT); 321 if ((args == null) || (args.length == 0)) 322 { 323 taskArguments = Collections.emptyList(); 324 } 325 else 326 { 327 taskArguments = Collections.unmodifiableList(Arrays.asList(args)); 328 } 329 } 330 331 332 333 /** 334 * Creates a new Groovy-scripted task from the provided set of task 335 * properties. 336 * 337 * @param properties The set of task properties and their corresponding 338 * values to use for the task. It must not be 339 * {@code null}. 340 * 341 * @throws TaskException If the provided set of properties cannot be used to 342 * create a valid Groovy-scripted task. 343 */ 344 public GroovyScriptedTask(final Map<TaskProperty,List<Object>> properties) 345 throws TaskException 346 { 347 super(GROOVY_SCRIPTED_TASK_CLASS, properties); 348 349 String className = null; 350 String[] args = null; 351 for (final Map.Entry<TaskProperty,List<Object>> entry : 352 properties.entrySet()) 353 { 354 final TaskProperty p = entry.getKey(); 355 final String attrName = p.getAttributeName(); 356 final List<Object> values = entry.getValue(); 357 358 if (attrName.equalsIgnoreCase(ATTR_GROOVY_SCRIPTED_TASK_CLASS)) 359 { 360 className = parseString(p, values, null); 361 } 362 else if (attrName.equalsIgnoreCase(ATTR_GROOVY_SCRIPTED_TASK_ARGUMENT)) 363 { 364 args = parseStrings(p, values, null); 365 } 366 } 367 368 if (className == null) 369 { 370 throw new TaskException(ERR_GROOVY_SCRIPTED_TASK_NO_CLASS.get( 371 getTaskEntryDN())); 372 } 373 374 taskClassName = className; 375 376 if (args == null) 377 { 378 taskArguments = Collections.emptyList(); 379 } 380 else 381 { 382 taskArguments = Collections.unmodifiableList(Arrays.asList(args)); 383 } 384 } 385 386 387 388 /** 389 * {@inheritDoc} 390 */ 391 @Override() 392 public String getTaskName() 393 { 394 return INFO_TASK_NAME_GROOVY_SCRIPTED_TASK.get(); 395 } 396 397 398 399 /** 400 * {@inheritDoc} 401 */ 402 @Override() 403 public String getTaskDescription() 404 { 405 return INFO_TASK_DESCRIPTION_GROOVY_SCRIPTED_TASK.get(); 406 } 407 408 409 410 /** 411 * Retrieves the fully-qualified name of the Groovy class providing the logic 412 * for the scripted task. 413 * 414 * @return The fully-qualified name of the Groovy class providing the logic 415 * for the scripted task. 416 */ 417 public String getGroovyScriptedTaskClassName() 418 { 419 return taskClassName; 420 } 421 422 423 424 /** 425 * Retrieves a list of the arguments to provide to the Groovy-scripted task. 426 * 427 * @return A list of the arguments to provide to the Groovy-scripted task, or 428 * an empty list if there are no arguments. 429 */ 430 public List<String> getGroovyScriptedTaskArguments() 431 { 432 return taskArguments; 433 } 434 435 436 437 /** 438 * {@inheritDoc} 439 */ 440 @Override() 441 protected List<String> getAdditionalObjectClasses() 442 { 443 return Collections.singletonList(OC_GROOVY_SCRIPTED_TASK); 444 } 445 446 447 448 /** 449 * {@inheritDoc} 450 */ 451 @Override() 452 protected List<Attribute> getAdditionalAttributes() 453 { 454 final ArrayList<Attribute> attrList = new ArrayList<>(2); 455 attrList.add(new Attribute(ATTR_GROOVY_SCRIPTED_TASK_CLASS, taskClassName)); 456 457 if (! taskArguments.isEmpty()) 458 { 459 attrList.add(new Attribute(ATTR_GROOVY_SCRIPTED_TASK_ARGUMENT, 460 taskArguments)); 461 } 462 463 return attrList; 464 } 465 466 467 468 /** 469 * {@inheritDoc} 470 */ 471 @Override() 472 public List<TaskProperty> getTaskSpecificProperties() 473 { 474 return Collections.unmodifiableList(Arrays.asList( 475 PROPERTY_TASK_CLASS, 476 PROPERTY_TASK_ARG)); 477 } 478 479 480 481 /** 482 * {@inheritDoc} 483 */ 484 @Override() 485 public Map<TaskProperty,List<Object>> getTaskPropertyValues() 486 { 487 final LinkedHashMap<TaskProperty,List<Object>> props = 488 new LinkedHashMap<>(2); 489 490 props.put(PROPERTY_TASK_CLASS, 491 Collections.<Object>singletonList(taskClassName)); 492 493 props.put(PROPERTY_TASK_ARG, 494 Collections.<Object>unmodifiableList(taskArguments)); 495 496 props.putAll(super.getTaskPropertyValues()); 497 return Collections.unmodifiableMap(props); 498 } 499}