001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2009 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2016 ForgeRock AS. 016 */ 017package org.opends.server.tasks; 018 019import static org.opends.messages.TaskMessages.*; 020import static org.opends.messages.ToolMessages.*; 021import static org.opends.server.config.ConfigConstants.*; 022import static org.opends.server.core.DirectoryServer.*; 023import static org.opends.server.util.StaticUtils.*; 024 025import java.io.File; 026import java.util.ArrayList; 027import java.util.HashMap; 028import java.util.HashSet; 029import java.util.List; 030import java.util.Map; 031import java.util.Random; 032 033import org.forgerock.i18n.LocalizableMessage; 034import org.forgerock.i18n.slf4j.LocalizedLogger; 035import org.forgerock.opendj.ldap.DN; 036import org.forgerock.opendj.ldap.ResultCode; 037import org.forgerock.opendj.ldap.schema.AttributeType; 038import org.opends.messages.Severity; 039import org.opends.messages.TaskMessages; 040import org.opends.server.api.Backend; 041import org.opends.server.api.Backend.BackendOperation; 042import org.opends.server.api.ClientConnection; 043import org.opends.server.backends.task.Task; 044import org.opends.server.backends.task.TaskState; 045import org.opends.server.core.DirectoryServer; 046import org.opends.server.core.LockFileManager; 047import org.opends.server.tools.makeldif.TemplateFile; 048import org.opends.server.types.Attribute; 049import org.opends.server.types.DirectoryException; 050import org.opends.server.types.Entry; 051import org.opends.server.types.ExistingFileBehavior; 052import org.opends.server.types.LDIFImportConfig; 053import org.opends.server.types.Operation; 054import org.opends.server.types.Privilege; 055import org.opends.server.types.SearchFilter; 056 057/** 058 * This class provides an implementation of a Directory Server task that can 059 * be used to import data from an LDIF file into a backend. 060 */ 061public class ImportTask extends Task 062{ 063 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 064 065 /** Stores mapping between configuration attribute name and its label. */ 066 private static final Map<String, LocalizableMessage> argDisplayMap = new HashMap<>(); 067 static 068 { 069 argDisplayMap.put(ATTR_IMPORT_LDIF_FILE, INFO_IMPORT_ARG_LDIF_FILE.get()); 070 argDisplayMap.put(ATTR_IMPORT_TEMPLATE_FILE, INFO_IMPORT_ARG_TEMPLATE_FILE.get()); 071 argDisplayMap.put(ATTR_IMPORT_RANDOM_SEED, INFO_IMPORT_ARG_RANDOM_SEED.get()); 072 argDisplayMap.put(ATTR_IMPORT_BACKEND_ID, INFO_IMPORT_ARG_BACKEND_ID.get()); 073 argDisplayMap.put(ATTR_IMPORT_INCLUDE_BRANCH, INFO_IMPORT_ARG_INCL_BRANCH.get()); 074 argDisplayMap.put(ATTR_IMPORT_EXCLUDE_BRANCH, INFO_IMPORT_ARG_EXCL_BRANCH.get()); 075 argDisplayMap.put(ATTR_IMPORT_INCLUDE_ATTRIBUTE, INFO_IMPORT_ARG_INCL_ATTR.get()); 076 argDisplayMap.put(ATTR_IMPORT_EXCLUDE_ATTRIBUTE, INFO_IMPORT_ARG_EXCL_ATTR.get()); 077 argDisplayMap.put(ATTR_IMPORT_INCLUDE_FILTER, INFO_IMPORT_ARG_INCL_FILTER.get()); 078 argDisplayMap.put(ATTR_IMPORT_EXCLUDE_FILTER, INFO_IMPORT_ARG_EXCL_FILTER.get()); 079 argDisplayMap.put(ATTR_IMPORT_REJECT_FILE, INFO_IMPORT_ARG_REJECT_FILE.get()); 080 argDisplayMap.put(ATTR_IMPORT_SKIP_FILE, INFO_IMPORT_ARG_SKIP_FILE.get()); 081 argDisplayMap.put(ATTR_IMPORT_OVERWRITE, INFO_IMPORT_ARG_OVERWRITE.get()); 082 argDisplayMap.put(ATTR_IMPORT_SKIP_SCHEMA_VALIDATION, INFO_IMPORT_ARG_SKIP_SCHEMA_VALIDATION.get()); 083 argDisplayMap.put(ATTR_IMPORT_IS_COMPRESSED, INFO_IMPORT_ARG_IS_COMPRESSED.get()); 084 argDisplayMap.put(ATTR_IMPORT_IS_ENCRYPTED, INFO_IMPORT_ARG_IS_ENCRYPTED.get()); 085 argDisplayMap.put(ATTR_IMPORT_CLEAR_BACKEND, INFO_IMPORT_ARG_CLEAR_BACKEND.get()); 086 } 087 088 private boolean isCompressed; 089 private boolean isEncrypted; 090 private boolean overwrite; 091 private boolean skipSchemaValidation; 092 private boolean clearBackend; 093 private String tmpDirectory; 094 private int threadCount; 095 private String backendID; 096 private String rejectFile; 097 private String skipFile; 098 private ArrayList<String> excludeAttributeStrings; 099 private ArrayList<String> excludeBranchStrings; 100 private ArrayList<String> excludeFilterStrings; 101 private ArrayList<String> includeAttributeStrings; 102 private ArrayList<String> includeBranchStrings; 103 private ArrayList<String> includeFilterStrings; 104 private ArrayList<String> ldifFiles; 105 private String templateFile; 106 private int randomSeed; 107 private LDIFImportConfig importConfig; 108 109 @Override 110 public LocalizableMessage getDisplayName() { 111 return INFO_TASK_IMPORT_NAME.get(); 112 } 113 114 @Override 115 public LocalizableMessage getAttributeDisplayName(String name) { 116 return argDisplayMap.get(name); 117 } 118 119 @Override public void initializeTask() throws DirectoryException 120 { 121 // If the client connection is available, then make sure the associated 122 // client has the LDIF_IMPORT privilege. 123 Operation operation = getOperation(); 124 if (operation != null) 125 { 126 ClientConnection clientConnection = operation.getClientConnection(); 127 if (! clientConnection.hasPrivilege(Privilege.LDIF_IMPORT, operation)) 128 { 129 LocalizableMessage message = ERR_TASK_LDIFIMPORT_INSUFFICIENT_PRIVILEGES.get(); 130 throw new DirectoryException(ResultCode.INSUFFICIENT_ACCESS_RIGHTS, message); 131 } 132 } 133 134 Entry taskEntry = getTaskEntry(); 135 136 AttributeType typeLdifFile = getSchema().getAttributeType(ATTR_IMPORT_LDIF_FILE); 137 AttributeType typeTemplateFile = getSchema().getAttributeType(ATTR_IMPORT_TEMPLATE_FILE); 138 AttributeType typeBackendID = getSchema().getAttributeType(ATTR_IMPORT_BACKEND_ID); 139 AttributeType typeIncludeBranch = getSchema().getAttributeType(ATTR_IMPORT_INCLUDE_BRANCH); 140 AttributeType typeExcludeBranch = getSchema().getAttributeType(ATTR_IMPORT_EXCLUDE_BRANCH); 141 AttributeType typeIncludeAttribute = getSchema().getAttributeType(ATTR_IMPORT_INCLUDE_ATTRIBUTE); 142 AttributeType typeExcludeAttribute = getSchema().getAttributeType(ATTR_IMPORT_EXCLUDE_ATTRIBUTE); 143 AttributeType typeIncludeFilter = getSchema().getAttributeType(ATTR_IMPORT_INCLUDE_FILTER); 144 AttributeType typeExcludeFilter = getSchema().getAttributeType(ATTR_IMPORT_EXCLUDE_FILTER); 145 AttributeType typeRejectFile = getSchema().getAttributeType(ATTR_IMPORT_REJECT_FILE); 146 AttributeType typeSkipFile = getSchema().getAttributeType(ATTR_IMPORT_SKIP_FILE); 147 AttributeType typeOverwrite = getSchema().getAttributeType(ATTR_IMPORT_OVERWRITE); 148 AttributeType typeSkipSchemaValidation = getSchema().getAttributeType(ATTR_IMPORT_SKIP_SCHEMA_VALIDATION); 149 AttributeType typeIsCompressed = getSchema().getAttributeType(ATTR_IMPORT_IS_COMPRESSED); 150 AttributeType typeIsEncrypted = getSchema().getAttributeType(ATTR_IMPORT_IS_ENCRYPTED); 151 AttributeType typeClearBackend = getSchema().getAttributeType(ATTR_IMPORT_CLEAR_BACKEND); 152 AttributeType typeRandomSeed = getSchema().getAttributeType(ATTR_IMPORT_RANDOM_SEED); 153 AttributeType typeThreadCount = getSchema().getAttributeType(ATTR_IMPORT_THREAD_COUNT); 154 AttributeType typeTmpDirectory = getSchema().getAttributeType(ATTR_IMPORT_TMP_DIRECTORY); 155 156 ArrayList<String> ldifFilestmp = asListOfStrings(taskEntry, typeLdifFile); 157 ldifFiles = new ArrayList<>(ldifFilestmp.size()); 158 for (String s : ldifFilestmp) 159 { 160 File f = new File (s); 161 if (!f.isAbsolute()) 162 { 163 f = new File(DirectoryServer.getInstanceRoot(), s); 164 try 165 { 166 s = f.getCanonicalPath(); 167 } 168 catch (Exception ex) 169 { 170 s = f.getAbsolutePath(); 171 } 172 } 173 if (!f.canRead()) { 174 LocalizableMessage message = ERR_LDIFIMPORT_LDIF_FILE_DOESNT_EXIST.get(s); 175 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 176 } 177 ldifFiles.add(s); 178 } 179 180 templateFile = asString(taskEntry, typeTemplateFile); 181 if (templateFile != null) 182 { 183 File f = new File(templateFile); 184 if (!f.isAbsolute()) 185 { 186 templateFile = new File(DirectoryServer.getInstanceRoot(), templateFile).getAbsolutePath(); 187 } 188 } 189 190 tmpDirectory = asString(taskEntry, typeTmpDirectory); 191 backendID = asString(taskEntry, typeBackendID); 192 includeBranchStrings = asListOfStrings(taskEntry, typeIncludeBranch); 193 excludeBranchStrings = asListOfStrings(taskEntry, typeExcludeBranch); 194 includeAttributeStrings = asListOfStrings(taskEntry, typeIncludeAttribute); 195 excludeAttributeStrings = asListOfStrings(taskEntry, typeExcludeAttribute); 196 includeFilterStrings = asListOfStrings(taskEntry, typeIncludeFilter); 197 excludeFilterStrings = asListOfStrings(taskEntry, typeExcludeFilter); 198 rejectFile = asString(taskEntry, typeRejectFile); 199 skipFile = asString(taskEntry, typeSkipFile); 200 overwrite = asBoolean(taskEntry, typeOverwrite); 201 skipSchemaValidation = asBoolean(taskEntry, typeSkipSchemaValidation); 202 isCompressed = asBoolean(taskEntry, typeIsCompressed); 203 isEncrypted = asBoolean(taskEntry, typeIsEncrypted); 204 clearBackend = asBoolean(taskEntry, typeClearBackend); 205 randomSeed = asInt(taskEntry, typeRandomSeed); 206 threadCount = asInt(taskEntry, typeThreadCount); 207 208 // Make sure that either the "includeBranchStrings" argument or the 209 // "backendID" argument was provided. 210 if(includeBranchStrings.isEmpty() && backendID == null) 211 { 212 LocalizableMessage message = ERR_LDIFIMPORT_MISSING_BACKEND_ARGUMENT.get( 213 typeIncludeBranch.getNameOrOID(), typeBackendID.getNameOrOID()); 214 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 215 } 216 217 Backend<?> backend = null; 218 ArrayList<DN> defaultIncludeBranches; 219 HashSet<DN> excludeBranches = new HashSet<>(excludeBranchStrings.size()); 220 HashSet<DN> includeBranches = new HashSet<>(includeBranchStrings.size()); 221 222 for (String s : includeBranchStrings) 223 { 224 DN includeBranch; 225 try 226 { 227 includeBranch = DN.valueOf(s); 228 } 229 catch (Exception e) 230 { 231 LocalizableMessage message = ERR_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE.get( 232 s, getExceptionMessage(e)); 233 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 234 } 235 236 includeBranches.add(includeBranch); 237 } 238 for (String s : excludeBranchStrings) 239 { 240 DN excludeBranch; 241 try 242 { 243 excludeBranch = DN.valueOf(s); 244 } 245 catch (Exception e) 246 { 247 LocalizableMessage message = ERR_LDIFIMPORT_CANNOT_DECODE_EXCLUDE_BASE.get( 248 s, getExceptionMessage(e)); 249 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 250 } 251 252 excludeBranches.add(excludeBranch); 253 } 254 255 for (String filterString : excludeFilterStrings) 256 { 257 try 258 { 259 SearchFilter.createFilterFromString(filterString); 260 } 261 catch (DirectoryException de) 262 { 263 LocalizableMessage message = ERR_LDIFIMPORT_CANNOT_PARSE_EXCLUDE_FILTER.get( 264 filterString, de.getMessageObject()); 265 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 266 } 267 } 268 269 for (String filterString : includeFilterStrings) 270 { 271 try 272 { 273 SearchFilter.createFilterFromString(filterString); 274 } 275 catch (DirectoryException de) 276 { 277 LocalizableMessage message = ERR_LDIFIMPORT_CANNOT_PARSE_INCLUDE_FILTER.get( 278 filterString, de.getMessageObject()); 279 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 280 } 281 } 282 283 if(backendID != null) 284 { 285 backend = DirectoryServer.getBackend(backendID); 286 if (backend == null) 287 { 288 LocalizableMessage message = ERR_LDIFIMPORT_NO_BACKENDS_FOR_ID.get(); 289 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 290 } 291 else if (!backend.supports(BackendOperation.LDIF_IMPORT)) 292 { 293 LocalizableMessage message = ERR_LDIFIMPORT_CANNOT_IMPORT.get(backendID); 294 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 295 } 296 } 297 else 298 { 299 // Find the backend that includes all the branches. 300 for(DN includeBranch : includeBranches) 301 { 302 Backend<?> locatedBackend = DirectoryServer.getBackend(includeBranch); 303 if(locatedBackend != null) 304 { 305 if(backend == null) 306 { 307 backend = locatedBackend; 308 } 309 else if(backend != locatedBackend) 310 { 311 // The include branches span across multiple backends. 312 LocalizableMessage message = ERR_LDIFIMPORT_INVALID_INCLUDE_BASE.get( 313 includeBranch, backend.getBackendID()); 314 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 315 } 316 } 317 else 318 { 319 // The include branch is not associated with any backend. 320 LocalizableMessage message = ERR_NO_BACKENDS_FOR_BASE.get(includeBranch); 321 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 322 } 323 } 324 } 325 326 // Make sure the selected backend will handle all the include branches 327 defaultIncludeBranches = new ArrayList<>(backend.getBaseDNs()); 328 329 for(DN includeBranch : includeBranches) 330 { 331 if (!Backend.handlesEntry(includeBranch, defaultIncludeBranches, excludeBranches)) 332 { 333 LocalizableMessage message = ERR_LDIFIMPORT_INVALID_INCLUDE_BASE.get( 334 includeBranch, backend.getBackendID()); 335 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 336 } 337 } 338 } 339 340 private int asInt(Entry taskEntry, AttributeType attributeType) 341 { 342 final List<Attribute> attrList = taskEntry.getAttribute(attributeType); 343 return TaskUtils.getSingleValueInteger(attrList, 0); 344 } 345 346 private boolean asBoolean(Entry taskEntry, AttributeType attributeType) 347 { 348 final List<Attribute> attrList = taskEntry.getAttribute(attributeType); 349 return TaskUtils.getBoolean(attrList, false); 350 } 351 352 private String asString(Entry taskEntry, AttributeType attributeType) 353 { 354 final List<Attribute> attrList = taskEntry.getAttribute(attributeType); 355 return TaskUtils.getSingleValueString(attrList); 356 } 357 358 private ArrayList<String> asListOfStrings(Entry taskEntry, AttributeType attributeType) 359 { 360 final List<Attribute> attrList = taskEntry.getAttribute(attributeType); 361 return TaskUtils.getMultiValueString(attrList); 362 } 363 364 @Override 365 public void interruptTask(TaskState interruptState, LocalizableMessage interruptReason) 366 { 367 if (TaskState.STOPPED_BY_ADMINISTRATOR.equals(interruptState) && importConfig != null) 368 { 369 addLogMessage(Severity.INFORMATION, TaskMessages.INFO_TASK_STOPPED_BY_ADMIN.get( 370 interruptReason)); 371 setTaskInterruptState(interruptState); 372 importConfig.cancel(); 373 } 374 } 375 376 @Override 377 public boolean isInterruptable() 378 { 379 return true; 380 } 381 382 @Override 383 protected TaskState runTask() 384 { 385 // See if there were any user-defined sets of include/exclude attributes or 386 // filters. If so, then process them. 387 HashSet<AttributeType> excludeAttributes = toAttributeTypes(excludeAttributeStrings); 388 HashSet<AttributeType> includeAttributes = toAttributeTypes(includeAttributeStrings); 389 390 ArrayList<SearchFilter> excludeFilters = new ArrayList<>(excludeFilterStrings.size()); 391 for (String filterString : excludeFilterStrings) 392 { 393 try 394 { 395 excludeFilters.add(SearchFilter.createFilterFromString(filterString)); 396 } 397 catch (DirectoryException de) 398 { 399 logger.error(ERR_LDIFIMPORT_CANNOT_PARSE_EXCLUDE_FILTER, filterString, de.getMessageObject()); 400 return TaskState.STOPPED_BY_ERROR; 401 } 402 } 403 404 ArrayList<SearchFilter> includeFilters = new ArrayList<>(includeFilterStrings.size()); 405 for (String filterString : includeFilterStrings) 406 { 407 try 408 { 409 includeFilters.add(SearchFilter.createFilterFromString(filterString)); 410 } 411 catch (DirectoryException de) 412 { 413 logger.error(ERR_LDIFIMPORT_CANNOT_PARSE_INCLUDE_FILTER, filterString, de.getMessageObject()); 414 return TaskState.STOPPED_BY_ERROR; 415 } 416 } 417 418 // Get the backend into which the LDIF should be imported. 419 Backend<?> backend = null; 420 HashSet<DN> defaultIncludeBranches; 421 HashSet<DN> excludeBranches = new HashSet<>(excludeBranchStrings.size()); 422 HashSet<DN> includeBranches = new HashSet<>(includeBranchStrings.size()); 423 424 for (String s : includeBranchStrings) 425 { 426 DN includeBranch; 427 try 428 { 429 includeBranch = DN.valueOf(s); 430 } 431 catch (Exception e) 432 { 433 logger.error(ERR_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE, s, getExceptionMessage(e)); 434 return TaskState.STOPPED_BY_ERROR; 435 } 436 437 includeBranches.add(includeBranch); 438 } 439 440 if(backendID != null) 441 { 442 backend = DirectoryServer.getBackend(backendID); 443 444 if (backend == null) 445 { 446 logger.error(ERR_LDIFIMPORT_NO_BACKENDS_FOR_ID); 447 return TaskState.STOPPED_BY_ERROR; 448 } 449 else if (!backend.supports(BackendOperation.LDIF_IMPORT)) 450 { 451 logger.error(ERR_LDIFIMPORT_CANNOT_IMPORT, backendID); 452 return TaskState.STOPPED_BY_ERROR; 453 } 454 } 455 else 456 { 457 // Find the backend that includes all the branches. 458 for(DN includeBranch : includeBranches) 459 { 460 Backend<?> locatedBackend = DirectoryServer.getBackend(includeBranch); 461 if(locatedBackend != null) 462 { 463 if(backend == null) 464 { 465 backend = locatedBackend; 466 } 467 else if(backend != locatedBackend) 468 { 469 // The include branches span across multiple backends. 470 logger.error(ERR_LDIFIMPORT_INVALID_INCLUDE_BASE, includeBranch, backend.getBackendID()); 471 return TaskState.STOPPED_BY_ERROR; 472 } 473 } 474 } 475 } 476 477 // Find backends with subordinate base DNs that should be excluded from the import. 478 defaultIncludeBranches = new HashSet<>(backend.getBaseDNs()); 479 480 if (backend.getSubordinateBackends() != null) 481 { 482 for (Backend<?> subBackend : backend.getSubordinateBackends()) 483 { 484 for (DN baseDN : subBackend.getBaseDNs()) 485 { 486 for (DN importBase : defaultIncludeBranches) 487 { 488 if (!baseDN.equals(importBase) && baseDN.isSubordinateOrEqualTo(importBase)) 489 { 490 excludeBranches.add(baseDN); 491 break; 492 } 493 } 494 } 495 } 496 } 497 498 for (String s : excludeBranchStrings) 499 { 500 DN excludeBranch; 501 try 502 { 503 excludeBranch = DN.valueOf(s); 504 } 505 catch (Exception e) 506 { 507 logger.error(ERR_LDIFIMPORT_CANNOT_DECODE_EXCLUDE_BASE, s, getExceptionMessage(e)); 508 return TaskState.STOPPED_BY_ERROR; 509 } 510 511 excludeBranches.add(excludeBranch); 512 } 513 514 if (includeBranchStrings.isEmpty()) 515 { 516 includeBranches = defaultIncludeBranches; 517 } 518 else 519 { 520 // Make sure the selected backend will handle all the include branches 521 for (DN includeBranch : includeBranches) 522 { 523 if (! Backend.handlesEntry(includeBranch, defaultIncludeBranches, 524 excludeBranches)) 525 { 526 logger.error(ERR_LDIFIMPORT_INVALID_INCLUDE_BASE, includeBranch, backend.getBackendID()); 527 return TaskState.STOPPED_BY_ERROR; 528 } 529 } 530 } 531 532 // Create the LDIF import configuration to use when reading the LDIF. 533 if (templateFile != null) 534 { 535 Random random; 536 try 537 { 538 random = new Random(randomSeed); 539 } 540 catch (Exception e) 541 { 542 random = new Random(); 543 } 544 545 String resourcePath = DirectoryServer.getInstanceRoot() + File.separator + 546 PATH_MAKELDIF_RESOURCE_DIR; 547 TemplateFile tf = new TemplateFile(resourcePath, random); 548 549 ArrayList<LocalizableMessage> warnings = new ArrayList<>(); 550 try 551 { 552 tf.parse(templateFile, warnings); 553 } 554 catch (Exception e) 555 { 556 logger.error(ERR_LDIFIMPORT_CANNOT_PARSE_TEMPLATE_FILE, templateFile, e.getMessage()); 557 return TaskState.STOPPED_BY_ERROR; 558 } 559 560 importConfig = new LDIFImportConfig(tf); 561 } 562 else 563 { 564 ArrayList<String> fileList = new ArrayList<>(ldifFiles); 565 importConfig = new LDIFImportConfig(fileList); 566 } 567 if(tmpDirectory == null) 568 { 569 tmpDirectory = "import-tmp"; 570 } 571 importConfig.setCompressed(isCompressed); 572 importConfig.setEncrypted(isEncrypted); 573 importConfig.setClearBackend(clearBackend); 574 importConfig.setExcludeAttributes(excludeAttributes); 575 importConfig.setExcludeBranches(excludeBranches); 576 importConfig.setExcludeFilters(excludeFilters); 577 importConfig.setIncludeAttributes(includeAttributes); 578 importConfig.setIncludeBranches(includeBranches); 579 importConfig.setIncludeFilters(includeFilters); 580 importConfig.setValidateSchema(!skipSchemaValidation); 581 importConfig.setTmpDirectory(tmpDirectory); 582 importConfig.setThreadCount(threadCount); 583 584 // FIXME -- Should this be conditional? 585 importConfig.setInvokeImportPlugins(true); 586 587 if (rejectFile != null) 588 { 589 try 590 { 591 ExistingFileBehavior existingBehavior = 592 overwrite ? ExistingFileBehavior.OVERWRITE : ExistingFileBehavior.APPEND; 593 594 importConfig.writeRejectedEntries(rejectFile, existingBehavior); 595 } 596 catch (Exception e) 597 { 598 logger.error(ERR_LDIFIMPORT_CANNOT_OPEN_REJECTS_FILE, rejectFile, getExceptionMessage(e)); 599 return TaskState.STOPPED_BY_ERROR; 600 } 601 } 602 603 if (skipFile != null) 604 { 605 try 606 { 607 ExistingFileBehavior existingBehavior = 608 overwrite ? ExistingFileBehavior.OVERWRITE : ExistingFileBehavior.APPEND; 609 importConfig.writeSkippedEntries(skipFile, existingBehavior); 610 } 611 catch (Exception e) 612 { 613 logger.error(ERR_LDIFIMPORT_CANNOT_OPEN_SKIP_FILE, skipFile, getExceptionMessage(e)); 614 return TaskState.STOPPED_BY_ERROR; 615 } 616 } 617 618 // Notify the task listeners that an import is going to start 619 // this must be done before disabling the backend to allow 620 // listeners to get access to the backend configuration 621 // and to take appropriate actions. 622 DirectoryServer.notifyImportBeginning(backend, importConfig); 623 624 // Disable the backend. 625 try 626 { 627 TaskUtils.disableBackend(backend.getBackendID()); 628 } 629 catch (DirectoryException e) 630 { 631 logger.traceException(e); 632 633 logger.error(e.getMessageObject()); 634 return TaskState.STOPPED_BY_ERROR; 635 } 636 637 try 638 { 639 // Acquire an exclusive lock for the backend. 640 try 641 { 642 String lockFile = LockFileManager.getBackendLockFileName(backend); 643 StringBuilder failureReason = new StringBuilder(); 644 if (! LockFileManager.acquireExclusiveLock(lockFile, failureReason)) 645 { 646 logger.error(ERR_LDIFIMPORT_CANNOT_LOCK_BACKEND, backend.getBackendID(), failureReason); 647 return TaskState.STOPPED_BY_ERROR; 648 } 649 } 650 catch (Exception e) 651 { 652 logger.traceException(e); 653 654 logger.error(ERR_LDIFIMPORT_CANNOT_LOCK_BACKEND, backend.getBackendID(), getExceptionMessage(e)); 655 return TaskState.STOPPED_BY_ERROR; 656 } 657 658 // Launch the import. 659 try 660 { 661 backend.importLDIF(importConfig, DirectoryServer.getInstance().getServerContext()); 662 } 663 catch (DirectoryException de) 664 { 665 logger.traceException(de); 666 667 DirectoryServer.notifyImportEnded(backend, importConfig, false); 668 logger.error(ERR_LDIFIMPORT_ERROR_DURING_IMPORT.get(de.getMessageObject())); 669 return TaskState.STOPPED_BY_ERROR; 670 } 671 catch (Exception e) 672 { 673 logger.traceException(e); 674 675 DirectoryServer.notifyImportEnded(backend, importConfig, false); 676 logger.error(ERR_LDIFIMPORT_ERROR_DURING_IMPORT, getExceptionMessage(e)); 677 return TaskState.STOPPED_BY_ERROR; 678 } 679 finally 680 { 681 // Release the exclusive lock on the backend. 682 try 683 { 684 String lockFile = LockFileManager.getBackendLockFileName(backend); 685 StringBuilder failureReason = new StringBuilder(); 686 if (! LockFileManager.releaseLock(lockFile, failureReason)) 687 { 688 logger.warn(WARN_LDIFIMPORT_CANNOT_UNLOCK_BACKEND, backend.getBackendID(), failureReason); 689 return TaskState.COMPLETED_WITH_ERRORS; 690 } 691 } 692 catch (Exception e) 693 { 694 logger.traceException(e); 695 696 logger.warn(WARN_LDIFIMPORT_CANNOT_UNLOCK_BACKEND, backend.getBackendID(), getExceptionMessage(e)); 697 return TaskState.COMPLETED_WITH_ERRORS; 698 } 699 } 700 } 701 finally 702 { 703 // Enable the backend. 704 try 705 { 706 TaskUtils.enableBackend(backend.getBackendID()); 707 // It is necessary to retrieve the backend structure again 708 // because disabling and enabling it again may have resulted 709 // in a new backend being registered to the server. 710 backend = DirectoryServer.getBackend(backend.getBackendID()); 711 } 712 catch (DirectoryException e) 713 { 714 logger.traceException(e); 715 716 logger.error(e.getMessageObject()); 717 return TaskState.STOPPED_BY_ERROR; 718 } 719 DirectoryServer.notifyImportEnded(backend, importConfig, true); 720 } 721 722 // Clean up after the import by closing the import config. 723 importConfig.close(); 724 return getFinalTaskState(); 725 } 726 727 private HashSet<AttributeType> toAttributeTypes(ArrayList<String> attrNames) 728 { 729 final HashSet<AttributeType> attrTypes = new HashSet<>(attrNames.size()); 730 for (String attrName : attrNames) 731 { 732 attrTypes.add(DirectoryServer.getSchema().getAttributeType(attrName)); 733 } 734 return attrTypes; 735 } 736}