001/* 002 * Copyright 2013-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2013-2020 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2015-2020 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.unboundidds.tasks; 037 038 039 040import java.util.ArrayList; 041import java.util.Arrays; 042import java.util.Collections; 043import java.util.Date; 044import java.util.LinkedHashMap; 045import java.util.List; 046import java.util.Map; 047 048import com.unboundid.ldap.sdk.Attribute; 049import com.unboundid.ldap.sdk.Entry; 050import com.unboundid.util.NotMutable; 051import com.unboundid.util.StaticUtils; 052import com.unboundid.util.ThreadSafety; 053import com.unboundid.util.ThreadSafetyLevel; 054import com.unboundid.util.Validator; 055 056import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*; 057 058 059 060/** 061 * This class defines a Directory Server task that can be used to cause entries 062 * contained in a local DB backend to be re-encoded, which may be used to 063 * apply any configuration changes that affect the encoding of that entry (e.g., 064 * if the entry should be encrypted, hashed, compressed, or fully or partially 065 * uncached; or if these settings should be reverted). 066 * <BR> 067 * <BLOCKQUOTE> 068 * <B>NOTE:</B> This class, and other classes within the 069 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 070 * supported for use against Ping Identity, UnboundID, and 071 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 072 * for proprietary functionality or for external specifications that are not 073 * considered stable or mature enough to be guaranteed to work in an 074 * interoperable way with other types of LDAP servers. 075 * </BLOCKQUOTE> 076 * <BR> 077 * The properties that are available for use with this type of task include: 078 * <UL> 079 * <LI>The backend ID of the backend in which entries should be re-encoded. 080 * This must be provided.</LI> 081 * <LI>The base DN of a branch of entries to include in the re-encode 082 * processing.</LI> 083 * <LI>The base DN of a branch of entries to exclude from the re-encode 084 * processing.</LI> 085 * <LI>A filter to use to identify entries to include in the re-encode 086 * processing.</LI> 087 * <LI>A filter to use to identify entries to exclude from the re-encode 088 * processing.</LI> 089 * <LI>The maximum rate at which to re-encode entries, in number of entries 090 * per second.</LI> 091 * <LI>An indication as to whether to skip entries that are fully 092 * uncached.</LI> 093 * <LI>An indication as to whether to skip entries that are partially 094 * uncached.</LI> 095 * </UL> 096 */ 097@NotMutable() 098@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 099public final class ReEncodeEntriesTask 100 extends Task 101{ 102 /** 103 * The fully-qualified name of the Java class that is used for the re-encode 104 * entries task. 105 */ 106 static final String RE_ENCODE_ENTRIES_TASK_CLASS = 107 "com.unboundid.directory.server.tasks.ReEncodeEntriesTask"; 108 109 110 /** 111 * The name of the attribute used to specify the backend ID containing the 112 * entries to re-encode. 113 */ 114 private static final String ATTR_BACKEND_ID = "ds-task-reencode-backend-id"; 115 116 117 /** 118 * The name of the attribute used to specify the include branch(es). 119 */ 120 private static final String ATTR_INCLUDE_BRANCH = 121 "ds-task-reencode-include-branch"; 122 123 124 /** 125 * The name of the attribute used to specify the exclude branch(es). 126 */ 127 private static final String ATTR_EXCLUDE_BRANCH = 128 "ds-task-reencode-exclude-branch"; 129 130 131 /** 132 * The name of the attribute used to specify the include filter(s). 133 */ 134 private static final String ATTR_INCLUDE_FILTER = 135 "ds-task-reencode-include-filter"; 136 137 138 /** 139 * The name of the attribute used to specify the exclude filter(s). 140 */ 141 private static final String ATTR_EXCLUDE_FILTER = 142 "ds-task-reencode-exclude-filter"; 143 144 145 /** 146 * The name of the attribute used to specify the maximum re-encode rate in 147 * entries per second. 148 */ 149 private static final String ATTR_MAX_ENTRIES_PER_SECOND = 150 "ds-task-reencode-max-entries-per-second"; 151 152 153 /** 154 * The name of the attribute used to specify whether to skip fully uncached 155 * entries. 156 */ 157 private static final String ATTR_SKIP_FULLY_UNCACHED = 158 "ds-task-reencode-skip-fully-uncached-entries"; 159 160 161 /** 162 * The name of the attribute used to specify whether to skip partially 163 * uncached entries. 164 */ 165 private static final String ATTR_SKIP_PARTIALLY_UNCACHED = 166 "ds-task-reencode-skip-partially-uncached-entries"; 167 168 169 /** 170 * The name of the object class used in re-encode entries task entries. 171 */ 172 private static final String OC_REENCODE_ENTRIES_TASK = 173 "ds-task-reencode"; 174 175 176 /** 177 * The task property that will be used for the backend ID. 178 */ 179 static final TaskProperty PROPERTY_BACKEND_ID = 180 new TaskProperty(ATTR_BACKEND_ID, 181 INFO_DISPLAY_NAME_REENCODE_BACKEND_ID.get(), 182 INFO_DESCRIPTION_REENCODE_BACKEND_ID.get(), 183 String.class, true, false, false); 184 185 186 187 /** 188 * The task property that will be used for the include branch(es). 189 */ 190 private static final TaskProperty PROPERTY_INCLUDE_BRANCH = 191 new TaskProperty(ATTR_INCLUDE_BRANCH, 192 INFO_DISPLAY_NAME_REENCODE_INCLUDE_BRANCH.get(), 193 INFO_DESCRIPTION_REENCODE_INCLUDE_BRANCH.get(), 194 String.class, false, true, false); 195 196 197 198 /** 199 * The task property that will be used for the exclude branch(es). 200 */ 201 private static final TaskProperty PROPERTY_EXCLUDE_BRANCH = 202 new TaskProperty(ATTR_EXCLUDE_BRANCH, 203 INFO_DISPLAY_NAME_REENCODE_EXCLUDE_BRANCH.get(), 204 INFO_DESCRIPTION_REENCODE_EXCLUDE_BRANCH.get(), 205 String.class, false, true, false); 206 207 208 209 /** 210 * The task property that will be used for the include filter(s). 211 */ 212 private static final TaskProperty PROPERTY_INCLUDE_FILTER = 213 new TaskProperty(ATTR_INCLUDE_FILTER, 214 INFO_DISPLAY_NAME_REENCODE_INCLUDE_FILTER.get(), 215 INFO_DESCRIPTION_REENCODE_INCLUDE_FILTER.get(), 216 String.class, false, true, false); 217 218 219 220 /** 221 * The task property that will be used for the exclude filter(s). 222 */ 223 private static final TaskProperty PROPERTY_EXCLUDE_FILTER = 224 new TaskProperty(ATTR_EXCLUDE_FILTER, 225 INFO_DISPLAY_NAME_REENCODE_EXCLUDE_FILTER.get(), 226 INFO_DESCRIPTION_REENCODE_EXCLUDE_FILTER.get(), 227 String.class, false, true, false); 228 229 230 231 /** 232 * The task property that will be used for the maximum reencode rate. 233 */ 234 private static final TaskProperty PROPERTY_MAX_ENTRIES_PER_SECOND = 235 new TaskProperty(ATTR_MAX_ENTRIES_PER_SECOND, 236 INFO_DISPLAY_NAME_REENCODE_MAX_ENTRIES_PER_SECOND.get(), 237 INFO_DESCRIPTION_REENCODE_MAX_ENTRIES_PER_SECOND.get(), 238 Long.class, false, false, false); 239 240 241 242 /** 243 * The task property that will be used to indicate whether to skip fully 244 * uncached entries. 245 */ 246 private static final TaskProperty PROPERTY_SKIP_FULLY_UNCACHED = 247 new TaskProperty(ATTR_SKIP_FULLY_UNCACHED, 248 INFO_DISPLAY_NAME_REENCODE_SKIP_FULLY_UNCACHED.get(), 249 INFO_DESCRIPTION_REENCODE_SKIP_FULLY_UNCACHED.get(), 250 Boolean.class, false, false, false); 251 252 253 254 /** 255 * The task property that will be used to indicate whether to skip partially 256 * uncached entries. 257 */ 258 private static final TaskProperty PROPERTY_SKIP_PARTIALLY_UNCACHED = 259 new TaskProperty(ATTR_SKIP_PARTIALLY_UNCACHED, 260 INFO_DISPLAY_NAME_REENCODE_SKIP_PARTIALLY_UNCACHED.get(), 261 INFO_DESCRIPTION_REENCODE_SKIP_PARTIALLY_UNCACHED.get(), 262 Boolean.class, false, false, false); 263 264 265 266 /** 267 * The serial version UID for this serializable class. 268 */ 269 private static final long serialVersionUID = 1804218099237094046L; 270 271 272 273 // Indicates whether to skip fully-uncached entries. 274 private final boolean skipFullyUncachedEntries; 275 276 // Indicates whether to skip partially-uncached entries. 277 private final boolean skipPartiallyUncachedEntries; 278 279 // The maximum number of entries to re-encode per second. 280 private final Long maxEntriesPerSecond; 281 282 // The list of exclude branch DNs. 283 private final List<String> excludeBranches; 284 285 // The list of exclude filters. 286 private final List<String> excludeFilters; 287 288 // The list of include branch DNs. 289 private final List<String> includeBranches; 290 291 // The list of include filters. 292 private final List<String> includeFilters; 293 294 // The backend ID for the backend containing entries to re-encode. 295 private final String backendID; 296 297 298 299 /** 300 * Creates a new uninitialized re-encode entries task instance which should 301 * only be used for obtaining general information about this task, including 302 * the task name, description, and supported properties. Attempts to use a 303 * task created with this constructor for any other reason will likely fail. 304 */ 305 public ReEncodeEntriesTask() 306 { 307 skipFullyUncachedEntries = false; 308 skipPartiallyUncachedEntries = false; 309 maxEntriesPerSecond = null; 310 excludeBranches = null; 311 excludeFilters = null; 312 includeBranches = null; 313 includeFilters = null; 314 backendID = null; 315 } 316 317 318 319 /** 320 * Creates a new re-encode entries task with the provided information. 321 * 322 * @param taskID The task ID to use for this task. If 323 * it is {@code null} then a UUID will 324 * be generated for use as the task ID. 325 * @param backendID The backend ID of the backend 326 * containing the entries to re-encode. 327 * It must not be {@code null}. 328 * @param includeBranches A list containing the base DNs of 329 * branches to include in re-encode 330 * processing. It may be {@code null} 331 * or empty if there should not be any 332 * include branches. 333 * @param excludeBranches A list containing the base DNs of 334 * branches to exclude from re-encode 335 * processing. It may be {@code null} 336 * or empty if there should not be any 337 * exclude branches. 338 * @param includeFilters A list containing filters to use to 339 * identify entries to include in 340 * re-encode processing. It may be 341 * {@code null} or empty if there should 342 * not be any include filters. 343 * @param excludeFilters A list containing filters to use to 344 * identify entries to exclude from 345 * re-encode processing. It may be 346 * {@code null} or empty if there should 347 * not be any exclude filters. 348 * @param maxEntriesPerSecond The maximum number of entries to 349 * re-encode per second. It may be 350 * {@code null} to indicate that no 351 * limit should be imposed. 352 * @param skipFullyUncachedEntries Indicates whether to skip re-encode 353 * processing for entries that are fully 354 * uncached. 355 * @param skipPartiallyUncachedEntries Indicates whether to skip re-encode 356 * processing for entries that contain 357 * a mix of cached and uncached 358 * attributes. 359 */ 360 public ReEncodeEntriesTask(final String taskID, 361 final String backendID, 362 final List<String> includeBranches, 363 final List<String> excludeBranches, 364 final List<String> includeFilters, 365 final List<String> excludeFilters, 366 final Long maxEntriesPerSecond, 367 final boolean skipFullyUncachedEntries, 368 final boolean skipPartiallyUncachedEntries) 369 { 370 this(taskID, backendID, includeBranches, excludeBranches, includeFilters, 371 excludeFilters, maxEntriesPerSecond, skipFullyUncachedEntries, 372 skipPartiallyUncachedEntries, null, null, null, null, null); 373 } 374 375 376 377 /** 378 * Creates a new re-encode entries task with the provided information. 379 * 380 * @param taskID The task ID to use for this task. If 381 * it is {@code null} then a UUID will 382 * be generated for use as the task ID. 383 * @param backendID The backend ID of the backend 384 * containing the entries to re-encode. 385 * It must not be {@code null}. 386 * @param includeBranches A list containing the base DNs of 387 * branches to include in re-encode 388 * processing. It may be {@code null} 389 * or empty if there should not be any 390 * include branches. 391 * @param excludeBranches A list containing the base DNs of 392 * branches to exclude from re-encode 393 * processing. It may be {@code null} 394 * or empty if there should not be any 395 * exclude branches. 396 * @param includeFilters A list containing filters to use to 397 * identify entries to include in 398 * re-encode processing. It may be 399 * {@code null} or empty if there should 400 * not be any include filters. 401 * @param excludeFilters A list containing filters to use to 402 * identify entries to exclude from 403 * re-encode processing. It may be 404 * {@code null} or empty if there should 405 * not be any exclude filters. 406 * @param maxEntriesPerSecond The maximum number of entries to 407 * re-encode per second. It may be 408 * {@code null} to indicate that no 409 * limit should be imposed. 410 * @param skipFullyUncachedEntries Indicates whether to skip re-encode 411 * processing for entries that are fully 412 * uncached. 413 * @param skipPartiallyUncachedEntries Indicates whether to skip re-encode 414 * processing for entries that contain 415 * a mix of cached and uncached 416 * attributes. 417 * @param scheduledStartTime The time that this task should start 418 * running. 419 * @param dependencyIDs The list of task IDs that will be 420 * required to complete before this task 421 * will be eligible to start. 422 * @param failedDependencyAction Indicates what action should be taken 423 * if any of the dependencies for this 424 * task do not complete successfully. 425 * @param notifyOnCompletion The list of e-mail addresses of 426 * individuals that should be notified 427 * when this task completes. 428 * @param notifyOnError The list of e-mail addresses of 429 * individuals that should be notified 430 * if this task does not complete 431 * successfully. 432 */ 433 public ReEncodeEntriesTask(final String taskID, final String backendID, 434 final List<String> includeBranches, 435 final List<String> excludeBranches, 436 final List<String> includeFilters, 437 final List<String> excludeFilters, 438 final Long maxEntriesPerSecond, 439 final boolean skipFullyUncachedEntries, 440 final boolean skipPartiallyUncachedEntries, 441 final Date scheduledStartTime, 442 final List<String> dependencyIDs, 443 final FailedDependencyAction failedDependencyAction, 444 final List<String> notifyOnCompletion, 445 final List<String> notifyOnError) 446 { 447 this(taskID, backendID, includeBranches, excludeBranches, includeFilters, 448 excludeFilters, maxEntriesPerSecond, skipFullyUncachedEntries, 449 skipPartiallyUncachedEntries, scheduledStartTime, dependencyIDs, 450 failedDependencyAction, null, notifyOnCompletion, null, 451 notifyOnError, null, null, null); 452 } 453 454 455 456 /** 457 * Creates a new re-encode entries task with the provided information. 458 * 459 * @param taskID The task ID to use for this task. If 460 * it is {@code null} then a UUID will 461 * be generated for use as the task ID. 462 * @param backendID The backend ID of the backend 463 * containing the entries to re-encode. 464 * It must not be {@code null}. 465 * @param includeBranches A list containing the base DNs of 466 * branches to include in re-encode 467 * processing. It may be {@code null} 468 * or empty if there should not be any 469 * include branches. 470 * @param excludeBranches A list containing the base DNs of 471 * branches to exclude from re-encode 472 * processing. It may be {@code null} 473 * or empty if there should not be any 474 * exclude branches. 475 * @param includeFilters A list containing filters to use to 476 * identify entries to include in 477 * re-encode processing. It may be 478 * {@code null} or empty if there should 479 * not be any include filters. 480 * @param excludeFilters A list containing filters to use to 481 * identify entries to exclude from 482 * re-encode processing. It may be 483 * {@code null} or empty if there should 484 * not be any exclude filters. 485 * @param maxEntriesPerSecond The maximum number of entries to 486 * re-encode per second. It may be 487 * {@code null} to indicate that no 488 * limit should be imposed. 489 * @param skipFullyUncachedEntries Indicates whether to skip re-encode 490 * processing for entries that are fully 491 * uncached. 492 * @param skipPartiallyUncachedEntries Indicates whether to skip re-encode 493 * processing for entries that contain 494 * a mix of cached and uncached 495 * attributes. 496 * @param scheduledStartTime The time that this task should start 497 * running. 498 * @param dependencyIDs The list of task IDs that will be 499 * required to complete before this task 500 * will be eligible to start. 501 * @param failedDependencyAction Indicates what action should be taken 502 * if any of the dependencies for this 503 * task do not complete successfully. 504 * @param notifyOnStart The list of e-mail addresses of 505 * individuals that should be notified 506 * when this task starts running. 507 * @param notifyOnCompletion The list of e-mail addresses of 508 * individuals that should be notified 509 * when this task completes. 510 * @param notifyOnSuccess The list of e-mail addresses of 511 * individuals that should be notified 512 * if this task completes successfully. 513 * @param notifyOnError The list of e-mail addresses of 514 * individuals that should be notified 515 * if this task does not complete 516 * successfully. 517 * @param alertOnStart Indicates whether the server should 518 * send an alert notification when this 519 * task starts. 520 * @param alertOnSuccess Indicates whether the server should 521 * send an alert notification if this 522 * task completes successfully. 523 * @param alertOnError Indicates whether the server should 524 * send an alert notification if this 525 * task fails to complete successfully. 526 */ 527 public ReEncodeEntriesTask(final String taskID, final String backendID, 528 final List<String> includeBranches, 529 final List<String> excludeBranches, 530 final List<String> includeFilters, 531 final List<String> excludeFilters, 532 final Long maxEntriesPerSecond, 533 final boolean skipFullyUncachedEntries, 534 final boolean skipPartiallyUncachedEntries, 535 final Date scheduledStartTime, 536 final List<String> dependencyIDs, 537 final FailedDependencyAction failedDependencyAction, 538 final List<String> notifyOnStart, 539 final List<String> notifyOnCompletion, 540 final List<String> notifyOnSuccess, 541 final List<String> notifyOnError, final Boolean alertOnStart, 542 final Boolean alertOnSuccess, final Boolean alertOnError) 543 { 544 super(taskID, RE_ENCODE_ENTRIES_TASK_CLASS, scheduledStartTime, 545 dependencyIDs, failedDependencyAction, notifyOnStart, 546 notifyOnCompletion, notifyOnSuccess, notifyOnError, alertOnStart, 547 alertOnSuccess, alertOnError); 548 549 Validator.ensureNotNull(backendID); 550 551 this.backendID = backendID; 552 this.maxEntriesPerSecond = maxEntriesPerSecond; 553 this.skipFullyUncachedEntries = skipFullyUncachedEntries; 554 this.skipPartiallyUncachedEntries = skipPartiallyUncachedEntries; 555 556 if ((includeBranches == null) || includeBranches.isEmpty()) 557 { 558 this.includeBranches = Collections.emptyList(); 559 } 560 else 561 { 562 this.includeBranches = Collections.unmodifiableList(includeBranches); 563 } 564 565 if ((excludeBranches == null) || excludeBranches.isEmpty()) 566 { 567 this.excludeBranches = Collections.emptyList(); 568 } 569 else 570 { 571 this.excludeBranches = Collections.unmodifiableList(excludeBranches); 572 } 573 574 if ((includeFilters == null) || includeFilters.isEmpty()) 575 { 576 this.includeFilters = Collections.emptyList(); 577 } 578 else 579 { 580 this.includeFilters = Collections.unmodifiableList(includeFilters); 581 } 582 583 if ((excludeFilters == null) || excludeFilters.isEmpty()) 584 { 585 this.excludeFilters = Collections.emptyList(); 586 } 587 else 588 { 589 this.excludeFilters = Collections.unmodifiableList(excludeFilters); 590 } 591 } 592 593 594 595 /** 596 * Creates a new re-encode entries task from the provided entry. 597 * 598 * @param entry The entry to use to create this re-encode entries task. 599 * 600 * @throws TaskException If the provided entry cannot be parsed as a 601 * re-encode entries task entry. 602 */ 603 public ReEncodeEntriesTask(final Entry entry) 604 throws TaskException 605 { 606 super(entry); 607 608 609 // Get the backend ID. It must be present. 610 backendID = entry.getAttributeValue(ATTR_BACKEND_ID); 611 if (backendID == null) 612 { 613 throw new TaskException(ERR_REENCODE_TASK_MISSING_REQUIRED_ATTR.get( 614 entry.getDN(), ATTR_BACKEND_ID)); 615 } 616 617 // Get the set of include branches. 618 final String[] iBranches = entry.getAttributeValues(ATTR_INCLUDE_BRANCH); 619 if (iBranches == null) 620 { 621 includeBranches = Collections.emptyList(); 622 } 623 else 624 { 625 includeBranches = Collections.unmodifiableList(Arrays.asList(iBranches)); 626 } 627 628 // Get the set of exclude branches. 629 final String[] eBranches = entry.getAttributeValues(ATTR_EXCLUDE_BRANCH); 630 if (eBranches == null) 631 { 632 excludeBranches = Collections.emptyList(); 633 } 634 else 635 { 636 excludeBranches = Collections.unmodifiableList(Arrays.asList(eBranches)); 637 } 638 639 // Get the set of include filters. 640 final String[] iFilters = entry.getAttributeValues(ATTR_INCLUDE_FILTER); 641 if (iFilters == null) 642 { 643 includeFilters = Collections.emptyList(); 644 } 645 else 646 { 647 includeFilters = Collections.unmodifiableList(Arrays.asList(iFilters)); 648 } 649 650 // Get the set of exclude filters. 651 final String[] eFilters = entry.getAttributeValues(ATTR_EXCLUDE_FILTER); 652 if (eFilters == null) 653 { 654 excludeFilters = Collections.emptyList(); 655 } 656 else 657 { 658 excludeFilters = Collections.unmodifiableList(Arrays.asList(eFilters)); 659 } 660 661 // Get the max entry rate. 662 maxEntriesPerSecond = 663 entry.getAttributeValueAsLong(ATTR_MAX_ENTRIES_PER_SECOND); 664 665 // Determine whether to skip fully uncached entries. 666 final Boolean skipFullyUncached = 667 entry.getAttributeValueAsBoolean(ATTR_SKIP_FULLY_UNCACHED); 668 if (skipFullyUncached == null) 669 { 670 skipFullyUncachedEntries = false; 671 } 672 else 673 { 674 skipFullyUncachedEntries = skipFullyUncached; 675 } 676 677 // Determine whether to skip partially uncached entries. 678 final Boolean skipPartiallyUncached = 679 entry.getAttributeValueAsBoolean(ATTR_SKIP_PARTIALLY_UNCACHED); 680 if (skipPartiallyUncached == null) 681 { 682 skipPartiallyUncachedEntries = false; 683 } 684 else 685 { 686 skipPartiallyUncachedEntries = skipPartiallyUncached; 687 } 688 } 689 690 691 692 /** 693 * Creates a new re-encode entries task from the provided set of task 694 * properties. 695 * 696 * @param properties The set of task properties and their corresponding 697 * values to use for the task. It must not be 698 * {@code null}. 699 * 700 * @throws TaskException If the provided set of properties cannot be used to 701 * create a valid re-encode entries task. 702 */ 703 public ReEncodeEntriesTask(final Map<TaskProperty,List<Object>> properties) 704 throws TaskException 705 { 706 super(RE_ENCODE_ENTRIES_TASK_CLASS, properties); 707 708 boolean skipFullyUncached = false; 709 boolean skipPartiallyUncached = false; 710 Long maxRate = null; 711 List<String> eBranches = Collections.emptyList(); 712 List<String> eFilters = Collections.emptyList(); 713 List<String> iBranches = Collections.emptyList(); 714 List<String> iFilters = Collections.emptyList(); 715 String id = null; 716 717 for (final Map.Entry<TaskProperty,List<Object>> e : properties.entrySet()) 718 { 719 final TaskProperty p = e.getKey(); 720 final String attrName = p.getAttributeName(); 721 final List<Object> values = e.getValue(); 722 723 if (attrName.equalsIgnoreCase(ATTR_BACKEND_ID)) 724 { 725 id = parseString(p, values, null); 726 } 727 else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_BRANCH)) 728 { 729 final String[] branches = parseStrings(p, values, null); 730 if (branches != null) 731 { 732 iBranches = Collections.unmodifiableList(Arrays.asList(branches)); 733 } 734 } 735 else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_BRANCH)) 736 { 737 final String[] branches = parseStrings(p, values, null); 738 if (branches != null) 739 { 740 eBranches = Collections.unmodifiableList(Arrays.asList(branches)); 741 } 742 } 743 else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_FILTER)) 744 { 745 final String[] filters = parseStrings(p, values, null); 746 if (filters != null) 747 { 748 iFilters = Collections.unmodifiableList(Arrays.asList(filters)); 749 } 750 } 751 else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_FILTER)) 752 { 753 final String[] filters = parseStrings(p, values, null); 754 if (filters != null) 755 { 756 eFilters = Collections.unmodifiableList(Arrays.asList(filters)); 757 } 758 } 759 else if (attrName.equalsIgnoreCase(ATTR_MAX_ENTRIES_PER_SECOND)) 760 { 761 maxRate = parseLong(p, values, null); 762 } 763 else if (attrName.equalsIgnoreCase(ATTR_SKIP_FULLY_UNCACHED)) 764 { 765 skipFullyUncached = parseBoolean(p, values, false); 766 } 767 else if (attrName.equalsIgnoreCase(ATTR_SKIP_PARTIALLY_UNCACHED)) 768 { 769 skipPartiallyUncached = parseBoolean(p, values, false); 770 } 771 } 772 773 if (id == null) 774 { 775 throw new TaskException(ERR_REENCODE_TASK_MISSING_REQUIRED_PROPERTY.get( 776 ATTR_BACKEND_ID)); 777 } 778 779 backendID = id; 780 includeBranches = iBranches; 781 excludeBranches = eBranches; 782 includeFilters = iFilters; 783 excludeFilters = eFilters; 784 maxEntriesPerSecond = maxRate; 785 skipFullyUncachedEntries = skipFullyUncached; 786 skipPartiallyUncachedEntries = skipPartiallyUncached; 787 } 788 789 790 791 /** 792 * {@inheritDoc} 793 */ 794 @Override() 795 public String getTaskName() 796 { 797 return INFO_TASK_NAME_REENCODE_ENTRIES.get(); 798 } 799 800 801 802 /** 803 * {@inheritDoc} 804 */ 805 @Override() 806 public String getTaskDescription() 807 { 808 return INFO_TASK_DESCRIPTION_REENCODE_ENTRIES.get(); 809 } 810 811 812 813 /** 814 * Retrieves the backend ID for the backend containing the entries to 815 * re-encode. 816 * 817 * @return The backend ID for the backend containing the entries to 818 * re-encode. 819 */ 820 public String getBackendID() 821 { 822 return backendID; 823 } 824 825 826 827 /** 828 * Retrieves the base DNs of the branches to include in re-encode processing, 829 * if defined. 830 * 831 * @return The base DNs of the branches to include in re-encode processing, 832 * or an empty list if there should not be any include branches. 833 */ 834 public List<String> getIncludeBranches() 835 { 836 return includeBranches; 837 } 838 839 840 841 /** 842 * Retrieves the base DNs of the branches to exclude from re-encode 843 * processing, if defined. 844 * 845 * @return The base DNs of the branches to exclude from re-encode processing, 846 * or an empty list if there should not be any exclude branches. 847 */ 848 public List<String> getExcludeBranches() 849 { 850 return excludeBranches; 851 } 852 853 854 855 /** 856 * Retrieves a set of filters to use to identify entries to include in 857 * re-encode processing, if defined. 858 * 859 * @return A set of filters to use to identify entries to include in 860 * re-encode processing, or an empty list if there should not be any 861 * include filters. 862 */ 863 public List<String> getIncludeFilters() 864 { 865 return includeFilters; 866 } 867 868 869 870 /** 871 * Retrieves a set of filters to use to identify entries to exclude from 872 * re-encode processing, if defined. 873 * 874 * @return A set of filters to use to identify entries to exclude from 875 * re-encode processing, or an empty list if there should not be any 876 * exclude filters. 877 */ 878 public List<String> getExcludeFilters() 879 { 880 return excludeFilters; 881 } 882 883 884 885 /** 886 * Retrieves the maximum number of entries that should be re-encoded per 887 * second, if defined. 888 * 889 * @return The maximum number of entries that should be re-encoded per 890 * second, or {@code null} if no rate limit should be imposed. 891 */ 892 public Long getMaxEntriesPerSecond() 893 { 894 return maxEntriesPerSecond; 895 } 896 897 898 899 /** 900 * Indicates whether to skip re-encode processing for entries that are stored 901 * as fully uncached. 902 * 903 * @return {@code true} if fully uncached entries should be skipped, or 904 * {@code false} if not. 905 */ 906 public boolean skipFullyUncachedEntries() 907 { 908 return skipFullyUncachedEntries; 909 } 910 911 912 913 /** 914 * Indicates whether to skip re-encode processing for entries that have a 915 * mix of cached and uncached attributes. 916 * 917 * @return {@code true} if partially uncached entries should be skipped, or 918 * {@code false} if not. 919 */ 920 public boolean skipPartiallyUncachedEntries() 921 { 922 return skipPartiallyUncachedEntries; 923 } 924 925 926 927 /** 928 * {@inheritDoc} 929 */ 930 @Override() 931 protected List<String> getAdditionalObjectClasses() 932 { 933 return Collections.singletonList(OC_REENCODE_ENTRIES_TASK); 934 } 935 936 937 938 /** 939 * {@inheritDoc} 940 */ 941 @Override() 942 protected List<Attribute> getAdditionalAttributes() 943 { 944 final ArrayList<Attribute> attrList = new ArrayList<>(7); 945 attrList.add(new Attribute(ATTR_BACKEND_ID, backendID)); 946 attrList.add(new Attribute(ATTR_SKIP_FULLY_UNCACHED, 947 String.valueOf(skipFullyUncachedEntries))); 948 attrList.add(new Attribute(ATTR_SKIP_PARTIALLY_UNCACHED, 949 String.valueOf(skipPartiallyUncachedEntries))); 950 951 if (! includeBranches.isEmpty()) 952 { 953 attrList.add(new Attribute(ATTR_INCLUDE_BRANCH, includeBranches)); 954 } 955 956 if (! excludeBranches.isEmpty()) 957 { 958 attrList.add(new Attribute(ATTR_EXCLUDE_BRANCH, excludeBranches)); 959 } 960 961 if (! includeFilters.isEmpty()) 962 { 963 attrList.add(new Attribute(ATTR_INCLUDE_FILTER, includeFilters)); 964 } 965 966 if (! excludeFilters.isEmpty()) 967 { 968 attrList.add(new Attribute(ATTR_EXCLUDE_FILTER, excludeFilters)); 969 } 970 971 if (maxEntriesPerSecond != null) 972 { 973 attrList.add(new Attribute(ATTR_MAX_ENTRIES_PER_SECOND, 974 String.valueOf(maxEntriesPerSecond))); 975 } 976 977 return attrList; 978 } 979 980 981 982 /** 983 * {@inheritDoc} 984 */ 985 @Override() 986 public List<TaskProperty> getTaskSpecificProperties() 987 { 988 return Collections.unmodifiableList(Arrays.asList( 989 PROPERTY_BACKEND_ID, 990 PROPERTY_INCLUDE_BRANCH, 991 PROPERTY_EXCLUDE_BRANCH, 992 PROPERTY_INCLUDE_FILTER, 993 PROPERTY_EXCLUDE_FILTER, 994 PROPERTY_MAX_ENTRIES_PER_SECOND, 995 PROPERTY_SKIP_FULLY_UNCACHED, 996 PROPERTY_SKIP_PARTIALLY_UNCACHED)); 997 } 998 999 1000 1001 /** 1002 * {@inheritDoc} 1003 */ 1004 @Override() 1005 public Map<TaskProperty,List<Object>> getTaskPropertyValues() 1006 { 1007 final LinkedHashMap<TaskProperty,List<Object>> props = 1008 new LinkedHashMap<>(StaticUtils.computeMapCapacity(15)); 1009 1010 props.put(PROPERTY_BACKEND_ID, 1011 Collections.<Object>singletonList(backendID)); 1012 props.put(PROPERTY_INCLUDE_BRANCH, 1013 Collections.<Object>unmodifiableList(includeBranches)); 1014 props.put(PROPERTY_EXCLUDE_BRANCH, 1015 Collections.<Object>unmodifiableList(excludeBranches)); 1016 props.put(PROPERTY_INCLUDE_FILTER, 1017 Collections.<Object>unmodifiableList(includeFilters)); 1018 props.put(PROPERTY_EXCLUDE_FILTER, 1019 Collections.<Object>unmodifiableList(excludeFilters)); 1020 1021 if (maxEntriesPerSecond == null) 1022 { 1023 props.put(PROPERTY_MAX_ENTRIES_PER_SECOND, 1024 Collections.emptyList()); 1025 } 1026 else 1027 { 1028 props.put(PROPERTY_MAX_ENTRIES_PER_SECOND, 1029 Collections.<Object>singletonList(maxEntriesPerSecond)); 1030 } 1031 1032 props.put(PROPERTY_SKIP_FULLY_UNCACHED, 1033 Collections.<Object>singletonList(skipFullyUncachedEntries)); 1034 props.put(PROPERTY_SKIP_PARTIALLY_UNCACHED, 1035 Collections.<Object>singletonList(skipPartiallyUncachedEntries)); 1036 1037 props.putAll(super.getTaskPropertyValues()); 1038 return Collections.unmodifiableMap(props); 1039 } 1040}