001/* 002 * Copyright 2008-2019 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2019 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.Debug; 036import com.unboundid.util.NotMutable; 037import com.unboundid.util.StaticUtils; 038import com.unboundid.util.ThreadSafety; 039import com.unboundid.util.ThreadSafetyLevel; 040 041import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*; 042 043 044 045/** 046 * This class defines a Directory Server task that can be used to request that 047 * the server terminate a client connection. 048 * <BR> 049 * <BLOCKQUOTE> 050 * <B>NOTE:</B> This class, and other classes within the 051 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 052 * supported for use against Ping Identity, UnboundID, and 053 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 054 * for proprietary functionality or for external specifications that are not 055 * considered stable or mature enough to be guaranteed to work in an 056 * interoperable way with other types of LDAP servers. 057 * </BLOCKQUOTE> 058 * <BR> 059 * The properties that are available for use with this type of task include: 060 * <UL> 061 * <LI>The connection ID for the client connection to be terminated. This 062 * is required.</LI> 063 * <LI>A flag that indicates whether the client connection should be notified 064 * (e.g., using a notice of disconnection unsolicited notification) before 065 * the connection is actually terminated.</LI> 066 * <LI>An optional message that may provide a reason for the disconnect. If 067 * this is provided, it will appear in the server log, and it may be 068 * provided to the client if the client is to be notified before the 069 * connection is closed.</LI> 070 * </UL> 071 072 */ 073@NotMutable() 074@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 075public final class DisconnectClientTask 076 extends Task 077{ 078 /** 079 * The fully-qualified name of the Java class that is used for the disconnect 080 * client task. 081 */ 082 static final String DISCONNECT_CLIENT_TASK_CLASS = 083 "com.unboundid.directory.server.tasks.DisconnectClientTask"; 084 085 086 087 /** 088 * The name of the attribute used to specify the connection ID of the client 089 * connection to terminate. 090 */ 091 private static final String ATTR_CONNECTION_ID = 092 "ds-task-disconnect-connection-id"; 093 094 095 096 /** 097 * The name of the attribute used to specify the disconnect message to provide 098 * to the server. 099 */ 100 private static final String ATTR_DISCONNECT_MESSAGE = 101 "ds-task-disconnect-message"; 102 103 104 105 /** 106 * The name of the attribute used to indicate whether to send a notice of 107 * disconnection message to the client before closing the connection. 108 */ 109 private static final String ATTR_NOTIFY_CLIENT = 110 "ds-task-disconnect-notify-client"; 111 112 113 114 /** 115 * The name of the object class used in disconnect client task entries. 116 */ 117 private static final String OC_DISCONNECT_CLIENT_TASK = "ds-task-disconnect"; 118 119 120 121 /** 122 * The task property for the connection ID. 123 */ 124 private static final TaskProperty PROPERTY_CONNECTION_ID = 125 new TaskProperty(ATTR_CONNECTION_ID, 126 INFO_DISPLAY_NAME_DISCONNECT_CONN_ID.get(), 127 INFO_DESCRIPTION_DISCONNECT_CONN_ID.get(), Long.class, 128 true, false, false); 129 130 131 132 /** 133 * The task property for the disconnect message. 134 */ 135 private static final TaskProperty PROPERTY_DISCONNECT_MESSAGE = 136 new TaskProperty(ATTR_DISCONNECT_MESSAGE, 137 INFO_DISPLAY_NAME_DISCONNECT_MESSAGE.get(), 138 INFO_DESCRIPTION_DISCONNECT_MESSAGE.get(), String.class, 139 false, false, false); 140 141 142 143 /** 144 * The task property for the notify client flag. 145 */ 146 private static final TaskProperty PROPERTY_NOTIFY_CLIENT = 147 new TaskProperty(ATTR_NOTIFY_CLIENT, 148 INFO_DISPLAY_NAME_DISCONNECT_NOTIFY.get(), 149 INFO_DESCRIPTION_DISCONNECT_NOTIFY.get(), Boolean.class, 150 false, false, false); 151 152 153 154 /** 155 * The serial version UID for this serializable class. 156 */ 157 private static final long serialVersionUID = 6870137048384152893L; 158 159 160 161 // Indicates whether to send the client a notice of disconnection. 162 private final boolean notifyClient; 163 164 // The connection ID of the connection to disconnect. 165 private final long connectionID; 166 167 // A disconnect message to provide to the server. 168 private final String disconnectMessage; 169 170 171 172 /** 173 * Creates a new uninitialized disconnect client task instance which should 174 * only be used for obtaining general information about this task, including 175 * the task name, description, and supported properties. Attempts to use a 176 * task created with this constructor for any other reason will likely fail. 177 */ 178 public DisconnectClientTask() 179 { 180 notifyClient = false; 181 connectionID = -1; 182 disconnectMessage = null; 183 } 184 185 186 187 /** 188 * Creates a new disconnect client task with the provided information. 189 * 190 * @param taskID The task ID to use for this task. If it is 191 * {@code null} then a UUID will be generated for 192 * use as the task ID. 193 * @param connectionID The connection ID of the client connection to 194 * terminate. 195 * @param disconnectMessage A message to provide to the server to indicate 196 * the reason for the disconnect. It will be 197 * included in the server log, and will be provided 198 * to the client if a notice of disconnection is to 199 * be sent. It may be {@code null} if no message 200 * is to be provided. 201 * @param notifyClient Indicates whether to send a notice of 202 * disconnection message to the client before 203 * terminating the connection. 204 */ 205 public DisconnectClientTask(final String taskID, final long connectionID, 206 final String disconnectMessage, 207 final boolean notifyClient) 208 { 209 this(taskID, connectionID, disconnectMessage, notifyClient, null, null, 210 null, null, null); 211 } 212 213 214 215 /** 216 * Creates a new add disconnect client task with the provided information. 217 * 218 * @param taskID The task ID to use for this task. If it is 219 * {@code null} then a UUID will be generated 220 * for use as the task ID. 221 * @param connectionID The connection ID of the client connection 222 * to terminate. 223 * @param disconnectMessage A message to provide to the server to 224 * indicate the reason for the disconnect. It 225 * will be included in the server log, and 226 * will be provided to the client if a notice 227 * of disconnection is to be sent. It may be 228 * {@code null} if no message is to be 229 * provided. 230 * @param notifyClient Indicates whether to send a notice of 231 * disconnection message to the client before 232 * terminating the connection. 233 * @param scheduledStartTime The time that this task should start 234 * running. 235 * @param dependencyIDs The list of task IDs that will be required 236 * to complete before this task will be 237 * eligible to start. 238 * @param failedDependencyAction Indicates what action should be taken if 239 * any of the dependencies for this task do 240 * not complete successfully. 241 * @param notifyOnCompletion The list of e-mail addresses of individuals 242 * that should be notified when this task 243 * completes. 244 * @param notifyOnError The list of e-mail addresses of individuals 245 * that should be notified if this task does 246 * not complete successfully. 247 */ 248 public DisconnectClientTask(final String taskID, final long connectionID, 249 final String disconnectMessage, final boolean notifyClient, 250 final Date scheduledStartTime, final List<String> dependencyIDs, 251 final FailedDependencyAction failedDependencyAction, 252 final List<String> notifyOnCompletion, 253 final List<String> notifyOnError) 254 { 255 this(taskID, connectionID, disconnectMessage, notifyClient, 256 scheduledStartTime, dependencyIDs, failedDependencyAction, null, 257 notifyOnCompletion, null, notifyOnError, null, null, null); 258 } 259 260 261 262 /** 263 * Creates a new add disconnect client task with the provided information. 264 * 265 * @param taskID The task ID to use for this task. If it is 266 * {@code null} then a UUID will be generated 267 * for use as the task ID. 268 * @param connectionID The connection ID of the client connection 269 * to terminate. 270 * @param disconnectMessage A message to provide to the server to 271 * indicate the reason for the disconnect. It 272 * will be included in the server log, and 273 * will be provided to the client if a notice 274 * of disconnection is to be sent. It may be 275 * {@code null} if no message is to be 276 * provided. 277 * @param notifyClient Indicates whether to send a notice of 278 * disconnection message to the client before 279 * terminating the connection. 280 * @param scheduledStartTime The time that this task should start 281 * running. 282 * @param dependencyIDs The list of task IDs that will be required 283 * to complete before this task will be 284 * eligible to start. 285 * @param failedDependencyAction Indicates what action should be taken if 286 * any of the dependencies for this task do 287 * not complete successfully. 288 * @param notifyOnStart The list of e-mail addresses of individuals 289 * that should be notified when this task 290 * starts running. 291 * @param notifyOnCompletion The list of e-mail addresses of individuals 292 * that should be notified when this task 293 * completes. 294 * @param notifyOnSuccess The list of e-mail addresses of individuals 295 * that should be notified if this task 296 * completes successfully. 297 * @param notifyOnError The list of e-mail addresses of individuals 298 * that should be notified if this task does 299 * not complete successfully. 300 * @param alertOnStart Indicates whether the server should send an 301 * alert notification when this task starts. 302 * @param alertOnSuccess Indicates whether the server should send an 303 * alert notification if this task completes 304 * successfully. 305 * @param alertOnError Indicates whether the server should send an 306 * alert notification if this task fails to 307 * complete successfully. 308 */ 309 public DisconnectClientTask(final String taskID, final long connectionID, 310 final String disconnectMessage, final boolean notifyClient, 311 final Date scheduledStartTime, final List<String> dependencyIDs, 312 final FailedDependencyAction failedDependencyAction, 313 final List<String> notifyOnStart, 314 final List<String> notifyOnCompletion, 315 final List<String> notifyOnSuccess, 316 final List<String> notifyOnError, final Boolean alertOnStart, 317 final Boolean alertOnSuccess, final Boolean alertOnError) 318 { 319 super(taskID, DISCONNECT_CLIENT_TASK_CLASS, scheduledStartTime, 320 dependencyIDs, failedDependencyAction, notifyOnStart, 321 notifyOnCompletion, notifyOnSuccess, notifyOnError, alertOnStart, 322 alertOnSuccess, alertOnError); 323 324 this.connectionID = connectionID; 325 this.disconnectMessage = disconnectMessage; 326 this.notifyClient = notifyClient; 327 } 328 329 330 331 /** 332 * Creates a new disconnect client task from the provided entry. 333 * 334 * @param entry The entry to use to create this disconnect client task. 335 * 336 * @throws TaskException If the provided entry cannot be parsed as a 337 * disconnect client task entry. 338 */ 339 public DisconnectClientTask(final Entry entry) 340 throws TaskException 341 { 342 super(entry); 343 344 345 // Get the connection ID. It must be present. 346 final String idStr = entry.getAttributeValue(ATTR_CONNECTION_ID); 347 if (idStr == null) 348 { 349 throw new TaskException(ERR_DISCONNECT_TASK_NO_CONN_ID.get( 350 getTaskEntryDN())); 351 } 352 else 353 { 354 try 355 { 356 connectionID = Long.parseLong(idStr); 357 } 358 catch (final Exception e) 359 { 360 Debug.debugException(e); 361 throw new TaskException(ERR_DISCONNECT_TASK_CONN_ID_NOT_LONG.get( 362 getTaskEntryDN(), idStr), 363 e); 364 } 365 } 366 367 368 // Get the disconnect message. It may be absent. 369 disconnectMessage = entry.getAttributeValue(ATTR_DISCONNECT_MESSAGE); 370 371 372 // Determine whether to notify the client. It may be absent. 373 notifyClient = parseBooleanValue(entry, ATTR_NOTIFY_CLIENT, false); 374 } 375 376 377 378 /** 379 * Creates a new disconnect client task from the provided set of task 380 * properties. 381 * 382 * @param properties The set of task properties and their corresponding 383 * values to use for the task. It must not be 384 * {@code null}. 385 * 386 * @throws TaskException If the provided set of properties cannot be used to 387 * create a valid disconnect client task. 388 */ 389 public DisconnectClientTask(final Map<TaskProperty,List<Object>> properties) 390 throws TaskException 391 { 392 super(DISCONNECT_CLIENT_TASK_CLASS, properties); 393 394 boolean notify = false; 395 Long connID = null; 396 String msg = null; 397 398 399 for (final Map.Entry<TaskProperty,List<Object>> entry : 400 properties.entrySet()) 401 { 402 final TaskProperty p = entry.getKey(); 403 final String attrName = p.getAttributeName(); 404 final List<Object> values = entry.getValue(); 405 406 if (attrName.equalsIgnoreCase(ATTR_CONNECTION_ID)) 407 { 408 connID = parseLong(p, values, connID); 409 } 410 else if (attrName.equalsIgnoreCase(ATTR_DISCONNECT_MESSAGE)) 411 { 412 msg = parseString(p, values, msg); 413 } 414 else if (attrName.equalsIgnoreCase(ATTR_NOTIFY_CLIENT)) 415 { 416 notify = parseBoolean(p, values, notify); 417 } 418 } 419 420 if (connID == null) 421 { 422 throw new TaskException(ERR_DISCONNECT_TASK_NO_CONN_ID.get( 423 getTaskEntryDN())); 424 } 425 426 connectionID = connID; 427 disconnectMessage = msg; 428 notifyClient = notify; 429 } 430 431 432 433 /** 434 * {@inheritDoc} 435 */ 436 @Override() 437 public String getTaskName() 438 { 439 return INFO_TASK_NAME_DISCONNECT_CLIENT.get(); 440 } 441 442 443 444 /** 445 * {@inheritDoc} 446 */ 447 @Override() 448 public String getTaskDescription() 449 { 450 return INFO_TASK_DESCRIPTION_DISCONNECT_CLIENT.get(); 451 } 452 453 454 455 /** 456 * Retrieves the connection ID of the client connection to disconnect. 457 * 458 * @return The connection ID of the client connection to disconnect. 459 */ 460 public long getConnectionID() 461 { 462 return connectionID; 463 } 464 465 466 467 /** 468 * Retrieves the disconnect message to provide to the server, and potentially 469 * to the client. 470 * 471 * @return The disconnect message, or {@code null} if no message is to be 472 * provided. 473 */ 474 public String getDisconnectMessage() 475 { 476 return disconnectMessage; 477 } 478 479 480 481 /** 482 * Indicates whether to send a notice of disconnection message to the client 483 * before terminating the connection. 484 * 485 * @return {@code true} if the server should send a notice of disconnection 486 * to the client, or {@code false} if it should terminate the 487 * connection without warning. 488 */ 489 public boolean notifyClient() 490 { 491 return notifyClient; 492 } 493 494 495 496 /** 497 * {@inheritDoc} 498 */ 499 @Override() 500 protected List<String> getAdditionalObjectClasses() 501 { 502 return Collections.singletonList(OC_DISCONNECT_CLIENT_TASK); 503 } 504 505 506 507 /** 508 * {@inheritDoc} 509 */ 510 @Override() 511 protected List<Attribute> getAdditionalAttributes() 512 { 513 final ArrayList<Attribute> attrs = new ArrayList<>(3); 514 515 attrs.add(new Attribute(ATTR_CONNECTION_ID, String.valueOf(connectionID))); 516 attrs.add(new Attribute(ATTR_NOTIFY_CLIENT, String.valueOf(notifyClient))); 517 518 if (disconnectMessage != null) 519 { 520 attrs.add(new Attribute(ATTR_DISCONNECT_MESSAGE, disconnectMessage)); 521 } 522 523 return attrs; 524 } 525 526 527 528 /** 529 * {@inheritDoc} 530 */ 531 @Override() 532 public List<TaskProperty> getTaskSpecificProperties() 533 { 534 final List<TaskProperty> propList = Arrays.asList( 535 PROPERTY_CONNECTION_ID, 536 PROPERTY_DISCONNECT_MESSAGE, 537 PROPERTY_NOTIFY_CLIENT); 538 539 return Collections.unmodifiableList(propList); 540 } 541 542 543 544 /** 545 * {@inheritDoc} 546 */ 547 @Override() 548 public Map<TaskProperty,List<Object>> getTaskPropertyValues() 549 { 550 final LinkedHashMap<TaskProperty,List<Object>> props = 551 new LinkedHashMap<>(StaticUtils.computeMapCapacity(10)); 552 553 props.put(PROPERTY_CONNECTION_ID, 554 Collections.<Object>singletonList(connectionID)); 555 556 if (disconnectMessage == null) 557 { 558 props.put(PROPERTY_DISCONNECT_MESSAGE, Collections.emptyList()); 559 } 560 else 561 { 562 props.put(PROPERTY_DISCONNECT_MESSAGE, 563 Collections.<Object>singletonList(disconnectMessage)); 564 } 565 566 props.put(PROPERTY_NOTIFY_CLIENT, 567 Collections.<Object>singletonList(notifyClient)); 568 569 props.putAll(super.getTaskPropertyValues()); 570 return Collections.unmodifiableMap(props); 571 } 572}