6916202: More cases of invalid ldap filters accepted and processed
Reviewed-by: vinnie, weijun
This commit is contained in:
parent
5925b23d55
commit
3f2af07ba1
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,6 +33,7 @@ import java.io.IOException;
|
||||
/**
|
||||
* LDAP (RFC-1960) and LDAPv3 (RFC-2254) search filters.
|
||||
*
|
||||
* @author Xuelei Fan
|
||||
* @author Vincent Ryan
|
||||
* @author Jagane Sundar
|
||||
* @author Rosanna Lee
|
||||
@ -258,7 +259,7 @@ final class Filter {
|
||||
byte[] answer = new byte[j];
|
||||
System.arraycopy(tbuf, 0, answer, 0, j);
|
||||
if (dbg) {
|
||||
Ber.dumpBER(System.err, null, answer, 0, j);
|
||||
Ber.dumpBER(System.err, "", answer, 0, j);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
@ -330,7 +331,7 @@ final class Filter {
|
||||
}
|
||||
|
||||
|
||||
valueStart = eq + 1; // value starts after equal sign
|
||||
valueStart = eq + 1; // value starts after equal sign
|
||||
valueEnd = filtEnd;
|
||||
typeStart = filtStart; // beginning of string
|
||||
|
||||
@ -355,20 +356,199 @@ final class Filter {
|
||||
break;
|
||||
default:
|
||||
typeEnd = eq;
|
||||
//initializing ftype to make the compiler happy
|
||||
ftype = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dbg) {
|
||||
System.err.println("type: " + typeStart + ", " + typeEnd);
|
||||
System.err.println("value: " + valueStart + ", " + valueEnd);
|
||||
}
|
||||
|
||||
// check validity of type
|
||||
//
|
||||
// RFC4512 defines the type as the following ABNF:
|
||||
// attr = attributedescription
|
||||
// attributedescription = attributetype options
|
||||
// attributetype = oid
|
||||
// oid = descr / numericoid
|
||||
// descr = keystring
|
||||
// keystring = leadkeychar *keychar
|
||||
// leadkeychar = ALPHA
|
||||
// keychar = ALPHA / DIGIT / HYPHEN
|
||||
// numericoid = number 1*( DOT number )
|
||||
// number = DIGIT / ( LDIGIT 1*DIGIT )
|
||||
// options = *( SEMI option )
|
||||
// option = 1*keychar
|
||||
//
|
||||
// And RFC4515 defines the extensible type as the following ABNF:
|
||||
// attr [dnattrs] [matchingrule] / [dnattrs] matchingrule
|
||||
int optionsStart = -1;
|
||||
int extensibleStart = -1;
|
||||
if ((filter[typeStart] >= '0' && filter[typeStart] <= '9') ||
|
||||
(filter[typeStart] >= 'A' && filter[typeStart] <= 'Z') ||
|
||||
(filter[typeStart] >= 'a' && filter[typeStart] <= 'z')) {
|
||||
|
||||
boolean isNumericOid =
|
||||
filter[typeStart] >= '0' && filter[typeStart] <= '9';
|
||||
for (int i = typeStart + 1; i < typeEnd; i++) {
|
||||
// ';' is an indicator of attribute options
|
||||
if (filter[i] == ';') {
|
||||
if (isNumericOid && filter[i - 1] == '.') {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
|
||||
// attribute options
|
||||
optionsStart = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// ':' is an indicator of extensible rules
|
||||
if (filter[i] == ':' && ftype == LDAP_FILTER_EXT) {
|
||||
if (isNumericOid && filter[i - 1] == '.') {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
|
||||
// extensible matching
|
||||
extensibleStart = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isNumericOid) {
|
||||
// numeric object identifier
|
||||
if ((filter[i] == '.' && filter[i - 1] == '.') ||
|
||||
(filter[i] != '.' &&
|
||||
!(filter[i] >= '0' && filter[i] <= '9'))) {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
} else {
|
||||
// descriptor
|
||||
if (filter[i] != '-' &&
|
||||
!(filter[i] >= '0' && filter[i] <= '9') &&
|
||||
!(filter[i] >= 'A' && filter[i] <= 'Z') &&
|
||||
!(filter[i] >= 'a' && filter[i] <= 'z')) {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ftype == LDAP_FILTER_EXT && filter[typeStart] == ':') {
|
||||
// extensible matching
|
||||
extensibleStart = typeStart;
|
||||
} else {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
|
||||
// check attribute options
|
||||
if (optionsStart > 0) {
|
||||
for (int i = optionsStart + 1; i < typeEnd; i++) {
|
||||
if (filter[i] == ';') {
|
||||
if (filter[i - 1] == ';') {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ':' is an indicator of extensible rules
|
||||
if (filter[i] == ':' && ftype == LDAP_FILTER_EXT) {
|
||||
if (filter[i - 1] == ';') {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
|
||||
// extensible matching
|
||||
extensibleStart = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (filter[i] != '-' &&
|
||||
!(filter[i] >= '0' && filter[i] <= '9') &&
|
||||
!(filter[i] >= 'A' && filter[i] <= 'Z') &&
|
||||
!(filter[i] >= 'a' && filter[i] <= 'z')) {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check extensible matching
|
||||
if (extensibleStart > 0) {
|
||||
boolean isMatchingRule = false;
|
||||
for (int i = extensibleStart + 1; i < typeEnd; i++) {
|
||||
if (filter[i] == ':') {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
} else if ((filter[i] >= '0' && filter[i] <= '9') ||
|
||||
(filter[i] >= 'A' && filter[i] <= 'Z') ||
|
||||
(filter[i] >= 'a' && filter[i] <= 'z')) {
|
||||
boolean isNumericOid = filter[i] >= '0' && filter[i] <= '9';
|
||||
i++;
|
||||
for (int j = i; j < typeEnd; j++, i++) {
|
||||
// allows no more than two extensible rules
|
||||
if (filter[j] == ':') {
|
||||
if (isMatchingRule) {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
if (isNumericOid && filter[j - 1] == '.') {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
|
||||
isMatchingRule = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isNumericOid) {
|
||||
// numeric object identifier
|
||||
if ((filter[j] == '.' && filter[j - 1] == '.') ||
|
||||
(filter[j] != '.' &&
|
||||
!(filter[j] >= '0' && filter[j] <= '9'))) {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
} else {
|
||||
// descriptor
|
||||
if (filter[j] != '-' &&
|
||||
!(filter[j] >= '0' && filter[j] <= '9') &&
|
||||
!(filter[j] >= 'A' && filter[j] <= 'Z') &&
|
||||
!(filter[j] >= 'a' && filter[j] <= 'z')) {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure the latest byte is not isolated
|
||||
if (filter[typeEnd - 1] == '.' || filter[typeEnd - 1] == ';' ||
|
||||
filter[typeEnd - 1] == ':') {
|
||||
throw new InvalidSearchFilterException(
|
||||
"invalid attribute description");
|
||||
}
|
||||
|
||||
if (typeEnd == eq) { // filter type is of "equal"
|
||||
if (findUnescaped(filter, '*', valueStart, valueEnd) == -1) {
|
||||
ftype = LDAP_FILTER_EQUALITY;
|
||||
} else if (filter[valueStart] == '*' && valueStart == (valueEnd - 1)) {
|
||||
} else if (filter[valueStart] == '*' &&
|
||||
valueStart == (valueEnd - 1)) {
|
||||
ftype = LDAP_FILTER_PRESENT;
|
||||
} else {
|
||||
encodeSubstringFilter(ber, filter,
|
||||
typeStart, typeEnd, valueStart, valueEnd);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (dbg) {
|
||||
System.err.println("type: " + typeStart + ", " + typeEnd);
|
||||
System.err.println("value: " + valueStart + ", " + valueEnd);
|
||||
}
|
||||
|
||||
if (ftype == LDAP_FILTER_PRESENT) {
|
||||
@ -379,7 +559,7 @@ final class Filter {
|
||||
} else {
|
||||
ber.beginSeq(ftype);
|
||||
ber.encodeOctetString(filter, Ber.ASN_OCTET_STR,
|
||||
typeStart, typeEnd-typeStart);
|
||||
typeStart, typeEnd - typeStart);
|
||||
ber.encodeOctetString(
|
||||
unescapeFilterValue(filter, valueStart, valueEnd),
|
||||
Ber.ASN_OCTET_STR);
|
||||
@ -623,7 +803,8 @@ final class Filter {
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private static final boolean dbg = false;
|
||||
// private static final boolean dbg = false;
|
||||
private static final boolean dbg = true;
|
||||
private static int dbgIndent = 0;
|
||||
|
||||
private static void dprint(String msg) {
|
||||
|
311
jdk/test/com/sun/jndi/ldap/InvalidLdapFilters.java
Normal file
311
jdk/test/com/sun/jndi/ldap/InvalidLdapFilters.java
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6916202
|
||||
* @summary More cases of invalid ldap filters accepted and processed
|
||||
* @run main/othervm InvalidLdapFilters valid (cn=Babs)
|
||||
* @run main/othervm InvalidLdapFilters valid (&(cn=Bob))
|
||||
* @run main/othervm InvalidLdapFilters valid (&(objectClass=*)(uid=*))
|
||||
* @run main/othervm InvalidLdapFilters valid (|(cn=Bob))
|
||||
* @run main/othervm InvalidLdapFilters valid (|(objectClass=*)(uid=*))
|
||||
* @run main/othervm InvalidLdapFilters valid (!(cn=Tim))
|
||||
* @run main/othervm InvalidLdapFilters valid (!(!(cn=Tim)))
|
||||
* @run main/othervm InvalidLdapFilters valid (!(&(objectClass=*)(uid=*)))
|
||||
* @run main/othervm InvalidLdapFilters valid (!(|(objectClass=*)(uid=*)))
|
||||
* @run main/othervm InvalidLdapFilters valid (o=univ*of*mich*)
|
||||
* @run main/othervm InvalidLdapFilters valid (seeAlso=)
|
||||
* @run main/othervm InvalidLdapFilters valid (cn:caseExactMatch:=Flintstone)
|
||||
* @run main/othervm InvalidLdapFilters valid (cn:=Betty)
|
||||
* @run main/othervm InvalidLdapFilters valid (sn:dn:2.4.6.8.10:=Barney)
|
||||
* @run main/othervm InvalidLdapFilters valid (o:dn:=Ace)
|
||||
* @run main/othervm InvalidLdapFilters valid (:1.2.3:=Wilma)
|
||||
* @run main/othervm InvalidLdapFilters valid (:DN:2.4.6.8.10:=Dino)
|
||||
* @run main/othervm InvalidLdapFilters valid (1.2.3=abc)
|
||||
* @run main/othervm InvalidLdapFilters valid (cn;lang-de;lang-en=abc)
|
||||
* @run main/othervm InvalidLdapFilters valid (owner=abc)
|
||||
* @run main/othervm InvalidLdapFilters valid (sn;lang-en:dn:2.4.6.8.10:=Barney)
|
||||
* @run main/othervm InvalidLdapFilters valid
|
||||
(&(objectClass=Person)(|(sn=Jensen)(cn=Bab*)))
|
||||
* @run main/othervm InvalidLdapFilters invalid "(&(cn=Robert Dean)))"
|
||||
* @run main/othervm InvalidLdapFilters invalid (&|(cn=Bob))
|
||||
* @run main/othervm InvalidLdapFilters invalid (&&(cn=Bob))
|
||||
* @run main/othervm InvalidLdapFilters invalid (|&(cn=Bob))
|
||||
* @run main/othervm InvalidLdapFilters invalid (||(cn=Bob))
|
||||
* @run main/othervm InvalidLdapFilters invalid (:1.2.:=Wilma)
|
||||
* @run main/othervm InvalidLdapFilters invalid (::DN:2.4.6.8.10:=Dino)
|
||||
* @run main/othervm InvalidLdapFilters invalid (:DN::2.4.6.8.10:=Dino)
|
||||
* @run main/othervm InvalidLdapFilters invalid (:DN:2.4.6.8.10::=Dino)
|
||||
* @run main/othervm InvalidLdapFilters invalid (:DN:2.4.6..8.10:=Dino)
|
||||
* @run main/othervm InvalidLdapFilters invalid (:DN:2.4.6.8.:=Dino)
|
||||
* @run main/othervm InvalidLdapFilters invalid (1.2.;::=abc)
|
||||
* @run main/othervm InvalidLdapFilters invalid (1.2.3;::=abc)
|
||||
* @run main/othervm InvalidLdapFilters invalid (1.2.3;x;=abc)
|
||||
* @run main/othervm InvalidLdapFilters invalid (1.2.3:x::=abc)
|
||||
* @run main/othervm InvalidLdapFilters invalid (1.2.3:x=abc)
|
||||
* @run main/othervm InvalidLdapFilters invalid (sn;:dn:2.4.6.8.10:=Barney)
|
||||
* @run main/othervm InvalidLdapFilters invalid "\"((objectClass=*)&(uid=*))\""
|
||||
* @run main/othervm InvalidLdapFilters invalid "&(objectClass=*)(uid=*)"
|
||||
* @run main/othervm InvalidLdapFilters invalid "(:DN:2.4.6.8.10:cn:=Dino)"
|
||||
* @run main/othervm InvalidLdapFilters invalid "(:DN:2.4.6.8.10:cn=Dino)"
|
||||
* @run main/othervm InvalidLdapFilters invalid
|
||||
"((objectCategory=person)(cn=u)(!(cn=u2*)))"
|
||||
* @run main/othervm InvalidLdapFilters invalid
|
||||
"((&(objectClass=user)(cn=andy*)(cn=steve*)(cn=bob*)))"
|
||||
*
|
||||
* @author Xuelei Fan
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import javax.naming.*;
|
||||
import javax.naming.directory.*;
|
||||
import java.util.Properties;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
public class InvalidLdapFilters {
|
||||
// Should we run the client or server in a separate thread?
|
||||
//
|
||||
// Both sides can throw exceptions, but do you have a preference
|
||||
// as to which side should be the main thread.
|
||||
static boolean separateServerThread = true;
|
||||
|
||||
// use any free port by default
|
||||
volatile int serverPort = 0;
|
||||
|
||||
// Is the server ready to serve?
|
||||
volatile static boolean serverReady = false;
|
||||
|
||||
// Define the server side of the test.
|
||||
//
|
||||
// If the server prematurely exits, serverReady will be set to true
|
||||
// to avoid infinite hangs.
|
||||
void doServerSide() throws Exception {
|
||||
ServerSocket serverSock = new ServerSocket(serverPort);
|
||||
|
||||
// signal client, it's ready to accecpt connection
|
||||
serverPort = serverSock.getLocalPort();
|
||||
serverReady = true;
|
||||
|
||||
// accept a connection
|
||||
Socket socket = serverSock.accept();
|
||||
System.out.println("Server: Connection accepted");
|
||||
|
||||
InputStream is = socket.getInputStream();
|
||||
OutputStream os = socket.getOutputStream();
|
||||
|
||||
// read the bindRequest
|
||||
while (is.read() != -1) {
|
||||
// ignore
|
||||
is.skip(is.available());
|
||||
break;
|
||||
}
|
||||
|
||||
byte[] bindResponse = {0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A,
|
||||
0x01, 0x00, 0x04, 0x00, 0x04, 0x00};
|
||||
// write bindResponse
|
||||
os.write(bindResponse);
|
||||
os.flush();
|
||||
|
||||
// ignore any more request.
|
||||
while (is.read() != -1) {
|
||||
// ignore
|
||||
is.skip(is.available());
|
||||
}
|
||||
|
||||
is.close();
|
||||
os.close();
|
||||
socket.close();
|
||||
serverSock.close();
|
||||
}
|
||||
|
||||
// Define the client side of the test.
|
||||
//
|
||||
// If the server prematurely exits, serverReady will be set to true
|
||||
// to avoid infinite hangs.
|
||||
void doClientSide() throws Exception {
|
||||
// Wait for server to get started.
|
||||
while (!serverReady) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
|
||||
// set up the environment for creating the initial context
|
||||
Hashtable<Object, Object> env = new Hashtable<Object, Object>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY,
|
||||
"com.sun.jndi.ldap.LdapCtxFactory");
|
||||
env.put(Context.PROVIDER_URL, "ldap://localhost:" + serverPort);
|
||||
env.put("com.sun.jndi.ldap.read.timeout", "1000");
|
||||
|
||||
// env.put(Context.SECURITY_AUTHENTICATION, "simple");
|
||||
// env.put(Context.SECURITY_PRINCIPAL,"cn=root");
|
||||
// env.put(Context.SECURITY_CREDENTIALS,"root");
|
||||
|
||||
// create initial context
|
||||
DirContext context = new InitialDirContext(env);
|
||||
|
||||
// searching
|
||||
SearchControls scs = new SearchControls();
|
||||
scs.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||
|
||||
try {
|
||||
NamingEnumeration answer =
|
||||
context.search("o=sun,c=us", searchFilter, scs);
|
||||
} catch (InvalidSearchFilterException isfe) {
|
||||
if (filterIsValid) {
|
||||
// unexpected filter exception.
|
||||
throw new Exception("Unexpected ISFE", isfe);
|
||||
} else {
|
||||
// ignore, it is the expected filter exception.
|
||||
System.out.println("Expected exception: " + isfe.getMessage());
|
||||
}
|
||||
} catch (NamingException ne) {
|
||||
// maybe a read timeout exception, as the server does not response.
|
||||
if (filterIsValid) {
|
||||
System.out.println("Expected exception: " + ne.getMessage());
|
||||
} else {
|
||||
throw new Exception("Not an InvalidSearchFilterException", ne);
|
||||
}
|
||||
}
|
||||
|
||||
context.close();
|
||||
}
|
||||
|
||||
private static boolean filterIsValid;
|
||||
private static String searchFilter;
|
||||
|
||||
private static void parseArguments(String[] args) {
|
||||
System.out.println("arguments length: " + args.length);
|
||||
if (args[0].equals("valid")) {
|
||||
filterIsValid = true;
|
||||
}
|
||||
|
||||
searchFilter = args[1];
|
||||
}
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* The remainder is just support stuff
|
||||
*/
|
||||
|
||||
// client and server thread
|
||||
Thread clientThread = null;
|
||||
Thread serverThread = null;
|
||||
|
||||
// client and server exceptions
|
||||
volatile Exception serverException = null;
|
||||
volatile Exception clientException = null;
|
||||
|
||||
void startServer(boolean newThread) throws Exception {
|
||||
if (newThread) {
|
||||
serverThread = new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
doServerSide();
|
||||
} catch (Exception e) {
|
||||
/*
|
||||
* Our server thread just died.
|
||||
*
|
||||
* Release the client, if not active already...
|
||||
*/
|
||||
System.err.println("Server died...");
|
||||
System.err.println(e);
|
||||
serverReady = true;
|
||||
serverException = e;
|
||||
}
|
||||
}
|
||||
};
|
||||
serverThread.start();
|
||||
} else {
|
||||
doServerSide();
|
||||
}
|
||||
}
|
||||
|
||||
void startClient(boolean newThread) throws Exception {
|
||||
if (newThread) {
|
||||
clientThread = new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
doClientSide();
|
||||
} catch (Exception e) {
|
||||
/*
|
||||
* Our client thread just died.
|
||||
*/
|
||||
System.err.println("Client died...");
|
||||
clientException = e;
|
||||
}
|
||||
}
|
||||
};
|
||||
clientThread.start();
|
||||
} else {
|
||||
doClientSide();
|
||||
}
|
||||
}
|
||||
|
||||
// Primary constructor, used to drive remainder of the test.
|
||||
InvalidLdapFilters() throws Exception {
|
||||
if (separateServerThread) {
|
||||
startServer(true);
|
||||
startClient(false);
|
||||
} else {
|
||||
startClient(true);
|
||||
startServer(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for other side to close down.
|
||||
*/
|
||||
if (separateServerThread) {
|
||||
serverThread.join();
|
||||
} else {
|
||||
clientThread.join();
|
||||
}
|
||||
|
||||
/*
|
||||
* When we get here, the test is pretty much over.
|
||||
*
|
||||
* If the main thread excepted, that propagates back
|
||||
* immediately. If the other thread threw an exception, we
|
||||
* should report back.
|
||||
*/
|
||||
if (serverException != null) {
|
||||
System.out.print("Server Exception:");
|
||||
throw serverException;
|
||||
}
|
||||
if (clientException != null) {
|
||||
System.out.print("Client Exception:");
|
||||
throw clientException;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// parse the customized arguments
|
||||
parseArguments(args);
|
||||
|
||||
// start the test
|
||||
new InvalidLdapFilters();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user