pjs/directory/java-sdk/tools/LDAPSearch.java

600 строки
18 KiB
Java

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
import java.io.*;
import java.net.*;
import java.util.*;
import netscape.ldap.*;
import netscape.ldap.util.*;
import netscape.ldap.controls.*;
/**
* Execute Search operations through the LDAP client interface.
* This class is implemented based on the LDAP class library.
*
* <pre>
* usage : java LDAPSearch -b baseDN [options] filter [attributes...]
* for example : java LDAPSearch -b "c=us" -h ds.internic.net -p 389
* "(objectClass=*)"
*
* note: '-' or '/' is used to distinct the option field.
* e.g. -a -b /c /d parameter -e parameter
*
* filter:
* Any string in RFC1558 specification.
* e.g. "(objectClass=*)"
*
* attributes: {0..n}
* All the string parameters follows with the filter.
* e.g. filter attrsA attrsB attrsC
* </pre>
*
* @version 1.0
*/
public class LDAPSearch extends LDAPTool {
/**
* This is the main function.
* @param args list of arguments
*/
public static void main(String args[]) {
/* extract parameters from the arguments list */
extractParameters(args);
if (!m_justShow) {
/* perform an LDAP client connection operation */
try {
m_client = new LDAPConnection();
m_client.connect( m_ldaphost, m_ldapport );
} catch(Exception e) {
System.err.println("Error: client connection failed!");
System.exit(0);
}
/* perform an LDAP bind operation */
try {
m_client.authenticate( m_version, m_binddn, m_passwd );
} catch (Exception e) {
System.err.println( e.toString() );
System.exit(0);
}
/* perform a search operation */
dosearch();
m_pw.flush();
m_pw.close();
/* disconnect */
try {
m_client.disconnect();
} catch (Exception e) {
System.err.println( e.toString() );
}
}
System.exit(0);
}
/**
* Prints usage.
*/
private static void doUsage() {
System.err.println("usage: LDAPSearch -b basedn [options] " +
"filter [attributes...]");
System.err.println("options");
System.err.println(" -h host LDAP server name or IP address");
System.err.println(" -p port LDAP server TCP port number");
System.err.println(" -V version LDAP protocol version " +
"number (default is 3)");
System.err.println(" -D binddn bind dn");
System.err.println(" -w password bind passwd (for simple " +
"authentication)");
System.err.println(" -v run in verbose mode");
System.err.println(" -n show what would be done but "+
"don't actually do it");
System.err.println(" -d level set LDAP debugging level " +
"to \'level\'");
System.err.println(" -R do not automatically follow " +
"referrals");
System.err.println(" -O hop limit maximum number of referral " +
"hops to traverse");
System.err.println(" -H display usage information");
System.err.println(" -t write values to files");
System.err.println(" -A retrieve attribute names only");
System.err.println(" -F sep print \'sep\' instead of " +
"\'=\' between attribute names and values");
System.err.println(" -S attr sort the results by attribute " +
"\'attr\'");
System.err.println(" -s scope one of base, one, or sub " +
"(search scope)");
System.err.println(" -a deref one of never, always, search, " +
"or find (alias dereferencing)");
System.err.println(" -l timelimit time limit (in seconds) for " +
"search");
System.err.println(" -T do not fold (wrap) long lines "+
"(default is to fold)");
System.err.println(" -x perform sorting on server");
System.err.println(" -M manage references (treat them "+
"as regular entries)");
System.err.println(" -z sizelimit size limit (in entries) for " +
"search");
System.err.println(" -G before:after:index:count | before:after:value "+
"where 'before' and 'after' are the number of "+
"entries surrounding 'index'. 'count' is the "+
"content count, 'value' is the search value.");
}
/**
* This function is to extract specified parameters from the
* arguments list.
* @param args list of args
*/
protected static void extractParameters(String args[]) {
String privateOpts = "HATtxvna:b:F:l:s:S:z:G:";
GetOpt options = LDAPTool.extractParameters( privateOpts, args );
/* -H Help */
if (options.hasOption('H')) {
doUsage();
System.exit(0);
} /* Help */
/* -A retrieve attribute name only == no values */
if (options.hasOption('A'))
m_attrsonly = true;
if (options.hasOption('x'))
m_sortOnServer = true;
if (options.hasOption('t'))
m_tempFiles = true;
/* -F separator */
if (options.hasOption('F'))
m_sep = options.getOptionParam('F');
/* -a set alias deref option */
if (options.hasOption('a')) { /* has option a */
String param = options.getOptionParam('a');
if (param.equalsIgnoreCase("never"))
m_deref = 0;
else if (param.equalsIgnoreCase("search"))
m_deref = 1;
else if (param.equalsIgnoreCase("find"))
m_deref = 2;
else if (param.equalsIgnoreCase("always"))
m_deref = 3;
else
System.err.println("Error: alias deref option " +
"should be never, search, find, " +
"or always.");
} /* has option a */
/* -b searchbase */
if (options.hasOption('b'))
m_base = options.getOptionParam('b');
/* -S sort attribute */
if (options.hasOption('S'))
m_sort.addElement( options.getOptionParam('S') );
/* -l time limit */
if (options.hasOption('l')) { /* if the option is -l */
try {
m_timelimit = Integer.parseInt(options.getOptionParam('l'));
} catch (NumberFormatException e) {
m_timelimit = 0;
}
} /* if the option is -l */
/* -s search scope */
if (options.hasOption('s')) { /* has option s */
String param = options.getOptionParam('s');
if (param.equalsIgnoreCase("base"))
m_scope = 0;
else if (param.equalsIgnoreCase("one"))
m_scope = 1;
else if (param.equalsIgnoreCase("sub"))
m_scope = 2;
else
System.err.println("Error: scope should be base, " +
"one or sub.");
} /* has option s */
/* -z size limit */
if (options.hasOption('z')) { /* if the option is -z */
try {
m_sizelimit = Integer.parseInt(options.getOptionParam('z'));
} catch (NumberFormatException e) {
m_sizelimit = 0;
}
} /* if the option is -z */
/* -T fold line */
if (options.hasOption('T')) { /* if the option is -T */
m_foldLine = false;
}
parseVlv(options);
/* extract the filter string and attributes */
Enumeration pa = options.getParameters().elements();
Vector vec = new Vector();
while (pa.hasMoreElements()) { /* while */
vec.addElement(pa.nextElement());
} /* while */
int counter = vec.size();
if (counter <= 0) { /* No filter */
System.err.println("Error: must supply filter string!");
doUsage();
System.exit(0);
} /* No filter */
if (counter == 1) { /* Has filter but no attributes */
/* gets filter string */
m_filter = (String)vec.elementAt(0);
if (m_verbose)
System.err.println("filter pattern: "+m_filter);
/* no attributes */
m_attrs = null;
if (m_verbose) {
System.err.println("returning: ALL");
System.err.println("filter is: ("+m_filter+")");
}
} /* Has filter but no attributes */
if (counter > 1) { /* Has filter and attributes */
/* gets filter string */
m_filter = (String)vec.elementAt(0);
if (m_verbose) {
System.err.println("filter pattern: "+m_filter);
System.err.print("returning:");
}
/* gets attributes */
m_attrs = new String[counter];
for (int j = 1; j < counter; j++) {
m_attrs[j-1] = (String)vec.elementAt(j);
if (m_verbose)
System.err.print(" "+m_attrs[j-1]);
}
if (m_verbose) {
System.err.println();
System.err.println("filter is: ("+m_filter+")");
}
} /* Has filter and attributes */
}
private static void parseVlv(GetOpt options) {
/* -G virtual list */
if (options.hasOption('G')) { /* if the option is -G */
String val = options.getOptionParam('G');
StringTokenizer tokenizer = new StringTokenizer(val, ":");
m_vlvTokens = tokenizer.countTokens();
if (m_vlvTokens < 3) {
doUsage();
System.exit(0);
}
try {
m_beforeCount = Integer.parseInt((String)tokenizer.nextElement());
} catch (NumberFormatException e) {
m_beforeCount = 0;
}
try {
m_afterCount = Integer.parseInt((String)tokenizer.nextElement());
} catch (NumberFormatException e) {
m_afterCount = 0;
}
if (m_vlvTokens == 3) {
m_searchVal = (String)tokenizer.nextElement();
} else if (m_vlvTokens > 3) {
try {
m_index = Integer.parseInt((String)tokenizer.nextElement());
} catch (NumberFormatException e) {
m_index = 0;
}
try {
m_count = Integer.parseInt((String)tokenizer.nextElement());
} catch (NumberFormatException e) {
m_count = 0;
}
}
} /* if the option is -G */
}
/**
* This class-method is used to call the LDAP Search Operation with the
* specified options, parameters, filters and/or attributes.
*/
private static void dosearch() {
LDAPControl[] controls = null;
try {
Vector cons = new Vector();
LDAPSortControl sort = null;
if ( m_sortOnServer && (m_sort.size() > 0) ) {
LDAPSortKey[] keys = new LDAPSortKey[m_sort.size()];
for( int i = 0; i < keys.length; i++ ) {
keys[i] = new LDAPSortKey( (String)m_sort.elementAt(i) );
}
sort = new LDAPSortControl( keys, true );
cons.addElement(sort);
}
if ((sort == null) && (m_vlvTokens >= 3)) {
System.err.println("Server-side sorting is required for "+
"virtual list option");
doUsage();
System.exit(0);
}
LDAPVirtualListControl vControl = null;
if (m_vlvTokens == 3) {
vControl = new LDAPVirtualListControl(m_searchVal,
m_beforeCount, m_afterCount);
} else if (m_vlvTokens > 3) {
vControl = new LDAPVirtualListControl(m_index, m_beforeCount,
m_afterCount, m_count);
}
if (vControl != null)
cons.addElement(vControl);
if (m_ordinary) {
LDAPControl manageDSAITControl = new LDAPControl(
LDAPControl.MANAGEDSAIT, true, null);
cons.addElement(manageDSAITControl);
}
if (cons.size() > 0) {
controls = new LDAPControl[cons.size()];
cons.copyInto(controls);
}
} catch (Exception e) {
System.err.println( e.toString() );
System.exit(0);
}
/* perform an LDAP Search Operation */
LDAPSearchResults res = null;
try {
LDAPSearchConstraints cons =
(LDAPSearchConstraints)m_client.getSearchConstraints().clone();
cons.setServerControls(controls);
cons.setDereference( m_deref );
cons.setMaxResults( m_sizelimit );
cons.setTimeLimit( m_timelimit );
cons.setReferrals( m_referrals );
if ( m_referrals ) {
setDefaultReferralCredentials( cons );
}
cons.setHopLimit( m_hopLimit );
res = m_client.search( m_base, m_scope,
m_filter, m_attrs,
m_attrsonly, cons );
} catch (Exception e) {
System.err.println( e.toString() );
System.exit(1);
}
/* Sort? */
if ( (m_sort.size() > 0) && !m_sortOnServer ) {
String[] sortAttrs = new String[m_sort.size()];
for( int i = 0; i < sortAttrs.length; i++ )
sortAttrs[i] = (String)m_sort.elementAt( i );
res.sort( new LDAPCompareAttrNames( sortAttrs ) );
}
/* print out the values of the entries */
printResults( res );
/* Any sort control responses? */
showControls( m_client.getResponseControls() );
}
/**
* Print the result entries.
* @param res Search results
*/
private static void printResults( LDAPSearchResults res ) {
/* print out the retrieved entries */
try {
/* Loop on results until finished */
while ( res.hasMoreElements() ) {
LDAPEntry findEntry = null;
try {
/* Next directory entry */
findEntry = (LDAPEntry)res.next();
} catch (LDAPReferralException ee) {
LDAPUrl[] urls= ee.getURLs();
System.err.println("Referral entries: ");
for (int i=0; i<urls.length; i++)
System.err.println("\t"+urls[i].getUrl().toString());
continue;
}
String dn = findEntry.getDN();
if (dn != null)
printString("dn" + m_sep + " " + dn);
else
printString("dn" + m_sep);
/* Get the attributes of the entry */
LDAPAttributeSet findAttrs = findEntry.getAttributeSet();
Enumeration enumAttrs = findAttrs.getAttributes();
/* Loop on attributes */
while ( enumAttrs.hasMoreElements() ) {
LDAPAttribute anAttr =
(LDAPAttribute)enumAttrs.nextElement();
String attrName = anAttr.getName();
if (m_attrsonly) {
printString(attrName+":");
continue;
}
/* Loop on values for this attribute */
Enumeration enumVals;
enumVals = anAttr.getByteValues();
if (enumVals != null) {
while ( enumVals.hasMoreElements() ) {
if ( m_tempFiles ) {
try {
FileOutputStream f = getTempFile( attrName );
f.write( (byte[])enumVals.nextElement() );
} catch ( Exception e ) {
System.err.println( "Error writing values " +
"of " + attrName + ", " +
e.toString() );
System.exit(1);
}
} else {
byte[] b = (byte[])enumVals.nextElement();
String s = null;
if (LDIF.isPrintable(b)) {
s = new String(b, "UTF8");
printString(attrName + m_sep + " " + s);
} else {
ByteBuf inBuf = new ByteBuf( b, 0, b.length );
ByteBuf encodedBuf = new ByteBuf();
// Translate to base 64
MimeBase64Encoder encoder = new MimeBase64Encoder();
encoder.translate( inBuf, encodedBuf );
int nBytes = encodedBuf.length();
if ( nBytes > 0 ) {
s = new String(encodedBuf.toBytes(), 0, nBytes);
printString( attrName + ":: " + s );
} else {
m_pw.print( attrName + ": \n" );
}
}
}
}
}
else
System.err.println("Failed to do string conversion for "+attrName);
}
m_pw.println();
}
} catch (Exception e) {
System.err.println( e.toString() );
System.exit(0);
}
}
private static void printString( String value ) {
if (m_foldLine)
LDIF.breakString(m_pw, value, MAX_LINE);
else {
m_pw.print(value);
m_pw.print( '\n' );
}
}
/**
* If there was a sort control returned, and the result code was
* not zero, show it.
* @param controls Any server controls returned.
**/
private static void showControls( LDAPControl[] controls ) {
if ( controls == null )
return;
int[] results = new int[1];
String bad = LDAPSortControl.parseResponse( controls, results );
if ( results[0] != LDAPException.SUCCESS ) {
System.err.println( "Error code: " + results[0] );
if ( bad != null )
System.err.println( "Offending attribute: " + bad );
else
System.err.println( "No offending attribute returned" );
} else
m_pw.println("Server indicated results sorted OK");
LDAPVirtualListResponse vResponse =
LDAPVirtualListResponse.parseResponse(controls);
if (vResponse != null) {
int resultCode = vResponse.getResultCode();
if (resultCode == LDAPException.SUCCESS) {
m_pw.println("Server indicated virtual list positioning OK");
m_pw.println("index "+vResponse.getFirstPosition()+
" content count "+vResponse.getContentCount());
} else
System.err.println("Virtual List Error: "+
LDAPException.errorCodeToString(resultCode));
}
}
private static FileOutputStream getTempFile( String name )
throws IOException {
int num = 0;
File f;
String filename;
do {
filename = name + '.' + num;
f = new File( filename );
num++;
} while ( f.exists() );
printString(name + m_sep + " " + filename);
return new FileOutputStream( f );
}
/**
* Internal variables
*/
private static boolean m_attrsonly = false;
private static int m_deref = 0;
private static int m_scope = 2; // default is sub search
private static int m_sizelimit = 0;
private static int m_timelimit = 0;
private static int verbose = 0;
private static String m_attrs[] = null;
private static String m_base = "o=ace industry,c=us";
private static String m_filter = null;
private static String m_sep = ":";
private static Vector m_sort = new Vector();
private static boolean m_sortOnServer = false;
private static boolean m_tempFiles = false;
private static int m_beforeCount = 0;
private static int m_afterCount = 0;
private static int m_index = 0;
private static int m_count = 0;
private static int m_vlvTokens = 0;
private static String m_searchVal = null;
private static boolean m_foldLine = true;
private static final int MAX_LINE = 77;
private static PrintWriter m_pw = new PrintWriter(System.out);
}