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 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 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 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 /** 157 * Creates a new third-party 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 Java class providing 163 * 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 ThirdPartyTask(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 third-party 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 Java class 184 * providing the logic for the task. It must 185 * 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 ThirdPartyTask(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, THIRD_PARTY_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 third-party task from the provided entry. 235 * 236 * @param entry The entry to use to create this third-party task. 237 * 238 * @throws TaskException If the provided entry cannot be parsed as a 239 * third-party task entry. 240 */ 241 public ThirdPartyTask(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_THIRD_PARTY_TASK_CLASS); 249 if (taskClassName == null) 250 { 251 throw new TaskException(ERR_THIRD_PARTY_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_THIRD_PARTY_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 third-party task from the provided set of task properties. 273 * 274 * @param properties The set of task properties and their corresponding 275 * values to use for the task. It must not be 276 * {@code null}. 277 * 278 * @throws TaskException If the provided set of properties cannot be used to 279 * create a valid third-party task. 280 */ 281 public ThirdPartyTask(final Map<TaskProperty,List<Object>> properties) 282 throws TaskException 283 { 284 super(THIRD_PARTY_TASK_CLASS, properties); 285 286 String className = null; 287 String[] args = null; 288 for (final Map.Entry<TaskProperty,List<Object>> entry : 289 properties.entrySet()) 290 { 291 final TaskProperty p = entry.getKey(); 292 final String attrName = p.getAttributeName(); 293 final List<Object> values = entry.getValue(); 294 295 if (attrName.equalsIgnoreCase(ATTR_THIRD_PARTY_TASK_CLASS)) 296 { 297 className = parseString(p, values, null); 298 } 299 else if (attrName.equalsIgnoreCase(ATTR_THIRD_PARTY_TASK_ARGUMENT)) 300 { 301 args = parseStrings(p, values, null); 302 } 303 } 304 305 if (className == null) 306 { 307 throw new TaskException(ERR_THIRD_PARTY_TASK_NO_CLASS.get( 308 getTaskEntryDN())); 309 } 310 311 taskClassName = className; 312 313 if (args == null) 314 { 315 taskArguments = Collections.emptyList(); 316 } 317 else 318 { 319 taskArguments = Collections.unmodifiableList(Arrays.asList(args)); 320 } 321 } 322 323 324 325 /** 326 * {@inheritDoc} 327 */ 328 @Override() 329 public String getTaskName() 330 { 331 return INFO_TASK_NAME_THIRD_PARTY_TASK.get(); 332 } 333 334 335 336 /** 337 * {@inheritDoc} 338 */ 339 @Override() 340 public String getTaskDescription() 341 { 342 return INFO_TASK_DESCRIPTION_THIRD_PARTY_TASK.get(); 343 } 344 345 346 347 /** 348 * Retrieves the fully-qualified name of the Java class providing the logic 349 * for the third-party task. 350 * 351 * @return The fully-qualified name of the Java class providing the logic 352 * for the third-party task. 353 */ 354 public String getThirdPartyTaskClassName() 355 { 356 return taskClassName; 357 } 358 359 360 361 /** 362 * Retrieves a list of the arguments to provide to the third-party task. 363 * 364 * @return A list of the arguments to provide to the third-party task, or 365 * an empty list if there are no arguments. 366 */ 367 public List<String> getThirdPartyTaskArguments() 368 { 369 return taskArguments; 370 } 371 372 373 374 /** 375 * {@inheritDoc} 376 */ 377 @Override() 378 protected List<String> getAdditionalObjectClasses() 379 { 380 return Arrays.asList(OC_THIRD_PARTY_TASK); 381 } 382 383 384 385 /** 386 * {@inheritDoc} 387 */ 388 @Override() 389 protected List<Attribute> getAdditionalAttributes() 390 { 391 final ArrayList<Attribute> attrList = new ArrayList<Attribute>(2); 392 attrList.add(new Attribute(ATTR_THIRD_PARTY_TASK_CLASS, taskClassName)); 393 394 if (! taskArguments.isEmpty()) 395 { 396 attrList.add(new Attribute(ATTR_THIRD_PARTY_TASK_ARGUMENT, 397 taskArguments)); 398 } 399 400 return attrList; 401 } 402 403 404 405 /** 406 * {@inheritDoc} 407 */ 408 @Override() 409 public List<TaskProperty> getTaskSpecificProperties() 410 { 411 return Collections.unmodifiableList(Arrays.asList( 412 PROPERTY_TASK_CLASS, 413 PROPERTY_TASK_ARG)); 414 } 415 416 417 418 /** 419 * {@inheritDoc} 420 */ 421 @Override() 422 public Map<TaskProperty,List<Object>> getTaskPropertyValues() 423 { 424 final LinkedHashMap<TaskProperty,List<Object>> props = 425 new LinkedHashMap<TaskProperty,List<Object>>(2); 426 427 props.put(PROPERTY_TASK_CLASS, 428 Collections.<Object>unmodifiableList(Arrays.asList(taskClassName))); 429 430 props.put(PROPERTY_TASK_ARG, 431 Collections.<Object>unmodifiableList(taskArguments)); 432 433 props.putAll(super.getTaskPropertyValues()); 434 return Collections.unmodifiableMap(props); 435 } 436}