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