/*
|
* CDDL HEADER START
|
*
|
* The contents of this file are subject to the terms of the
|
* Common Development and Distribution License, Version 1.0 only
|
* (the "License"). You may not use this file except in compliance
|
* with the License.
|
*
|
* You can obtain a copy of the license at
|
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
|
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
|
* See the License for the specific language governing permissions
|
* and limitations under the License.
|
*
|
* When distributing Covered Code, include this CDDL HEADER in each
|
* file and include the License file at
|
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
|
* add the following below this CDDL HEADER, with the fields enclosed
|
* by brackets "[]" replaced with your own identifying information:
|
* Portions Copyright [yyyy] [name of copyright owner]
|
*
|
* CDDL HEADER END
|
*
|
*
|
* Copyright 2006-2008 Sun Microsystems, Inc.
|
*/
|
package org.opends.server.tasks;
|
import org.opends.messages.Message;
|
import org.opends.messages.TaskMessages;
|
|
import static org.opends.messages.TaskMessages.*;
|
import static org.opends.messages.ToolMessages.*;
|
import static org.opends.server.loggers.debug.DebugLogger.*;
|
import org.opends.server.loggers.debug.DebugTracer;
|
import org.opends.server.types.DebugLogLevel;
|
import static org.opends.server.util.StaticUtils.*;
|
import static org.opends.server.config.ConfigConstants.*;
|
import static org.opends.server.core.DirectoryServer.getAttributeType;
|
|
import org.opends.server.backends.task.Task;
|
import org.opends.server.backends.task.TaskState;
|
import org.opends.server.core.DirectoryServer;
|
import org.opends.server.core.LockFileManager;
|
import org.opends.server.api.Backend;
|
import org.opends.server.api.ClientConnection;
|
import org.opends.server.types.Attribute;
|
import org.opends.server.types.AttributeType;
|
import org.opends.server.types.DirectoryException;
|
import org.opends.server.types.DN;
|
import org.opends.server.types.Entry;
|
|
|
import org.opends.server.types.ExistingFileBehavior;
|
import org.opends.server.types.LDIFImportConfig;
|
import org.opends.server.types.Operation;
|
import org.opends.server.types.Privilege;
|
import org.opends.server.types.ResultCode;
|
import org.opends.server.types.SearchFilter;
|
|
import java.util.HashSet;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.HashMap;
|
|
/**
|
* This class provides an implementation of a Directory Server task that can
|
* be used to import data from an LDIF file into a backend.
|
*/
|
public class ImportTask extends Task
|
{
|
/**
|
* The tracer object for the debug logger.
|
*/
|
private static final DebugTracer TRACER = getTracer();
|
|
|
/**
|
* Stores mapping between configuration attribute name and its label.
|
*/
|
static private Map<String,Message> argDisplayMap =
|
new HashMap<String,Message>();
|
|
static {
|
argDisplayMap.put(
|
ATTR_IMPORT_LDIF_FILE,
|
INFO_IMPORT_ARG_LDIF_FILE.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_APPEND,
|
INFO_IMPORT_ARG_APPEND.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_REPLACE_EXISTING,
|
INFO_IMPORT_ARG_REPLACE_EXISTING.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_BACKEND_ID,
|
INFO_IMPORT_ARG_BACKEND_ID.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_INCLUDE_BRANCH,
|
INFO_IMPORT_ARG_INCL_BRANCH.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_EXCLUDE_BRANCH,
|
INFO_IMPORT_ARG_EXCL_BRANCH.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_INCLUDE_ATTRIBUTE,
|
INFO_IMPORT_ARG_INCL_ATTR.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_EXCLUDE_ATTRIBUTE,
|
INFO_IMPORT_ARG_EXCL_ATTR.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_INCLUDE_FILTER,
|
INFO_IMPORT_ARG_INCL_FILTER.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_EXCLUDE_FILTER,
|
INFO_IMPORT_ARG_EXCL_FILTER.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_REJECT_FILE,
|
INFO_IMPORT_ARG_REJECT_FILE.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_SKIP_FILE,
|
INFO_IMPORT_ARG_SKIP_FILE.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_OVERWRITE,
|
INFO_IMPORT_ARG_OVERWRITE.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_SKIP_SCHEMA_VALIDATION,
|
INFO_IMPORT_ARG_SKIP_SCHEMA_VALIDATION.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_IS_COMPRESSED,
|
INFO_IMPORT_ARG_IS_COMPRESSED.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_IS_ENCRYPTED,
|
INFO_IMPORT_ARG_IS_ENCRYPTED.get());
|
|
argDisplayMap.put(
|
ATTR_IMPORT_CLEAR_BACKEND,
|
INFO_IMPORT_ARG_CLEAR_BACKEND.get());
|
}
|
|
|
boolean append = false;
|
boolean isCompressed = false;
|
boolean isEncrypted = false;
|
boolean overwrite = false;
|
boolean replaceExisting = false;
|
boolean skipSchemaValidation = false;
|
boolean clearBackend = false;
|
String backendID = null;
|
String rejectFile = null;
|
String skipFile = null;
|
ArrayList<String> excludeAttributeStrings = null;
|
ArrayList<String> excludeBranchStrings = null;
|
ArrayList<String> excludeFilterStrings = null;
|
ArrayList<String> includeAttributeStrings = null;
|
ArrayList<String> includeBranchStrings = null;
|
ArrayList<String> includeFilterStrings = null;
|
ArrayList<String> ldifFiles = null;
|
|
private LDIFImportConfig importConfig;
|
|
/**
|
* {@inheritDoc}
|
*/
|
public Message getDisplayName() {
|
return INFO_TASK_IMPORT_NAME.get();
|
}
|
|
/**
|
* {@inheritDoc}
|
*/
|
public Message getAttributeDisplayName(String name) {
|
return argDisplayMap.get(name);
|
}
|
|
/**
|
* {@inheritDoc}
|
*/
|
@Override public void initializeTask() throws DirectoryException
|
{
|
// If the client connection is available, then make sure the associated
|
// client has the LDIF_IMPORT privilege.
|
Operation operation = getOperation();
|
if (operation != null)
|
{
|
ClientConnection clientConnection = operation.getClientConnection();
|
if (! clientConnection.hasPrivilege(Privilege.LDIF_IMPORT, operation))
|
{
|
Message message = ERR_TASK_LDIFIMPORT_INSUFFICIENT_PRIVILEGES.get();
|
throw new DirectoryException(ResultCode.INSUFFICIENT_ACCESS_RIGHTS,
|
message);
|
}
|
}
|
|
|
Entry taskEntry = getTaskEntry();
|
|
AttributeType typeLdifFile;
|
AttributeType typeAppend;
|
AttributeType typeReplaceExisting;
|
AttributeType typeBackendID;
|
AttributeType typeIncludeBranch;
|
AttributeType typeExcludeBranch;
|
AttributeType typeIncludeAttribute;
|
AttributeType typeExcludeAttribute;
|
AttributeType typeIncludeFilter;
|
AttributeType typeExcludeFilter;
|
AttributeType typeRejectFile;
|
AttributeType typeSkipFile;
|
AttributeType typeOverwrite;
|
AttributeType typeSkipSchemaValidation;
|
AttributeType typeIsCompressed;
|
AttributeType typeIsEncrypted;
|
AttributeType typeClearBackend;
|
|
typeLdifFile =
|
getAttributeType(ATTR_IMPORT_LDIF_FILE, true);
|
typeAppend =
|
getAttributeType(ATTR_IMPORT_APPEND, true);
|
typeReplaceExisting =
|
getAttributeType(ATTR_IMPORT_REPLACE_EXISTING, true);
|
typeBackendID =
|
getAttributeType(ATTR_IMPORT_BACKEND_ID, true);
|
typeIncludeBranch =
|
getAttributeType(ATTR_IMPORT_INCLUDE_BRANCH, true);
|
typeExcludeBranch =
|
getAttributeType(ATTR_IMPORT_EXCLUDE_BRANCH, true);
|
typeIncludeAttribute =
|
getAttributeType(ATTR_IMPORT_INCLUDE_ATTRIBUTE, true);
|
typeExcludeAttribute =
|
getAttributeType(ATTR_IMPORT_EXCLUDE_ATTRIBUTE, true);
|
typeIncludeFilter =
|
getAttributeType(ATTR_IMPORT_INCLUDE_FILTER, true);
|
typeExcludeFilter =
|
getAttributeType(ATTR_IMPORT_EXCLUDE_FILTER, true);
|
typeRejectFile =
|
getAttributeType(ATTR_IMPORT_REJECT_FILE, true);
|
typeSkipFile =
|
getAttributeType(ATTR_IMPORT_SKIP_FILE, true);
|
typeOverwrite =
|
getAttributeType(ATTR_IMPORT_OVERWRITE, true);
|
typeSkipSchemaValidation =
|
getAttributeType(ATTR_IMPORT_SKIP_SCHEMA_VALIDATION, true);
|
typeIsCompressed =
|
getAttributeType(ATTR_IMPORT_IS_COMPRESSED, true);
|
typeIsEncrypted =
|
getAttributeType(ATTR_IMPORT_IS_ENCRYPTED, true);
|
typeClearBackend =
|
getAttributeType(ATTR_IMPORT_CLEAR_BACKEND, true);
|
|
List<Attribute> attrList;
|
|
attrList = taskEntry.getAttribute(typeLdifFile);
|
ldifFiles = TaskUtils.getMultiValueString(attrList);
|
|
attrList = taskEntry.getAttribute(typeAppend);
|
append = TaskUtils.getBoolean(attrList, false);
|
|
attrList = taskEntry.getAttribute(typeReplaceExisting);
|
replaceExisting = TaskUtils.getBoolean(attrList, false);
|
|
attrList = taskEntry.getAttribute(typeBackendID);
|
backendID = TaskUtils.getSingleValueString(attrList);
|
|
attrList = taskEntry.getAttribute(typeIncludeBranch);
|
includeBranchStrings = TaskUtils.getMultiValueString(attrList);
|
|
attrList = taskEntry.getAttribute(typeExcludeBranch);
|
excludeBranchStrings = TaskUtils.getMultiValueString(attrList);
|
|
attrList = taskEntry.getAttribute(typeIncludeAttribute);
|
includeAttributeStrings = TaskUtils.getMultiValueString(attrList);
|
|
attrList = taskEntry.getAttribute(typeExcludeAttribute);
|
excludeAttributeStrings = TaskUtils.getMultiValueString(attrList);
|
|
attrList = taskEntry.getAttribute(typeIncludeFilter);
|
includeFilterStrings = TaskUtils.getMultiValueString(attrList);
|
|
attrList = taskEntry.getAttribute(typeExcludeFilter);
|
excludeFilterStrings = TaskUtils.getMultiValueString(attrList);
|
|
attrList = taskEntry.getAttribute(typeRejectFile);
|
rejectFile = TaskUtils.getSingleValueString(attrList);
|
|
attrList = taskEntry.getAttribute(typeSkipFile);
|
skipFile = TaskUtils.getSingleValueString(attrList);
|
|
attrList = taskEntry.getAttribute(typeOverwrite);
|
overwrite = TaskUtils.getBoolean(attrList, false);
|
|
attrList = taskEntry.getAttribute(typeSkipSchemaValidation);
|
skipSchemaValidation = TaskUtils.getBoolean(attrList, false);
|
|
attrList = taskEntry.getAttribute(typeIsCompressed);
|
isCompressed = TaskUtils.getBoolean(attrList, false);
|
|
attrList = taskEntry.getAttribute(typeIsEncrypted);
|
isEncrypted = TaskUtils.getBoolean(attrList, false);
|
|
attrList = taskEntry.getAttribute(typeClearBackend);
|
clearBackend = TaskUtils.getBoolean(attrList, false);
|
|
// Make sure that either the "includeBranchStrings" argument or the
|
// "backendID" argument was provided.
|
if(includeBranchStrings.isEmpty() && backendID == null)
|
{
|
Message message = ERR_LDIFIMPORT_MISSING_BACKEND_ARGUMENT.get(
|
typeIncludeBranch.getNameOrOID(), typeBackendID.getNameOrOID());
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
|
}
|
|
Backend backend = null;
|
ArrayList<DN> defaultIncludeBranches;
|
ArrayList<DN> excludeBranches =
|
new ArrayList<DN>(excludeBranchStrings.size());
|
ArrayList<DN> includeBranches =
|
new ArrayList<DN>(includeBranchStrings.size());
|
|
for (String s : includeBranchStrings)
|
{
|
DN includeBranch;
|
try
|
{
|
includeBranch = DN.decode(s);
|
}
|
catch (DirectoryException de)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE.get(
|
s, de.getMessageObject());
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
|
}
|
catch (Exception e)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE.get(
|
s, getExceptionMessage(e));
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
|
}
|
|
if(! includeBranches.contains(includeBranch))
|
{
|
includeBranches.add(includeBranch);
|
}
|
}
|
for (String s : excludeBranchStrings)
|
{
|
DN excludeBranch;
|
try
|
{
|
excludeBranch = DN.decode(s);
|
}
|
catch (DirectoryException de)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_DECODE_EXCLUDE_BASE.get(
|
s, de.getMessageObject());
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
|
}
|
catch (Exception e)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_DECODE_EXCLUDE_BASE.get(
|
s, getExceptionMessage(e));
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
|
}
|
|
if (! excludeBranches.contains(excludeBranch))
|
{
|
excludeBranches.add(excludeBranch);
|
}
|
}
|
|
for (String filterString : excludeFilterStrings)
|
{
|
try
|
{
|
SearchFilter.createFilterFromString(filterString);
|
}
|
catch (DirectoryException de)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_PARSE_EXCLUDE_FILTER.get(
|
filterString, de.getMessageObject());
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
|
}
|
}
|
|
for (String filterString : includeFilterStrings)
|
{
|
try
|
{
|
SearchFilter.createFilterFromString(filterString);
|
}
|
catch (DirectoryException de)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_PARSE_INCLUDE_FILTER.get(
|
filterString, de.getMessageObject());
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
|
}
|
}
|
|
if(backendID != null)
|
{
|
backend = DirectoryServer.getBackend(backendID);
|
if (backend == null)
|
{
|
Message message = ERR_LDIFIMPORT_NO_BACKENDS_FOR_ID.get();
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
|
}
|
else if (! backend.supportsLDIFImport())
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_IMPORT.get(backendID);
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
|
}
|
// Make sure that if the "backendID" argument was provided, no include
|
// base was included, and the "append" ption was not provided, the
|
// "clearBackend" argument was also provided if there are more then one
|
// baseDNs for the backend being imported.
|
else if(!append && includeBranchStrings.isEmpty() &&
|
backend.getBaseDNs().length > 1 && !clearBackend)
|
{
|
StringBuilder builder = new StringBuilder();
|
for(DN dn : backend.getBaseDNs())
|
{
|
builder.append(dn.toNormalizedString());
|
builder.append(" ");
|
}
|
Message message = ERR_LDIFIMPORT_MISSING_CLEAR_BACKEND.get(
|
builder.toString(), typeClearBackend.getNameOrOID());
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
|
}
|
}
|
else
|
{
|
// Find the backend that includes all the branches.
|
for(DN includeBranch : includeBranches)
|
{
|
Backend locatedBackend = DirectoryServer.getBackend(includeBranch);
|
if(locatedBackend != null)
|
{
|
if(backend == null)
|
{
|
backend = locatedBackend;
|
}
|
else if(backend != locatedBackend)
|
{
|
// The include branches span across multiple backends.
|
Message message = ERR_LDIFIMPORT_INVALID_INCLUDE_BASE.get(
|
includeBranch.toNormalizedString(), backend.getBackendID());
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
|
message);
|
}
|
}
|
}
|
}
|
|
// Make sure the selected backend will handle all the include branches
|
defaultIncludeBranches = new ArrayList<DN>(backend.getBaseDNs().length);
|
for (DN dn : backend.getBaseDNs())
|
{
|
defaultIncludeBranches.add(dn);
|
}
|
|
for(DN includeBranch : includeBranches)
|
{
|
if (! Backend.handlesEntry(includeBranch, defaultIncludeBranches,
|
excludeBranches))
|
{
|
Message message = ERR_LDIFIMPORT_INVALID_INCLUDE_BASE.get(
|
includeBranch.toNormalizedString(), backend.getBackendID());
|
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
|
}
|
}
|
}
|
|
|
/**
|
* {@inheritDoc}
|
*/
|
public void interruptTask(TaskState interruptState, Message interruptReason)
|
{
|
if (TaskState.STOPPED_BY_ADMINISTRATOR.equals(interruptState) &&
|
importConfig != null)
|
{
|
addLogMessage(TaskMessages.INFO_TASK_STOPPED_BY_ADMIN.get(
|
interruptReason));
|
setTaskInterruptState(interruptState);
|
importConfig.cancel();
|
}
|
}
|
|
|
/**
|
* {@inheritDoc}
|
*/
|
public boolean isInterruptable()
|
{
|
return true;
|
}
|
|
|
/**
|
* {@inheritDoc}
|
*/
|
protected TaskState runTask()
|
{
|
// See if there were any user-defined sets of include/exclude attributes or
|
// filters. If so, then process them.
|
HashSet<AttributeType> excludeAttributes =
|
new HashSet<AttributeType>(excludeAttributeStrings.size());
|
for (String attrName : excludeAttributeStrings)
|
{
|
String lowerName = attrName.toLowerCase();
|
AttributeType attrType = DirectoryServer.getAttributeType(lowerName);
|
if (attrType == null)
|
{
|
attrType = DirectoryServer.getDefaultAttributeType(attrName);
|
}
|
|
excludeAttributes.add(attrType);
|
}
|
|
HashSet<AttributeType> includeAttributes =
|
new HashSet<AttributeType>(includeAttributeStrings.size());
|
for (String attrName : includeAttributeStrings)
|
{
|
String lowerName = attrName.toLowerCase();
|
AttributeType attrType = DirectoryServer.getAttributeType(lowerName);
|
if (attrType == null)
|
{
|
attrType = DirectoryServer.getDefaultAttributeType(attrName);
|
}
|
|
includeAttributes.add(attrType);
|
}
|
|
ArrayList<SearchFilter> excludeFilters =
|
new ArrayList<SearchFilter>(excludeFilterStrings.size());
|
for (String filterString : excludeFilterStrings)
|
{
|
try
|
{
|
excludeFilters.add(SearchFilter.createFilterFromString(filterString));
|
}
|
catch (DirectoryException de)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_PARSE_EXCLUDE_FILTER.get(
|
filterString, de.getMessageObject());
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
}
|
|
ArrayList<SearchFilter> includeFilters =
|
new ArrayList<SearchFilter>(includeFilterStrings.size());
|
for (String filterString : includeFilterStrings)
|
{
|
try
|
{
|
includeFilters.add(SearchFilter.createFilterFromString(filterString));
|
}
|
catch (DirectoryException de)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_PARSE_INCLUDE_FILTER.get(
|
filterString, de.getMessageObject());
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
}
|
|
|
// Get the backend into which the LDIF should be imported.
|
Backend backend = null;
|
ArrayList<DN> defaultIncludeBranches;
|
ArrayList<DN> excludeBranches =
|
new ArrayList<DN>(excludeBranchStrings.size());
|
ArrayList<DN> includeBranches =
|
new ArrayList<DN>(includeBranchStrings.size());
|
|
for (String s : includeBranchStrings)
|
{
|
DN includeBranch;
|
try
|
{
|
includeBranch = DN.decode(s);
|
}
|
catch (DirectoryException de)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE.get(
|
s, de.getMessageObject());
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
catch (Exception e)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE.get(
|
s, getExceptionMessage(e));
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
|
if(! includeBranches.contains(includeBranch))
|
{
|
includeBranches.add(includeBranch);
|
}
|
}
|
|
if(backendID != null)
|
{
|
backend = DirectoryServer.getBackend(backendID);
|
|
if (backend == null)
|
{
|
Message message = ERR_LDIFIMPORT_NO_BACKENDS_FOR_ID.get();
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
else if (! backend.supportsLDIFImport())
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_IMPORT.get(backendID);
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
// Make sure that if the "backendID" argument was provided, no include
|
// base was included, and the "append" ption was not provided, the
|
// "clearBackend" argument was also provided if there are more then one
|
// baseDNs for the backend being imported.
|
else if(!append && includeBranches.isEmpty() &&
|
backend.getBaseDNs().length > 1 && !clearBackend)
|
{
|
StringBuilder builder = new StringBuilder();
|
builder.append(backend.getBaseDNs()[0].toNormalizedString());
|
for(int i = 1; i < backend.getBaseDNs().length; i++)
|
{
|
builder.append(" / ");
|
builder.append(backend.getBaseDNs()[i].toNormalizedString());
|
}
|
Message message = ERR_LDIFIMPORT_MISSING_CLEAR_BACKEND.get(
|
builder.toString(), ATTR_IMPORT_CLEAR_BACKEND);
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
}
|
else
|
{
|
// Find the backend that includes all the branches.
|
for(DN includeBranch : includeBranches)
|
{
|
Backend locatedBackend = DirectoryServer.getBackend(includeBranch);
|
if(locatedBackend != null)
|
{
|
if(backend == null)
|
{
|
backend = locatedBackend;
|
}
|
else if(backend != locatedBackend)
|
{
|
// The include branches span across multiple backends.
|
Message message = ERR_LDIFIMPORT_INVALID_INCLUDE_BASE.get(
|
includeBranch.toNormalizedString(), backend.getBackendID());
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
}
|
}
|
}
|
|
// Find backends with subordinate base DNs that should be excluded from the
|
// import.
|
|
defaultIncludeBranches = new ArrayList<DN>(backend.getBaseDNs().length);
|
for (DN dn : backend.getBaseDNs())
|
{
|
defaultIncludeBranches.add(dn);
|
}
|
|
if (backend.getSubordinateBackends() != null)
|
{
|
for (Backend subBackend : backend.getSubordinateBackends())
|
{
|
for (DN baseDN : subBackend.getBaseDNs())
|
{
|
for (DN importBase : defaultIncludeBranches)
|
{
|
if (baseDN.isDescendantOf(importBase) &&
|
(! baseDN.equals(importBase)))
|
{
|
if (! excludeBranches.contains(baseDN))
|
{
|
excludeBranches.add(baseDN);
|
}
|
|
break;
|
}
|
}
|
}
|
}
|
}
|
|
for (String s : excludeBranchStrings)
|
{
|
DN excludeBranch;
|
try
|
{
|
excludeBranch = DN.decode(s);
|
}
|
catch (DirectoryException de)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_DECODE_EXCLUDE_BASE.get(
|
s, de.getMessageObject());
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
catch (Exception e)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_DECODE_EXCLUDE_BASE.get(
|
s, getExceptionMessage(e));
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
|
if (! excludeBranches.contains(excludeBranch))
|
{
|
excludeBranches.add(excludeBranch);
|
}
|
}
|
|
if (includeBranchStrings.isEmpty())
|
{
|
includeBranches = defaultIncludeBranches;
|
}
|
else
|
{
|
// Make sure the selected backend will handle all the include branches
|
for(DN includeBranch : includeBranches)
|
{
|
if (! Backend.handlesEntry(includeBranch, defaultIncludeBranches,
|
excludeBranches))
|
{
|
Message message = ERR_LDIFIMPORT_INVALID_INCLUDE_BASE.get(
|
includeBranch.toNormalizedString(), backend.getBackendID());
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
}
|
}
|
|
// Create the LDIF import configuration to use when reading the LDIF.
|
ArrayList<String> fileList = new ArrayList<String>(ldifFiles);
|
importConfig = new LDIFImportConfig(fileList);
|
importConfig.setAppendToExistingData(append);
|
importConfig.setReplaceExistingEntries(replaceExisting);
|
importConfig.setCompressed(isCompressed);
|
importConfig.setEncrypted(isEncrypted);
|
importConfig.setClearBackend(clearBackend);
|
importConfig.setExcludeAttributes(excludeAttributes);
|
importConfig.setExcludeBranches(excludeBranches);
|
importConfig.setExcludeFilters(excludeFilters);
|
importConfig.setIncludeAttributes(includeAttributes);
|
importConfig.setIncludeBranches(includeBranches);
|
importConfig.setIncludeFilters(includeFilters);
|
importConfig.setValidateSchema(!skipSchemaValidation);
|
|
// FIXME -- Should this be conditional?
|
importConfig.setInvokeImportPlugins(true);
|
|
if (rejectFile != null)
|
{
|
try
|
{
|
ExistingFileBehavior existingBehavior;
|
if (overwrite)
|
{
|
existingBehavior = ExistingFileBehavior.OVERWRITE;
|
}
|
else
|
{
|
existingBehavior = ExistingFileBehavior.APPEND;
|
}
|
|
importConfig.writeRejectedEntries(rejectFile, existingBehavior);
|
}
|
catch (Exception e)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_OPEN_REJECTS_FILE.get(
|
rejectFile, getExceptionMessage(e));
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
}
|
|
if (skipFile != null)
|
{
|
try
|
{
|
ExistingFileBehavior existingBehavior;
|
if (overwrite)
|
{
|
existingBehavior = ExistingFileBehavior.OVERWRITE;
|
}
|
else
|
{
|
existingBehavior = ExistingFileBehavior.APPEND;
|
}
|
|
importConfig.writeRejectedEntries(skipFile, existingBehavior);
|
}
|
catch (Exception e)
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_OPEN_SKIP_FILE.get(
|
skipFile, getExceptionMessage(e));
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
}
|
|
// Get the set of base DNs for the backend as an array.
|
DN[] baseDNs = new DN[defaultIncludeBranches.size()];
|
defaultIncludeBranches.toArray(baseDNs);
|
|
// Notify the task listeners that an import is going to start
|
// this must be done before disabling the backend to allow
|
// listeners to get access to the backend configuration
|
// and to take appropriate actions.
|
DirectoryServer.notifyImportBeginning(backend, importConfig);
|
|
// Disable the backend.
|
try
|
{
|
TaskUtils.disableBackend(backend.getBackendID());
|
}
|
catch (DirectoryException e)
|
{
|
if (debugEnabled())
|
{
|
TRACER.debugCaught(DebugLogLevel.ERROR, e);
|
}
|
|
logError(e.getMessageObject());
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
|
|
try
|
{
|
// Acquire an exclusive lock for the backend.
|
try
|
{
|
String lockFile = LockFileManager.getBackendLockFileName(backend);
|
StringBuilder failureReason = new StringBuilder();
|
if (! LockFileManager.acquireExclusiveLock(lockFile, failureReason))
|
{
|
Message message = ERR_LDIFIMPORT_CANNOT_LOCK_BACKEND.get(
|
backend.getBackendID(), String.valueOf(failureReason));
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
}
|
catch (Exception e)
|
{
|
if (debugEnabled())
|
{
|
TRACER.debugCaught(DebugLogLevel.ERROR, e);
|
}
|
|
Message message = ERR_LDIFIMPORT_CANNOT_LOCK_BACKEND.get(
|
backend.getBackendID(), getExceptionMessage(e));
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
|
|
// Launch the import.
|
try
|
{
|
backend.importLDIF(importConfig);
|
}
|
catch (DirectoryException de)
|
{
|
if (debugEnabled())
|
{
|
TRACER.debugCaught(DebugLogLevel.ERROR, de);
|
}
|
|
DirectoryServer.notifyImportEnded(backend, importConfig, false);
|
Message message =
|
ERR_LDIFIMPORT_ERROR_DURING_IMPORT.get(de.getMessageObject());
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
catch (Exception e)
|
{
|
if (debugEnabled())
|
{
|
TRACER.debugCaught(DebugLogLevel.ERROR, e);
|
}
|
|
DirectoryServer.notifyImportEnded(backend, importConfig, false);
|
Message message =
|
ERR_LDIFIMPORT_ERROR_DURING_IMPORT.get(getExceptionMessage(e));
|
logError(message);
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
finally
|
{
|
// Release the exclusive lock on the backend.
|
try
|
{
|
String lockFile = LockFileManager.getBackendLockFileName(backend);
|
StringBuilder failureReason = new StringBuilder();
|
if (! LockFileManager.releaseLock(lockFile, failureReason))
|
{
|
Message message = WARN_LDIFIMPORT_CANNOT_UNLOCK_BACKEND.get(
|
backend.getBackendID(), String.valueOf(failureReason));
|
logError(message);
|
return TaskState.COMPLETED_WITH_ERRORS;
|
}
|
}
|
catch (Exception e)
|
{
|
if (debugEnabled())
|
{
|
TRACER.debugCaught(DebugLogLevel.ERROR, e);
|
}
|
|
Message message = WARN_LDIFIMPORT_CANNOT_UNLOCK_BACKEND.get(
|
backend.getBackendID(), getExceptionMessage(e));
|
logError(message);
|
return TaskState.COMPLETED_WITH_ERRORS;
|
}
|
|
}
|
}
|
finally
|
{
|
// Enable the backend.
|
try
|
{
|
TaskUtils.enableBackend(backend.getBackendID());
|
// It is necessary to retrieve the backend structure again
|
// because disabling and enabling it again may have resulted
|
// in a new backend being registered to the server.
|
backend = DirectoryServer.getBackend(backend.getBackendID());
|
}
|
catch (DirectoryException e)
|
{
|
if (debugEnabled())
|
{
|
TRACER.debugCaught(DebugLogLevel.ERROR, e);
|
}
|
|
logError(e.getMessageObject());
|
return TaskState.STOPPED_BY_ERROR;
|
}
|
DirectoryServer.notifyImportEnded(backend, importConfig, true);
|
}
|
|
|
// Clean up after the import by closing the import config.
|
importConfig.close();
|
return getFinalTaskState();
|
}
|
}
|