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 2008-2017 UnboundID Corp.
* All Rights Reserved.
*/
/*
* Copyright (C) 2008-2017 UnboundID Corp.
*
* 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.ldap.sdk.examples;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List;
import com.unboundid.ldap.sdk.Control;
import com.unboundid.ldap.sdk.LDAPConnection;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.ldap.sdk.Version;
import com.unboundid.ldif.LDIFChangeRecord;
import com.unboundid.ldif.LDIFException;
import com.unboundid.ldif.LDIFReader;
import com.unboundid.util.LDAPCommandLineTool;
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.ControlArgument;
import com.unboundid.util.args.FileArgument;
/**
* This class provides a simple tool that can be used to perform add, delete,
* modify, and modify DN operations against an LDAP directory server. The
* changes to apply can be read either from standard input or from an LDIF file.
*
* Some of the APIs demonstrated by this example include:
*
*
Argument Parsing (from the {@code com.unboundid.util.args}
* package)
*
LDAP Command-Line Tool (from the {@code com.unboundid.util}
* package)
*
LDIF Processing (from the {@code com.unboundid.ldif} package)
*
*
* The behavior of this utility is controlled by command line arguments.
* Supported arguments include those allowed by the {@link LDAPCommandLineTool}
* class, as well as the following additional arguments:
*
*
"-f {path}" or "--ldifFile {path}" -- specifies the path to the LDIF
* file containing the changes to apply. If this is not provided, then
* changes will be read from standard input.
*
"-a" or "--defaultAdd" -- indicates that any LDIF records encountered
* that do not include a changetype should be treated as add change
* records. If this is not provided, then such records will be
* rejected.
*
"-c" or "--continueOnError" -- indicates that processing should
* continue if an error occurs while processing an earlier change. If
* this is not provided, then the command will exit on the first error
* that occurs.
*
"--bindControl {control}" -- specifies a control that should be
* included in the bind request sent by this tool before performing any
* update operations.
*
*/
@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
public final class LDAPModify
extends LDAPCommandLineTool
implements Serializable
{
/**
* The serial version UID for this serializable class.
*/
private static final long serialVersionUID = -2602159836108416722L;
// Indicates whether processing should continue even if an error has occurred.
private BooleanArgument continueOnError;
// Indicates whether LDIF records without a changetype should be considered
// add records.
private BooleanArgument defaultAdd;
// The argument used to specify any bind controls that should be used.
private ControlArgument bindControls;
// The LDIF file to be processed.
private FileArgument ldifFile;
/**
* Parse the provided command line arguments and make the appropriate set of
* changes.
*
* @param args The command line arguments provided to this program.
*/
public static void main(final String[] args)
{
final ResultCode resultCode = main(args, System.out, System.err);
if (resultCode != ResultCode.SUCCESS)
{
System.exit(resultCode.intValue());
}
}
/**
* Parse the provided command line arguments and make the appropriate set of
* changes.
*
* @param args The command line arguments provided to this program.
* @param outStream The output stream to which standard out should be
* written. It may be {@code null} if output should be
* suppressed.
* @param errStream The output stream to which standard error should be
* written. It may be {@code null} if error messages
* should be suppressed.
*
* @return A result code indicating whether the processing was successful.
*/
public static ResultCode main(final String[] args,
final OutputStream outStream,
final OutputStream errStream)
{
final LDAPModify ldapModify = new LDAPModify(outStream, errStream);
return ldapModify.runTool(args);
}
/**
* Creates a new instance of this tool.
*
* @param outStream The output stream to which standard out should be
* written. It may be {@code null} if output should be
* suppressed.
* @param errStream The output stream to which standard error should be
* written. It may be {@code null} if error messages
* should be suppressed.
*/
public LDAPModify(final OutputStream outStream, final OutputStream errStream)
{
super(outStream, errStream);
}
/**
* Retrieves the name for this tool.
*
* @return The name for this tool.
*/
@Override()
public String getToolName()
{
return "ldapmodify";
}
/**
* Retrieves the description for this tool.
*
* @return The description for this tool.
*/
@Override()
public String getToolDescription()
{
return "Perform add, delete, modify, and modify " +
"DN operations in an LDAP directory server.";
}
/**
* Retrieves the version string for this tool.
*
* @return The version string for this tool.
*/
@Override()
public String getToolVersion()
{
return Version.NUMERIC_VERSION_STRING;
}
/**
* Indicates whether this tool should provide support for an interactive mode,
* in which the tool offers a mode in which the arguments can be provided in
* a text-driven menu rather than requiring them to be given on the command
* line. If interactive mode is supported, it may be invoked using the
* "--interactive" argument. Alternately, if interactive mode is supported
* and {@link #defaultsToInteractiveMode()} returns {@code true}, then
* interactive mode may be invoked by simply launching the tool without any
* arguments.
*
* @return {@code true} if this tool supports interactive mode, or
* {@code false} if not.
*/
@Override()
public boolean supportsInteractiveMode()
{
return true;
}
/**
* Indicates whether this tool defaults to launching in interactive mode if
* the tool is invoked without any command-line arguments. This will only be
* used if {@link #supportsInteractiveMode()} returns {@code true}.
*
* @return {@code true} if this tool defaults to using interactive mode if
* launched without any command-line arguments, or {@code false} if
* not.
*/
@Override()
public boolean defaultsToInteractiveMode()
{
return true;
}
/**
* Indicates whether this tool should provide arguments for redirecting output
* to a file. If this method returns {@code true}, then the tool will offer
* an "--outputFile" argument that will specify the path to a file to which
* all standard output and standard error content will be written, and it will
* also offer a "--teeToStandardOut" argument that can only be used if the
* "--outputFile" argument is present and will cause all output to be written
* to both the specified output file and to standard output.
*
* @return {@code true} if this tool should provide arguments for redirecting
* output to a file, or {@code false} if not.
*/
@Override()
protected boolean supportsOutputFile()
{
return true;
}
/**
* Indicates whether this tool should default to interactively prompting for
* the bind password if a password is required but no argument was provided
* to indicate how to get the password.
*
* @return {@code true} if this tool should default to interactively
* prompting for the bind password, or {@code false} if not.
*/
@Override()
protected boolean defaultToPromptForBindPassword()
{
return true;
}
/**
* Indicates whether this tool supports the use of a properties file for
* specifying default values for arguments that aren't specified on the
* command line.
*
* @return {@code true} if this tool supports the use of a properties file
* for specifying default values for arguments that aren't specified
* on the command line, or {@code false} if not.
*/
@Override()
public boolean supportsPropertiesFile()
{
return true;
}
/**
* Indicates whether the LDAP-specific arguments should include alternate
* versions of all long identifiers that consist of multiple words so that
* they are available in both camelCase and dash-separated versions.
*
* @return {@code true} if this tool should provide multiple versions of
* long identifiers for LDAP-specific arguments, or {@code false} if
* not.
*/
@Override()
protected boolean includeAlternateLongIdentifiers()
{
return true;
}
/**
* Adds the arguments used by this program that aren't already provided by the
* generic {@code LDAPCommandLineTool} framework.
*
* @param parser The argument parser to which the arguments should be added.
*
* @throws ArgumentException If a problem occurs while adding the arguments.
*/
@Override()
public void addNonLDAPArguments(final ArgumentParser parser)
throws ArgumentException
{
String description = "Treat LDIF records that do not contain a " +
"changetype as add records.";
defaultAdd = new BooleanArgument('a', "defaultAdd", description);
defaultAdd.addLongIdentifier("default-add");
parser.addArgument(defaultAdd);
description = "Attempt to continue processing additional changes if " +
"an error occurs.";
continueOnError = new BooleanArgument('c', "continueOnError",
description);
continueOnError.addLongIdentifier("continue-on-error");
parser.addArgument(continueOnError);
description = "The path to the LDIF file containing the changes. If " +
"this is not provided, then the changes will be read from " +
"standard input.";
ldifFile = new FileArgument('f', "ldifFile", false, 1, "{path}",
description, true, false, true, false);
ldifFile.addLongIdentifier("ldif-file");
parser.addArgument(ldifFile);
description = "Information about a control to include in the bind request.";
bindControls = new ControlArgument(null, "bindControl", false, 0, null,
description);
bindControls.addLongIdentifier("bind-control");
parser.addArgument(bindControls);
}
/**
* {@inheritDoc}
*/
@Override()
protected List getBindControls()
{
return bindControls.getValues();
}
/**
* Performs the actual processing for this tool. In this case, it gets a
* connection to the directory server and uses it to perform the requested
* operations.
*
* @return The result code for the processing that was performed.
*/
@Override()
public ResultCode doToolProcessing()
{
// Set up the LDIF reader that will be used to read the changes to apply.
final LDIFReader ldifReader;
try
{
if (ldifFile.isPresent())
{
// An LDIF file was specified on the command line, so we will use it.
ldifReader = new LDIFReader(ldifFile.getValue());
}
else
{
// No LDIF file was specified, so we will read from standard input.
ldifReader = new LDIFReader(System.in);
}
}
catch (IOException ioe)
{
err("I/O error creating the LDIF reader: ", ioe.getMessage());
return ResultCode.LOCAL_ERROR;
}
// Get the connection to the directory server.
final LDAPConnection connection;
try
{
connection = getConnection();
out("Connected to ", connection.getConnectedAddress(), ':',
connection.getConnectedPort());
}
catch (LDAPException le)
{
err("Error connecting to the directory server: ", le.getMessage());
return le.getResultCode();
}
// Attempt to process and apply the changes to the server.
ResultCode resultCode = ResultCode.SUCCESS;
while (true)
{
// Read the next change to process.
final LDIFChangeRecord changeRecord;
try
{
changeRecord = ldifReader.readChangeRecord(defaultAdd.isPresent());
}
catch (LDIFException le)
{
err("Malformed change record: ", le.getMessage());
if (! le.mayContinueReading())
{
err("Unable to continue processing the LDIF content.");
resultCode = ResultCode.DECODING_ERROR;
break;
}
else if (! continueOnError.isPresent())
{
resultCode = ResultCode.DECODING_ERROR;
break;
}
else
{
// We can try to keep processing, so do so.
continue;
}
}
catch (IOException ioe)
{
err("I/O error encountered while reading a change record: ",
ioe.getMessage());
resultCode = ResultCode.LOCAL_ERROR;
break;
}
// If the change record was null, then it means there are no more changes
// to be processed.
if (changeRecord == null)
{
break;
}
// Apply the target change to the server.
try
{
out("Processing ", changeRecord.getChangeType().toString(),
" operation for ", changeRecord.getDN());
changeRecord.processChange(connection);
out("Success");
out();
}
catch (LDAPException le)
{
err("Error: ", le.getMessage());
err("Result Code: ", le.getResultCode().intValue(), " (",
le.getResultCode().getName(), ')');
if (le.getMatchedDN() != null)
{
err("Matched DN: ", le.getMatchedDN());
}
if (le.getReferralURLs() != null)
{
for (final String url : le.getReferralURLs())
{
err("Referral URL: ", url);
}
}
err();
if (! continueOnError.isPresent())
{
resultCode = le.getResultCode();
break;
}
}
}
// Close the connection to the directory server and exit.
connection.close();
out("Disconnected from the server");
return resultCode;
}
/**
* {@inheritDoc}
*/
@Override()
public LinkedHashMap getExampleUsages()
{
final LinkedHashMap examples =
new LinkedHashMap();
String[] args =
{
"--hostname", "server.example.com",
"--port", "389",
"--bindDN", "uid=admin,dc=example,dc=com",
"--bindPassword", "password",
"--ldifFile", "changes.ldif"
};
String description =
"Attempt to apply the add, delete, modify, and/or modify DN " +
"operations contained in the 'changes.ldif' file against the " +
"specified directory server.";
examples.put(args, description);
args = new String[]
{
"--hostname", "server.example.com",
"--port", "389",
"--bindDN", "uid=admin,dc=example,dc=com",
"--bindPassword", "password",
"--continueOnError",
"--defaultAdd"
};
description =
"Establish a connection to the specified directory server and then " +
"wait for information about the add, delete, modify, and/or modify " +
"DN operations to perform to be provided via standard input. If " +
"any invalid operations are requested, then the tool will display " +
"an error message but will continue running. Any LDIF record " +
"provided which does not include a 'changeType' line will be " +
"treated as an add request.";
examples.put(args, description);
return examples;
}
}