Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2020-2021 Ping Identity Corporation
* All Rights Reserved.
*/
/*
* Copyright 2020-2021 Ping Identity Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright (C) 2020-2021 Ping Identity Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (GPLv2 only)
* or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
package com.unboundid.ldif;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.zip.GZIPOutputStream;
import com.unboundid.ldap.listener.SearchEntryParer;
import com.unboundid.ldap.sdk.DN;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.Filter;
import com.unboundid.ldap.sdk.InternalSDKHelper;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPURL;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.ldap.sdk.SearchResultEntry;
import com.unboundid.ldap.sdk.SearchScope;
import com.unboundid.ldap.sdk.Version;
import com.unboundid.ldap.sdk.schema.EntryValidator;
import com.unboundid.ldap.sdk.schema.Schema;
import com.unboundid.ldap.sdk.unboundidds.tools.ColumnBasedLDAPResultWriter;
import com.unboundid.ldap.sdk.unboundidds.tools.DNsOnlyLDAPResultWriter;
import com.unboundid.ldap.sdk.unboundidds.tools.JSONLDAPResultWriter;
import com.unboundid.ldap.sdk.unboundidds.tools.LDAPResultWriter;
import com.unboundid.ldap.sdk.unboundidds.tools.LDIFLDAPResultWriter;
import com.unboundid.ldap.sdk.unboundidds.tools.ToolUtils;
import com.unboundid.ldap.sdk.unboundidds.tools.ValuesOnlyLDAPResultWriter;
import com.unboundid.util.CommandLineTool;
import com.unboundid.util.Debug;
import com.unboundid.util.NotNull;
import com.unboundid.util.Nullable;
import com.unboundid.util.ObjectPair;
import com.unboundid.util.OutputFormat;
import com.unboundid.util.PassphraseEncryptedOutputStream;
import com.unboundid.util.StaticUtils;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
import com.unboundid.util.args.ArgumentException;
import com.unboundid.util.args.ArgumentParser;
import com.unboundid.util.args.BooleanArgument;
import com.unboundid.util.args.DNArgument;
import com.unboundid.util.args.FileArgument;
import com.unboundid.util.args.IntegerArgument;
import com.unboundid.util.args.ScopeArgument;
import com.unboundid.util.args.StringArgument;
import static com.unboundid.ldif.LDIFMessages.*;
/**
* This class provides a command-line tool that can be used to search for
* entries matching a given set of criteria in an LDIF file.
*/
@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
public final class LDIFSearch
extends CommandLineTool
{
/**
* The server root directory for the Ping Identity Directory Server (or
* related Ping Identity server product) that contains this tool, if
* applicable.
*/
@Nullable private static final File PING_SERVER_ROOT =
InternalSDKHelper.getPingIdentityServerRoot();
/**
* Indicates whether the tool is running as part of a Ping Identity Directory
* Server (or related Ping Identity Server Product) installation.
*/
private static final boolean PING_SERVER_AVAILABLE =
(PING_SERVER_ROOT != null);
/**
* The column at which to wrap long lines.
*/
private static final int WRAP_COLUMN = StaticUtils.TERMINAL_WIDTH_COLUMNS - 1;
// The argument parser for this tool.
@Nullable private volatile ArgumentParser parser;
// The completion message for this tool.
@NotNull private final AtomicReference completionMessage;
// Indicates whether the LDIF encryption passphrase file has been read.
private volatile boolean ldifEncryptionPassphraseFileRead;
// Encryption passphrases used thus far.
@NotNull private final List inputEncryptionPassphrases;
// The list of LDAP URLs to use when processing searches, mapped to the
// corresponding search entry parers.
@NotNull private final List searchURLs;
// The LDAP result writer for this tool.
@NotNull private volatile LDAPResultWriter resultWriter;
// The command-line arguments supported by this tool.
@Nullable private BooleanArgument checkSchema;
@Nullable private BooleanArgument compressOutput;
@Nullable private BooleanArgument doNotWrap;
@Nullable private BooleanArgument encryptOutput;
@Nullable private BooleanArgument isCompressed;
@Nullable private BooleanArgument overwriteExistingOutputFile;
@Nullable private BooleanArgument separateOutputFilePerSearch;
@Nullable private BooleanArgument stripTrailingSpaces;
@Nullable private DNArgument baseDN;
@Nullable private FileArgument filterFile;
@Nullable private FileArgument ldapURLFile;
@Nullable private FileArgument ldifEncryptionPassphraseFile;
@Nullable private FileArgument ldifFile;
@Nullable private FileArgument outputFile;
@Nullable private FileArgument outputEncryptionPassphraseFile;
@Nullable private FileArgument schemaPath;
@Nullable private IntegerArgument sizeLimit;
@Nullable private IntegerArgument timeLimitSeconds;
@Nullable private IntegerArgument wrapColumn;
@Nullable private ScopeArgument scope;
@Nullable private StringArgument outputFormat = null;
/**
* Invokes this tool with the provided set of command-line arguments.
*
* @param args The set of arguments provided to this tool. It may be
* empty but must not be {@code null}.
*/
public static void main(@NotNull final String... args)
{
final ResultCode resultCode = main(System.out, System.err, args);
if (resultCode != ResultCode.SUCCESS)
{
System.exit(resultCode.intValue());
}
}
/**
* Invokes this tool with the provided set of command-line arguments, using
* the given output and error streams.
*
* @param out The output stream to use for standard output. It may be
* {@code null} if standard output should be suppressed.
* @param err The output stream to use for standard error. It may be
* {@code null} if standard error should be suppressed.
* @param args The set of arguments provided to this tool. It may be
* empty but must not be {@code null}.
*
* @return A result code indicating the status of processing. Any result
* code other than {@link ResultCode#SUCCESS} should be considered
* an error.
*/
@NotNull()
public static ResultCode main(@Nullable final OutputStream out,
@Nullable final OutputStream err,
@NotNull final String... args)
{
final LDIFSearch tool = new LDIFSearch(out, err);
return tool.runTool(args);
}
/**
* Creates a new instance of this tool with the provided output and error
* streams.
*
* @param out The output stream to use for standard output. It may be
* {@code null} if standard output should be suppressed.
* @param err The output stream to use for standard error. It may be
* {@code null} if standard error should be suppressed.
*/
public LDIFSearch(@Nullable final OutputStream out,
@Nullable final OutputStream err)
{
super(out, err);
resultWriter = new LDIFLDAPResultWriter(getOut(), WRAP_COLUMN);
parser = null;
completionMessage = new AtomicReference<>();
inputEncryptionPassphrases = new ArrayList<>(5);
searchURLs = new ArrayList<>();
ldifEncryptionPassphraseFileRead = false;
checkSchema = null;
compressOutput = null;
doNotWrap = null;
encryptOutput = null;
isCompressed = null;
overwriteExistingOutputFile = null;
separateOutputFilePerSearch = null;
stripTrailingSpaces = null;
baseDN = null;
filterFile = null;
ldapURLFile = null;
ldifEncryptionPassphraseFile = null;
ldifFile = null;
outputFile = null;
outputFormat = null;
outputEncryptionPassphraseFile = null;
schemaPath = null;
sizeLimit = null;
timeLimitSeconds = null;
wrapColumn = null;
scope = null;
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public String getToolName()
{
return "ldifsearch";
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public String getToolDescription()
{
return INFO_LDIFSEARCH_TOOL_DESCRIPTION.get();
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public String getToolVersion()
{
return Version.NUMERIC_VERSION_STRING;
}
/**
* {@inheritDoc}
*/
@Override()
public int getMinTrailingArguments()
{
return 0;
}
/**
* {@inheritDoc}
*/
@Override()
public int getMaxTrailingArguments()
{
return -1;
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public String getTrailingArgumentsPlaceholder()
{
return INFO_LDIFSEARCH_TRAILING_ARGS_PLACEHOLDER.get();
}
/**
* {@inheritDoc}
*/
@Override()
public boolean supportsInteractiveMode()
{
return true;
}
/**
* {@inheritDoc}
*/
@Override()
public boolean defaultsToInteractiveMode()
{
return true;
}
/**
* {@inheritDoc}
*/
@Override()
public boolean supportsPropertiesFile()
{
return true;
}
/**
* {@inheritDoc}
*/
@Override()
@Nullable()
protected String getToolCompletionMessage()
{
return completionMessage.get();
}
/**
* {@inheritDoc}
*/
@Override()
public void addToolArguments(@NotNull final ArgumentParser parser)
throws ArgumentException
{
this.parser = parser;
ldifFile = new FileArgument('l', "ldifFile", true, 0, null,
INFO_LDIFSEARCH_ARG_DESC_LDIF_FILE.get(), true, true, true, false);
ldifFile.addLongIdentifier("ldif-file", true);
ldifFile.addLongIdentifier("inputFile", true);
ldifFile.addLongIdentifier("input-file", true);
ldifFile.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_INPUT.get());
parser.addArgument(ldifFile);
final String ldifPWDesc;
if (PING_SERVER_AVAILABLE)
{
ldifPWDesc = INFO_LDIFSEARCH_ARG_DESC_LDIF_PW_FILE_PING_SERVER.get();
}
else
{
ldifPWDesc = INFO_LDIFSEARCH_ARG_DESC_LDIF_PW_FILE_STANDALONE.get();
}
ldifEncryptionPassphraseFile = new FileArgument(null,
"ldifEncryptionPassphraseFile", false, 1, null, ldifPWDesc, true,
true, true, false);
ldifEncryptionPassphraseFile.addLongIdentifier(
"ldif-encryption-passphrase-file", true);
ldifEncryptionPassphraseFile.addLongIdentifier("ldifPassphraseFile", true);
ldifEncryptionPassphraseFile.addLongIdentifier("ldif-passphrase-file",
true);
ldifEncryptionPassphraseFile.addLongIdentifier("ldifEncryptionPasswordFile",
true);
ldifEncryptionPassphraseFile.addLongIdentifier(
"ldif-encryption-password-file", true);
ldifEncryptionPassphraseFile.addLongIdentifier("ldifPasswordFile", true);
ldifEncryptionPassphraseFile.addLongIdentifier("ldif-password-file", true);
ldifEncryptionPassphraseFile.addLongIdentifier(
"inputEncryptionPassphraseFile", true);
ldifEncryptionPassphraseFile.addLongIdentifier(
"input-encryption-passphrase-file", true);
ldifEncryptionPassphraseFile.addLongIdentifier("inputPassphraseFile", true);
ldifEncryptionPassphraseFile.addLongIdentifier("input-passphrase-file",
true);
ldifEncryptionPassphraseFile.addLongIdentifier(
"inputEncryptionPasswordFile", true);
ldifEncryptionPassphraseFile.addLongIdentifier(
"input-encryption-password-file", true);
ldifEncryptionPassphraseFile.addLongIdentifier("inputPasswordFile", true);
ldifEncryptionPassphraseFile.addLongIdentifier("input-password-file", true);
ldifEncryptionPassphraseFile.setArgumentGroupName(
INFO_LDIFSEARCH_ARG_GROUP_INPUT.get());
parser.addArgument(ldifEncryptionPassphraseFile);
stripTrailingSpaces = new BooleanArgument(null, "stripTrailingSpaces", 1,
INFO_LDIFSEARCH_ARG_DESC_STRIP_TRAILING_SPACES.get());
stripTrailingSpaces.addLongIdentifier("strip-trailing-spaces", true);
stripTrailingSpaces.addLongIdentifier("ignoreTrailingSpaces", true);
stripTrailingSpaces.addLongIdentifier("ignore-trailing-spaces", true);
stripTrailingSpaces.setArgumentGroupName(
INFO_LDIFSEARCH_ARG_GROUP_INPUT.get());
parser.addArgument(stripTrailingSpaces);
final String schemaPathDesc;
if (PING_SERVER_AVAILABLE)
{
schemaPathDesc = INFO_LDIFSEARCH_ARG_DESC_SCHEMA_PATH_PING_SERVER.get();
}
else
{
schemaPathDesc = INFO_LDIFSEARCH_ARG_DESC_SCHEMA_PATH_STANDALONE.get();
}
schemaPath = new FileArgument(null, "schemaPath", false, 0, null,
schemaPathDesc, true, true, false, false);
schemaPath.addLongIdentifier("schema-path", true);
schemaPath.addLongIdentifier("schemaFile", true);
schemaPath.addLongIdentifier("schema-file", true);
schemaPath.addLongIdentifier("schemaDirectory", true);
schemaPath.addLongIdentifier("schema-directory", true);
schemaPath.addLongIdentifier("schema", true);
schemaPath.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_INPUT.get());
parser.addArgument(schemaPath);
checkSchema = new BooleanArgument(null, "checkSchema", 1,
INFO_LDIFSEARCH_ARG_DESC_CHECK_SCHEMA.get());
checkSchema.addLongIdentifier("check-schema", true);
checkSchema.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_INPUT.get());
parser.addArgument(checkSchema);
isCompressed = new BooleanArgument(null, "isCompressed", 1,
INFO_LDIFSEARCH_ARG_DESC_IS_COMPRESSED.get());
isCompressed.addLongIdentifier("is-compressed", true);
isCompressed.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_INPUT.get());
isCompressed.setHidden(true);
parser.addArgument(isCompressed);
outputFile = new FileArgument('o', "outputFile", false, 1, null,
INFO_LDIFSEARCH_ARG_DESC_OUTPUT_FILE.get(), false, true, true, false);
outputFile.addLongIdentifier("output-file", true);
outputFile.addLongIdentifier("outputLDIF", true);
outputFile.addLongIdentifier("output-ldif", true);
outputFile.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_OUTPUT.get());
parser.addArgument(outputFile);
separateOutputFilePerSearch = new BooleanArgument(null,
"separateOutputFilePerSearch", 1,
INFO_LDIFSEARCH_ARG_DESC_SEPARATE_OUTPUT_FILES.get());
separateOutputFilePerSearch.addLongIdentifier(
"separate-output-file-per-search", true);
separateOutputFilePerSearch.addLongIdentifier("separateOutputFiles", true);
separateOutputFilePerSearch.addLongIdentifier("separate-output-files",
true);
separateOutputFilePerSearch.setArgumentGroupName(
INFO_LDIFSEARCH_ARG_GROUP_OUTPUT.get());
parser.addArgument(separateOutputFilePerSearch);
compressOutput = new BooleanArgument(null, "compressOutput", 1,
INFO_LDIFSEARCH_ARG_DESC_COMPRESS_OUTPUT.get());
compressOutput.addLongIdentifier("compress-output", true);
compressOutput.addLongIdentifier("compressLDIF", true);
compressOutput.addLongIdentifier("compress-ldif", true);
compressOutput.addLongIdentifier("compress", true);
compressOutput.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_OUTPUT.get());
parser.addArgument(compressOutput);
encryptOutput = new BooleanArgument(null, "encryptOutput", 1,
INFO_LDIFSEARCH_ARG_DESC_ENCRYPT_OUTPUT.get());
encryptOutput.addLongIdentifier("encrypt-output", true);
encryptOutput.addLongIdentifier("encryptLDIF", true);
encryptOutput.addLongIdentifier("encrypt-ldif", true);
encryptOutput.addLongIdentifier("encrypt", true);
encryptOutput.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_OUTPUT.get());
parser.addArgument(encryptOutput);
outputEncryptionPassphraseFile = new FileArgument(null,
"outputEncryptionPassphraseFile", false, 1, null,
INFO_LDIFSEARCH_ARG_DESC_OUTPUT_PW_FILE.get(), true, true, true,
false);
outputEncryptionPassphraseFile.addLongIdentifier(
"output-encryption-passphrase-file", true);
outputEncryptionPassphraseFile.addLongIdentifier("outputPassphraseFile",
true);
outputEncryptionPassphraseFile.addLongIdentifier("output-passphrase-file",
true);
outputEncryptionPassphraseFile.addLongIdentifier(
"outputEncryptionPasswordFile", true);
outputEncryptionPassphraseFile.addLongIdentifier(
"output-encryption-password-file", true);
outputEncryptionPassphraseFile.addLongIdentifier("outputPasswordFile",
true);
outputEncryptionPassphraseFile.addLongIdentifier("output-password-file",
true);
outputEncryptionPassphraseFile.addLongIdentifier(
"outputEncryptionPasswordFile", true);
outputEncryptionPassphraseFile.addLongIdentifier(
"output-encryption-password-file", true);
outputEncryptionPassphraseFile.addLongIdentifier("outputPasswordFile",
true);
outputEncryptionPassphraseFile.addLongIdentifier("output-password-file",
true);
outputEncryptionPassphraseFile.setArgumentGroupName(
INFO_LDIFSEARCH_ARG_GROUP_OUTPUT.get());
parser.addArgument(outputEncryptionPassphraseFile);
overwriteExistingOutputFile = new BooleanArgument('O',
"overwriteExistingOutputFile", 1,
INFO_LDIFSEARCH_ARG_DESC_OVERWRITE_EXISTING.get());
overwriteExistingOutputFile.addLongIdentifier(
"overwrite-existing-output-file", true);
overwriteExistingOutputFile.addLongIdentifier(
"overwriteExistingOutputFiles", true);
overwriteExistingOutputFile.addLongIdentifier(
"overwrite-existing-output-files", true);
overwriteExistingOutputFile.addLongIdentifier("overwriteExistingOutput",
true);
overwriteExistingOutputFile.addLongIdentifier("overwrite-existing-output",
true);
overwriteExistingOutputFile.addLongIdentifier("overwriteExisting", true);
overwriteExistingOutputFile.addLongIdentifier("overwrite-existing", true);
overwriteExistingOutputFile.addLongIdentifier("overwrite", true);
overwriteExistingOutputFile.setArgumentGroupName(
INFO_LDIFSEARCH_ARG_GROUP_OUTPUT.get());
parser.addArgument(overwriteExistingOutputFile);
final Set outputFormatAllowedValues = StaticUtils.setOf("ldif",
"json", "csv", "multi-valued-csv", "tab-delimited",
"multi-valued-tab-delimited", "dns-only", "values-only");
outputFormat = new StringArgument(null, "outputFormat", false, 1,
"{ldif|json|csv|multi-valued-csv|tab-delimited|" +
"multi-valued-tab-delimited|dns-only|values-only}",
INFO_LDIFSEARCH_ARG_DESC_OUTPUT_FORMAT.get(),
outputFormatAllowedValues, "ldif");
outputFormat.addLongIdentifier("output-format", true);
outputFormat.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_OUTPUT.get());
parser.addArgument(outputFormat);
wrapColumn = new IntegerArgument(null, "wrapColumn", false, 1, null,
INFO_LDIFSEARCH_ARG_DESC_WRAP_COLUMN.get(), 5, Integer.MAX_VALUE);
wrapColumn.addLongIdentifier("wrap-column", true);
wrapColumn.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_OUTPUT.get());
parser.addArgument(wrapColumn);
doNotWrap = new BooleanArgument('T', "doNotWrap", 1,
INFO_LDIFSEARCH_ARG_DESC_DO_NOT_WRAP.get());
doNotWrap.addLongIdentifier("do-not-wrap", true);
doNotWrap.addLongIdentifier("dontWrap", true);
doNotWrap.addLongIdentifier("dont-wrap", true);
doNotWrap.addLongIdentifier("noWrap", true);
doNotWrap.addLongIdentifier("no-wrap", true);
doNotWrap.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_OUTPUT.get());
parser.addArgument(doNotWrap);
baseDN = new DNArgument('b', "baseDN", false, 1, null,
INFO_LDIFSEARCH_ARG_DESC_BASE_DN.get());
baseDN.addLongIdentifier("base-dn", true);
baseDN.addLongIdentifier("searchBaseDN", true);
baseDN.addLongIdentifier("search-base-dn", true);
baseDN.addLongIdentifier("searchBase", true);
baseDN.addLongIdentifier("search-base", true);
baseDN.addLongIdentifier("base", true);
baseDN.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_CRITERIA.get());
parser.addArgument(baseDN);
scope = new ScopeArgument('s', "scope", false, null,
INFO_LDIFSEARCH_ARG_DESC_SCOPE.get());
scope.addLongIdentifier("searchScope", true);
scope.addLongIdentifier("search-scope", true);
scope.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_CRITERIA.get());
parser.addArgument(scope);
filterFile = new FileArgument('f', "filterFile", false, 0, null,
INFO_LDIFSEARCH_ARG_DESC_FILTER_FILE.get(), true, true, true, false);
filterFile.addLongIdentifier("filter-file", true);
filterFile.addLongIdentifier("filtersFile", true);
filterFile.addLongIdentifier("filters-file", true);
filterFile.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_CRITERIA.get());
parser.addArgument(filterFile);
ldapURLFile = new FileArgument(null, "ldapURLFile", false, 0, null,
INFO_LDIFSEARCH_ARG_DESC_LDAP_URL_FILE.get(), true, true, true, false);
ldapURLFile.addLongIdentifier("ldap-url-file", true);
ldapURLFile.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_CRITERIA.get());
parser.addArgument(ldapURLFile);
sizeLimit = new IntegerArgument('z', "sizeLimit", false, 1, null,
INFO_LDIFSEARCH_ARG_DESC_SIZE_LIMIT.get(), 0, Integer.MAX_VALUE, 0);
sizeLimit.addLongIdentifier("size-limit", true);
sizeLimit.addLongIdentifier("searchSizeLimit", true);
sizeLimit.addLongIdentifier("search-size-limit", true);
sizeLimit.setArgumentGroupName(INFO_LDIFSEARCH_ARG_GROUP_CRITERIA.get());
sizeLimit.setHidden(true);
parser.addArgument(sizeLimit);
timeLimitSeconds = new IntegerArgument('t', "timeLimitSeconds", false, 1,
null, INFO_LDIFSEARCH_ARG_DESC_TIME_LIMIT_SECONDS.get(), 0,
Integer.MAX_VALUE, 0);
timeLimitSeconds.addLongIdentifier("time-limit-seconds", true);
timeLimitSeconds.addLongIdentifier("timeLimit", true);
timeLimitSeconds.setArgumentGroupName(
INFO_LDIFSEARCH_ARG_GROUP_CRITERIA.get());
timeLimitSeconds.setHidden(true);
parser.addArgument(timeLimitSeconds);
parser.addDependentArgumentSet(separateOutputFilePerSearch, outputFile);
parser.addDependentArgumentSet(compressOutput, outputFile);
parser.addDependentArgumentSet(encryptOutput, outputFile);
parser.addDependentArgumentSet(overwriteExistingOutputFile, outputFile);
parser.addDependentArgumentSet(outputEncryptionPassphraseFile,
encryptOutput);
parser.addExclusiveArgumentSet(wrapColumn, doNotWrap);
parser.addExclusiveArgumentSet(baseDN, ldapURLFile);
parser.addExclusiveArgumentSet(scope, ldapURLFile);
parser.addExclusiveArgumentSet(filterFile, ldapURLFile);
parser.addExclusiveArgumentSet(outputFormat, separateOutputFilePerSearch);
}
/**
* {@inheritDoc}
*/
@Override()
public void doExtendedArgumentValidation()
throws ArgumentException
{
// If the output file exists and either compressOutput or encryptOutput is
// present, then the overwrite argument must also be present.
final File outFile = outputFile.getValue();
if ((outFile != null) && outFile.exists() &&
(compressOutput.isPresent() || encryptOutput.isPresent()) &&
(! overwriteExistingOutputFile.isPresent()))
{
throw new ArgumentException(
ERR_LDIFSEARCH_APPEND_WITH_COMPRESSION_OR_ENCRYPTION.get(
compressOutput.getIdentifierString(),
encryptOutput.getIdentifierString(),
overwriteExistingOutputFile.getIdentifierString()));
}
// Create the set of LDAP URLs to use when issuing the searches.
final List trailingArgs = parser.getTrailingArguments();
final List requestedAttributes = new ArrayList<>();
if (filterFile.isPresent())
{
// If there are trailing arguments, then make sure the first one is not a
// valid filter.
if (! trailingArgs.isEmpty())
{
try
{
Filter.create(trailingArgs.get(0));
throw new ArgumentException(
ERR_LDIFSEARCH_FILTER_FILE_WITH_TRAILING_FILTER.get());
}
catch (final LDAPException e)
{
// This was expected.
}
}
requestedAttributes.addAll(trailingArgs);
readFilterFile();
}
else if (ldapURLFile.isPresent())
{
// Make sure there aren't any trailing arguments.
if (! trailingArgs.isEmpty())
{
throw new ArgumentException(
ERR_LDIFSEARCH_LDAP_URL_FILE_WITH_TRAILING_ARGS.get());
}
readLDAPURLFile();
// If there are multiple LDAP URLs, and if they should not be sent to
// separate output files, then they must all have the same set of
// requested attributes.
if ((searchURLs.size() > 1) &&
(! separateOutputFilePerSearch.isPresent()))
{
final Iterator iterator = searchURLs.iterator();
final Set requestedAttrs =
new HashSet<>(Arrays.asList(iterator.next().getAttributes()));
while (iterator.hasNext())
{
final Set attrSet = new HashSet<>(Arrays.asList(
iterator.next().getAttributes()));
if (! requestedAttrs.equals(attrSet))
{
throw new ArgumentException(
ERR_LDIFSEARCH_DIFFERENT_URL_ATTRS_IN_SAME_FILE.get(
ldapURLFile.getIdentifierString(),
separateOutputFilePerSearch.getIdentifierString()));
}
}
}
}
else
{
// Make sure there is at least one trailing argument, and that it's a
// valid filter. If there are any others, then they must be the
// requested arguments.
if (trailingArgs.isEmpty())
{
throw new ArgumentException(ERR_LDIFSEARCH_NO_FILTER.get());
}
final Filter filter;
try
{
final List trailingArgList = new ArrayList<>(trailingArgs);
final Iterator trailingArgIterator = trailingArgList.iterator();
filter = Filter.create(trailingArgIterator.next());
while (trailingArgIterator.hasNext())
{
requestedAttributes.add(trailingArgIterator.next());
}
}
catch (final LDAPException e)
{
Debug.debugException(e);
throw new ArgumentException(
ERR_LDIFSEARCH_FIRST_TRAILING_ARG_NOT_FILTER.get(), e);
}
DN dn = baseDN.getValue();
if (dn == null)
{
dn = DN.NULL_DN;
}
SearchScope searchScope = scope.getValue();
if (searchScope == null)
{
searchScope = SearchScope.SUB;
}
try
{
searchURLs.add(new LDAPURL("ldap", null, null, dn,
requestedAttributes.toArray(StaticUtils.NO_STRINGS),
searchScope, filter));
}
catch (final LDAPException e)
{
Debug.debugException(e);
// This should never happen.
throw new ArgumentException(StaticUtils.getExceptionMessage(e), e);
}
}
// Create the result writer.
final String outputFormatStr =
StaticUtils.toLowerCase(outputFormat.getValue());
if (outputFormatStr.equals("json"))
{
resultWriter = new JSONLDAPResultWriter(getOut());
}
else if (outputFormatStr.equals("csv") ||
outputFormatStr.equals("multi-valued-csv") ||
outputFormatStr.equals("tab-delimited") ||
outputFormatStr.equals("multi-valued-tab-delimited"))
{
// These output formats cannot be used with the --ldapURLFile argument.
if (ldapURLFile.isPresent())
{
throw new ArgumentException(
ERR_LDIFSEARCH_OUTPUT_FORMAT_NOT_SUPPORTED_WITH_URLS.get(
outputFormat.getValue(), ldapURLFile.getIdentifierString()));
}
// These output formats require a set of requested attributes.
if (requestedAttributes.isEmpty())
{
throw new ArgumentException(
ERR_LDIFSEARCH_OUTPUT_FORMAT_REQUIRES_REQUESTED_ATTRS.get(
outputFormat.getValue()));
}
final OutputFormat format;
final boolean includeAllValues;
switch (outputFormatStr)
{
case "multi-valued-csv":
format = OutputFormat.CSV;
includeAllValues = true;
break;
case "tab-delimited":
format = OutputFormat.TAB_DELIMITED_TEXT;
includeAllValues = false;
break;
case "multi-valued-tab-delimited":
format = OutputFormat.TAB_DELIMITED_TEXT;
includeAllValues = true;
break;
case "csv":
default:
format = OutputFormat.CSV;
includeAllValues = false;
break;
}
resultWriter = new ColumnBasedLDAPResultWriter(getOut(),
format, requestedAttributes, WRAP_COLUMN, includeAllValues);
}
else if (outputFormatStr.equals("dns-only"))
{
resultWriter = new DNsOnlyLDAPResultWriter(getOut());
}
else if (outputFormatStr.equals("values-only"))
{
resultWriter = new ValuesOnlyLDAPResultWriter(getOut());
}
else
{
final int wc;
if (doNotWrap.isPresent())
{
wc = Integer.MAX_VALUE;
}
else if (wrapColumn.isPresent())
{
wc = wrapColumn.getValue();
}
else
{
wc = WRAP_COLUMN;
}
resultWriter = new LDIFLDAPResultWriter(getOut(), wc);
}
}
/**
* Uses the contents of any specified filter files, along with the configured
* base DN, scope, and requested attributes, to populate the set of search
* URLs.
*
* @throws ArgumentException If a problem is encountered while constructing
* the search URLs.
*/
private void readFilterFile()
throws ArgumentException
{
DN dn = baseDN.getValue();
if (dn == null)
{
dn = DN.NULL_DN;
}
SearchScope searchScope = scope.getValue();
if (searchScope == null)
{
searchScope = SearchScope.SUB;
}
final String[] requestedAttributes =
parser.getTrailingArguments().toArray(StaticUtils.NO_STRINGS);
for (final File f : filterFile.getValues())
{
final InputStream inputStream;
try
{
inputStream = openInputStream(f);
}
catch (final LDAPException e)
{
Debug.debugException(e);
throw new ArgumentException(e.getMessage(), e);
}
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(inputStream)))
{
while (true)
{
final String line = reader.readLine();
if (line == null)
{
break;
}
if (line.isEmpty() || line.startsWith("#"))
{
continue;
}
try
{
final Filter filter = Filter.create(line.trim());
searchURLs.add(new LDAPURL("ldap", null, null, dn,
requestedAttributes, searchScope, filter));
}
catch (final LDAPException e)
{
Debug.debugException(e);
throw new ArgumentException(
ERR_LDIFSEARCH_FILTER_FILE_INVALID_FILTER.get(line,
f.getAbsolutePath(), e.getMessage()),
e);
}
}
}
catch (final IOException e)
{
Debug.debugException(e);
throw new ArgumentException(
ERR_LDIFSEARCH_ERROR_READING_FILTER_FILE.get(f.getAbsolutePath(),
StaticUtils.getExceptionMessage(e)),
e);
}
finally
{
try
{
inputStream.close();
}
catch (final Exception e)
{
Debug.debugException(e);
}
}
}
if (searchURLs.isEmpty())
{
throw new ArgumentException(ERR_LDIFSEARCH_NO_FILTERS_FROM_FILE.get(
filterFile.getValues().get(0).getAbsolutePath()));
}
}
/**
* Uses the contents of any specified LDAP URL files to populate the set of
* search URLs.
*
* @throws ArgumentException If a problem is encountered while constructing
* the search URLs.
*/
private void readLDAPURLFile()
throws ArgumentException
{
for (final File f : ldapURLFile.getValues())
{
final InputStream inputStream;
try
{
inputStream = openInputStream(f);
}
catch (final LDAPException e)
{
Debug.debugException(e);
throw new ArgumentException(e.getMessage(), e);
}
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(inputStream)))
{
while (true)
{
final String line = reader.readLine();
if (line == null)
{
break;
}
if (line.isEmpty() || line.startsWith("#"))
{
continue;
}
try
{
searchURLs.add(new LDAPURL(line.trim()));
}
catch (final LDAPException e)
{
Debug.debugException(e);
throw new ArgumentException(
ERR_LDIFSEARCH_LDAP_URL_FILE_INVALID_URL.get(line,
f.getAbsolutePath(), e.getMessage()),
e);
}
}
}
catch (final IOException e)
{
Debug.debugException(e);
throw new ArgumentException(
ERR_LDIFSEARCH_ERROR_READING_LDAP_URL_FILE.get(f.getAbsolutePath(),
StaticUtils.getExceptionMessage(e)),
e);
}
finally
{
try
{
inputStream.close();
}
catch (final Exception e)
{
Debug.debugException(e);
}
}
}
if (searchURLs.isEmpty())
{
throw new ArgumentException(ERR_LDIFSEARCH_NO_URLS_FROM_FILE.get(
ldapURLFile.getValues().get(0).getAbsolutePath()));
}
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public ResultCode doToolProcessing()
{
// Get the schema to use when performing LDIF processing.
final Schema schema;
try
{
if (schemaPath.isPresent())
{
schema = getSchema(schemaPath.getValues());
}
else if (PING_SERVER_AVAILABLE)
{
schema = getSchema(Collections.singletonList(StaticUtils.constructPath(
PING_SERVER_ROOT, "config", "schema")));
}
else
{
schema = Schema.getDefaultStandardSchema();
}
}
catch (final Exception e)
{
Debug.debugException(e);
logCompletionMessage(true,
ERR_LDIFSEARCH_CANNOT_GET_SCHEMA.get(
StaticUtils.getExceptionMessage(e)));
return ResultCode.LOCAL_ERROR;
}
// Create search entry parers for all of the search URLs.
final Map urlMap = new LinkedHashMap<>();
for (final LDAPURL url : searchURLs)
{
final SearchEntryParer parer = new SearchEntryParer(
Arrays.asList(url.getAttributes()), schema);
urlMap.put(url, parer);
}
// If we should check schema, then create the entry validator.
final EntryValidator entryValidator;
if (checkSchema.isPresent())
{
entryValidator = new EntryValidator(schema);
}
else
{
entryValidator = null;
}
// Create the output files, if appropriate.
OutputStream outputStream = null;
SearchEntryParer singleParer = null;
final Map separateWriters =
new LinkedHashMap<>();
try
{
if (outputFile.isPresent())
{
final int numURLs = searchURLs.size();
if (separateOutputFilePerSearch.isPresent() && (numURLs > 1))
{
int i=1;
for (final LDAPURL url : searchURLs)
{
final File f = new
File(outputFile.getValue().getAbsolutePath() + '.' + i);
final LDIFSearchSeparateSearchDetails details =
new LDIFSearchSeparateSearchDetails(url, f,
createLDIFWriter(f, url), schema);
separateWriters.put(url, details);
i++;
}
}
else
{
try
{
outputStream = createOutputStream(outputFile.getValue());
resultWriter.updateOutputStream(outputStream);
}
catch (final Exception e)
{
Debug.debugException(e);
throw new LDAPException(ResultCode.LOCAL_ERROR,
ERR_LDIFSEARCH_CANNOT_WRITE_TO_FILE.get(
outputFile.getValue().getAbsolutePath(),
StaticUtils.getExceptionMessage(e)),
e);
}
}
}
// If we're not using separate writers, then write any appropriate header
// to the top of the output.
if (separateWriters.isEmpty())
{
resultWriter.writeHeader();
}
// Iterate through the LDIF files and process the entries they contain.
boolean errorEncountered = false;
final List matchingURLs = new ArrayList<>();
final List entryInvalidReasons = new ArrayList<>();
for (final File f : ldifFile.getValues())
{
final LDIFReader ldifReader;
try
{
ldifReader = new LDIFReader(openInputStream(f));
if (stripTrailingSpaces.isPresent())
{
ldifReader.setTrailingSpaceBehavior(TrailingSpaceBehavior.STRIP);
}
else
{
ldifReader.setTrailingSpaceBehavior(TrailingSpaceBehavior.REJECT);
}
}
catch (final Exception e)
{
Debug.debugException(e);
logCompletionMessage(true,
ERR_LDIFSEARCH_CANNOT_OPEN_LDIF_FILE.get(f.getName(),
StaticUtils.getExceptionMessage(e)));
return ResultCode.LOCAL_ERROR;
}
try
{
while (true)
{
final Entry entry;
try
{
entry = ldifReader.readEntry();
}
catch (final LDIFException e)
{
Debug.debugException(e);
if (e.mayContinueReading())
{
commentToErr(ERR_LDIFSEARCH_RECOVERABLE_READ_ERROR.get(
f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)));
errorEncountered = true;
continue;
}
else
{
logCompletionMessage(true,
ERR_LDIFSEARCH_UNRECOVERABLE_READ_ERROR.get(
f.getAbsolutePath(),
StaticUtils.getExceptionMessage(e)));
return ResultCode.LOCAL_ERROR;
}
}
catch (final Exception e)
{
logCompletionMessage(true,
ERR_LDIFSEARCH_UNRECOVERABLE_READ_ERROR.get(
f.getAbsolutePath(),
StaticUtils.getExceptionMessage(e)));
return ResultCode.LOCAL_ERROR;
}
if (entry == null)
{
break;
}
if (entryValidator != null)
{
entryInvalidReasons.clear();
if (! entryValidator.entryIsValid(entry, entryInvalidReasons))
{
commentToErr(ERR_LDIFSEARCH_ENTRY_VIOLATES_SCHEMA.get(
entry.getDN()));
for (final String invalidReason : entryInvalidReasons)
{
commentToErr("- " + invalidReason);
}
err();
errorEncountered = true;
continue;
}
}
if (separateWriters.isEmpty())
{
matchingURLs.clear();
for (final LDAPURL url : searchURLs)
{
if (urlMatchesEntry(url, entry))
{
matchingURLs.add(url);
}
}
if (matchingURLs.isEmpty())
{
continue;
}
try
{
if (searchURLs.size() > 1)
{
resultWriter.writeComment(
INFO_LDIFSEARCH_ENTRY_MATCHES_URLS.get(entry.getDN()));
for (final LDAPURL url : matchingURLs)
{
resultWriter.writeComment(url.toString());
}
}
if (singleParer == null)
{
singleParer = new SearchEntryParer(
Arrays.asList(searchURLs.get(0).getAttributes()),
schema);
}
resultWriter.writeSearchResultEntry(
new SearchResultEntry(singleParer.pareEntry(entry)));
if (! outputFile.isPresent())
{
resultWriter.flush();
}
}
catch (final Exception e)
{
Debug.debugException(e);
if (outputFile.isPresent())
{
logCompletionMessage(true,
ERR_LDIFSEARCH_WRITE_ERROR_WITH_FILE.get(entry.getDN(),
outputFile.getValue().getAbsolutePath(),
StaticUtils.getExceptionMessage(e)));
}
else
{
logCompletionMessage(true,
ERR_LDIFSEARCH_WRITE_ERROR_NO_FILE.get(entry.getDN(),
StaticUtils.getExceptionMessage(e)));
}
return ResultCode.LOCAL_ERROR;
}
}
else
{
for (final LDIFSearchSeparateSearchDetails details :
separateWriters.values())
{
final LDAPURL url = details.getLDAPURL();
if (urlMatchesEntry(url, entry))
{
try
{
final Entry paredEntry =
details.getSearchEntryParer().pareEntry(entry);
details.getLDIFWriter().writeEntry(paredEntry);
}
catch (final Exception ex)
{
Debug.debugException(ex);
logCompletionMessage(true,
ERR_LDIFSEARCH_WRITE_ERROR_WITH_FILE.get(entry.getDN(),
details.getOutputFile().getAbsolutePath(),
StaticUtils.getExceptionMessage(ex)));
return ResultCode.LOCAL_ERROR;
}
}
}
}
}
}
finally
{
try
{
ldifReader.close();
}
catch (final Exception e)
{
Debug.debugException(e);
}
}
}
if (errorEncountered)
{
logCompletionMessage(true,
WARN_LDIFSEARCH_COMPLETED_WITH_ERRORS.get());
return ResultCode.PARAM_ERROR;
}
else
{
logCompletionMessage(false,
INFO_LDIFSEARCH_COMPLETED_SUCCESSFULLY.get());
return ResultCode.SUCCESS;
}
}
catch (final LDAPException e)
{
Debug.debugException(e);
logCompletionMessage(true, e.getMessage());
return e.getResultCode();
}
finally
{
try
{
resultWriter.flush();
if (outputStream != null)
{
outputStream.close();
}
}
catch (final Exception e)
{
Debug.debugException(e);
}
for (final LDIFSearchSeparateSearchDetails details :
separateWriters.values())
{
try
{
details.getLDIFWriter().close();
}
catch (final Exception e)
{
Debug.debugException(e);
}
}
}
}
/**
* Retrieves the schema contained in the specified paths.
*
* @param paths The paths to use to access the schema.
*
* @return The schema read from the specified files.
*
* @throws Exception If a problem is encountered while loading the schema.
*/
@NotNull()
private static Schema getSchema(@NotNull final List paths)
throws Exception
{
final Set schemaFiles = new LinkedHashSet<>();
for (final File f : paths)
{
if (f.exists())
{
if (f.isFile())
{
schemaFiles.add(f);
}
else if (f.isDirectory())
{
final TreeMap sortedFiles = new TreeMap<>();
for (final File fileInDir : f.listFiles())
{
if (fileInDir.isFile())
{
sortedFiles.put(fileInDir.getName(), fileInDir);
}
}
schemaFiles.addAll(sortedFiles.values());
}
}
}
return Schema.getSchema(new ArrayList<>(schemaFiles));
}
/**
* Opens the input stream to use to read from the specified file.
*
* @param f The file for which to open the input stream. It may optionally
* be compressed and/or encrypted.
*
* @return The input stream that was created.
*
* @throws LDAPException If a problem is encountered while opening the file.
*/
@NotNull()
private InputStream openInputStream(@NotNull final File f)
throws LDAPException
{
if (ldifEncryptionPassphraseFile.isPresent() &&
(! ldifEncryptionPassphraseFileRead))
{
readPassphraseFile(ldifEncryptionPassphraseFile.getValue());
ldifEncryptionPassphraseFileRead = true;
}
boolean closeStream = true;
InputStream inputStream = null;
try
{
inputStream = new FileInputStream(f);
final ObjectPair p =
ToolUtils.getPossiblyPassphraseEncryptedInputStream(
inputStream, inputEncryptionPassphrases,
(! ldifEncryptionPassphraseFile.isPresent()),
INFO_LDIFSEARCH_ENTER_ENCRYPTION_PW.get(f.getName()),
ERR_LDIFSEARCH_WRONG_ENCRYPTION_PW.get(), getOut(), getErr());
inputStream = p.getFirst();
addPassphrase(p.getSecond());
inputStream = ToolUtils.getPossiblyGZIPCompressedInputStream(inputStream);
closeStream = false;
return inputStream;
}
catch (final Exception e)
{
Debug.debugException(e);
throw new LDAPException(ResultCode.LOCAL_ERROR,
ERR_LDIFSEARCH_ERROR_OPENING_INPUT_FILE.get(f.getAbsolutePath(),
StaticUtils.getExceptionMessage(e)),
e);
}
finally
{
if ((inputStream != null) && closeStream)
{
try
{
inputStream.close();
}
catch (final Exception e)
{
Debug.debugException(e);
}
}
}
}
/**
* Reads the contents of the specified passphrase file and adds it to the list
* of passphrases.
*
* @param f The passphrase file to read.
*
* @throws LDAPException If a problem is encountered while trying to read
* the passphrase from the provided file.
*/
private void readPassphraseFile(@NotNull final File f)
throws LDAPException
{
try
{
addPassphrase(getPasswordFileReader().readPassword(f));
}
catch (final Exception e)
{
Debug.debugException(e);
throw new LDAPException(ResultCode.LOCAL_ERROR,
ERR_LDIFSEARCH_CANNOT_READ_PW_FILE.get(f.getAbsolutePath(),
StaticUtils.getExceptionMessage(e)),
e);
}
}
/**
* Updates the list of encryption passphrases with the provided passphrase, if
* it is not already present.
*
* @param passphrase The passphrase to be added. It may optionally be
* {@code null} (in which case no action will be taken).
*/
private void addPassphrase(@Nullable final char[] passphrase)
{
if (passphrase == null)
{
return;
}
for (final char[] existingPassphrase : inputEncryptionPassphrases)
{
if (Arrays.equals(existingPassphrase, passphrase))
{
return;
}
}
inputEncryptionPassphrases.add(passphrase);
}
/**
* Creates an output stream that may be used to write to the specified file.
*
* @param f The file to be written.
*
* @return The output stream that was created.
*
* @throws LDAPException If a problem occurs while creating the output
* stream.
*/
@NotNull()
private OutputStream createOutputStream(@NotNull final File f)
throws LDAPException
{
OutputStream outputStream = null;
boolean closeOutputStream = true;
try
{
try
{
outputStream = new FileOutputStream(f,
(! overwriteExistingOutputFile.isPresent()));
}
catch (final Exception e)
{
Debug.debugException(e);
throw new LDAPException(ResultCode.LOCAL_ERROR,
ERR_LDIFSEARCH_CANNOT_OPEN_OUTPUT_FILE.get(f.getAbsolutePath(),
StaticUtils.getExceptionMessage(e)),
e);
}
if (encryptOutput.isPresent())
{
try
{
final char[] passphrase;
if (outputEncryptionPassphraseFile.isPresent())
{
passphrase = getPasswordFileReader().readPassword(
outputEncryptionPassphraseFile.getValue());
}
else
{
passphrase = ToolUtils.promptForEncryptionPassphrase(false, true,
INFO_LDIFSEARCH_PROMPT_OUTPUT_FILE_ENC_PW.get(),
INFO_LDIFSEARCH_CONFIRM_OUTPUT_FILE_ENC_PW.get(), getOut(),
getErr()).toCharArray();
}
outputStream = new PassphraseEncryptedOutputStream(passphrase,
outputStream, null, true, true);
}
catch (final Exception e)
{
Debug.debugException(e);
throw new LDAPException(ResultCode.LOCAL_ERROR,
ERR_LDIFSEARCH_CANNOT_ENCRYPT_OUTPUT_FILE.get(
StaticUtils.getExceptionMessage(e)),
e);
}
}
if (compressOutput.isPresent())
{
try
{
outputStream = new GZIPOutputStream(outputStream);
}
catch (final Exception e)
{
Debug.debugException(e);
throw new LDAPException(ResultCode.LOCAL_ERROR,
ERR_LDIFSEARCH_CANNOT_COMPRESS_OUTPUT_FILE.get(
f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)),
e);
}
}
closeOutputStream = false;
return outputStream;
}
finally
{
if (closeOutputStream && (outputStream != null))
{
try
{
outputStream.close();
}
catch (final Exception e)
{
Debug.debugException(e);
}
}
}
}
/**
* Creates an LDIF writer to write to the specified file.
*
* @param f The file to be written.
* @param ldapURL The LDAP URL with which the file will be associated. It
* may be {@code null} if the file is shared across multiple
* URLs.
*
* @return The LDIF writer that was created.
*
* @throws LDAPException If a problem occurs while creating the LDIF writer.
*/
@NotNull()
private LDIFWriter createLDIFWriter(@NotNull final File f,
@Nullable final LDAPURL ldapURL)
throws LDAPException
{
boolean closeOutputStream = true;
final OutputStream outputStream = createOutputStream(f);
try
{
final LDIFWriter ldifWriter = new LDIFWriter(outputStream);
if (doNotWrap.isPresent())
{
ldifWriter.setWrapColumn(0);
}
else if (wrapColumn.isPresent())
{
ldifWriter.setWrapColumn(wrapColumn.getValue());
}
else
{
ldifWriter.setWrapColumn(WRAP_COLUMN);
}
if (ldapURL != null)
{
try
{
ldifWriter.writeComment(
INFO_LDIFSEARCH_ENTRIES_MATCHING_URL.get(ldapURL.toString()),
false, true);
}
catch (final Exception e)
{
Debug.debugException(e);
}
}
closeOutputStream = false;
return ldifWriter;
}
finally
{
if (closeOutputStream)
{
try
{
outputStream.close();
}
catch (final Exception e)
{
Debug.debugException(e);
}
}
}
}
/**
* Indicates whether the given entry matches the criteria in the provided LDAP
* URL.
*
* @param url The URL for which to make the determination.
* @param entry The entry for which to make the determination.
*
* @return {@code true} if the entry matches the criteria in the LDAP URL, or
* {@code false} if not.
*/
private boolean urlMatchesEntry(@NotNull final LDAPURL url,
@NotNull final Entry entry)
{
try
{
return (entry.matchesBaseAndScope(url.getBaseDN(), url.getScope()) &&
url.getFilter().matchesEntry(entry));
}
catch (final Exception e)
{
Debug.debugException(e);
return false;
}
}
/**
* Writes a line-wrapped, commented version of the provided message to
* standard output.
*
* @param message The message to be written.
*/
private void commentToOut(@NotNull final String message)
{
getOut().flush();
for (final String line : StaticUtils.wrapLine(message, (WRAP_COLUMN - 2)))
{
out("# " + line);
}
getOut().flush();
}
/**
* Writes a line-wrapped, commented version of the provided message to
* standard error.
*
* @param message The message to be written.
*/
private void commentToErr(@NotNull final String message)
{
getErr().flush();
for (final String line : StaticUtils.wrapLine(message, (WRAP_COLUMN - 2)))
{
err("# " + line);
}
getErr().flush();
}
/**
* Writes the provided message and sets it as the completion message.
*
* @param isError Indicates whether the message should be written to
* standard error rather than standard output.
* @param message The message to be written.
*/
private void logCompletionMessage(final boolean isError,
@NotNull final String message)
{
completionMessage.compareAndSet(null, message);
if (! outputFile.isPresent())
{
resultWriter.writeComment(message);
}
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public LinkedHashMap getExampleUsages()
{
final LinkedHashMap examples = new LinkedHashMap<>();
examples.put(
new String[]
{
"--ldifFile", "data.ldif",
"(uid=jdoe)"
},
INFO_LDIFSEARCH_EXAMPLE_1.get());
examples.put(
new String[]
{
"--ldifFile", "data.ldif",
"--outputFile", "people.ldif",
"--baseDN", "dc=example,dc=com",
"--scope", "sub",
"(objectClass=person)",
"givenName",
"sn",
"cn",
},
INFO_LDIFSEARCH_EXAMPLE_2.get());
return examples;
}
}