Merge from LDAPJavaSDK_40beta_19990802_BRANCH. Some files removed. Some added

This commit is contained in:
chuckb%netscape.com 1999-08-04 02:03:56 +00:00
parent 16db76eb51
commit c33e5d92b5
149 changed files with 10783 additions and 4663 deletions

View File

@ -1,14 +1,14 @@
======================================================================
NETSCAPE DIRECTORY SDK FOR JAVA:
BUILD INSTRUCTIONS
Last updated: June 4, 1999
Last updated: August 2, 1999
======================================================================
For information on the Netscape Directory SDK source release,
see http://www.mozilla.org/directory/
Note the following:
- The LDAP filter classes (in the netscape.ldap.util package)
use the OROMatcher(tm) regular expression package (from ORO Inc.).
use the OROMatcher(tm) regular expression package (from ORO Java Software).
This is not provided with the source code release. If you want this
package, you need to get it from ORO, Inc. (For details, see the
ORO, Inc. home page at http://www.oroinc.com/.)
@ -21,7 +21,7 @@ System Requirements:
32MB of RAM, 128MB of swap, recommended 64MB of RAM.
Tool Requirements:
Sun Microsystems Java Development Kit (JDK) 1.1.5
Sun Microsystems Java Development Kit (JDK) 1.1.7
(or a more recent version)
GNU make 3.74 or a more recent version
@ -36,10 +36,10 @@ Instructions:
In csh/tcsh:
setenv JAVA_HOME "<directory where the JDK is installed>"
For example:
setenv JAVA_HOME "/usr/local/jdk1.1.5"
setenv JAVA_HOME "/usr/local/jdk1.1.7"
setenv CLASSPATH "<location of the JDK classes.zip file>"
For example:
setenv CLASSPATH "/usr/local/jdk1.1.5/lib/classes.zip"
setenv CLASSPATH "/usr/local/jdk1.1.7/lib/classes.zip"
In sh/bash/ksh:
JAVA_HOME="<directory where the JDK is installed>"
@ -56,10 +56,21 @@ Instructions:
gmake -f ldap.mk basepackage
To generate javadoc specify "doc" as the target:
gmake -f ldap.mk doc
Note that if you are using JDK1.1, javadoc images will be missing
and you'll need to copy those images from somewhere else into
mozilla/directory/java-sdk/dist/doc/images. If you are using JDK1.2
you do not need to do that.
The SDK will be built and copied into the following directories:
mozilla/directory/java-sdk/dist/classes - class files and manifest file
mozilla/directory/java-sdk/dist/packages - ldapjdk.jar JAR file
(if you've specified "basepackage" as the target)
mozilla/directory/java-sdk/dist/doc - ldapjdk javadoc
(if you've specified "doc" as the target)
4. Build the JNDI LDAP Service Provider classes by entering the following commands:
@ -70,10 +81,16 @@ Instructions:
gmake -f ldapsp.mk basepackage
To generate javadoc specify "doc" as the target:
gmake -f ldapsp.mk doc
The SDK will be built and copied into the following directories:
mozilla/directory/java-sdk/dist/classes - class files
mozilla/directory/java-sdk/dist/packages - ldapsp.jar JAR file
(if you've specified "basepackage" as the target)
mozilla/directory/java-sdk/dist/doc/ldapsp - ldapsp controls' javadoc
(if you've specified "doc" as the target)
The JNDI LDAP Service Provider depends on the LDAP Java classes, so you
always must build the LDAP Java first. For more information on JNDI see
@ -87,7 +104,7 @@ System Requirements:
Windows NT 3.51 or 4.0 (4.0 preferred).
Tool Requirements:
Sun Microsystems Java Development Kit (JDK) 1.1.5
Sun Microsystems Java Development Kit (JDK) 1.1.7
(or a more recent version)
GNU Tools for Windows (you can find these on the Internet).
Specifically, you'll need:
@ -127,10 +144,10 @@ Instructions:
directory is at d:\mozilla_src\mozilla.)
set JAVA_HOME=(directory where the JDK is installed)
For example:
set JAVA_HOME=D:\jdk1.1.5
set JAVA_HOME=D:\jdk1.1.7
set CLASSPATH=(location of the JDK classes.zip file)
For example:
set CLASSPATH=D:\jdk1.1.5\lib\classes.zip
set CLASSPATH=D:\jdk1.1.7\lib\classes.zip
In addition, make sure to set your PATH environment variable to
include the tools that you have downloaded.
@ -144,10 +161,22 @@ Instructions:
gmake -f ldap.mk basepackage
To generate javadoc specify "doc" as the target:
gmake -f ldap.mk doc
Note that if you are using JDK1.1, javadoc images will be missing
and you'll need to copy those images from somewhere else into
mozilla\directory\java-sdk\dist\doc\images. If you are using JDK1.2
you do not need to do that.
The SDK will be built and copied into the following directories:
mozilla\directory\java-sdk\dist\classes - class files and manifest file
mozilla\directory\java-sdk\dist\packages - ldapjdk.jar JAR file
(if you've specified "basepackage" as the target)
mozilla\directory\java-sdk\dist\doc - ldapjdk javadoc
(if you've specified "doc" as the target)
3. Build the JNDI LDAP Service Provider classes by entering the following commands:
@ -158,10 +187,16 @@ Instructions:
gmake -f ldapsp.mk basepackage
To generate javadoc specify "doc" as the target:
gmake -f ldapsp.mk doc
The SDK will be built and copied into the following directories:
mozilla/directory/java-sdk/dist/classes - class files
mozilla/directory/java-sdk/dist/packages - ldapsp.jar JAR file
(if you've specified "basepackage" as the target)
mozilla\directory\java-sdk\dist\doc\ldapsp - ldapsp controls' javadoc
(if you've specified "doc" as the target)
The JNDI LDAP Service Provider depends on the LDAP Java classes, so you
always must build the LDAP Java first. For more information on JNDI see

View File

@ -1,61 +0,0 @@
README for september 28
On September 28, a new source drop was assembled. The LDAPConnection
version is now 3.05. Compared to the original 3.0 source drop, this
addresses the following problems:
On disconnect (or on finalizing an LDAPConnection object, which
implicitly calls the finalizer), a reference to the underlying socket
was kept, so that the socket was not closed. As a consequence, an
application which repeatedly did connect and disconnect would
experience a resource leak. On UNIX systems, the java VM might
eventually crash because of insufficient file descriptors. On Windows,
it might eventually crash because of memory exhaustion.
Referrals were not correctly followed on add operations.
Support has now been added for referrals on authentication. There is
a new overloaded authenticate method in LDAPConnection which takes an
LDAPSearchConstraints as a parameter.
There was no check for an empty or null host String on connect. Now,
LDAPConnection.connect() throws an LDAPException for these two cases.
Automatic reconnect when the server was restarted did not work. This
is now handled transparently on the next operation. Also,
LDAPConnection.isConnected() did not always return a correct response.
A bad referral (one that points to a non-existent or inaccessible
server or entry) would cause any following valid results from a search
to be discarded.
For asynchronous searches (batchSize == 1), it was possible that
search results would arrive from the server and be buffered by the SDK
faster than they could be processed by the application (using
LDAPSearchResults.next() or LDAPSearchResults.nextElement()). The
buffered results might use up more memory than was available in the
java VM, causing it to crash. Now, there is a limit of 100 on the
number of buffered entries per asynchronous search. The number can be
changed with LDAPSearchConstraints.setMaxBacklog(int backlog). If
there are no synchronous searches on a physical connection, and any
asynchronous searches have full backlog buffers, the listener thread
sleeps until search results are processed by the client.
Persistent search response controls could be overwritten before a
client could process them. Now they are queued and served up one at a
time to the client.
LDAPSearchResults().getCount() always returned the number of results
processed by the client, rather than the number of results available
to be processed by the client.
LDAPSearchResults.sort() would throw a ClassCastException if the
LDAPSearchResults object contained exceptions (LDAPException and
LDAPReferralException) in addition to any LDAPEntry objects.
----
There is also a new directory "tools" containing source for the
command-line tools LDAPSearch, LDAPModify, and LDAPDelete.

View File

@ -12,7 +12,7 @@
#
# 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
# Copyright (C) 1999 Netscape Communications Corporation. All Rights
# Reserved.
#
# Makefile for the LDAP classes
@ -20,6 +20,37 @@
# An optimized compile is done by default. You can specify "DEBUG=1" on
# the make line to generate debug symbols in the bytecode.
#
# The package includes com.netscape.sasl (until there is another
# home for it)
#
# You can compile only subsets of the classes by specifying one of the
# following:
# doc
# classes
# LDAPCLASSES
# MAIN
# CLIENT
# OPERS
# UTIL
# BER
# BEANS
# SASL
# TOOLS
# FILTER
#
# Create the JAR files with the following targets:
# package
# basepackage
# filterpackage
# beanpackage
# docpackage
#
# The usual mozilla environment variable must be defined:
# MOZ_SRC (the root of your CVS tree)
#
# And the Java root directory
# JAVA_HOME
#
ARCH := $(shell uname -s)
MCOM_ROOT=.
@ -36,6 +67,7 @@ else
endif
# Destination for class files and packages
CLASS_DEST=$(BASEDIR)/dist/classes
FILTER_CLASS_DEST=$(BASEDIR)/dist/ldapfilt
# Set up the CLASSPATH automatically,
ifeq ($(ARCH), WINNT)
@ -53,12 +85,14 @@ else
SEP=:
endif
endif
JAVACLASSPATH:=$(BASEDIR)/ldapjdk$(SEP)$(BASEDIR)/ldapbeans$(SEP)$(BASEDIR)/ldapfilter$(SEP)$(CLASSPATH)
JAASLIB=$(BASEDIR)/ldapjdk/lib/jaas.jar
JAVACLASSPATH:=$(BASEDIR)/ldapjdk$(SEP)$(JAASLIB)$(SEP)$(BASEDIR)/ldapbeans$(SEP)$(JDK)/lib/classes.zip$(SEP)$(CLASSPATH)
SRCDIR=netscape/ldap
BEANDIR=$(BASEDIR)/ldapbeans/netscape/ldap/beans
DISTDIR=$(MCOM_ROOT)/dist
CLASSDIR=$(MCOM_ROOT)/dist/classes
FILTERCLASSDIR=$(MCOM_ROOT)/dist/ldapfilt
CLASSPACKAGEDIR=$(DISTDIR)/packages
PACKAGENAME=javaldap.zip
ifeq ($(DEBUG), 1)
@ -66,10 +100,24 @@ BASEPACKAGENAME=ldapjdk_debug.jar
else
BASEPACKAGENAME=ldapjdk.jar
endif
FILTERJAR=ldapfilt.jar
CLASSPACKAGE=$(CLASSPACKAGEDIR)/$(PACKAGENAME)
BEANPACKAGENAME=ldapbeans.jar
TOOLSTARGETDIR=$(DISTDIR)/tools
TOOLSDIR=$(BASEDIR)/tools
DOCDIR=$(DISTDIR)/doc
BERDOCPACKAGEDIR=$(DISTDIR)/doc/ber
DOCNAME=ldapdoc.zip
DOCPACKAGE=$(CLASSPACKAGEDIR)/$(DOCNAME)
EXAMPLEDIR=$(DISTDIR)/examples
#TESTSRCDIR=$(BASEDIR)/netsite/ldap/java/netscape/ldap/tests
ERRORSDIR=$(CLASSDIR)/netscape/ldap/errors
SASLDIR=com/netscape/sasl
SASLMECHANISMDIR=com/netscape/sasl/mechanisms
ifndef JAVADOC
JAVADOC=$(JDKBIN)javadoc -classpath "$(JAVACLASSPATH)"
endif
ifndef JAVAC
ifdef JAVA_HOME
JDKBIN=$(JDK)/bin/
@ -81,6 +129,11 @@ ifndef JAVAC
endif
endif
BERDOCCLASSES=netscape.ldap.ber.stream
DOCCLASSES=netscape.ldap netscape.ldap.beans netscape.ldap.controls \
netscape.ldap.util $(TOOLSDIR)/*.java $(BERDOCCLASSES)
all: classes
basics: $(DISTDIR) $(CLASSDIR)
@ -88,8 +141,25 @@ basics: $(DISTDIR) $(CLASSDIR)
classes: LDAPCLASSES BEANS TOOLS
doc: $(DISTDIR) $(DOCDIR) DOCS
berdoc: $(DISTDIR) $(BERDOCPACKAGEDIR) BERDOCS
examples: $(DISTDIR) $(EXAMPLEDIR)/java $(EXAMPLEDIR)/js $(EXAMPLEDIR)/java/beans EXAMPLES
tests: $(CLASSDIR)
cd $(TESTSRCDIR); $(JAVAC) -d $(CLASS_DEST) *.java
package: basepackage filterpackage beanpackage docpackage
basepackage: $(CLASSPACKAGEDIR)
cd $(DISTDIR)/classes; rm -f ../packages/$(BASEPACKAGENAME); $(JAR) cvfm ../packages/$(BASEPACKAGENAME) manifest.mf netscape/ldap/*.class netscape/ldap/client/*.class netscape/ldap/client/opers/*.class netscape/ldap/ber/stream/*.class netscape/ldap/controls/*.class netscape/ldap/util/*.class netscape/ldap/errors/*.props com/netscape/sasl/*.class tools/*.class
cd $(DISTDIR)/classes; rm -f ../packages/$(BASEPACKAGENAME); $(JAR) cvfm ../packages/$(BASEPACKAGENAME) manifest.mf netscape/ldap/*.class netscape/ldap/client/*.class netscape/ldap/client/opers/*.class netscape/ldap/ber/stream/*.class netscape/ldap/controls/*.class netscape/ldap/util/*.class netscape/ldap/errors/*.props com/netscape/sasl/*.class com/netscape/sasl/mechanisms/*.class tools/*.class
beanpackage: $(CLASSPACKAGEDIR)
cd $(DISTDIR)/classes; rm -f ../packages/$(BEANPACKAGENAME); $(JAR) cvf ../packages/$(BEANPACKAGENAME) netscape/ldap/beans
docpackage: $(DOCDIR) $(CLASSPACKAGEDIR)
cd $(DOCDIR); rm -f ../packages/$(DOCNAME); $(JAR) cvf ../packages/$(DOCNAME) *.html *.css netscape/ldap/*.html netscape/ldap/beans/*.html netscape/ldap/controls/*.html netscape/ldap/util/*.html netscape/ldap/ber/stream/*.html
MAIN: basics
cd ldapjdk/$(SRCDIR); $(JAVAC) -d "$(CLASS_DEST)" *.java
@ -106,6 +176,9 @@ BER: basics
UTIL: basics
cd ldapjdk/$(SRCDIR)/util; $(JAVAC) -d "$(CLASS_DEST)" *.java
SASLMECHANISM: basics
cd ldapjdk/$(SASLMECHANISMDIR); $(JAVAC) -d "$(CLASS_DEST)" *.java
SASL: basics
cd ldapjdk/$(SASLDIR); $(JAVAC) -d "$(CLASS_DEST)" *.java
@ -115,7 +188,7 @@ ERRORS: basics $(ERRORSDIR)
CONTROLS: basics
cd ldapjdk/$(SRCDIR)/controls; $(JAVAC) -d "$(CLASS_DEST)" *.java
LDAPCLASSES: BER OPERS CLIENT MAIN UTIL CONTROLS ERRORS SASL
LDAPCLASSES: BER OPERS CLIENT MAIN UTIL CONTROLS ERRORS SASL SASLMECHANISM
BEANS: OTHERBEANS
@ -125,13 +198,31 @@ OTHERBEANS: basics
TOOLS: basics
cd tools; $(JAVAC) -d "$(CLASS_DEST)" *.java
FILTER: $(FILTERCLASSDIR)
cd ldapfilter/netscape/ldap/util; $(JAVAC) -d "$(FILTER_CLASS_DEST)" *.java
filterpackage: $(CLASSPACKAGEDIR)
cd "$(FILTER_CLASS_DEST)"; rm -f ../packages/$(FILTERJAR); $(JAR) cvf ../packages/$(FILTERJAR) netscape/ldap/util/*.class
DOCS:
$(JAVADOC) -d $(DOCDIR) $(DOCCLASSES)
BERDOCS:
$(JAVADOC) -d $(BERDOCPACKAGEDIR) $(BERDOCCLASSES)
EXAMPLES:
-cp -p $(EXAMPLESRCDIR)/java/* $(EXAMPLEDIR)/java
-cp -p $(EXAMPLESRCDIR)/java/beans/* $(EXAMPLEDIR)/java/beans
-cp -p $(EXAMPLESRCDIR)/java/beans/makejars.* $(CLASSDIR)
-cp -p $(EXAMPLESRCDIR)/js/* $(EXAMPLEDIR)/js
clean:
rm -rf $(DISTDIR)
$(CLASSPACKAGEDIR):
mkdir -p $@
$(DOCPACKAGEDIR):
$(DOCDIR):
mkdir -p $@
$(DISTDIR):
@ -143,3 +234,5 @@ $(CLASSDIR):
$(ERRORSDIR):
mkdir -p $@
$(FILTERCLASSDIR):
mkdir -p $@

View File

@ -338,9 +338,12 @@ public class LDAPBasePropertySupport implements Serializable {
m_conn.getAuthenticationPassword() );
}
};
LDAPSearchConstraints cons = conn.getSearchConstraints();
cons.setReferrals( true );
cons.setRebindProc( rebind );
try {
conn.setOption(LDAPConnection.REFERRALS, Boolean.TRUE);
conn.setOption(LDAPConnection.REFERRALS_REBIND_PROC, rebind);
} catch (LDAPException e) {
//will never happen
}
}
/**

View File

@ -284,6 +284,10 @@ public class LDAPFilter implements Cloneable {
if ( cFilterTemplate[i] == '%' ) {
i++;
if ( cFilterTemplate[i] == 'v' ) {
if ( i == (cFilterTemplate.length-1) ) {
sbFilter.append ( strValue );
break;
}
i++;
switch ( cFilterTemplate[i] ) {
case '$':

View File

@ -0,0 +1,123 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package com.netscape.sasl;
import java.util.Hashtable;
import javax.security.auth.callback.CallbackHandler;
/**
* An interface for creating instances of <tt>SaslClient</tt>.
*
* @see SaslClient
* @see Sasl
*/
public class ClientFactory implements SaslClientFactory {
public ClientFactory() {
_mechanismTable = new Hashtable();
for( int i = 0; i < _mechanismNames.length; i++ ) {
_mechanismTable.put( _mechanismNames[i],
PACKAGENAME + '.' +
_mechanismClasses[i] );
}
}
/**
* Creates a SaslClient using the parameters supplied.
*
* @param mechanisms The non-null list of mechanism names to try.
* Each is the IANA-registered name of a SASL mechanism. (e.g.
* "GSSAPI", "CRAM-MD5").
* @param authorizationId The possibly null authorization ID to
* use. When the SASL authentication completes successfully, the
* entity named by authorizationId is granted access.
* @param protocol The non-null string name of the protocol for
* which the authentication is being performed (e.g., "ldap").
* @param serverName The non-null string name of the server to
* which we are creating an authenticated connection.
* @param props The possibly null properties to be used by the SASL
* mechanisms to configure the authentication exchange. For example,
* "javax.security.sasl.encryption.maximum" might be used to
* specify the maximum key length to use for encryption.
* @param cbh The possibly null callback handler to used by the
* SASL mechanisms to get further information from the
* application/library to complete the authentication. For example,
* a SASL mechanism might require the authentication ID and
* password from the caller.
* @return A possibly null <tt>SaslClient</tt> created using the
* parameters supplied. If null, this factory cannot produce a
* <tt>SaslClient</tt> using the parameters supplied.
* @exception SaslException if it cannot create a
* <tt>SaslClient</tt> because of an error.
*/
public SaslClient createSaslClient(
String[] mechanisms,
String authorizationId,
String protocol,
String serverName,
Hashtable props,
CallbackHandler cbh ) throws SaslException {
String mechName = null;
if ( Sasl.debug ) {
System.out.println(
"ClientFactory.createSaslClient" );
}
for( int i = 0; (mechName == null) &&
(i < mechanisms.length); i++ ) {
mechName = (String)_mechanismTable.get( mechanisms[i] );
}
if ( mechName != null ) {
try {
Class c = Class.forName( mechName );
SaslClient client = (SaslClient)c.newInstance();
if ( Sasl.debug ) {
System.out.println(
"ClientFactory.createSaslClient: newInstance for " +
mechName + " returned " + client);
}
return client;
} catch ( Exception e ) {
System.err.println(
"ClientFactory.createSaslClient: " + e );
}
} else {
if ( Sasl.debug ) {
System.out.println(
"ClientFactory.createSaslClient: does not support " +
"any of the mechanisms" );
for( int i = 0; i < mechanisms.length; i++ ) {
System.out.println( " " + mechanisms[i] );
}
}
}
return null;
}
/**
* Returns an array of names of mechanisms supported by this
* factory.
* @return A non-null array containing IANA-registered SASL
* mechanism names.
*/
public String[] getMechanismNames() {
return _mechanismNames;
}
private final String PACKAGENAME = "com.netscape.sasl.mechanisms";
private final String[] _mechanismNames = { "EXTERNAL" };
private final String[] _mechanismClasses = { "SaslExternal" };
private Hashtable _mechanismTable;
}

View File

@ -1,26 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl;
import com.netscape.sasl.SASLException;
/**
* This is just a base interface which does not contain any methods.
*/
public interface SASLClientCB {
}

View File

@ -1,203 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl;
/**
*
*<PRE>
* Mechanism Drivers
* --------------- ------------------- -----------------
* | Application |-----| Protocol Driver |------| MD5 |
* --------------- ------------------- | -----------------
* |
* | -----------------
* |--| Kerberos v5 |
* | -----------------
* |
* | -----------------
* |--| PKCS-11 |
* | -----------------
* |
*
* |
*
* |
* | - - - - - - - - -
* |--| xxxYYYxxx |
* - - - - - - - - -
*</PRE>
* An application chooses a Protocol Driver specific to the
* protocol it wants to use, and specifies one or more acceptable
* mechanisms. The Protocol Driver controls the socket, and knows
* the format/packaging of bytes sent down and received from the
* socket, but does not know how to authenticate or to encrypt/
* decrypt the bytes. It uses one of of the Mechanism Drivers
* to help it perform authentication, where all parameters to
* be used in encryption from then on are determined. In a protocol-
* specific way, the Protocol Driver examines each byte string received
* from the server to determine if the authentication process has
* been completed. If not, the byte string is passed to the Mechanism
* Driver to be interpreted as a server challenge; the Mechanism
* Driver returns an appropriate response, which the Protocol Driver
* can encode in a protocol-specific way and return to the server.
*<P>
* If the Protocol Driver concludes from the byte string received from
* the server that authentication is complete, it may query
* the Mechanism Driver if it considers the authentication process
* complete, in order to thwart early completion messages inserted by
* and intruder.
*<P>
* On completed
* authentication, the Protocol Driver receives from the Mechanism
* Driver a Security Layer Driver object. From this point on,
* the Protocol Driver passes byte arrays received from its socket
* to the Security Layer Driver object for decoding before
* returning them to the application, and passes
* application byte arrays to the Security Layer Driver object
* for encryption before passing them down the socket.
*<P>
* A complication here is that some authentication methods may
* require additional user/application input (at least on the client
* side). That means that a Mechanism Driver may need to call up to
* an application during the authentication process. In the following,
* an interface SASLAuthenticationCB has been defined, allowing
* an application to (if necessary) provide a user with prompts and
* obtain additional information required to continue the process.
*<P>
* For LDAP, the Protocol Driver can be considered built in to
* the LDAPConnection class (actually it is more likely an object
* to which an LDAPConnection object has a reference).
*<P>
* However,
* there should be a generalized framework for registering and
* finding Mechanism Drivers. Maybe best to do something like
* content and protocol handlers in java: look for them in some
* predefined place in the general class hierarchy, e.g.
* netscape.security.mechanisms. So if a Protocol Driver is
* asked to use "GSSAPI", it would attempt to instantiate
* netscape.security.mechanisms.gssapi. A non-standard place can
* also be specified, e.g. "myclasses.mechanisms.GSSAPI".
* This functionality should be folded into a mechanism driver
* factory, which knows where to find candidate classes for
* instantiation.
*<P>
* The Mechanism Drivers are protocol-independent, and don't deal
* directly with network connections, just byte arrays, so they
* should be implemented in a generalizable way for all protocols.
*<P>
* A Security Layer Driver typically inherits a State object from
* the Mechanism Driver, where parameters and resolutions reached
* during authentication have been stored.
*<P>
* One way to allow specifying an open-ended list of parameters is
* with a Properties object. That is what is done in the following.
*
* @author rweltman@netscape.com
* @version 1.0
*/
public interface SASLClientMechanismDriver {
/**
* This method prepares a byte array to use for the initial
* request to authenticate. A SASLException is thrown if the driver
* cannot initiate authentication with the supplied parameters.
* @param id Protocol-dependent identification, e.g. user name or
* distinguished name.
* @param protocol A protocol supported by the mechanism driver, e.g.
* "pop3", "ldap"
* @param serverName Only used in kerberos, currently: fully qualified
* name of server to authenticate to.
* @param props Additional configuration for the session, e.g.
*<PRE>
* "security.policy.encryption.minimum" Minimum key length;
* default 0
* "security.policy.encryption.maximum" Maximum key length;
* default 256
* "security.policy.server_authentication" True if server must
* authenticate to client;
* default <CODE>false</CODE>
* "security.ip.local" For kerberos v4; no default
* "security.ip.remote" For kerberos v4; no default
* "security.maxbuffer" Reject frames larger than
* this; default 0 (client
* will not use the security
* layer)
*</PRE>
* @param authCB An optional object which can be invoked by the
* mechanism driver to acquire additional authentication information,
* such as user name and password.
* @return A byte array to be used for the initial authentication. It
* may be <CODE>null</CODE> for a standard initial sequence in some
* protocols, such as POP, SMTP, and IMAP.
* @exception SASLException if an initial authentication request can
* not be formulated with the supplied parameters.
*/
public byte[] startAuthentication( String id,
String protocol,
String serverName,
java.util.Properties props,
SASLClientCB authCB )
throws SASLException;
/**
* If a challenge is received from the server during the
* authentication process, this method is called by the
* Protocol Driver to prepare an appropriate next request to submit
* to the server.
* @param challenge Received server challenge.
* @return Request to submit to server.
* @exception SASLException if the server challenge could not
* be handled or the driver is unable for other reasons to
* continue the authentication process.
*/
public byte[] evaluateResponse( byte[] challenge )
throws SASLException;
/**
* The following method may be called at any time to determine if
* the authentication process is finished. Typically, the protocol
* driver will not do this until it has received something
* from the server which indicates (in a protocol-specific manner)
* that the process
* has completed.
* @return <CODE>true</CODE> if authentication is complete.
*/
public boolean isComplete();
/**
* Once authentication is complete, the Protocol Driver calls the
* following method to obtain an object capable of encoding/decoding
* data content for the rest of the session (or until there is a
* new round of authentication). An exception is thrown if
* authentication is not yet complete.
* @return A SASLSecurityLayer object capable of doing
* encoding/decoding during the session.
* @exception SASLException if no security layer has been negotiated
* or if authentication is not complete.
*/
public SASLSecurityLayer getSecurityLayer() throws SASLException;
/**
* Report the name of this driver, e.g. "GSSAPI".
* @return The name of the mechanism driver, without any location
* qualification.
*/
public String getMechanismName();
}

View File

@ -1,62 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl;
/*
* Exception type returned on SASL authentication failures.
*/
public class SASLException extends Exception {
/**
* Constructs a default exception with no specific error information.
*/
public SASLException() {
}
/**
* Constructs a default exception with a specified string as
* additional information.
* @param message The additional error information.
*/
public SASLException( String message ) {
super( message );
}
/**
* Constructs a default exception with a specified string as
* additional information, and a result code.
* @param message The additional error information.
* @param resultCode The result code returned.
*/
public SASLException( String message, int resultCode ) {
super( message );
this.m_resultCode = resultCode;
}
public int getResultCode() {
return m_resultCode;
}
public String toString() {
if (m_resultCode != -1)
return super.toString() + " (" + m_resultCode + ")" ;
else
return super.toString();
}
private int m_resultCode = -1;
}

View File

@ -1,34 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl;
import java.util.*;
/**
* Obtain a language to use for localization of user-visible text.
*/
public interface SASLGetLanguageCB extends SASLClientCB {
/**
* Returns a language to use in localizing user-visible text.
* @param locale The Locale object
* @return a localized text.
*/
public String getLanguage(Locale locale);
}

View File

@ -1,32 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl;
/**
* Present information to a user. No confirmation is expected.
*/
public interface SASLInfoClientCB extends SASLClientCB {
/**
* Presents the user with the supplied textual information.
* @param prompt Textual information to be provided to the client. It
* may be localized.
*/
public void promptInfo(String prompt);
}

View File

@ -1,94 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl;
/**
* This class provides a SASLClientMechanismDriver, or a list of mechanisms.
*/
public class SASLMechanismFactory {
/**
* Returns an object implementing a requested mechanism driver. A
* SASLException is thrown if no corresponding mechanism driver can be
* instantiated.
* @param mechanisms A list of mechanism names
* @param packageName A package from which to instantiate the mechanism
* driver, eg, "myclasses.SASL.mechanisms". If null, a system default
* is used.
*/
public static SASLClientMechanismDriver getMechanismDriver(
String[] mechanisms, String packageName) throws SASLException {
for (int i=0; i<mechanisms.length; i++) {
try {
SASLClientMechanismDriver driver =
getMechanismDriver(mechanisms[i], packageName);
if (driver != null)
return driver;
} catch (SASLException e) {
}
}
throw new SASLException();
}
public static SASLClientMechanismDriver getMechanismDriver(
String mechanism, String packageName) throws SASLException {
String className = packageName+"."+mechanism;
SASLClientMechanismDriver driver = null;
try {
Class c = Class.forName(className);
java.lang.reflect.Constructor[] m = c.getConstructors();
for (int i = 0; i < m.length; i++) {
/* Check if the signature is right: String */
Class[] params = m[i].getParameterTypes();
if (params.length == 0) {
driver =
(SASLClientMechanismDriver)(m[i].newInstance(null));
return driver;
} else if ((params.length == 1) &&
(params[0].getName().equals("java.lang.String"))) {
Object[] args = new Object[1];
args[0] = mechanism;
driver =
(SASLClientMechanismDriver)(m[i].newInstance(args));
return driver;
}
}
System.out.println("No appropriate constructor in " + mechanism);
} catch (ClassNotFoundException e) {
System.out.println("Class "+mechanism+" not found");
} catch (Exception e) {
System.out.println("Failed to create "+mechanism+
" mechanism driver");
}
throw new SASLException();
}
public static String[] getMechanisms() throws SASLException {
throw new SASLException("Method getMechanisms not supported now", 80);
}
public static String[] getMechanisms(String packageName)
throws SASLException {
throw new SASLException("Method getMechanisms not supported now");
}
}

View File

@ -1,52 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl;
/**
* Represents an object which provides more information for authentication can
* be called by a Mechanism driver. Typically the object provides an ID and
* a password.
*/
public interface SASLNamePasswordClientCB extends SASLClientCB {
/**
* The UI may or may not be popped up and the user is allowed to enter
* the information. It returns true unless the operation was cancelled.
* @param defaultID A default which may be used in selecting credentials.
* @param serverFQDN The fully qualified domain name of the host to which
* authentication is being attempted. Used with kerberos.
* @param protocol "IMAP", "POP", etc. Used with kerberos.
* @param prompt Textual information to be provided to the client for
* obtaining an ID and password. It may be localized.
* @return true if the operation is successful, otherwise, false.
*/
public boolean promptNamePassword(String defaultID, String serverFQDN,
String protocol, String prompt);
/**
* Retrieve the ID.
* @return ID
*/
public String getID();
/**
* Retrieve the password.
* @return password
*/
public String getPassword();
}

View File

@ -1,37 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl;
/**
* Present information to a user and return an indication that an operation
* is to proceed or to be cancelled.
*/
public interface SASLOkayCancelClientCB extends SASLClientCB {
/**
* Presents the user with the supplied textual information. The return
* value is true to continue operations, false to abort. This may be
* implemented with OK and CANCEL buttons in a dialog. If okText and/or
* cancelText are non-null and not empty, they may be used to label buttons.
*
* @return true to continue operations, false to abort.
*/
public boolean promptOkayCancel(String prompt, String okText,
String cancelText);
}

View File

@ -1,45 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl;
/**
* Represents an object which provides more information for authentication can
* be called by a Mechanism driver. Typically the object provides a password.
*/
public interface SASLPasswordClientCB extends SASLClientCB {
/**
* The UI may or may not be popped up and the user is allowed to enter the
* information. It returns true unless the operation was cancelled.
* @param defaultID A default which may be used in selecting credentials.
* @param serverFQDN The fully qualified domain name of the host to which
* authentication is being attempted. Used with kerberos.
* @param protocol "IMAP", "POP", etc. Used with kerberos.
* @param Textual information to be provided to the client for obtaining a
* password. It may be localized.
* @return true if the operation is successful, otherwise, false.
*/
public boolean promptPassword(String defaultID, String serverFQDN,
String protocol, String prompt);
/**
* Called by a mechanism driver to retrieve the password obtained by the
* object during promptPassword.
* @return a Password
*/
public String getPassword();
}

View File

@ -1,44 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl;
import com.netscape.sasl.SASLException;
/**
* An object of this type translates buffers back and forth during a
* session, after the authentication process has completed.
*/
public interface SASLSecurityLayer {
/**
* Take a protocol-dependent byte array and encode it (encrypt, for
* example) for sending to the server.
* @param vals Byte array to be encoded.
* @return Encoded byte array.
* @exception SASLException if an encoded array could not be returned,
* e.g. because of insufficient memory.
*/
public byte[] encode( byte[] vals ) throws SASLException;
/**
* Take an encoded byte array received from the server and decode it.
* @param vals Encoded byte array.
* @return Decoded byte array.
* @exception SASLException if a decoded array could not be returned,
* e.g. because of insufficient memory.
*/
public byte[] decode( byte[] vals ) throws SASLException;
}

View File

@ -1,31 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl;
/**
* Present warning information to the user who must take some action to proceed.
*/
public interface SASLWarningClientCB extends SASLClientCB {
/**
* Presents the user with the supplied textual information and waits for
* the user to take some action to proceed.
* @param prompt Textual information to be provided to the client. It may
* be localized.
*/
public void promptWarning(String prompt);
}

View File

@ -0,0 +1,235 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package com.netscape.sasl;
import java.util.Hashtable;
import javax.security.auth.callback.CallbackHandler;
import java.util.StringTokenizer;
import java.io.*;
/**
* A static class for creating SASL clients and servers.
*<p>
* This class defines the policy of how to locate, load, and instantiate
* SASL clients and servers.
* Currently, only the client methods are available.
*<p>
* For example, an application or library gets a SASL client by doing
* something like:
*<blockquote><pre>
* SaslClient sc = Sasl.createSaslClient(mechanisms,
* authorizationId, protocol, serverName, props, callbackHandler);
*</pre></blockquote>
* It can then proceed to use the client create an authentication connection.
* For example, an LDAP library might use the client as follows:
*<blockquote><pre>
* InputStream is = ldap.getInputStream();
* OutputStream os = ldap.getOutputStream();
* byte[] toServer = sc.createInitialResponse();
* LdapResult res = ldap.sendBindRequest(dn, sc.getName(), toServer);
* while (!sc.isComplete() && res.status == SASL_BIND_IN_PROGRESS) {
* toServer = sc.evaluateChallenge(res.getBytesFromServer());
* if (toServer != null) {
* res = ldap.sendBindRequest(dn, sc.getName(), toServer);
* }
* }
* if (sc.isComplete() && res.status == SUCCESS) {
* // Get the input and output streams; may be unchanged
* is = sc.getInputStream( is );
* os = sc.getOutputStream( os );
* // Use these streams from now on
* ldap.setInputStream( is );
* ldap.setOutputStream( os );
* }
*</pre></blockquote>
*
* IMPLEMENTATION NOTE: To use this class on JDK1.2, the caller needs:
*<ul><tt>
*<li>java.lang.RuntimePermission("getSecurityManager")
*<li>java.lang.RuntimePermission("getClassLoader")
*<li>java.util.PropertyPermission("javax.security.sasl.client.pkgs", "read");
*</tt></ul>
*/
public class Sasl {
private static SaslClientFactory clientFactory = null;
static final boolean debug = false;
// Cannot create one of these
private Sasl() {
}
/**
* The property name containing a list of package names, separated by
* '|'. Each package contains a class named <tt>ClientFactory</tt> that
* implements the <tt>SaslClientFactory</tt> interface.
* Its value is "javax.security.sasl.client.pkgs".
*/
public static final String CLIENTPKGS = "javax.security.sasl.client.pkgs";
/**
* Creates a SaslClient using the parameters supplied.
* The algorithm for selection is as follows:
*<ol>
*<li>If a factory has been installed via <tt>setSaslClientFactory()</tt>,
* try it first. If non-null answer produced, return it.
*<li>The <tt>javax.security.sasl.client.pkgs</tt> property contains
* a '|'-separated list of package names. Each package contains a
* class named <tt>ClientFactory</tt>. Load each factory
* and try to create a <tt>SaslClient</tt>.
* Repeat this for
* each package on the list until a non-null answer is produced.
* If non-null answer produced, return it.
*<li>Repeat previous step using the <tt>javax.security.sasl.client.pkgs</tt>
* System property.
*<li>If no non-null answer produced, return null.
*</ol>
*
* @param mechanisms The non-null list of mechanism names to try. Each is the
* IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
* @param authorizationId The possibly null authorization ID to use. When
* the SASL authentication completes successfully, the entity named
* by authorizationId is granted access.
* @param protocol The non-null string name of the protocol for which
* the authentication is being performed (e.g., "ldap").
* @param serverName The non-null string name of the server to which
* we are creating an authenticated connection.
* @param props The possibly null properties to be used by the SASL
* mechanisms to configure the authentication exchange. For example,
* "javax.security.sasl.encryption.maximum" might be used to specify
* the maximum key length to use for encryption.
* @param cbh The possibly null callback handler to used by the SASL
* mechanisms to get further information from the application/library
* to complete the authentication. For example, a SASL mechanism might
* require the authentication ID and password from the caller.
*@return A possibly null <tt>SaslClient</tt> created using the parameters
* supplied. If null, cannot find a <tt>SaslClientFactory</tt>
* that will produce one.
*@exception SaslException If cannot create a <tt>SaslClient</tt> because
* of an error.
*/
public static SaslClient createSaslClient(
String[] mechanisms,
String authorizationId,
String protocol,
String serverName,
Hashtable props,
CallbackHandler cbh) throws SaslException {
if (debug) {
System.out.println("Sasl.createSaslClient");
}
SaslClient mech = null;
// If factory has been set, try it first
if (clientFactory != null) {
mech = clientFactory.createSaslClient(
mechanisms, authorizationId,
protocol, serverName, props, cbh);
}
// No mechanism produced
if (mech == null) {
String pkgs = (props == null) ? null :
(String) props.get(CLIENTPKGS);
// Try properties argument
if (pkgs != null) {
mech = loadFromPkgList(pkgs, mechanisms,
authorizationId,
protocol, serverName,
props, cbh);
}
// Try system properties
if (mech == null &&
(pkgs = System.getProperty(CLIENTPKGS)) != null) {
mech = loadFromPkgList(pkgs, mechanisms,
authorizationId,
protocol, serverName,
props, cbh);
}
}
return mech;
}
private static SaslClient loadFromPkgList(String pkgs,
String[] mechanisms,
String authorizationId,
String protocol,
String serverName,
Hashtable props,
CallbackHandler cbh)
throws SaslException {
StringTokenizer packagePrefixIter = new StringTokenizer(pkgs, "|");
SaslClient mech = null;
SaslClientFactory fac = null;
while (mech == null && packagePrefixIter.hasMoreTokens()) {
String pkg = packagePrefixIter.nextToken().trim();
String clsName = pkg + ".ClientFactory";
if (debug) {
System.out.println("Sasl.loadFromPkgList: " + clsName);
}
Class cls = null;
try {
cls = Class.forName(clsName);
} catch (Exception e) {
System.err.println( "Sasl.loadFromPkgList: " + e );
}
if (cls != null) {
try {
fac = (SaslClientFactory) cls.newInstance();
} catch (InstantiationException e) {
throw new SaslException(
"Cannot instantiate " + clsName);
} catch (IllegalAccessException e) {
throw new SaslException(
"Cannot access constructor of " + clsName);
}
mech = fac.createSaslClient(mechanisms, authorizationId,
protocol, serverName, props,
cbh);
}
}
return mech;
}
/**
* Sets the default <tt>SaslClientFactory</tt> to use.
* This method sets <tt>fac</tt> to be the default factory.
* It can only be called with a non-null value once per VM.
* If a factory has been set already, this method throws
* <tt>IllegalStateException</tt>.
* @param fac The possibly null factory to set. If null, doesn't
* do anything.
* @exception IllegalStateException If factory already set.
*/
public static void setSaslClientFactory(SaslClientFactory fac) {
if (clientFactory != null) {
throw new IllegalStateException (
"SaslClientFactory already defined");
}
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkSetFactory();
}
clientFactory = fac;
}
}

View File

@ -0,0 +1,140 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package com.netscape.sasl;
import java.util.Hashtable;
import java.io.*;
/**
* Performs SASL authentication as a client.
*<p>
* A protocol library such as one for LDAP gets an instance of this
* class in order to perform authentication defined by a specific SASL
* mechanism. Invoking methods on the <tt>SaslClient</tt> instance
* process challenges and create responses according to the SASL
* mechanism implemented by the <tt>SaslClient</tt>.
* As the authentication proceeds, the instance
* encapsulates the state of a SASL client's authentication exchange.
*<p>
* Here's an example of how an LDAP library might use a <tt>SaslClient</tt>.
* It first gets an instance of a <tt>SaslClient</tt>:
*<blockquote><pre>
* SaslClient sc = Sasl.createSaslClient(mechanisms,
* authorizationId, protocol, serverName, props, callbackHandler);
*</pre></blockquote>
* It can then proceed to use the client for authentication.
* For example, an LDAP library might use the client as follows:
*<blockquote><pre>
* InputStream is = ldap.getInputStream();
* OutputStream os = ldap.getOutputStream();
* byte[] toServer = sc.createInitialResponse();
* LdapResult res = ldap.sendBindRequest(dn, sc.getName(), toServer);
* while (!sc.isComplete() && res.status == SASL_BIND_IN_PROGRESS) {
* toServer = sc.evaluateChallenge(res.getBytesFromServer());
* if (toServer != null) {
* res = ldap.sendBindRequest(dn, sc.getName(), toServer);
* }
* }
* if (sc.isComplete() && res.status == SUCCESS) {
* // Get the input and output streams; may be unchanged
* is = sc.getInputStream( is );
* os = sc.getOutputStream( os );
* // Use these streams from now on
* ldap.setInputStream( is );
* ldap.setOutputStream( os );
* }
*</pre></blockquote>
*
* Note that the call to <tt>createInitialResponse()</tt> is optional.
* Protocols such as IMAP4 do not invoke it but instead only use
* <tt>evaluateChallenge()</tt>, possibly with an empty challenge.
* It is the responsibility of the <tt>SaslClient</tt> implementation
* for a mechanism to take this into account so that it behaves properly
* regardless of whether <tt>createInitialResponse()</tt> is called.
*
* @see Sasl
* @see SaslClientFactory
*/
public abstract interface SaslClient {
/**
* Returns the IANA-registered mechanism name of this SASL client.
* (e.g. "CRAM-MD5", "GSSAPI").
* @return A non-null string representing the IANA-registered mechanism name.
*/
public abstract String getMechanismName();
/**
* Retrieves the initial response.
*
* @return The possibly null byte array containing the initial response.
* It is null if the mechanism does not have an initial response.
* @exception SaslException If an error occurred while creating
* the initial response.
*/
public abstract byte[] createInitialResponse() throws SaslException;
/**
* Evaluates the challenge data and generates a response.
*
* @param challenge The non-null challenge sent from the server.
*
* @return The possibly null reponse to send to the server.
* It is null if the challenge accompanied a "SUCCESS" status and the challenge
* only contains data for the client to update its state and no response
* needs to be sent to the server.
* @exception SaslException If an error occurred while processing
* the challenge or generating a response.
*/
public abstract byte[] evaluateChallenge(byte[] challenge)
throws SaslException;
/**
* Determines whether the authentication exchange has completed.
* @return true if the authentication exchange has completed; false otherwise.
*/
public abstract boolean isComplete();
/**
* Retrieves an input stream for the session. It may return
* the same stream that is passed in, if no processing is to be
* done by the client object.
*
* This method can only be called if isComplete() returns true.
* @param is The original input stream for reading from the server.
* @return An input stream for reading from the server, which
* may include processing the original stream.
* @exception IOException If the authentication exchange has not completed
* or an error occurred while getting the stream.
*/
public abstract InputStream getInputStream(InputStream is) throws IOException;
/**
* Retrieves an output stream for the session. It may return
* the same stream that is passed in, if no processing is to be
* done by the client object.
*
* This method can only be called if isComplete() returns true.
* @param is The original output stream for writing to the server.
* @return An output stream for writing to the server, which
* may include processing the original stream.
* @exception IOException If the authentication exchange has not completed
* or an error occurred while getting the stream.
*/
public abstract OutputStream getOutputStream(OutputStream os) throws IOException;
}

View File

@ -0,0 +1,69 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package com.netscape.sasl;
import java.util.Hashtable;
import javax.security.auth.callback.CallbackHandler;
/**
* An interface for creating instances of <tt>SaslClient</tt>.
*
* @see SaslClient
* @see Sasl
*/
public abstract interface SaslClientFactory {
/**
* Creates a SaslClient using the parameters supplied.
*
* @param mechanisms The non-null list of mechanism names to try. Each is the
* IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
* @param authorizationId The possibly null authorization ID to use. When
* the SASL authentication completes successfully, the entity named
* by authorizationId is granted access.
* @param protocol The non-null string name of the protocol for which
* the authentication is being performed (e.g., "ldap").
* @param serverName The non-null string name of the server to which
* we are creating an authenticated connection.
* @param props The possibly null properties to be used by the SASL
* mechanisms to configure the authentication exchange. For example,
* "javax.security.sasl.encryption.maximum" might be used to specify
* the maximum key length to use for encryption.
* @param cbh The possibly null callback handler to used by the SASL
* mechanisms to get further information from the application/library
* to complete the authentication. For example, a SASL mechanism might
* require the authentication ID and password from the caller.
*@return A possibly null <tt>SaslClient</tt> created using the parameters
* supplied. If null, this factory cannot produce a <tt>SaslClient</tt>
* using the parameters supplied.
*@exception SaslException If cannot create a <tt>SaslClient</tt> because
* of an error.
*/
public abstract SaslClient createSaslClient(
String[] mechanisms,
String authorizationId,
String protocol,
String serverName,
Hashtable props,
CallbackHandler cbh) throws SaslException;
/**
* Returns an array of names of mechanisms supported by this factory.
* @return A non-null array containing a IANA-registered SASL mechanism names.
*/
public abstract String[] getMechanismNames();
}

View File

@ -0,0 +1,146 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package com.netscape.sasl;
/**
* This class represents an error that has occurred when using SASL.
*
*/
public class SaslException extends java.io.IOException {
/**
* The possibly null root cause exception.
* @serial
*/
private Throwable exception;
/**
* Constructs a new instance of <tt>SaslException</tt>.
* The root exception and the detailed message are null.
*/
public SaslException () {
super();
}
/**
* Constructs a new instance of <tt>SaslException</tt> with a detailed message.
* The root exception is null.
* @param detail A possibly null string containing details of the exception.
*
* @see java.lang.Throwable#getMessage
*/
public SaslException (String detail) {
super(detail);
}
/**
* Constructs a new instance of <tt>SaslException</tt> with a detailed message
* and a root exception.
* For example, a SaslException might result from a problem with
* the callback handler, which might throw a NoSuchCallbackException if
* it does not support the requested callback, or throw an IOException
* if it had problems obtaining data for the callback. The
* SaslException's root exception would be then be the exception thrown
* by the callback handler.
*
* @param detail A possibly null string containing details of the exception.
* @param ex A possibly null root exception that caused this exception.
*
* @see java.lang.Throwable#getMessage
* @see #getException
*/
public SaslException (String detail, Throwable ex) {
super(detail);
exception = ex;
}
/**
* Returns the root exception that caused this exception.
* @return The possibly null root exception that caused this exception.
*/
public Throwable getException() {
return exception;
}
/**
* Prints this exception's stack trace to <tt>System.err</tt>.
* If this exception has a root exception; the stack trace of the
* root exception is printed to <tt>System.err</tt> instead.
*/
public void printStackTrace() {
printStackTrace( System.err );
}
/**
* Prints this exception's stack trace to a print stream.
* If this exception has a root exception; the stack trace of the
* root exception is printed to the print stream instead.
* @param ps The non-null print stream to which to print.
*/
public void printStackTrace(java.io.PrintStream ps) {
if ( exception != null ) {
String superString = super.toString();
synchronized ( ps ) {
ps.print(superString
+ (superString.endsWith(".") ? "" : ".")
+ " Root exception is ");
exception.printStackTrace( ps );
}
} else {
super.printStackTrace( ps );
}
}
/**
* Prints this exception's stack trace to a print writer.
* If this exception has a root exception; the stack trace of the
* root exception is printed to the print writer instead.
* @param ps The non-null print writer to which to print.
*/
public void printStackTrace(java.io.PrintWriter pw) {
if ( exception != null ) {
String superString = super.toString();
synchronized (pw) {
pw.print(superString
+ (superString.endsWith(".") ? "" : ".")
+ " Root exception is ");
exception.printStackTrace( pw );
}
} else {
super.printStackTrace( pw );
}
}
/**
* Returns the string representation of this exception.
* The string representation contains
* this exception's class name, its detailed messsage, and if
* it has a root exception, the string representation of the root
* exception. This string representation
* is meant for debugging and not meant to be interpreted
* programmatically.
* @return The non-null string representation of this exception.
* @see java.lang.Throwable#getMessage
*/
public String toString() {
String answer = super.toString();
if (exception != null && exception != this) {
answer += " [Root exception is " + exception.toString() + "]";
}
return answer;
}
}

View File

@ -1,104 +0,0 @@
/* -*- 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.
*/
package com.netscape.sasl.mechanisms;
import com.netscape.sasl.*;
/**
* This class provides the implementation of the EXTERNAL mechanism driver.
* This mechanism is passed in the SASL External bind request to retrieve the
* current result code from the server.
*/
public class SASLExternalMechanism implements SASLClientMechanismDriver {
/**
* Default constructor
*/
public SASLExternalMechanism() {
m_mechanismName = MECHANISM_NAME;
}
/**
* This method prepares a byte array to use for the initial request to
* authenticate.
* @param id Protocol-dependent identification, for this class, it is ignored.
* @param protocol A protocol supported by the mechanism driver, e.g.
* "pop3", "ldap"
* @param serverName For this class, it is ignored.
* @param props Additional configuration for the session. For this class,
* it is ignored.
* @param authCB An optional object which can be invoked by the mechanism
* driver to acquire additional authentication information, such
* as user name and password. For this class, it is ignored.
* @return An byte array. For the case of the SASL External bind, it is
* always null.
* @exception SASLException Never thrown by this class.
*/
public byte[] startAuthentication(String id, String protocol,
String serverName, java.util.Properties props, SASLClientCB authCB)
throws SASLException {
return null;
}
/**
* Returns the name of mechanism driver.
* @return The mechanism name.
*/
public String getMechanismName() {
return m_mechanismName;
}
/**
* The protocol driver prepares an appropriate next request to submit
* to the server based on the challenge received from the server.
* @param challenge For this class, it is ignored.
* @return Request to submit to server. For this class, it is always null.
* @exception SASLException Never thrown by this class.
*/
public byte[] evaluateResponse(byte[] challenge) throws SASLException {
return null;
}
/**
* The method may be called at any time to determine if the authentication
* process is finished.
* @return <CODE>true</CODE> if authentication is complete. For this class,
* always returns <CODE>true</CODE>.
*/
public boolean isComplete() {
return true;
}
/**
* The protocol driver calls the method to obtain an object capable of
* encoding/decoding data content for the rest of the session (or until
* there is a new round of authentication). An exception is thrown if
* authentication is not yet complete.
* @return A SASLSecurityLayer object. For this class, it is always null.
* @exception SASLException Never thrown by this class.
*/
public SASLSecurityLayer getSecurityLayer() throws SASLException {
return null;
}
private final static String LDAP_PROTOCOL = "LDAP";
private final static String MECHANISM_NAME = "EXTERNAL";
private String m_packageName;
private String m_mechanismName;
}

View File

@ -0,0 +1,121 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package com.netscape.sasl.mechanisms;
import java.io.*;
import com.netscape.sasl.*;
/**
* This class provides the implementation of the EXTERNAL mechanism driver.
* This mechanism is passed in the SASL External bind request to retrieve the
* current result code from the server.
*/
public class SaslExternal implements SaslClient {
/**
* Default constructor
*/
public SaslExternal() {
}
/**
* Retrieves the initial response.
*
* @return The possibly null byte array containing the initial response.
* It is null if the mechanism does not have an initial response.
* @exception SaslException If an error occurred while creating
* the initial response.
*/
public byte[] createInitialResponse() throws SaslException {
return null;
}
/**
* Evaluates the challenge data and generates a response.
*
* @param challenge The non-null challenge sent from the server.
*
* @return The possibly null reponse to send to the server.
* It is null if the challenge accompanied a "SUCCESS" status
* and the challenge only contains data for the client to
* update its state and no response needs to be sent to the server.
* @exception SaslException If an error occurred while processing
* the challenge or generating a response.
*/
public byte[] evaluateChallenge(byte[] challenge)
throws SaslException {
return null;
}
/**
* Returns the name of mechanism driver.
* @return The mechanism name.
*/
public String getMechanismName() {
return MECHANISM_NAME;
}
/**
* The method may be called at any time to determine if the authentication
* process is finished.
* @return <CODE>true</CODE> if authentication is complete. For this class,
* always returns <CODE>true</CODE>.
*/
public boolean isComplete() {
return true;
}
/**
* Retrieves an input stream for the session. It may return
* the same stream that is passed in, if no processing is to be
* done by the client object.
*
* This method can only be called if isComplete() returns true.
* @param is The original input stream for reading from the server.
* @return An input stream for reading from the server, which
* may include processing the original stream. For this class, the
* input parameter is always returned.
* @exception IOException If the authentication exchange has not completed
* or an error occurred while getting the stream.
*/
public InputStream getInputStream(InputStream is)
throws IOException {
return is;
}
/**
* Retrieves an output stream for the session. It may return
* the same stream that is passed in, if no processing is to be
* done by the client object.
*
* This method can only be called if isComplete() returns true.
* @param is The original output stream for writing to the server.
* @return An output stream for writing to the server, which
* may include processing the original stream. For this class, the
* input parameter is always returned.
* @exception IOException If the authentication exchange has not completed
* or an error occurred while getting the stream.
*/
public OutputStream getOutputStream(OutputStream os)
throws IOException {
return os;
}
private final static String MECHANISM_NAME = "EXTERNAL";
}

Binary file not shown.

View File

@ -0,0 +1,88 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import java.lang.reflect.*;
import java.util.Hashtable;
/**
* Utility class to dynamically find methods of a class and to invoke
* them
*/
class DynamicInvoker {
static Object invokeMethod(Object obj, String packageName,
String methodName, Object[] args, String[] argNames)
throws LDAPException {
try {
java.lang.reflect.Method m = getMethod(packageName, methodName,
argNames);
if (m != null) {
return (m.invoke(obj, args));
}
} catch (Exception e) {
throw new LDAPException("Invoking "+methodName+": "+
e.toString(), LDAPException.PARAM_ERROR);
}
return null;
}
static java.lang.reflect.Method getMethod(String packageName,
String methodName, String[] args) throws LDAPException {
try {
java.lang.reflect.Method method = null;
String suffix = "";
if (args != null)
for (int i=0; i<args.length; i++)
suffix = suffix+args[i].getClass().getName();
String key = packageName+"."+methodName+"."+suffix;
if ((method = (java.lang.reflect.Method)(m_methodLookup.get(key)))
!= null)
return method;
Class c = Class.forName(packageName);
java.lang.reflect.Method[] m = c.getMethods();
for (int i = 0; i < m.length; i++ ) {
Class[] params = m[i].getParameterTypes();
if ((m[i].getName().equals(methodName)) &&
signatureCorrect(params, args)) {
m_methodLookup.put(key, m[i]);
return m[i];
}
}
throw new LDAPException("Method " + methodName + " not found in " +
packageName);
} catch (ClassNotFoundException e) {
throw new LDAPException("Class "+ packageName + " not found");
}
}
static private boolean signatureCorrect(Class params[], String args[]) {
if (args == null)
return true;
if (params.length != args.length)
return false;
for (int i=0; i<params.length; i++) {
if (!params[i].getName().equals(args[i]))
return false;
}
return true;
}
private static Hashtable m_methodLookup = new Hashtable();
}

View File

@ -0,0 +1,438 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import java.util.*;
import java.io.*;
import javax.security.auth.callback.CallbackHandler;
/**
* Encapsulates a connection to an LDAP server, providing access to the input queue
* for messages received.
*
* @version 1.0
*/
public interface LDAPAsynchronousConnection {
/**
* Adds an entry to the directory.
*
* @param entry LDAPEntry object specifying the distinguished name and
* attributes of the new entry.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @param cons Constraints specific to the operation.
* @return LDAPSearchListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPEntry
* @see netscape.ldap.LDAPResponseListener
*/
public LDAPResponseListener add(LDAPEntry entry,
LDAPResponseListener listener)
throws LDAPException;
/**
* Adds an entry to the directory and allows you to specify constraints
* for this LDAP add operation by using an <CODE>LDAPConstraints</CODE>
* object. For example, you can specify whether or not to follow referrals.
* You can also apply LDAP v3 controls to the operation.
* <P>
*
* @param entry LDAPEntry object specifying the distinguished name and
* attributes of the new entry.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @param cons Constraints specific to the operation.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPEntry
* @see netscape.ldap.LDAPResponseListener
* @see netscape.ldap.LDAPConstraints
*/
public LDAPResponseListener add(LDAPEntry entry,
LDAPResponseListener listener,
LDAPConstraints cons)
throws LDAPException;
/**
* Authenticates to the LDAP server (that the object is currently
* connected to) using the specified name and password. If the object
* has been disconnected from an LDAP server, this method attempts to
* reconnect to the server. If the object had already authenticated, the
* old authentication is discarded.
*
* @param dn If non-null and non-empty, specifies that the connection
* and all operations through it should be authenticated with dn as the
* distinguished name.
* @param passwd If non-null and non-empty, specifies that the connection
* and all operations through it should be authenticated with dn as the
* distinguished name and passwd as password.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPResponseListener
*/
public LDAPResponseListener bind(String dn,
String passwd,
LDAPResponseListener listener)
throws LDAPException;
/**
* Authenticates to the LDAP server (that the object is currently
* connected to) using the specified name and password and allows you
* to specify constraints for this LDAP add operation by using an
* <CODE>LDAPConstraints</CODE> object. If the object
* has been disconnected from an LDAP server, this method attempts to
* reconnect to the server. If the object had already authenticated, the
* old authentication is discarded.
*
* @param dn If non-null and non-empty, specifies that the connection
* and all operations through it should be authenticated with dn as the
* distinguished name.
* @param passwd If non-null and non-empty, specifies that the connection
* and all operations through it should be authenticated with dn as the
* distinguished name and passwd as password.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @param cons Constraints specific to the operation.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPResponseListener
* @see netscape.ldap.LDAPConstraints
*/
public LDAPResponseListener bind(String dn,
String passwd,
LDAPResponseListener listener,
LDAPConstraints cons)
throws LDAPException;
/**
* Deletes the entry for the specified DN from the directory.
*
* @param dn Distinguished name of the entry to delete.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPResponseListener
* @see netscape.ldap.LDAPConstraints
*/
public LDAPResponseListener delete(String dn,
LDAPResponseListener listener)
throws LDAPException;
/**
* Deletes the entry for the specified DN from the directory.
*
* @param dn Distinguished name of the entry to delete.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @param cons Constraints specific to the operation.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPResponseListener
* @see netscape.ldap.LDAPConstraints
*/
public LDAPResponseListener delete(String dn,
LDAPResponseListener listener,
LDAPConstraints cons)
throws LDAPException;
/**
* Makes a single change to an existing entry in the directory (for
* example, changes the value of an attribute, adds a new attribute
* value, or removes an existing attribute value).<BR>
* The LDAPModification object specifies both the change to be made and
* the LDAPAttribute value to be changed.
*
* @param dn Distinguished name of the entry to modify.
* @param mod A single change to be made to an entry.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPModification
* @see netscape.ldap.LDAPResponseListener
*/
public LDAPResponseListener modify(String dn,
LDAPModification mod,
LDAPResponseListener listener)
throws LDAPException;
/**
* Makes a single change to an existing entry in the directory (for
* example, changes the value of an attribute, adds a new attribute
* value, or removes an existing attribute value).<BR>
* The LDAPModification object specifies both the change to be made and
* the LDAPAttribute value to be changed.
*
* @param dn Distinguished name of the entry to modify.
* @param mod A single change to be made to an entry.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @param cons Constraints specific to the operation.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPModification
* @see netscape.ldap.LDAPResponseListener
* @see netscape.ldap.LDAPConstraints
*/
public LDAPResponseListener modify(String dn,
LDAPModification mod,
LDAPResponseListener listener,
LDAPConstraints cons)
throws LDAPException;
/**
* Makes a set of changes to an existing entry in the directory (for
* example, changes attribute values, adds new attribute values, or
* removes existing attribute values).
* <P>
* @param dn Distinguished name of the entry to modify.
* @param mods A set of modifications to be made to the entry.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPModificationSet
* @see netscape.ldap.LDAPResponseListener
*/
public LDAPResponseListener modify(String dn,
LDAPModificationSet mods,
LDAPResponseListener listener)
throws LDAPException;
/**
* Makes a set of changes to an existing entry in the directory (for
* example, changes attribute values, adds new attribute values, or
* removes existing attribute values).
*
* @param dn Distinguished name of the entry to modify.
* @param mods A set of modifications to be made to the entry.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @param cons Constraints specific to the operation.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPModificationSet
* @see netscape.ldap.LDAPResponseListener
* @see netscape.ldap.LDAPConstraints
*/
public LDAPResponseListener modify(String dn,
LDAPModificationSet mods,
LDAPResponseListener listener,
LDAPConstraints cons)
throws LDAPException;
/**
* Renames an existing entry in the directory.
*
* @param dn Current distinguished name of the entry.
* @param newRdn New relative distinguished name for the entry.
* @param deleteOldRdn If true, the old name is not retained as an
* attribute value.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPResponseListener
*/
public LDAPResponseListener rename(String dn,
String newRdn,
boolean deleteOldRdn,
LDAPResponseListener listener)
throws LDAPException;
/**
* Renames an existing entry in the directory.
*
* @param dn Current distinguished name of the entry.
* @param newRdn New relative distinguished name for the entry.
* @param deleteOldRdn If true, the old name is not retained as an
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @param cons Constraints specific to the operation.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPResponseListener
* @see netscape.ldap.LDAPConstraints
*/
public LDAPResponseListener rename(String dn,
String newRdn,
boolean deleteOldRdn,
LDAPResponseListener listener,
LDAPConstraints cons)
throws LDAPException;
/**
* Performs the search specified by the criteria that you enter. <P>
* To abandon the search, use the <CODE>abandon</CODE> method.
*
* @param base The base distinguished name to search from
* @param scope The scope of the entries to search. You can specify one
* of the following: <P>
* <UL>
* <LI><CODE>LDAPv2.SCOPE_BASE</CODE> (search only the base DN) <P>
* <LI><CODE>LDAPv2.SCOPE_ONE</CODE>
* (search only entries under the base DN) <P>
* <LI><CODE>LDAPv2.SCOPE_SUB</CODE>
* (search the base DN and all entries within its subtree) <P>
* </UL>
* <P>
* @param filter Search filter specifying the search criteria.
* @param attrs List of attributes that you want returned in the
* search results.
* @param typesOnly If true, returns the names but not the values of the
* attributes found. If false, returns the names and values for
* attributes found
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @return LDAPSearchListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPAsynchronousConnection#abandon(netscape.ldap.LDAPSearchListener)
*/
public LDAPSearchListener search(String base,
int scope,
String filter,
String attrs[],
boolean typesOnly,
LDAPSearchListener listener)
throws LDAPException;
/**
* Performs the search specified by the criteria that you enter.
* This method also allows you to specify constraints for the search
* (such as the maximum number of entries to find or the
* maximum time to wait for search results). <P>
* To abandon the search, use the <CODE>abandon</CODE> method.
*
* @param base The base distinguished name to search from
* @param scope The scope of the entries to search. You can specify one
* of the following: <P>
* <UL>
* <LI><CODE>LDAPv2.SCOPE_BASE</CODE> (search only the base DN) <P>
* <LI><CODE>LDAPv2.SCOPE_ONE</CODE>
* (search only entries under the base DN) <P>
* <LI><CODE>LDAPv2.SCOPE_SUB</CODE>
* (search the base DN and all entries within its subtree) <P>
* </UL>
* <P>
* @param filter Search filter specifying the search criteria.
* @param attrs List of attributes that you want returned in the search
* results.
* @param typesOnly If true, returns the names but not the values of the
* attributes found. If false, returns the names and values for
* attributes found.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @param cons Constraints specific to this search (for example, the
* maximum number of entries to return).
* @return LDAPSearchListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
* @see netscape.ldap.LDAPAsynchronousConnection#abandon(netscape.ldap.LDAPSearchListener)
*/
public LDAPSearchListener search(String base,
int scope,
String filter,
String attrs[],
boolean typesOnly,
LDAPSearchListener listener,
LDAPSearchConstraints cons)
throws LDAPException;
/**
* Compare an attribute value with one in the directory. The result can
* be obtained by calling <CODE>getResultCode</CODE> on the
* <CODE>LDAPResponse</CODE> from the <CODE>LDAPResponseListener</CODE>.
* The code will be <CODE>LDAPException.COMPARE_TRUE</CODE> or
* <CODE>LDAPException.COMPARE_FALSE</CODE>.
*
* @param dn Distinguished name of the entry to compare.
* @param attr Attribute with a value to compare.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
*/
public LDAPResponseListener compare(String dn,
LDAPAttribute attr,
LDAPResponseListener listener)
throws LDAPException;
/**
* Compare an attribute value with one in the directory. The result can
* be obtained by calling <CODE>getResultCode</CODE> on the
* <CODE>LDAPResponse</CODE> from the <CODE>LDAPResponseListener</CODE>.
* The code will be <CODE>LDAPException.COMPARE_TRUE</CODE> or
* <CODE>LDAPException.COMPARE_FALSE</CODE>.
*
* @param dn Distinguished name of the entry to compare.
* @param attr Attribute with a value to compare.
* @param listener Handler for messages returned from a server in response
* to this request. If it is null, a listener object is created internally.
* @param cons Constraints specific to this operation.
* @return LDAPResponseListener Handler for messages returned from a server
* in response to this request.
* @exception LDAPException Failed to send request.
*/
public LDAPResponseListener compare(String dn,
LDAPAttribute attr,
LDAPResponseListener listener,
LDAPConstraints cons)
throws LDAPException;
/**
* Cancels the ldap request with the specified id and discards
* any results already received.
*
* @param id A LDAP request id
* @exception LDAPException Failed to send request.
*/
public void abandon(int id) throws LDAPException;
/**
* Cancels all outstanding search requests associated with this
* LDAPSearchListener object and discards any results already received.
*
* @param searchlistener A search listener returned from a search.
* @exception LDAPException Failed to send request.
*/
public void abandon(LDAPSearchListener searchlistener)
throws LDAPException;
}

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
@ -143,7 +143,31 @@ public class LDAPAttribute {
}
return v.elements();
}
/**
* Returns a array for the values of the attribute as <CODE>String</CODE> objects.
* @return Array of attribute values. Each element in the array
* will be a <CODE>String</CODE> object.
*/
public String[] getStringValueArray() {
String s[] = new String[values.length];
synchronized(this) {
try {
for (int i=0; i < values.length; i++) {
if ( values[i] !=null ) {
s[i] = new String((byte[])values[i], "UTF8");
} else {
s[i] = new String("");
}
}
} catch (Exception e) {
return null;
}
}
return s;
}
/**
* Returns an enumerator for the values of the attribute in <CODE>byte[]</CODE>
* format.
@ -164,6 +188,29 @@ public class LDAPAttribute {
return v.elements();
}
/**
* Returns an array for the values of the attribute in <CODE>byte[]</CODE>
* format.
* @return Array of attribute values. Each element in the array
* will be of type <CODE>byte[]</CODE>.
*/
public byte[][] getByteValueArray() {
byte b[][] = new byte[values.length][];
synchronized(this) {
try {
for (int i=0; i < values.length; i++) {
b[i] = new byte[((byte[])(values[i])).length];
System.arraycopy((byte[])values[i], 0, (byte[])b[i], 0,
((byte[])(values[i])).length);
}
} catch (Exception e) {
return null;
}
}
return b;
}
/**
* Returns the name of the attribute.
* @return Name of the attribute.
@ -445,23 +492,28 @@ public class LDAPAttribute {
* @return string representation parameters
*/
private String getParamString() {
String s = "";
StringBuffer sb = new StringBuffer();
if ( values.length > 0 ) {
for (int i = 0; i < values.length; i++) {
if (i != 0)
s = s + ",";
if (i != 0) {
sb.append(",");
}
byte[] val = (byte[])values[i];
try {
s = s + new String(val, "UTF8");
sb.append(new String(val, "UTF8"));
} catch (Exception e) {
if (val != null)
s = s + val.length + " bytes";
else
s = s + "null value";
if (val != null) {
sb.append(val.length);
sb.append(" bytes");
}
else {
sb.append("null value");
}
}
}
}
return "{type='" + getName() + "', values='" + s + "'}";
return "{type='" + getName() + "', values='" + sb.toString() + "'}";
}
/**

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
@ -44,22 +44,66 @@ import java.util.*;
* When you construct an <CODE>LDAPAttributeSchema</CODE> object, you can
* specify these types of information as arguments to the constructor or
* in the AttributeTypeDescription format specified in RFC 2252.
* (When an LDAP client searches an LDAP server for the schema, the server
* When an LDAP client searches an LDAP server for the schema, the server
* returns schema information as an object with attribute values in this
* format.)
* format.
* <P>
* There a number of additional optional description fields which
* are not explicitly accessible through LDAPAttributeSchema, but which
* can be managed with setQualifier, getQualifier, and getQualifierNames:
* <P>
*
* <UL>
* <LI>EQUALITY
* <LI>ORDERING
* <LI>SUBSTR
* <LI>COLLECTIVE
* <LI>NO-USER-MODIFICATION
* <LI>USAGE
* <LI>OBSOLETE
* </UL>
* <P>
*
* You can get the name, OID, and description of this attribute type
* definition by using the <CODE>getName</CODE>, <CODE>getOID</CODE>, and
* <CODE>getDescription</CODE> methods inherited from the abstract class
* <CODE>LDAPSchemaElement</CODE>.
* <CODE>LDAPSchemaElement</CODE>. Optional and custom qualifiers are
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
* from <CODE>LDAPSchemaElement</CODE>.
* <P>
*
* If you need to add or remove this attribute type definition from the
* schema, you can use the <CODE>add</CODE> and <CODE>remove</CODE>
* To add or remove this attribute type definition from the
* schema, use the <CODE>add</CODE> and <CODE>remove</CODE>
* methods, which this class inherits from the <CODE>LDAPSchemaElement</CODE>
* abstract class.
* <P>
* RFC 2252 defines AttributeTypeDescription as follows:
* <P>
* <PRE>
* AttributeTypeDescription = "(" whsp
* numericoid whsp ; AttributeType identifier
* [ "NAME" qdescrs ] ; name used in AttributeType
* [ "DESC" qdstring ] ; description
* [ "OBSOLETE" whsp ]
* [ "SUP" woid ] ; derived from this other
* ; AttributeType
* [ "EQUALITY" woid ; Matching Rule name
* [ "ORDERING" woid ; Matching Rule name
* [ "SUBSTR" woid ] ; Matching Rule name
* [ "SYNTAX" whsp noidlen whsp ] ; see section 4.3
* [ "SINGLE-VALUE" whsp ] ; default multi-valued
* [ "COLLECTIVE" whsp ] ; default not collective
* [ "NO-USER-MODIFICATION" whsp ]; default user modifiable
* [ "USAGE" whsp AttributeUsage ]; default userApplications
* whsp ")"
*
* AttributeUsage =
* "userApplications" /
* "directoryOperation" /
* "distributedOperation" / ; DSA-shared
* "dSAOperation" ; DSA-specific, value depends on server
* </PRE>
*
* @version 1.0
* @see netscape.ldap.LDAPSchemaElement
@ -98,6 +142,27 @@ public class LDAPAttributeSchema extends LDAPSchemaElement {
super( name, oid, description );
attrName = "attributetypes";
this.syntax = syntax;
this.syntaxString = internalSyntaxToString();
this.single = single;
}
/**
* Constructs an attribute type definition, using the specified
* information.
* @param name Name of the attribute type.
* @param oid Object identifier (OID) of the attribute type
* in dotted-string format (for example, "1.2.3.4").
* @param description Description of attribute type.
* @param syntaxString Syntax of this attribute type in dotted-string
* format (for example, "1.2.3.4.5").
* @param single <CODE>true</CODE> if the attribute type is single-valued.
*/
public LDAPAttributeSchema( String name, String oid, String description,
String syntaxString, boolean single ) {
super( name, oid, description );
attrName = "attributetypes";
this.syntaxString = syntaxString;
this.syntax = syntaxCheck( syntaxString );
this.single = single;
}
@ -119,59 +184,13 @@ public class LDAPAttributeSchema extends LDAPSchemaElement {
*/
public LDAPAttributeSchema( String raw ) {
attrName = "attributetypes";
raw.trim();
// Skip past "( " and ")"
int l = raw.length();
raw = raw.substring( 2, l - 1 );
l = raw.length();
int ind = raw.indexOf( ' ' );
oid = raw.substring( 0, ind );
char[] ch = new char[l];
raw = raw.substring( ind + 1, l );
l = raw.length();
raw.getChars( 0, l, ch, 0 );
ind = 0;
l = ch.length;
while ( ind < l ) {
String s = "";
String val;
while( ch[ind] == ' ' )
ind++;
int last = ind + 1;
while( (last < l) && (ch[last] != ' ') )
last++;
if ( (ind < l) && (last < l) ) {
s = new String( ch, ind, last-ind );
ind = last;
if ( s.equalsIgnoreCase( "SINGLE-VALUE" ) ) {
single = true;
continue;
}
} else {
ind = l;
}
while( (ind < l) && (ch[ind] != '\'') )
ind++;
last = ind + 1;
while( (last < l) && (ch[last] != '\'') ) {
last++;
}
if ( (ind < last) && (last < l) ) {
val = new String( ch, ind+1, last-ind-1 );
ind = last + 1;
if ( s.equalsIgnoreCase( "NAME" ) ) {
name = val;
} else if ( s.equalsIgnoreCase( "DESC" ) ) {
description = val;
} else if ( s.equalsIgnoreCase( "SYNTAX" ) ) {
syntax = syntaxCheck( val );
}
}
parseValue( raw );
String val = (String)properties.get( SYNTAX );
if ( val != null ) {
syntaxString = val;
syntax = syntaxCheck( val );
}
single = properties.containsKey( "SINGLE-VALUE" );
}
/**
@ -185,12 +204,22 @@ public class LDAPAttributeSchema extends LDAPSchemaElement {
* <LI><CODE>telephone</CODE> (telephone number -- identical to cis,
* but blanks and dashes are ignored during comparisons)
* <LI><CODE>dn</CODE> (distinguished name)
* <LI><CODE>unknown</CODE> (not a known syntax)
* </UL>
*/
public int getSyntax() {
return syntax;
}
/**
* Gets the syntax of the attribute type in dotted-decimal format,
* for example "1.2.3.4.5"
* @return the attribute syntax in dotted-decimal format.
*/
public String getSyntaxString() {
return syntaxString;
}
/**
* Determines if the attribute type is single-valued.
* @return <code>true</code> if single-valued,
@ -215,41 +244,11 @@ public class LDAPAttributeSchema extends LDAPSchemaElement {
} else if ( syntax == integer ) {
s = intString;
} else {
s = "unknown";
s = syntaxString;
}
return s;
}
/**
* Get the attribute type definition in a string representation
* of the AttributeTypeDescription data type defined in X.501 (see
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol
* (v3): Attribute Syntax Definitions</A>
* for a description of this format).
* This is the format that LDAP servers and clients use to exchange
* schema information. (For example, when
* you search an LDAP server for its schema, the server returns an entry
* with the attributes "objectclasses" and "attributetypes". The
* values of the "attributetypes" attribute are attribute type
* descriptions in this format.)
* <P>
*
* @return A string in a format that can be used as the value of
* the <CODE>attributetypes</CODE> attribute (which describes
* an attribute type in the schema) of a <CODE>subschema</CODE> object.
*/
public String getValue() {
String s = "( " + oid + " NAME \'" + name + "\' DESC \'" +
description + "\' SYNTAX \'";
s += internalSyntaxToString();
s += "\' ";
if ( single )
s += "SINGLE-VALUE ";
s += ')';
return s;
}
protected String syntaxToString() {
String s;
if ( syntax == cis ) {
@ -265,11 +264,43 @@ public class LDAPAttributeSchema extends LDAPSchemaElement {
} else if ( syntax == dn ) {
s = "distinguished name";
} else {
s = "unknown";
s = syntaxString;
}
return s;
}
/**
* Prepare a value in RFC 2252 format for submitting to a server
*
* @param quotingBug <CODE>true</CODE> if SUP and SYNTAX values are to
* be quoted. That is to satisfy bugs in certain LDAP servers.
* @return A String ready to be submitted to an LDAP server
*/
String getValue( boolean quotingBug ) {
String s = getValuePrefix();
s += getValue( SUPERIOR, false );
String val = getOptionalValues( MATCHING_RULES );
if ( val.length() > 0 ) {
s += val + ' ';
}
s += getValue( SYNTAX, quotingBug );
s += ' ';
val = getOptionalValues( NOVALS );
if ( val.length() > 0 ) {
s += val + ' ';
}
val = getOptionalValues( new String[] {USAGE} );
if ( val.length() > 0 ) {
s += val + ' ';
}
val = getCustomValues();
if ( val.length() > 0 ) {
s += val + ' ';
}
s += ')';
return s;
}
/**
* Get the definition of the attribute type in a user friendly format.
* This is the format that the attribute type definition uses when
@ -280,10 +311,12 @@ public class LDAPAttributeSchema extends LDAPSchemaElement {
String s = "Name: " + name + "; OID: " + oid + "; Type: ";
s += syntaxToString();
s += "; Description: " + description + "; ";
if ( single )
if ( single ) {
s += "single-valued";
else
} else {
s += "multi-valued";
}
s += getQualifierString( EXPLICIT );
return s;
}
@ -305,6 +338,64 @@ public class LDAPAttributeSchema extends LDAPSchemaElement {
return i;
}
/**
* Parses an attribute schema definition to see if the SYNTAX value
* is quoted. It shouldn't be (according to RFC 2252), but it is for
* some LDAP servers. It will either be:<BR>
* <CODE>SYNTAX 1.3.6.1.4.1.1466.115.121.1.15</CODE> or<BR>
* <CODE>SYNTAX '1.3.6.1.4.1.1466.115.121.1.15'</CODE>
* @param raw Definition of the attribute type in the
* AttributeTypeDescription format.
*/
static boolean isSyntaxQuoted( String raw ) {
int ind = raw.indexOf( " SYNTAX " );
if ( ind >= 0 ) {
ind += 8;
int l = raw.length() - ind;
// Extract characters
char[] ch = new char[l];
raw.getChars( ind, raw.length(), ch, 0 );
ind = 0;
// Skip to ' or start of syntax value
while( (ind < ch.length) && (ch[ind] == ' ') ) {
ind++;
}
if ( ind < ch.length ) {
return ( ch[ind] == '\'' );
}
}
return false;
}
// Predefined qualifiers
public static final String EQUALITY = "EQUALITY";
public static final String ORDERING = "ORDERING";
public static final String SUBSTR = "SUBSTR";
public static final String SINGLE = "SINGLE-VALUE";
public static final String COLLECTIVE = "COLLECTIVE";
public static final String NO_USER_MODIFICATION = "NO-USER-MODIFICATION";
public static final String USAGE = "USAGE";
public static final String SYNTAX = "SYNTAX";
protected int syntax = unknown;
private boolean single = false;
protected String syntaxString = null;
protected boolean single = false;
static String[] NOVALS = { SINGLE,
COLLECTIVE,
NO_USER_MODIFICATION };
static {
for( int i = 0; i < NOVALS.length; i++ ) {
novalsTable.put( NOVALS[i], NOVALS[i] );
}
}
static final String[] MATCHING_RULES = { EQUALITY,
ORDERING,
SUBSTR };
// Qualifiers tracked explicitly
static final String[] EXPLICIT = { SINGLE,
OBSOLETE,
COLLECTIVE,
NO_USER_MODIFICATION,
SYNTAX};
}

View File

@ -388,11 +388,13 @@ public class LDAPAttributeSet implements Cloneable
* @return String representation of all attributes in the set.
*/
public String toString() {
String s = "LDAPAttributeSet: ";
if ( attrs.length > 0 ) {
for( int i = 0; i < attrs.length; i++ )
s += attrs[i].toString();
StringBuffer sb = new StringBuffer("LDAPAttributeSet: ");
for( int i = 0; i < attrs.length; i++ ) {
if (i != 0) {
sb.append(" ");
}
sb.append(attrs[i].toString());
}
return s;
return sb.toString();
}
}

View File

@ -0,0 +1,43 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
/**
* Used to do explicit bind processing on a referral. A client may
* specify an instance of this class to be used on a single operation
* (through the <CODE>LDAPConstraints</CODE> object) or for all operations
* (through <CODE>LDAPConnection.setOption()</CODE>). It is typically used
* to control the authentication mechanism used on implicit referral
* handling.
*/
public interface LDAPBind {
/**
* This method is called by <CODE>LDAPConnection</CODE> when
* authenticating. An implementation may access the host, port,
* credentials, and other information in the <CODE>LDAPConnection</CODE>
* to decide on an appropriate authentication mechanism, and/or may
* interact with a user or external module.
* @exception netscape.ldap.LDAPException
* @see netscape.ldap.LDAPConnection#bind
* @param conn An established connection to an LDAP server.
*/
public void bind(LDAPConnection conn) throws LDAPException;
}

View File

@ -19,7 +19,6 @@ package netscape.ldap;
import java.util.*;
import java.io.*;
import netscape.ldap.*;
import netscape.ldap.client.*;
import netscape.ldap.util.*;
import java.util.zip.CRC32;
@ -254,7 +253,8 @@ public class LDAPCache implements TimerEventListener {
break;
}
}
if ((scope == LDAPConnection.SCOPE_SUB) && (dn1.contains(dn2))) {
if ((scope == LDAPConnection.SCOPE_SUB) &&
(dn1.isDescendantOf(dn2))) {
break;
}
}
@ -357,7 +357,7 @@ public class LDAPCache implements TimerEventListener {
* @exception LDAPException Thrown when failed to create key.
*/
Long createKey(String host, int port, String baseDN, String filter,
int scope, String[] attrs, String bindDN, LDAPSearchConstraints cons)
int scope, String[] attrs, String bindDN, LDAPConstraints cons)
throws LDAPException {
DN dn = new DN(baseDN);
@ -617,11 +617,13 @@ public class LDAPCache implements TimerEventListener {
if ((str == null) || (str.length < 1))
return "0"+DELIM;
else {
sortStrings(str);
String[] sorted = new String[str.length];
System.arraycopy( str, 0, sorted, 0, str.length );
sortStrings(sorted);
String s = str.length+DELIM;
for (int i=0; i<str.length; i++)
s = s+str[i].trim()+DELIM;
String s = sorted.length+DELIM;
for (int i=0; i<sorted.length; i++)
s = s+sorted[i].trim()+DELIM;
return s;
}
}
@ -687,25 +689,11 @@ class Timer {
t.start();
}
/**
* Suspend the timer.
*/
void suspend() {
t.suspend();
}
/**
* Stop the timer.
*/
void stop() {
t.stop();
}
/**
* Restart the timer.
*/
void restart() {
t.resume();
t.interrupt();
}
/**
@ -770,7 +758,7 @@ class TimerRunnable implements Runnable {
try {
this.wait(m_timer.getTimeout());
} catch (InterruptedException e) {
System.out.println("Timer get interrupted");
// This happens if the timer is stopped
}
}

View File

@ -36,10 +36,10 @@ class LDAPCheckComm {
if ( sec == null ) {
/* Not an applet, we can do what we want to */
throw new LDAPException("No security manager");
return null;
} else if ( sec.toString().startsWith("java.lang.NullSecurityManager") ) {
/* Not an applet, we can do what we want to */
throw new LDAPException("No security manager");
return null;
} else if (sec.toString().startsWith("netscape.security.AppletSecurity")) {
/* Running as applet. Is PrivilegeManager around? */
try {

View File

@ -0,0 +1,408 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import java.util.*;
import java.io.*;
import java.net.*;
/**
* Make a connection to a server from a list using "smart" failover.
* Connection attempts can be made serially from the same thread, or
* in parallel by creating a separate thread after the specified delay.
* Connection setup status is preserved for later attempts, so that servers
* that are more likely to be available will be tried first.
* When a connection is successfully created, a socket is opened. The socket
* is passed to the LDAPConnThread. The LDAPConnThread must call
* invalidateConnection() if the connection is lost due to a network or
* server error, or disconnect() if the connection is deliberately terminated
* by the user.
*/
class LDAPConnSetupMgr implements Cloneable{
/**
* Policy for opening a connection when multiple servers are used
*/
private static final int SERIAL = 0;
private static final int PARALLEL = 1;
/**
* ServerEntry.connSetupStatus possible value. The values also represent
* the likelihood that the connection will be setup to a server. Lower
* values have higher priority. See sortDsList() method
*/
private static final int CONNECTED = 0;
private static final int DISCONNECTED = 1;
private static final int NEVER_USED = 2;
private static final int FAILED = 3;
/**
* Representation for a server in the server list.
*/
class ServerEntry {
String host;
int port;
int connSetupStatus;
Thread connSetupThread;
ServerEntry(String host, int port, int status) {
this.host = host;
this.port = port;
connSetupStatus = status;
connSetupThread = null;
}
public String toString() {
return "{" +host+":"+port + " status="+connSetupStatus+"}";
}
}
/**
* Socket to the connected server
*/
private Socket m_socket = null;
/**
* Last exception occured during connection setup
*/
private LDAPException m_connException = null;
/**
* List of server to use for the connection setup
*/
ServerEntry[] m_dsList;
/**
* Index of the last connected server
*/
private int m_dsIdx = -1;
/**
* Socket factory for SSL connections
*/
LDAPSocketFactory m_factory;
/**
* Connection setup policy (PARALLEL or SERIAL)
*/
int m_policy;
/**
* Delay in ms before another connection setup thread is started.
*/
int m_connSetupDelay;
/**
* Constructor
* @param host List of host names to connect to
* @param port List of port numbers corresponding to the host list
* @param factory Socket factory for SSL connections
* @param delay delay in seconds for the parallel connection setup policy.
* Possible values are: <br>(delay=-1) use serial policy,<br>
* (delay=0) start immediately concurrent threads to each specified server
* <br>(delay>0) create a new connection setup thread after delay seconds
*/
LDAPConnSetupMgr(String[] hosts, int[] ports, LDAPSocketFactory factory, int delay) {
m_dsList = new ServerEntry[hosts.length];
for (int i=0; i < hosts.length; i++) {
m_dsList[i] = new ServerEntry(hosts[i], ports[i], NEVER_USED);
}
m_factory = factory;
m_policy = (delay < 0) ? SERIAL : PARALLEL;
m_connSetupDelay = delay*1000;
}
/**
* Constructor used by clone()
*/
private LDAPConnSetupMgr() {}
/**
* Try to open the connection to any of the servers in the list.
*/
Socket openConnection() throws LDAPException{
m_socket = null;
m_connException = null;
// If reconnecting, sort dsList so that servers more likly to
// be available are tried first
sortDsList();
if (m_policy == SERIAL || m_dsList.length == 1) {
openSerial();
}
else {
openParallel();
}
if (m_socket != null) {
return m_socket;
}
if (m_connException != null) {
throw m_connException;
}
return null;
}
/**
* To be called when the current connection is lost.
* Put the connected server at the end of the server list for
* the next connect attempt.
*/
void invalidateConnection() {
if (m_socket != null) {
m_dsList[m_dsIdx].connSetupStatus = FAILED;
// Move the entry to the end of the list
int srvCnt = m_dsList.length, j=0;
ServerEntry[] newDsList = new ServerEntry[m_dsList.length];
for (int i=0; i < srvCnt; i++) {
if (i != m_dsIdx) {
newDsList[j++] = m_dsList[i];
}
}
newDsList[j] = m_dsList[m_dsIdx];
m_dsList = newDsList;
m_dsIdx = j;
}
m_socket = null;
}
/**
* To be called when the current connection is terminated by the user
* Mark the connected server status as DISCONNECTED. This will
* put it at top of the server list for the next connect attempt.
*/
void disconnect() {
if (m_socket != null) {
m_dsList[m_dsIdx].connSetupStatus = DISCONNECTED;
}
m_socket = null;
}
Socket getSocket() {
return m_socket;
}
String getHost() {
if (m_dsIdx >= 0) {
return m_dsList[m_dsIdx].host;
}
return m_dsList[0].host;
}
int getPort() {
if (m_dsIdx >= 0) {
return m_dsList[m_dsIdx].port;
}
return m_dsList[0].port;
}
/**
* Check if the user has voluntarily closed the connection
*/
boolean isUserDisconnected() {
return (m_dsIdx >=0 &&
m_dsList[m_dsIdx].connSetupStatus == DISCONNECTED);
}
/**
* Try sequentially to open a new connection to a server.
*/
private void openSerial() {
for (int i=0; i < m_dsList.length; i++) {
m_dsList[i].connSetupThread = Thread.currentThread();
connectServer(i);
if (m_socket != null) {
return;
}
}
}
/**
* Try concurrently to open a new connection a server. Create a separate
* thread for each connection attempt.
*/
private synchronized void openParallel() {
for (int i=0; m_socket==null && i < m_dsList.length; i++) {
//Create a Thread to execute connectSetver()
final int dsIdx = i;
String threadName = "ConnSetupMgr " +
m_dsList[dsIdx].host + ":" + m_dsList[dsIdx].port;
Thread t = new Thread(new Runnable() {
public void run() {
connectServer(dsIdx);
}
}, threadName);
m_dsList[dsIdx].connSetupThread = t;
t.setDaemon(true);
t.start();
// Wait before starting another thread if the delay is not zero
if (m_connSetupDelay != 0 && i < (m_dsList.length-1)) {
try {
wait(m_connSetupDelay);
}
catch (InterruptedException e) {}
}
}
// At this point all threads are started. Wait until first thread
// succeeds to connect or all threads terminate
while (m_socket == null) {
// Check whether there are still running threads
boolean threadsRunning = false;
for (int i=0; i < m_dsList.length; i++) {
if (m_dsList[i].connSetupThread != null) {
threadsRunning = true;
break;
}
}
if (!threadsRunning) { return; }
// Wait for a thread to terminate
try {
wait();
}
catch (InterruptedException e) {}
}
}
/**
* Connect to the server at the given index
*/
private void connectServer(int idx) {
ServerEntry entry = m_dsList[idx];
Thread currThread = Thread.currentThread();
Socket sock = null;
LDAPException conex = null;
try {
/* If we are to create a socket ourselves, make sure it has
sufficient privileges to connect to the desired host */
if (m_factory == null) {
sock = new Socket (entry.host, entry.port);
//s.setSoLinger( false, -1 );
} else {
sock = m_factory.makeSocket(entry.host, entry.port);
}
}
catch (IOException e) {
conex = new LDAPException("failed to connect to server "
+ entry.host+":"+entry.port, LDAPException.CONNECT_ERROR);
}
catch (LDAPException e) {
conex = e;
}
if (currThread.isInterrupted()) {
return;
}
synchronized (this) {
if (m_socket == null && entry.connSetupThread == currThread) {
entry.connSetupThread = null;
if (sock != null) {
entry.connSetupStatus = CONNECTED;
m_socket = sock;
m_dsIdx = idx;
cleanup(); // Signal other concurrent threads to terminate
}
else {
entry.connSetupStatus = FAILED;
m_connException = conex;
}
notifyAll();
}
}
}
/**
* Terminate all concurrently running connection setup threads
*/
private synchronized void cleanup() {
Thread currThread = Thread.currentThread();
for (int i=0; i < m_dsList.length; i++) {
ServerEntry entry = m_dsList[i];
if (entry.connSetupThread != null && entry.connSetupThread != currThread) {
entry.connSetupStatus = FAILED;
//Thread.stop() is considered to be dangerous, use Thread.interrupt().
//interrupt() will however not work if the thread is blocked in the
//socket library native connect() call, but the connect() will
//eventually timeout and the thread will die.
entry.connSetupThread.interrupt();
entry.connSetupThread = null;
}
}
}
/**
* Sort Server List so that servers which are more likely to be available
* are tried first. The likelihood of making a successful connection
* is determined by the connSetupStatus. Lower values have higher
* likelihood. Thus, the order of server access is (1) disconnected by
* the user (2) never used (3) connection setup failed/connection lost
*/
private void sortDsList() {
int srvCnt = m_dsList.length;
for (int i=1; i < srvCnt; i++) {
for (int j=0; j < i; j++) {
if (m_dsList[i].connSetupStatus < m_dsList[j].connSetupStatus) {
// swap entries
ServerEntry entry = m_dsList[j];
m_dsList[j] = m_dsList[i];
m_dsList[i] = entry;
}
}
}
}
public String toString() {
String str = "dsIdx="+m_dsIdx+ " dsList=";
for (int i=0; i < m_dsList.length; i++) {
str += m_dsList[i]+ " ";
}
return str;
}
public Object clone() {
LDAPConnSetupMgr cloneMgr = new LDAPConnSetupMgr();
cloneMgr.m_factory = m_factory;
cloneMgr.m_policy = m_policy;
cloneMgr.m_connSetupDelay = m_connSetupDelay;
cloneMgr.m_dsIdx = m_dsIdx;
cloneMgr.m_dsList = new ServerEntry[m_dsList.length];
cloneMgr.m_socket = m_socket;
for (int i=0; i<m_dsList.length; i++) {
ServerEntry e = m_dsList[i];
cloneMgr.m_dsList[i] = new ServerEntry(e.host, e.port, e.connSetupStatus);
}
return cloneMgr;
}
}

View File

@ -0,0 +1,543 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import java.util.*;
import netscape.ldap.client.*;
import netscape.ldap.client.opers.*;
import netscape.ldap.ber.stream.*;
import netscape.ldap.util.*;
import java.io.*;
import java.net.*;
/**
* Multiple LDAPConnection clones can share a single physical connection,
* which is maintained by a thread.
*
* +----------------+
* | LDAPConnection | --------+
* +----------------+ |
* |
* +----------------+ | +----------------+
* | LDAPConnection | --------+------- | LDAPConnThread |
* +----------------+ | +----------------+
* |
* +----------------+ |
* | LDAPConnection | --------+
* +----------------+
*
* All LDAPConnections send requests and get responses from
* LDAPConnThread (a thread).
*/
class LDAPConnThread extends Thread {
/**
* Constants
*/
private final static int MAXMSGID = Integer.MAX_VALUE;
/**
* Internal variables
*/
transient private static int m_highMsgId;
transient private InputStream m_serverInput;
transient private OutputStream m_serverOutput;
transient private Hashtable m_requests;
transient private Hashtable m_messages = null;
transient private Vector m_registered;
transient private boolean m_disconnected = false;
transient private LDAPCache m_cache = null;
transient private boolean m_failed = false;
private Socket m_socket = null;
transient private Thread m_thread = null;
transient Object m_sendRequestLock = new Object();
transient LDAPConnSetupMgr m_connMgr = null;
/**
* Constructs a connection thread that maintains connection to the
* LDAP server.
* @param host LDAP host name
* @param port LDAP port number
* @param factory LDAP socket factory
*/
public LDAPConnThread(LDAPConnSetupMgr connMgr, LDAPCache cache)
throws LDAPException {
super("LDAPConnection " + connMgr.getHost() +":"+ connMgr.getPort());
m_requests = new Hashtable ();
m_registered = new Vector ();
m_connMgr = connMgr;
m_socket = connMgr.getSocket();
setCache( cache );
setDaemon(true);
try {
m_serverInput = new BufferedInputStream (m_socket.getInputStream());
m_serverOutput = new BufferedOutputStream (m_socket.getOutputStream());
} catch (IOException e) {
// a kludge to make the thread go away. Since the thread has already
// been created, the only way to clean up the thread is to call the
// start() method. Otherwise, the exit method will be never called
// because the start() was never called. In the run method, the stop
// method calls right away if the m_failed is set to true.
m_failed = true;
start();
throw new LDAPException ( "failed to connect to server " +
m_connMgr.getHost(), LDAPException.CONNECT_ERROR );
}
start(); /* start the thread */
}
InputStream getInputStream() {
return m_serverInput;
}
void setInputStream( InputStream is ) {
m_serverInput = is;
}
OutputStream getOutputStream() {
return m_serverOutput;
}
void setOutputStream( OutputStream os ) {
m_serverOutput = os;
}
/**
* Set the cache to use for searches.
* @param cache The cache to use for searches; <CODE>null</CODE> for no cache
*/
synchronized void setCache( LDAPCache cache ) {
m_cache = cache;
m_messages = (m_cache != null) ? new Hashtable() : null;
}
/**
* Sends LDAP request via this connection thread.
* @param request request to send
* @param toNotify response listener to invoke when the response
* is ready
*/
synchronized void sendRequest (LDAPConnection conn, JDAPProtocolOp request,
LDAPMessageQueue toNotify, LDAPConstraints cons)
throws LDAPException {
if (m_serverOutput == null)
throw new LDAPException ( "not connected to a server",
LDAPException.SERVER_DOWN );
LDAPMessage msg =
new LDAPMessage(allocateId(), request, cons.getServerControls());
if ( toNotify != null ) {
if (!(request instanceof JDAPAbandonRequest ||
request instanceof JDAPUnbindRequest)) {
/* Only worry about toNotify if we expect a response... */
this.m_requests.put (new Integer (msg.getId()), toNotify);
/* Notify the backlog checker that there may be another outstanding
request */
resultRetrieved();
}
toNotify.addRequest(msg.getId(), conn, this);
}
synchronized( m_sendRequestLock ) {
try {
msg.write (m_serverOutput);
m_serverOutput.flush ();
} catch (IOException e) {
networkError(e);
}
}
}
/**
* Register with this connection thread.
* @param conn LDAP connection
*/
public synchronized void register(LDAPConnection conn) {
if (!m_registered.contains(conn))
m_registered.addElement(conn);
}
synchronized int getClientCount() {
return m_registered.size();
}
/**
* De-Register with this connection thread. If all the connection
* is deregistered. Then, this thread should be killed.
* @param conn LDAP connection
*/
public synchronized void deregister(LDAPConnection conn) {
m_registered.removeElement(conn);
if (m_registered.size() == 0) {
try {
LDAPConstraints cons = conn.getSearchConstraints();
sendRequest (null, new JDAPUnbindRequest (), null, cons);
cleanUp();
if ( m_thread != null ) {
m_thread.interrupt();
}
this.sleep(100); /* give enough time for threads to shutdown */
} catch (Exception e) {
LDAPConnection.printDebug(e.toString());
}
}
}
/**
* Clean ups before shutdown the thread.
*/
private void cleanUp() {
if (!m_disconnected) {
try {
m_serverOutput.close ();
} catch (Exception e) {
} finally {
m_serverOutput = null;
}
try {
m_serverInput.close ();
} catch (Exception e) {
} finally {
m_serverInput = null;
}
try {
m_socket.close ();
} catch (Exception e) {
} finally {
m_socket = null;
}
m_disconnected = true;
/**
* Notify the Connection Setup Manager that the connection was
* terminated by the user
*/
m_connMgr.disconnect();
/**
* Notify all the registered about this bad moment.
* IMPORTANT: This needs to be done at last. Otherwise, the socket
* input stream and output stream might never get closed and the whole
* task will get stuck in the stop method when we tried to stop the
* LDAPConnThread.
*/
if (m_registered != null) {
Vector registerCopy = (Vector)m_registered.clone();
Enumeration cancelled = registerCopy.elements();
while (cancelled.hasMoreElements ()) {
LDAPConnection c = (LDAPConnection)cancelled.nextElement();
c.deregisterConnection();
}
}
m_registered = null;
m_messages = null;
m_requests.clear();
}
}
/**
* Sleep if there is a backlog of search results
*/
private void checkBacklog() {
boolean doWait;
do {
doWait = false;
Enumeration listeners = m_requests.elements();
while( listeners.hasMoreElements() ) {
LDAPMessageQueue l =
(LDAPMessageQueue)listeners.nextElement();
// If there are any threads waiting for a regular response
// message, we have to go read the next incoming message
if ( !(l instanceof LDAPSearchListener) ) {
doWait = false;
break;
}
// If the backlog of any search thread is too great,
// wait for it to diminish, but if this is a synchronous
// search, then just keep reading
LDAPSearchListener sl = (LDAPSearchListener)l;
// Asynch operation ?
if (sl.isAsynchOp()) {
if (sl.getMessageCount() >= sl.getConstraints().getMaxBacklog()) {
doWait = true;
}
}
// synch op with non-zero batch size ?
else if (sl.getConstraints().getBatchSize() != 0) {
if (sl.getMessageCount() >= sl.getConstraints().getMaxBacklog()) {
doWait = true;
}
}
}
if ( doWait ) {
synchronized(this) {
try {
wait();
} catch (InterruptedException e ) {
}
}
}
} while ( doWait );
}
/**
* This is called when a search result has been retrieved from the incoming
* queue. We use the notification to unblock the listener thread, if it
* is waiting for the backlog to lighten.
*/
synchronized void resultRetrieved() {
notifyAll();
}
/**
* Reads from the LDAP server input stream for incoming LDAP messages.
*/
public void run() {
// if there is a problem of establishing connection to the server,
// stop the thread right away...
if (m_failed) {
return;
}
m_thread = Thread.currentThread();
LDAPMessage msg = null;
JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
while (true) {
yield();
int[] nread = new int[1];
nread[0] = 0;
// Avoid too great a backlog of results
checkBacklog();
try {
if (m_thread.isInterrupted()) {
break;
}
BERElement element = BERElement.getElement(decoder,
m_serverInput,
nread);
msg = LDAPMessage.parseMessage(element);
// passed in the ber element size to approximate the size of the cache
// entry, thereby avoiding serialization of the entry stored in the
// cache
processResponse (msg, nread[0]);
} catch (Exception e) {
networkError(e);
}
if (m_disconnected)
break;
}
}
/**
* Allocates a new LDAP message ID. These are arbitrary numbers used to
* correlate client requests with server responses.
* @return new unique msgId
*/
private synchronized int allocateId () {
m_highMsgId = (m_highMsgId + 1) % MAXMSGID;
return m_highMsgId;
}
/**
* When a response arrives from the LDAP server, it is processed by
* this routine. It will pass the message on to the listening object
* associated with the LDAP msgId.
* @param incoming New message from LDAP server
*/
private synchronized void processResponse (LDAPMessage incoming, int size) {
Integer messageID = new Integer (incoming.getId());
LDAPMessageQueue l = (LDAPMessageQueue)m_requests.get (messageID);
if (l == null) {
return; /* nobody is waiting for this response (!) */
}
// For asynch operations controls are to be read from the LDAPMessage
// For synch operations controls are copied into the LDAPConnection
// For synch search operations, controls are also copied into
// LDAPSearchResults (see LDAPConnection.checkSearchMsg())
if ( ! l.isAsynchOp()) {
/* Were there any controls for this client? */
LDAPControl[] con = incoming.getControls();
if (con != null) {
int msgid = incoming.getId();
LDAPConnection ldc = l.getConnection(msgid);
if (ldc != null) {
ldc.setResponseControls( this,
new LDAPResponseControl(ldc, msgid, con));
}
}
}
Vector v = null;
JDAPProtocolOp op = incoming.getProtocolOp ();
if ((op instanceof JDAPSearchResponse) ||
(op instanceof JDAPSearchResultReference)) {
l.addMessage (incoming);
Long key = ((LDAPSearchListener)l).getKey();
if ((m_cache != null) && (key != null)) {
// get the vector containing the LDAPMessages for the specified messageID
v = (Vector)m_messages.get(messageID);
if (v == null) {
v = new Vector();
// keeps track of the total size of all LDAPMessages belonging to the
// same messageID, now the size is 0
v.addElement(new Long(0));
}
// add the size of the current LDAPMessage to the lump sum
// assume the size of LDAPMessage is more or less the same as the size
// of LDAPEntry. Eventually LDAPEntry object gets stored in the cache
// instead of LDAPMessage object.
long entrySize = ((Long)v.firstElement()).longValue() + size;
// update the lump sum located in the first element of the vector
v.setElementAt(new Long(entrySize), 0);
// convert LDAPMessage object into LDAPEntry which is stored to the
// end of the Vector
v.addElement(((LDAPSearchResult)incoming).getEntry());
// replace the entry
m_messages.put(messageID, v);
}
} else {
l.addMessage (incoming);
if (l instanceof LDAPSearchListener) {
Long key = ((LDAPSearchListener)l).getKey();
if (key != null) {
boolean fail = false;
JDAPProtocolOp protocolOp = incoming.getProtocolOp();
if (protocolOp instanceof JDAPSearchResult) {
JDAPResult res = (JDAPResult)protocolOp;
if (res.getResultCode() > 0) {
fail = true;
}
}
if ((!fail) && (m_cache != null)) {
// Collect all the LDAPMessages for the specified messageID
// no need to keep track of this entry. Remove it.
v = (Vector)m_messages.remove(messageID);
// If v is null, meaning there are no search results from the
// server
if (v == null) {
v = new Vector();
// set the entry size to be 0
v.addElement(new Long(0));
}
try {
// add the new entry with key and value (a vector of
// LDAPEntry objects)
m_cache.addEntry(key, v);
} catch (LDAPException e) {
System.out.println("Exception: "+e.toString());
}
}
}
}
m_requests.remove (messageID);
}
}
/**
* Stop dispatching responses for a particular message ID.
* @param id Message ID for which to discard responses.
*/
synchronized void abandon (int id ) {
LDAPMessageQueue l = (LDAPMessageQueue)m_requests.remove(new Integer(id));
if (l != null) {
l.removeRequest(id);
}
notifyAll(); // If LDAPConnThread is blocked in checkBacklog()
}
/**
* Handles network errors. Basically shuts down the whole connection.
* @param e The exception which was caught while trying to read from
* input stream.
*/
private synchronized void networkError (Exception e) {
try {
// notify the Connection Setup Manager that the connection is lost
m_connMgr.invalidateConnection();
// notify each listener that the server is down.
Enumeration requests = m_requests.elements();
while (requests.hasMoreElements()) {
LDAPMessageQueue listener =
(LDAPMessageQueue)requests.nextElement();
listener.setException(this, new LDAPException("Server down",
LDAPException.OTHER));
}
cleanUp();
} catch (NullPointerException ee) {
System.err.println("Exception: "+ee.toString());
}
/**
* Notify all the registered connections.
* IMPORTANT: This needs to be done last. Otherwise, the socket
* input stream and output stream might never get closed and the whole
* task will get stuck in the stop method when we try to stop the
* LDAPConnThread.
*/
if (m_registered != null) {
Vector registerCopy = (Vector)m_registered.clone();
Enumeration cancelled = registerCopy.elements();
while (cancelled.hasMoreElements ()) {
LDAPConnection c = (LDAPConnection)cancelled.nextElement();
c.deregisterConnection();
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,344 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
/**
* Represents a set of operation preferences.
* You can set these preferences for a particular operation
* by creating an <CODE>LDAPConstraints</CODE> object,
* specifying your preferences, and passing the object to
* the proper <CODE>LDAPConnection</CODE> method.
* <P>
*
* @version 1.0
*/
public class LDAPConstraints implements Cloneable {
private int m_hop_limit;
private LDAPBind m_bind_proc;
private LDAPRebind m_rebind_proc;
private boolean referrals;
private int m_time_limit;
private LDAPControl[] m_clientControls;
private LDAPControl[] m_serverControls;
/**
* Constructs an <CODE>LDAPConstraints</CODE> object that specifies
* the default set of constraints.
*/
public LDAPConstraints() {
m_time_limit = 0;
referrals = false;
m_bind_proc = null;
m_rebind_proc = null;
m_hop_limit = 5;
m_clientControls = null;
m_serverControls = null;
}
/**
* Constructs a new <CODE>LDAPConstraints</CODE> object and allows you
* to specify the constraints in that object.
* <P>
* @param msLimit Maximum time in milliseconds to wait for results (0
* by default, which means that there is no maximum time limit)
* @param doReferrals Specify <CODE>true</CODE> to follow referrals
* automatically, or <CODE>False</CODE> to throw an
* <CODE>LDAPReferralException</CODE> error if the server sends back
* a referral (<CODE>False</CODE> by default)
* @param rebind_proc Specifies the object that
* implements the <CODE>LDAPRebind</CODE> interface (you need to
* define this class). The object will be used when the client
* follows referrals automatically. The object provides the client
* with a method for getting the distinguished name and password
* used to authenticate to another LDAP server during a referral.
* (This field is <CODE>null</CODE> by default.)
* @param hop_limit Maximum number of referrals to follow in a
* sequence when attempting to resolve a request.
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
*/
public LDAPConstraints( int msLimit, boolean doReferrals,
LDAPRebind rebind_proc, int hop_limit) {
m_time_limit = msLimit;
referrals = doReferrals;
m_bind_proc = null;
m_rebind_proc = rebind_proc;
m_hop_limit = hop_limit;
m_clientControls = null;
m_serverControls = null;
}
/**
* Constructs a new <CODE>LDAPConstraints</CODE> object and allows you
* to specify the constraints in that object.
* <P>
* @param msLimit Maximum time in milliseconds to wait for results (0
* by default, which means that there is no maximum time limit)
* @param doReferrals Specify <CODE>true</CODE> to follow referrals
* automatically, or <CODE>False</CODE> to throw an
* <CODE>LDAPReferralException</CODE> error if the server sends back
* a referral (<CODE>False</CODE> by default)
* @param bind_proc Specifies the object that
* implements the <CODE>LDAPBind</CODE> interface (you need to
* define this class). The object will be used to authenticate to the
* server on referrals. (This field is <CODE>null</CODE> by default.)
* @param hop_limit Maximum number of referrals to follow in a
* sequence when attempting to resolve a request.
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
*/
public LDAPConstraints( int msLimit, boolean doReferrals,
LDAPBind bind_proc, int hop_limit) {
m_time_limit = msLimit;
referrals = doReferrals;
m_bind_proc = bind_proc;
m_rebind_proc = null;
m_hop_limit = hop_limit;
m_clientControls = null;
m_serverControls = null;
}
/**
* Returns the maximum number of milliseconds to wait for any operation
* under these constraints. If 0, there is no maximum time limit
* on waiting for the operation results.
* @return Maximum number of milliseconds to wait for operation results.
*/
public int getTimeLimit() {
return m_time_limit;
}
/**
* Specifies whether nor not referrals are followed automatically.
* Returns <CODE>true</CODE> if referrals are to be followed automatically,
* or <CODE>false</CODE> if referrals throw an
* <CODE>LDAPReferralException</CODE>.
* @return <CODE>true</CODE> if referrals are followed automatically,
* <CODE>False</CODE> if referrals throw an
* <CODE>LDAPReferralException</CODE>.
*/
public boolean getReferrals() {
return referrals;
}
/**
* Returns the object that provides the mechanism for authenticating to the
* server on referrals. This object must implement the <CODE>LDAPBind</CODE>
* interface.
* @return Object to be used to authenticate to the server on referrals.
* @see netscape.ldap.LDAPBind
*/
public LDAPBind getBindProc() {
return m_bind_proc;
}
/**
* Returns the object that provides the method for getting
* authentication information. This object must
* implement the <CODE>LDAPRebind</CODE> interface.
* @return Object to be used to obtain information for
* authenticating to other LDAP servers during referrals.
* @see netscape.ldap.LDAPRebind
* @see netscape.ldap.LDAPRebindAuth
*/
public LDAPRebind getRebindProc() {
return m_rebind_proc;
}
/**
* Returns the maximum number of hops to follow during a referral.
* @return Maximum number of hops to follow during a referral.
*/
public int getHopLimit() {
return m_hop_limit;
}
/**
* Returns any client controls to be applied by the client
* to LDAP operations.
* @return Client controls to be applied by the client to LDAP operations.
* @see netscape.ldap.LDAPControl
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public LDAPControl[] getClientControls() {
return m_clientControls;
}
/**
* Returns any server controls to be applied by the server
* to LDAP operations.
* @return Server controls to be applied by the server to LDAP operations.
* @see netscape.ldap.LDAPControl
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public LDAPControl[] getServerControls() {
return m_serverControls;
}
/**
* Sets the maximum number of milliseconds to wait for any operation
* under these constraints. If 0, there is no maximum time limit
* on waiting for the operation results.
* @param msLimit Maximum number of milliseconds to wait for operation
* results.
* (0 by default, which means that there is no maximum time limit.)
*/
public void setTimeLimit( int msLimit ) {
m_time_limit = msLimit;
}
/**
* Specifies whether nor not referrals are followed automatically.
* Returns <CODE>true</CODE> if referrals are to be followed automatically,
* or <CODE>false</CODE> if referrals throw an
* <CODE>LDAPReferralException</CODE>.
* (By default, this is set to <CODE>false</CODE>.)
* <P>
* If you set this to <CODE>true</CODE>, you need to create an object of
* this class that implements either the <CODE>LDAPRebind</CODE> or
* <CODE>LDAPBind</CODE> interface. The <CODE>LDAPRebind</CODE> object
* identifies the method for retrieving authentication information which
* will be used when connecting to other LDAP servers during referrals.
* This object should be passed to the <CODE>setRebindProc</CODE> method.
* Alternatively, the <CODE>LDAPBind</CODE> object identifies an
* authentication mechanism to be used instead of the default
* authentication mechanism when following referrals. This
* object should be passed to the <CODE>setBindProc</BIND> method.
* @param doReferrals Set to <CODE>true</CODE> if referrals should be
* followed automatically, or <CODE>False</CODE> if referrals should throw
* an <CODE>LDAPReferralException</CODE>.
* @see netscape.ldap.LDAPBind
* @see netscape.ldap.LDAPRebind
* @see netscape.ldap.LDAPRebindAuth
*/
public void setReferrals( boolean doReferrals ) {
referrals = doReferrals;
}
/**
* Sets the object that provides the mechanism for authenticating
* to the server on referrals. This object must implement
* the <CODE>LDAPBind</CODE> interface.(By default, this is
* <CODE>null</CODE>.) This method sets the <CODE>LDAPRebind</CODE>
* object to null for this constraint.
* @param bind_proc Object to be used to authenticate to the server
* on referrals.
* @see netscape.ldap.LDAPBind
*/
public void setBindProc( LDAPBind bind_proc ) {
m_bind_proc = bind_proc;
if (bind_proc != null) {
m_rebind_proc = null;
}
}
/**
* Specifies the object that provides the method for getting
* authentication information. This object must belong to a class
* that implements the <CODE>LDAPRebind</CODE> interface.
* (By default, this is <CODE>null</CODE>.) This method sets the
* <CODE>LDAPBind</CODE> object to null for this constraint.
* @param rebind_proc Object to be used to obtain information for
* authenticating to other LDAP servers during referrals.
*/
public void setRebindProc( LDAPRebind rebind_proc ) {
m_rebind_proc = rebind_proc;
if (rebind_proc != null) {
m_bind_proc = null;
}
}
/**
* Sets maximum number of hops to follow in sequence during a referral.
* (By default, this is 5.)
* @param hop_limit Maximum number of hops to follow during a referral.
*/
public void setHopLimit( int hop_limit ) {
m_hop_limit = hop_limit;
}
/**
* Sets a client control for LDAP operations.
* @param control Client control for LDAP operations.
* @see netscape.ldap.LDAPControl
*/
public void setClientControls( LDAPControl control ) {
m_clientControls = new LDAPControl[1];
m_clientControls[0] = control;
}
/**
* Sets an array of client controls for LDAP operations.
* @param controls Array of client controls for LDAP operations.
* @see netscape.ldap.LDAPControl
*/
public void setClientControls( LDAPControl[] controls ) {
m_clientControls = controls;
}
/**
* Sets a server control for LDAP operations.
* @param control Server control for LDAP operations.
* @see netscape.ldap.LDAPControl
*/
public void setServerControls( LDAPControl control ) {
m_serverControls = new LDAPControl[1];
m_serverControls[0] = control;
}
/**
* Sets an array of server controls for LDAP operations.
* @param controls An array of server controls for LDAP operations.
* @see netscape.ldap.LDAPControl
*/
public void setServerControls( LDAPControl[] controls ) {
m_serverControls = controls;
}
/**
* Makes a copy of an existing set of constraints.
* @returns A copy of an existing set of constraints.
*/
public Object clone() {
LDAPConstraints o = new LDAPConstraints();
o.m_time_limit = this.m_time_limit;
o.referrals = this.referrals;
o.m_bind_proc = this.m_bind_proc;
o.m_rebind_proc = this.m_rebind_proc;
o.m_hop_limit = this.m_hop_limit;
if ( (this.m_clientControls != null) &&
(this.m_clientControls.length > 0) ) {
o.m_clientControls = new LDAPControl[this.m_clientControls.length];
for( int i = 0; i < this.m_clientControls.length; i++ )
o.m_clientControls[i] =
(LDAPControl)this.m_clientControls[i].clone();
}
if ( (this.m_serverControls != null) &&
(this.m_serverControls.length > 0) ) {
o.m_serverControls = new LDAPControl[this.m_serverControls.length];
for( int i = 0; i < this.m_serverControls.length; i++ )
o.m_serverControls[i] =
(LDAPControl)this.m_serverControls[i].clone();
}
return o;
}
}

View File

@ -12,13 +12,18 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
import netscape.ldap.ber.stream.*;
import netscape.ldap.client.*;
import netscape.ldap.util.*;
import netscape.ldap.controls.*;
/**
* Represents arbitrary control data that can be used with a
@ -147,10 +152,10 @@ import netscape.ldap.ber.stream.*;
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
* @see netscape.ldap.LDAPConnection#getResponseControls
* @see netscape.ldap.LDAPSearchConstraints#getClientControls
* @see netscape.ldap.LDAPSearchConstraints#getServerControls
* @see netscape.ldap.LDAPSearchConstraints#setClientControls
* @see netscape.ldap.LDAPSearchConstraints#setServerControls
* @see netscape.ldap.LDAPConstraints#getClientControls
* @see netscape.ldap.LDAPConstraints#getServerControls
* @see netscape.ldap.LDAPConstraints#setClientControls
* @see netscape.ldap.LDAPConstraints#setServerControls
*/
public class LDAPControl implements Cloneable {
public final static String MANAGEDSAIT = "2.16.840.1.113730.3.4.2";
@ -176,8 +181,8 @@ public class LDAPControl implements Cloneable {
* cancelled when the server does not support this control (in other
* words, this control is critical to the LDAP operation).
* @param vals Control-specific data.
* @see netscape.ldap.LDAPSearchConstraints#setClientControls
* @see netscape.ldap.LDAPSearchConstraints#setServerControls
* @see netscape.ldap.LDAPConstraints#setClientControls
* @see netscape.ldap.LDAPConstraints#setServerControls
*/
public LDAPControl(String id,
boolean critical,
@ -186,7 +191,7 @@ public class LDAPControl implements Cloneable {
m_critical = critical;
m_value = vals;
}
/**
* Gets the object ID (OID) of the control.
* @return Object ID (OID) of the control.
@ -212,6 +217,225 @@ public class LDAPControl implements Cloneable {
return m_value;
}
/**
* Gets the ber representation of control.
* @return ber representation of control
*/
BERElement getBERElement() {
BERSequence seq = new BERSequence();
seq.addElement(new BEROctetString (m_oid));
seq.addElement(new BERBoolean (m_critical));
if ( (m_value == null) || (m_value.length < 1) )
seq.addElement(new BEROctetString ((byte[])null));
else {
seq.addElement(new BEROctetString (m_value, 0, m_value.length));
}
return seq;
}
/**
* Associates a class with an oid. This class must be an extension of
* <CODE>LDAPControl</CODE>, and should implement the <CODE>LDAPControl(
* String oid, boolean critical, byte[] value)</CODE> constructor to
* instantiate the control.
* @param oid The string representation of the oid.
* @param controlClass The class that instantatiates the control associated
* with oid.
* @exception netscape.ldap.LDAPException If the class parameter is not
* a subclass of <CODE>LDAPControl</CODE> or the class parameter does not
* implement the <CODE>LDAPControl(String oid, boolean critical, byte[] value)
* </CODE> constructor.
*/
public static void register(String oid, Class controlClass) throws
LDAPException {
if (controlClass == null) {
return;
}
// 1. make sure controlClass is a subclass of LDAPControl
Class superClass = controlClass;
while (superClass != LDAPControl.class && superClass != null) {
superClass = superClass.getSuperclass();
}
if (superClass == null)
throw new LDAPException("controlClass must be a subclass of " +
"LDAPControl", LDAPException.PARAM_ERROR);
// 2. make sure controlClass has the proper constructor
Class[] cparams = { String.class, boolean.class, byte[].class };
try {
controlClass.getConstructor(cparams);
} catch (NoSuchMethodException e) {
throw new LDAPException("controlClass does not implement the " +
"correct contstructor",
LDAPException.PARAM_ERROR);
}
// 3. check if the hash table exists
if (m_controlClassHash == null) {
m_controlClassHash = new Hashtable();
}
// 4. add the controlClass
m_controlClassHash.put(oid, controlClass);
}
/**
* Returns the <CODE>Class</CODE> that has been registered to oid.
* @param oid A String that associates the control class to a control.
* @return A <CODE>Class</CODE> that can instantiate a control of the
* type specified by oid.
* @see netscape.ldap.LDAPControl#register
*
*/
protected static Class lookupControlClass(String oid) {
if (m_controlClassHash == null) {
return null;
}
return (Class)m_controlClassHash.get(oid);
}
/**
* Returns a <CODE>LDAPControl</CODE> object instantiated by the Class
* associated by <CODE>LDAPControl.register</CODE> to the oid. If
* no Class is found for the given control, or an exception occurs when
* attempting to instantiate the control, a basic <CODE>LDAPControl</CODE>
* is instantiated using the parameters.
* @param oid The oid of the control to be instantiated.
* @param critical <CODE>true</CODE> if this is a critical control.
* @param value the byte value for the control.
* @return A newly instantiated <CODE>LDAPControl</CODE>.
* @see netscape.ldap.LDAPControl#register
*/
protected static LDAPControl createControl(String oid, boolean critical,
byte[] value) {
Class controlClass = lookupControlClass(oid);
if (controlClass == null) {
return new LDAPControl(oid, critical, value);
}
Class[] cparams = { String.class, boolean.class, byte[].class };
Constructor creator = null;
try {
creator = controlClass.getConstructor(cparams);
} catch (NoSuchMethodException e) {
//shouldn't happen, but...
System.err.println("Caught java.lang.NoSuchMethodException while" +
" attempting to instantiate a control of type " +
oid);
return new LDAPControl(oid, critical, value);
}
Object[] oparams = { oid, new Boolean(critical), value } ;
LDAPControl returnControl = null;
try {
returnControl = (LDAPControl)creator.newInstance(oparams);
} catch (Exception e) {
String eString = null;
if (e instanceof InvocationTargetException) {
eString = ((InvocationTargetException)
e).getTargetException().toString();
} else {
eString = e.toString();
}
System.err.println("Caught " + eString + " while attempting to" +
" instantiate a control of type " +
oid);
returnControl = new LDAPControl(oid, critical, value);
}
return returnControl;
}
/**
* Returns a <CODE>LDAPControl</CODE> object instantiated by the Class
* associated by <CODE>LDAPControl.register</CODE> to the oid. If
* no Class is found for the given control, or an exception occurs when
* attempting to instantiate the control, a basic <CODE>LDAPControl</CODE>
* is instantiated using the parameters.
* @param el The <CODE>BERElement</CODE> containing the control.
* @return A newly instantiated <CODE>LDAPControl</CODE>.
* @see netscape.ldap.LPAPControl#register
*
* Note:
* This code was extracted from <CODE>JDAPControl(BERElement el)</CODE>
* constructor
*/
static LDAPControl parseControl(BERElement el) {
BERSequence s = (BERSequence)el;
String oid = null;
boolean critical = false;
byte[] value = null;
try{
oid = new String(((BEROctetString)s.elementAt(0)).getValue(), "UTF8");
} catch(Throwable x) {}
Object obj = s.elementAt(1);
if (obj instanceof BERBoolean) {
critical = ((BERBoolean)obj).getValue();
}
else {
value = ((BEROctetString)obj).getValue();
}
if (s.size() >= 3) {
value = ((BEROctetString)s.elementAt(2)).getValue();
}
return createControl(oid, critical, value);
}
/**
* Instantiates all of the controls contained within the LDAP message
* fragment specified by data and returns them in an <CODE>LDAPControl</CODE>
* array. This fragment can be either the entire LDAP message or just the
* control section of the message.
* <P>
* If an exception occurs when instantiating a control, that control is
* returned as a basic <CODE>LDAPControl</CODE>.
* @param data The LDAP message fragment in raw BER format.
* @return A <CODE>LDAPControl</CODE> array containing all of the controls
* from the message fragment.
* @exception java.lang.IOException If the data passed to this method
* is not a valid LDAP message fragment.
* @see netscape.ldap.LDAPControl#register
*/
public static LDAPControl[] newInstance(byte[] data) throws IOException {
int[] bread = { 0 };
BERElement el = BERElement.getElement(new JDAPBERTagDecoder(),
new ByteArrayInputStream(data),
bread);
LDAPControl[] jc = null;
try {
// see if data is a LDAP message
LDAPMessage msg = LDAPMessage.parseMessage(el);
return msg.getControls();
} catch (IOException e) {
// that didn't work; let's see if its just the controls
BERTag tag = (BERTag)el;
if ( tag.getTag() == (BERTag.CONSTRUCTED|BERTag.CONTEXT|0) ) {
BERSequence controls = (BERSequence)tag.getValue();
jc = new LDAPControl[controls.size()];
for (int i = 0; i < controls.size(); i++) {
jc[i] = parseControl(controls.elementAt(i));
}
}
}
return jc;
}
/**
* Creates a copy of the control.
* @return Copy of the control.
@ -224,6 +448,7 @@ public class LDAPControl implements Cloneable {
vals[i] = m_value[i];
}
LDAPControl control = new LDAPControl( m_oid, m_critical, vals );
return control;
}
@ -244,8 +469,37 @@ public class LDAPControl implements Cloneable {
return outStream.toByteArray();
}
/**
* Return a string representation of the control for debugging
*
* @return A string representation of the control
*/
public String toString() {
String s = getID() + ' ' + isCritical();
if ( m_value != null ) {
s += ' ' + LDIF.toPrintableString( m_value );
}
return "LDAPControl {" + s + '}';
}
private String m_oid;
protected boolean m_critical = false;
protected byte[] m_value = null;
static private Hashtable m_controlClassHash = null;
static {
try {
LDAPControl.register( LDAPPasswordExpiringControl.EXPIRING,
LDAPPasswordExpiringControl.class );
LDAPControl.register( LDAPPasswordExpiredControl.EXPIRED,
LDAPPasswordExpiredControl.class );
LDAPControl.register( LDAPEntryChangeControl.ENTRYCHANGED,
LDAPEntryChangeControl.class );
LDAPControl.register( LDAPSortControl.SORTRESPONSE,
LDAPSortControl.class );
LDAPControl.register( LDAPVirtualListResponse.VIRTUALLISTRESPONSE,
LDAPVirtualListResponse.class );
} catch (LDAPException e) {
}
}
}

View File

@ -188,11 +188,14 @@ public class LDAPEntry {
* @return String representation of the entry's DN and its attributes.
*/
public String toString() {
String s = "LDAPEntry: ";
if ( dn != null )
s += dn + "; ";
if ( attrSet != null )
s += attrSet.toString();
return s;
StringBuffer sb = new StringBuffer("LDAPEntry: ");
if ( dn != null ) {
sb.append(dn);
sb.append("; ");
}
if ( attrSet != null ) {
sb.append(attrSet.toString());
}
return sb.toString();
}
}

View File

@ -154,8 +154,8 @@ public class LDAPException extends java.lang.Exception {
* method or the <CODE>LDAPSearchConstraints.setServerTimeLimit</CODE>
* method.<P>
*
* @see netscape.ldap.LDAPConnection@setOption
* @see netscape.ldap.LDAPSearchConstraints@setServerTimeLimit
* @see netscape.ldap.LDAPConnection#setOption
* @see netscape.ldap.LDAPSearchConstraints#setServerTimeLimit
*/
public final static int TIME_LIMIT_EXCEEDED = 3;
@ -213,7 +213,7 @@ public class LDAPException extends java.lang.Exception {
/**
* (9) The LDAP server is referring your client to another
* LDAP server. If you set up the <CODE>LDAPConnection</CODE>
* options or the <CODE>LDAPSearchConstraints</CODE> options
* options or the <CODE>LDAPConstraints</CODE> options
* for automatic referral, your client will automatically
* connect and authenticate to the other LDAP server.
* (This <CODE>LDAPException</CODE> will not be raised.)
@ -229,7 +229,7 @@ public class LDAPException extends java.lang.Exception {
*
* If instead you set <CODE>LDAPConnection.REFERRALS</CODE>
* to <CODE>false</CODE> (or if you set
* <CODE>LDAPSearchConstraints.setReferrals</CODE> to <CODE>false</CODE>,
* <CODE>LDAPConstraints.setReferrals</CODE> to <CODE>false</CODE>,
* an <CODE>LDAPReferralException</CODE> is raised.
* <P>
*
@ -239,8 +239,8 @@ public class LDAPException extends java.lang.Exception {
* <P>
*
* @see netscape.ldap.LDAPConnection#setOption
* @see netscape.ldap.LDAPSearchConstraints#setReferrals
* @see netscape.ldap.LDAPSearchConstraints#setRebindProc
* @see netscape.ldap.LDAPConstraints#setReferrals
* @see netscape.ldap.LDAPConstraints#setRebindProc
* @see netscape.ldap.LDAPRebind
* @see netscape.ldap.LDAPRebindAuth
* @see netscape.ldap.LDAPReferralException
@ -469,7 +469,7 @@ public class LDAPException extends java.lang.Exception {
* <P>
*
* @see netscape.ldap.LDAPConnection#rename(java.lang.String, java.lang.String, java.lang.String, boolean)
* @see netscape.ldap.LDAPConnection#rename(java.lang.String, java.lang.String, java.lang.String, boolean, LDAPSearchConstraints)
* @see netscape.ldap.LDAPConnection#rename(java.lang.String, java.lang.String, java.lang.String, boolean, LDAPConstraints)
*/
public final static int AFFECTS_MULTIPLE_DSAS = 71;
@ -770,7 +770,7 @@ public class LDAPException extends java.lang.Exception {
* <P>
*
* @return String representation of exception
* @see netscape.ldap.LDAPException#errorCodeToString(code)
* @see netscape.ldap.LDAPException#errorCodeToString(int)
*/
public String toString() {
String str = super.toString() + " (" + resultCode + ")" ;

View File

@ -0,0 +1,59 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import netscape.ldap.client.opers.JDAPExtendedResponse;
/**
* Represents a server response to an extended operation request.
*
* @version 1.0
*/
public class LDAPExtendedResponse extends LDAPResponse {
/**
* Constructor
*
* @param msgid message identifier
* @param rsp Extended operation response
* @paarm controls Array of controls of null
*/
LDAPExtendedResponse(int msgid, JDAPExtendedResponse rsp, LDAPControl controls[]) {
super(msgid, rsp, controls);
}
/**
* Returns the OID of the response.
*
* @return The response OID
*/
public String getOID() {
JDAPExtendedResponse result = (JDAPExtendedResponse)getProtocolOp();
return result.getID();
}
/**
* Returns the raw bytes of the value part of the response.
*
* @return Response as a raw array of bytes
*/
public byte[] getValue() {
JDAPExtendedResponse result = (JDAPExtendedResponse)getProtocolOp();
return result.getValue();
}
}

View File

@ -0,0 +1,53 @@
/* -*- 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.
*/
package netscape.ldap;
/**
* An exception thrown when the LDAP operation being invoked has
* been interrupted. For example, an application might interrupt a thread that
* is performing a search.
*
* @version 1.0
*/
public class LDAPInterruptedException extends LDAPException {
/**
* Constructs a default exception with a specified string of
* additional information. This string appears if you call
* the <CODE>toString()</CODE> method.
* <P>
*
* @param message The additional information.
* @see netscape.ldap.LDAPInterruptedException#toString()
*/
LDAPInterruptedException( String message ) {
super( message, LDAPException.OTHER, null);
}
/**
* Gets the string representation of the exception.
*/
public String toString() {
String str = "netscape.ldap.LDAPInterruptedException: ";
String msg = super.getMessage();
if (msg != null) {
str +=msg;
}
return str;
}
}

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
@ -46,22 +46,49 @@ import java.util.*;
* specify these types of information as arguments to the constructor or
* in the MatchingRuleDescription and MatchingRuleUseDescription formats
* specified in RFC 2252.
* (When an LDAP client searches an LDAP server for the schema, the server
* When an LDAP client searches an LDAP server for the schema, the server
* returns schema information as an object with attribute values in this
* format.)
* format.
* <P>
*
* You can get the name, OID, and description of this matching rule
* definition by using the <CODE>getName</CODE>, <CODE>getOID</CODE>, and
* <CODE>getDescription</CODE> methods inherited from the abstract class
* <CODE>LDAPSchemaElement</CODE>.
* <P>
* <CODE>LDAPSchemaElement</CODE>. Custom qualifiers are
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
* from <CODE>LDAPSchemaElement</CODE>.
* <P>
*
* If you need to add or remove this matching rule definition from the
* schema, you can use the <CODE>add</CODE> and <CODE>remove</CODE>
* To add or remove this matching rule definition from the
* schema, use the <CODE>add</CODE> and <CODE>remove</CODE>
* methods, which this class inherits from the <CODE>LDAPSchemaElement</CODE>
* abstract class.
* <P>
* RFC 2252 defines MatchingRuleDescription and MatchingRuleUseDescription
* as follows:
* <P>
* MatchingRuleDescription = "(" whsp
* numericoid whsp ; MatchingRule identifier
* [ "NAME" qdescrs ]
* [ "DESC" qdstring ]
* [ "OBSOLETE" whsp ]
* "SYNTAX" numericoid
* whsp ")"
*
* Values of the matchingRuleUse list the attributes which are suitable
* for use with an extensible matching rule.
*
* MatchingRuleUseDescription = "(" whsp
* numericoid whsp ; MatchingRule identifier
* [ "NAME" qdescrs ]
* [ "DESC" qdstring ]
* [ "OBSOLETE" ]
* "APPLIES" oids ; AttributeType identifiers
* whsp ")" * <PRE>
* </PRE>
* <P>
* <CODE>LDAPMatchingRuleSchema</CODE> abstracts away from the two types and
* manages their relationships transparently.
*
* @version 1.0
* @see netscape.ldap.LDAPSchemaElement
@ -105,11 +132,11 @@ public class LDAPMatchingRuleSchema extends LDAPAttributeSchema {
* (see <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* Attribute Syntax Definitions</A>. This is the format that LDAP servers
* and clients use to exchange schema information. (For example, when
* and clients use to exchange schema information. For example, when
* you search an LDAP server for its schema, the server returns an entry
* with attributes that include "matchingrule" and "matchingruleuse".
* The values of these attributes are matching rule descriptions
* in this format.)
* in this format.
* <P>
*
* @param raw Definition of the matching rule in the
@ -118,92 +145,22 @@ public class LDAPMatchingRuleSchema extends LDAPAttributeSchema {
* MatchingRuleUseDescription format.
*/
public LDAPMatchingRuleSchema( String raw, String use ) {
super();
attrName = "matchingrules";
oid = processRule( raw );
String o = processRule( use );
if ( (o != null) && (oid != null) && !o.equals(oid) ) {
System.err.println( "Rule oid " + oid +
" differs from use oid " + o );
parseValue( raw );
if ( use != null ) {
parseValue( use );
}
if ( oid == null )
oid = o;
}
/**
* Construct a rule definition from a value returned from
* a search of the schema in a Directory.
* @param raw The raw string value returned as one of the values
* of <code>matchingRuleUse</code> in searching the schema.
*/
private String processRule( String raw ) {
if ( raw == null )
return null;
/* Process the matchingRuleUse value */
raw.trim();
// Skip past "( " and ")"
int l = raw.length();
raw = raw.substring( 2, l - 1 );
l = raw.length();
int ind = raw.indexOf( ' ' );
String o = raw.substring( 0, ind );
char[] ch = new char[l];
raw = raw.substring( ind + 1, l );
l = raw.length();
raw.getChars( 0, l, ch, 0 );
ind = 0;
l = ch.length;
while ( ind < l ) {
String s = "";
String val;
while( ch[ind] == ' ' )
ind++;
int last = ind + 1;
while( (last < l) && (ch[last] != ' ') )
last++;
if ( (ind < l) && (last < l) ) {
s = new String( ch, ind, last-ind );
ind = last;
} else {
ind = l;
}
while( (ind < l) && (ch[ind] != '\'') && (ch[ind] != '(') )
ind++;
last = ind + 1;
while( (last < l) && (ch[last] != '\'') && (ch[last] != ')') ) {
last++;
}
if ( (ind < last) && (last < l) ) {
val = new String( ch, ind+1, last-ind-1 );
ind = last + 1;
if ( s.equalsIgnoreCase( "NAME" ) ) {
name = val;
} else if ( s.equalsIgnoreCase( "DESC" ) ) {
description = val;
} else if ( s.equalsIgnoreCase( "SYNTAX" ) ) {
syntax = syntaxCheck( val );
} else if ( s.equalsIgnoreCase( "APPLIES" ) ) {
/* Parse the list of attribute OIDs */
Vector v = new Vector();
StringTokenizer st = new StringTokenizer( val, " " );
while ( st.hasMoreTokens() ) {
String tok = st.nextToken();
if ( !tok.equals( "$" ) ) {
v.addElement( tok );
}
}
attributes = new String[v.size()];
v.copyInto( attributes );
v.removeAllElements();
v = null;
}
}
Vector v = (Vector)properties.get( "APPLIES" );
if ( v != null ) {
attributes = new String[v.size()];
v.copyInto( attributes );
v.removeAllElements();
}
String val = (String)properties.get( "SYNTAX" );
if ( val != null ) {
syntaxString = val;
syntax = syntaxCheck( val );
}
return o;
}
/**
@ -216,6 +173,25 @@ public class LDAPMatchingRuleSchema extends LDAPAttributeSchema {
return attributes;
}
String getValue( boolean quotingBug ) {
String s = getValuePrefix();
s += "SYNTAX ";
if ( quotingBug ) {
s += '\'';
}
s += syntaxString;
if ( quotingBug ) {
s += '\'';
}
s += ' ';
String val = getCustomValues();
if ( val.length() > 0 ) {
s += val + ' ';
}
s += ')';
return s;
}
/**
* Get the matching rule definition in the string representation
* of the MatchingRuleDescription data type defined in X.501 (see
@ -236,11 +212,7 @@ public class LDAPMatchingRuleSchema extends LDAPAttributeSchema {
* a matching rule in the schema) of a <CODE>subschema</CODE> object.
*/
public String getValue() {
String s = "( " + oid + " NAME \'" + name + "\' DESC \'" +
description + "\' SYNTAX \'";
s += internalSyntaxToString();
s += "\' )";
return s;
return getValue( false );
}
/**
@ -263,14 +235,19 @@ public class LDAPMatchingRuleSchema extends LDAPAttributeSchema {
* a matching rule in the schema) of a <CODE>subschema</CODE> object.
*/
public String getUseValue() {
String s = "( " + oid;
s += " APPLIES ( ";
String s = getValuePrefix();
s += "APPLIES ( ";
for( int i = 0; i < attributes.length; i++ ) {
if ( i > 0 )
s += " $ ";
s += attributes[i];
}
s += ") )";
s += ") ";
String val = getCustomValues();
if ( val.length() > 0 ) {
s += val + ' ';
}
s += ')';
return s;
}
@ -281,9 +258,10 @@ public class LDAPMatchingRuleSchema extends LDAPAttributeSchema {
* @param op Type of modification to make.
* @param name Name of attribute in the schema entry to modify. This
* is ignored here.
* @param dn The entry at which to update the schema.
* @exception LDAPException if the definition can't be added/removed.
*/
protected void update( LDAPConnection ld, int op, String name )
protected void update( LDAPConnection ld, int op, String name, String dn )
throws LDAPException {
LDAPAttribute[] attrs = new LDAPAttribute[2];
attrs[0] = new LDAPAttribute( "matchingRules",
@ -291,7 +269,7 @@ public class LDAPMatchingRuleSchema extends LDAPAttributeSchema {
/* Must update the matchingRuleUse value as well */
attrs[1] = new LDAPAttribute( "matchingRuleUse",
getUseValue() );
update( ld, op, attrs );
update( ld, op, attrs, dn );
}
/**
@ -312,6 +290,7 @@ public class LDAPMatchingRuleSchema extends LDAPAttributeSchema {
s += attributes[i];
}
}
s += getQualifierString( EXPLICIT );
return s;
}

View File

@ -15,7 +15,7 @@
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.client;
package netscape.ldap;
import java.util.*;
import netscape.ldap.client.opers.*;
@ -24,59 +24,87 @@ import java.io.*;
import java.net.*;
/**
* This class represents the LDAPMessage in RFC1777. The
* Base class for LDAP request and response messages.
* This class represents the LDAPMessage in RFC2251. The
* message is the entity that got transferred back and
* fro between the server and the client interface. Each
* message has a protocol operation. The protocol operation
* indicates if it is a request or response.
* <pre>
* LDAPMessage ::= SEQUECE {
* LDAPMessage ::= SEQUENCE {
* messageID MessageID,
* protocolOp CHOICE {
* bindRequest BindRequest,
* ...
* }
* controls [0] Controls OPTIONAL
* }
* </pre>
*
* @version 1.0
*/
public class JDAPMessage {
public class LDAPMessage {
public final static int BIND_REQUEST = 0;
public final static int BIND_RESPONSE = 1;
public final static int UNBIND_REQUEST = 2;
public final static int SEARCH_REQUEST = 3;
public final static int SEARCH_RESPONSE = 4;
public final static int SEARCH_RESULT = 5;
public final static int MODIFY_REQUEST = 6;
public final static int MODIFY_RESPONSE = 7;
public final static int ADD_REQUEST = 8;
public final static int ADD_RESPONSE = 9;
public final static int DEL_REQUEST = 10;
public final static int DEL_RESPONSE = 11;
public final static int MODIFY_RDN_REQUEST = 12;
public final static int MODIFY_RDN_RESPONSE = 13;
public final static int COMPARE_REQUEST = 14;
public final static int COMPARE_RESPONSE = 15;
public final static int ABANDON_REQUEST = 16;
public final static int SEARCH_RESULT_REFERENCE = 19;
public final static int EXTENDED_REQUEST = 23;
public final static int EXTENDED_RESPONSE = 24;
/**
* Internal variables
*/
protected int m_msgid;
protected JDAPProtocolOp m_protocolOp = null;
protected JDAPControl m_controls[] = null;
private int m_msgid;
private JDAPProtocolOp m_protocolOp = null;
private LDAPControl m_controls[] = null;
/**
* Constructs a ldap message.
* @param msgid message identifier
* @param op operation protocol
*/
public JDAPMessage(int msgid, JDAPProtocolOp op) {
LDAPMessage(int msgid, JDAPProtocolOp op) {
m_msgid = msgid;
m_protocolOp = op;
}
public JDAPMessage(int msgid, JDAPProtocolOp op, JDAPControl controls[]) {
LDAPMessage(int msgid, JDAPProtocolOp op, LDAPControl controls[]) {
m_msgid = msgid;
m_protocolOp = op;
m_controls = controls; /* LDAPv3 additions */
}
/**
* Constructs a ldap message with BERElement. This constructor
* is used by JDAPClient to build JDAPMessage from byte
* stream.
* Creates a ldap message from a BERElement. This method is used
* to parse LDAP response messages
*
* @param element ber element constructed from incoming byte stream
*/
public JDAPMessage(BERElement element) throws IOException {
static LDAPMessage parseMessage(BERElement element) throws IOException {
int l_msgid;
JDAPProtocolOp l_protocolOp = null;
LDAPControl l_controls[] = null;
if (element.getType() != BERElement.SEQUENCE)
throw new IOException("SEQUENCE in jdap message expected");
BERSequence seq = (BERSequence)element;
BERInteger msgid = (BERInteger)seq.elementAt(0);
m_msgid = msgid.getValue();
l_msgid = msgid.getValue();
BERElement protocolOp = (BERElement)seq.elementAt(1);
if (protocolOp.getType() != BERElement.TAG) {
throw new IOException("TAG in protocol operation is expected");
@ -84,10 +112,10 @@ public class JDAPMessage {
BERTag tag = (BERTag)protocolOp;
switch (tag.getTag()&0x1f) {
case JDAPProtocolOp.BIND_RESPONSE:
m_protocolOp = new JDAPBindResponse(protocolOp);
l_protocolOp = new JDAPBindResponse(protocolOp);
break;
case JDAPProtocolOp.SEARCH_RESPONSE:
m_protocolOp = new JDAPSearchResponse(protocolOp);
l_protocolOp = new JDAPSearchResponse(protocolOp);
break;
/*
* If doing search without bind,
@ -96,31 +124,31 @@ public class JDAPMessage {
*/
case JDAPProtocolOp.SEARCH_REQUEST:
case JDAPProtocolOp.SEARCH_RESULT:
m_protocolOp = new JDAPSearchResult(protocolOp);
l_protocolOp = new JDAPSearchResult(protocolOp);
break;
case JDAPProtocolOp.MODIFY_RESPONSE:
m_protocolOp = new JDAPModifyResponse(protocolOp);
l_protocolOp = new JDAPModifyResponse(protocolOp);
break;
case JDAPProtocolOp.ADD_RESPONSE:
m_protocolOp = new JDAPAddResponse(protocolOp);
l_protocolOp = new JDAPAddResponse(protocolOp);
break;
case JDAPProtocolOp.DEL_RESPONSE:
m_protocolOp = new JDAPDeleteResponse(protocolOp);
l_protocolOp = new JDAPDeleteResponse(protocolOp);
break;
case JDAPProtocolOp.MODIFY_RDN_RESPONSE:
m_protocolOp = new JDAPModifyRDNResponse(protocolOp);
l_protocolOp = new JDAPModifyRDNResponse(protocolOp);
break;
case JDAPProtocolOp.COMPARE_RESPONSE:
m_protocolOp = new JDAPCompareResponse(protocolOp);
l_protocolOp = new JDAPCompareResponse(protocolOp);
break;
case JDAPProtocolOp.SEARCH_RESULT_REFERENCE:
m_protocolOp = new JDAPSearchResultReference(protocolOp);
l_protocolOp = new JDAPSearchResultReference(protocolOp);
break;
case JDAPProtocolOp.EXTENDED_RESPONSE:
m_protocolOp = new JDAPExtendedResponse(protocolOp);
l_protocolOp = new JDAPExtendedResponse(protocolOp);
break;
default:
throw new IOException("Unknown rotocol operation");
throw new IOException("Unknown protocol operation");
}
/* parse control */
@ -128,27 +156,51 @@ public class JDAPMessage {
tag = (BERTag)seq.elementAt(2);
if ( tag.getTag() == (BERTag.CONSTRUCTED|BERTag.CONTEXT|0) ) {
BERSequence controls = (BERSequence)tag.getValue();
m_controls = new JDAPControl[controls.size()];
l_controls = new LDAPControl[controls.size()];
for (int i = 0; i < controls.size(); i++) {
m_controls[i] = new JDAPControl(controls.elementAt(i));
}
l_controls[i] = LDAPControl.parseControl(controls.elementAt(i));
}
}
}
if (l_protocolOp instanceof JDAPSearchResponse) {
return new LDAPSearchResult(l_msgid,
(JDAPSearchResponse) l_protocolOp, l_controls);
}
else if (l_protocolOp instanceof JDAPSearchResultReference) {
return new LDAPSearchResultReference(l_msgid,
(JDAPSearchResultReference) l_protocolOp, l_controls);
}
else if (l_protocolOp instanceof JDAPExtendedResponse) {
return new LDAPExtendedResponse(l_msgid,
(JDAPExtendedResponse) l_protocolOp, l_controls);
}
else {
return new LDAPResponse(l_msgid, l_protocolOp, l_controls);
}
}
/**
* Retrieves the message identifer.
* Returns the message identifer.
* @return message identifer
*/
public int getId(){
return m_msgid;
}
/**
* Returns the LDAP operation type of the message
* @return message type
*/
public int getType(){
return m_protocolOp.getType();
}
/**
* Retrieves the protocol operation.
* @return protocol operation
*/
public JDAPProtocolOp getProtocolOp() {
JDAPProtocolOp getProtocolOp() {
return m_protocolOp;
}
@ -156,7 +208,7 @@ public class JDAPMessage {
* Retrieves list of controls.
* @return controls
*/
public JDAPControl[] getControls() {
public LDAPControl[] getControls() {
return m_controls;
}
@ -164,7 +216,7 @@ public class JDAPMessage {
* Writes the ber encoding to stream.
* @param s output stream
*/
public void write(OutputStream s) throws IOException {
void write(OutputStream s) throws IOException {
BERSequence seq = new BERSequence();
BERInteger i = new BERInteger(m_msgid);
seq.addElement(i);
@ -189,6 +241,17 @@ public class JDAPMessage {
* @return ldap message
*/
public String toString() {
return "[JDAPMessage] " + m_msgid + " " + m_protocolOp.toString();
if (m_controls == null) {
return "[LDAPMessage] " + m_msgid + " " + m_protocolOp.toString();
}
else {
StringBuffer sb = new StringBuffer(
"[LDAPMessage] " + m_msgid + " " + m_protocolOp.toString());
for (int i =0; i < m_controls.length; i++) {
sb.append(" ctrl"+i+"=");
sb.append(m_controls[i].toString());
}
return sb.toString();
}
}
}

View File

@ -0,0 +1,428 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import java.util.Vector;
/**
* A queue of response messsages from the server. Multiple requests
* can be multiplexed on the same queue. For synchronous LDAPConnection
* requests, there will be only one request per queue. For asynchronous
* LDAPConnection requests, the user can add multiple request to the
* same queue.
*
* Superclass for LDAResponseListener and LDAPSearchListener
*
*/
class LDAPMessageQueue {
/**
* Request entry encapsulates request parameters
*/
private static class RequestEntry {
int id;
LDAPConnection connection;
LDAPConnThread connThread;
RequestEntry(int id, LDAPConnection connection, LDAPConnThread connThread) {
this.id= id;
this.connection = connection;
this.connThread = connThread;
}
}
/**
* Internal variables
*/
private /*LDAPMessage */ Vector m_messageQueue = new Vector(1);
private /*RequestEntry*/ Vector m_requestList = new Vector(1);
private LDAPException m_exception; /* For network errors */
private boolean m_asynchOp;
/**
* Constructor
* @param asynchOp A flag whether the object is used for asynchronous
* LDAP operations
* @see netscape.ldap.LDAPAsynchronousConnection
*/
LDAPMessageQueue (boolean asynchOp) {
m_asynchOp = asynchOp;
}
/**
* Returns a flag whether the listener is used for asynchronous LDAP
* operations
* @return Asynchronous operation flag
* @see netscape.ldap.LDAPAsynchronousConnection
*/
boolean isAsynchOp() {
return m_asynchOp;
}
/**
* Blocks until a response is available or until all operations
* associated with the object have completed or been canceled.
* @return LDAP message or null if there is no more outstanding requests
* @exception LDAPException Network error exception
* @exception LDAPInterruptedException The invoking thread was interrupted
*/
synchronized LDAPMessage nextMessage () throws LDAPException {
while(m_requestList.size() != 0 && m_exception == null && m_messageQueue.size() == 0) {
try {
wait ();
} catch (InterruptedException e) {
throw new LDAPInterruptedException("Interrupted LDAP operation");
}
}
// Network exception occurred ?
if (m_exception != null) {
LDAPException ex = m_exception;
m_exception = null;
throw ex;
}
// Are there any outstanding requests left
if (m_requestList.size() == 0) {
return null; // No outstanding requests
}
// Dequeue the first entry
LDAPMessage msg = (LDAPMessage) m_messageQueue.elementAt(0);
m_messageQueue.removeElementAt(0);
// Is the ldap operation completed?
if (msg instanceof LDAPResponse) {
removeRequest(msg.getId());
}
return msg;
}
/**
* Wait for request to complete. This method blocks until a message of
* type LDAPResponse has been received. Used by synchronous search
* with batch size of zero (block until all results are received)
* @return LDAPResponse message or null if there is no more outstanding requests
* @exception LDAPException Network error exception
* @exception LDAPInterruptedException The invoking thread was interrupted
*/
synchronized LDAPResponse completeRequest () throws LDAPException {
while (true) {
while(m_requestList.size() != 0 && m_exception == null && m_messageQueue.size() == 0) {
try {
wait ();
} catch (InterruptedException e) {
throw new LDAPInterruptedException("Interrupted LDAP operation");
}
}
// Network exception occurred ?
if (m_exception != null) {
LDAPException ex = m_exception;
m_exception = null;
throw ex;
}
// Are there any outstanding requests left?
if (m_requestList.size() == 0) {
return null; // No outstanding requests
}
// Search an instance of LDAPResponse
for (int i= m_messageQueue.size()-1; i >=0; i--) {
LDAPMessage msg = (LDAPMessage) m_messageQueue.elementAt(i);
if (msg instanceof LDAPResponse) {
// Dequeue the entry and return
m_messageQueue.removeElementAt(i);
return (LDAPResponse)msg;
}
}
// Not found, wait for the next message
try {
wait ();
} catch (InterruptedException e) {
throw new LDAPInterruptedException("Interrupted LDAP operation");
}
}
}
/**
* Merge two message queues.
* Move/append the content from another message queue to this one.
*
* To be used for synchronization of asynchronous LDAP operations where
* requests are sent by one thread but processed by another one
*
* A client may be implemented in such a way that one thread makes LDAP
* requests and calls l.getIDs(), while another thread is responsible for
* processing of responses (call l.getResponse()). Both threads are using
* the same listener objects. In such a case, a race
* condition may occur, where a LDAP response message is retrieved and
* the request terminated (request ID removed) before the first thread
* has a chance to execute l.getIDs().
* The proper way to handle this scenario is to create a separate listener
* for each new request, and after l.getIDs() has been invoked, merge the
* new request with the existing one.
* @param mq2 Message queue to be merged with this one.
*/
synchronized void merge(LDAPMessageQueue mq2) {
synchronized (mq2) {
for (int i=0; i < mq2.m_requestList.size(); i++) {
m_requestList.addElement(mq2.m_requestList.elementAt(i));
}
for (int i=0; i < mq2.m_messageQueue.size(); i++) {
m_messageQueue.addElement(mq2.m_messageQueue.elementAt(i));
}
if (mq2.m_exception != null) {
m_exception = mq2.m_exception;
}
mq2.reset();
notifyAll(); // notify for mq2
}
notifyAll(); // notify this mq
}
/**
* Retrieves all messages currently in the queue without blocking
* @returns Vector of messages
*/
synchronized Vector getAllMessages() {
Vector result = m_messageQueue;
m_messageQueue = new Vector(1);
return result;
}
/**
* Queues the LDAP server's response. This causes anyone waiting
* in nextMessage() to unblock.
* @param msg response message
*/
synchronized void addMessage (LDAPMessage msg) {
m_messageQueue.addElement(msg);
notifyAll ();
}
/**
* Signals that a network exception occured while servicing the
* request. This exception will be throw to any thread waiting
* in nextMessage()
* @param connThread LDAPConnThread on which the exception occurred
* @param e exception
*/
synchronized void setException (LDAPConnThread connThread, LDAPException e) {
m_exception = e;
removeAllRequests(connThread);
notifyAll ();
}
/**
* Checks if response message is received.
* @return true or false
*/
boolean isMessageReceived() {
return m_messageQueue.size() != 0;
}
/**
* Returns the count of queued messages
* @return message count
*/
public int getMessageCount () {
return m_messageQueue.size();
}
/**
* Remove all queued messages associated with the request ID
* Called when a LDAP operation is abandoned
*
* Not synchronized as its private and can be called only by
* abandon() and removeAllRequests()
*
* @return Count of removed messages
*/
private int removeAllMessages(int id) {
int removeCount=0;
for (int i=(m_messageQueue.size()-1); i>=0; i--) {
LDAPMessage msg = (LDAPMessage)m_messageQueue.elementAt(i);
if (msg.getId() == id) {
m_messageQueue.removeElementAt(i);
removeCount++;
}
}
return removeCount;
}
/**
* Resets the state of this object, so it can be recycled.
* Used by LDAPConnection synchronous operations.
* @see netscape.ldap.LDAPConnection#getResponseListener
* @see netscape.ldap.LDAPConnection#getSearchListener
*/
void reset () {
m_exception = null;
m_messageQueue.removeAllElements();
m_requestList.removeAllElements();
}
/**
* Returns the connection associated with the specified request id
* @parm id request id
* @return connection
*/
synchronized LDAPConnection getConnection(int id) {
for (int i=0; i < m_requestList.size(); i++) {
RequestEntry entry = (RequestEntry)m_requestList.elementAt(i);
if (id == entry.id) {
return entry.connection;
}
}
return null;
}
/**
* Returns the connection thread associated with the specified request id
* @parm id request id
* @return connection thread
*/
synchronized LDAPConnThread getConnThread(int id) {
for (int i=0; i < m_requestList.size(); i++) {
RequestEntry entry = (RequestEntry)m_requestList.elementAt(i);
if (id == entry.id) {
return entry.connThread;
}
}
return null;
}
/**
* Returns message id of the last request
* @return Message id.
*/
synchronized int getID() {
int reqCnt = m_requestList.size();
if ( reqCnt == 0) {
return -1;
}
else {
RequestEntry entry = (RequestEntry)m_requestList.elementAt(reqCnt-1);
return entry.id;
}
}
/**
* Returns a list of message ids for all outstanding requests
* @return Message id array
*/
synchronized int[] getIDs() {
int[] ids = new int[m_requestList.size()];
for (int i=0; i < ids.length; i++) {
RequestEntry entry = (RequestEntry)m_requestList.elementAt(i);
ids[i] = entry.id;
}
return ids;
}
/**
* Registers a LDAP request
* @param id LDAP request message ID
* @param connection LDAP Connection for the message ID
* @param connThread A physical connection to the server
*/
synchronized void addRequest(int id, LDAPConnection connection,
LDAPConnThread connThread) {
m_requestList.addElement(new RequestEntry(id, connection, connThread));
}
/**
* Returns the number of outstanding requests.
* @return Outstanding request count.
*/
public int getRequestCount() {
return m_requestList.size();
}
/**
* Remove request with the specified ID
* Called when a LDAP operation is abandoned (called from
* LDAPConnThread), or terminated (called by nextMessage() when
* LDAPResponse message is received)
* @return Flag whether the request was removed
*/
synchronized boolean removeRequest(int id) {
for (int i=0; i < m_requestList.size(); i++) {
RequestEntry entry = (RequestEntry)m_requestList.elementAt(i);
if (id == entry.id) {
m_requestList.removeElementAt(i);
removeAllMessages(id);
notifyAll();
return true;
}
}
return false;
}
/**
* Remove all requests associated with the specified connThread
* Called when a connThread has a network error
* @return Number of removed request
*/
synchronized int removeAllRequests(LDAPConnThread connThread) {
int removeCount=0;
for (int i=(m_requestList.size()-1); i>=0; i--) {
RequestEntry entry = (RequestEntry)m_requestList.elementAt(i);
if (connThread == entry.connThread) {
m_requestList.removeElementAt(i);
removeCount++;
// remove all queued messages as well
removeAllMessages(entry.id);
}
}
notifyAll();
return removeCount;
}
/**
* String representation of the object
*/
public String toString() {
StringBuffer sb = new StringBuffer("LDAPMessageQueue:");
sb.append(" requestIDs={");
for (int i=0; i < m_requestList.size(); i++) {
if (i>0) {
sb.append(",");
}
sb.append(((RequestEntry)m_requestList.elementAt(i)).id);
}
sb.append("} messageCount="+m_messageQueue.size());
return sb.toString();
}
}

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
@ -43,23 +43,24 @@ import java.util.*;
* When you construct an <CODE>LDAPObjectSchema</CODE> object, you can specify
* these types of information as arguments to the constructor or in the
* ObjectClassDescription format specified in RFC 2252.
* (When an LDAP client searches an LDAP server for the schema, the server
* When an LDAP client searches an LDAP server for the schema, the server
* returns schema information as an object with attribute values in this
* format.)
* format.
* <P>
*
* RFC 2252 also notes that you can specify whether or not an object class
* is abstract, structural, or auxiliary in the object description.
* (Abstract object classes are used only to derive other object classes.
* Abstract object classes are used only to derive other object classes.
* Entries cannot belong to an abstract object class. <CODE>top</CODE>
* is an abstract object class.) Entries must belong to a structural
* is an abstract object class. Entries must belong to a structural
* object class, so most object classes are structural object classes.
* Objects of the <CODE>LDAPObjectClassSchema</CODE> class are structural
* object classes by default. Auxiliary object classes can be used to
* construct entries of different types. For example, an auxiliary object
* class might be used to specify a type of entry with a structural object
* class that can vary (an auxiliary object class might specify that an
* entry must either be an organizationalPerson or residentialPerson).
* add attributes to entries of different types. For example, an
* auxiliary object class might be used to specify personal preference
* attributes. An entry can not contain just that object class, but may
* include it along with a structural object class, for example
* inetOrgPerson.
* If the definition of an object (in ObjectClassDescription format)
* specifies the AUXILIARY keyword, an <CODE>LDAPObjectClassSchema</CODE>
* object created from that description represents an auxiliary object class.
@ -68,14 +69,32 @@ import java.util.*;
* You can get the name, OID, and description of this object class
* definition by using the <CODE>getName</CODE>, <CODE>getOID</CODE>, and
* <CODE>getDescription</CODE> methods inherited from the abstract class
* <CODE>LDAPSchemaElement</CODE>.
* <CODE>LDAPSchemaElement</CODE>. Optional and custom qualifiers are
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
* from <CODE>LDAPSchemaElement</CODE>.
* <P>
*
* If you need to add or remove this object class definition from the
* schema, you can use the <CODE>add</CODE> and <CODE>remove</CODE>
* To add or remove this object class definition from the
* schema, use the <CODE>add</CODE> and <CODE>remove</CODE>
* methods, which this class inherits from the <CODE>LDAPSchemaElement</CODE>
* abstract class.
* <P>
* RFC 2252 defines ObjectClassDescription as follows:
* <P>
* <PRE>
* ObjectClassDescription = "(" whsp
* numericoid whsp ; ObjectClass identifier
* [ "NAME" qdescrs ]
* [ "DESC" qdstring ]
* [ "OBSOLETE" whsp ]
* [ "SUP" oids ] ; Superior ObjectClasses
* [ ( "ABSTRACT" / "STRUCTURAL" / "AUXILIARY" ) whsp ]
* ; default structural
* [ "MUST" oids ] ; AttributeTypes
* [ "MAY" oids ] ; AttributeTypes
* whsp ")"
* </PRE>
*
* @version 1.0
* @see netscape.ldap.LDAPSchemaElement
@ -97,14 +116,41 @@ public class LDAPObjectClassSchema extends LDAPSchemaElement {
*/
public LDAPObjectClassSchema( String name, String oid, String superior,
String description,
String[] required, String optional[] ) {
String[] required, String[] optional ) {
super( name, oid, description );
attrName = "objectclasses";
this.superior = superior;
for( int i = 0; i < required.length; i++ )
this.superiors = new String[] { superior };
for( int i = 0; i < required.length; i++ ) {
must.addElement( required[i] );
for( int i = 0; i < optional.length; i++ )
}
for( int i = 0; i < optional.length; i++ ) {
may.addElement( optional[i] );
}
}
/**
* Constructs an object class definition, using the specified
* information.
* @param name Name of the object class.
* @param oid Object identifier (OID) of the object class
* in dotted-string format (for example, "1.2.3.4").
* @param description Description of the object class.
* @param superiors Name of parent object classes
* (the object class that the new object class inherits from).
* @param required Array of the names of the attributes required
* in this object class.
* @param optional Array of the names of the optional attributes
* allowed in this object class.
* @param type Either ABSTRACT, STRUCTURAL, or AUXILIARY
*/
public LDAPObjectClassSchema( String name, String oid,
String[] superiors,
String description,
String[] required, String[] optional,
int type ) {
this( name, oid, superiors[0], description, required, optional );
this.superiors = superiors;
this.type = type;
}
/**
@ -125,85 +171,27 @@ public class LDAPObjectClassSchema extends LDAPSchemaElement {
*/
public LDAPObjectClassSchema( String raw ) {
attrName = "objectclasses";
raw.trim();
// Skip past "( " and ")"
int l = raw.length();
raw = raw.substring( 2, l - 1 );
l = raw.length();
int ind = raw.indexOf( ' ' );
oid = raw.substring( 0, ind );
char[] ch = new char[l];
raw = raw.substring( ind + 1, l );
l = raw.length();
raw.getChars( 0, l, ch, 0 );
ind = 0;
l = ch.length;
while ( ind < l ) {
String s = "";
String val;
while( ch[ind] == ' ' )
ind++;
int last = ind + 1;
while( (last < l) && (ch[last] != ' ') )
last++;
if ( (ind < l) && (last < l) ) {
s = new String( ch, ind, last-ind );
ind = last;
if ( s.equalsIgnoreCase( "AUXILIARY" ) ) {
auxiliary = true;
continue;
}
} else {
ind = l;
}
while( (ind < l) && (ch[ind] != '\'') && (ch[ind] != '(') )
ind++;
last = ind + 1;
if ( ind >= l ) {
break;
}
if ( ch[ind] == '\'' ) {
while( (last < l) && (ch[last] != '\'') ) {
last++;
}
if ( (ind < last) && (last < l) ) {
val = new String( ch, ind+1, last-ind-1 );
if ( s.equalsIgnoreCase( "NAME" ) ) {
name = val;
} else if ( s.equalsIgnoreCase( "DESC" ) ) {
description = val;
} else if ( s.equalsIgnoreCase( "SUP" ) ) {
superior = val;
}
}
} else {
Vector v = null;
if ( s.equalsIgnoreCase( "MAY" ) ) {
v = may;
} else if ( s.equalsIgnoreCase( "MUST" ) ) {
v = must;
} else {
continue;
}
while( (last < l) && (ch[last] != ')') ) {
last++;
}
if ( (ind < last) && (last < l) ) {
val = new String( ch, ind+1, last-ind-1 );
StringTokenizer st = new StringTokenizer( val, " " );
while ( st.hasMoreTokens() ) {
String tok = st.nextToken();
if ( !tok.equals( "$" ) ) {
v.addElement( tok );
}
}
}
}
ind = last + 1;
parseValue( raw );
String[] vals = getQualifier( SUPERIOR );
if ( vals != null ) {
superiors = vals;
setQualifier( SUPERIOR, (String)null );
}
if ( properties.containsKey( "AUXILIARY" ) ) {
type = AUXILIARY;
} else if ( properties.containsKey( "ABSTRACT" ) ) {
type = ABSTRACT;
} else if ( properties.containsKey( "STRUCTURAL" ) ) {
type = STRUCTURAL;
}
obsolete = properties.containsKey( OBSOLETE );
Vector v = (Vector)properties.get( "MAY" );
if ( v != null ) {
may = v;
}
v = (Vector)properties.get( "MUST" );
if ( v != null ) {
must = v;
}
}
@ -213,7 +201,18 @@ public class LDAPObjectClassSchema extends LDAPSchemaElement {
* inherits from.
*/
public String getSuperior() {
return superior;
return superiors[0];
}
/**
* Get the names of all object classes that this class inherits
* from. Typically only one, but RFC 2252 allows multiple
* inheritance.
* @return The names of the object classes that this class
* inherits from.
*/
public String[] getSuperiors() {
return superiors;
}
/**
@ -237,47 +236,37 @@ public class LDAPObjectClassSchema extends LDAPSchemaElement {
}
/**
* Get the object class definition in a string representation
* of the ObjectClassDescription data type defined in X.501 (see
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* Attribute Syntax Definitions</A> for a description of this format).
* This is the format that LDAP servers and clients use to exchange
* schema information. (For example, when
* you search an LDAP server for its schema, the server returns an entry
* with the attributes "objectclasses" and "attributetypes". The
* values of the "objectclasses" attribute are object class descriptions
* in this format.)
* <P>
*
* @return A string in a format that can be used as the value of
* the <code>objectclasses</code> attribute (which describes
* an object class in the schema) of a <CODE>subschema</CODE> object.
* Get the type of the object class.
* @return STRUCTURAL, ABSTRACT, or AUXILIARY
*/
public String getValue() {
String s = "( " + oid + " NAME \'" + name + "\' DESC \'" +
description + "\' SUP \'" + superior + "\' ";
if ( auxiliary )
s += "AUXILIARY ";
s += "MUST ( ";
int i = 0;
Enumeration e = getRequiredAttributes();
while( e.hasMoreElements() ) {
if ( i > 0 )
s += " $ ";
i++;
s += (String)e.nextElement();
public int getType() {
return type;
}
/**
* Prepare a value in RFC 2252 format for submitting to a server
*
* @param quotingBug <CODE>true</CODE> if SUP and SYNTAX values are to
* be quoted. That is to satisfy bugs in certain LDAP servers.
* @return A String ready to be submitted to an LDAP server
*/
String getValue( boolean quotingBug ) {
String s = getValuePrefix();
s += getValue( SUPERIOR, quotingBug );
s += ' ';
String val = getOptionalValues( NOVALS );
if ( val.length() > 0 ) {
s += val + ' ';
}
s += " ) MAY ( ";
e = getOptionalAttributes();
i = 0;
while( e.hasMoreElements() ) {
if ( i > 0 )
s += " $ ";
i++;
s += (String)e.nextElement();
s += getValue( "MUST", false );
s += ' ';
s += getValue( "MAY", false );
s += ' ';
val = getCustomValues();
if ( val.length() > 0 ) {
s += val + ' ';
}
s += ") )";
s += ')';
return s;
}
@ -289,8 +278,14 @@ public class LDAPObjectClassSchema extends LDAPSchemaElement {
*/
public String toString() {
String s = "Name: " + name + "; OID: " + oid +
"; Superior: " + superior +
"; Description: " + description + "; Required: ";
"; Superior: ";
for( int i = 0; i < superiors.length; i++ ) {
s += superiors[i];
if ( i < (superiors.length-1) ) {
s += ", ";
}
}
s += "; Description: " + description + "; Required: ";
int i = 0;
Enumeration e = getRequiredAttributes();
while( e.hasMoreElements() ) {
@ -308,11 +303,40 @@ public class LDAPObjectClassSchema extends LDAPSchemaElement {
i++;
s += (String)e.nextElement();
}
switch ( type ) {
case STRUCTURAL:
break;
case ABSTRACT:
s += "; ABSTRACT";
break;
case AUXILIARY:
s += "; AUXILIARY";
break;
}
if ( obsolete ) {
s += "; OBSOLETE";
}
s += getQualifierString( IGNOREVALS );
return s;
}
private String superior = "";
public static final int STRUCTURAL = 0;
public static final int ABSTRACT = 1;
public static final int AUXILIARY = 2;
private String[] superiors = { "" };
private Vector must = new Vector();
private Vector may = new Vector();
private boolean auxiliary = false;
private int type = STRUCTURAL;
// Qualifers known to not have values
static String[] NOVALS = { "ABSTRACT", "STRUCTURAL",
"AUXILIARY" };
static {
for( int i = 0; i < NOVALS.length; i++ ) {
novalsTable.put( NOVALS[i], NOVALS[i] );
}
}
static String[] IGNOREVALS = { "ABSTRACT", "STRUCTURAL",
"AUXILIARY", "MUST", "MAY" };
}

View File

@ -17,7 +17,6 @@
*/
package netscape.ldap;
import netscape.ldap.*;
import java.util.*;
import java.io.*;

View File

@ -0,0 +1,82 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import netscape.ldap.client.opers.JDAPProtocolOp;
import netscape.ldap.client.opers.JDAPResult;
/**
* Represents the response to a particular LDAP operation.
*
* @version 1.0
*/
public class LDAPResponse extends LDAPMessage {
/**
* Constructor
*
* @param msgid message identifier
* @param rsp Operation response
* @param controls Array of controls of null
*/
LDAPResponse(int msgid, JDAPProtocolOp rsp, LDAPControl controls[]) {
super(msgid, rsp, controls);
}
/**
* Returns any error message in the response.
*
* @return The error message of the last error (or <CODE>null</CODE>
* if no message was set).
*/
public String getErrorMessage() {
JDAPResult result = (JDAPResult) getProtocolOp();
return result.getErrorMessage();
}
/**
* Returns the partially matched DN field, if any, in a server response.
*
* @return The maximal subset of a DN which could be matched,
* or <CODE>null</CODE>.
*/
public String getMatchedDN() {
JDAPResult result = (JDAPResult) getProtocolOp();
return result.getMatchedDN();
}
/**
* Returns all referrals, if any, in a server response.
*
* @return A list of referrals or <CODE>null</CODE>.
*/
public String[] getReferrals() {
JDAPResult result = (JDAPResult) getProtocolOp();
return result.getReferrals();
}
/**
* Returns the result code in a server response.
*
* @return The result code.
*/
public int getResultCode() {
JDAPResult result = (JDAPResult) getProtocolOp();
return result.getResultCode();
}
}

View File

@ -0,0 +1,51 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
/*
* This object represents the value of the LDAPConnection.m_responseControlTable hashtable.
* It stores the response controls and its corresponding LDAPConnection and
* the message ID for its corresponding LDAPMessage.
*/
class LDAPResponseControl {
private LDAPConnection m_connection;
private int m_messageID;
private LDAPControl[] m_controls;
public LDAPResponseControl(LDAPConnection conn, int msgID,
LDAPControl[] controls) {
m_connection = conn;
m_messageID = msgID;
m_controls = new LDAPControl[controls.length];
for (int i=0; i<controls.length; i++)
m_controls[i] = controls[i];
}
public int getMsgID() {
return m_messageID;
}
public LDAPControl[] getControls() {
return m_controls;
}
public LDAPConnection getConnection() {
return m_connection;
}
}

View File

@ -12,141 +12,80 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import netscape.ldap.client.*;
/**
* An object for taking the asynchronous LDAP responses and making them
* appear somewhat synchronized. Uses built-in Java monitors to block
* until a response is received. This is also used to communicate
* exceptions across threads.
*
* This class is part of the implementation; it is of no interest to
* developers.
*
* @version 1.0
* Represents the message queue associated with a particular LDAP
* operation or operations.
*
*/
class LDAPResponseListener
{
/**
* Internal variables
*/
private JDAPMessage response;
private LDAPException exception;
private boolean responseReceived;
private boolean exceptionOccured;
private Thread me;
private LDAPControl[] controls;
private LDAPConnection connection;
private int id;
public class LDAPResponseListener extends LDAPMessageQueue{
/**
* Constructs a basic response Listener.
* Constructor
* @param asynchOp A flag whether the object is used for asynchronous
* LDAP operations
* @see netscape.ldap.LDAPAsynchronousConnection
*/
public LDAPResponseListener ( LDAPConnection conn ) {
connection = conn;
reset ();
LDAPResponseListener(boolean asynchOp) {
super(asynchOp);
}
/**
* Retrieves response message. This method blocks until the response
* has been received.
* @return jdap message
*/
synchronized JDAPMessage getResponse () throws LDAPException {
while (!responseReceived) {
try {
wait ();
} catch (InterruptedException e) {
}
}
if (exceptionOccured) throw exception;
return response;
}
/**
* Posts the LDAP server's response to the object. This causes
* anyone waiting on getResponse to unblock.
* @param response response message
*/
synchronized void setResponse (JDAPMessage response) {
this.response = response;
this.responseReceived = true;
notifyAll ();
}
/**
* Signals that an LDAPException occured while servicing the
* request. This exception will be throw to any threads waiting
* on getResponse
* @param e exception
*/
synchronized void setException (LDAPException e) {
exceptionOccured = true;
responseReceived = true;
exception = e;
notifyAll ();
}
/**
* Checks if response received.
* @return true or false
*/
boolean isResponseReceived() {
return responseReceived;
}
/**
* Resets the state of this object, so it can be recycled.
*/
void reset () {
responseReceived = false;
exceptionOccured = false;
me = null;
}
/**
* Keep track of the thread which issued the request.
* Blocks until a response is available, or until all operations
* associated with the object have completed or been canceled, and
* returns the response.
*
* @return A response for a LDAP operation or null if there is no
* more outstanding requests
* @exception LDAPException Network error exception
* @exception LDAPInterruptedException The invoking thread was interrupted
*/
void setThread() {
me = Thread.currentThread();
public LDAPResponse getResponse() throws LDAPException {
return (LDAPResponse)nextMessage();
}
/**
* What thread issued this request?
* @return The issuing thread
* Merge two response listeners
* Move/append the content from another response listener to this one.
*
* To be used for synchronization of asynchronous LDAP operations where
* requests are sent by one thread but processed by another one
*
* A client may be implemented in such a way that one thread makes LDAP
* requests and calls l.getIDs(), while another thread is responsible for
* processing of responses (call l.getResponse()). Both threads are using
* the same listener objects. In such a case, a race
* condition may occur, where a LDAP response message is retrieved and
* the request terminated (request ID removed) before the first thread
* has a chance to execute l.getIDs().
* The proper way to handle this scenario is to create a separate listener
* for each new request, and after l.getIDs() has been invoked, merge the
* new request with the existing one.
* @param listener2 The listener to be merged with.
*/
Thread getThread() {
return me;
public void merge(LDAPSearchListener listener2) {
super.merge(listener2);
}
/**
* Reports true if a response has been received from the server.
*
* @return A flag whether the response message queue is empty
*/
public boolean isResponseReceived() {
return super.isMessageReceived();
}
/**
* Return owner connection
* @return Owner connection
* Returns message ids for all outstanding requests
* @return Message id array
*/
LDAPConnection getConnection() {
return connection;
}
/**
* Returns message id.
* @return Message id.
*/
int getID() {
return id;
}
/**
* Sets the message id.
* @param id The message id.
*/
void setID( int id ) {
this.id = id;
public int[] getIDs() {
return super.getIDs();
}
}

View File

@ -12,14 +12,13 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import java.io.*;
import java.net.*;
import netscape.ldap.*;
/**
* Creates an SSL socket connection to an LDAP Server. This class
@ -40,7 +39,7 @@ import netscape.ldap.*;
*
* @version 1.0
* @see LDAPSSLSocketFactoryExt
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSSLSocketFactoryExt)
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
*/
public class LDAPSSLSocketFactory implements LDAPSSLSocketFactoryExt {
@ -246,17 +245,23 @@ public class LDAPSSLSocketFactory implements LDAPSSLSocketFactoryExt {
if (m_clientAuth) {
try {
/* Check if running in Communicator; if so, enable client auth */
java.lang.reflect.Method m = LDAPCheckComm.getMethod(
"netscape.security.PrivilegeManager", "enablePrivilege");
/* Check if running in Communicator; if so, enable client
auth */
String[] types = { "java.lang.String" };
java.lang.reflect.Method m =
DynamicInvoker.getMethod(
"netscape.security.PrivilegeManager",
"enablePrivilege",
types );
if (m != null) {
Object[] args = new Object[1];
args[0] = new String("ClientAuth");
m.invoke( null, args);
}
} catch (Exception e) {
throw new LDAPException("Invoking enablePrivilege: " +
e.toString(), LDAPException.PARAM_ERROR);
String msg = "LDAPSSLSocketFactory.makeSocket: invoking " +
"enablePrivilege: " + e.toString();
throw new LDAPException(msg, LDAPException.PARAM_ERROR);
}
}

View File

@ -17,8 +17,6 @@
*/
package netscape.ldap;
import netscape.ldap.*;
/**
* Represents a SSL socket connection that you can use to connect to an
* LDAP server. This interface extends the base interface LDAPSocketFactory

View File

@ -20,7 +20,6 @@ package netscape.ldap;
import java.io.*;
import java.net.*;
import java.util.Hashtable;
import netscape.ldap.*;
/**
* Creates an SSL socket connection to an LDAP Server. This class is provided

View File

@ -0,0 +1,273 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import java.util.*;
import netscape.ldap.client.*;
import netscape.ldap.client.opers.*;
import netscape.ldap.ber.stream.*;
import netscape.ldap.util.*;
import java.io.*;
import java.net.*;
import javax.security.auth.callback.CallbackHandler;
/**
* Authenticates to a server using SASL
*/
public class LDAPSaslBind implements LDAPBind, Serializable {
/**
* Construct an object which can authenticate to an LDAP server
* using the specified name and a specified SASL mechanism.
*
* @param dn If non-null and non-empty, specifies that the connection and
* all operations through it should be authenticated with dn as the
* distinguished name.
* @param mechanisms Array of mechanism names, e.g. { "GSSAPI", "SKEY" }
* @param props Optional additional properties of the desired
* authentication mechanism, e.g. minimum security level.
* @param cbh A class which may be called by the SASL framework to
* obtain additional information required.
*/
public LDAPSaslBind( String dn,
String[] mechanisms,
String packageName,
Hashtable props,
CallbackHandler cbh ) {
_dn = dn;
_mechanisms = mechanisms;
_packageName = packageName;
_props = props;
_cbh = cbh;
}
/**
* Authenticates to the LDAP server (that the object is currently
* connected to) using the parameter that were provided to the
* constructor. If the requested SASL mechanism is not
* available, an exception is thrown. If the object has been
* disconnected from an LDAP server, this method attempts to reconnect
* to the server. If the object had already authenticated, the old
* authentication is discarded.
*
* @param ldc An active connection to a server, which will have
* the new authentication state on return from the method.
* @exception LDAPException Failed to authenticate to the LDAP server.
*/
public void bind( LDAPConnection ldc ) throws LDAPException {
if ( _props == null ) {
_props = new Hashtable();
}
if ( (!_props.containsKey( CLIENTPKGS )) &&
(System.getProperty( CLIENTPKGS ) == null) ) {
_props.put( CLIENTPKGS, ldc.DEFAULT_SASL_PACKAGE );
}
_saslClient = getClient( ldc, _packageName );
if ( _saslClient != null ) {
bind( ldc, true );
return;
} else {
ldc.printDebug( "LDAPSaslBind.bind: getClient " +
"returned null" );
}
}
/**
* Get a SaslClient object from the Sasl framework
*
* @param ldc Contains the host name
* @param packageName Package containing a ClientFactory
* @return A SaslClient supporting one of the mechanisms
* of the member variable _mechanisms
* @exception LDAPException on error producing a client
*/
private Object getClient( LDAPConnection ldc, String packageName )
throws LDAPException {
try {
Object[] args = new Object[6];
args[0] = _mechanisms;
args[1] = _dn;
args[2] = "ldap";
args[3] = ldc.getHost();
args[4] = _props;
args[5] = _cbh;
String[] argNames = new String[6];
argNames[0] = "[Ljava.lang.String;";
argNames[1] = "java.lang.String";
argNames[2] = "java.lang.String";
argNames[3] = "java.lang.String";
argNames[4] = "java.util.Hashtable";
argNames[5] = CALLBACK_HANDLER;
// Get a mechanism driver
return DynamicInvoker.invokeMethod(null,
packageName+".Sasl",
"createSaslClient",
args, argNames);
} catch (Exception e) {
ldc.printDebug( "LDAPSaslBind.getClient: " +
packageName+".Sasl.createSaslClient: " +
e );
throw new LDAPException(e.toString(), LDAPException.OTHER);
}
}
void bind(LDAPConnection ldc, boolean rebind)
throws LDAPException {
if ((ldc.isConnected() && rebind) ||
!ldc.isConnected()) {
try {
// Get the initial request to start authentication
String className = _saslClient.getClass().getName();
ldc.printDebug( "LDAPSaslBind.bind: calling " +
className+".createInitialResponse" );
byte[] outVals =
(byte[])DynamicInvoker.invokeMethod(
_saslClient,
className,
"createInitialResponse", null, null);
String mechanismName =
(String)DynamicInvoker.invokeMethod(
_saslClient,
className,
"getMechanismName", null, null);
ldc.printDebug( "LDAPSaslBind.bind: mechanism " +
"name is " +
mechanismName );
boolean isExternal = isExternalMechanism(mechanismName);
int resultCode = LDAPException.SASL_BIND_IN_PROGRESS;
JDAPBindResponse response = null;
while (!checkForSASLBindCompletion(resultCode)) {
ldc.printDebug( "LDAPSaslBind.bind: calling " +
"saslBind" );
response = saslBind(ldc, mechanismName, outVals);
resultCode = response.getResultCode();
ldc.printDebug( "LDAPSaslBind.bind: saslBind " +
"returned " + resultCode );
if (isExternal) {
continue;
}
String challenge = response.getCredentials();
byte[] b = challenge.getBytes();
Object[] args = {b};
String[] argNames = {"[B"}; // class name for byte array
outVals =
(byte[])DynamicInvoker.invokeMethod(
_saslClient,
mechanismName, "evaluateChallenge",
args, argNames);
}
// Make sure authentication REALLY is complete
Boolean bool =
(Boolean)DynamicInvoker.invokeMethod(
_saslClient,
mechanismName, "isComplete", null, null);
if (!bool.booleanValue()) {
// Authentication session hijacked!
throw new LDAPException("The server indicates that " +
"authentication is successful" +
", but the SASL driver " +
"indicates that authentication" +
" is not yet done.",
LDAPException.OTHER);
}
Object[] args = {ldc.getInputStream()};
String[] argNames = {"java.io.InputStream"};
InputStream is =
(InputStream)DynamicInvoker.invokeMethod(
_saslClient,
mechanismName, "getInputStream", args, argNames);
ldc.setInputStream(is);
args[0] = ldc.getOutputStream();
argNames[0] = "java.io.OutputStream";
OutputStream os =
(OutputStream)DynamicInvoker.invokeMethod(
_saslClient,
mechanismName, "getOutputStream", args, argNames);
ldc.setOutputStream(os);
ldc.updateThreadConnTable();
} catch (LDAPException e) {
throw e;
} catch (Exception e) {
throw new LDAPException(e.toString(), LDAPException.OTHER);
}
}
}
boolean isExternalMechanism(String name) {
return name.equalsIgnoreCase( LDAPConnection.EXTERNAL_MECHANISM );
}
private boolean checkForSASLBindCompletion(int resultCode)
throws LDAPException{
if (resultCode == LDAPException.SUCCESS) {
return true;
} else if (resultCode == LDAPException.SASL_BIND_IN_PROGRESS) {
return false;
} else {
throw new LDAPException("Authentication failed", resultCode);
}
}
private JDAPBindResponse saslBind(LDAPConnection ldc,
String mechanismName,
byte[] credentials)
throws LDAPException {
LDAPResponseListener myListener = ldc.getResponseListener ();
try {
ldc.sendRequest(new JDAPBindRequest(3,
_dn,
mechanismName,
credentials),
myListener, ldc.getConstraints());
LDAPMessage response = myListener.getResponse();
JDAPProtocolOp protocolOp = response.getProtocolOp();
if (protocolOp instanceof JDAPBindResponse) {
return (JDAPBindResponse)protocolOp;
} else {
throw new LDAPException("Unknown response from the " +
"server during SASL bind",
LDAPException.OTHER);
}
} finally {
ldc.releaseResponseListener(myListener);
}
}
private static final String CALLBACK_HANDLER =
"javax.security.auth.callback.CallbackHandler";
private static final String CLIENTPKGS =
"javax.security.sasl.client.pkgs";
private String _dn;
private String[] _mechanisms;
private String _packageName;
private Hashtable _props;
private CallbackHandler _cbh;
private Object _saslClient = null;
}

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
@ -77,15 +77,19 @@ import java.util.*;
* LDAPAttributeSchema attrType = dirSchema.getAttribute(
* "userpassword" );
* if ( attrType != null ) {
* System.out.println("userPassword := "+attrType.toString());
* System.out.println("userPassword := " + attrType.toString());
* }
*
* // Add a new object class.
* // Create a new object class definition.
* String[] requiredAttrs = {"cn", "mail"};
* String[] optionalAttrs = {"sn", "phoneNumber"};
* LDAPObjectClassSchema newObjClass = new LDAPObjectClassSchema(
* "newInetOrgPerson", "1.2.3.4.5.6.7", "top", "Experiment",
* requiredAttrs, optionalAttrs );
* LDAPObjectClassSchema newObjClass =
* new LDAPObjectClassSchema( "newInetOrgPerson",
* "1.2.3.4.5.6.7",
* "top",
* "Experiment",
* requiredAttrs,
* optionalAttrs );
*
* // Authenticate as root DN to get permissions to edit the schema.
* ld.authenticate( ROOT_DN, ROOT_PASSWORD );
@ -94,9 +98,14 @@ import java.util.*;
* newObjClass.add( ld );
*
* // Create a new attribute type "hairColor".
* LDAPAttributeSchema newAttrType = new LDAPAttributeSchema(
* "hairColor", "1.2.3.4.5.4.3.2.1", "Blonde, red, etc",
* LDAPAttributeSchema.cis, false );
* LDAPAttributeSchema newAttrType =
* new LDAPAttributeSchema( "hairColor",
* "1.2.3.4.5.4.3.2.1",
* "Blonde, red, etc",
* LDAPAttributeSchema.cis,
* false );
* // Add a custom qualifier
* newObjClass.setQualifier( "X-OWNER", "John Jacobson" );
*
* // Add the new attribute type to the schema.
* newAttrType.add( ld );
@ -106,13 +115,15 @@ import java.util.*;
*
* // Get and print the new attribute type.
* newAttrType = dirSchema.getAttribute( "hairColor" );
* if ( newAttrType != null )
* System.out.println("hairColor := "+newAttrType.toString());
* if ( newAttrType != null ) {
* System.out.println("hairColor := " + newAttrType.toString());
* }
*
* // Get and print the new object class.
* newObjClass = dirSchema.getObjectClass( "newInetOrgPerson" );
* if ( newObjClass != null )
* System.out.println("newInetOrgPerson := "+newObjClass.toString());
* if ( newObjClass != null ) {
* System.out.println("newInetOrgPerson := " +newObjClass.toString());
* }
*
* ld.disconnect();
*
@ -194,7 +205,7 @@ public class LDAPSchema {
* @see netscape.ldap.LDAPSchemaElement#add
* @see netscape.ldap.LDAPSchemaElement#remove
*/
public void addObjectClass( LDAPObjectClassSchema objectSchema ) {
protected void addObjectClass( LDAPObjectClassSchema objectSchema ) {
objectClasses.put( objectSchema.getName().toLowerCase(),
objectSchema );
}
@ -225,7 +236,7 @@ public class LDAPSchema {
* @see netscape.ldap.LDAPSchemaElement#add
* @see netscape.ldap.LDAPSchemaElement#remove
*/
public void addAttribute( LDAPAttributeSchema attrSchema ) {
protected void addAttribute( LDAPAttributeSchema attrSchema ) {
attributes.put( attrSchema.getName().toLowerCase(), attrSchema );
}
@ -255,7 +266,7 @@ public class LDAPSchema {
* @see netscape.ldap.LDAPSchemaElement#add
* @see netscape.ldap.LDAPSchemaElement#remove
*/
public void addMatchingRule( LDAPMatchingRuleSchema matchSchema ) {
protected void addMatchingRule( LDAPMatchingRuleSchema matchSchema ) {
matchingRules.put( matchSchema.getName().toLowerCase(), matchSchema );
}
@ -338,29 +349,21 @@ public class LDAPSchema {
}
/**
* Retrieve the entire schema from a Directory Server.
* Retrieve the schema for a specific entry.
* @param ld An active connection to a Directory Server.
* @param dn The entry for which to fetch schema.
* @exception LDAPException on failure.
*/
public void fetchSchema( LDAPConnection ld ) throws LDAPException {
if ( (ld == null) || !ld.isConnected() ) {
throw new LDAPException( "No connection", LDAPException.OTHER );
}
LDAPEntry entry = ld.read( "" );
if ( entry == null )
throw new LDAPException( "", LDAPException.NO_SUCH_OBJECT );
LDAPAttribute attr = entry.getAttribute( "subschemasubentry" );
entryName = "cn=schema";
public void fetchSchema( LDAPConnection ld, String dn )
throws LDAPException {
/* Find the subschemasubentry value for this DN */
String entryName = getSchemaDN( ld, dn );
Enumeration en;
if ( attr != null ) {
en = attr.getStringValues();
if ( en.hasMoreElements() )
entryName = (String)en.nextElement();
}
/* Get the entire schema definition entry */
entry = readSchema( ld, entryName );
LDAPEntry entry = readSchema( ld, entryName );
/* Get all object class definitions */
attr = entry.getAttribute( "objectclasses" );
LDAPAttribute attr = entry.getAttribute( "objectclasses" );
if ( attr != null ) {
en = attr.getStringValues();
while( en.hasMoreElements() ) {
@ -410,6 +413,51 @@ public class LDAPSchema {
}
}
/**
* Retrieve the entire schema from the root of a Directory Server.
* @param ld An active connection to a Directory Server.
* @exception LDAPException on failure.
*/
public void fetchSchema( LDAPConnection ld ) throws LDAPException {
fetchSchema( ld, "" );
}
/**
* Read one attribute definition from a server to determine if
* attribute syntaxes are quoted (a bug, present in Netscape
* and Novell servers).
* @param ld An active connection to a Directory Server.
* @return <CODE>true</CODE> if standards-compliant
* @exception LDAPException on failure.
*/
static boolean isAttributeSyntaxStandardsCompliant( LDAPConnection ld )
throws LDAPException {
/* Check if this has already been investigated */
String schemaBug = (String)ld.getProperty( ld.SCHEMA_BUG_PROPERTY );
if ( schemaBug != null ) {
return schemaBug.equalsIgnoreCase( "standard" );
}
boolean compliant = true;
/* Get the schema definitions for attributes */
String entryName = getSchemaDN( ld, "" );
String[] attrs = { "attributetypes" };
LDAPEntry entry = readSchema( ld, entryName, attrs );
/* Get all attribute definitions, and check the first one */
LDAPAttribute attr = entry.getAttribute( "attributetypes" );
if ( attr != null ) {
Enumeration en = attr.getStringValues();
if( en.hasMoreElements() ) {
compliant = !LDAPAttributeSchema.isSyntaxQuoted(
(String)en.nextElement() );
}
}
ld.setProperty( ld.SCHEMA_BUG_PROPERTY, compliant ? "standard" :
"NetscapeBug" );
return compliant;
}
/**
* Displays the schema (including the descriptions of its object
* classes, attribute types, and matching rules) in an easily
@ -418,34 +466,72 @@ public class LDAPSchema {
* @return A string containing the schema in printable format.
*/
public String toString() {
String s = "Object classes: ";
String s = "Object classes:\n";
Enumeration en = getObjectClasses();
while( en.hasMoreElements() ) {
s += (String)en.nextElement();
s += ' ';
s += en.nextElement().toString();
s += '\n';
}
s += "Attributes: ";
s += "Attributes:\n";
en = getAttributes();
while( en.hasMoreElements() ) {
s += (String)en.nextElement();
s += ' ';
s += en.nextElement().toString();
s += '\n';
}
s += "Matching rules: ";
s += "Matching rules:\n";
en = getMatchingRules();
while( en.hasMoreElements() ) {
s += (String)en.nextElement();
s += ' ';
s += en.nextElement().toString();
s += '\n';
}
return s;
}
private LDAPEntry readSchema( LDAPConnection ld, String dn ) throws LDAPException {
/**
* Retrieve the DN of the schema definitions for a specific entry.
* @param ld An active connection to a Directory Server.
* @param dn The entry for which to fetch schema.
* @exception LDAPException on failure.
*/
static String getSchemaDN( LDAPConnection ld, String dn )
throws LDAPException {
if ( (ld == null) || !ld.isConnected() ) {
throw new LDAPException( "No connection", LDAPException.OTHER );
}
String[] attrs = { "subschemasubentry" };
LDAPEntry entry = readSchema( ld, dn, attrs );
if ( entry == null ) {
throw new LDAPException( "", LDAPException.NO_SUCH_OBJECT );
}
LDAPAttribute attr = entry.getAttribute( attrs[0] );
String entryName = "cn=schema";
if ( attr != null ) {
Enumeration en = attr.getStringValues();
if ( en.hasMoreElements() ) {
entryName = (String)en.nextElement();
}
}
return entryName;
}
private static LDAPEntry readSchema( LDAPConnection ld, String dn,
String[] attrs )
throws LDAPException {
LDAPSearchResults results = ld.search (dn, ld.SCOPE_BASE,
"objectclass=subschema",
null, false);
attrs, false);
if ( !results.hasMoreElements() ) {
throw new LDAPException( "Cannot read schema",
LDAPException.INSUFFICIENT_ACCESS_RIGHTS );
}
return results.next ();
}
private static LDAPEntry readSchema( LDAPConnection ld, String dn )
throws LDAPException {
return readSchema( ld, dn, null );
}
/**
* Helper for "main" to print out schema elements.
* @param en Enumeration of schema elements.
@ -454,6 +540,7 @@ public class LDAPSchema {
while( en.hasMoreElements() ) {
LDAPSchemaElement s = (LDAPSchemaElement)en.nextElement();
System.out.println( " " + s );
// System.out.println( " " + s.getValue() );
}
}
@ -499,5 +586,4 @@ public class LDAPSchema {
private Hashtable objectClasses = new Hashtable();
private Hashtable attributes = new Hashtable();
private Hashtable matchingRules = new Hashtable();
String entryName = null;
}

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
@ -41,9 +41,19 @@ import java.util.*;
* <LI>a name identifying the element
* <LI>an OID identifying the element
* <LI>a description of the element
* <LI>a qualifier "OBSOLETE"
* </UL>
* <P>
*
* In addition, there are optional standard qualifiers for attribute
* types (see LDAPAttributeSchema), and implementation-specific
* qualifiers may be added. Non-standard qualifiers must have names
* starting with X-, e.g. "X-OWNER 'John Jacobson'". Optional and
* non-standard qualifiers can be accessed with <CODE>getQualifier</CODE> and
* <CODE>setQualifier</CODE>, and enumerated with
* <CODE>getQualifierNames</CODE>.
* <P>
*
* The <CODE>LDAPSchemaElement</CODE> class implements methods that
* you can use with different types of schema elements (object class
* definitions, attribute type definitions, and matching rule definitions).
@ -120,11 +130,12 @@ public abstract class LDAPSchemaElement {
* @param atrr Attribute in the schema entry to modify.
* @exception LDAPException if the definition can't be added/removed.
*/
protected void update( LDAPConnection ld, int op, LDAPAttribute attr )
throws LDAPException {
protected void update( LDAPConnection ld, int op, LDAPAttribute attr,
String dn )
throws LDAPException {
LDAPAttribute[] attrs = new LDAPAttribute[1];
attrs[0] = attr;
update( ld, op, attrs );
update( ld, op, attrs, dn );
}
/**
@ -135,13 +146,15 @@ public abstract class LDAPSchemaElement {
* @param attrs Attributes in the schema entry to modify.
* @exception LDAPException if the definition can't be added/removed.
*/
protected void update( LDAPConnection ld, int op, LDAPAttribute[] attrs )
throws LDAPException {
protected void update( LDAPConnection ld, int op, LDAPAttribute[] attrs,
String dn )
throws LDAPException {
LDAPModificationSet mods = new LDAPModificationSet();
for( int i = 0; i < attrs.length; i++ ) {
mods.add( op, attrs[i] );
}
ld.modify( "cn=schema", mods );
String entryName = LDAPSchema.getSchemaDN( ld, dn );
ld.modify( entryName, mods );
}
/**
@ -152,11 +165,14 @@ public abstract class LDAPSchemaElement {
* @param name Name of attribute in the schema entry to modify.
* @exception LDAPException if the definition can't be added/removed.
*/
protected void update( LDAPConnection ld, int op, String name )
throws LDAPException {
protected void update( LDAPConnection ld, int op, String name,
String dn )
throws LDAPException {
boolean quotingBug =
!LDAPSchema.isAttributeSyntaxStandardsCompliant( ld );
LDAPAttribute attr = new LDAPAttribute( name,
getValue() );
update( ld, op, attr );
getValue( quotingBug ) );
update( ld, op, attr, dn );
}
/**
@ -166,11 +182,26 @@ public abstract class LDAPSchemaElement {
* edit the schema.
* @param ld The <CODE>LDAPConnection</CODE> object representing
* a connection to an LDAP server.
* @param dn The entry at which to add the schema definition.
* @exception LDAPException The specified definition cannot be
* added to the schema.
*/
public void add( LDAPConnection ld, String dn ) throws LDAPException {
update( ld, LDAPModification.ADD, attrName, dn );
}
/**
* Adds the current object class, attribute type, or matching rule
* definition to the schema at the root DSE. Typically, most servers
* will require you to authenticate before allowing you to
* edit the schema.
* @param ld The <CODE>LDAPConnection</CODE> object representing
* a connection to an LDAP server.
* @exception LDAPException The specified definition cannot be
* added to the schema.
*/
public void add( LDAPConnection ld ) throws LDAPException {
update( ld, LDAPModification.ADD, attrName );
add( ld, "" );
}
/**
@ -181,17 +212,40 @@ public abstract class LDAPSchemaElement {
* @param ld The <CODE>LDAPConnection</CODE> object representing
* a connection to an LDAP server.
* @param newValue The new value
* @param dn The entry at which to modify the schema definition.
* @exception LDAPException The specified definition cannot be
* modified.
*/
public void modify( LDAPConnection ld, LDAPSchemaElement newValue,
String dn )
throws LDAPException {
boolean quotingBug =
!LDAPSchema.isAttributeSyntaxStandardsCompliant( ld );
LDAPModificationSet mods = new LDAPModificationSet();
mods.add( LDAPModification.DELETE,
new LDAPAttribute( attrName, getValue( quotingBug ) ) );
mods.add( LDAPModification.ADD,
new LDAPAttribute( attrName,
newValue.getValue( quotingBug ) ) );
String entryName = LDAPSchema.getSchemaDN( ld, dn );
ld.modify( entryName, mods );
}
/**
* Replace a single value of the object class, attribute type,
* or matching rule definition in the schema at the root DSE.
* Typically, most servers
* will require you to authenticate before allowing you to
* edit the schema.
* @param ld The <CODE>LDAPConnection</CODE> object representing
* a connection to an LDAP server.
* @param newValue The new value
* @exception LDAPException The specified definition cannot be
* modified.
*/
public void modify( LDAPConnection ld, LDAPSchemaElement newValue )
throws LDAPException {
LDAPModificationSet mods = new LDAPModificationSet();
mods.add( LDAPModification.DELETE,
new LDAPAttribute( attrName, getValue() ) );
mods.add( LDAPModification.ADD,
new LDAPAttribute( attrName, newValue.getValue() ) );
ld.modify( "cn=schema", mods );
modify( ld, newValue, "" );
}
/**
@ -201,22 +255,388 @@ public abstract class LDAPSchemaElement {
* edit the schema.
* @param ld The <CODE>LDAPConnection</CODE> object representing
* a connection to an LDAP server.
* @param dn The entry at which to remove the schema definition.
* @exception LDAPException The specified definition cannot be
* removed from the schema.
*/
public void remove( LDAPConnection ld, String dn ) throws LDAPException {
update( ld, LDAPModification.DELETE, attrName, dn );
}
/**
* Removes the current object class, attribute type, or matching rule
* definition from the schema at the root DSE. Typically, most servers
* will require you to authenticate before allowing you to
* edit the schema.
* @param ld The <CODE>LDAPConnection</CODE> object representing
* a connection to an LDAP server.
* @exception LDAPException The specified definition cannot be
* removed from the schema.
*/
public void remove( LDAPConnection ld ) throws LDAPException {
update( ld, LDAPModification.DELETE, attrName );
remove( ld, "" );
}
/**
* Gets the definition of the current object class, attribute type, or
* matching rule in a format expected by the server when adding the
* definition to the directory. This must be overridden by derived classes.
* @return A String that can be used as a value of the element
* in the schema of a Directory.
* Report if the element is marked as obsolete.
* @return <CODE>true<CODE> if the element is defined as obsolete.
*/
public abstract String getValue();
public boolean isObsolete() {
return obsolete;
}
/**
* Parse a raw schema value into OID, name, description, and
* a Hashtable of other qualifiers and values
*
* @param raw A raw schema definition
*/
protected void parseValue( String raw ) {
if ( properties == null ) {
properties = new Hashtable();
}
int l = raw.length();
// Processing is faster in char array than in String
char[] ch = new char[l];
raw.getChars( 0, l, ch, 0 );
// Trim leading and trailing space
l--;
while( ch[l] == ' ' ) {
l--;
}
int start = 0;
while( ch[start] == ' ' ) {
start++;
}
// Skip past "( " and ")" to start of OID
start += 2;
// Find end of OID
int ind = start + 1;
while( ch[ind] != ' ' ) {
ind++;
}
oid = new String( ch, start, ind - start );
ind = ind + 1;
String s;
String val;
while ( ind < l ) {
// Skip past blanks to start of next token
while( ch[ind] == ' ' ) {
ind++;
}
// Find end of token
int last = ind + 1;
while( (last < l) && (ch[last] != ' ') )
last++;
if ( last < l ) {
// Found a token
s = new String( ch, ind, last-ind );
ind = last;
if ( novalsTable.containsKey( s ) ) {
properties.put( s, "" );
continue;
}
} else {
// Reached end of string with no end of token
s = "";
ind = l;
break;
}
// Find the start of the value of the token
while( (ind < l) && (ch[ind] == ' ') ) {
ind++;
}
last = ind + 1;
if ( ind >= l ) {
break;
}
boolean quoted = false;
boolean list = false;
if ( ch[ind] == '\'' ) {
// The value is quoted
quoted = true;
ind++;
while( (last < l) && (ch[last] != '\'') ) {
last++;
}
} else if ( ch[ind] == '(' ) {
// The value is a list
list = true;
ind++;
while( (last < l) && (ch[last] != ')') ) {
last++;
}
} else {
// The value is not quoted
while( (last < l) && (ch[last] != ' ') ) {
last++;
}
}
if ( (ind < last) && (last < l) ) {
if ( list ) {
Vector v = new Vector();
val = new String( ch, ind+1, last-ind-1 );
StringTokenizer st = new StringTokenizer( val, " " );
while ( st.hasMoreTokens() ) {
String tok = st.nextToken();
if ( !tok.equals( "$" ) ) {
// Remove quotes, if any
if ( tok.charAt( 0 ) == '\'' ) {
tok = tok.substring( 1, tok.length()-1 );
}
v.addElement( tok );
}
}
properties.put( s, v );
} else {
val = new String( ch, ind, last-ind );
if ( s.equals( "NAME" ) ) {
name = val;
} else if ( s.equals( "DESC" ) ) {
description = val;
} else {
properties.put( s, val );
}
if ( quoted ) {
last++;
}
}
}
ind = last + 1;
}
}
/**
* Format a String in the format defined in X.501 (see
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
* >RFC 2252, Lightweight Directory Access Protocol
* (v3): Attribute Syntax Definitions</A>
* for a description of this format).
* This is the format that LDAP servers and clients use to exchange
* schema information. For example, when
* you search an LDAP server for its schema, the server returns an entry
* with the attributes "objectclasses" and "attributetypes". The
* values of the "attributetypes" attribute are attribute type
* descriptions in this format.
* <P>
* @param quotingBug <CODE>true</CODE> if single quotes are to be
* supplied around the SYNTAX and SUP value
* @return A formatted String for defining a schema element
*/
public String getValue() {
return getValue( false );
}
abstract String getValue( boolean quotingBug );
/**
* Prepare the initial common part of a schema element value in
* RFC 2252 format for submitting to a server
*
* @return The OID, name, description, and possibly OBSOLETE
* fields of a schema element definition
*/
String getValuePrefix() {
String s = "( " + oid + " NAME \'" + name + "\' DESC \'" +
description + "\' ";
if ( isObsolete() ) {
s += OBSOLETE + ' ';
}
return s;
}
/**
* Get qualifiers which may or may not be present
*
* @param names List of qualifiers to look up
* @return String in RFC 2252 format containing any values
* found, not terminated with ' '
*/
protected String getOptionalValues( String[] names ) {
String s = "";
for( int i = 0; i < names.length; i++ ) {
String[] vals = getQualifier( names[i] );
if ( (vals != null) && (vals.length > 0) ) {
s += names[i] + ' ' + vals[0];
}
}
return s;
}
/**
* Get any qualifiers marked as custom
*
* @return String in RFC 2252 format, without a terminating
* ' '
*/
protected String getCustomValues() {
String s = "";
Enumeration en = properties.keys();
while( en.hasMoreElements() ) {
String key = (String)en.nextElement();
if ( !key.startsWith( "X-" ) ) {
continue;
}
s += getValue( key, true );
}
return s;
}
/**
* Get a qualifier's value or values, if present, and format
* the String according to RFC 2252
*
* @return String in RFC 2252 format, without a terminating
* ' '
*/
String getValue( String key, boolean doQuote ) {
String s = "";
Object o = properties.get( key );
if ( o == null ) {
return s;
}
if ( o instanceof String ) {
if ( ((String)o).length() > 0 ) {
s += key + ' ';
if ( doQuote ) {
s += '\'';
}
s += (String)o;
if ( doQuote ) {
s += '\'';
}
}
} else {
s += key + " ( ";
Vector v = (Vector)o;
for( int i = 0; i < v.size(); i++ ) {
if ( doQuote ) {
s += '\'';
}
s += (String)v.elementAt(i);
if ( doQuote ) {
s += '\'';
}
s += ' ';
if ( i < (v.size() - 1) ) {
s += "$ ";
}
}
s += ')';
}
return s;
}
/**
* Keep track of qualifiers which are not predefined.
* @param name Name of qualifier
* @param value Value of qualifier. "" for no value
*/
public void setQualifier( String name, String value ) {
if ( properties == null ) {
properties = new Hashtable();
}
if ( value != null ) {
properties.put( name, value );
} else {
properties.remove( name );
}
}
/**
* Keep track of qualifiers which are not predefined.
* @param name Name of qualifier
* @param values Array of values
*/
public void setQualifier( String name, String[] values ) {
if ( values == null ) {
return;
}
if ( properties == null ) {
properties = new Hashtable();
}
Vector v = new Vector();
for( int i = 0; i < v.size(); i++ ) {
v.addElement( values[i] );
}
properties.put( name, v );
}
/**
* Get the value of a qualifier which is not predefined.
* @param name Name of qualifier
* @return Value or values of qualifier. <CODE>null</CODE> if not
* present, a zero-length array if present but with no value
*/
public String[] getQualifier( String name ) {
if ( properties == null ) {
return null;
}
Object o = properties.get( name );
if ( o == null ) {
return null;
}
if ( o instanceof Vector ) {
Vector v = (Vector)o;
String[] vals = new String[v.size()];
v.copyInto( vals );
return vals;
}
String s = (String)o;
if ( s.length() < 1 ) {
return new String[0];
} else {
return new String[] { s };
}
}
/**
* Get an enumeration of all qualifiers which are not predefined.
* @return Enumeration of qualifiers.
*/
public Enumeration getQualifierNames() {
return properties.keys();
}
/**
* Create a string for use in toString with any qualifiers of the element.
*
* @param ignore Any qualifiers to NOT include
* @return A String with any known qualifiers
*/
String getQualifierString( String[] ignore ) {
Hashtable toIgnore = null;
if ( ignore != null ) {
toIgnore = new Hashtable();
for( int i = 0; i < ignore.length; i++ ) {
toIgnore.put( ignore[i], ignore[i] );
}
}
String s = "";
Enumeration en = getQualifierNames();
while( en.hasMoreElements() ) {
String qualifier = (String)en.nextElement();
if ( (toIgnore != null) && toIgnore.containsKey( qualifier ) ) {
continue;
}
s += "; " + qualifier;
String[] vals = getQualifier( qualifier );
if ( vals == null ) {
s += ' ';
continue;
}
s += ": ";
for( int i = 0; i < vals.length; i++ ) {
s += vals[i] + ' ';
}
}
return s;
}
// Constants for known syntax types
public static final int unknown = 0;
public static final int cis = 1;
public static final int binary = 2;
@ -237,8 +657,19 @@ public abstract class LDAPSchemaElement {
"1.3.6.1.4.1.1466.115.121.1.27";
protected static final String dnString =
"1.3.6.1.4.1.1466.115.121.1.12";
protected String oid = "";
// Predefined qualifiers which apply to any schema element type
public static final String OBSOLETE = "OBSOLETE";
public static final String SUPERIOR = "SUP";
// Properties which are common to all schema elements
protected String oid = null;
protected String name = "";
protected String description = "";
protected String attrName = null;
protected boolean obsolete = false;
protected String rawValue = null;
// Additional qualifiers
protected Hashtable properties = null;
// Qualifiers known to not have values
static protected Hashtable novalsTable = new Hashtable();
}

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
@ -27,18 +27,13 @@ package netscape.ldap;
*
* @version 1.0
*/
public class LDAPSearchConstraints implements Cloneable {
public class LDAPSearchConstraints extends LDAPConstraints
implements Cloneable {
private int timeLimit;
private int serverTimeLimit;
private int deref;
private int maxRes;
private boolean referrals;
private int batch;
private LDAPRebind m_rebind_proc;
private int m_hop_limit;
private LDAPControl[] m_clientControls;
private LDAPControl[] m_serverControls;
private int serverTimeLimit;
transient private int m_maxBacklog = 100;
/**
@ -46,16 +41,11 @@ public class LDAPSearchConstraints implements Cloneable {
* the default set of search constraints.
*/
public LDAPSearchConstraints() {
timeLimit = 0;
serverTimeLimit = 0;
super();
deref = 0;
maxRes = 1000;
referrals = false;
batch = 1;
m_rebind_proc = null;
m_hop_limit = 10;
m_clientControls = null;
m_serverControls = null;
serverTimeLimit = 0;
}
/**
@ -79,7 +69,7 @@ public class LDAPSearchConstraints implements Cloneable {
* (1 by default)
* @param rebind_proc Specifies the object of the class that
* implements the <CODE>LDAPRebind</CODE> interface (you need to
* define this class). The object will be using when the client
* define this class). The object will be used when the client
* follows referrals automatically. The object provides the client
* with a method for getting the distinguished name and password
* used to authenticate to another LDAP server during a referral.
@ -93,15 +83,10 @@ public class LDAPSearchConstraints implements Cloneable {
public LDAPSearchConstraints( int msLimit, int dereference,
int maxResults, boolean doReferrals, int batchSize,
LDAPRebind rebind_proc, int hop_limit) {
timeLimit = msLimit;
super(msLimit, doReferrals, rebind_proc, hop_limit);
deref = dereference;
maxRes = maxResults;
referrals = doReferrals;
batch = batchSize;
m_rebind_proc = rebind_proc;
m_hop_limit = hop_limit;
m_clientControls = null;
m_serverControls = null;
}
/**
@ -125,9 +110,9 @@ public class LDAPSearchConstraints implements Cloneable {
* a referral (<CODE>False</CODE> by default)
* @param batchSize Specify the number of results to return at a time
* (1 by default)
* @param rebind_proc Specifies the object of the class that
* implements the <CODE>LDAPRebind</CODE> interface (you need to
* define this class). The object will be using when the client
* @param rebind_proc Specifies the object that
* implements the <CODE>LDAPRebind</CODE> interface.
* The object will be used when the client
* follows referrals automatically. The object provides the client
* with a method for getting the distinguished name and password
* used to authenticate to another LDAP server during a referral.
@ -144,26 +129,56 @@ public class LDAPSearchConstraints implements Cloneable {
int batchSize,
LDAPRebind rebind_proc,
int hop_limit) {
timeLimit = msLimit;
super(msLimit, doReferrals, rebind_proc, hop_limit);
serverTimeLimit = timeLimit;
deref = dereference;
maxRes = maxResults;
referrals = doReferrals;
batch = batchSize;
m_rebind_proc = rebind_proc;
m_hop_limit = hop_limit;
m_clientControls = null;
m_serverControls = null;
}
/**
* Returns the maximum number of milliseconds to wait for any operation
* under these search constraints. If 0, there is no maximum time limit
* on waiting for the operation results.
* @return Maximum number of milliseconds to wait for operation results.
* Constructs a new <CODE>LDAPSearchConstraints</CODE> object and allows you
* to specify the search constraints in that object.
* <P>
* @param msLimit Maximum time in milliseconds to wait for results (0
* by default, which means that there is no maximum time limit)
* @param timeLimit Maximum time in seconds for the server to spend
* processing a search request (0 by default for no limit)
* @param dereference Either <CODE>LDAPv2.DEREF_NEVER</CODE>,
* <CODE>LDAPv2.DEREF_FINDING</CODE>,
* <CODE>LDAPv2.DEREF_SEARCHING</CODE>, or
* <CODE>LDAPv2.DEREF_ALWAYS</CODE> (see LDAPConnection.setOption).
* <CODE>LDAPv2.DEREF_NEVER</CODE> is the default.
* @param maxResults Maximum number of search results to return
* (1000 by default)
* @param doReferrals Specify <CODE>true</CODE> to follow referrals
* automatically, or <CODE>False</CODE> to throw an
* <CODE>LDAPReferralException</CODE> error if the server sends back
* a referral (<CODE>False</CODE> by default)
* @param batchSize Specify the number of results to return at a time
* (1 by default)
* @param bind_proc Specifies the object that
* implements the <CODE>LDAPBind</CODE> interface (you need to
* define this class). The object will be used to authenticate
* to the server on referrals.
* (This field is <CODE>null</CODE> by default.)
* @param hop_limit Maximum number of referrals to follow in a
* sequence when attempting to resolve a request.
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl, netscape.ldap.LDAPSearchConstraints)
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
*/
public int getTimeLimit() {
return timeLimit;
public LDAPSearchConstraints( int msLimit, int timeLimit,
int dereference,
int maxResults, boolean doReferrals,
int batchSize,
LDAPBind bind_proc,
int hop_limit) {
super(msLimit, doReferrals, bind_proc, hop_limit);
serverTimeLimit = timeLimit;
deref = dereference;
maxRes = maxResults;
batch = batchSize;
}
/**
@ -200,17 +215,6 @@ public class LDAPSearchConstraints implements Cloneable {
return maxRes;
}
/**
* Specifies whether nor not referrals are followed automatically.
* Returns <CODE>true</CODE> if referrals are to be followed automatically,
* or <CODE>false</CODE> if referrals throw an <CODE>LDAPReferralException</CODE>.
* @return <CODE>true</CODE> if referrals are followed automatically, <CODE>False</CODE>
* if referrals throw an <CODE>LDAPReferralException</CODE>.
*/
public boolean getReferrals() {
return referrals;
}
/**
* Returns the suggested number of results to return at a time during
* search. This should be 0 if intermediate results are not needed, and
@ -221,63 +225,6 @@ public class LDAPSearchConstraints implements Cloneable {
return batch;
}
/**
* Returns the object that provides the method for getting
* authentication information. This object must belong to a class
* that implements the <CODE>LDAPRebind</CODE> interface.
* @return Object to be used to obtain information for
* authenticating to other LDAP servers during referrals.
* @see netscape.ldap.LDAPRebind
* @see netscape.ldap.LDAPRebindAuth
*/
public LDAPRebind getRebindProc() {
return m_rebind_proc;
}
/**
* Returns the maximum number of hops to follow during a referral.
* @return Maximum number of hops to follow during a referral.
*/
public int getHopLimit() {
return m_hop_limit;
}
/**
* Returns any client controls to be applied by the client
* to LDAP operations.
* @return Client controls to be applied by the client to LDAP operations.
* @see netscape.ldap.LDAPControl
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public LDAPControl[] getClientControls() {
return m_clientControls;
}
/**
* Returns any server controls to be applied by the server
* to LDAP operations.
* @return Server controls to be applied by the server to LDAP operations.
* @see netscape.ldap.LDAPControl
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public LDAPControl[] getServerControls() {
return m_serverControls;
}
/**
* Sets the maximum number of milliseconds to wait for any operation
* under these search constraints. If 0, there is no maximum time limit
* on waiting for the operation results.
* @param msLimit Maximum number of milliseconds to wait for operation
* results.
* (0 by default, which means that there is no maximum time limit.)
*/
public void setTimeLimit( int msLimit ) {
timeLimit = msLimit;
}
/**
* Sets the maximum number of seconds for the server to spend
* returning search results. If 0, there is no time limit.
@ -313,26 +260,6 @@ public class LDAPSearchConstraints implements Cloneable {
maxRes = maxResults;
}
/**
* Specifies whether nor not referrals are followed automatically.
* Returns <CODE>true</CODE> if referrals are to be followed automatically,
* or <CODE>false</CODE> if referrals throw an <CODE>LDAPReferralException</CODE>.
* (By default, this is set to <CODE>false</CODE>.)
* <P>
* If you set this to <CODE>true</CODE>, you need to define a class that implements
* the <CODE>LDAPRebind</CODE> interface. You need to create an object of this class
* and pass the object to the <CODE>setRebindProc</CODE> method. This identifies the method
* for retrieving authentication information, which is used when connecting to other LDAP
* servers during referrals.
* @param doReferrals Set to <CODE>true</CODE> if referrals should be followed automatically,
* or <CODE>False</CODE> if referrals should throw an <CODE>LDAPReferralException</CODE>.
* @see netscape.ldap.LDAPRebind
* @see netscape.ldap.LDAPRebindAuth
*/
public void setReferrals( boolean doReferrals ) {
referrals = doReferrals;
}
/**
* Sets the suggested number of results to return at a time during search.
* This should be 0 if intermediate results are not needed, and 1 if
@ -343,69 +270,11 @@ public class LDAPSearchConstraints implements Cloneable {
batch = batchSize;
}
/**
* Specifies the object that provides the method for getting
* authentication information. This object must belong to a class
* that implements the <CODE>LDAPRebind</CODE> interface.
* (By default, this is <CODE>null</CODE>.)
* @param rebind_proc Object to be used to obtain information for
* authenticating to other LDAP servers during referrals.
*/
public void setRebindProc( LDAPRebind rebind_proc ) {
m_rebind_proc = rebind_proc;
}
/**
* Sets maximum number of hops to follow in sequence during a referral.
* (By default, this is 10.)
* @param hop_limit Maximum number of hops to follow during a referral.
*/
public void setHopLimit( int hop_limit ) {
m_hop_limit = hop_limit;
}
/**
* Sets a client control for LDAP operations.
* @param control Client control for LDAP operations.
* @see netscape.ldap.LDAPControl
*/
public void setClientControls( LDAPControl control ) {
m_clientControls = new LDAPControl[1];
m_clientControls[0] = control;
}
/**
* Sets an array of client controls for LDAP operations.
* @param controls Array of client controls for LDAP operations.
* @see netscape.ldap.LDAPControl
*/
public void setClientControls( LDAPControl[] controls ) {
m_clientControls = controls;
}
/**
* Sets a server control for LDAP operations.
* @param control Server control for LDAP operations.
* @see netscape.ldap.LDAPControl
*/
public void setServerControls( LDAPControl control ) {
m_serverControls = new LDAPControl[1];
m_serverControls[0] = control;
}
/**
* Sets an array of server controls for LDAP operations.
* @param controls An array of server controls for LDAP operations.
* @see netscape.ldap.LDAPControl
*/
public void setServerControls( LDAPControl[] controls ) {
m_serverControls = controls;
}
/**
* Set the maximum number of unread entries any search listener can
* have before we stop reading from the server.
* @param backlog The maximum number of unread entries per listener
* @deprecated Use <CODE>LDAPConnection.getOption()</CODE>
*/
public void setMaxBacklog( int backlog ) {
m_maxBacklog = backlog;
@ -415,6 +284,7 @@ public class LDAPSearchConstraints implements Cloneable {
* Get the maximum number of unread entries any search listener can
* have before we stop reading from the server.
* @return The maximum number of unread entries per listener
* @deprecated Use <CODE>LDAPConnection.setOption()</CODE>
*/
public int getMaxBacklog() {
return m_maxBacklog;
@ -427,24 +297,43 @@ public class LDAPSearchConstraints implements Cloneable {
public Object clone() {
LDAPSearchConstraints o = new LDAPSearchConstraints();
o.timeLimit = this.timeLimit;
o.serverTimeLimit = this.serverTimeLimit;
o.deref = this.deref;
o.maxRes = this.maxRes;
o.referrals = this.referrals;
o.batch = this.batch;
o.m_rebind_proc = this.m_rebind_proc;
o.m_hop_limit = this.m_hop_limit;
if ( (this.m_clientControls != null) && (this.m_clientControls.length > 0) ) {
o.m_clientControls = new LDAPControl[this.m_clientControls.length];
for( int i = 0; i < this.m_clientControls.length; i++ )
o.m_clientControls[i] = this.m_clientControls[i];
o.setHopLimit(this.getTimeLimit());
o.setReferrals(this.getReferrals());
o.setTimeLimit(this.getTimeLimit());
if (this.getBindProc() != null) {
o.setBindProc(this.getBindProc());
} else {
o.setRebindProc(this.getRebindProc());
}
if ( (this.m_serverControls != null) && (this.m_serverControls.length > 0) ) {
o.m_serverControls = new LDAPControl[this.m_serverControls.length];
for( int i = 0; i < this.m_serverControls.length; i++ )
o.m_serverControls[i] = this.m_serverControls[i];
LDAPControl[] tClientControls = this.getClientControls();
LDAPControl[] oClientControls;
if ( (tClientControls != null) &&
(tClientControls.length > 0) ) {
oClientControls = new LDAPControl[tClientControls.length];
for( int i = 0; i < tClientControls.length; i++ )
oClientControls[i] = (LDAPControl)tClientControls[i].clone();
o.setClientControls(oClientControls);
}
LDAPControl[] tServerControls = this.getServerControls();
LDAPControl[] oServerControls;
if ( (tServerControls != null) &&
(tServerControls.length > 0) ) {
oServerControls = new LDAPControl[tServerControls.length];
for( int i = 0; i < tServerControls.length; i++ )
oServerControls[i] = (LDAPControl)tServerControls[i].clone();
o.setServerControls(oServerControls);
}
return o;
}
}

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
@ -21,20 +21,11 @@ import java.util.*;
import netscape.ldap.client.*;
/**
* This implements an object for taking the asynchronous LDAP responses
* and making them appear somewhat synchronized. Uses built-in Java
* monitors to block until a response is received. This is also used
* to communicate exceptions across threads. This is used in particular
* for LDAP search operations; all other operations use the generic
* LDAPResponseListener object.
* Manages search results, references and responses returned on one or
* more search requests
*
* This class is part of the implementation; it is of no interest to
* developers.
*
* @version 1.0
*/
class LDAPSearchListener extends LDAPResponseListener {
private Vector searchResults;
public class LDAPSearchListener extends LDAPMessageQueue {
// this instance variable is only for cache purpose
private Long m_key = null;
@ -42,78 +33,84 @@ class LDAPSearchListener extends LDAPResponseListener {
/**
* Constructs a LDAP search listener.
* @param asynchOp A flag whether the object is used for asynchronous
* LDAP operations
* @param cons LDAP Search Constraints
* @see netscape.ldap.LDAPAsynchronousConnection
*/
LDAPSearchListener ( LDAPConnection conn,
LDAPSearchListener ( boolean asynchOp,
LDAPSearchConstraints cons ) {
super ( conn );
super ( asynchOp );
m_constraints = cons;
searchResults = new Vector ();
}
/**
* Informs the object of new search items (but not a response)
* @param newResult new search result message
* Block until all results are in. Used for synchronous search with
* batch size of zero.
* @return search response message
* @exception Network exception error
*/
synchronized void addSearchResult (JDAPMessage newResult) {
searchResults.addElement (newResult);
notifyAll ();
LDAPResponse completeSearchOperation () throws LDAPException{
return completeRequest();
}
/**
* Returns a collection of the currently-known search results.
* @return search result in enumeration
*/
Enumeration getSearchResults () {
return searchResults.elements ();
}
/**
* Returns a count of the currently-known search results.
* @return search result count
* Blocks until a search result, reference or response is available, * or until all operations associated with the object have completed * or been canceled.
*
* @return A search result, search reference, or search response message
* or null if there is no more outstanding requests
* @exception LDAPException Network error exception
* @exception LDAPInterruptedException The invoking thread was interrupted
* @see LDAPResponse
* @see LDAPSearchResult
* @see LDAPSearchResultReference
*/
int getCount () {
return searchResults.size ();
}
public LDAPMessage getResponse () throws LDAPException{
LDAPMessage result = nextMessage();
/**
* Resets the state of this object, so it can be recycled.
*/
void reset () {
super.reset();
if ( searchResults != null )
searchResults.removeAllElements();
}
/**
* Returns the next server search result. This method only makes
* sense in asynchronous mode. It will block if no new messages have
* been received since the last call to nextResult. If a response
* is received indicating that there are no more matches, this
* method returns null.
* @return jdap message
*/
JDAPMessage nextResult () {
JDAPMessage result;
synchronized( this ) {
while (searchResults.size() < 1) {
if (isResponseReceived()) {
searchResults.removeAllElements();
return null;
}
try {
wait();
} catch (InterruptedException e ) {
}
}
result = (JDAPMessage)searchResults.elementAt (0);
/* Allow garbage collection to free this result */
searchResults.removeElementAt (0);
}
getConnection().resultRetrieved();
// Notify LDAPConnThread to wake up if backlog limit has been reached
if (result instanceof LDAPSearchResult || result instanceof LDAPSearchResultReference) {
LDAPConnection ld = getConnection(result.getId());
if (ld != null) {
ld.resultRetrieved();
}
}
return result;
}
/**
* Merge two search listeners
* Move/append the content from another search listener to this one.
*
* To be used for synchronization of asynchronous LDAP operations where
* requests are sent by one thread but processed by another one
*
* A client may be implemented in such a way that one thread makes LDAP
* requests and calls l.getIDs(), while another thread is responsible for
* processing of responses (call l.getResponse()). Both threads are using
* the same listener objects. In such a case, a race
* condition may occur, where a LDAP response message is retrieved and
* the request terminated (request ID removed) before the first thread
* has a chance to execute l.getIDs().
* The proper way to handle this scenario is to create a separate listener
* for each new request, and after l.getIDs() has been invoked, merge the
* new request with the existing one.
* @param listener2 The listener to be merged with.
*/
public void merge(LDAPSearchListener listener2) {
super.merge(listener2);
}
/**
* Returns message ids for all outstanding requests
* @return Message id array
*/
public int[] getIDs() {
return super.getIDs();
}
/**
* Return the search constraints used to create this object
* @return the search constraints used to create this object

View File

@ -0,0 +1,68 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import netscape.ldap.client.opers.JDAPSearchResponse;
/**
* A LDAPSearchResult object encapsulates a single search result.
*
* @version 1.0
*/
public class LDAPSearchResult extends LDAPMessage {
/**
* LDAPEntry
*/
private LDAPEntry m_entry;
/**
* Constructor
*
* @param msgid message identifier
* @param rsp Search operation response
* @param controls Array of controls of null
* @see netscape.ldap.LDAPEntry
*/
LDAPSearchResult(int msgid, JDAPSearchResponse rsp, LDAPControl[]controls) {
super(msgid, rsp, controls);
}
/**
* Returns the entry of a server search response.
* @return An entry returned by the server in response to a search
* request
* @see netscape.ldap.LDAPEntry
*/
public LDAPEntry getEntry() {
if (m_entry == null) {
JDAPSearchResponse rsp = (JDAPSearchResponse)getProtocolOp();
LDAPAttribute[] lattrs = rsp.getAttributes();
LDAPAttributeSet attrs;
if ( lattrs != null ) {
attrs = new LDAPAttributeSet( lattrs );
}
else {
attrs = new LDAPAttributeSet();
}
String dn = rsp.getObjectName();
m_entry = new LDAPEntry( dn, attrs );
}
return m_entry;
}
}

View File

@ -0,0 +1,54 @@
/* -*- 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
import netscape.ldap.client.opers.JDAPSearchResultReference;
/**
* An LDAPSearchResultReference object encapsulates a continuation
* reference from a search operation.
*
* @version 1.0
*/
public class LDAPSearchResultReference extends LDAPMessage {
/**
* A lists of referred to Ldap URLs
*/
private String m_URLs[];
/**
* Constructor
*
* @param msgid message identifier
* @param resRef Search result reference response
* @param controls Array of controls of null
* @see netscape.ldap.LDAPEntry
*/
LDAPSearchResultReference(int msgid, JDAPSearchResultReference resRef, LDAPControl[]controls) {
super(msgid, resRef, controls);
m_URLs = resRef.getUrls();
}
/**
* Returns a list of referred to LDAP URLs
* @return A list of URLs
*/
public String[] getUrls() {
return m_URLs;
}
}

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
@ -53,6 +53,7 @@ public class LDAPSearchResults implements Enumeration {
private boolean currAttrsOnly;
private Vector referralResults = new Vector();
private Vector exceptions;
private LDAPControl[] responseControls = null;
// only used for the persistent search
private boolean firstResult = false;
@ -112,46 +113,34 @@ public class LDAPSearchResults implements Enumeration {
currAttrsOnly = attrsOnly;
}
void add( JDAPProtocolOp sr ) {
if (sr instanceof JDAPSearchResponse)
add((JDAPSearchResponse)sr);
else if (sr instanceof JDAPSearchResultReference)
add((JDAPSearchResultReference)sr);
/**
* Add search entry of referral
* @param msg LDAPSearchResult or LDAPsearchResultReference
*/
void add( LDAPMessage msg ) {
if (msg instanceof LDAPSearchResult) {
entries.addElement( ((LDAPSearchResult)msg).getEntry());
}
else if (msg instanceof LDAPSearchResultReference) {
/* convert to LDAPReferralException */
String urls[] = ((LDAPSearchResultReference)msg).getUrls();
if (urls != null) {
if (exceptions == null) {
exceptions = new Vector();
}
exceptions.addElement(new LDAPReferralException(null, 0, urls));
}
}
}
/**
* Adds one result of a search (from JDAP) to the object.
* @param sr A search response in JDAP format
* Add exception
* @param e exception
*/
void add( JDAPSearchResponse sr ) {
LDAPAttribute[] lattrs = sr.getAttributes();
LDAPAttributeSet attrs;
if ( lattrs != null )
attrs = new LDAPAttributeSet( lattrs );
else
attrs = new LDAPAttributeSet();
String dn = sr.getObjectName();
LDAPEntry entry = new LDAPEntry( dn, attrs );
entries.addElement( entry );
}
/**
* Adds search reference to this object.
*/
void add( JDAPSearchResultReference sr ) {
/* convert to LDAPReferralException */
String urls[] = sr.getUrls();
if (urls != null) {
if (exceptions == null)
exceptions = new Vector();
exceptions.addElement(new LDAPReferralException(null, 0, urls));
}
}
void add(LDAPException e) {
if (exceptions == null)
if (exceptions == null) {
exceptions = new Vector();
}
exceptions.addElement(e);
}
@ -223,6 +212,26 @@ public class LDAPSearchResults implements Enumeration {
quicksort (toSort, compare, shigh+1, high);
}
/**
* Sets the response controls for this search result.
* @param controls The controls to be stored.
*/
protected void setResponseControls(LDAPControl[] controls) {
responseControls = controls;
}
/**
* Returns the controls returned with this search result. If any control
* is registered with <CODE>LDAPControl</CODE>, an attempt is made to
* instantiate the control. If the instantiation fails, the control is
* returned as a basic <CODE>LDAPControl</CODE>.
* @return An array of type <CODE>LDAPControl</CODE>
* @see netscape.ldap.LDAPControl#register
*/
public LDAPControl[] getResponseControls() {
return responseControls;
}
/**
* Sorts the search results.
* <P>
@ -452,8 +461,10 @@ public class LDAPSearchResults implements Enumeration {
totalReferralEntries = totalReferralEntries+res.getCount();
}
if (resultSource != null) {
count = resultSource.getCount();
}
count = resultSource.getMessageCount();
} else {
count = entries.size();
}
if (exceptions != null)
return (count + exceptions.size() + totalReferralEntries);
return (count + totalReferralEntries);
@ -492,13 +503,20 @@ public class LDAPSearchResults implements Enumeration {
return;
}
JDAPMessage msg = resultSource.nextResult();
if (msg == null) {
LDAPMessage msg = null;
try {
msg = resultSource.nextMessage();
} catch (LDAPException e) {
add(e);
currConn.releaseSearchListener(resultSource);
return;
}
if (msg instanceof LDAPResponse) {
try {
// check response and see if we need to do referral
// v2: referral stored in the JDAPResult
JDAPMessage response = resultSource.getResponse();
currConn.checkSearchMsg(this, response, currCons,
currConn.checkSearchMsg(this, msg, currCons,
currBase, currScope, currFilter, currAttrs, currAttrsOnly);
} catch (LDAPException e) {
System.err.println("Exception: "+e);

View File

@ -41,7 +41,6 @@ public class LDAPSortKey {
* attribute in reverse order and use the matching rule identified
* by the OID 1.2.3.4) <P>
*</UL>
* @see netscape.ldap.controls.LDAPPagedControl
* @see netscape.ldap.controls.LDAPSortControl
* @see netscape.ldap.controls.LDAPVirtualListControl
*/
@ -76,7 +75,6 @@ public class LDAPSortKey {
* </UL>
* @param reverse If <CODE>true</CODE>, the sorting is done in
* descending order.
* @see netscape.ldap.controls.LDAPPagedControl
* @see netscape.ldap.controls.LDAPSortControl
* @see netscape.ldap.controls.LDAPVirtualListControl
*/
@ -102,7 +100,6 @@ public class LDAPSortKey {
* descending order.
* @param matchRule Object ID (OID) of the matching rule for
* the attribute (for example, <CODE>1.2.3.4</CODE>).
* @see netscape.ldap.controls.LDAPPagedControl
* @see netscape.ldap.controls.LDAPSortControl
* @see netscape.ldap.controls.LDAPVirtualListControl
*/

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
@ -87,6 +87,14 @@ public interface LDAPv2 {
*/
public static final int TIMELIMIT = 4;
/**
* Option specifying the maximum number of milliseconds the
* server should wait when returning search results.
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int SERVER_TIMELIMIT = 5;
/**
* Option specifying whether or not referrals to other LDAP
* servers are followed automatically.
@ -118,6 +126,15 @@ public interface LDAPv2 {
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int REFERRALS_HOP_LIMIT = 10;
/**
* Option specifying the object containing the method for
* authenticating to the server.
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
* @see netscape.ldap.LDAPBind
*/
public static final int BIND = 13;
/**
* Option specifying the version of the LDAP protocol
@ -230,6 +247,15 @@ public interface LDAPv2 {
*/
public void disconnect() throws LDAPException;
/**
* Notifies the server to not send additional results associated with this
* <CODE>LDAPSearchResults</CODE> object, and discards any results already
* received.
* @param results LDAPSearchResults object returned from a search.
* @exception LDAPException Failed to notify the server.
*/
public void abandon(LDAPSearchResults results) throws LDAPException;
/**
* Authenticates user with the LDAP server.
* @param Dn Distinguished name to use for authentication.
@ -238,6 +264,14 @@ public interface LDAPv2 {
*/
public void authenticate (String DN, String passwd) throws LDAPException;
/**
* Authenticates user with the LDAP server.
* @param Dn Distinguished name to use for authentication.
* @param passwd Password for authentication.
* @exception LDAPException Failed to authenticate to the server.
*/
public void bind (String DN, String passwd) throws LDAPException;
/**
* Read the entry corresponding to the specified distinguished name (DN).
* @param DN Distinguished name of the entry to retrieve.
@ -328,7 +362,7 @@ public interface LDAPv2 {
* @exception LDAPException Failed to perform the comparison.
*/
public boolean compare (String DN, LDAPAttribute attr,
LDAPSearchConstraints cons) throws LDAPException;
LDAPConstraints cons) throws LDAPException;
/**
* Adds an entry to the directory.
@ -343,7 +377,7 @@ public interface LDAPv2 {
* @param cons The constraints set for the add operation.
* @exception LDAPException Failed to add the entry to the directory.
*/
public void add (LDAPEntry entry, LDAPSearchConstraints cons)
public void add (LDAPEntry entry, LDAPConstraints cons)
throws LDAPException;
/**
@ -362,7 +396,7 @@ public interface LDAPv2 {
* @exception LDAPException Failed to modify the specified entry.
*/
public void modify (String DN, LDAPModification mod,
LDAPSearchConstraints cons) throws LDAPException;
LDAPConstraints cons) throws LDAPException;
/**
* Modifies the attributes of a directory entry.
@ -380,7 +414,7 @@ public interface LDAPv2 {
* @exception LDAPException Failed to modify the specified entry.
*/
public void modify (String DN, LDAPModificationSet mods,
LDAPSearchConstraints cons ) throws LDAPException;
LDAPConstraints cons ) throws LDAPException;
/**
* Removes an entry from the directory.
@ -395,7 +429,7 @@ public interface LDAPv2 {
* @param cons The constraints set for the delete operation.
* @exception LDAPException Failed to remove the entry from the directory.
*/
public void delete( String DN, LDAPSearchConstraints cons )
public void delete( String DN, LDAPConstraints cons )
throws LDAPException;
/**
@ -421,13 +455,14 @@ public interface LDAPv2 {
* @exception LDAPException Failed to rename the entry in the directory.
*/
public void rename ( String DN, String newRDN, boolean deleteOldRDN,
LDAPSearchConstraints cons ) throws LDAPException;
LDAPConstraints cons ) throws LDAPException;
/**
* Retrieves an option that applies to the connection.
* The particular meaning may be implementation-dependent.
* The standard options are the search options described by
* the <CODE>LDAPSearchConstraints</CODE> class.
* The standard options are the options described by
* the <CODE>LDAPSearchConstraints</CODE> and <CODE>LDAPConstraints</CODE>
* classes.
* @exception LDAPException Failed to retrieve the value of the specified option.
*/
public Object getOption( int option ) throws LDAPException;
@ -435,8 +470,9 @@ public interface LDAPv2 {
/**
* Sets an option that applies to the connection.
* The particular meaning may be implementation-dependent.
* The standard options are the search options described by
* the <CODE>LDAPSearchConstraints</CODE> class.
* The standard options are the options described by
* the <CODE>LDAPSearchConstraints</CODE> and <CODE>LDAPConstraints</CODE>
* classes.
* @exception LDAPException Failed to set the specified option.
*/
public void setOption( int option, Object value ) throws LDAPException;

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap;
@ -71,6 +71,28 @@ public interface LDAPv3 extends LDAPv2 {
String passwd)
throws LDAPException;
/**
* Authenticates to the LDAP server (that the object is currently
* connected to) using the specified name and password, with the
* specified LDAP protocol version. If the server does not support
* the requested protocol version, an exception is thrown. If the
* object has been disconnected from an LDAP server, this method
* attempts to reconnect to the server. If the object had already
* authenticated, the old authentication is discarded.
* @param version LDAP protocol version requested: currently 2 or 3.
* @param dn If non-null and non-empty, specifies that the
* connection and all operations through it should be
* authenticated with dn as the distinguished name.
* @param passwd If non-null and non-empty, specifies that the
* connection and all operations through it should be
* authenticated with passwd as password.
* @exception LDAPException Failed to authenticate to the LDAP server.
*/
public void bind(int version,
String dn,
String passwd)
throws LDAPException;
/**
* Performs an extended operation on the directory. Extended operations
* are part of version 3 of the LDAP protocol.
@ -107,7 +129,7 @@ public interface LDAPv3 extends LDAPv2 {
* @exception LDAPException Failed to rename the specified entry.
*/
public void rename( String DN, String newRDN, String newParentDN,
boolean deleteOldRDN, LDAPSearchConstraints cons ) throws LDAPException;
boolean deleteOldRDN, LDAPConstraints cons ) throws LDAPException;
/**
* Returns an array of the latest controls (if any) from server.

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -21,12 +21,12 @@ import java.util.*;
import java.io.*;
/**
* This class is for the any object that is unknown to the
* This class is for the "any" object that is unknown to the
* BER package but conforms to BER rules.
*
* <pre>
* Encoding Rule:
* The encoding is the encoding of the chosen type.
* The encoding is that of the particular implementation.
* </pre>
*
* @version 1.0
@ -39,7 +39,7 @@ public class BERAny extends BERElement {
private BERElement m_value = null;
/**
* Constructs an any element.
* Constructs an "any" element.
* @param value BERElement value
*/
public BERAny(BERElement value) {
@ -47,10 +47,10 @@ public class BERAny extends BERElement {
}
/**
* Constructs an any element with the input stream.
* Note that with the current decoding architecture any types
* will not be decoded as any's but rather only as the types
* chosen. The following method will never be called.
* Constructs an "any" element from an input stream.
* Note that with the current decoding architecture "any" types
* will not be decoded as any's but rather as the particular
* implementation. The following method will never be called.
* @param stream input stream
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream.
@ -62,7 +62,7 @@ public class BERAny extends BERElement {
}
/**
* Sends the BER encoding directly to stream.
* Sends the BER encoding directly to an output stream.
* @param stream output stream
*/
public void write(OutputStream stream) throws IOException {

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -28,6 +28,12 @@ import java.io.*;
* the number of bits ourselves in m_value_num_bits.
* Change is required when BitSet is fixed.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x03
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
*/
@ -47,9 +53,9 @@ public class BERBitString extends BERElement {
}
/**
* Constructs a bitstring element with the input stream.
* Constructs a bitstring element from an input stream
* (for constructed encodings).
* @param stream input stream
* @param stream source
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream.
* @exception IOException failed to construct
@ -110,9 +116,9 @@ public class BERBitString extends BERElement {
}
/**
* Constructs a bitstring element with the input stream.
* Constructs a bitstring element from an input stream
* (for primitive encodings).
* @param stream input stream
* @param stream source
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream.
* @exception IOException failed to construct
@ -166,7 +172,7 @@ public class BERBitString extends BERElement {
}
/**
* Sends the BER encoding directly to stream.
* Sends the BER encoding directly to a stream.
* Always sends in primitive form.
* @param stream output stream
*/

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -53,8 +53,8 @@ public class BERBoolean extends BERElement {
}
/**
* Constructs a boolean element with the input stream.
* @param stream input stream
* Constructs a boolean element from an input stream.
* @param stream source
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream.
* @exception IOException failed to construct
@ -72,7 +72,7 @@ public class BERBoolean extends BERElement {
}
/**
* Sends the BER encoding directly to stream.
* Sends the BER encoding directly to a stream.
* @param stream output stream
*/
public void write(OutputStream stream) throws IOException {

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -33,24 +33,22 @@ public abstract class BERCharacterString extends BERElement {
protected String m_value = null;
/**
* Constructs an characterstring element containing buffer.
* Constructs a character string element containing a buffer.
*/
public BERCharacterString() {
}
/**
* Constructs an octetstring element containing buffer.
* @param buffer string containing 'octets'
* Constructs a character string element containing buffer.
* @param buffer a string value
*/
public BERCharacterString(String string) {
m_value = string;
}
/**
* Constructs a characterstring element from buffer.
* @param buffer buffer containing 'octets'
* @param start start of buffer range to copy
* @param end end of buffer range to copy
* Constructs a character string element from a byte array.
* @param buffer buffer containing UTF8 data
*/
public BERCharacterString(byte[] buffer) {
try{
@ -60,7 +58,7 @@ public abstract class BERCharacterString extends BERElement {
}
/**
* Constructs a characterstring element with the input stream.
* Constructs a character string element from an input stream
* (for constructed encoding)
* @param stream input stream
* @param bytes_read array of 1 int, incremented by number of bytes read.
@ -113,9 +111,9 @@ public abstract class BERCharacterString extends BERElement {
}
/**
* Constructs a characterstring element with the input stream.
* Constructs a character string element from an input stream
* (for primitive encoding)
* @param stream input stream
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read.
* @exception IOException failed to construct
*/
@ -137,12 +135,12 @@ public abstract class BERCharacterString extends BERElement {
}
}
private byte[] byte_buf;
/**
* Writes BER to stream.
* @param stream output stream
*/
private byte[] byte_buf;
public void write(OutputStream stream) throws IOException {
stream.write(getType()); /* tag */
if (m_value == null) {

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -21,12 +21,12 @@ import java.util.*;
import java.io.*;
/**
* This class is for the Choice object. Note that this class will be
* used by the client.
* This class is for the Choice object. Note that this class may be
* used by a client.
*
* <pre>
* ENCODING RULE:
* Encoding is the encoding of the chosen type.
* Encoding is the encoding of the specific type used.
* </pre>
*
* @version 1.0
@ -40,17 +40,17 @@ public class BERChoice extends BERElement {
/**
* Constructs a choice element.
* @param value BERElement value
* @param value Any BERElement value
*/
public BERChoice(BERElement value) {
m_value = value;
}
/**
* Constructs a choice element with the input stream.
* Constructs a choice element from an input stream.
* Note that with the current decoding architecture choice types
* will not be decoded as choices but rather only as the types
* chosen. The following method will never be called.
* will not be decoded as choices but rather as the types
* chosen. The following method will never be called.
* @param stream input stream
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream.
@ -62,9 +62,9 @@ public class BERChoice extends BERElement {
}
/**
* Sends the BER encoding of the chosen type directly to stream.
* Sends the BER encoding of the chosen type directly to a stream.
* @param stream output stream
* @exception IOException failed to construct
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
m_value.write(stream);

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -21,7 +21,7 @@ import java.util.*;
import java.io.*;
/**
* This abstract class serves as a based class for constructs
* This abstract class serves as a based class for constructed
* types such as sequence or set.
*
* @version 1.0
@ -40,7 +40,7 @@ public abstract class BERConstruct extends BERElement {
}
/**
* Constructs a construct element with the input stream.
* Constructs a construct element from an input stream.
* @param decoder decoder for application specific ber
* @param stream input stream from socket
* @param bytes_read array of 1 int; value incremented by number
@ -99,7 +99,7 @@ public abstract class BERConstruct extends BERElement {
}
/**
* Sends the BER encoding directly to stream.
* Sends the BER encoding directly to a stream.
* @param stream output stream
* @exception IOException failed to send
*/

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -21,13 +21,13 @@ import java.util.*;
import java.io.*;
/**
* This class is for the tagged object. Nested tag is
* This class is for the tagged object type. A nested tag is
* allowed. A tagged element contains another BER element.
*
* @version 1.0
* @seeAlso CCITT X.209
*/
public abstract class BERElement {
public abstract class BERElement implements Serializable {
/**
* Possible element types.
*/
@ -85,9 +85,9 @@ public abstract class BERElement {
/**
* Gets a ber element from the input stream.
* @param decoder decoder for application specific ber
* @param stream stream where ber encoding comes
* @param stream source of ber encoding
* @param bytes_read array of 1 int; value incremented by
* number of bytes fread from stream.
* number of bytes read from stream.
* @exception IOException failed to decode an element.
*/
public static BERElement getElement(BERTagDecoder decoder,
@ -150,7 +150,8 @@ public abstract class BERElement {
}
/**
* Decodes length octets from stream.
* Reads and decodes a length byte and then that many octets
* from the input stream.
* @param stream input stream to read from
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream.
@ -227,11 +228,12 @@ public abstract class BERElement {
}
/**
* Reads the unsigned binary from the input stream.
* @param stream inputstream
* @param byte_read number of byte read
* @param length length of the byte to be read
* @return the value of the two complement
* Reads a number of bytes from an input stream and form
* an integer..
* @param stream source of data
* @param bytes_read number of bytes read
* @param length number of bytes to be read (1 - 4)
* @return the value of the data as two's complement
* @exception IOException failed to read octets
*/
protected int readUnsignedBinary(InputStream stream,
@ -249,11 +251,12 @@ public abstract class BERElement {
}
/**
* Reads the two complement representation from the input stream.
* @param stream inputstream
* @param byte_read number of byte read
* @param length length of the byte to be read
* @return the value of the two complement
* Reads the two's complement representation of an integer from
* an input stream.
* @param stream source of data
* @param bytes_read number of bytes read
* @param length number of bytes to be read
* @return the integer value as two's complement
* @exception IOException failed to read octets
*/
protected int readTwosComplement(InputStream stream,
@ -295,7 +298,7 @@ public abstract class BERElement {
}
/**
* Sends the BER encoding directly to stream.
* Sends the BER encoding directly to a stream.
* @param stream output stream.
* @return bytes written to stream.
*/

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -23,13 +23,25 @@ import java.io.*;
/**
* This class is for the Enumerated object.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x0a
* length = (short or long form)
* one or more contents octets hold integral value
* value in two's complement
*
* Example: (Enumerated - 1)
* 0A 01 01
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
*/
public class BEREnumerated extends BERIntegral {
/**
* Constructs an enumerated element with value.
* Constructs an enumerated element with a value.
* @param value integral value
*/
public BEREnumerated(int value) {

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -47,12 +47,12 @@ import java.io.*;
*/
public abstract class BERIntegral extends BERElement {
/**
* Internal variables
* Value of element
*/
private int m_value;
/**
* Constructs an integral type.
* Constructs an integral type with a value.
* @param value integer value
*/
public BERIntegral(int value) {
@ -60,8 +60,8 @@ public abstract class BERIntegral extends BERElement {
}
/**
* Constructs an integral element with the input stream.
* @param stream input stream
* Constructs an integral element from an input stream.
* @param stream source
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
* @exception IOException failed to construct
@ -95,8 +95,8 @@ public abstract class BERIntegral extends BERElement {
/**
* Writes BER to stream.
* @return number of bytes written to stream.
* @exception IOException failed to send
* @param stream output stream.
* @exception IOException on failure to write
*/
public void write(OutputStream stream) throws IOException {
int binary_value = m_value;
@ -121,9 +121,11 @@ public abstract class BERIntegral extends BERElement {
do {
if (m_value < 0)
content_octets[num_content_octets+offset] = (byte)((binary_value^0xFF)&0xFF);
content_octets[num_content_octets+offset] =
(byte)((binary_value^0xFF)&0xFF);
else
content_octets[num_content_octets+offset] = (byte)(binary_value&0xFF);
content_octets[num_content_octets+offset] =
(byte)(binary_value&0xFF);
binary_value = (binary_value>>8);
num_content_octets++;
@ -134,7 +136,7 @@ public abstract class BERIntegral extends BERElement {
for (i=0; i<num_content_octets; i++)
net_octets[offset+num_content_octets-1-i] = content_octets[offset+i];
/* pse 1/16/96 if +ve value encoded and the leading encoding bit is set
/* pse 1/16/96 if we have the value encoded and the leading encoding bit is set
then stuff in a leading zero byte */
lead = (int)net_octets[offset];
@ -152,7 +154,7 @@ public abstract class BERIntegral extends BERElement {
/**
* Gets the integral value.
* @param element type
* @return element value
*/
public int getValue() {
return m_value;
@ -160,7 +162,7 @@ public abstract class BERIntegral extends BERElement {
/**
* Gets the element type.
* @param element type
* @return element type
*/
public abstract int getType();

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -46,7 +46,7 @@ public class BERNull extends BERElement {
}
/**
* Constructs a null element with the input stream.
* Constructs a null element from an input stream.
* @param stream input stream from socket
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
@ -60,7 +60,7 @@ public class BERNull extends BERElement {
/**
* Sends the BER encoding directly to stream.
* @param stream output stream
* @exception IOException failed to send
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
byte[] buffer = new byte[2];
@ -71,7 +71,7 @@ public class BERNull extends BERElement {
/**
* Gets the element type.
* @param element type
* @return element type
*/
public int getType() {
return BERElement.NULL;

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -21,7 +21,15 @@ import java.util.*;
import java.io.*;
/**
* This class is for NumericString type.
* This class is for the NumericString type.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x12
* length = (short or long form)
* one or more contents octets
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
@ -29,15 +37,15 @@ import java.io.*;
public class BERNumericString extends BERCharacterString {
/**
* Constructs an octetstring element containing buffer.
* @param buffer string containing 'octets'
* Constructs a numeric string element from a string
* @param buffer string with value of element
*/
public BERNumericString(String string) {
m_value = string;
}
/**
* Constructs a numericstring element from buffer.
* Constructs a numeric string element from a byte array
* @param buffer buffer
*/
public BERNumericString(byte[] buffer) {
@ -45,9 +53,9 @@ public class BERNumericString extends BERCharacterString {
}
/**
* Constructs a numericstring element with the input stream.
* Constructs a numeric string element from an input stream
* (for constructed encoding)
* @param stream input stream
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read.
* @exception IOException failed to construct
*/
@ -57,7 +65,7 @@ public class BERNumericString extends BERCharacterString {
}
/**
* Constructs a numericstring element with the input stream.
* Constructs a numericstring element from an input stream
* (for primitive encoding)
* @param stream input stream
* @param bytes_read array of 1 int, incremented by number of bytes read.
@ -70,7 +78,7 @@ public class BERNumericString extends BERCharacterString {
/**
* Gets the element type.
* @param element type
* @return element type
*/
public int getType() {
return BERElement.NUMERICSTRING;

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -29,13 +29,13 @@ import java.io.*;
*/
public class BERObjectId extends BERElement {
/**
* Internal variables
* Values of each component of the OID
*/
private int[] m_value = null;
/**
* Constructs a object id element.
* @param value object id value
* Constructs an object id element from an array of values.
* @param value object id value as array of components
*/
public BERObjectId(int[] value) {
m_value = new int[value.length];
@ -43,7 +43,7 @@ public class BERObjectId extends BERElement {
}
/**
* Constructs a object id element.
* Constructs an object id element from a string.
* @param value object id value in format "2.100.3"
*/
public BERObjectId(String value) {
@ -54,8 +54,8 @@ public class BERObjectId extends BERElement {
}
/**
* Constructs an object id element with the input stream.
* @param stream input stream
* Constructs an object id element from an input stream.
* @param stream source
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream.
* @exception IOException failed to construct
@ -77,7 +77,9 @@ public class BERObjectId extends BERElement {
oid.addElement(new Integer(1));
else
oid.addElement(new Integer(2));
oid.addElement(new Integer(sub_id - (((Integer)oid.elementAt(oid.size()-1)).intValue() * 40)));
oid.addElement(new Integer(
sub_id - (((Integer)oid.elementAt(
oid.size()-1)).intValue() * 40)));
while (contents_length > 0) {
contents_read[0] = 0;
@ -92,10 +94,10 @@ public class BERObjectId extends BERElement {
}
/**
* Sends the BER encoding directly to stream. Note that OID must
* Sends the BER encoding directly to a stream. Note that OID must
* have >= 2 identifier components (values).
* @param stream output stream
* @exception IOException failed to construct
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
stream.write(BERElement.OBJECTID);
@ -154,7 +156,7 @@ public class BERObjectId extends BERElement {
/**
* Gets the element value.
* @param element value
* @return element value
*/
public int[] getValue() {
return m_value;
@ -162,7 +164,7 @@ public class BERObjectId extends BERElement {
/**
* Gets the element type.
* @param element type
* @return element type
*/
public int getType() {
return BERElement.OBJECTID;

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -21,7 +21,15 @@ import java.util.*;
import java.io.*;
/**
* This class is for OctetString type.
* This class is for the OctetString type.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x04
* length = (short or long form)
* one or more contents octets
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
@ -29,12 +37,12 @@ import java.io.*;
public class BEROctetString extends BERElement {
/**
* Internal variables
* Raw value of element
*/
private byte[] m_value = null;
/**
* Constructs an octetstring element containing a copy of
* Constructs an octet string element containing a copy of
* the contents of buffer.
* @param buffer A UCS-2 String.
*/
@ -48,7 +56,7 @@ public class BEROctetString extends BERElement {
}
/**
* Constructs an octetstring element containing a reference to
* Constructs an octet string element containing a reference to
* buffer.
* @param buffer A byte array, which must be in UTF-8 format if
* it is string data.
@ -58,7 +66,7 @@ public class BEROctetString extends BERElement {
}
/**
* Constructs an octetstring element containing a
* Constructs an octet string element containing a
* subset of buffer.
* @param buffer buffer containing 'octets'
* @param start start of buffer range to copy
@ -72,9 +80,10 @@ public class BEROctetString extends BERElement {
}
/**
* Constructs a octetstring element with the input stream.
* Constructs an octet string element from an input stream
* (for constructed encoding)
* @param stream input stream
* @param decoder a decode that understands the specific tags
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read.
* @exception IOException failed to construct
*/
@ -118,9 +127,9 @@ public class BEROctetString extends BERElement {
}
/**
* Constructs a octetstring element with the input stream.
* Constructs an octet string element from an input stream
* (for primitive encoding)
* @param stream input stream
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read.
* @exception IOException failed to construct
*/
@ -141,7 +150,7 @@ public class BEROctetString extends BERElement {
/**
* Writes BER to stream
* @return number of bytes written to stream.
* @exception IOException failed to send
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
stream.write((byte)BERElement.OCTETSTRING); /* OCTETSTRING tag */

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -21,7 +21,15 @@ import java.util.*;
import java.io.*;
/**
* This class is for PrintableString type.
* This class is for the PrintableString type.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x13
* length = (short or long form)
* one or more contents octets
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
@ -29,25 +37,25 @@ import java.io.*;
public class BERPrintableString extends BERCharacterString {
/**
* Constructs an octetstring element containing buffer.
* @param buffer string containing 'octets'
* Constructs a printable string element containing buffer.
* @param buffer string value
*/
public BERPrintableString(String string) {
m_value = string;
}
/**
* Constructs a printablestring element from buffer.
* @param buffer buffer
* Constructs a printables tring element from buffer.
* @param buffer byte array value
*/
public BERPrintableString(byte[] buffer) {
super(buffer);
}
/**
* Constructs a printablestring element with the input stream.
* Constructs a printable string element from an input stream
* (for constructed encoding)
* @param stream input stream
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read.
* @exception IOException failed to construct
*/
@ -57,9 +65,9 @@ public class BERPrintableString extends BERCharacterString {
}
/**
* Constructs a printablestring element with the input stream.
* Constructs a printablestring element from an input stream
* (for primitive encoding)
* @param stream input stream
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read.
* @exception IOException failed to construct
*/
@ -68,17 +76,16 @@ public class BERPrintableString extends BERCharacterString {
super(stream,bytes_read);
}
/**
* Gets the element type.
* @param element type
* @return element type
*/
public int getType() {
return BERElement.PRINTABLESTRING;
}
/**
* Gets the string representation. Note that currently prints out
* Gets the string representation. Note that it prints out
* values in decimal form.
* @return string representation of tag
*/

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -32,19 +32,19 @@ import java.io.*;
* @seeAlso CCITT X.209
*/
public class BERReal extends BERElement {
/*
/**
* Constants: special ASN.1 real values
*/
public final static float PLUS_INFINITY = 1.0f/0.0f;
public final static float MINUS_INFINITY = -1.0f/0.0f;
/**
* Internal variables
* Value of element
*/
private float m_value = 0;
/**
* Constructs a real element.
* Constructs a real element with a value
* @param value float value
*/
public BERReal(float value) {
@ -52,8 +52,8 @@ public class BERReal extends BERElement {
}
/**
* Constructs a real element with the input stream.
* @param stream input stream
* Constructs a real element from an input stream.
* @param stream source
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream.
* @exception IOException failed to construct
@ -162,9 +162,9 @@ public class BERReal extends BERElement {
}
/**
* Sends the BER encoding directly to stream.
* Sends the BER encoding directly to a stream.
* @param stream output stream
* @exception IOException failed to construct
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
if (m_value == 0) {
@ -193,7 +193,7 @@ public class BERReal extends BERElement {
/**
* Gets the element type.
* @param element type
* @return element type
*/
public int getType() {
return BERElement.REAL;

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -24,6 +24,11 @@ import java.io.*;
* This class is for the Sequence object. A sequence object can
* contains a sequence of BER Elements.
*
* <pre>
* ENCODING RULE:
* tag = 0x30 (always constructed)
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
*/
@ -36,7 +41,7 @@ public class BERSequence extends BERConstruct {
}
/**
* Constructs a sequence element.
* Constructs a sequence element from an input stream.
* @param decoder application specific ber decoder.
* @param stream input stream to read ber from.
* @param bytes_read array of 1 int; value is incremented by
@ -45,12 +50,13 @@ public class BERSequence extends BERConstruct {
*/
public BERSequence(BERTagDecoder decoder, InputStream stream,
int[] bytes_read) throws IOException {
super(decoder, stream, bytes_read);
}
/**
* Gets the element type.
* @param element type
* @return element type
*/
public int getType() {
return BERElement.SEQUENCE;

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -21,9 +21,14 @@ import java.util.*;
import java.io.*;
/**
* This class is for the Set object. A set object can contains
* This class is for the Set object. A set object can contain
* a set of BER elements.
*
* <pre>
* ENCODING RULE:
* tag = 0x31 (always constructed)
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
*/
@ -36,9 +41,9 @@ public class BERSet extends BERConstruct {
}
/**
* Constructs a set element with the input stream.
* Constructs a set element from an input stream.
* @param decoder decoder for application specific ber
* @param stream input stream
* @param stream source
* @param bytes_read array of 1 int; value incremented by number
* of bytes read from stream.
* @exception IOException failed to construct
@ -49,9 +54,9 @@ public class BERSet extends BERConstruct {
}
/**
* Sends the BER encoding directly to stream.
* Sends the BER encoding directly to a stream.
* @param stream output stream
* @exception IOException failed to construct
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
super.write(stream);
@ -59,7 +64,7 @@ public class BERSet extends BERConstruct {
/**
* Gets the element type.
* @param element type
* @return element type
*/
public int getType() {
return BERElement.SET;

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -21,19 +21,30 @@ import java.util.*;
import java.io.*;
/**
* This class is for the tagged object. Nested tag is
* This class is for the tagged object type. A nested tag is
* allowed. A tagged element contains another
* ber element.
*
* @version 1.0
* <pre>
* ENCODING RULE:
* tag = whatever it is constructed with
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
*/
public class BERTag extends BERElement {
/**
* Internal variables
* Value of tag
*/
private int m_tag = 0;
/**
* Value of element
*/
private BERElement m_element = null;
/**
* Implicit or not
*/
private boolean m_implicit = false;
/**
@ -49,10 +60,10 @@ public class BERTag extends BERElement {
}
/**
* Constructs a tag element with the input stream.
* Constructs a tag element from an input stream.
* @param decoder decoder object for application specific tags
* @param tag tag value; already stripped from stream
* @param stream input stream
* @param stream source
* @param bytes_read array of 1 int; incremented by number
* ofbytes read from stream
* @exception IOException failed to construct
@ -81,9 +92,9 @@ public class BERTag extends BERElement {
}
/**
* Sets implicit tag. If it is a implicit tag
* the next element tag can be omitted. (will
* not be send to stream or buffer)
* Sets the implicit tag. If it is an implicit tag,
* the next element tag can be omitted (it will
* not be sent to a stream or buffer).
* @param value implicit flag
*/
public void setImplicit(boolean value) {
@ -91,7 +102,7 @@ public class BERTag extends BERElement {
}
/**
* Sends the BER encoding directly to stream.
* Sends the BER encoding directly to a stream.
* @param stream output stream
* @exception IOException failed to send
*/

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -23,10 +23,10 @@ import java.io.*;
/**
* This is an abstract class which should be extended
* for use by the BERTag class in decoding application
* specific BER tags. Since different application may
* define its own tag, the BER package needs tag decoder
* to give hints on how to decode implicit tagged
* objects. Note that each application should extend this
* specific BER tags. Since different applications may
* define their own tag, the BER package needs a tag decoder
* to give hints on how to decode implicitly tagged
* objects. Each application should extend this
* decoder.
*
* @version 1.0
@ -35,8 +35,13 @@ import java.io.*;
public abstract class BERTagDecoder {
/**
* Gets an application specific ber element from a buffer.
* @param buffer ber encoding buffer
* Gets an application specific ber element from an input stream.
* @param decoder an instance of a BERTagDecoder
* @param tag element tag
* @param stream source stream
* @param bytes_read array of 1 int; value incremented by number
* of bytes read from stream.
* @param implicit array of implicit flags
*/
public abstract BERElement getElement(BERTagDecoder decoder, int tag,
InputStream stream, int[] bytes_read, boolean[] implicit)

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -21,7 +21,15 @@ import java.util.*;
import java.io.*;
/**
* This class is for UTCTime object.
* This class is for the UTCTime object.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x17
* length = (short or long form)
* one or more contents octets
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
@ -34,17 +42,17 @@ public class BERUTCTime extends BERElement {
private String m_value = null;
/**
* Constructs an octetstring element containing buffer.
* @param buffer string containing 'octets'
* Constructs a UTC time element containing the specified string.
* @param utc_string string in UTC time format
*/
public BERUTCTime(String utc_string) {
m_value = utc_string;
}
/**
* Constructs a UTCTime element with the input stream.
* Constructs a UTCTime element from an input stream
* (for constructed encoding)
* @param stream input stream
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read.
* @exception IOException failed to construct
*/
@ -85,9 +93,9 @@ public class BERUTCTime extends BERElement {
}
/**
* Constructs a octetstring element with the input stream.
* Constructs a UTC time element from an input stream
* (for primitive encoding)
* @param stream input stream
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read.
* @exception IOException failed to construct
*/
@ -109,14 +117,14 @@ public class BERUTCTime extends BERElement {
}
/**
* Writes ber to stream
* Writes ber to a stream
* @return number of bytes written to stream.
* @exception IOException failed to send
* @exception IOException failed to write
*/
private byte[] byte_buf;
public void write(OutputStream stream) throws IOException {
stream.write((byte)BERElement.OCTETSTRING); /* OCTETSTRING tag */
stream.write((byte)getType());
if (m_value == null) {
sendDefiniteLength(stream, 0);
} else {

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.ber.stream;
@ -21,7 +21,15 @@ import java.util.*;
import java.io.*;
/**
* This class is for VisibleString object.
* This class is for the VisibleString object.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x1A
* length = (short or long form)
* one or more contents octets
* </pre>
*
* @version 1.0
* @seeAlso X.209

View File

@ -20,7 +20,6 @@ package netscape.ldap.client;
import java.util.*;
import java.io.*;
import netscape.ldap.ber.stream.*;
import netscape.ldap.client.*;
/**
* This class implements the attribute value assertion.

View File

@ -1,124 +0,0 @@
/* -*- 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.
*/
package netscape.ldap.client;
import java.util.*;
import netscape.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the controls for LDAPv3.
* <pre>
* Control ::= SEQUENCE {
* controlType LDAPOID,
* criticality BOOLEAN DEFAULT FALSE,
* controlValue OCTET STRING OPTIONAL
* }
* </pre>
*
* @version 1.0
* @see RFC1777
*/
public class JDAPControl {
/**
* Internal variables
*/
String m_type = null;
boolean m_criticality = false;
byte m_vals[] = null;
/**
* Constructs add request.
* @param dn distinguished name of adding entry
* @param attrs list of attribute associated with entry
*/
public JDAPControl(String type, boolean criticality, byte vals[]) {
m_type = type;
m_criticality = criticality;
m_vals = vals;
}
/**
* Constructs control from BER element.
* @param e BER element
*/
public JDAPControl(BERElement e) {
BERSequence s = (BERSequence)e;
try{
m_type = new String(((BEROctetString)s.elementAt(0)).getValue(), "UTF8");
} catch(Throwable x)
{}
Object value = s.elementAt(1);
if (value instanceof BERBoolean)
m_criticality = ((BERBoolean)value).getValue();
else
m_vals = ((BEROctetString)value).getValue();
if (s.size() >= 3)
m_vals = ((BEROctetString)s.elementAt(2)).getValue();
}
/**
* Gets the ber representation of control.
* @return ber representation of control
*/
public BERElement getBERElement() {
BERSequence seq = new BERSequence();
seq.addElement(new BEROctetString (m_type));
seq.addElement(new BERBoolean (m_criticality));
if ( (m_vals == null) || (m_vals.length < 1) )
seq.addElement(new BEROctetString ((byte[])null));
else {
seq.addElement(new BEROctetString (m_vals, 0, m_vals.length));
}
return seq;
}
/**
* Returns the identifier of the control.
* @return Returns the type of the Control, as a string.
*/
public String getID() {
return m_type;
}
/**
* Reports if the control is critical.
* @return true if the LDAP operation should be discarded if
* the server does not support this Control.
*/
public boolean isCritical() {
return m_criticality;
}
/**
* Returns the data of the control.
* @return Returns the data of the Control, as a byte array.
*/
public byte[] getValue() {
return m_vals;
}
/**
* Retrieves the string representation of extended request.
* @return string representation of extended request
*/
public String toString() {
return "Control" + " { type=" + m_type + ", criticality=" + m_criticality;
}
}

View File

@ -20,7 +20,6 @@ package netscape.ldap.client;
import java.util.*;
import netscape.ldap.ber.stream.*;
import java.io.*;
import netscape.ldap.client.*;
/**
* This class implements the filter substring.

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.client.opers;
@ -66,10 +66,10 @@ public class JDAPExtendedRequest implements JDAPProtocolOp {
*/
public BERElement getBERElement() {
BERSequence seq = new BERSequence();
seq.addElement(new BERTag(BERTag.APPLICATION|0,
seq.addElement(new BERTag(BERTag.CONTEXT|0,
new BEROctetString (m_oid), true));
if (m_value != null) {
seq.addElement(new BERTag(BERTag.APPLICATION|1,
seq.addElement(new BERTag(BERTag.CONTEXT|1,
new BEROctetString (m_value, 0, m_value.length), true));
}
BERTag element = new BERTag(BERTag.APPLICATION|BERTag.CONSTRUCTED|23,

View File

@ -40,8 +40,8 @@ import java.net.*;
* ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
* entry LDAPDN,
* newrdn RelativeLDAPDN,
* newSuperior [0] LDAPDN OPTIONAL
* deleteoldrdn BOOLEAN,
* newSuperior [0] LDAPDN OPTIONAL
* }
* </pre>
*
@ -118,10 +118,11 @@ public class JDAPModifyRDNRequest extends JDAPBaseDNRequest
BERSequence seq = new BERSequence();
seq.addElement(new BEROctetString(m_old_dn));
seq.addElement(new BEROctetString(m_new_rdn));
seq.addElement(new BERBoolean(m_delete_old_dn));
/* LDAPv3 new parent dn feature support */
if (m_new_superior != null)
seq.addElement(new BEROctetString(m_new_superior));
seq.addElement(new BERBoolean(m_delete_old_dn));
seq.addElement(new BERTag(BERTag.CONTEXT|0,
new BEROctetString (m_new_superior), true));
BERTag element = new BERTag(BERTag.APPLICATION|BERTag.CONSTRUCTED|12,
seq, true);
return element;

View File

@ -66,6 +66,7 @@ public class JDAPSearchRequest extends JDAPBaseDNRequest
public final static int DEREF_FINDING_BASE_OBJ = 2;
public final static int DEREF_ALWAYS = 3;
public final static String DEFAULT_FILTER = "(objectclass=*)";
/**
* Private variables
*/
@ -76,6 +77,7 @@ public class JDAPSearchRequest extends JDAPBaseDNRequest
protected int m_time_limit;
protected boolean m_attrs_only;
protected String m_filter = null;
protected JDAPFilter m_parsedFilter = null;
protected String m_attrs[] = null;
/**
@ -88,17 +90,23 @@ public class JDAPSearchRequest extends JDAPBaseDNRequest
* @param attrs_only should return type only
* @param filter string filter based on RFC1558
* @param attrs list of attribute types
* @exception IllegalArgumentException if the filter has bad syntax
*
*/
public JDAPSearchRequest(String base_dn, int scope, int deref,
int size_limit, int time_limit, boolean attrs_only,
String filter, String attrs[]) {
String filter, String attrs[]) throws IllegalArgumentException {
m_base_dn = base_dn;
m_scope = scope;
m_deref = deref;
m_size_limit = size_limit;
m_time_limit = time_limit;
m_attrs_only = attrs_only;
m_filter = filter;
m_filter = (filter == null) ? DEFAULT_FILTER : filter;
m_parsedFilter = JDAPFilter.getFilter(m_filter);
if (m_parsedFilter == null){
throw new IllegalArgumentException("Bad search filter");
}
m_attrs = attrs;
}
@ -173,10 +181,7 @@ public class JDAPSearchRequest extends JDAPBaseDNRequest
seq.addElement(new BERInteger(m_size_limit));
seq.addElement(new BERInteger(m_time_limit));
seq.addElement(new BERBoolean(m_attrs_only));
JDAPFilter filter = JDAPFilter.getFilter(m_filter);
if (filter == null)
return null;
seq.addElement(filter.getBERElement());
seq.addElement(m_parsedFilter.getBERElement());
BERSequence attr_type_list = new BERSequence();
if (m_attrs != null) {
for (int i = 0; i < m_attrs.length; i++) {
@ -196,6 +201,7 @@ public class JDAPSearchRequest extends JDAPBaseDNRequest
public String toString() {
String s = null;
if (m_attrs != null) {
s = "";
for (int i = 0; i < m_attrs.length; i++) {
if (i != 0)
s = s + "+";

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.controls;
@ -38,9 +38,8 @@ import netscape.ldap.*;
* <P>
*
* Typically, you use the <CODE>getResponseControls</CODE> method of
* the <CODE>LDAPConnection</CODE> object and the <CODE>parseResponse</CODE>
* method of the <CODE>LDAPPersistSearchControl</CODE> object to get
* an <CODE>LDAPEntryChangeControl</CODE> object.
* the <CODE>LDAPConnection</CODE> object to get any
* <CODE>LDAPEntryChangeControl</CODE> objects returned by the server.
* <P>
*
* Once you retrieve an <CODE>LDAPEntryChangeControl</CODE> object from
@ -64,18 +63,68 @@ public class LDAPEntryChangeControl extends LDAPControl {
/**
* Constructs a new <CODE>LDAPEntryChangeControl</CODE> object.
* Call the <CODE>parseResponse</CODE> method of the
* <CODE>LDAPPersistSearchControl</CODE> object to retrieve the
* actual "entry change notification" control from the server.
*
* @see netscape.ldap.LDAPControl
* @see netscape.ldap.controls.LDAPPersistSearchControl
*/
public LDAPEntryChangeControl()
{
public LDAPEntryChangeControl() {
super(ENTRYCHANGED, false, null);
}
/**
* Contructs an <CODE>LDAPEntryChangedControl</CODE> object.
* This constructor is used by <CODE>LDAPControl.register</CODE> to
* instantiate entry change controls.
* @param oid This parameter must be
* <CODE>LDAPEntryChangeControl.ENTRYCHANGED</CODE>
* or a <CODE>LDAPException</CODE> is thrown.
* @param critical True if this control is critical.
* @param value The value associated with this control.
* @exception netscape.ldap.LDAPException If oid is not
* <CODE>LDAPEntryChangeControl.ENTRYCHANGED</CODE>.
* @exception java.io.IOException If value is not a valid BER sequence.
* @see netscape.ldap.LDAPControl#register
*/
public LDAPEntryChangeControl(String oid, boolean critical, byte[] value)
throws LDAPException, IOException {
super(ENTRYCHANGED, false, value);
if (!oid.equals( ENTRYCHANGED )) {
throw new LDAPException("oid must be LDAPEntryChangeControl." +
"ENTRYCHANGED", LDAPException.PARAM_ERROR);
}
ByteArrayInputStream inStream = new ByteArrayInputStream(m_value);
BERSequence seq = new BERSequence();
JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
int[] numRead = new int[1];
numRead[0] = 0;
BERSequence s = (BERSequence)BERElement.getElement(decoder, inStream,
numRead);
BEREnumerated enum = (BEREnumerated)s.elementAt(0);
m_changeTypes = enum.getValue();
if (s.size() > 1) {
if (s.elementAt(1) instanceof BEROctetString) {
BEROctetString str = (BEROctetString)s.elementAt(1);
try {
m_previousDN = new String(str.getValue(), "UTF8");
} catch (UnsupportedEncodingException e) {
}
} else if (s.elementAt(1) instanceof BERInteger) {
BERInteger num = (BERInteger)s.elementAt(1);
m_changeNumber = num.getValue();
}
}
if (s.size() > 2) {
BERInteger num = (BERInteger)s.elementAt(2);
m_changeNumber = num.getValue();
}
}
/**
* Sets the change number (which identifies the record of the change
* in the server's change log) in this "entry change notification"
@ -166,9 +215,30 @@ public class LDAPEntryChangeControl extends LDAPControl {
return m_previousDN;
}
public String toString() {
StringBuffer sb = new StringBuffer("{EntryChangedCtrl:");
sb.append(" isCritical=");
sb.append(isCritical());
sb.append(" changeTypes=");
sb.append(LDAPPersistSearchControl.typesToString(m_changeTypes));
sb.append(" previousDN=");
sb.append(m_previousDN);
sb.append(" changeNumber=");
sb.append(m_changeNumber);
sb.append("}");
return sb.toString();
}
private int m_changeNumber = -1;
private int m_changeTypes = -1;
private String m_previousDN = null;
public final static String ENTRYCHANGED = "2.16.840.1.113730.3.4.7";
}

View File

@ -12,12 +12,13 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.controls;
import netscape.ldap.LDAPControl;
import netscape.ldap.LDAPException;
/**
* Represents an LDAP v3 server control that may be returned if a
@ -30,6 +31,32 @@ import netscape.ldap.LDAPControl;
*/
public class LDAPPasswordExpiredControl extends LDAPStringControl {
public final static String EXPIRED = "2.16.840.1.113730.3.4.4";
/**
* Contructs an <CODE>LDAPPasswordExpiredControl</CODE> object.
* This constructor is used by <CODE>LDAPControl.register</CODE> to
* instantiate password expired controls.
* <P>
* To retrieve the message from the server, call <CODE>getMessage</CODE>.
* @param oid This parameter must be equal to
* <CODE>LDAPPasswordExpiredControl.EXPIRED</CODE>
* or a <CODE>LDAPException</CODE> is thrown.
* @param critical True if this control is critical.
* @param value The value associated with this control.
* @exception netscape.ldap.LDAPException If oid is not
* <CODE>LDAPPasswordExpiredControl.EXPIRED</CODE>.
* @see netscape.ldap.LDAPControl#register
*/
public LDAPPasswordExpiredControl( String oid, boolean critical,
byte[] value ) throws LDAPException {
super( EXPIRED, critical, value );
if ( !oid.equals( EXPIRED )) {
throw new LDAPException( "oid must be LDAPPasswordExpiredControl." +
"PWEXPIRED", LDAPException.PARAM_ERROR);
}
}
/**
* @param controls An array of <CODE>LDAPControl</CODE> objects,
* representing the controls returned by the server
@ -37,9 +64,23 @@ public class LDAPPasswordExpiredControl extends LDAPStringControl {
* <CODE>getResponseControls</CODE> method of the
* <CODE>LDAPConnection</CODE> class.
* @return An error message string, or null if none is in the control.
* @see netscape.ldap.LDAPConnection#getResponseControls
* @see netscape.ldap.LDAPConnection#getResponseControls
* @deprecated LDAPPasswordExpiredControl controls are now automatically
* instantiated.
*/
public static String parseResponse( LDAPControl[] controls ) {
return LDAPStringControl.parseResponse( controls, EXPIRED );
}
/**
* Gets the message returned by the server with this control
* @return The message returned by the server
*/
public String getMessage() {
return m_msg;
}
}

View File

@ -12,12 +12,13 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.controls;
import netscape.ldap.LDAPControl;
import netscape.ldap.LDAPException;
/**
* Represents an LDAP v3 server control that may be returned if a
@ -30,6 +31,52 @@ import netscape.ldap.LDAPControl;
*/
public class LDAPPasswordExpiringControl extends LDAPStringControl {
public final static String EXPIRING = "2.16.840.1.113730.3.4.5";
/**
* Contructs an <CODE>LDAPPasswordExpiringControl</CODE> object.
* This constructor is used by <CODE>LDAPControl.register</CODE> to
* instantiate password expiring controls.
* <P>
* To retrieve the number of seconds until this password expires,
* call <CODE>getSecondsToExpiration</CODE>.
* @param oid This parameter must be
* <CODE>LDAPPasswordExpiringControl.EXPIRING</CODE>
* or an <CODE>LDAPException</CODE> is thrown.
* @param critical True if this control is critical.
* @param value The value associated with this control.
* @exception netscape.ldap.LDAPException If oid is not
* <CODE>LDAPPasswordExpiringControl.EXPIRING.</CODE>
* @see netscape.ldap.LDAPControl#register
*/
public LDAPPasswordExpiringControl( String oid, boolean critical,
byte[] value ) throws LDAPException {
super( EXPIRING, critical, value );
if ( !oid.equals( EXPIRING )) {
throw new LDAPException( "oid must be LDAPPasswordExpiringControl" +
".EXPIRING", LDAPException.PARAM_ERROR );
}
}
/**
* Gets the number of seconds until the password expires returned by the
* server.
* @return int The number of seconds until the password expires.
* @exception java.lang.NumberFormatException If the server returned an
* undecipherable message. In this case, use <CODE>getMessage</CODE> to
* retrieve the message as a string.
*/
public int getSecondsToExpiration() {
return Integer.parseInt( m_msg );
}
/**
* Gets the value associated with this control parsed as a string.
* @return The value associated with this control parsed as a string.
*/
public String getMessage() {
return m_msg;
}
/**
* @param controls An array of <CODE>LDAPControl</CODE> objects,
* representing the controls returned by the server
@ -37,7 +84,9 @@ public class LDAPPasswordExpiringControl extends LDAPStringControl {
* <CODE>getResponseControls</CODE> method of the
* <CODE>LDAPConnection</CODE> class.
* @return An error message string, or null if none is in the control.
* @see netscape.ldap.LDAPConnection#getResponseControls
* @see netscape.ldap.LDAPConnection#getResponseControls
* @deprecated LDAPPasswordExpiringControl controls are now automatically
* instantiated.
*/
public static String parseResponse( LDAPControl[] controls ) {
return LDAPStringControl.parseResponse( controls, EXPIRING );

View File

@ -151,6 +151,9 @@ public class LDAPPersistSearchControl extends LDAPControl {
super(PERSISTENTSEARCH, isCritical, null);
m_value = createPersistSearchSpecification(changeTypes,
changesOnly, returnControls);
m_changeTypes = changeTypes;
m_changesOnly = changesOnly;
m_returnECs = returnControls;
}
/**
@ -238,6 +241,8 @@ public class LDAPPersistSearchControl extends LDAPControl {
*
* @param c Byte array that contains BER elements.
* @return The entry change control.
* @deprecated LDAPEntryChangeControl controls are now automatically
* instantiated.
*/
public LDAPEntryChangeControl parseResponse(byte[] c) {
LDAPEntryChangeControl con = new LDAPEntryChangeControl();
@ -270,7 +275,7 @@ public class LDAPPersistSearchControl extends LDAPControl {
BERInteger num = (BERInteger)s.elementAt(2);
con.setChangeNumber(num.getValue());
}
} catch (Throwable e) {
} catch (Exception e) {
return null;
}
@ -306,8 +311,13 @@ public class LDAPPersistSearchControl extends LDAPControl {
* if ( returnedControls != null ) {
*
* // Get the entry change control.
* LDAPEntryChangeControl entryCtrl =
* persistCtrl.parseResponse( returnedControls );
* LDAPEntryChangeControl entryCtrl = null;
* for ( int i = 0; i < returnedControls.length; i++ ) {
* if ( returnedControls[i] instanceof LDAPEntryChangeControl ) {
* entryCtrl = (LDAPEntryChangeControl)returnedControls[i];
* break;
* }
* }
* if ( entryCtrl != null ) {
*
* // Get and print the type of change made to the entry.
@ -363,6 +373,8 @@ public class LDAPPersistSearchControl extends LDAPControl {
* control was sent, this method returns null.
* @see netscape.ldap.controls.LDAPEntryChangeControl
* @see netscape.ldap.LDAPConnection#getResponseControls
* @deprecated LDAPEntryChangeControl controls are now automatically
* instantiated.
*/
public static LDAPEntryChangeControl parseResponse(LDAPControl[] controls) {
@ -401,6 +413,48 @@ public class LDAPPersistSearchControl extends LDAPControl {
return flattenBER( seq );
}
public String toString() {
StringBuffer sb = new StringBuffer("{PersistSearchCtrl:");
sb.append(" isCritical=");
sb.append(isCritical());
sb.append(" returnEntryChangeCtrls=");
sb.append(m_returnECs);
sb.append(" changesOnly=");
sb.append(m_changesOnly);
sb.append(" changeTypes=");
sb.append(typesToString(m_changeTypes));
sb.append("}");
return sb.toString();
}
/**
* This method is also used by LDAPentryChangeControl.toString()
*/
static String typesToString(int changeTypes) {
String types = "";
if ((changeTypes & ADD) != 0) {
types += (types.length() > 0) ? "+ADD" : "ADD";
}
if ((changeTypes & DELETE) != 0) {
types += (types.length() > 0) ? "+DEL" : "DEL";
}
if ((changeTypes & MODIFY) != 0) {
types += (types.length() > 0) ? "+MOD" : "MOD";
}
if ((changeTypes & MODDN) != 0) {
types += (types.length() > 0) ? "+MODDN" : "MODDN";
}
return types;
}
private int m_changeTypes = 1;
private boolean m_changesOnly = false;
private boolean m_returnECs = false;

View File

@ -66,8 +66,9 @@ import netscape.ldap.ber.stream.*;
*
* @version 1.0
* @see netscape.ldap.LDAPControl
* @see netscape.ldap.LDAPConstraints
* @see netscape.ldap.LDAPSearchConstraints
* @see netscape.ldap.LDAPSearchConstraints#setServerControls(LDAPControl)
* @see netscape.ldap.LDAPConstraints#setServerControls(LDAPControl)
*/
public class LDAPProxiedAuthControl extends LDAPControl {
public final static String PROXIEDAUTHREQUEST =

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.controls;
@ -21,6 +21,7 @@ import java.io.*;
import netscape.ldap.LDAPControl;
import netscape.ldap.LDAPSortKey;
import netscape.ldap.client.JDAPBERTagDecoder;
import netscape.ldap.LDAPException;
import netscape.ldap.ber.stream.*;
/**
@ -90,7 +91,8 @@ import netscape.ldap.ber.stream.*;
* </UL>
* <P>
*
* To parse this control, use the <CODE>parseResponse</CODE> method.
* To retrieve the data from this control, use the <CODE>getResultCode</CODE>
* and <CODE>getFailedAttribute</CODE> methods.
* <P>
*
* The following table lists what kinds of results to expect from the
@ -206,13 +208,83 @@ import netscape.ldap.ber.stream.*;
* @version 1.0
* @see netscape.ldap.LDAPSortKey
* @see netscape.ldap.LDAPControl
* @see netscape.ldap.LDAPConstraints
* @see netscape.ldap.LDAPSearchConstraints
* @see netscape.ldap.LDAPSearchConstraints#setServerControls(LDAPControl)
* @see netscape.ldap.LDAPConstraints#setServerControls(LDAPControl)
*/
public class LDAPSortControl extends LDAPControl {
public final static String SORTREQUEST = "1.2.840.113556.1.4.473";
public final static String SORTRESPONSE = "1.2.840.113556.1.4.474";
private String m_failedAttribute = null;
private int m_resultCode = 0;
/**
* Constructs a sort response <CODE>LDAPSortControl</CODE> object.
* This constructor is used by <CODE>LDAPControl.register</CODE> to
* instantiate sort response controls.
* <P>
* To retrieve the result code of the sort operation, call
* <CODE>getResultCode</CODE>.
* <P>
* To retrieve the attribute that caused the sort operation to fail, call
* <CODE>getFailedAttribute</CODE>.
* @param oid The oid for this control. This must be
* <CODE>LDAPSortControl.SORTRESPONSE</CODE> or a <CODE>LDAPException</CODE>
* is thrown.
* @param critical True if this control is critical to the operation.
* @param value The value associated with this control.
* @exception netscape.ldap.LDAPException If oid is not
* <CODE>LDAPSortControl.SORTRESPONSE</CODE>.
* @exception java.io.IOException If value contains an invalid BER sequence.
* @see netscape.ldap.LDAPControl#register
*/
public LDAPSortControl( String oid, boolean critical, byte[] value )
throws LDAPException, IOException {
super( oid, critical, value );
if ( !oid.equals( SORTRESPONSE )) {
throw new LDAPException( "oid must be LDAPSortControl.SORTRESPONSE",
LDAPException.PARAM_ERROR);
}
ByteArrayInputStream inStream = new ByteArrayInputStream( value );
BERSequence ber = new BERSequence();
JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
int[] nRead = { 0 };
/* A sequence */
BERSequence seq = (BERSequence)BERElement.getElement(decoder, inStream,
nRead );
/* First is result code */
int m_resultCode = ((BEREnumerated)seq.elementAt( 0 )).getValue();
/* Then, possibly an attribute that failed sorting */
if(seq.size() == 1) {
return;
}
/* If this is not an octet string, let there be an exception */
BEROctetString t = (BEROctetString)seq.elementAt(1);
try {
m_failedAttribute = new String(t.getValue(), "UTF8");
} catch (UnsupportedEncodingException e) {
}
}
/**
* @return The attribute that caused the sort operation to fail.
*/
public String getFailedAttribute() {
return m_failedAttribute;
}
/**
* @return The result code from the search operation.
*/
public int getResultCode() {
return m_resultCode;
}
/**
* Constructs an <CODE>LDAPSortControl</CODE> object with a single
* sorting key.
@ -418,6 +490,8 @@ public class LDAPSortControl extends LDAPControl {
* @return The attribute that caused the error, or null if the server did
* not specify which attribute caused the error.
* @see netscape.ldap.LDAPConnection#getResponseControls
* @deprecated LDAPSortControl response controls are now automatically
* instantiated.
*/
public static String parseResponse( LDAPControl[] controls, int[] results ) {
String attr = null;
@ -450,7 +524,7 @@ public class LDAPSortControl extends LDAPControl {
/* If this is not an octet string, let there be an exception */
BEROctetString t = (BEROctetString)seq.elementAt(1);
attr = new String(t.getValue(), "UTF8");
} catch(Throwable x) {
} catch(Exception x) {
}
}
return attr;
@ -487,5 +561,13 @@ public class LDAPSortControl extends LDAPControl {
/* Suck out the data and return it */
return flattenBER( ber );
}
// register SORTRESPONSE with LDAPControl
static {
try {
LDAPControl.register( SORTRESPONSE, LDAPSortControl.class );
} catch (LDAPException e) {
}
}
}

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.controls;
@ -24,6 +24,32 @@ import netscape.ldap.LDAPControl;
* only value. This is to be used as a base class by real such controls.
*/
abstract class LDAPStringControl extends LDAPControl {
protected String m_msg = null;
LDAPStringControl() {
super();
}
/**
* Constructs a <CODE>LDAPStringControl</CODE> object, and stores the
* value as a string. To retrieve this string value, use
* <CODE>getMsg()</CODE>.
* @param oid The oid of defining this control.
* @param critical True if this control is critical.
* @param value The value associated with this control.
* @see netscape.ldap.LDAPcontrol
*/
public LDAPStringControl( String oid, boolean critical, byte[] value ) {
super( oid, critical, value );
if ( value != null ) {
try {
m_msg = new String( value, "UTF8" );
} catch ( java.io.IOException e ) {
}
}
}
/**
* Parses a response control sent by the server and
* retrieves a string.

View File

@ -141,8 +141,13 @@ import netscape.ldap.ber.stream.*;
*
* // Check if we have a control returned
* LDAPControl[] c = _ldc.getResponseControls();
* LDAPVirtualListResponse nextCont =
* LDAPVirtualListResponse.parseResponse( c );
* LDAPVirtualListResponse nextCont = null;
* for ( int i = 0; i < c.length; i++ ) {
* if ( c[i] instanceof LDAPVirtualListResponse ) {
* nextCont = (LDAPVirtualListResponse)c[i];
* break;
* }
* }
* if ( nextCont != null ) {
* _selectedIndex = nextCont.getFirstPosition() - 1;
* _top = Math.max( 0, _selectedIndex - _beforeCount );
@ -197,14 +202,18 @@ import netscape.ldap.ber.stream.*;
*}
*</CODE></PRE>
* <PRE>
* VirtualListViewRequest ::= SEQUENCE {
* beforeCount INTEGER,
* afterCount INTEGER,
* CHOICE {
* byIndex [0] SEQUENCE {
* index INTEGER,
* contentCount INTEGER }
* byFilter [1] jumpTo Substring }
* VirtualListViewRequest ::= SEQUENCE {
* beforeCount INTEGER (0 .. maxInt),
* afterCount INTEGER (0 .. maxInt),
* CHOICE {
* byIndex [0] SEQUENCE {
* index INTEGER,
* contentCount INTEGER
* }
* byFilter [1] jumpTo Substring
* },
* contextID OCTET STRING OPTIONAL
* }
* </PRE>
*
* @version 1.0
@ -238,6 +247,12 @@ public class LDAPVirtualListControl extends LDAPControl {
setRange( jumpTo, beforeCount, afterCount );
}
public LDAPVirtualListControl( String jumpTo, int beforeCount,
int afterCount, String context ) {
this( jumpTo, beforeCount, afterCount );
m_context = context;
}
/**
* Constructs a new <CODE>LDAPVirtualListControl</CODE> object. Use this
* constructor on a subsquent search operation, after we know the
@ -257,6 +272,13 @@ public class LDAPVirtualListControl extends LDAPControl {
setRange( startIndex, beforeCount, afterCount );
}
public LDAPVirtualListControl( int startIndex, int beforeCount,
int afterCount, int contentCount,
String context ) {
this( startIndex, beforeCount, afterCount, contentCount );
m_context = context;
}
/**
* Sets the starting index, and the number of entries before and after
* to return. Apply this method to a control returned from a previous
@ -334,6 +356,22 @@ public class LDAPVirtualListControl extends LDAPControl {
return m_afterCount;
}
/**
* Gets the optional context cookie
* @return The optional context cookie
*/
public String getContext() {
return m_context;
}
/**
* Sets the optional context cookie
* @param context The optional context cookie
*/
public void setContext( String context ) {
m_context = context;
}
/**
* Creates a "flattened" BER encoding of the requested page
* specifications and return it as a byte array.
@ -351,6 +389,9 @@ public class LDAPVirtualListControl extends LDAPControl {
seq.addElement( new BERInteger( afterCount ) );
seq.addElement( new BERTag(BERTag.CONTEXT|TAG_BYFILTER,
new BEROctetString(subFilter), true) );
if ( m_context != null ) {
seq.addElement( new BEROctetString(m_context) );
}
/* Suck out the data and return it */
return flattenBER( seq );
}
@ -379,6 +420,9 @@ public class LDAPVirtualListControl extends LDAPControl {
seq.addElement(
new BERTag(BERTag.CONTEXT|BERTag.CONSTRUCTED|TAG_BYINDEX,
indexSeq,true) );
if ( m_context != null ) {
seq.addElement( new BEROctetString(m_context) );
}
/* Suck out the data and return it */
return flattenBER( seq );
@ -390,4 +434,5 @@ public class LDAPVirtualListControl extends LDAPControl {
private int m_afterCount = 0;
private int m_listIndex = -1;
private int m_listSize = 0;
private String m_context = null;
}

View File

@ -12,7 +12,7 @@
*
* 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
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
package netscape.ldap.controls;
@ -21,6 +21,7 @@ import java.io.*;
import netscape.ldap.client.JDAPBERTagDecoder;
import netscape.ldap.LDAPControl;
import netscape.ldap.ber.stream.*;
import netscape.ldap.LDAPException;
/**
* Represents control data for returning paged results from a search.
@ -28,21 +29,23 @@ import netscape.ldap.ber.stream.*;
* @version 1.0
*
*<PRE>
* VirtualListViewResponse ::= SEQUENCE {
* firstPosition INTEGER,
* contentCount INTEGER,
* virtualListViewResult ENUMERATED {
* success (0),
* unwillingToPerform (53),
* insufficientAccessRights (50),
* operationsError (1),
* busy (51),
* timeLimitExceeded (3),
* adminLimitExceeded (11),
* sortControlMissing (60),
* indexRangeError (?),
* }
* }
* VirtualListViewResponse ::= SEQUENCE {
* targetPosition INTEGER (0 .. maxInt),
* contentCount INTEGER (0 .. maxInt),
* virtualListViewResult ENUMERATED {
* success (0),
* operatonsError (1),
* timeLimitExceeded (3),
* adminLimitExceeded (11),
* insufficientAccessRights (50),
* busy (51),
* unwillingToPerform (53),
* sortControlMissing (60),
* offsetRangeError (61),
* other (80)
* },
* contextID OCTET STRING OPTIONAL
* }
*</PRE>
*/
@ -57,6 +60,29 @@ public class LDAPVirtualListResponse extends LDAPControl {
super( VIRTUALLISTRESPONSE, true, null );
}
/**
* Contructs an <CODE>LDAPVirtualListResponse</CODE> object.
* @param oid This parameter must be equal to
* <CODE>LDAPVirtualListResponse.VIRTUALLISTRESPONSE</CODE> or a
* <CODE>LDAPException</CODE>is thrown.
* @param critical True if this control is critical.
* @param value The value associated with this control.
* @exception netscape.ldap.LDAPException If oid is not
* <CODE>LDAPVirtualListResponse.VIRTUALLISTRESPONSE</CODE>.
* @see netscape.ldap.LDAPControl#register
*/
public LDAPVirtualListResponse( String oid, boolean critical,
byte[] value ) throws LDAPException {
super( VIRTUALLISTRESPONSE, critical, value );
if ( !oid.equals( VIRTUALLISTRESPONSE ) ) {
throw new LDAPException( "oid must be LDAPVirtualListResponse." +
"VIRTUALLISTRESPONSE",
LDAPException.PARAM_ERROR);
}
parseResponse();
}
/**
* Constructs a new <CODE>LDAPVirtualListResponse</CODE> object.
* @param value A BER encoded byte array.
@ -92,6 +118,14 @@ public class LDAPVirtualListResponse extends LDAPControl {
return m_resultCode;
}
/**
* Gets the context cookie, if any.
* @return The result context cookie.
*/
public String getContext() {
return m_context;
}
/**
* Returns a control useful for subsequent paged results searches.
* "this" should be a control returned on a previous paged results
@ -115,11 +149,14 @@ public class LDAPVirtualListResponse extends LDAPControl {
/* First is firstPosition */
m_firstPosition = ((BERInteger)seq.elementAt( 0 )).getValue();
m_contentCount = ((BERInteger)seq.elementAt( 1 )).getValue();
BEREnumerated enum = (BEREnumerated)seq.elementAt( 2 );
m_resultCode = enum.getValue();
} catch(Throwable x) {
m_resultCode = ((BEREnumerated)seq.elementAt( 2 )).getValue();
if( seq.size() > 3 ) {
BEROctetString str = (BEROctetString)seq.elementAt( 3 );
m_context = new String(str.getValue(), "UTF8");
}
} catch(Exception x) {
m_firstPosition = m_contentCount = m_resultCode = -1;
}
m_context = null; }
}
/**
@ -127,6 +164,8 @@ public class LDAPVirtualListResponse extends LDAPControl {
* @param controls An array of controls that may include a VLV
* results control.
* @return The control, if any; otherwise null.
* @deprecated LDAPVirtualListResponse controls are now automatically
* instantiated.
*/
public static LDAPVirtualListResponse parseResponse(
LDAPControl[] controls ) {
@ -148,4 +187,6 @@ public class LDAPVirtualListResponse extends LDAPControl {
private int m_firstPosition = 0;
private int m_contentCount = 0;
private int m_resultCode = -1;
private String m_context = null;
}

Some files were not shown because too many files have changed in this diff Show More