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