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