LDAPSearch.java revision 7e6345b129555b8ed3ec87d83b42a3cc55b66cf1
/*
* 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
* 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-2009 Sun Microsystems, Inc.
*/
/**
* This class provides a tool that can be used to issue search requests to the
* Directory Server.
*/
public class LDAPSearch
{
/**
* The tracer object for the debug logger.
*/
/**
* The fully-qualified name of this class.
*/
// The set of response controls for the search.
// The message ID counter to use for requests.
private AtomicInteger nextMessageID;
// The print stream to use for standard error.
private PrintStream err;
// The print stream to use for standard output.
private PrintStream out;
/**
* Constructor for the LDAPSearch object.
*
* @param nextMessageID The message ID counter to use for requests.
* @param out The print stream to use for standard output.
* @param err The print stream to use for standard error.
*/
{
this.nextMessageID = nextMessageID;
}
/**
* Execute the search based on the specified input parameters.
*
* @param connection The connection to use for the search.
* @param baseDN The base DN for the search request.
* @param filters The filters to use for the results.
* @param attributes The attributes to return in the results.
* @param searchOptions The constraints for the search.
* @param wrapColumn The column at which to wrap long lines.
*
* @return The number of matching entries returned by the server. If there
* were multiple search filters provided, then this will be the
* total number of matching entries for all searches.
*
* @throws IOException If a problem occurs while attempting to communicate
* with the Directory Server.
*
* @throws LDAPException If the Directory Server returns an error response.
*/
int wrapColumn )
throws IOException, LDAPException
{
int matchingEntries = 0;
{
filter, attributes);
if(!searchOptions.showOperations())
{
try
{
byte opType;
do
{
int resultCode = 0;
switch(opType)
{
for (Control c : responseControls)
{
{
try
{
if (previousDN != null)
{
previousDN.toString()));
}
} catch (Exception e) {}
}
{
try
{
{
{
get(timeToExpStr));
}
}
else
{
if (acrc.isInactive())
{
}
{
}
{
{
}
}
{
{
.get(timeToUnlockStr));
}
}
}
} catch (Exception e) {}
}
{
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
}
}
}
break;
break;
{
{
try
{
{
}
}
catch (Exception e)
{
getExceptionMessage(e));
}
}
{
try
{
((LDAPControl) c).getValue());
{
}
else
{
}
}
catch (Exception e)
{
getExceptionMessage(e));
}
}
}
break;
default:
// FIXME - throw exception?
break;
}
if(resultCode != SUCCESS)
{
}
else if (errorMessage != null)
{
}
} while(opType != OP_TYPE_SEARCH_RESULT_DONE);
} catch(ASN1Exception ae)
{
if (debugEnabled())
{
}
}
}
}
{
}
return matchingEntries;
}
/**
* Appends an LDIF representation of the entry to the provided buffer.
*
* @param entry The entry to be written as LDIF.
* @param buffer The buffer to which the entry should be appended.
* @param wrapColumn The column at which long lines should be wrapped.
* @param typesOnly Indicates whether to include only attribute types
* without values.
*/
int wrapColumn, boolean typesOnly)
{
// Add the DN to the buffer.
int colsRemaining;
if (needsBase64Encoding(dnString))
{
}
else
{
}
{
}
else
{
int startPos = colsRemaining;
{
}
{
}
}
// Add the attributes to the buffer.
for (LDAPAttribute a : attributes)
{
if(typesOnly)
{
} else
{
for (ByteString v : a.getValues())
{
if (needsBase64Encoding(v))
{
} else
{
valueString = v.toString();
}
{
} else
{
int startPos = colsRemaining;
{
}
if (startPos < valueLength)
{
}
}
}
}
}
// Make sure to add an extra blank line to ensure that there will be one
// between this entry and the next.
}
/**
* Retrieves the set of response controls included in the last search result
* done message.
*
* @return The set of response controls included in the last search result
* done message.
*/
{
return responseControls;
}
/**
* The main method for LDAPSearch tool.
*
* @param args The command-line arguments provided to this program.
*/
{
if(retCode != 0)
{
}
}
/**
* Parses the provided command-line arguments and uses that information to
* run the ldapsearch tool.
*
* @param args The command-line arguments provided to this program.
*
* @return The error code.
*/
{
}
/**
* Parses the provided command-line arguments and uses that information to
* run the ldapsearch tool.
*
* @param args The command-line arguments provided to this
* program.
* @param initializeServer Indicates whether to initialize the server.
* @param outStream The output stream to use for standard output, or
* <CODE>null</CODE> if standard output is not
* needed.
* @param errStream The output stream to use for standard error, or
* <CODE>null</CODE> if standard error is not
* needed.
*
* @return The error code.
*/
{
}
/**
* Parses the provided command-line arguments and uses that information to
* run the ldapsearch tool.
*
* @param args The command-line arguments provided to this
* program.
* @param initializeServer Indicates whether to initialize the server.
* @param returnMatchingEntries whether when the option --countEntries is
* specified, the number of matching entries should
* be returned or not.
* @param outStream The output stream to use for standard output, or
* <CODE>null</CODE> if standard output is not
* needed.
* @param errStream The output stream to use for standard error, or
* <CODE>null</CODE> if standard error is not
* needed.
*
* @return The error code.
*/
{
{
}
else
{
}
{
}
else
{
}
// Create the command-line argument parser for use with this program.
false, true, 0, 0,
"[filter] [attributes ...]");
try
{
OPTION_LONG_HOST, false, false, true,
null,
OPTION_LONG_PORT, false, false, true,
OPTION_LONG_BINDDN, false, false, true,
false, false, true,
false, false,
OPTION_LONG_BASEDN, true, false, true,
searchScope = new MultiChoiceArgument(
"searchScope", 's', "searchScope", false,
false,
OPTION_LONG_FILENAME, false, false,
null,
saslExternal = new BooleanArgument(
"useSASLExternal", 'r',
"useSASLExternal",
OPTION_LONG_SASLOPTION, false,
true, true,
null,
OPTION_LONG_KEYSTOREPATH, false, false, true,
null,
OPTION_LONG_KEYSTORE_PWD, false, false,
true, INFO_KEYSTORE_PWD_PLACEHOLDER.get(),
new FileBasedArgument("keystorepasswordfile",
false, false,
certNickname = new StringArgument(
"certnickname", OPTION_SHORT_CERT_NICKNAME,
false, false, true,
null,
false, false, true,
null,
new FileBasedArgument(
"truststorepasswordfile",
OPTION_LONG_TRUSTSTORE_PWD_FILE, false, false,
OPTION_LONG_PROXYAUTHID, false,
false, true,
reportAuthzID = new BooleanArgument(
"usepwpolicycontrol", null,
false, false, true,
simplePageSize = new IntegerArgument(
"simplepagesize", null,
"simplePageSize", false, false, true,
false, 0,
assertionFilter = new StringArgument(
"assertionfilter", null,
false, false,
true, INFO_ASSERTION_FILTER_PLACEHOLDER.get(),
"matchedvalues", null,
"matchedValuesFilter", false, true, true,
sortOrder = new StringArgument(
"sortorder", 'S', "sortOrder", false,
new StringArgument(
"vlvdescriptor", 'G', "virtualListView", false,
false, true,
new StringArgument("effectiveRightsUser",
OPTION_LONG_EFFECTIVERIGHTSUSER, false, false, true,
new StringArgument("effectiveRightsAttrs",
OPTION_LONG_EFFECTIVERIGHTSATTR, false, true, true,
OPTION_LONG_PROTOCOL_VERSION, false, false,
true,
false, true,
null,
false, true,
null,
false, true,
null,
false, true,
null,
"dontWrap",
} catch (ArgumentException ae)
{
return CLIENT_SIDE_PARAM_ERROR;
}
// Parse the command-line arguments provided to this program.
try
{
}
catch (ArgumentException ae)
{
return CLIENT_SIDE_PARAM_ERROR;
}
// If we should just display usage or version information,
// then print it and exit.
if (argParser.usageOrVersionDisplayed())
{
return 0;
}
{
// the list of trailing arguments should be structured as follow:
// - If a filter file is present, trailing arguments are considered
// as attributes
// - If filter file is not present, the first trailing argument is
// considered the filter, the other as attributes.
{
try
{
} catch (LDAPException le)
{
if (debugEnabled())
{
}
return CLIENT_SIDE_PARAM_ERROR;
}
}
// The rest are attributes
for(String s : filterAndAttributeStrings)
{
attributes.add(s);
}
}
{
return CLIENT_SIDE_PARAM_ERROR;
}
{
return CLIENT_SIDE_PARAM_ERROR;
}
{
return CLIENT_SIDE_PARAM_ERROR;
}
{
return CLIENT_SIDE_PARAM_ERROR;
}
int portNumber = 389;
try
{
} catch(ArgumentException ae)
{
if (debugEnabled())
{
}
return CLIENT_SIDE_PARAM_ERROR;
}
// Read the LDAP version number.
try
{
{
return CLIENT_SIDE_PARAM_ERROR;
}
} catch(ArgumentException ae)
{
if (debugEnabled())
{
}
return CLIENT_SIDE_PARAM_ERROR;
}
// password policy control.
(!bindPasswordFile.isPresent() &&
{
// read the password from the stdin.
try
{
//As per rfc 4513(section-5.1.2) a client should avoid sending
//an empty password to the server.
{
}
{
if (debugEnabled())
{
}
return CLIENT_SIDE_PARAM_ERROR;
}
}
else if(bindPasswordValue == null)
{
// Read from file if it exists.
}
if (keyStorePassword.isPresent())
{
}
else if (keyStorePasswordFile.isPresent())
{
}
if (trustStorePassword.isPresent())
{
}
else if (trustStorePasswordFile.isPresent())
{
}
try
{
} catch(ArgumentException ex1)
{
return CLIENT_SIDE_PARAM_ERROR;
}
if(val == false)
{
return CLIENT_SIDE_PARAM_ERROR;
}
if(val == false)
{
return CLIENT_SIDE_PARAM_ERROR;
}
if(controlStr.isPresent())
{
{
{
return CLIENT_SIDE_PARAM_ERROR;
}
}
}
if(effectiveRightsUser.isPresent()) {
return CLIENT_SIDE_PARAM_ERROR;
}
}
if (proxyAuthzID.isPresent())
{
new ProxiedAuthV2Control(true,
}
if (pSearchInfo.isPresent())
{
new HashSet<PersistentSearchChangeType>();
boolean changesOnly = true;
boolean returnECs = true;
if (! tokenizer.hasMoreTokens())
{
return CLIENT_SIDE_PARAM_ERROR;
}
else
{
{
return CLIENT_SIDE_PARAM_ERROR;
}
}
if (tokenizer.hasMoreTokens())
{
while (st.hasMoreTokens())
{
{
}
{
}
{
}
{
}
{
}
else
{
return CLIENT_SIDE_PARAM_ERROR;
}
}
}
if (changeTypes.isEmpty())
{
}
if (tokenizer.hasMoreTokens())
{
{
changesOnly = true;
}
{
changesOnly = false;
}
else
{
return CLIENT_SIDE_PARAM_ERROR;
}
}
if (tokenizer.hasMoreTokens())
{
{
returnECs = true;
}
{
returnECs = false;
}
else
{
return CLIENT_SIDE_PARAM_ERROR;
}
}
}
if (assertionFilter.isPresent())
{
try
{
// FIXME -- Change this to the correct OID when the official one is
// assigned.
new LDAPAssertionRequestControl(true, filter);
}
catch (LDAPException le)
{
le.getMessage());
return CLIENT_SIDE_PARAM_ERROR;
}
}
if (matchedValuesFilter.isPresent())
{
new ArrayList<MatchedValuesFilter>();
for (String s : mvFilterStrings)
{
try
{
}
catch (LDAPException le)
{
le.getMessage());
return CLIENT_SIDE_PARAM_ERROR;
}
}
}
{
try
{
}
catch (LDAPException le)
{
le.getErrorMessage());
return CLIENT_SIDE_PARAM_ERROR;
}
}
if (vlvDescriptor.isPresent())
{
{
return CLIENT_SIDE_PARAM_ERROR;
}
if (numTokens == 3)
{
try
{
}
catch (Exception e)
{
return CLIENT_SIDE_PARAM_ERROR;
}
}
else if (numTokens == 4)
{
try
{
contentCount));
}
catch (Exception e)
{
return CLIENT_SIDE_PARAM_ERROR;
}
}
else
{
return CLIENT_SIDE_PARAM_ERROR;
}
}
if (subEntriesArgument.isPresent())
{
new SubentriesControl(true, true);
}
// Set the connection options.
if(saslOptions.isPresent())
{
{
{
if(mechValue == false)
{
return CLIENT_SIDE_PARAM_ERROR;
}
} else
{
if(propValue == false)
{
return CLIENT_SIDE_PARAM_ERROR;
}
}
}
}
{
{
return CLIENT_SIDE_PARAM_ERROR;
}
if(keyStorePathValue == null)
{
return CLIENT_SIDE_PARAM_ERROR;
}
}
// Read the filter strings.
if(fileNameValue != null)
{
try
{
{
{
// ignore empty lines.
continue;
}
}
} catch(Exception e)
{
if (debugEnabled())
{
}
return CLIENT_SIDE_PARAM_ERROR;
}
finally
{
{
try
{
} catch (IOException ioe) {}
}
}
}
{
return CLIENT_SIDE_PARAM_ERROR;
}
int wrapColumn = 80;
{
wrapColumn = 0;
}
try
{
if (initializeServer)
{
// Bootstrap and initialize directory data structures.
}
// Connect to the specified host with the supplied userDN and password.
{
if (certNickname.isPresent())
{
}
else
{
clientAlias = null;
}
sslConnectionFactory = new SSLConnectionFactory();
}
{
// We don't actually need to open a connection or perform the search,
// so we're done. We should return 0 to either mean that the processing
// was successful or that there were no matching entries, based on
// countEntries.isPresent() (but in either case the return value should
// be zero).
return 0;
}
int matchingEntries = 0;
if (simplePageSize.isPresent())
{
{
}
while (true)
{
boolean responseFound = false;
for (Control c : responseControls)
{
{
try
{
responseFound = true;
break;
}
catch (DirectoryException de)
{
throw new LDAPException(
}
}
}
if (! responseFound)
{
}
{
break;
}
}
}
else
{
}
{
return matchingEntries;
}
else
{
return 0;
}
} catch(LDAPException le)
{
{
}
else
{
if (debugEnabled())
{
}
}
return code;
} catch(LDAPConnectionException lce)
{
if (debugEnabled())
{
}
lce.getResultCode(),
lce.getMatchedDN());
return code;
} catch(Exception e)
{
if (debugEnabled())
{
}
return 1;
} finally
{
if(connection != null)
{
if (ldapSearch == null)
{
}
else
{
}
}
}
}
}