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 046 * third-party code created 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 Java class providing the logic for the 061 * third-party 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 ThirdPartyTask 068 extends Task 069{ 070 /** 071 * The fully-qualified name of the Java class that is used for the core 072 * third-party task. 073 */ 074 static final String THIRD_PARTY_TASK_CLASS = 075 "com.unboundid.directory.sdk.extensions.ThirdPartyTask"; 076 077 078 079 /** 080 * The name of the attribute used to specify the fully-qualified name of the 081 * Java class providing the task logic. 082 */ 083 private static final String ATTR_THIRD_PARTY_TASK_CLASS = 084 "ds-third-party-task-java-class"; 085 086 087 088 /** 089 * The name of the attribute used to provide arguments for the task. 090 */ 091 private static final String ATTR_THIRD_PARTY_TASK_ARGUMENT = 092 "ds-third-party-task-argument"; 093 094 095 096 /** 097 * The name of the object class used in third-party task entries. 098 */ 099 private static final String OC_THIRD_PARTY_TASK = 100 "ds-third-party-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_THIRD_PARTY_TASK_CLASS, 109 INFO_DISPLAY_NAME_THIRD_PARTY_TASK_CLASS.get(), 110 INFO_DESCRIPTION_THIRD_PARTY_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_THIRD_PARTY_TASK_ARGUMENT, 120 INFO_DISPLAY_NAME_THIRD_PARTY_TASK_ARG.get(), 121 INFO_DESCRIPTION_THIRD_PARTY_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 = 8448474409066265724L; 130 131 132 133 // A list of the arguments for the task. 134 private final List<String> taskArguments; 135 136 // The name of the java class providing the logic for the third-party task. 137 private final String taskClassName; 138 139 140 141 /** 142 * Creates a new uninitialized third-party 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 ThirdPartyTask() 148 { 149 taskArguments = null; 150 taskClassName = null; 151 } 152 153 154 155 /** 156 * Creates a new third-party 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 Java class providing 162 * 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 ThirdPartyTask(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 third-party 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 Java class 183 * providing the logic for the task. It must 184 * 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 ThirdPartyTask(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 third-party 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 Java class 226 * providing the logic for the task. It must 227 * 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 ThirdPartyTask(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, THIRD_PARTY_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 third-party task from the provided entry. 297 * 298 * @param entry The entry to use to create this third-party task. 299 * 300 * @throws TaskException If the provided entry cannot be parsed as a 301 * third-party task entry. 302 */ 303 public ThirdPartyTask(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_THIRD_PARTY_TASK_CLASS); 311 if (taskClassName == null) 312 { 313 throw new TaskException(ERR_THIRD_PARTY_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_THIRD_PARTY_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 third-party task from the provided set of task properties. 335 * 336 * @param properties The set of task properties and their corresponding 337 * values to use for the task. It must not be 338 * {@code null}. 339 * 340 * @throws TaskException If the provided set of properties cannot be used to 341 * create a valid third-party task. 342 */ 343 public ThirdPartyTask(final Map<TaskProperty,List<Object>> properties) 344 throws TaskException 345 { 346 super(THIRD_PARTY_TASK_CLASS, properties); 347 348 String className = null; 349 String[] args = null; 350 for (final Map.Entry<TaskProperty,List<Object>> entry : 351 properties.entrySet()) 352 { 353 final TaskProperty p = entry.getKey(); 354 final String attrName = p.getAttributeName(); 355 final List<Object> values = entry.getValue(); 356 357 if (attrName.equalsIgnoreCase(ATTR_THIRD_PARTY_TASK_CLASS)) 358 { 359 className = parseString(p, values, null); 360 } 361 else if (attrName.equalsIgnoreCase(ATTR_THIRD_PARTY_TASK_ARGUMENT)) 362 { 363 args = parseStrings(p, values, null); 364 } 365 } 366 367 if (className == null) 368 { 369 throw new TaskException(ERR_THIRD_PARTY_TASK_NO_CLASS.get( 370 getTaskEntryDN())); 371 } 372 373 taskClassName = className; 374 375 if (args == null) 376 { 377 taskArguments = Collections.emptyList(); 378 } 379 else 380 { 381 taskArguments = Collections.unmodifiableList(Arrays.asList(args)); 382 } 383 } 384 385 386 387 /** 388 * {@inheritDoc} 389 */ 390 @Override() 391 public String getTaskName() 392 { 393 return INFO_TASK_NAME_THIRD_PARTY_TASK.get(); 394 } 395 396 397 398 /** 399 * {@inheritDoc} 400 */ 401 @Override() 402 public String getTaskDescription() 403 { 404 return INFO_TASK_DESCRIPTION_THIRD_PARTY_TASK.get(); 405 } 406 407 408 409 /** 410 * Retrieves the fully-qualified name of the Java class providing the logic 411 * for the third-party task. 412 * 413 * @return The fully-qualified name of the Java class providing the logic 414 * for the third-party task. 415 */ 416 public String getThirdPartyTaskClassName() 417 { 418 return taskClassName; 419 } 420 421 422 423 /** 424 * Retrieves a list of the arguments to provide to the third-party task. 425 * 426 * @return A list of the arguments to provide to the third-party task, or 427 * an empty list if there are no arguments. 428 */ 429 public List<String> getThirdPartyTaskArguments() 430 { 431 return taskArguments; 432 } 433 434 435 436 /** 437 * {@inheritDoc} 438 */ 439 @Override() 440 protected List<String> getAdditionalObjectClasses() 441 { 442 return Collections.singletonList(OC_THIRD_PARTY_TASK); 443 } 444 445 446 447 /** 448 * {@inheritDoc} 449 */ 450 @Override() 451 protected List<Attribute> getAdditionalAttributes() 452 { 453 final ArrayList<Attribute> attrList = new ArrayList<>(2); 454 attrList.add(new Attribute(ATTR_THIRD_PARTY_TASK_CLASS, taskClassName)); 455 456 if (! taskArguments.isEmpty()) 457 { 458 attrList.add(new Attribute(ATTR_THIRD_PARTY_TASK_ARGUMENT, 459 taskArguments)); 460 } 461 462 return attrList; 463 } 464 465 466 467 /** 468 * {@inheritDoc} 469 */ 470 @Override() 471 public List<TaskProperty> getTaskSpecificProperties() 472 { 473 return Collections.unmodifiableList(Arrays.asList( 474 PROPERTY_TASK_CLASS, 475 PROPERTY_TASK_ARG)); 476 } 477 478 479 480 /** 481 * {@inheritDoc} 482 */ 483 @Override() 484 public Map<TaskProperty,List<Object>> getTaskPropertyValues() 485 { 486 final LinkedHashMap<TaskProperty,List<Object>> props = 487 new LinkedHashMap<>(2); 488 489 props.put(PROPERTY_TASK_CLASS, 490 Collections.<Object>singletonList(taskClassName)); 491 492 props.put(PROPERTY_TASK_ARG, 493 Collections.<Object>unmodifiableList(taskArguments)); 494 495 props.putAll(super.getTaskPropertyValues()); 496 return Collections.unmodifiableMap(props); 497 } 498}