Compare commits

..

1 Commits

Author SHA1 Message Date
(no author)
aa69c86c42 This commit was manufactured by cvs2svn to create tag 'LDAPJavaSDK_41'.
git-svn-id: svn://10.0.0.236/tags/LDAPJavaSDK_41@68710 18797224-902f-48f8-a5cc-f745e15eee43
2000-05-08 20:58:50 +00:00
264 changed files with 53493 additions and 2519 deletions

View File

@@ -0,0 +1,208 @@
======================================================================
NETSCAPE DIRECTORY SDK FOR JAVA:
BUILD INSTRUCTIONS
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 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/.)
Unix/Linux Build Instructions
-----------------------------
System Requirements:
32MB of RAM, 128MB of swap, recommended 64MB of RAM.
Tool Requirements:
Sun Microsystems Java Development Kit (JDK) 1.1.7
(or a more recent version)
GNU make 3.74 or a more recent version
Instructions:
1. Uncompress and extract the source files by entering the
following command (or your preferred variant of this command):
gzip -dc <filename>.tar.gz | tar -xvf -
2. Set and unset the following environment variables.
In csh/tcsh:
setenv JAVA_HOME "<directory where the JDK is installed>"
For example:
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.7/lib/classes.zip"
In sh/bash/ksh:
JAVA_HOME="<directory where the JDK is installed>"
CLASSPATH="<location of the JDK classes.zip file>"
export JAVA_HOME CLASSPATH
3. Build the LDAP Java classes by entering the following commands:
cd mozilla/directory/java-sdk
gmake -f ldap.mk
If you also want the classes packaged in a JAR file,
specify "basepackage" as the target:
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:
gmake -f ldapsp.mk
If you also want the classes packaged in a JAR file,
specify "basepackage" as the target:
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
ldapsp/Readme.html and http://java.sun.com/products/jndi/index.html
Windows Build Instructions
--------------------------
System Requirements:
Windows NT 3.51 or 4.0 (4.0 preferred).
Tool Requirements:
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:
cp.exe
rm.exe
Here are some sample download sites to find these:
Cygnus (http://www.cygnus.com/misc/gnu-win32)
GNU (http://www.gnu.org/order/ftp.html)
MIT (ftp://prep.ai.mit.edu/pub/gnu)
Netscape uses internally modified versions of the following tools:
gmake.exe
shmsdos.exe
uname.exe
You can download them from http://www.mozilla.org/download-mozilla.html
(click the Windows Build Tools link). When you unzip the file, the
tools will be located in the windows\bin\x86 directory.
All of these tools need to be put in your path.
Extracting the Source Files:
The source files for the Directory SDK are zipped in a file.
When unzipping the file, make sure to specify that you want to
preserve the directory structure. For example,
make sure that "Use Folder Names" is checked.
Instructions:
NOTE: Make sure to run the commands from a standard Windows NT
command prompt. Although you may be able to use other shells
to build the SDK, you may need to adjust the makefiles for
the shell that you are using.
1. Set the following environment variables (within the command session,
either manually or via a script), or within the system environment
through the Control Panel | System control panel):
set MOZ_SRC=(top of your source tree, drive letter and path.
For example, set MOZ_SRC=d:\mozilla_src, if the mozilla
directory is at d:\mozilla_src\mozilla.)
set JAVA_HOME=(directory where the JDK is installed)
For example:
set JAVA_HOME=D:\jdk1.1.7
set CLASSPATH=(location of the JDK classes.zip file)
For example:
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.
2. Enter the following commands to build the LDAP Java classes:
cd mozilla\directory\java-sdk
gmake -f ldap.mk
If you also want the classes packaged in a JAR file,
specify "basepackage" as the target:
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:
gmake -f ldapsp.mk
If you also want the classes packaged in a JAR file,
specify "basepackage" as the target:
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
ldapsp/Readme.html and http://java.sun.com/products/jndi/index.html
--------------------------------------------------------
Copyright (c) 1999 Netscape Communications Corporation.
(http://home.netscape.com/misc/contact_info.html)

View File

@@ -0,0 +1,248 @@
# -*- 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.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1999 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
# Makefile for the LDAP classes
#
# 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
# FACTORY
# 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=.
ifeq ($(ARCH), WINNT)
MOZ_DIR:=$(subst \,/,$(MOZ_SRC))
BASEDIR:=$(MOZ_DIR)/mozilla/directory/java-sdk
else
ifeq ($(ARCH), WIN95)
MOZ_DIR:=$(subst \,/,$(MOZ_SRC))
BASEDIR:=$(MOZ_DIR)/mozilla/directory/java-sdk
else
BASEDIR := $(shell cd $(MCOM_ROOT); pwd)
endif
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)
JDK := $(subst \,/,$(JAVA_HOME))
JAR:=$(JDK)/bin/jar
SEP=;
else
ifeq ($(ARCH), WIN95)
JDK := $(subst \,/,$(JAVA_HOME))
JAR:=$(JDK)/bin/jar
SEP=;
else
JDK := $(JAVA_HOME)
JAR:=$(JAVA_HOME)/bin/jar
SEP=:
endif
endif
JAASLIB=$(BASEDIR)/ldapjdk/lib/jaas.jar
JSSELIB=$(BASEDIR)/ldapjdk/lib/jnet.jar$(SEP)$(BASEDIR)/ldapjdk/lib/jsse.jar
JAVACLASSPATH:=$(BASEDIR)/ldapjdk$(SEP)$(JAASLIB)$(SEP)$(JSSELIB)$(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)
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/
endif
ifeq ($(DEBUG), 1)
JAVAC=$(JDKBIN)javac -g -classpath "$(JAVACLASSPATH)"
else
JAVAC=$(JDKBIN)javac -O -classpath "$(JAVACLASSPATH)"
endif
endif
BERDOCCLASSES=netscape.ldap.ber.stream
SASLDOCCLASSES=com.netscape.sasl com.netscape.sasl.mechanisms
DOCCLASSES=netscape.ldap netscape.ldap.beans netscape.ldap.controls \
netscape.ldap.util netscape.ldap.factory \
$(SASLDOCCLASSES) $(TOOLSDIR)/*.java $(BERDOCCLASSES)
all: classes
basics: $(DISTDIR) $(CLASSDIR)
classes: LDAPCLASSES BEANS
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) cvf ../packages/$(BASEPACKAGENAME) netscape/ldap/*.class netscape/ldap/client/*.class netscape/ldap/client/opers/*.class netscape/ldap/ber/stream/*.class netscape/ldap/controls/*.class netscape/ldap/factory/*.class netscape/ldap/util/*.class netscape/ldap/errors/*.props com/netscape/sasl/*.class com/netscape/sasl/mechanisms/*.class *.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
FACTORY: basics
cd ldapjdk/$(SRCDIR)/factory; $(JAVAC) -d "$(CLASS_DEST)" *.java
CLIENT: basics
cd ldapjdk/$(SRCDIR)/client; $(JAVAC) -d "$(CLASS_DEST)" *.java
OPERS: basics
cd ldapjdk/$(SRCDIR)/client/opers; $(JAVAC) -d "$(CLASS_DEST)" *.java
BER: basics
cd ldapjdk/$(SRCDIR)/ber/stream; $(JAVAC) -d "$(CLASS_DEST)" *.java
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
ERRORS: basics $(ERRORSDIR)
cp -p ldapjdk/$(SRCDIR)/errors/*.props $(ERRORSDIR)
CONTROLS: basics
cd ldapjdk/$(SRCDIR)/controls; $(JAVAC) -d "$(CLASS_DEST)" *.java
LDAPCLASSES: BER OPERS CLIENT MAIN FACTORY UTIL CONTROLS ERRORS SASL SASLMECHANISM TOOLS
BEANS: OTHERBEANS
OTHERBEANS: basics
cd ldapbeans/$(SRCDIR)/beans; $(JAVAC) -d "$(CLASS_DEST)" *.java
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 $@
$(DOCDIR):
mkdir -p $@
$(DISTDIR):
mkdir -p $@
$(CLASSDIR):
mkdir -p $@
$(ERRORSDIR):
mkdir -p $@
$(FILTERCLASSDIR):
mkdir -p $@

View File

@@ -0,0 +1,71 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.beans;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.Serializable;
public class DisplayString extends TextArea implements Serializable {
public DisplayString() {
super();
setEditable(false);
}
public void reportChange(PropertyChangeEvent evt) {
Object obj = (Object)evt.getNewValue();
if (obj == null) {
append("null\n");
return;
}
String[] values = null;
if (obj instanceof String) {
values = new String[1];
values[0] = (String)obj;
}
else
values = (String[])obj;
int width = getSize().width - 10;
Font f = getFont();
for (int i=0; i<values.length; i++) {
String text = values[i];
if (f != null) {
// Trim the text to fit.
FontMetrics fm = getFontMetrics(f);
while (fm.stringWidth(text) > width) {
text = text.substring(0, text.length()-1);
}
}
append(text+'\n');
}
}
public void clear (ActionEvent e) {
setText("");
invalidate();
repaint();
}
}

View File

@@ -0,0 +1,4 @@
Name: netscape/ldap/beans/DisplayString.class
Java-Bean: True
Name: netscape/ldap/beans/DisplayStringBeanInfo.class

View File

@@ -0,0 +1,67 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.beans;
import java.beans.SimpleBeanInfo;
import java.beans.BeanDescriptor;
import java.beans.EventSetDescriptor;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.beans.ParameterDescriptor;
import java.beans.BeanInfo;
/**
* BeanInfo for displaying string
*
*/
public class DisplayStringBeanInfo extends SimpleBeanInfo {
public DisplayStringBeanInfo() throws Exception {
beanClass = Class.forName( "netscape.ldap.beans.DisplayString" );
// Publish descriptor ---------------------------------------------
try {
_beanDescriptor = new BeanDescriptor(beanClass);
_beanDescriptor.setDisplayName( "Text Field" );
_beanDescriptor.setShortDescription(
"LDAP property retrieval -"
+ " provided a host, port, base, search filter,"
+ " and optionally a username and password,"
+ " return an array of string values both as a"
+ " function return and as a Property change event." );
} catch (Exception e) {
}
}
public BeanDescriptor getBeanDescriptor() {
return _beanDescriptor;
}
private static Class beanClass;
private BeanDescriptor _beanDescriptor;
private EventSetDescriptor[] _eventSetDescriptor;
private PropertyDescriptor[] _propertyDescriptor;
}

View File

@@ -0,0 +1,395 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.beans;
import netscape.ldap.*;
import java.util.StringTokenizer;
// This class has a bound property
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
/**
* This is a base class that is extended by various specialized LDAP
* Beans. It provides the common properties and accessors used by
* them.
*/
public class LDAPBasePropertySupport implements Serializable {
/**
* Constructor with no parameters
*/
public LDAPBasePropertySupport() {}
/**
* Returns the host to search at.
* @return DNS name or dotted IP name of host to search at
*/
public String getHost() {
return _host;
}
/**
* Sets host string.
* @param theHost host name
*/
public void setHost( String theHost ) {
_host = theHost;
}
/**
* Returns the port to search at.
* @return Port to search at
*/
public int getPort() {
return _port;
}
/**
* Sets port number.
* @param thePort port
*/
public void setPort( int thePort ) {
_port = thePort;
}
/**
* Returns the directory base to search at.
* @return directory base to search
*/
public String getBase() {
return _base;
}
/**
* Sets the starting base
* @param theBase starting base
*/
public void setBase( String theBase ) {
_base = theBase;
}
/**
* Returns the DN to authenticate as; null or empty for anonymous.
* @return DN to authenticate as
*/
public String getAuthDN() {
return _authDN;
}
/**
* Sets the DN to authenticate as; null or empty for anonymous.
* @param authDN the DN to authenticate as
*/
public void setAuthDN( String authDN ) {
this._authDN = authDN;
}
/**
* Returns the password for the DN to authenticate as
* @return Password of DN to authenticate as
*/
public String getAuthPassword() {
return _authPassword;
}
/**
* Sets the password for the DN to authenticate as
* @param authPassword the password to use in authentication
*/
public void setAuthPassword( String authPassword ) {
this._authPassword = authPassword;
}
/**
* Returns the user name
* @return The user name
*/
public String getUserName() {
return _userName;
}
/**
* Set the user name. The name should be of the form "Polly Plum".
* @param name The user name
*/
public void setUserName( String name ) {
_userName = name;
}
/**
* Return the user ID.
* @return name the user id
*/
public String getUserID() {
return _userID;
}
/**
* Set the user ID.
* @param name the value of the user id
*/
public void setUserID( String name ) {
_userID = name;
}
/**
* Get the current search scope
* @return the current search scope as integer
*/
public int getScope() {
return _scope;
}
/**
* Set the search scope using an integer
* @param scope one of LDAPConnection.SCOPE_BASE,
* LDAPConnection.SCOPE_SUB, LDAPConnection.SCOPE_ONE
*/
public void setScope( int scope ) {
_scope = scope;
}
/**
* Returns the search filter
* @return search filter
*/
public String getFilter() {
return _filter;
}
/**
* Sets the search filter
* @param filter search filter
*/
public void setFilter( String filter ) {
_filter = filter;
}
/**
* Returns true if debug output is on
* @return true if debug output is on
*/
public boolean getDebug() {
return _debug;
}
/**
* Turns debug output on or off
* @param on true for debug output
*/
public void setDebug( boolean on ) {
_debug = on;
}
/**
* Returns the latest error code
* @return The latest error code
*/
public int getErrorCode() {
return _errCode;
}
/**
* Sets an error code for retrieval by a client
* @param code An error code
*/
public void setErrorCode( int code ) {
_errCode = code;
}
/**
* Add a client to be notified when an authentication result is in
* @param listener a client to be notified of changes
*/
public void addPropertyChangeListener( PropertyChangeListener listener ) {
printDebug( "Adding listener " + listener );
m_propSupport.addPropertyChangeListener( listener );
}
/**
* Remove a client which had requested notification on authentication
* @param listener a client to not be notified of changes
*/
public void removePropertyChangeListener(
PropertyChangeListener listener ) {
m_propSupport.removePropertyChangeListener( listener );
}
/**
* Support for bound property notification
* @param propName Name of changed property
* @param oldValue Previous value of property
* @param newValue New value of property
*/
public void firePropertyChange(
String propName,
Object oldValue,
Object newValue ) {
if (m_propSupport == null)
m_propSupport = new PropertyChangeSupport( this );
m_propSupport.firePropertyChange( propName, oldValue, newValue );
}
protected void printDebug( String s ) {
if ( _debug )
System.out.println( s );
}
/**
* Sets up basic connection privileges for Communicator if necessary,
* and connects
* @param host Host to connect to.
* @param port Port number.
* @exception LDAPException from connect()
*/
protected void connect( LDAPConnection conn, String host, int port )
throws LDAPException {
boolean needsPrivileges = true;
/* Running standalone? */
SecurityManager sec = System.getSecurityManager();
printDebug( "Security manager = " + sec );
if ( sec == null ) {
printDebug( "No security manager" );
/* Not an applet, we can do what we want to */
needsPrivileges = false;
/* Can't do instanceof on an abstract class */
} else if ( sec.toString().startsWith("java.lang.NullSecurityManager") ) {
printDebug( "No security manager" );
/* Not an applet, we can do what we want to */
needsPrivileges = false;
} else if ( sec.toString().startsWith(
"netscape.security.AppletSecurity" ) ) {
/* Connecting to the local host? */
try {
if ( host.equalsIgnoreCase(
java.net.InetAddress.getLocalHost().getHostName() ) )
needsPrivileges = false;
} catch ( java.net.UnknownHostException e ) {
}
}
if ( needsPrivileges ) {
/* Running as applet. Is PrivilegeManager around? */
String mgr = "netscape.security.PrivilegeManager";
try {
Class c = Class.forName( mgr );
java.lang.reflect.Method[] m = c.getMethods();
if ( m != null ) {
for( int i = 0; i < m.length; i++ ) {
if ( m[i].getName().equals( "enablePrivilege" ) ) {
try {
Object[] args = new Object[1];
args[0] = new String( "UniversalConnect" );
m[i].invoke( null, args );
printDebug( "UniversalConnect enabled" );
args[0] = new String( "UniversalPropertyRead" );
m[i].invoke( null, args );
printDebug( "UniversalPropertyRead enabled" );
} catch ( Exception e ) {
printDebug( "Exception on invoking " +
"enablePrivilege: " +
e.toString() );
break;
}
break;
}
}
}
} catch ( ClassNotFoundException e ) {
printDebug( "no " + mgr );
}
}
conn.connect( host, port );
setDefaultReferralCredentials( conn );
}
protected void setDefaultReferralCredentials(
LDAPConnection conn ) {
final LDAPConnection m_conn = conn;
LDAPRebind rebind = new LDAPRebind() {
public LDAPRebindAuth getRebindAuthentication(
String host,
int port ) {
return new LDAPRebindAuth(
m_conn.getAuthenticationDN(),
m_conn.getAuthenticationPassword() );
}
};
try {
conn.setOption(LDAPConnection.REFERRALS, Boolean.TRUE);
conn.setOption(LDAPConnection.REFERRALS_REBIND_PROC, rebind);
} catch (LDAPException e) {
//will never happen
}
}
/**
* Utility method to convert an array of Strings to a single String
* with line feeds between elements.
* @param aResult The array of Strings to convert
* @return A String with the elements separated by line feeds
*/
public String convertToString( String[] aResult ) {
String sResult = "";
if ( null != aResult ) {
for ( int i = 0; i < aResult.length; i++ ) {
sResult += aResult[i] + "\n";
}
}
return sResult;
}
/*
* Variables
*/
/* Error codes from search operations, etc */
public static final int OK = 0;
public static final int INVALID_PARAMETER = 1;
public static final int CONNECT_ERROR = 2;
public static final int AUTHENTICATION_ERROR = 3;
public static final int PROPERTY_NOT_FOUND = 4;
public static final int AMBIGUOUS_RESULTS = 5;
public static final int NO_SUCH_OBJECT = 6;
private boolean _debug = false;
private int _errCode = 0;
private String _host = new String("localhost");
private int _port = 389;
private int _scope = LDAPConnection.SCOPE_SUB;
private String _base = new String("");
private String _filter = new String("");
private String _authDN = new String("");
private String _authPassword = new String("");
private String _userName = new String("");
private String _userID = new String("");
transient private PropertyChangeSupport m_propSupport =
new PropertyChangeSupport( this );
}

View File

@@ -0,0 +1,362 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.beans;
import netscape.ldap.*;
import netscape.ldap.beans.LDAPBasePropertySupport;
import java.util.Enumeration;
import java.util.Vector;
import java.io.Serializable;
import java.awt.event.*;
/**
* Invisible Bean that just takes a host, port, directory base,
* search string, and optional authentication name and password,
* and returns a list of all matching DNs. The search has the scope
* "SUB", which means that it will find an entry anywhere at or
* below the directory base, unless a different scope is specified.
* <BR><BR>
* Optionally, a client can register as a PropertyChangeListener
* and will be notified when the values are available.
*<BR><BR>
* A null result means no matching DNs were found. The reason is
* available through getErrorCode(), which returns one of
* the following:
*<PRE>
* OK
* INVALID_PARAMETER
* CONNECT_ERROR
* AUTHENTICATION_ERROR
* PROPERTY_NOT_FOUND
* AMBIGUOUS_RESULTS
*</PRE>
*
*/
public class LDAPGetEntries extends LDAPBasePropertySupport implements Serializable {
/**
* Constructor with no parameters
*/
public LDAPGetEntries() {
super();
}
/**
* Constructor with host, port, and base initializers
* @param theHost host string
* @param thePort port number
* @param theBase directory base string
*/
public LDAPGetEntries( String theHost, int thePort, String theBase ) {
setHost( theHost );
setPort( thePort );
setBase( theBase );
}
/**
* Constructor with host, port, base, and scope initializers
* @param theHost host string
* @param thePort port number
* @param theBase directory base string
* @param theScope one of LDAPConnection.SCOPE_BASE,
* LDAPConnection.SCOPE_SUB, LDAPConnection.SCOPE_ONE
*/
public LDAPGetEntries( String theHost,
int thePort,
String theBase,
int theScope ) {
setHost( theHost );
setPort( thePort );
setBase( theBase );
setScope( theScope );
}
private void notifyResult( String error ) {
firePropertyChange( "error", _errorMsg, error );
_errorMsg = error;
}
private void notifyResult( String[] newResult ) {
String sNewResult = convertToString( newResult );
firePropertyChange( "result", _result, newResult );
_sResult = sNewResult;
_result = newResult;
}
/**
* Returns the name of the attribute to retrieve
* @return attribute name to retrieve
*/
public String getAttribute() {
return _attribute;
}
/**
* Sets the attribute to retrieve
*/
public void setAttribute( String attr ) {
_attribute = attr;
}
public void setResultString( String sNewValue ) {
_sResult = sNewValue;
}
public String getResultString() {
return _sResult;
}
/**
* Searches and returns values for a specified attribute
* @param host host string
* @param port port number
* @param base directory base string
* @param scope one of LDAPConnection.SCOPE_BASE,
* LDAPConnection.SCOPE_SUB, LDAPConnection.SCOPE_ONE
* @param filter search filter
* @param attribute name of property to return values for
* @return Array of values for the property
*/
public String[] getEntries( String host,
int port,
String base,
int scope,
String filter) {
setHost( host );
setPort( port );
setBase( base );
setScope( scope );
setFilter( filter );
return getEntries();
}
/**
* Searches and returns values for a specified attribute
* @param host host string
* @param port port number
* @param base directory base string
* @param scope one of LDAPConnection.SCOPE_BASE,
* LDAPConnection.SCOPE_SUB, LDAPConnection.SCOPE_ONE
* @param userName The user name
* @param userid The user id
* @return Array of DNs
*/
public String[] getEntries( String host,
int port,
String base,
int scope,
String userid,
String userName) {
setHost( host );
setPort( port );
setBase( base );
setScope( scope );
if (userName == null)
userName = new String("");
setUserName( userName );
if (userid == null)
userid = new String("");
setUserID( userid );
return getEntries();
}
// Added this method in order to get exposed in BDK
public void getEntries(ActionEvent x) {
getEntries();
}
/**
* Searches and returns values of a previously registered property,
* using previously set parameters
* @return Array of values for the property
*/
public String[] getEntries() {
boolean invalid = false;
if ((getUserName().length() < 1) && (getUserID().length() < 1) &&
(getFilter().length() < 1)) {
printDebug("No user name or user ID");
invalid = true;
} else if ( (getHost().length() < 1) || (getBase().length() < 1) ) {
printDebug( "Invalid host name or search base" );
invalid = true;
}
if ( invalid ) {
setErrorCode( INVALID_PARAMETER );
notifyResult( (String)null);
return null;
}
if (getFilter().length() < 1) {
String filter = new String("");
if ((getUserName().length() > 1) && (getUserID().length() > 1)) {
filter = "(|(cn="+getUserName()+")(uid="+getUserID()+"))";
} else if (getUserName().length() > 1) {
filter = "cn="+getUserName();
} else if (getUserID().length() > 1) {
filter = "uid="+getUserID();
}
setFilter(filter);
}
String[] res = null;
LDAPConnection m_ldc = new LDAPConnection();
try {
try {
printDebug("Connecting to " + getHost() +
" " + getPort());
connect( m_ldc, getHost(), getPort());
} catch (Exception e) {
printDebug( "Failed to connect to " + getHost() + ": " +
e.toString() );
setErrorCode( CONNECT_ERROR );
notifyResult( (String)null );
m_ldc = null;
throw( new Exception() );
}
// Authenticate?
if ( (!getAuthDN().equals("")) &&
(!getAuthPassword().equals("")) ) {
printDebug( "Authenticating " + getAuthDN() );
try {
m_ldc.authenticate( getAuthDN(), getAuthPassword() );
} catch (Exception e) {
printDebug( "Failed to authenticate: " + e.toString() );
setErrorCode( AUTHENTICATION_ERROR );
notifyResult( (String)null );
throw( new Exception() );
}
}
// Search
try {
printDebug("Searching " + getBase() +
" for " + getFilter() + ", scope = " + getScope());
String[] attrs = { _attribute };
LDAPSearchResults results = m_ldc.search( getBase(),
getScope(),
getFilter(),
attrs,
false);
// Create a vector for the results
Vector v = new Vector();
LDAPEntry entry = null;
while ( results.hasMoreElements() ) {
try {
entry = results.next();
} catch (LDAPException e) {
if (getDebug())
notifyResult(e.toString());
continue;
}
// Add the DN to the list
String value = "";
if ( _attribute.equals("dn") ) {
value = entry.getDN();
} else {
LDAPAttribute attr = entry.getAttribute( _attribute );
if ( attr != null ) {
Enumeration vals = attr.getStringValues();
if ( (vals != null) && (vals.hasMoreElements()) ) {
value = (String)vals.nextElement();
}
}
}
v.addElement( value );
printDebug( "... " + value );
}
// Pull out the DNs and create a string array
if ( v.size() > 0 ) {
res = new String[v.size()];
v.copyInto( res );
v.removeAllElements();
setErrorCode( OK );
} else {
printDebug( "No entries found for " + getFilter() );
setErrorCode( PROPERTY_NOT_FOUND );
}
} catch (Exception e) {
if (getDebug()) {
printDebug( "Failed to search for " + getFilter() + ": " +
e.toString() );
}
setErrorCode( PROPERTY_NOT_FOUND );
}
} catch (Exception e) {
}
// Disconnect
try {
if ( (m_ldc != null) && m_ldc.isConnected() )
m_ldc.disconnect();
} catch ( Exception e ) {
}
// Notify any clients with a PropertyChangeEvent
notifyResult( res );
return res;
}
/**
* The main body if we run it as application instead of applet.
* @param args list of arguments
*/
public static void main(String args[]) {
String[] scope = { "base", "one", "sub" };
int scopeIndex = -1;
for( int i = 0; (i < scope.length) && (args.length == 5); i++ ) {
if ( args[3].equalsIgnoreCase(scope[i]) ) {
scopeIndex = i;
break;
}
}
if ( scopeIndex < 0 ) {
System.out.println( "Usage: LDAPGetEntries host port base" +
" scope filter" );
System.exit(1);
}
LDAPGetEntries app = new LDAPGetEntries();
app.setHost( args[0] );
app.setPort( java.lang.Integer.parseInt( args[1] ) );
app.setBase( args[2] );
app.setScope( scopeIndex );
app.setFilter( args[4] );
String[] response = app.getEntries();
if ( response != null ) {
for( int i = 0; i < response.length; i++ )
System.out.println( "\t" + response[i] );
}
System.exit(0);
}
/*
* Variables
*/
private String _attribute = "dn";
private String[] _result;
private String _sResult = null;
private String _errorMsg = null;
}

View File

@@ -0,0 +1,7 @@
Name: netscape/ldap/beans/LDAPGetEntries.class
Java-Bean: True
Name: netscape/ldap/beans/LDAPBasePropertySupport.class
Name: netscape/ldap/beans/LDAPGetEntriesBeanInfo.class

View File

@@ -0,0 +1,133 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.beans;
import java.beans.SimpleBeanInfo;
import java.beans.BeanDescriptor;
import java.beans.EventSetDescriptor;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.beans.ParameterDescriptor;
import java.beans.BeanInfo;
/**
* BeanInfo for LDAPGetEntries
*/
public class LDAPGetEntriesBeanInfo extends SimpleBeanInfo {
public LDAPGetEntriesBeanInfo() throws Exception {
beanClass = Class.forName( "netscape.ldap.beans.LDAPGetEntries" );
try {
PropertyDescriptor host =
new PropertyDescriptor("host", beanClass);
PropertyDescriptor port =
new PropertyDescriptor("port", beanClass);
PropertyDescriptor authDN =
new PropertyDescriptor("authDN", beanClass);
PropertyDescriptor authPassword =
new PropertyDescriptor("authPassword", beanClass);
PropertyDescriptor base =
new PropertyDescriptor("base", beanClass);
PropertyDescriptor userName =
new PropertyDescriptor("userName", beanClass);
PropertyDescriptor userID =
new PropertyDescriptor("userID", beanClass);
PropertyDescriptor filter =
new PropertyDescriptor("filter", beanClass);
PropertyDescriptor scope =
new PropertyDescriptor("scope", beanClass);
PropertyDescriptor debug =
new PropertyDescriptor("debug", beanClass);
PropertyDescriptor rv[] =
{host, port, authDN, authPassword, base, filter,
scope, userName, userID, debug};
_propertyDescriptor = new PropertyDescriptor[rv.length];
for( int i = 0; i < rv.length; i++ )
_propertyDescriptor[i] = rv[i];
} catch (Exception e) {
throw new Error(e.toString());
}
// Publish events --------------------------------------------------
try {
_eventSetDescriptor = new EventSetDescriptor[1];
_eventSetDescriptor[0] = new EventSetDescriptor(beanClass,
"propertyChange",
Class.forName("java.beans.PropertyChangeListener"),
"propertyChange");
} catch (Exception e) {
throw new Error(e.toString());
}
// Publish descriptor ---------------------------------------------
try {
_beanDescriptor = new BeanDescriptor(beanClass);
_beanDescriptor.setDisplayName( "LDAP entry retrieval" );
_beanDescriptor.setShortDescription(
"LDAP property retrieval -"
+ " provided a host, port, base, search filter,"
+ " and optionally a username and password,"
+ " return an array of string values both as a"
+ " function return and as a Property change event." );
} catch (Exception e) {
}
}
/**
* @return the public properties
*/
public PropertyDescriptor[] getPropertyDescriptors() {
return _propertyDescriptor;
}
public EventSetDescriptor[] getEventSetDescriptors() {
return _eventSetDescriptor;
}
public BeanInfo[] getAdditionalBeanInfo() {
return null;
}
public int getDefaultEventIndex() {
return -1;
}
public int getDefaultPropertyIndex() {
return -1;
}
public BeanDescriptor getBeanDescriptor() {
return _beanDescriptor;
}
private static Class beanClass;
private BeanDescriptor _beanDescriptor;
private EventSetDescriptor[] _eventSetDescriptor;
private PropertyDescriptor[] _propertyDescriptor;
}

View File

@@ -0,0 +1,336 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.beans;
import netscape.ldap.*;
import netscape.ldap.beans.LDAPBasePropertySupport;
import java.util.Enumeration;
import java.util.Vector;
import java.io.Serializable;
import java.beans.*;
import java.awt.event.*;
/**
* Invisible Bean that just takes a name and password, host and
* port, and directory base and attribute name, and returns an
* attribute's values from a Directory Server. The values are
* assumed to be strings, and are returned as an array. The
* search has the scope "SUB", which means that it will find
* an entry anywhere at or below the directory base.
* <BR><BR>
* Optionally, a client can register as a PropertyChangeListener
* and will be notified when the values are available.
*<BR><BR>
* A null result means the property fetch failed. The reason is
* available through getErrorCode(), which returns one of
* the following:
*<PRE>
* OK
* INVALID_PARAMETER
* CONNECT_ERROR
* AUTHENTICATION_ERROR
* PROPERTY_NOT_FOUND
* AMBIGUOUS_RESULTS
*</PRE>
*/
public class LDAPGetProperty extends LDAPBasePropertySupport implements
Serializable {
/**
* Constructor with no parameters
*/
public LDAPGetProperty() {}
/**
* Constructor with host, port, and base initializers
* @param theHost host string
* @param thePort port number
* @param theBase directory base string
*/
public LDAPGetProperty( String theHost, int thePort, String theBase ) {
setHost( theHost );
setPort( thePort );
setBase( theBase );
}
/**
* Returns the name of the attribute to retrieve
* @return attribute name to retrieve
*/
public String getAttribute() {
return _attribute;
}
/**
* Sets the attribute to retrieve
*/
public void setAttribute( String attr ) {
_attribute = attr;
}
private void notifyResult( String[] newResult ) {
String sNewResult = convertToString( newResult );
firePropertyChange( "result", _result, newResult );
_sResult = sNewResult;
_result = newResult;
}
private void notifyResult( Vector newResult ) {
firePropertyChange( "result", _resultV, newResult );
_resultV = (Vector)newResult.clone();
}
private void notifyResult( String error ) {
firePropertyChange( "error", _errorMsg, error );
_errorMsg = error;
}
public void setDNs(PropertyChangeEvent evt) {
Object obj = (Object)evt.getNewValue();
if ((obj != null) && (obj instanceof String[])) {
String[] strings = (String[])obj;
if (strings.length == 0)
return;
_dns = new String[strings.length];
System.arraycopy(obj, 0, _dns, 0, strings.length);
System.out.println("length of dns -> "+_dns.length);
}
}
/**
* Searches and returns values for a specified attribute
* @param host host string
* @param port port number
* @param base directory base string
* @param filter search filter
* @param attribute name of property to return values for
* @return Array of values for the property
*/
public String[] getProperty( String host, int port, String base,
String filter, String attribute) {
setHost( host );
setPort( port );
setBase( base );
setFilter( filter );
setAttribute( attribute );
return getProperty();
}
// Added this method in order to get exposed in BDK
public void getProperty(ActionEvent x) {
getProperty();
}
/**
* Searches and returns values of a previously registered property,
* using previously set parameters
* @return Array of values for the property
*/
public String[] getProperty() {
if ( (_attribute.length() < 1) || (getFilter().length() < 1) ) {
printDebug( "Invalid attribute name or filter" );
setErrorCode( INVALID_PARAMETER );
notifyResult( (String[])null );
return null;
}
String[] res = null;
LDAPConnection m_ldc;
try {
m_ldc = new LDAPConnection();
printDebug("Connecting to " + getHost() +
" " + getPort());
connect( m_ldc, getHost(), getPort());
} catch (Exception e) {
printDebug( "Failed to connect to " + getHost() + ": "
+ e.toString() );
setErrorCode( CONNECT_ERROR );
notifyResult( (String[])null );
return null;
}
// Authenticate?
if (_dns != null) {
for (int i=0; i<_dns.length; i++) {
try {
m_ldc.authenticate(_dns[i], getAuthPassword());
break;
} catch (Exception e) {
if (i == _dns.length-1) {
printDebug( "Failed to authenticate to " +
getHost() + ": " + e.toString() );
setErrorCode( AUTHENTICATION_ERROR );
notifyResult( (String[])null );
return null;
}
}
}
} else if ( (!getAuthDN().equals("")) && (!getAuthPassword().equals("")) ) {
printDebug( "Authenticating " + getAuthDN() + " - " +
getAuthPassword() );
try {
m_ldc.authenticate( getAuthDN(), getAuthPassword() );
} catch (Exception e) {
printDebug( "Failed to authenticate to " +
getHost() + ": " + e.toString() );
setErrorCode( AUTHENTICATION_ERROR );
notifyResult( (String[])null );
return null;
}
}
int numDataEntries = 0;
// Search
try {
String[] attrs = new String[1];
attrs[0] = _attribute;
LDAPSearchResults results = m_ldc.search(getBase(),
getScope(),
getFilter(),
attrs, false);
// Should be only one result, at most
LDAPEntry currEntry = null;
LDAPEntry entry = null;
while ( results.hasMoreElements() ) {
try {
currEntry = results.next();
if (numDataEntries == 0)
entry = currEntry;
if (++numDataEntries > 1) {
printDebug( "More than one entry found for " +
getFilter() );
setErrorCode( AMBIGUOUS_RESULTS );
break;
}
} catch (LDAPException e) {
if (getDebug())
notifyResult(e.toString());
continue;
}
}
if (numDataEntries == 1) {
printDebug( "... " + entry.getDN() );
// Good - exactly one entry found; get the attribute
// Treat DN as a special case
if ( _attribute.equalsIgnoreCase( "dn" ) ) {
res = new String[1];
res[0] = entry.getDN();
setErrorCode( OK );
} else {
LDAPAttributeSet attrset = entry.getAttributeSet();
Enumeration attrsenum = attrset.getAttributes();
if (attrsenum.hasMoreElements()) {
LDAPAttribute attr =
(LDAPAttribute)attrsenum.nextElement();
printDebug( attr.getName() + " = " );
// Get the values as strings
Enumeration valuesenum = attr.getStringValues();
if (valuesenum != null) {
// Create a string array for the results
Vector v = new Vector();
while (valuesenum.hasMoreElements()) {
String val = (String)valuesenum.nextElement();
v.addElement( val );
printDebug( "\t\t" + val );
}
res = new String[v.size()];
v.copyInto( res );
setErrorCode( OK );
} else {
Enumeration byteEnum = attr.getByteValues();
Vector v = new Vector();
while (byteEnum.hasMoreElements()) {
byte[] val = (byte[])byteEnum.nextElement();
v.addElement( val );
printDebug( "\t\t" + val );
}
setErrorCode( OK );
notifyResult(v);
return (res = null);
}
} else {
printDebug( "No properties found for " +
_attribute );
setErrorCode( PROPERTY_NOT_FOUND );
}
}
}
} catch (Exception e) {
if (getDebug()) {
printDebug( "Failed to search for " + getFilter() + ": "
+ e.toString() );
}
setErrorCode( PROPERTY_NOT_FOUND );
}
if (numDataEntries == 0) {
printDebug( "No entries found for " + getFilter() );
setErrorCode( PROPERTY_NOT_FOUND );
}
// Disconnect
try {
if ( (m_ldc != null) && m_ldc.isConnected() )
m_ldc.disconnect();
} catch ( Exception e ) {
}
notifyResult( res );
return res;
}
/**
* The main body if we run it as application instead of applet.
* @param args list of arguments
*/
public static void main(String args[]) {
if (args.length != 5) {
System.out.println( "Usage: LDAPGetProperty host port base" +
" filter attribute" );
System.exit(1);
}
LDAPGetProperty app = new LDAPGetProperty();
app.setHost( args[0] );
app.setPort( java.lang.Integer.parseInt( args[1] ) );
app.setBase( args[2] );
app.setFilter( args[3] );
app.setAttribute( args[4] );
String[] response = app.getProperty();
if ( response != null ) {
for( int i = 0; i < response.length; i++ )
System.out.println( "\t" + response[i] );
}
System.exit(0);
}
/*
* Variables
*/
private String[] _dns = null;
private String _attribute = new String("cn");
transient private String[] _result;
private Vector _resultV = null;
private String _sResult = null;
private String _errorMsg = null;
}

View File

@@ -0,0 +1,6 @@
Name: netscape/ldap/beans/LDAPGetProperty.class
Java-Bean: True
Name: netscape/ldap/beans/LDAPBasePropertySupport.class
Name: netscape/ldap/beans/LDAPGetPropertyBeanInfo.class

View File

@@ -0,0 +1,142 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.beans;
import java.beans.SimpleBeanInfo;
import java.beans.BeanDescriptor;
import java.beans.EventSetDescriptor;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.beans.ParameterDescriptor;
import java.beans.BeanInfo;
/**
* BeanInfo for LDAPGetProperty
*/
public class LDAPGetPropertyBeanInfo extends SimpleBeanInfo {
public LDAPGetPropertyBeanInfo() throws Exception {
beanClass = Class.forName( "netscape.ldap.beans.LDAPGetProperty" );
try {
PropertyDescriptor host =
new PropertyDescriptor("host", beanClass);
PropertyDescriptor port =
new PropertyDescriptor("port", beanClass);
PropertyDescriptor authDN =
new PropertyDescriptor("authDN", beanClass);
PropertyDescriptor authPassword =
new PropertyDescriptor("authPassword", beanClass);
PropertyDescriptor base =
new PropertyDescriptor("base", beanClass);
PropertyDescriptor filter =
new PropertyDescriptor("filter", beanClass);
PropertyDescriptor scope =
new PropertyDescriptor("scope", beanClass);
PropertyDescriptor attribute =
new PropertyDescriptor("attribute", beanClass);
PropertyDescriptor debug =
new PropertyDescriptor("debug", beanClass);
PropertyDescriptor rv[] =
{host, port, authDN, authPassword, base, scope, attribute,
filter, debug};
_propertyDescriptor = new PropertyDescriptor[rv.length];
for( int i = 0; i < rv.length; i++ )
_propertyDescriptor[i] = rv[i];
} catch (Exception e) {
throw new Error(e.toString());
}
// Publish events --------------------------------------------------
try {
_eventSetDescriptor = new EventSetDescriptor[1];
_eventSetDescriptor[0] = new EventSetDescriptor(beanClass,
"propertyChange",
Class.forName("java.beans.PropertyChangeListener"),
"propertyChange");
} catch (Exception e) {
throw new Error(e.toString());
}
// Publish descriptor ---------------------------------------------
try {
_beanDescriptor = new BeanDescriptor(beanClass);
_beanDescriptor.setDisplayName( "LDAP property retrieval" );
_beanDescriptor.setShortDescription(
"LDAP property retrieval -"
+ " provided a host, port, base, search filter,"
+ " and optionally a username and password,"
+ " return an array of string values both as a"
+ " function return and as a Property change event." );
} catch (Exception e) {
}
}
/**
* @return the public properties
*/
public PropertyDescriptor[] getPropertyDescriptors() {
return _propertyDescriptor;
}
/**
* @return the public methods
*/
public MethodDescriptor[] getMethodDescriptors() {
return _methodDescriptor;
}
public EventSetDescriptor[] getEventSetDescriptors() {
return _eventSetDescriptor;
}
public BeanInfo[] getAdditionalBeanInfo() {
return null;
}
public int getDefaultEventIndex() {
return -1;
}
public int getDefaultPropertyIndex() {
return -1;
}
public BeanDescriptor getBeanDescriptor() {
return _beanDescriptor;
}
private static Class beanClass;
private BeanDescriptor _beanDescriptor;
private EventSetDescriptor[] _eventSetDescriptor;
private MethodDescriptor[] _methodDescriptor;
private PropertyDescriptor[] _propertyDescriptor;
}

View File

@@ -0,0 +1,437 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.beans;
import netscape.ldap.*;
import netscape.ldap.util.*;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.io.Serializable;
import java.awt.event.*;
/**
* Invisible Bean that just takes a host and port, optional
* authentication name and password, and DN of a group and another DN
* which might be a member of the group, and returns true or
* false, depending on whether the second DN is a member of the first.
* <BR>
* Also handles the case of dynamic groups by derefencing the URL
* and searching for membership based on the url search.
* <BR>
* It doesn't handle nested groups.
* <BR><BR>
* A false result means the member could not be identified as
* belonging to the group. The exact reason is
* available through getErrorCode(), which returns one of
* the following:
*<PRE>
* OK
* INVALID_PARAMETER
* CONNECT_ERROR
* AUTHENTICATION_ERROR
* PROPERTY_NOT_FOUND
* AMBIGUOUS_RESULTS
* NO_SUCH_OBJECT
*</PRE>
*/
public class LDAPIsMember extends LDAPBasePropertySupport
implements Serializable {
/**
* Constructor with no parameters
*/
public LDAPIsMember() {}
/**
* Constructor with host, port, and group DN initializers
* @param host host string
* @param port port number
* @param group distinguished name of the group
*/
public LDAPIsMember( String host, int port, String group ) {
setHost( host );
setPort( port );
setGroup( group );
}
/**
* Constructor with host, port, authentication DN and password
* and group DN initializers
* @param host host string
* @param port port number
* @param dn fully qualified distinguished name to authenticate
* @param password password for authenticating the dn
* @param group distinguished name of the group
*/
public LDAPIsMember( String host, int port,
String dn, String password, String theGroup ) {
setHost( host );
setPort( port );
setGroup( theGroup );
setAuthDN( dn );
setAuthPassword( password );
}
private void notifyResult( String newResult ) {
firePropertyChange( "result", _result, newResult );
_result = newResult;
}
/**
* Checks if an entity (specified by distinguished name) is a
* member of a particular group (specified by distinguished name)
* @return true if the specified member belongs to the group
*/
public boolean isMember() {
String host = getHost();
int port = getPort();
String dn = getAuthDN();
String password = getAuthPassword();
String group = getGroup();
String member = getMember();
_result = new String("");
if ( (host == null) || (host.length() < 1) ) {
printDebug( "Invalid host name" );
setErrorCode( INVALID_PARAMETER );
notifyResult(null);
return false;
}
if ( (member == null) || (group == null) ||
(member.length() < 1) || (group.length() < 1) ) {
printDebug( "Invalid member or group name" );
setErrorCode( INVALID_PARAMETER );
notifyResult(null);
return false;
}
LDAPConnection m_ldc;
boolean isMember = false;
try {
m_ldc = new LDAPConnection();
printDebug("Connecting to " + host +
" " + port);
connect( m_ldc, getHost(), getPort());
} catch (Exception e) {
printDebug( "Failed to connect to " + host + ": "
+ e.toString() );
setErrorCode( CONNECT_ERROR );
notifyResult(null);
return false;
}
// Authenticate?
if ( (dn != null) && (password != null) &&
(dn.length() > 0) && (password.length() > 0) ) {
printDebug( "Authenticating " + dn + " - " + password );
try {
m_ldc.authenticate( dn, password );
} catch (Exception e) {
printDebug( "Failed to authenticate to " +
host + ": " + e.toString() );
setErrorCode( AUTHENTICATION_ERROR );
notifyResult(null);
return false;
}
}
int numDataEntries = 0;
// Search
try {
String[] attrs = new String[4];
attrs[0] = "member";
attrs[1] = "uniqueMember";
attrs[2] = "memberOfGroup";
attrs[3] = "memberurl";
LDAPSearchResults results =
m_ldc.search( group,
LDAPConnection.SCOPE_BASE,
"objectclass=*",
attrs, false);
// Should be only one result, at most
LDAPEntry entry = null;
LDAPEntry currEntry = null;
while ( results.hasMoreElements() ) {
try {
currEntry = (LDAPEntry)results.next();
if (numDataEntries == 0)
entry = currEntry;
if (++numDataEntries > 1) {
printDebug( "More than one entry found for " +
getFilter() );
setErrorCode( AMBIGUOUS_RESULTS );
break;
}
} catch (LDAPReferralException e) {
if (getDebug()) {
notifyResult("Referral URLs: ");
LDAPUrl refUrls[] = e.getURLs();
for (int i = 0; i < refUrls.length; i++)
notifyResult(refUrls[i].getUrl());
}
continue;
} catch (LDAPException e) {
if (getDebug())
notifyResult(e.toString());
continue;
}
}
if (numDataEntries == 1) {
printDebug( "... " + entry.getDN() );
String normMember = normalizeDN( member );
// Good - exactly one entry found; get the attributes
LDAPAttributeSet attrset = entry.getAttributeSet();
Enumeration attrsenum = attrset.getAttributes();
while ( attrsenum.hasMoreElements() && !isMember ) {
LDAPAttribute attr =
(LDAPAttribute)attrsenum.nextElement();
printDebug( attr.getName() + " = " );
boolean urlHandler =
attr.getName().equalsIgnoreCase("memberurl");
/* Get the values as strings.
The following code also handles dynamic
groups by calling URLMatch to see if an entry
DN is found via a URL search.
This is transparent to the caller of the bean.
*/
Enumeration valuesenum = attr.getStringValues();
if (valuesenum != null) {
while (valuesenum.hasMoreElements()) {
String val = (String)valuesenum.nextElement();
if (urlHandler) {
if ( URLMatch(m_ldc, val, normMember) ) {
isMember = true;
setErrorCode( OK );
break;
}
}
printDebug( "\t\t" + val );
String normFound = normalizeDN( val );
if ( normMember.equals( normFound ) ) {
isMember = true;
setErrorCode( OK );
break;
}
}
} else {
setErrorCode(PROPERTY_NOT_FOUND);
printDebug("Failed to do string conversion for "+
attr.getName());
}
}
if ( !isMember )
setErrorCode( PROPERTY_NOT_FOUND );
}
} catch (Exception e) {
printDebug( "Failed to search for " + group + ": "
+ e.toString() );
setErrorCode( NO_SUCH_OBJECT );
}
if (numDataEntries == 0) {
printDebug( "No entries found for " + group );
setErrorCode( NO_SUCH_OBJECT );
}
try {
if ( (m_ldc != null) && m_ldc.isConnected() )
m_ldc.disconnect();
} catch ( Exception e ) {
}
if (isMember)
notifyResult("Y");
else
notifyResult("N");
return isMember;
}
/**
* Checks if an entity (specified by distinguished name) is a
* member of a particular group (specified by distinguished name)
* @param host host string
* @param port port number
* @param dn fully qualified distinguished name to authenticate;
* can be null or ""
* @param password password for authenticating the dn; can be null
* or ""
* @param group distinguished name of the group
* @param member distinguished name of member to be checked
* @return true if the specified member belongs to the group
*/
public boolean isMember( String host, int port,
String dn, String password,
String group, String member ) {
setHost(host);
setPort(port);
setAuthDN(dn);
setAuthPassword(password);
setGroup(group);
setMember(member);
return isMember();
}
/**
* Checks if an entity (specified by distinguished name) is a
* member of a particular group (specified by distinguished name)
* @return true if the specified member belongs to the group
*/
public void isMember(ActionEvent e) {
isMember();
}
/**
* Returns the distinguished name of the group
* @return group name
*/
public String getGroup() {
return _group;
}
/**
* Sets the distinguished name of the group
* @param group group name
*/
public void setGroup( String group ) {
_group = group;
}
/**
* Returns the distinguished name of the member
* @return member name
*/
public String getMember() {
return _member;
}
/**
* Sets the distinguished name of the member
* @param member member name
*/
public void setMember( String member ) {
_member = member;
}
private String normalizeDN( String dn ) {
return new DN( dn ).toRFCString().toUpperCase();
}
/**
* Return true if normMember is result of url search.
* Urls from dynamic groups do not typically contain
* the host and port so we need to fix them before
* constructing an LDAP URL.
* current ldap:///.... make ldap://host:port/...
**/
private boolean URLMatch(LDAPConnection ld, String URL,
String normMemberDN) {
String cURL = URL;
boolean isMember = false;
int loc = URL.indexOf(":///");
if ( loc > 0) {
cURL = URL.substring(0,loc) + "://" + ld.getHost() +
":" + ld.getPort() + URL.substring(loc+3);
}
printDebug("URLMatch: url = " + cURL +
", member DN = " + normMemberDN);
LDAPUrl ldapurl;
try {
ldapurl = new LDAPUrl(cURL);
printDebug("URL ->"+ldapurl.getUrl());
} catch (java.net.MalformedURLException murl) {
printDebug("bad URL");
return isMember;
}
try {
LDAPSearchResults results = ld.search(ldapurl);
String entry = "";
while ( results.hasMoreElements() && !isMember ) {
try {
entry = ((LDAPEntry)results.next()).getDN();
String normEntry = normalizeDN( entry );
if (normEntry.equals(normMemberDN)) {
isMember = true;
break;
}
} catch (LDAPReferralException e) {
if (getDebug()) {
notifyResult("Referral URLs: ");
LDAPUrl refUrls[] = e.getURLs();
for (int i = 0; i < refUrls.length; i++)
notifyResult(refUrls[i].getUrl());
}
continue;
} catch (LDAPException e) {
if (getDebug())
notifyResult(e.toString());
continue;
}
}
} catch (LDAPException lde) {
printDebug("Failed search for url " + ldapurl.getUrl());
setErrorCode(NO_SUCH_OBJECT);
}
return isMember;
}
/**
* The main body if we run it as application instead of applet.
* @param args list of arguments
*/
public static void main(String args[]) {
if (args.length != 4) {
System.out.println( "Usage: LDAPIsMember host port group" +
" member" );
System.exit(1);
}
LDAPIsMember app = new LDAPIsMember();
app.setHost( args[0] );
app.setPort( java.lang.Integer.parseInt( args[1] ) );
app.setGroup( args[2] );
app.setMember( args[3] );
boolean response = app.isMember();
if ( response == false )
System.out.println( "Not a member" );
else
System.out.println( "Is a member" );
System.exit(0);
}
/*
* Variables
*/
public static final int OK = 0;
public static final int INVALID_PARAMETER = 1;
public static final int CONNECT_ERROR = 2;
public static final int AUTHENTICATION_ERROR = 3;
public static final int PROPERTY_NOT_FOUND = 4;
public static final int AMBIGUOUS_RESULTS = 5;
public static final int NO_SUCH_OBJECT = 5;
private String _group = new String("");
private String _member = new String("");
private String _result = new String("");
}

View File

@@ -0,0 +1,6 @@
Name: netscape/ldap/beans/LDAPIsMember.class
Java-Bean: True
Name: netscape/ldap/beans/LDAPBasePropertySupport.class
Name: netscape/ldap/beans/LDAPIsMemberBeanInfo.class

View File

@@ -0,0 +1,114 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.beans;
import java.beans.SimpleBeanInfo;
import java.beans.BeanDescriptor;
import java.beans.EventSetDescriptor;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.beans.ParameterDescriptor;
import java.beans.BeanInfo;
/**
* BeanInfo for LDAPIsMember
*/
public class LDAPIsMemberBeanInfo extends SimpleBeanInfo {
public LDAPIsMemberBeanInfo() throws Exception {
beanClass = Class.forName( "netscape.ldap.beans.LDAPIsMember" );
// Publish properties -------------------------------------------------
try {
PropertyDescriptor host =
new PropertyDescriptor("host", beanClass);
PropertyDescriptor port =
new PropertyDescriptor("port", beanClass);
PropertyDescriptor authDN =
new PropertyDescriptor("authDN", beanClass);
PropertyDescriptor authPassword =
new PropertyDescriptor("authPassword", beanClass);
PropertyDescriptor group =
new PropertyDescriptor("group", beanClass);
PropertyDescriptor member =
new PropertyDescriptor("member", beanClass);
PropertyDescriptor debug =
new PropertyDescriptor("debug", beanClass);
PropertyDescriptor rv[] =
{host, port, authDN, authPassword, group, member, debug};
_propertyDescriptor = new PropertyDescriptor[rv.length];
for( int i = 0; i < rv.length; i++ )
_propertyDescriptor[i] = rv[i];
} catch (Exception e) {
throw new Error(e.toString());
}
// Publish descriptor ---------------------------------------------
try {
_beanDescriptor = new BeanDescriptor(beanClass);
_beanDescriptor.setDisplayName( "LDAP IsMember" );
_beanDescriptor.setShortDescription(
"LDAP IsMember -"
+ " provided a host, port, group name and member name,"
+ " and optionally an authentication name and password,"
+ " return true if the member belongs to the group." );
} catch (Exception e) {
}
}
/**
* @return the public properties
*/
public PropertyDescriptor[] getPropertyDescriptors() {
return _propertyDescriptor;
}
public EventSetDescriptor[] getEventSetDescriptors() {
return _eventSetDescriptor;
}
public BeanInfo[] getAdditionalBeanInfo() {
return null;
}
public int getDefaultEventIndex() {
return -1;
}
public int getDefaultPropertyIndex() {
return -1;
}
public BeanDescriptor getBeanDescriptor() {
return _beanDescriptor;
}
private static Class beanClass;
private BeanDescriptor _beanDescriptor;
private EventSetDescriptor[] _eventSetDescriptor;
private PropertyDescriptor[] _propertyDescriptor;
}

View File

@@ -0,0 +1,182 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.beans;
import netscape.ldap.*;
import netscape.ldap.beans.LDAPBasePropertySupport;
import java.io.Serializable;
import java.awt.event.*;
/**
* Invisible Bean that just authenticates a user with a Directory
* Server and returns Y or N. It takes a host and port, and then either
* a full distinguished name and password, an RDN and directory base, or
* a cn value and directory base.
* <BR><BR>
* Optionally, a client can register as
* a PropertyChangeListener and will be notified when an authentication
* completes.
* <BR><BR>
* The Bean can be used from JavaScript, as in the following example
* where the parameters are taken from HTML text fields in an HTML
* form called "input":
* <PRE>
* <XMP>
* <SCRIPT LANGUAGE="JavaScript">
* function checkAuthentication() {
* auth = new Packages.netscape.ldap.beans.LDAPSimpleAuth();
* auth.setHost( document.input.host.value );
* auth.setPort( parseInt(document.input.port.value) );
* auth.setAuthDN( document.input.username.value );
* auth.setAuthPassword( document.input.password.value );
* result = auth.authenticate();
* alert( "The response is: " + result );
* }
* </SCRIPT>
* </XMP>
*</PRE>
*/
public class LDAPSimpleAuth extends LDAPBasePropertySupport implements
Serializable {
/**
* Constructor with no parameters
*/
public LDAPSimpleAuth() {}
/**
* Constructor with host and port initializers
* @param theHost host string
* @param thePort port number
*/
public LDAPSimpleAuth( String theHost,
int thePort ) {
setHost( theHost );
setPort( thePort );
}
/**
* Constructor with all required authentication parameters
* @param theHost host string
* @param thePort port number
* @param dn fully qualified distinguished name to authenticate
* @param password password for authenticating the dn
*/
public LDAPSimpleAuth( String theHost,
int thePort,
String dn,
String password ) {
setHost( theHost );
setPort( thePort );
setAuthDN( dn );
setAuthPassword( password );
}
private void notifyResult( String newResult ) {
firePropertyChange( "result", result, newResult );
result = newResult;
}
/**
* Connect to LDAP server using parameters specified in
* constructor and/or by setting properties and attempt to
* authenticate.
* @return "Y" on successful authentication, "N" otherwise
*/
public String authenticate() {
LDAPConnection m_ldc = null;
String result = "N";
try {
m_ldc = new LDAPConnection();
System.out.println("Connecting to " + getHost() +
" " + getPort());
connect( m_ldc, getHost(), getPort());
} catch (Exception e) {
System.out.println( "Failed to connect to " + getHost() +
": " + e.toString() );
}
if ( m_ldc.isConnected() ) {
System.out.println( "Authenticating " + getAuthDN() );
try {
m_ldc.authenticate( getAuthDN(), getAuthPassword() );
result = "Y";
} catch (Exception e) {
System.out.println( "Failed to authenticate to " +
getHost() + ": " + e.toString() );
}
}
try {
if ( (m_ldc != null) && m_ldc.isConnected() )
m_ldc.disconnect();
} catch ( Exception e ) {
}
notifyResult( result );
return result;
}
/**
* Connect to LDAP server using parameters specified in
* constructor and/or by setting properties and attempt to
* authenticate.
* @param dn fully qualified distinguished name to authenticate
* @param password password for authenticating the dn
* @return "Y" on successful authentication, "N" otherwise
*/
public String authenticate( String dn,
String password ) {
setAuthDN( dn );
setAuthPassword( password );
return authenticate();
}
public void authenticate( ActionEvent x) {
authenticate();
}
/**
* The main body if we run it as stand-alone application.
* @param args list of arguments
*/
public static void main(String args[]) {
if (args.length != 4) {
System.out.println( " LDAPSimpleAuth " +
"host port DN password" );
System.exit(1);
}
LDAPSimpleAuth app = new LDAPSimpleAuth();
app.setHost( args[0] );
app.setPort( java.lang.Integer.parseInt( args[1] ) );
app.setAuthDN( args[2] );
app.setAuthPassword( args[3] );
String response = app.authenticate();
System.out.println( "Response: " + response );
System.exit(0);
}
/*
* Variables
*/
transient private String result = new String("");
}

View File

@@ -0,0 +1,6 @@
Name: netscape/ldap/beans/LDAPSimpleAuth.class
Java-Bean: True
Name: netscape/ldap/beans/LDAPBasePropertySupport.class
Name: netscape/ldap/beans/LDAPSimpleAuthBeanInfo.class

View File

@@ -0,0 +1,122 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.beans;
import java.beans.SimpleBeanInfo;
import java.beans.BeanDescriptor;
import java.beans.EventSetDescriptor;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.beans.ParameterDescriptor;
import java.beans.BeanInfo;
/**
* BeanInfo for LDAPSimpleAuth
*/
public class LDAPSimpleAuthBeanInfo extends SimpleBeanInfo {
public LDAPSimpleAuthBeanInfo() throws Exception {
beanClass = Class.forName( "netscape.ldap.beans.LDAPSimpleAuth" );
try {
PropertyDescriptor host =
new PropertyDescriptor("host", beanClass);
PropertyDescriptor port =
new PropertyDescriptor("port", beanClass);
PropertyDescriptor authDN =
new PropertyDescriptor("authDN", beanClass);
PropertyDescriptor authPassword =
new PropertyDescriptor("authPassword", beanClass);
PropertyDescriptor debug =
new PropertyDescriptor("debug", beanClass);
PropertyDescriptor rv[] =
{host, port, authDN, authPassword, debug};
_propertyDescriptor = new PropertyDescriptor[rv.length];
for( int i = 0; i < rv.length; i++ )
_propertyDescriptor[i] = rv[i];
} catch (Exception e) {
throw new Error(e.toString());
}
// Publish events --------------------------------------------------
try {
_eventSetDescriptor = new EventSetDescriptor[1];
_eventSetDescriptor[0] = new EventSetDescriptor(beanClass,
"propertyChange",
Class.forName("java.beans.PropertyChangeListener"),
"propertyChange");
} catch (Exception e) {
throw new Error(e.toString());
}
// Publish descriptor ---------------------------------------------
try {
_beanDescriptor = new BeanDescriptor(beanClass);
_beanDescriptor.setDisplayName( "LDAP user authentication" );
_beanDescriptor.setShortDescription(
"LDAP user authentication -"
+ " provided a host, port, base, username, and password,"
+ " report if the user can be authenticated both as a"
+ " function return and as a Property change event." );
} catch (Exception e) {
}
}
/**
* @return the public properties
*/
public PropertyDescriptor[] getPropertyDescriptors() {
return _propertyDescriptor;
}
public EventSetDescriptor[] getEventSetDescriptors() {
return _eventSetDescriptor;
}
public BeanInfo[] getAdditionalBeanInfo() {
return null;
}
public int getDefaultEventIndex() {
return -1;
}
public int getDefaultPropertyIndex() {
return -1;
}
public BeanDescriptor getBeanDescriptor() {
return _beanDescriptor;
}
private static Class beanClass;
private BeanDescriptor _beanDescriptor;
private EventSetDescriptor[] _eventSetDescriptor;
private PropertyDescriptor[] _propertyDescriptor;
}

View File

@@ -0,0 +1,87 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.util;
/**
* The exception thrown when there is a problem with either an LDAPFilter
* or with the File/URL/Buffer form which we're creating the LDAPFilter.
*
* @see LDAPFilter
* @see LDAPFilterDescriptor
* @version 1.0
*/
public class BadFilterException extends Exception {
private String m_strException;
private int m_nLine = -1;
/**
* Creates an <b>Unknown</b> BadFilterException
*/
public BadFilterException () {
m_strException = "Unknown Error";
}
/**
* Creates a BadFilterException with the
* given string
*/
public BadFilterException ( String s ) {
m_strException = s;
}
/**
* Creates a BadFilterException with the
* given string and line number
*/
public BadFilterException ( String s, int nErrorLineNumber ) {
m_strException = s;
m_nLine = nErrorLineNumber;
}
/**
* Returns the exception string.
*/
public String toString() {
return m_strException;
}
/**
* If appropriate, return the line number of the ldapfilter.conf
* file (or url or buffer) where this error occurred. This method
* will return -1 if the line number was not set.
*/
public int getErrorLineNumber() {
return m_nLine;
}
/**
* Set the line number in the ldapfilter.conf file/url/buffer where
* this error occurred.
*/
void setErrorLineNumber ( int nErrorLineNumber ) {
m_nLine = m_nLine;
}
}

View File

@@ -0,0 +1,533 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.util;
import netscape.ldap.*;
import java.util.*;
/**
* Represents an LDAP search filter, which includes the string-based
* representation of the filter and other information retrieved from the
* LDAP filter configuration file (or from a buffer in memory or from a URL).
* <P>
*
* Although this class provides methods to create and modify LDAP
* filters, in most cases, you do not need to use these methods.
* In most situations, these classes are used to access individual
* filters from filter configuration files.
* <P>
*
* For example, you might do the following:
* <P>
*
* <OL>
* <LI>Connect to the LDAP server and accept a set of search criteria.
* <LI>Create an LDAP filter configuration file.
* <LI>Call the <CODE>LDAPFilterDescriptor</CODE> constructor to
* read the filter configuration file into memory.
* <LI>Call the <CODE>getFilters</CODE> method to get a list of
* filters that match the search criteria. This list of filters
* is represented by an <CODE>LDAPFilterList</CODE> object.
* <LI>Iterate through the list of filters (each filter is represented
* by an <CODE>LDAPFilter</CODE> object), and apply the filter to
* a search.
* </OL>
* <P>
*
* For an example of using an object of this class and for more information on
* the filter configuration file syntax, see the documentation for <a
* href="n.l.u.LDAPFilterDescriptor.html">LDAPFilterDescriptor</a>.
* <P>
*
* @see LDAPFilterDescriptor
* @see LDAPFilterList
* @version 1.0
*/
public class LDAPFilter implements Cloneable {
private static final int DEFAULT_FILTER_LENGTH = 256;
private String m_strFilter = null;
private String m_strDescription; // token 4 from filter configuration file
private int m_nScope; // token 5 from filter configuration file
private boolean m_bIsExact;
private String m_strMatchPattern; // token 1 from filter configuration file
private String m_strDelimeter; // token 2 from filter configuration file
private String m_strFilterTemplate; // token 3 from filter configuration file
private int m_nLine;
private String m_strSuffix;
private String m_strPrefix;
/**
* Constructs an <CODE>LDAPFilter</CODE> object. In most situations,
* you do not need to construct an LDAPFilter object. Instead, you
* work with <CODE>LDAPFilter</CODE> objects created from the
* <CODE>LDAPFilter</CODE> objects and <CODE>LDAPFilterDescriptor</CODE>
* objects.
* <P>
*
* This constructor uses the integer value for a search scope in
* addition to other information to construct an <CODE>LDAPFilter</CODE>
* object. The integer value of the search scope can be one of the
* following:
* <ul>
* <li><CODE>LDAPConnection.SCOPE_BASE</CODE>
* <li><CODE>LDAPConnection.SCOPE_ONE</CODE>
* <li><CODE>LDAPConnection.SCOPE_SUB</CODE>
* </ul>
*
* If an invalid scope is specified, the constructor throws an
* <CODE>illegalArgumentException</CODE>.
*/
public LDAPFilter ( String strMatchPattern,
String strDelimeter,
String strFilterTemplate,
String strDescription,
int nScope ) throws IllegalArgumentException{
m_strMatchPattern = convertMatchPattern ( strMatchPattern );
m_strDelimeter = strDelimeter;
m_strFilterTemplate = strFilterTemplate;
m_strDescription = strDescription;
m_nScope = nScope;
}
/**
* Constructs an <CODE>LDAPFilter</CODE> object. In most situations,
* you do not need to construct an LDAPFilter object. Instead, you
* work with <CODE>LDAPFilter</CODE> objects created from the
* <CODE>LDAPFilter</CODE> objects and <CODE>LDAPFilterDescriptor</CODE>
* objects.
* <P>
*
* This constructor uses the string value for a search scope in
* addition to other information to construct an <CODE>LDAPFilter</CODE>
* object. The string value of the search scope can be one of the
* following:
* <ul>
* <li><CODE>&quot;base&quot;</CODE>
* <li><CODE>&quot;onelevel&quot;</CODE>
* <li><CODE>&quot;subtree&quot;</CODE>
* </ul>
*
* If an invalid scope is specified, the constructor throws an
* <CODE>illegalArgumentException</CODE>.
*/
public LDAPFilter ( String strMatchPattern,
String strDelimeter,
String strFilterTemplate,
String strDescription,
String strScope )
throws IllegalArgumentException {
if ( strScope.equals ( "base" ) ) {
m_nScope = LDAPConnection.SCOPE_BASE;
} else if ( strScope.equals ( "onelevel" ) ) {
m_nScope = LDAPConnection.SCOPE_ONE;
} else if ( strScope.equals ( "subtree" ) ) {
m_nScope = LDAPConnection.SCOPE_SUB;
}
m_strMatchPattern = strMatchPattern;
m_strDelimeter = strDelimeter;
m_strFilterTemplate = strFilterTemplate;
m_strDescription = strDescription;
}
/**
* Print out a string representation of the LDAPFilter.
* Basically, it prints out the appropriate fields.
* <P>
*
* For example, suppose you called the method in this way:
* <P>
*
* <PRE>System.out.println(filter.toString());</PRE>
*
* The resulting output might look like this:
* <P>
*
* <PRE>
* matchPtn: "@"
* delim: " "
* filttmpl: "(mail=%v*)"
* descript: "start of email address"
* scope: "LDAPConnection.SCOPE_SUB"
* line: "32"
* FILTER: "(mail=babs@aceindustry.com*)"
* </PRE>
*/
public String toString() {
StringBuffer strBuf = new StringBuffer ( 300 );
strBuf.append ( " matchPtn: \"" + m_strMatchPattern+"\"\n" );
strBuf.append ( " delim: \"" + m_strDelimeter+"\"\n" );
strBuf.append ( " filttmpl: \"" + m_strFilterTemplate+"\"\n" );
strBuf.append ( " descript: \"" + m_strDescription+"\"\n" );
switch ( m_nScope ) {
case LDAPConnection.SCOPE_BASE:
strBuf.append ( " scope: \"LDAPConnection.SCOPE_BASE\"\n" );
break;
case LDAPConnection.SCOPE_ONE:
strBuf.append ( " scope: \"LDAPConnection.SCOPE_ONE\"\n" );
break;
case LDAPConnection.SCOPE_SUB:
strBuf.append ( " scope: \"LDAPConnection.SCOPE_SUB\"\n" );
break;
}
strBuf.append ( " line: \"" + m_nLine+"\"\n" );
strBuf.append ( " FILTER: \"" + m_strFilter+"\"\n" );
return strBuf.toString();
}
/**
* Sets up the filter string, given the string <CODE>strValue</CODE>.
* If the <CODE>strPrefix</CODE> and <CODE>strSuffix</CODE> arguments
* are non-null strings, they are prepended and appended
* to the filter string (respectively).
* <P>
*
* This string, which is available through the <CODE>getFilter()</CODE>
* method, should be suitable for use as search criteria when
* calling the <CODE>LDAPConnection.search()</CODE> method.
* <P>
*
* <b>Notes:</b>
* <P>
*
* <UL>
* <LI>This method <i>does not</i> maintain the affixes
* set with the <CODE>LDAPFilterDescriptor.setFilterAffixes</CODE>
* method, so you
* need to explicitly define any filter prefixes or suffixes here.<p>
*
* <LI> This method only uses the
* strPrefix and strSuffix for this invocation of setupFilter. It
* does not redefine strPrefix and strSuffix for later
* invocations. <p>
* </UL>
* <P>
*
* @see netscape.ldap.util.LDAPFilterDescriptor#setFilterAffixes
* @see #setFilterAffixes
*/
public void setupFilter ( String strValue, String strPrefix,
String strSuffix ) {
createFilterString ( strValue, strPrefix, strSuffix );
}
/**
* Sets up the filter string, given the string <CODE>strValue</CODE>.
* This string, which is available through the <CODE>getFilter()</CODE>
* method, should be suitable for use as search criteria when
* calling the <CODE>LDAPConnection.search()</CODE> method.
* <P>
*
* <b>Note:</b> If you want to specify a filter prefix and suffix,
* you need to explicitly define them by calling the
* <CODE>setFilterAffixes()</CODE> method.
*
* @see netscape.ldap.util.LDAPFilterDescriptor#setFilterAffixes
* @see #setFilterAffixes
*
*/
public void setupFilter ( String strValue ) {
createFilterString ( strValue, null, null );
}
/**
* Create the filter string which can be used in
* LDAPConnection.search() and others given the parameter
* strValue. If strPrefix and strSuffix are non-null strings,
* prepend strPrefix and append strSuffix.
*/
void createFilterString ( String strValue, String strPrefix,
String strSuffix ) {
StringTokenizer strTok =
new StringTokenizer ( strValue, m_strDelimeter );
// Initialize an array of broken up values so that we
// can reference them directly.
String[] aValues = new String[strTok.countTokens()];
int nTokens = strTok.countTokens();
for ( int i = 0; i < nTokens; i++ ) {
aValues[i] = strTok.nextToken();
}
StringBuffer sbFilter = new StringBuffer ( DEFAULT_FILTER_LENGTH);
if ( strPrefix != null ) {
sbFilter.append ( strPrefix );
}
char[] cFilterTemplate = m_strFilterTemplate.toCharArray();
int i = 0;
while ( i < cFilterTemplate.length ) {
if ( cFilterTemplate[i] == '%' ) {
i++;
if ( cFilterTemplate[i] == 'v' ) {
if ( i == (cFilterTemplate.length-1) ) {
sbFilter.append ( strValue );
break;
}
i++;
switch ( cFilterTemplate[i] ) {
case '$':
sbFilter.append ( aValues[aValues.length] );
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
int nValue = Integer.parseInt
( new Character
(cFilterTemplate[i]).toString() );
nValue--;
i++;
if ( cFilterTemplate[i] == '-' ) {
i++;
if ( Character.isDigit ( cFilterTemplate[i] )) {
int nValue2 = Integer.parseInt
( new Character
(cFilterTemplate[i]).toString() );
nValue2--;
for ( int j = nValue; j <= nValue2; j++ ) {
sbFilter.append ( aValues[j] );
sbFilter.append
( ( j == nValue2 ) ? "" : " " );
}
} else {
for ( int j = nValue; j < aValues.length;j++ ) {
sbFilter.append ( aValues[j] );
sbFilter.append
( ( j == aValues.length - 1 ) ? "" : " " );
}
sbFilter.append ( cFilterTemplate[i]);
}
} else {
sbFilter.append ( aValues[nValue] );
sbFilter.append ( cFilterTemplate[i] );
}
break;
// We just got a plain old %v, so insert the
// strValue
default:
sbFilter.append ( strValue );
sbFilter.append ( cFilterTemplate[i] );
break;
}
} else {
sbFilter.append ( "%" );
sbFilter.append ( cFilterTemplate[i] );
}
} else {
sbFilter.append ( cFilterTemplate[i] );
}
i++;
}
if ( strSuffix != null ) {
sbFilter.append ( strSuffix );
}
m_strFilter = sbFilter.toString();
}
/**
* Makes a copy of this <CODE>LDAPFilter</CODE> object.
*/
public Object clone() {
try {
return super.clone();
} catch ( CloneNotSupportedException e ) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* Set the line number from which this filter was created. This
* is used only when the LDAPFilter is created when an
* LDAPFilterDescriptor is initialized from a file/URL/buffer.
*/
void setLine ( int nLine ) {
m_nLine = nLine;
}
/**
* The ldapfilter.conf specifies match patterns in a funny way.
* A "." means "any character" except when used inside of a set of
* square brackets "[]", in which case, the "." means just a
* plain old period (not a * special character).
*
* This function converts periods inside of a set of square
* brackets into a "\." as per normal regexp code.
*/
String convertMatchPattern ( String strMatchPattern ) {
StringBuffer sb = new StringBuffer ( strMatchPattern.length() + 1);
char[] a_cMatchPattern = strMatchPattern.toCharArray();
boolean bInBrackets = false;
for ( int i = 0; i < a_cMatchPattern.length; i++ ) {
if ( a_cMatchPattern[i] == '.' ) {
if ( bInBrackets ) {
sb.append ( "\\" );
}
} else if ( a_cMatchPattern[i] == '[' ) {
bInBrackets = true;
} else if ( a_cMatchPattern[i] == ']' ) {
bInBrackets = false;
}
sb.append ( a_cMatchPattern[i] );
}
return sb.toString();
}
/**
* Returns the filter string. This method will return null if the
* filter string has not been calculated by the <CODE>setupFilter()</CODE>,
* <CODE>getFilter (strValue)</CODE>, or <CODE>getFilter (strValue,
* strPrefix, strSuffix )</CODE> methods.
*
* @see #setupFilter
* @see #getFilter
*/
public String getFilter () {
return m_strFilter;
}
/**
* Create a filter string given a string value. This method uses
* any Prefixes or Suffixes that have been set by the
* setFilterAffixes() method.<p>
*
* This is the same as doing:
* <pre>
* setupFilter ( strValue );
* getFilter();
* </pre>
*/
public String getFilter ( String strValue ) {
createFilterString ( strValue, m_strPrefix, m_strSuffix );
return m_strFilter;
}
/**
* Create a filter string given a string value. If strPrefix
* and/or strSuffix is non-null, these values are prepended and
* appended to the returned string.<p>
*
* This is the same as doing:
* <pre>
* setupFilter ( strValue, strPrefix, strSuffix );
* getFilter();
* </pre>
*/
public String getFilter ( String strValue, String strPrefix,
String strSuffix ) {
createFilterString ( strValue, strPrefix, strSuffix );
return m_strFilter;
}
/**
* Return this filter's match pattern. The match pattern is
* found as the first token in a filter configuration line in the
* ldapfilter.conf file.
*/
public String getMatchPattern() {
return m_strMatchPattern;
}
/**
* Return this filter's delimeter. The delmimeter is
* found as the second token in a filter configuration line in the
* ldapfilter.conf file.
*/
public String getDelimeter() {
return m_strDelimeter;
}
/**
* Return this filter's filter template. The filter template is
* found as the third token in a filter configuration line in the
* ldapfilter.conf file.
*/
public String getFilterTemplate() {
return m_strFilterTemplate;
}
/**
* Return this filter's description. The description is
* found as the fourth token in a filter configuration line in the
* ldapfilter.conf file.
*/
public String getDescription() {
return m_strDescription;
}
/**
* Return this filter's scope. The scope is
* found as the fifth (optional) token in a filter configuration
* line in the ldapfilter.conf file.
*/
public String getScope() {
switch ( m_nScope ) {
case LDAPConnection.SCOPE_BASE:
return "base";
case LDAPConnection.SCOPE_ONE:
return "onelevel";
case LDAPConnection.SCOPE_SUB:
return "subtree";
default:
return "UNKNOWN!";
}
}
/**
* Return this filter's line number. The line number is
* mostly a debugging variable to let the developer know which
* filter from the filter configuration file is being used.
*/
public String getLineNumber() {
return Integer.toString ( m_nLine );
}
public void setFilterAffixes ( String strPrefix, String strSuffix ) {
m_strPrefix = strPrefix;
m_strSuffix = strSuffix;
}
}

View File

@@ -0,0 +1,496 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.util;
import java.io.*;
import java.util.*;
import java.net.*;
import com.oroinc.text.regex.*;
import netscape.ldap.*;
/**
* Represents an LDAP filter configuration file read into memory.
* <P>
*
* Once you read in a filter file to create an object of this class,
* you can access the filter information through the methods that create
* <CODE>LDAPFilterList</CODE> and <CODE>LDAPFilter</CODE> objects.
* (You do not need to manually construct these objects yourself.)
* <P>
*
* This class (along with the other LDAP filter classes) provide
* functionality equivalent to the LDAP filter functions in the LDAP C API.
* <p>
*
* The format of the file/URL/buffer must be that as defined in the
* ldapfilter.conf(5) man page from the University of Michigan LDAP-3.3
* distribution. <p>
*
* The LDAP filter classes provide a powerful way to configure LDAP clients
* by modifying a configuration file.<p>
*
* The following is a short example for how to use the
* LDAP filter classes.
*
* <pre>
*
* // ... Setup LDAPConnection up here ...
* <p>
*
* LDAPFilterDescriptor filterDescriptor;
* <p>
*
* // Create the LDAPFilterDescriptor given the file
* // "ldapfilter.conf".
* try {
* filterDescriptor = new LDAPFilterDescriptor ( "ldapfilter.conf" );
* <p>
*
* // Now retrieve the Filters in the form of an
* // LDAPFilterList
* LDAPFilterList filterList = new filterDescriptor.getFilters("match_tag", "string_user_typed");
* <p>
*
* // For each filter, do the search. Normally, you wouldn't
* // do the search if the first filter matched, but this is
* // just showing the enumeration type aspects of
* // LDAPFilterList
* LDAPFilter filter;
* while ( filterList.hasMoreElements() ) {
* filter = filterList.next();
* LDAPResults results = LDAPConnection.search (
* strBase, // base DN
* filter.getScope(), // scope
* filter.getFilter(), // completed filter
* null, // all attribs
* false ); // attrsOnly?
* }
* <p>
*
* // ...more processing here...
* } catch ( BadFilterException e ) {
* System.out.println ( e.toString() );
* System.exit ( 0 );
* } catch ( IOException e ) {
* // ...handle exception here...
* }
* </pre>
*
*
* @see LDAPFilterList
* @see LDAPFilter
* @version 1.0
*/
public class LDAPFilterDescriptor {
private Vector m_vFilterSet = new Vector();
private String m_strLine;
private int m_nLine;
private String m_strPrefix;
private String m_strAffix;
private LDAPIntFilterSet m_tmpFilterSet = null;
private String m_strLastMatchPattern = null;
private String m_strLastDelimiter = null;
/**
* The Default scope is used when a scope is not defined
* in the filter file. The scope is the only "optional" parameter
* in the file.
*/
private static final int DEFAULT_SCOPE = LDAPConnection.SCOPE_SUB;
/**
* Creates an LDAPFilterDescriptor object from an existing filter
* configuration file. This file has the format as defined in the
* ldapfilter.conf(5) man page.
*
* @exception netscape.ldap.util.BadFilterException
* One of the filters was not generated properly. Most likely
* this is due to an improperly formatted ldapfilter.conf file.
*/
public LDAPFilterDescriptor ( String strFile )
throws FileNotFoundException, BadFilterException {
DataInputStream inputStream =
new DataInputStream ( new FileInputStream ( strFile ) );
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
init( reader );
}
/**
* Creates an LDAPFilterDescriptor object from an existing
* StringBuffer. This file has the format as defined in the
* ldapfilter.conf(5) man page.
*
* @exception netscape.ldap.util.BadFilterException
* One of the filters was not generated properly. Most likely
* this is due to an improperly formatted ldapfilter.conf file.
*/
public LDAPFilterDescriptor ( StringBuffer strBuffer )
throws BadFilterException {
init( strBuffer );
}
/**
* Creates an LDAPFilterDescriptor object from a URL.
* This file has the format as defined in the
* ldapfilter.conf(5) man page.
*
* @exception netscape.ldap.util.BadFilterException
* One of the filters was not generated properly. Most likely
* this is due to an improperly formatted ldapfilter.conf file.
*/
public LDAPFilterDescriptor ( URL url )
throws IOException, BadFilterException {
URLConnection urlc = url.openConnection();
DataInputStream inputStream =
new DataInputStream ( urlc.getInputStream() );
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
init( reader );
}
/**
* This function initializes the LDAPFilterDescriptor. It's
* called internally, and should never be called directly by the
* developer.
*/
private void init ( Object inputObj)
throws BadFilterException {
String strCommentPattern = "(?:^\\s*#|^\\s*$)";
String strDataPattern = "(?:\\s*\"([^\"]*)\"|([^\\s]*))\\s*";
Perl5Compiler compiler = new Perl5Compiler();
Perl5Pattern patComment;
Perl5Pattern patData;
Vector vStrings = new Vector ( 5 );
try {
patComment = (Perl5Pattern)compiler.compile ( strCommentPattern );
patData = (Perl5Pattern)compiler.compile ( strDataPattern );
} catch ( MalformedPatternException e ) {
// This should NEVER happen...
System.out.println ( "FATAL Error, couldn't compile pattern");
System.out.println ( " " + e.getMessage() );
return;
}
// Setup some temporary variables.
m_nLine = 0;
try {
if (inputObj instanceof StringBuffer) {
StringBuffer ibuffer = (StringBuffer)inputObj;
StringBuffer buffer = new StringBuffer();
for (int i=0; i<ibuffer.length(); i++) {
if (ibuffer.charAt(i) == '\n') {
m_strLine = buffer.toString();
m_nLine++;
setFilter(patComment, patData, vStrings);
buffer = new StringBuffer();
} else
buffer.append(ibuffer.charAt(i));
}
} else {
while ((m_strLine=((BufferedReader)inputObj).readLine()) != null) {
m_nLine++;
setFilter(patComment, patData, vStrings);
}
}
// BUGBUG: Fixed. 7-28-97
// We're done with the input, so we need to append the
// last temporary FilterSet into the list of FilterSets.
if ( m_tmpFilterSet != null ) {
m_vFilterSet.addElement ( m_tmpFilterSet );
}
} catch ( IOException e ) {
}
}
private void setFilter(Perl5Pattern patComment, Perl5Pattern patData,
Vector vStrings) throws IOException, BadFilterException {
MatchResult result;
Perl5Matcher matcher = new Perl5Matcher();
PatternMatcherInput input;
LDAPFilter tmpFilter = null;
input = new PatternMatcherInput ( m_strLine );
if ( ! ( matcher.contains ( input, patComment ) ) ) {
input.setCurrentOffset(input.getBeginOffset());
// System.out.println ( "\nNEW LINE: " + m_strLine );
if ( ! vStrings.isEmpty() ) {
vStrings.removeAllElements();
}
while ( matcher.contains ( input, patData ) ) {
// Within this while loop, we're looking for
// all the data tokens. Our regular
// expression is setup to look for words
// separated by whitespace or sets of
// characters in quotataion marks. A remnant
// of the regexp is that we have two
// backreferences, only one will have data at
// any time.
result = matcher.getMatch();
for ( int i = 1; i <=2; i++ ) {
if ( result.group(i) != null ) {
if ( ! result.group(i).equals ( "" ) ) {
//System.out.println ( "Match #" + i +
// ": \"" + result.group(i) + "\"" );
vStrings.addElement ( result.group(i));
}
}
}
}
switch ( vStrings.size() ) {
case 1:
// If the current filter set is not null,
// add it to the filter set vector.
if ( m_tmpFilterSet != null ) {
m_vFilterSet.addElement ( m_tmpFilterSet );
}
// Now create a new filterset.
m_tmpFilterSet = new LDAPIntFilterSet
( (String)vStrings.elementAt ( 0 ) );
break;
// Two tokens mens we're the the second (or
// higher line in a token. We need to append
// the information stored in the list onto
// the tmpFilter.
case 2:
if ( ( m_strLastMatchPattern != null ) &&
( m_strLastDelimiter != null ) ) {
tmpFilter = new LDAPFilter(
m_strLastMatchPattern,
m_strLastDelimiter,
(String)vStrings.elementAt ( 0 ),
(String)vStrings.elementAt ( 1 ),
DEFAULT_SCOPE );
tmpFilter.setLine ( m_nLine );
if ( m_tmpFilterSet != null ) {
m_tmpFilterSet.appendFilter ( tmpFilter );
} else {
throw MakeException ( "Attempting to add a filter to a null filterset" );
}
} else {
throw MakeException ( "Attempting to create a relative filter with no preceeding full filter" );
}
break;
// Three tokens means we're the second (or
// higher line in a filter. create a new
// filter grabbing info from the last filter
case 3:
if ( ( m_strLastMatchPattern != null ) &&
( m_strLastDelimiter != null ) ) {
tmpFilter = new LDAPFilter (
m_strLastMatchPattern,
m_strLastDelimiter,
(String)vStrings.elementAt ( 0 ),
(String)vStrings.elementAt ( 1 ),
(String)vStrings.elementAt ( 2 ) );
tmpFilter.setLine ( m_nLine );
if ( m_tmpFilterSet != null ) {
m_tmpFilterSet.appendFilter ( tmpFilter );
} else {
throw MakeException
("Attempting to add a filter to a null filterset");
}
} else {
throw MakeException
("Attempting to create a relative filter with no preceeding full filter" );
}
break;
// 4 tokens means this is the first line in a
// token. All data is new. However, we're using
// the default scope.
case 4:
tmpFilter = new LDAPFilter (
(String)vStrings.elementAt ( 0 ),
(String)vStrings.elementAt ( 1 ),
(String)vStrings.elementAt ( 2 ),
(String)vStrings.elementAt ( 3 ),
DEFAULT_SCOPE );
tmpFilter.setLine ( m_nLine );
m_strLastMatchPattern = (String)vStrings.elementAt ( 0 );
m_strLastDelimiter = (String)vStrings.elementAt ( 1 );
if ( m_tmpFilterSet != null ) {
m_tmpFilterSet.newFilter ( tmpFilter );
} else {
throw MakeException
("Attempting to add a filter to a null filterset");
}
break;
// 5 tokens means this is the first line in a
// token. All data is new.
case 5:
tmpFilter = new LDAPFilter (
(String)vStrings.elementAt ( 0 ),
(String)vStrings.elementAt ( 1 ),
(String)vStrings.elementAt ( 2 ),
(String)vStrings.elementAt ( 3 ),
(String)vStrings.elementAt ( 4 ) );
tmpFilter.setLine ( m_nLine );
m_strLastMatchPattern = (String)vStrings.elementAt ( 0 );
m_strLastDelimiter = (String)vStrings.elementAt ( 1 );
if ( m_tmpFilterSet != null ) {
m_tmpFilterSet.newFilter ( tmpFilter );
} else {
throw MakeException
("Attempting to add a filter to a null filterset");
}
break;
default:
throw MakeException ( "Wrong number of tokens (" + vStrings.size() + ")" );
//break;
}
}
}
/**
* just a utility method to create an exception.
*/
private BadFilterException MakeException ( String strMsg ) {
return new BadFilterException
( "BadFilterException while creating Filters,\n" +
"Line Number: " + m_nLine +
",\n --> " + m_strLine + "\nThe error is: " +
strMsg, m_nLine );
}
/**
* Output a text dump of this filter descriptor. It cycles
* through all of the internal LDAPIntFilterSet objects and calls
* their toString() methods.
*
* @see LDAPIntFilterSet#toString
*/
public String toString() {
StringBuffer strBuf = new StringBuffer ( 4000 );
for ( int i = 0; i < m_vFilterSet.size(); i++ ) {
strBuf.append ( "Filter Set number: " + i + "\n" );
strBuf.append (
((LDAPIntFilterSet)m_vFilterSet.elementAt ( i )).toString() +
"\n" );
strBuf.append ( "\n" );
//System.out.println ( (m_vFilterSet.elementAt ( i )).toString());
}
return strBuf.toString();
}
/**
* Return all the filters which match the strTagPat (regular
* expression), and the user input (strValue)
*/
public LDAPFilterList getFilters ( String strTagPat, String strValue )
throws IllegalArgumentException {
strTagPat = strTagPat.trim();
strValue = strValue.trim();
if ( ( strTagPat == null ) || ( strTagPat.equals ("") ) ) {
throw new IllegalArgumentException
( "The Tag Pattern can not be null" );
}
if ( ( strValue == null ) || ( strValue.equals ("") ) ) {
throw new IllegalArgumentException ( "The Value can not be null" );
}
LDAPFilterList retList = new LDAPFilterList();
Perl5Compiler compiler = new Perl5Compiler();
Perl5Pattern patTag; // The strTagPat that's compiled
// For efficiency, we're pre-allocating a patternMatcherInput
// here.
PatternMatcherInput matcherValue = new PatternMatcherInput ( strValue );
// first we need to make a new regexp from the strTagPat
// For efficiency, we're precompiling the strTagPat into
// a pattern here. That pattern doesn't change, the Tag string
// changes per LDAPFIlterSet.
try {
patTag = (Perl5Pattern)compiler.compile ( strTagPat );
} catch ( MalformedPatternException e ) {
throw new IllegalArgumentException
( "The parameter: " + strTagPat + " is not valid" );
}
// We "ask" each of the filterset's to see if there is
// a matching filter.
boolean bMatched = false;
int i = 0;
while ( ! bMatched ) {
Vector vMatchingFilters =
((LDAPIntFilterSet)m_vFilterSet.elementAt ( i )).getFilters
(patTag, matcherValue );
if ( vMatchingFilters.size() > 0 ) {
for ( int j = 0; j < vMatchingFilters.size(); j++ ) {
LDAPFilter tmpFilter =
(LDAPFilter)
((LDAPFilter)
vMatchingFilters.elementAt ( j )).clone();
tmpFilter.setupFilter ( strValue, m_strPrefix,
m_strAffix );
bMatched = true; // this really doesn't matter.
retList.add ( tmpFilter );
}
return retList;
}
i++;
}
return null;
}
/**
* Prepend the parameter (strPrefix) and append the second
* parameter (strAffix) to every filter that is returned by the
* getFilters() method. <p>
*/
public void setFilterAffixes ( String strPrefix, String strAffix ) {
m_strPrefix = strPrefix;
m_strAffix = strAffix;
}
}

View File

@@ -0,0 +1,101 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.util;
import java.util.*;
/**
* The list of LDAPFilter objects returned from a LDAPFilterDescriptor
* Object. Note that this is an enumeration, so if multiple iterations
* are needed, save the results.
*
* @see LDAPFilterDescriptor
* @see LDAPFilter
* @version 1.0
*/
public class LDAPFilterList implements Enumeration {
private Vector m_vFilterList;
private static int DEFAULT_LIST_SIZE = 2;
/**
* Constructs an LDAPFilterList object. This methos shouldn't need to
* be called by the developer directly. Construction of the
* LDAPFilterList object should take place when the Prepare function
* of LDAPFilterDescriptor is called.
*
*/
public LDAPFilterList () {
m_vFilterList = new Vector ( DEFAULT_LIST_SIZE );
}
/**
* Add an LDAPFilter to the private vector. Since the filter we're
* being passed has already been cloned from the master
* LDAPFilterDescriptor set, all we have to do is add it to the list.
*/
void add ( LDAPFilter filter ) {
m_vFilterList.addElement ( filter );
}
/**
* Returns true if there are any LDAPFilter objects to returned.
*/
public boolean hasMoreElements() {
return ( ! m_vFilterList.isEmpty() );
}
/**
* Returns the next LDAPFilter as an Object. Note: the preferred way
* to return the next LDAPFilter is to call next()
*
* @see LDAPFilterList#next()
* @return The next LDAPFilter object (as an instance of Object)
*/
public Object nextElement() {
Object o = m_vFilterList.firstElement();
m_vFilterList.removeElementAt ( 0 );
return o;
}
/**
* Returns the next LDAPFilter
*
* @return The next LDAPFilter
*/
public LDAPFilter next() {
Object o = m_vFilterList.firstElement();
m_vFilterList.removeElementAt ( 0 );
return (LDAPFilter)o;
}
/**
* Return the number of filters in the filter list.
* Note that this number decreases every time next() or nextElement() is
* called because the elements are removed as they're returned.
*/
public int numFilters (){
return m_vFilterList.size();
}
}

View File

@@ -0,0 +1,118 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.util;
import java.util.*;
import com.oroinc.text.regex.*;
/**
* Represents an Internal LDAPFilterList object. This is an internal object
* that should never be instantiated directly by the developer. We
* store all filters that have the same match pattern here.
*/
public class LDAPIntFilterList {
private Vector m_vFilter;
private String m_strMatchPattern;
// a regexp pattern of m_strMatchPattern
private Perl5Pattern m_patMatch = null;
private Perl5Matcher m_matcher;
private Perl5Compiler m_compiler;
LDAPIntFilterList ( LDAPFilter filter ) throws
BadFilterException {
m_strMatchPattern = filter.getMatchPattern();
// We're going to compile the pattern for strMatchPattern
// now, so that we can throw an exception if it is a bad
// pattern.
m_matcher = new Perl5Matcher();
m_compiler = new Perl5Compiler();
try {
m_patMatch = (Perl5Pattern)m_compiler.compile
( m_strMatchPattern );
} catch ( MalformedPatternException e ) {
throw new BadFilterException (
"The Regular Expression for this filter is bad. " +
"Line number: " + filter.getLineNumber() );
}
m_vFilter = new Vector();
m_vFilter.addElement ( filter );
}
/**
* Add a "relative" filter to an existing filter list. We do this
* becuse the ldapfilter file defines that we can have multiple
* filters per match pattern (and delimeter). This method is
* called by the parent LDAPIntFilterSet because the file specified
* a "relative" filter (a filter in the ldapfilter.conf file that
* only has 2 or 3 tokens).
*/
void AddFilter ( LDAPFilter filter ) {
m_vFilter.addElement ( filter );
}
/**
* Return the number of Filters this InternalFilterList contains.
*/
// Since we're storing the filters as a vector, just return
// Vector.size().
int numFilters () {
return m_vFilter.size();
}
public String toString() {
StringBuffer strBuf = new StringBuffer ( 100 );
strBuf.append ( " Match Pattern: \"" + m_strMatchPattern + "\"\n" );
for ( int i = 0; i < m_vFilter.size(); i++ ) {
strBuf.append ( ((LDAPFilter)m_vFilter.elementAt(i)).toString() );
strBuf.append ( "\n" );
}
return strBuf.toString();
}
/**
* Return the requested filter.
*/
LDAPFilter getFilter ( int nFilter ) {
return (LDAPFilter)m_vFilter.elementAt ( nFilter );
}
/**
* Try to match the filter to the given string. This method is called
* when the user types in data. We match the expression (stored in
* m_strMatchPattern) to the value that the user typed in (the
* parameter to this method).
*/
boolean MatchFilter ( PatternMatcherInput matcherValue ) {
matcherValue.setCurrentOffset ( matcherValue.getBeginOffset() );
return m_matcher.contains ( matcherValue, m_patMatch );
}
}

View File

@@ -0,0 +1,163 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.util;
import java.util.*;
import com.oroinc.text.regex.*;
/**
* Represents an LDAPIntFilterSet object. This is an internal object that
* should never be instantiated directly by the developer.
*/
public class LDAPIntFilterSet {
private Vector m_vLDAPIntFilterList;
private String m_strTag;
private PatternMatcherInput m_matcherTag = null;
private Perl5Matcher m_matcher = null;
/**
* Return a Vector of filters that match botht the tag pattern
* (in Perl5Pattern form), and the string strValue. This method
* should only be called by LDAPFilterDescriptor().
*/
// remember, we have the string (m_strTag), the pattern has
// been precompiled by the LDAPFilterDescriptor (patTag)
Vector getFilters ( Perl5Pattern patTag,
PatternMatcherInput matcherValue ) {
Vector vRet = new Vector();
if ( m_matcherTag == null ) {
m_matcher = new Perl5Matcher();
m_matcherTag = new PatternMatcherInput ( m_strTag );
} else {
m_matcherTag.setCurrentOffset ( m_matcherTag.getBeginOffset() );
}
// Check to see if the strTag (converted into patTag)
// matches the tag string from the file (converted into
// m_matcherTag)
if ( m_matcher.contains ( m_matcherTag, patTag ) ) {
LDAPIntFilterList tmpIntFilterList;
LDAPFilter tmpFilter;
for ( int i = 0; i < m_vLDAPIntFilterList.size(); i++ ) {
tmpIntFilterList =
(LDAPIntFilterList)m_vLDAPIntFilterList.elementAt ( i );
if ( tmpIntFilterList.MatchFilter ( matcherValue ) ) {
for (int j=0; j < tmpIntFilterList.numFilters(); j++ ) {
vRet.addElement ( tmpIntFilterList.getFilter ( j ));
}
// potential BUGBUG, i'm not sure if we want
// to get out of this loop now or if we just
// want to get out of the external loop. For
// now, go with the former.
return vRet;
}
}
}
return vRet;
}
/**
* Create an LDAPIntFilterSet with a given Tag string. The tag
* string specifies which applications or query types should use
* this filter set. It is normally a single token on a line by
* itself in the filter configuration file. <p>
* For more information about the filter configuration file, see
* the man page for ldapfilter.conf.
*/
public LDAPIntFilterSet ( String strTag ) {
m_strTag = strTag;
m_vLDAPIntFilterList = new Vector();
}
/**
* Add a new filter to this filter set.
*
* @exception netscape.ldap.util.BadFilterException
* If the regular expression pattern given in the first token
* is bad.
*/
void newFilter ( LDAPFilter filter ) throws BadFilterException {
LDAPIntFilterList tmpFilterList = new LDAPIntFilterList( filter );
m_vLDAPIntFilterList.addElement ( tmpFilterList );
}
/**
* Append a new filter to the existing set. This happens when the
* LDAPFilterDescriptor object reads a line from the filter
* configuration file that has 2 or 3 tokens.
*/
void appendFilter ( LDAPFilter filter ) {
((LDAPIntFilterList)m_vLDAPIntFilterList.lastElement()).AddFilter ( filter );
}
/**
* Return true if this filter set matches the regular expression
* string that is passed in.
*/
boolean match ( String strTagPat ) {
Perl5Matcher matcher = new Perl5Matcher();
Perl5Compiler compiler = new Perl5Compiler();
PatternMatcherInput input;
Perl5Pattern patTag;
MatchResult result;
try {
patTag = (Perl5Pattern)compiler.compile ( strTagPat );
} catch ( MalformedPatternException e ) {
// Need to do something here.
return false;
}
input = new PatternMatcherInput ( m_strTag );
if ( matcher.contains ( input, patTag ) ) {
return true;
} else {
return false;
}
}
/**
* Print out the String representation of this object. It calls
* the toString() method of all the LDAPFilter objects contained
* within it's set.
*
* @see LDAPFilter#toString()
*/
public String toString() {
StringBuffer strBuf = new StringBuffer ( 2000 );
strBuf.append ( " strTag: " + m_strTag + "\n" );
for ( int i = 0; i < m_vLDAPIntFilterList.size(); i++ ) {
strBuf.append ( " filter #: " + i + "\n" );
strBuf.append (
((LDAPIntFilterList)m_vLDAPIntFilterList.elementAt(i)).toString() );
strBuf.append ( "\n" );
}
return strBuf.toString();
}
}

View File

@@ -0,0 +1,127 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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

@@ -0,0 +1,239 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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,144 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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,73 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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,150 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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

@@ -0,0 +1,125 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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";
}

View File

@@ -0,0 +1,8 @@
Jar files in this directory are used only for compilation and are
not to be distributed.
jaas.jar
required for SASL code compilation
jnet.jar and jsse.jar
required for JSSESocketFactory.java compilation

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,92 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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,440 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import java.io.*;
/**
* 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 make 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 make 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 make 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 make 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 <code>true</code>, 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 <code>true</code>, 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.
* @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 from which to search
* @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 those entries that are one level below 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 to return in the search results
* @param typesOnly if <code>true</code>, returns the names but not the values of the
* attributes found. If <code>false</code>, returns the names and values of the
* 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 from which to search
* @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 those entries that are one level below 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 to return in the search results
* @param typesOnly if <code>true</code>, returns the names but not the values of the
* attributes found. If <code>false</code>, 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;
/**
* Compares an attribute value with one in the directory. The result
* is 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 the specified request. If it is null, a listener object is created internally.
* @return LDAPResponseListener handler for messages returned from a server
* in response to the specified request.
* @exception LDAPException Failed to send request.
*/
public LDAPResponseListener compare(String dn,
LDAPAttribute attr,
LDAPResponseListener listener)
throws LDAPException;
/**
* Compares an attribute value with one in the directory. The result
* is 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 the specified 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 the specified 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 an 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

@@ -0,0 +1,536 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.io.*;
import java.util.*;
import netscape.ldap.ber.stream.*;
/**
* Represents the name and values of an attribute in an entry.
*
* @version 1.0
* @see netscape.ldap.LDAPAttributeSet
*/
public class LDAPAttribute implements java.io.Serializable {
static final long serialVersionUID = -4594745735452202600L;
private String name = null;
private byte[] nameBuf = null;
/**
* Internally, this is a list of "byte[]"-based attribute values.
*/
private Object values[] = new Object[0];
/**
* Constructs an attribute from another existing attribute.
* Effectively, this makes a copy of the existing attribute.
* @param attr the attribute to copy
*/
public LDAPAttribute( LDAPAttribute attr ) {
name = attr.name;
nameBuf = attr.nameBuf;
values = new Object[attr.values.length];
for (int i = 0; i < attr.values.length; i++) {
values[i] = new byte[((byte[])attr.values[i]).length];
System.arraycopy((byte[])attr.values[i], 0, (byte[])values[i], 0,
((byte[])attr.values[i]).length);
}
}
/**
* Constructs an attribute with no values.
* @param attrName name of the attribute
*/
public LDAPAttribute( String attrName ) {
name = attrName;
}
/**
* Constructs an attribute with a byte-formatted value.
* @param attrName name of the attribute
* @param attrValue value of the attribute in byte format
*/
public LDAPAttribute( String attrName, byte[] attrValue ) {
name = attrName;
addValue(attrValue);
}
/**
* Constructs an attribute that has a single string value.
* @param attrName name of the attribute
* @param attrValue value of the attribute in String format
*/
public LDAPAttribute( String attrName, String attrValue ) {
name = attrName;
addValue( attrValue );
}
/**
* Constructs an attribute that has an array of string values.
* @param attrName name of the attribute
* @param attrValues the list of string values for this attribute
*/
public LDAPAttribute( String attrName, String[] attrValues ) {
name = attrName;
if (attrValues != null) {
setValues( attrValues );
}
}
/**
* Constructs an attribute from a BER (Basic Encoding Rules) element.
* (The protocol elements of LDAP are encoded for exchange using the
* Basic Encoding Rules.)
* @param element element that you want translated into an attribute
* @exception IOException The attribute could not be created from
* the specified element.
*/
public LDAPAttribute(BERElement element) throws IOException {
BERSequence seq = (BERSequence)element;
BEROctetString type = (BEROctetString)seq.elementAt(0);
nameBuf = type.getValue();
BERSet set = (BERSet)seq.elementAt(1);
if (set.size() > 0) {
Object[] vals = new Object[set.size()];
for (int i = 0; i < set.size(); i++) {
vals[i] = ((BEROctetString)set.elementAt(i)).getValue();
}
setValues( vals );
}
}
/**
* Returns the number of values of the attribute.
* @return number of values for this attribute.
*/
public int size() {
return values.length;
}
/**
* Returns an enumerator for the string values of an attribute.
* @return enumerator for the string values.
*/
public Enumeration getStringValues() {
Vector v = new Vector();
synchronized(this) {
try {
for (int i=0; i<values.length; i++) {
if ( values[i] != null ) {
v.addElement(new String ((byte[])values[i], "UTF8"));
} else {
v.addElement( new String( "" ) );
}
}
} catch ( Exception e ) {
return null;
}
}
return v.elements();
}
/**
* Returns the values of the attribute as an array of <CODE>String</CODE>
* objects.
* @return array of attribute values. Each element in the array
* is 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.
* @return a set of attribute values. Each element in the enumeration
* is of type <CODE>byte[]</CODE>.
*/
public Enumeration getByteValues() {
Vector v = new Vector();
synchronized(this) {
for (int i=0; i<values.length; i++) {
if ( values[i] != null ) {
v.addElement(values[i]);
} else {
v.addElement( new byte[0] );
}
}
}
return v.elements();
}
/**
* Returns the values of the attribute in an array of <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.
*/
public String getName() {
if ((name == null) && (nameBuf != null)) {
try{
name = new String(nameBuf, "UTF8");
} catch(Throwable x) {}
}
return name;
}
/**
* Extracts the subtypes from the specified attribute name.
* For example, if the attribute name is <CODE>cn;lang-ja;phonetic</CODE>,
* this method returns an array containing <CODE>lang-ja</CODE>
* and <CODE>phonetic</CODE>.
* <P>
*
* @param attrName name of the attribute from which to extract the subtypes
* @return array of subtypes, or null (if the name has no subtypes).
* @see netscape.ldap.LDAPAttribute#getBaseName
*/
public static String[] getSubtypes(String attrName) {
StringTokenizer st = new StringTokenizer(attrName, ";");
if( st.hasMoreElements() ) {
// First element is base name
st.nextElement();
String[] subtypes = new String[st.countTokens()];
int i = 0;
// Extract the types
while( st.hasMoreElements() )
subtypes[i++] = (String)st.nextElement();
return subtypes;
}
return null;
}
/**
* Extracts the subtypes from the attribute name of the current
* <CODE>LDAPAttribute</CODE> object. For example, if the attribute
* name is <CODE>cn;lang-ja;phonetic</CODE>, this method returns an array
* containing <CODE>lang-ja</CODE> and <CODE>phonetic</CODE>.
*<P>
*
* @return array of subtypes, or null (if the name has no subtypes).
*/
public String[] getSubtypes() {
return getSubtypes(getName());
}
/**
* Extracts the language subtype from the attribute name of the
* <CODE>LDAPAttribute</CODE> object, if any. For example, if the
* attribute name is <CODE>cn;lang-ja;phonetic</CODE>, this method
* returns the String <CODE>lang-ja</CODE>.
*<P>
*
* @return the language subtype, or null (if the name has no
* language subtype).
*/
public String getLangSubtype() {
String[] subTypes = getSubtypes();
if ( subTypes != null ) {
for( int i = 0; i < subTypes.length; i++ ) {
if ((subTypes[i].length() >= 5) &&
(subTypes[i].substring(0, 5).equalsIgnoreCase("lang-")))
return subTypes[i];
}
}
return null;
}
/**
* Extracts the base name from the specified attribute name.
* For example, if the attribute name is <CODE>cn;lang-ja;phonetic</CODE>,
* this method returns <CODE>cn</CODE>.
* <P>
*
* @param attrName name of the attribute from which to extract the base name
* @return base name (the attribute name without any subtypes).
* @see netscape.ldap.LDAPAttribute#getSubtypes
*/
public static String getBaseName(String attrName) {
String basename = attrName;
StringTokenizer st = new StringTokenizer(attrName, ";");
if( st.hasMoreElements() )
// First element is base name
basename = (String)st.nextElement();
return basename;
}
/**
* Extracts the base name from the attribute name of the current
* <CODE>LDAPAttribute</CODE> object. For example, if the attribute
* name is <CODE>cn;lang-ja;phonetic</CODE>, this method returns
* <CODE>cn</CODE>.
* <P>
*
* @return base name (the attribute name without any subtypes).
* @see netscape.ldap.LDAPAttribute#getSubtypes
*/
public String getBaseName() {
return getBaseName(getName());
}
/**
* Reports whether the attribute name contains the specified subtype.
* For example, if you check for the subtype <CODE>lang-en</CODE>
* and the attribute name is <CODE>cn;lang-en</CODE>, this method
* returns <CODE>true</CODE>.
* <P>
*
* @param subtype the single subtype for which you want to check
* @return true if the attribute name contains the specified subtype.
* @see netscape.ldap.LDAPAttribute#getSubtypes
*/
public boolean hasSubtype(String subtype) {
String[] mytypes = getSubtypes();
for(int i = 0; i < mytypes.length; i++) {
if( subtype.equalsIgnoreCase( mytypes[i] ) )
return true;
}
return false;
}
/**
* Reports if the attribute name contains all specified subtypes
* For example, if you check for the subtypes <CODE>lang-en</CODE>
* and <CODE>phonetic</CODE> and the attribute name is
* <CODE>cn;lang-en;phonetic</CODE>, this method returns <CODE>true</CODE>.
* If the attribute name is <CODE>cn;phonetic</CODE> or
* <CODE>cn;lang-en</CODE>, this method returns <CODE>false</CODE>.
* <P>
* @param subtypes an array of subtypes to check
* @return true if the attribute name contains all subtypes
* @see netscape.ldap.LDAPAttribute#getSubtypes
*/
public boolean hasSubtypes(String[] subtypes) {
for(int i = 0; i < subtypes.length; i++) {
if( !hasSubtype(subtypes[i]) )
return false;
}
return true;
}
/**
* Adds a string value to the attribute.
* @param attrValue the string value to add to the attribute
*/
public synchronized void addValue( String attrValue ) {
if (attrValue != null) {
try {
byte[] b = attrValue.getBytes("UTF8");
addValue( b );
} catch(Throwable x)
{}
}
}
/**
* Sets the string values as the attribute's values.
* @param attrValues the string values to use in the attribute
*/
protected void setValues( String[] attrValues ) {
Object[] vals;
if (attrValues != null) {
vals = new Object[attrValues.length];
for (int i = 0; i < vals.length; i++) {
try {
vals[i] = attrValues[i].getBytes("UTF8");
} catch(Throwable x)
{ vals[i] = new byte[0]; }
}
} else {
vals = new Object[0];
}
setValues(vals);
}
/**
* Adds a <CODE>byte[]</CODE>-formatted value to the attribute.
* @param attrValue the <CODE>byte[]</CODE>-formatted value to
* add to the attribute
*/
public synchronized void addValue( byte[] attrValue ) {
if (attrValue != null) {
Object[] vals = new Object[values.length+1];
for (int i = 0; i < values.length; i++)
vals[i] = values[i];
vals[values.length] = attrValue;
values = vals;
}
}
/**
* Sets the byte[] values as the attribute's values.
* @param attrValues the values to use in the attribute
*/
protected synchronized void setValues( Object[] attrValues ) {
values = attrValues;
}
/**
* Removes a string value from the attribute.
* @param attrValue the string value to remove
*/
public synchronized void removeValue( String attrValue) {
if (attrValue != null) {
try{
byte b[] = attrValue.getBytes("UTF8");
removeValue ( b );
} catch(Throwable x)
{}
}
}
/**
* Removes a <CODE>byte[]</CODE>-formatted value from the attribute.
* @param attrValue <CODE>byte[]</CODE>-formatted value to remove
*/
public synchronized void removeValue( byte[] attrValue) {
if ((attrValue == null) || (values == null)|| (values.length < 1))
return;
int ind = -1;
for (int i=0; i<values.length; i++) {
if (equalValue(attrValue, (byte[])values[i])) {
ind = i;
break;
}
}
if (ind >= 0) {
Object[] vals = new Object[values.length-1];
int j = 0;
for (int i = 0; i < values.length; i++) {
if (i != ind) {
vals[j++] = values[i];
}
}
values = vals;
}
}
private static boolean equalValue(byte[] a, byte[] b) {
if (a.length != b.length)
return false;
for (int i=0; i<a.length; i++) {
if (a[i] != b[i])
return false;
}
return true;
}
/**
* Retrieves the BER (Basic Encoding Rules) representation of an attribute.
* (The protocol elements of LDAP are encoded for exchange using the
* Basic Encoding Rules.)
* @return the BER representation of the attribute.
*/
public BERElement getBERElement() {
try {
BERSequence seq = new BERSequence();
seq.addElement(new BEROctetString(getName()));
BERSet set = new BERSet();
for (int i = 0; i < values.length; i++) {
set.addElement(new BEROctetString((byte[])values[i]));
}
seq.addElement(set);
return seq;
} catch (IOException e) {
return null;
}
}
/**
* Retrieves the string representation of attribute parameters.
* @return string representation parameters.
*/
private String getParamString() {
StringBuffer sb = new StringBuffer();
if ( values.length > 0 ) {
for (int i = 0; i < values.length; i++) {
if (i != 0) {
sb.append(",");
}
byte[] val = (byte[])values[i];
try {
sb.append(new String(val, "UTF8"));
} catch (Exception e) {
if (val != null) {
sb.append(val.length);
sb.append(" bytes");
}
else {
sb.append("null value");
}
}
}
}
return "{type='" + getName() + "', values='" + sb.toString() + "'}";
}
/**
* Retrieves the string representation of an attribute
* in an LDAP entry. For example:
*
* <PRE>LDAPAttribute {type='cn', values='Barbara Jensen,Babs Jensen'}</PRE>
*
* @return string representation of the attribute.
*/
public String toString() {
return "LDAPAttribute " + getParamString();
}
}

View File

@@ -0,0 +1,370 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* The definition of an attribute type in the schema.
* <A HREF="http://www.ietf.org/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* Attribute Syntax Definitions</A> covers the types of information
* to specify when defining an attribute type. According to the RFC,
* the description of an attribute type can include the following:
* <P>
*
* <UL>
* <LI>an OID identifying the attribute type
* <LI>a name identifying the attribute type
* <LI>a description of the attribute type
* <LI>the name of the parent attribute type
* <LI>the syntax used by the attribute (for example,
* <CODE>cis</CODE> or <CODE>int</CODE>)
* <LI>an indication of whether the attribute type is single-valued
* or multi-valued
* </UL>
* <P>
*
* 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
* returns schema information as an object with attribute values in this
* 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>
*
* To get the name, OID, and description of this attribute type
* definition, use the <CODE>getName</CODE>, <CODE>getOID</CODE>, and
* <CODE>getDescription</CODE> methods inherited from the abstract class
* <CODE>LDAPSchemaElement</CODE>. Optional and custom qualifiers are
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
* from <CODE>LDAPSchemaElement</CODE>.
* <P>
*
* 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
**/
public class LDAPAttributeSchema extends LDAPSchemaElement {
static final long serialVersionUID = 2482595821879862595L;
/**
* Constructs a blank element.
*/
protected LDAPAttributeSchema() {
super();
}
/**
* 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 syntax syntax of this attribute type. The value of this
* argument can be one of the following:
* <UL>
* <LI><CODE>cis</CODE> (case-insensitive string)
* <LI><CODE>ces</CODE> (case-exact string)
* <LI><CODE>binary</CODE> (binary data)
* <LI><CODE>int</CODE> (integer)
* <LI><CODE>telephone</CODE> (telephone number -- identical to cis,
* but blanks and dashes are ignored during comparisons)
* <LI><CODE>dn</CODE> (distinguished name)
* </UL>
* @param single <CODE>true</CODE> if the attribute type is single-valued
*/
public LDAPAttributeSchema( String name, String oid, String description,
int syntax, boolean single ) {
this( name, oid, description, cisString, single );
syntaxElement.syntax = syntax;
String syntaxType = syntaxElement.internalSyntaxToString( syntax );
if ( syntaxType != null ) {
syntaxElement.syntaxString = syntaxType;
}
setQualifier( SYNTAX, getSyntaxString() );
}
/**
* 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 ) {
this( name, oid, description, syntaxString, single, null, null );
}
/**
* 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
* @param superior superior attribute as a name or OID; <CODE>null</CODE>
* if there is no superior
* @param aliases names which are to be considered aliases for this
* attribute; <CODE>null</CODE> if there are no aliases
*/
public LDAPAttributeSchema( String name, String oid, String description,
String syntaxString, boolean single,
String superior, String[] aliases ) {
super( name, oid, description, aliases );
attrName = "attributetypes";
syntaxElement.syntax = syntaxElement.syntaxCheck( syntaxString );
syntaxElement.syntaxString = syntaxString;
setQualifier( SYNTAX, syntaxElement.syntaxString );
if ( single ) {
setQualifier( SINGLE, "" );
}
if ( (superior != null) && (superior.length() > 0) ) {
setQualifier( SUPERIOR, superior );
}
}
/**
* Constructs an attribute type definition based on a description in
* the AttributeTypeDescription format. For information on this format,
* (see <A HREF="http://www.ietf.org/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
* you search an LDAP server for its schema, the server returns an entry
* with the attributes "objectclasses" and "attributetypes". The
* values of "attributetypes" are attribute type descriptions
* in this format.)
* <P>
*
* @param raw definition of the attribute type in the
* AttributeTypeDescription format
*/
public LDAPAttributeSchema( String raw ) {
attrName = "attributetypes";
parseValue( raw );
String val = (String)properties.get( SYNTAX );
if ( val != null ) {
syntaxElement.syntaxString = val;
syntaxElement.syntax = syntaxElement.syntaxCheck( val );
}
}
/**
* Determines if the attribute type is single-valued.
* @return <code>true</code> if single-valued,
* <code>false</code> if multi-valued.
*/
public boolean isSingleValued() {
return (properties != null) ? properties.containsKey( SINGLE ) :
false;
}
/**
* Gets the name of the attribute that this attribute inherits from,
* if any.
* @return the name of the attribute from which this attribute
* inherits, or <CODE>null</CODE> if it does not have a superior.
*/
public String getSuperior() {
String[] val = getQualifier( SUPERIOR );
return ((val != null) && (val.length > 0)) ? val[0] : null;
}
/**
* Gets the syntax of the schema element
* @return one of the following values:
* <UL>
* <LI><CODE>cis</CODE> (case-insensitive string)
* <LI><CODE>ces</CODE> (case-exact string)
* <LI><CODE>binary</CODE> (binary data)
* <LI><CODE>int</CODE> (integer)
* <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 syntaxElement.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 syntaxElement.syntaxString;
}
/**
* Prepares a value in RFC 2252 format for submission to a server
*
* @param quotingBug <CODE>true</CODE> if SUP and SYNTAX values are to
* be quoted. This is required to work with bugs in certain LDAP servers.
* @return a String ready for submission to an LDAP server.
*/
String getValue( boolean quotingBug ) {
String s = getValuePrefix();
String val = getValue( SUPERIOR, false );
if ( val.length() > 0 ) {
s += val + ' ';
}
val = getOptionalValues( MATCHING_RULES );
if ( val.length() > 0 ) {
s += val + ' ';
}
val = getValue( SYNTAX, quotingBug );
if ( val.length() > 0 ) {
s += val + ' ';
}
if ( isSingleValued() ) {
s += SINGLE + ' ';
}
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;
}
/**
* Gets the definition of the attribute type in a user friendly format.
* This is the format that the attribute type definition uses when
* printing the attribute type or the schema.
* @return definition of the attribute type in a user friendly format.
*/
public String toString() {
String s = "Name: " + name + "; OID: " + oid + "; Type: ";
s += syntaxElement.syntaxToString();
s += "; Description: " + description + "; ";
if ( isSingleValued() ) {
s += "single-valued";
} else {
s += "multi-valued";
}
s += getQualifierString( IGNOREVALS );
s += getAliasString();
return s;
}
// 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";
// Qualifiers known to not have values; prepare a Hashtable
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 which we output explicitly in toString()
static final String[] IGNOREVALS = { SINGLE,
OBSOLETE,
SUPERIOR,
SINGLE,
COLLECTIVE,
NO_USER_MODIFICATION,
SYNTAX};
protected LDAPSyntaxSchemaElement syntaxElement =
new LDAPSyntaxSchemaElement();
}

View File

@@ -0,0 +1,407 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import netscape.ldap.client.*;
import netscape.ldap.client.opers.*;
/**
* Represents a set of attributes (for example, the set of attributes
* in an entry).
*
* @version 1.0
* @see netscape.ldap.LDAPAttribute
*/
public class LDAPAttributeSet implements Cloneable, java.io.Serializable {
static final long serialVersionUID = 5018474561697778100L;
Hashtable attrHash = null;
LDAPAttribute[] attrs = new LDAPAttribute[0];
/* If there are less attributes than this in the set, it's not worth
creating a Hashtable - faster and cheaper most likely to string
comparisons. Most applications fetch attributes once only, anyway */
static final int ATTR_COUNT_REQUIRES_HASH = 5;
/**
* Constructs a new set of attributes. This set is initially empty.
*/
public LDAPAttributeSet() {
}
/**
* Constructs an attribute set.
* @param attrs the list of attributes
*/
public LDAPAttributeSet( LDAPAttribute[] attrs ) {
this.attrs = attrs;
}
public synchronized Object clone() {
try {
LDAPAttributeSet attributeSet = new LDAPAttributeSet();
attributeSet.attrs = new LDAPAttribute[attrs.length];
for (int i = 0; i < attrs.length; i++) {
attributeSet.attrs[i] = new LDAPAttribute(attrs[i]);
}
return attributeSet;
} catch (Exception e) {
return null;
}
}
/**
* Returns an enumeration of the attributes in this attribute set.
* @return enumeration of the attributes in this set.
*/
public Enumeration getAttributes () {
Vector v = new Vector();
synchronized(this) {
for (int i=0; i<attrs.length; i++) {
v.addElement(attrs[i]);
}
}
return v.elements();
}
/**
* Creates a new attribute set containing only the attributes
* that have the specified subtypes.
* <P>
*
* For example, suppose an attribute set contains the following attributes:
* <P>
*
* <PRE>
* cn
* cn;lang-ja
* sn;phonetic;lang-ja
* sn;lang-us
* </PRE>
*
* If you call the <CODE>getSubset</CODE> method and pass
* <CODE>lang-ja</CODE> as the argument, the method returns
* an attribute set containing the following attributes:
* <P>
*
* <PRE>
* cn;lang-ja
* sn;phonetic;lang-ja
* </PRE>
*
* @param subtype semi-colon delimited list of subtypes
* to find within attribute names.
* For example:
* <PRE>
* "lang-ja" // Only Japanese language subtypes
* "binary" // Only binary subtypes
* "binary;lang-ja" // Only Japanese language subtypes
* which also are binary
* </PRE>
* @return attribute set containing the attributes that have
* the specified subtypes.
* @see netscape.ldap.LDAPAttribute
* @see netscape.ldap.LDAPAttributeSet#getAttribute
* @see netscape.ldap.LDAPEntry#getAttributeSet
*/
public LDAPAttributeSet getSubset(String subtype) {
LDAPAttributeSet attrs = new LDAPAttributeSet();
if ( subtype == null )
return attrs;
StringTokenizer st = new StringTokenizer(subtype, ";");
if( st.countTokens() < 1 )
return attrs;
String[] searchTypes = new String[st.countTokens()];
int i = 0;
while( st.hasMoreElements() ) {
searchTypes[i] = (String)st.nextElement();
i++;
}
Enumeration attrEnum = getAttributes();
while( attrEnum.hasMoreElements() ) {
LDAPAttribute attr = (LDAPAttribute)attrEnum.nextElement();
if( attr.hasSubtypes( searchTypes ) )
attrs.add( new LDAPAttribute( attr ) );
}
return attrs;
}
/**
* Returns a single attribute that exactly matches the specified attribute
* name.
* @param attrName name of attribute to return
* For example:
*<PRE>
* "cn" // Only a non-subtyped version of cn
* "cn;lang-ja" // Only a Japanese version of cn
*</PRE>
* @return attribute that has exactly the same name, or null
* (if no attribute in the set matches the specified name).
* @see netscape.ldap.LDAPAttribute
*/
public LDAPAttribute getAttribute( String attrName ) {
prepareHashtable();
if (attrHash != null) {
return (LDAPAttribute)attrHash.get( attrName.toLowerCase() );
} else {
for (int i = 0; i < attrs.length; i++) {
if (attrName.equalsIgnoreCase(attrs[i].getName())) {
return attrs[i];
}
}
return null;
}
}
/**
* Prepares hashtable for fast attribute lookups.
*/
private void prepareHashtable() {
if ((attrHash == null) && (attrs.length >= ATTR_COUNT_REQUIRES_HASH)) {
attrHash = new Hashtable();
for (int j = 0; j < attrs.length; j++) {
attrHash.put( attrs[j].getName().toLowerCase(), attrs[j] );
}
}
}
/**
* Returns the subtype that matches the attribute name specified
* by <CODE>attrName</CODE> and the language specificaton identified
* by <CODE>lang</CODE>.
* <P>
*
* If no attribute in the set has the specified name and subtype,
* the method returns <CODE>null</CODE>.
*
* Attributes containing subtypes other than <CODE>lang</CODE>
* (for example, <CODE>cn;binary</CODE>) are returned only if
* they contain the specified <CODE>lang</CODE> subtype and if
* the set contains no attribute having only the <CODE>lang</CODE>
* subtype. (For example, <CODE>getAttribute( "cn", "lang-ja" )</CODE>
* returns <CODE>cn;lang-ja;phonetic</CODE> only if the
* <CODE>cn;lang-ja</CODE> attribute does not exist.)
* <P>
*
* If null is specified for the <CODE>lang</CODE> argument,
* calling this method is the same as calling the
* <CODE>getAttribute(attrName)</CODE> method.
* <P>
*
* For example, suppose an entry contains only the following attributes:
* <P>
* <UL>
* <LI><CODE>cn;lang-en</CODE>
* <LI><CODE>cn;lang-ja-JP-kanji</CODE>
* <LI><CODE>sn</CODE>
* </UL>
* <P>
*
* Calling the following methods will return the following values:
* <P>
* <UL>
* <LI><CODE>getAttribute( "cn" )</CODE> returns <CODE>null</CODE>.
* <LI><CODE>getAttribute( "sn" )</CODE> returns the "<CODE>sn</CODE>" attribute.
* <LI><CODE>getAttribute( "cn", "lang-en-us" )</CODE> returns the "<CODE>cn;lang-en</CODE>" attribute.
* <LI><CODE>getAttribute( "cn", "lang-en" )</CODE> returns the "<CODE>cn;lang-en</CODE>" attribute.
* <LI><CODE>getAttribute( "cn", "lang-ja" )</CODE> returns <CODE>null</CODE>.
* <LI><CODE>getAttribute( "sn", "lang-en" )</CODE> returns the "<CODE>sn</CODE>" attribute.
*</UL>
* <P>
* @param attrName name of attribute to find in the entry
* @param lang a language specification
* @return the attribute that matches the base name and that best
* matches any specified language subtype.
* @see netscape.ldap.LDAPAttribute
*/
public LDAPAttribute getAttribute( String attrName, String lang ) {
if ( (lang == null) || (lang.length() < 1) )
return getAttribute( attrName );
String langLower = lang.toLowerCase();
if ((langLower.length() < 5) ||
( !langLower.substring( 0, 5 ).equals( "lang-" ) )) {
return null;
}
StringTokenizer st = new StringTokenizer( langLower, "-" );
// Skip first token, which is "lang-"
st.nextToken();
String[] langComponents = new String[st.countTokens()];
int i = 0;
while ( st.hasMoreTokens() ) {
langComponents[i] = st.nextToken();
i++;
}
String searchBasename = LDAPAttribute.getBaseName(attrName);
String[] searchTypes = LDAPAttribute.getSubtypes(attrName);
LDAPAttribute found = null;
int matchCount = 0;
for( i = 0; i < attrs.length; i++ ) {
boolean isCandidate = false;
LDAPAttribute attr = attrs[i];
// Same base name?
if ( attr.getBaseName().equalsIgnoreCase(searchBasename) ) {
// Accept any subtypes?
if( (searchTypes == null) || (searchTypes.length < 1) ) {
isCandidate = true;
} else {
// No, have to check each subtype for inclusion
if( attr.hasSubtypes( searchTypes ) )
isCandidate = true;
}
}
String attrLang = null;
if ( isCandidate ) {
attrLang = attr.getLangSubtype();
// At this point, the base name and subtypes are okay
if ( attrLang == null ) {
// If there are no language attributes, this one is okay
found = attr;
} else {
// We just have to check for language match
st = new StringTokenizer( attrLang.toLowerCase(), "-" );
// Skip first token, which is "lang-"
st.nextToken();
// No match if the attribute's language spec is longer
// than the target one
if ( st.countTokens() > langComponents.length )
continue;
// How many subcomponents of the language match?
int j = 0;
while ( st.hasMoreTokens() ) {
if ( !langComponents[j].equals( st.nextToken() ) ) {
j = 0;
break;
}
j++;
}
if ( j > matchCount ) {
found = attr;
matchCount = j;
}
}
}
}
return found;
}
/**
* Returns the attribute at the position specified by the index.
* For example, if you specify the index 0, the method returns the
* first attribute in the set. The index is 0-based.
*
* @param index index of the attribute to obtain
* @return attribute at the position specified by the index.
*/
public LDAPAttribute elementAt (int index) {
return attrs[index];
}
/**
* Removes the attribute at the position specified by the index.
* For example, if you specify the index 0, the method removes the
* first attribute in the set. The index is 0-based.
*
* @param index index of the attribute to remove
*/
public void removeElementAt (int index) {
if ((index >= 0) && (index < attrs.length)) {
synchronized(this) {
LDAPAttribute[] vals = new LDAPAttribute[attrs.length-1];
int j = 0;
for (int i = 0; i < attrs.length; i++) {
if (i != index) {
vals[j++] = attrs[i];
}
}
if (attrHash != null) {
attrHash.remove(attrs[index].getName().toLowerCase());
}
attrs = vals;
}
}
}
/**
* Returns the number of attributes in this set.
* @return number of attributes in this attribute set.
*/
public int size () {
return attrs.length;
}
/**
* Adds the specified attribute to this attribute set.
* @param attr attribute to add to this set
*/
public synchronized void add( LDAPAttribute attr ) {
if (attr != null) {
LDAPAttribute[] vals = new LDAPAttribute[attrs.length+1];
for (int i = 0; i < attrs.length; i++)
vals[i] = attrs[i];
vals[attrs.length] = attr;
attrs = vals;
if (attrHash != null) {
attrHash.put( attr.getName().toLowerCase(), attr );
}
}
}
/**
* Removes the specified attribute from the set.
* @param name name of the attribute to remove
*/
public synchronized void remove( String name ) {
for( int i = 0; i < attrs.length; i++ ) {
if ( name.equalsIgnoreCase( attrs[i].getName() ) ) {
removeElementAt(i);
break;
}
}
}
/**
* Retrieves the string representation of all attributes
* in the attribute set. For example:
*
* <PRE>
* LDAPAttributeSet: LDAPAttribute {type='cn', values='Barbara Jensen,Babs
* Jensen'}LDAPAttribute {type='sn', values='Jensen'}LDAPAttribute {type='
* givenname', values='Barbara'}LDAPAttribute {type='objectclass', values=
* 'top,person,organizationalPerson,inetOrgPerson'}LDAPAttribute {type='ou',
* values='Product Development,People'}
* </PRE>
*
* @return string representation of all attributes in the set.
*/
public String 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 sb.toString();
}
}

View File

@@ -0,0 +1,48 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
/**
* Performs explicit bind processing on a referral. A client may
* specify an instance of this class for use on a single operation
* (through the <CODE>LDAPConstraints</CODE> object) or 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 of <CODE>LDAPBind</CODE> may access
* the host, port, credentials, and other information in the
* <CODE>LDAPConnection</CODE> in order to decide on an appropriate
* authentication mechanism.<BR>
* The bind method can also 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

@@ -0,0 +1,815 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import java.io.*;
import netscape.ldap.client.*;
import netscape.ldap.util.*;
import java.util.zip.CRC32;
/**
* <CODE>LDAPCache</CODE> represents an in-memory cache that you can use
* to reduce the number of search requests sent to the LDAP server.
* <P>
*
* Each item in the cache represents a search request and
* its results. Each item is uniquely identified by the
* search criteria, which includes:
* <P>
*
* <UL>
* <LI>the host name and port number of the LDAP server
* <LI>the base DN of the search
* <LI>the search filter
* <LI>the scope of the search
* <LI>the attributes to be returned in the search results
* <LI>the DN used to authenticate the client when binding
* to the server
* <LI>the LDAP v3 controls specified in the search request
* </UL>
* <P>
*
* After a search request is cached, the results of any
* subsequent search requests using the same criteria are
* read from the cache. Note that if any part of the
* criteria differs (for example, if a different DN is used
* when binding to the server or if a different set of
* attributes to be returned is specified), the search
* request is sent to the server.
* <P>
*
* When you create the cache, you specify the maximum amount
* of time that an item can be kept in the cache. When an
* item's age exceeds that time limit, the item is removed
* from the cache.
* <P>
*
* The cache also has a maximum size that you specify when
* creating the cache. If adding a new item exceeds the
* maximum size of the cache, the first entries in the cache
* are removed to make enough space for the new item.
* <P>
*
* Finally, when creating the cache, you can specify a list
* of the base DNs in search requests that you want to cache.
* For example, if you specify <CODE>o=Airius.com</CODE> as
* a base DN to cache, your client caches search requests
* where the base DN is <CODE>o=Airius.com</CODE>.
* <P>
*
* To specify that you want to use a cache for a particular
* LDAP session, call the <CODE>setCache</CODE> method of
* the <CODE>LDAPConnection</CODE> object that you are
* working with.
* <P>
*
* All clones of an <CODE>LDAPConnection</CODE> object share
* the same <CODE>LDAPCache</CODE> object.
* <P>
*
* Note that <CODE>LDAPCache</CODE> does not maintain consistency
* with the directory, so that cached search results may no longer be
* valid after a directory update. If the same application is performing
* both cached searches and directory updates, then the
* application should flush the corresponding cache entries after an update.
* To do this use the <CODE>flushEntries</CODE> method.
* <P>
*
* Also, note that search requests that return referrals are not cached.
* <P>
*
* The <CODE>LDAPCache</CODE> class includes methods for
* getting statistics (such as hit rates) from the cache and
* for flushing entries from the cache.
* <P>
*
* @see netscape.ldap.LDAPConnection#setCache(netscape.ldap.LDAPCache)
* @see netscape.ldap.LDAPConnection#getCache
*/
public class LDAPCache implements Serializable {
static final long serialVersionUID = 6275167993337814294L;
private Hashtable m_cache;
private long m_timeToLive;
private long m_maxSize;
private String[] m_dns;
private Vector m_orderedStruct;
private long m_remainingSize = 0;
// Count of LDAPConnections that share this cache
private int m_refCnt = 0;
/**
* Delimiter used internally when creating keys
* for the cache.
*/
public static final String DELIM = "#";
private TTLTimer m_timer = null;
private long m_totalOpers = 0;
private long m_hits = 0;
private long m_flushes = 0;
// Debug can be activated by defining debug.cache property
private static boolean m_debug = false;
static {
try {
String traceProp = System.getProperty("debug.cache");
m_debug = (traceProp != null);
}
catch (Exception e) {
;// In browser access to property might not be allowed
}
}
/**
* Constructs a new <CODE>LDAPCache</CODE> object, using the
* specified maximum size of the cache (in bytes) and the maximum
* age of cached items (in seconds). When items in the cache
* exceed this age, they are removed from the cache.
* <P>
*
* @param ttl the maximum amount of time that an item can be cached
* (in seconds)
* @param size the maximum size of the cache (in bytes)
*/
public LDAPCache(long ttl, long size)
{
init(ttl, size);
}
/**
* Constructs a new <CODE>LDAPCache</CODE> object, using the
* specified maximum size of the cache (in bytes), and the maximum
* age of cached items (in seconds), and an array of the base DNs
* of searches that you want to cache. (For example,
* if the array of base DNs includes <CODE>o=Airius.com</CODE>,
* the cache stores search results if the base DN in the search
* request is <CODE>o=Airius.com</CODE>.)
* <P>
*
* @param ttl the maximum amount of time that an item can be cached
* (in seconds)
* @param size the maximum size of the cache (in bytes)
* @param dns the list of base DNs of searches that you want to cache.
*/
public LDAPCache(long ttl, long size, String[] dns)
{
init(ttl, size);
m_dns = new String[dns.length];
if ((dns != null) && (dns.length > 0))
for (int i=0; i<dns.length; i++) {
m_dns[i] = (new DN(dns[i])).toString();
}
}
/**
* Gets the maximum size of the cache (in bytes).
* <P>
*
* @return the maximum size of the cache (in bytes).
*/
public long getSize()
{
return m_maxSize;
}
/**
* Gets the maximum age allowed for cached items (in
* seconds). (Items that exceed this age are
* removed from the cache.)
* <P>
*
* @return the maximum age of items in the cache (in
* seconds).
*/
public long getTimeToLive()
{
return m_timeToLive/1000;
}
/**
* Gets the array of base DNs of searches to be cached.
* (Search requests with these base DNs are cached.)
* <P>
*
* @return the array of base DNs.
*/
public String[] getBaseDNs()
{
return m_dns;
}
/**
* Flush the entries identified by DN and scope from the cache.
* <P>
*
* @param dn the distinguished name (or base DN) of the entries
* to be removed from the cache. Use this parameter in conjunction
* with <CODE>scope</CODE> to identify the entries that you want
* removed from the cache. If this parameter is <CODE>null</CODE>,
* the entire cache is flushed.
* @param scope the scope identifying the entries that you want
* removed from the cache. The value of this parameter can be
* one of the following:
* <UL>
* <LI><CODE>LDAPv2.SCOPE_BASE</CODE> (to remove the entry identified
* by <CODE>dn</CODE>)
* <LI><CODE>LDAPv2.SCOPE_ONE</CODE> (to remove the entries that
* have <CODE>dn</CODE> as their parent entry)
* <LI><CODE>LDAPv2.SCOPE_SUB</CODE> (to remove the entries in the
* subtree under <CODE>dn</CODE> in the directory)
* </UL>
* <P>
* @return <CODE>true</CODE> if the entry is removed from the cache;
* <CODE>false</CODE> if the entry is not removed.
*/
public synchronized boolean flushEntries(String dn, int scope) {
if (m_debug)
System.out.println("DEBUG: User request for flushing entry: dn "+
dn+" and scope "+scope);
// if the dn is null, invalidate the whole cache
if (dn == null)
{
// reclaim all the cache spaces
m_remainingSize = m_maxSize;
m_cache.clear();
m_orderedStruct.removeAllElements();
// reset stats
m_totalOpers = m_hits = m_flushes = 0;
return true;
}
DN dn2 = new DN(dn);
Enumeration e = m_cache.keys();
while(e.hasMoreElements()) {
Long key = (Long)e.nextElement();
Vector val = (Vector)m_cache.get(key);
int j=1;
int size2=val.size();
for (; j<size2; j++) {
String d = ((LDAPEntry)val.elementAt(j)).getDN();
DN dn1 = new DN(d);
if (dn1.equals(dn2))
break;
if (scope == LDAPConnection.SCOPE_ONE) {
DN parentDN1 = dn1.getParent();
if (parentDN1.equals(dn2)) {
break;
}
}
if ((scope == LDAPConnection.SCOPE_SUB) &&
(dn1.isDescendantOf(dn2))) {
break;
}
}
if (j < size2) {
for (int k=0; k<m_orderedStruct.size(); k++) {
Vector v = (Vector)m_orderedStruct.elementAt(k);
if (key.equals((Long)v.elementAt(0))) {
m_orderedStruct.removeElementAt(k);
break;
}
}
m_cache.remove(key);
if (m_debug)
System.out.println("DEBUG: Successfully removed entry ->"+key);
return true;
}
}
if (m_debug)
System.out.println("DEBUG: The number of keys in the cache is "
+m_cache.size());
return false;
}
/**
* Gets the amount of available space (in bytes) left in the cache.
* <P>
*
* @return the available space (in bytes) in the cache.
*/
public long getAvailableSize() {
return m_remainingSize;
}
/**
* Gets the total number of requests for retrieving items from
* the cache. This includes both items successfully found in
* the cache and items not found in the cache.
* <P>
*
* @return the total number of requests for retrieving items from
* the cache.
*/
public long getTotalOperations() {
return m_totalOpers;
}
/**
* Gets the total number of requests which failed to find and
* retrieve an item from the cache.
* <P>
*
* @return the number of requests that did not find and retrieve
* an item in the cache.
*/
public long getNumMisses() {
return (m_totalOpers - m_hits);
}
/**
* Gets the total number of requests which successfully found and
* retrieved an item from the cache.
* @return the number of requests that successfully found and
* retrieved an item from the cache.
*/
public long getNumHits() {
return m_hits;
}
/**
* Gets the total number of entries that are flushed when timer expires
* and <CODE>flushEntries</CODE> is called.
* <P>
*
* @return the total number of entries that are flushed when timer
* expires.
*/
public long getNumFlushes() {
return m_flushes;
}
/**
* Create a key for a cache entry by concatenating all input parameters
* @return the key for a cache entry
* @exception LDAPException Thrown when failed to create key.
*/
Long createKey(String host, int port, String baseDN, String filter,
int scope, String[] attrs, String bindDN, LDAPConstraints cons)
throws LDAPException {
DN dn = new DN(baseDN);
baseDN = dn.toString();
if (m_dns != null) {
int i=0;
for (; i<m_dns.length; i++) {
if (baseDN.equals(m_dns[i]))
break;
}
if (i >= m_dns.length)
throw new LDAPException(baseDN+" is not a cached base DN",
LDAPException.OTHER);
}
String key = null;
key = appendString(baseDN);
key = key+appendString(scope);
key = key+appendString(host);
key = key+appendString(port);
key = key+appendString(filter);
key = key+appendString(attrs);
key = key+appendString(bindDN);
LDAPControl[] serverControls = null;
LDAPControl[] clientControls = null;
// get server and client controls
if (cons != null)
{
serverControls = cons.getServerControls();
clientControls = cons.getClientControls();
}
if ((serverControls != null) && (serverControls.length > 0))
{
String[] objID = new String[serverControls.length];
for (int i=0; i<serverControls.length; i++) {
LDAPControl ctrl = serverControls[i];
long val = getCRC32(ctrl.getValue());
objID[i] = ctrl.getID() + ctrl.isCritical() + new Long(val).toString();
}
key = key + appendString(objID);
}
else
key = key+appendString(0);
if ((clientControls != null) && (clientControls.length > 0))
{
String[] objID = new String[clientControls.length];
for (int i=0; i<clientControls.length; i++) {
LDAPControl ctrl = clientControls[i];
long val = getCRC32(ctrl.getValue());
objID[i] = ctrl.getID() + ctrl.isCritical() + new Long(val).toString();
}
key = key + appendString(objID);
}
else
key = key+appendString(0);
long val = getCRC32(key.getBytes());
if(m_debug) {
System.out.println("key="+val + " for "+key);
}
return new Long(val);
}
/**
* Gets the cache entry based on the specified key.
* @param key the key for the cache entry
* @return the cache entry.
*/
synchronized Object getEntry(Long key) {
Object obj = null;
obj = m_cache.get(key);
m_totalOpers++;
if (m_debug) {
if (obj == null)
System.out.println("DEBUG: Entry whose key -> "+key+
" not found in the cache.");
else
System.out.println("DEBUG: Entry whose key -> "+key+
" found in the cache.");
}
if (obj != null)
m_hits++;
return obj;
}
/**
* Flush entries which stay longer or equal to the time-to-live.
*/
synchronized void flushEntries()
{
Vector v = null;
boolean delete = false;
long currTime = System.currentTimeMillis();
m_flushes = 0;
while(true) {
if (m_orderedStruct.size() <= 0)
break;
v = (Vector)m_orderedStruct.firstElement();
long diff = currTime-((Long)v.elementAt(1)).longValue();
if (diff >= m_timeToLive) {
Long key = (Long)v.elementAt(0);
if (m_debug)
System.out.println("DEBUG: Timer flush entry whose key is "+key);
Vector entry = (Vector)m_cache.remove(key);
m_remainingSize = m_remainingSize + ((Long)entry.firstElement()).longValue();
// always delete the first one
m_orderedStruct.removeElementAt(0);
m_flushes++;
}
else
break;
}
if (m_debug)
System.out.println("DEBUG: The number of keys in the cache is "
+m_cache.size());
}
/**
* Add the entry to the hashtable cache and to the vector respectively.
* The vector is used to keep track of the order of the entries being added.
* @param key the key for the cache entry
* @param value the cache entry being added to the cache for the specified
* key
* @return a flag indicating whether the entry was added.
*/
synchronized boolean addEntry(Long key, Object value)
{
// if entry exists, dont perform add operation
if (m_cache.get(key) != null)
return false;
Vector v = (Vector)value;
long size = ((Long)v.elementAt(0)).longValue();
if (size > m_maxSize) {
if (m_debug) {
System.out.println("Failed to add an entry to the cache since the new entry exceeds the cache size");
}
return false;
}
// if the size of entry being added is bigger than the spare space in the
// cache
if (size > m_remainingSize) {
while (true) {
Vector element = (Vector)m_orderedStruct.firstElement();
Long str = (Long)element.elementAt(0);
Vector val = (Vector)m_cache.remove(str);
if (m_debug)
System.out.println("DEBUG: The spare size of the cache is not big enough "+
"to hold the new entry, deleting the entry whose key -> "+str);
// always remove the first one
m_orderedStruct.removeElementAt(0);
m_remainingSize = m_remainingSize +
((Long)val.elementAt(0)).longValue();
if (m_remainingSize >= size)
break;
}
}
m_remainingSize = m_remainingSize - size;
m_cache.put(key, v);
Vector element = new Vector();
element.addElement(key);
element.addElement(new Long(System.currentTimeMillis()));
m_orderedStruct.addElement(element);
// Start TTL Timer if first entry is added
if (m_orderedStruct.size() == 1) {
scheduleTTLTimer();
}
if (m_debug)
{
System.out.println("DEBUG: Adding a new entry whose key -> "+key);
System.out.println("DEBUG: The current number of keys in the cache "+
m_cache.size());
}
return true;
}
/**
* Flush entries which stayed longer or equal to the time-to-live, and
* Set up the TTLTimer for the next flush. Called when first entry is
* added to the cache and when the TTLTimer expires.
*/
synchronized void scheduleTTLTimer() {
if (m_orderedStruct.size() <= 0) {
return;
}
if (m_timer == null) {
m_timer = new TTLTimer(this);
}
Vector v = (Vector)m_orderedStruct.firstElement();
long currTime = System.currentTimeMillis();
long creationTime = ((Long)v.elementAt(1)).longValue();
long timeout = creationTime + m_timeToLive - currTime;
if (timeout > 0) {
m_timer.start(timeout);
}
else {
flushEntries();
scheduleTTLTimer();
}
}
/**
* Gets the number of entries being cached.
* @return the number of entries being cached.
*/
public int getNumEntries()
{
return m_cache.size();
}
/**
* Get number of LDAPConnections that share this cache
* @return Reference Count
*/
int getRefCount() {
return m_refCnt;
}
/**
* Add a new reference to this cache.
*
*/
synchronized void addReference() {
m_refCnt++;
if (m_debug) {
System.err.println("Cache refCnt="+ m_refCnt);
}
}
/**
* Remove a reference to this cache.
* If the reference count is 0, cleaup the cache.
*
*/
synchronized void removeReference() {
if (m_refCnt > 0) {
m_refCnt--;
if (m_debug) {
System.err.println("Cache refCnt="+ m_refCnt);
}
if (m_refCnt == 0 ) {
cleanup();
}
}
}
/**
* Cleans up
*/
synchronized void cleanup() {
flushEntries(null, 0);
if (m_timer != null) {
m_timer.stop();
m_timer = null;
}
}
/**
* Initialize the instance variables.
*/
private void init(long ttl, long size)
{
m_cache = new Hashtable();
m_timeToLive = ttl*1000;
m_maxSize = size;
m_remainingSize = size;
m_dns = null;
m_orderedStruct = new Vector();
}
/**
* Concatenates the specified integer with the delimiter.
* @param str the String to concatenate with the delimiter
* @return the concatenated string.
*/
private String appendString(String str) {
if (str == null)
return "null"+DELIM;
else
return str.trim()+DELIM;
}
/**
* Concatenates the specified integer with the delimiter.
* @param num the integer to concatenate with the delimiter
* @return the concatenated string.
*/
private String appendString(int num) {
return num+DELIM;
}
/**
* Concatenate the specified string array with the delimiter.
* @param str a string array
* @return the concatenated string.
*/
private String appendString(String[] str) {
if ((str == null) || (str.length < 1))
return "0"+DELIM;
else {
String[] sorted = new String[str.length];
System.arraycopy( str, 0, sorted, 0, str.length );
sortStrings(sorted);
String s = sorted.length+DELIM;
for (int i=0; i<sorted.length; i++)
s = s+sorted[i].trim()+DELIM;
return s;
}
}
/**
* Sorts the array of strings using bubble sort.
* @param str the array of strings to sort. The str parameter contains
* the sorted result.
*/
private void sortStrings(String[] str) {
for (int i=0; i<str.length; i++)
str[i] = str[i].trim();
for (int i=0; i<str.length-1; i++)
for (int j=i+1; j<str.length; j++)
{
if (str[i].compareTo(str[j]) > 0)
{
String t = str[i];
str[i] = str[j];
str[j] = t;
}
}
}
/**
* Create a 32 bits CRC from the given byte array.
*/
private long getCRC32(byte[] barray) {
if (barray==null) {
return 0;
}
CRC32 crcVal = new CRC32();
crcVal.update(barray);
return crcVal.getValue();
}
}
/**
* Represents a timer which will timeout for every certain interval. It
* provides methods to start, stop, or restart timer.
*/
class TTLTimer implements Runnable{
private long m_timeout;
private LDAPCache m_cache;
private Thread t = null;
/**
* Constructor with the specified timout.
* @param timeout the timeout value in milliseconds
*/
TTLTimer(LDAPCache cache) {
m_cache = cache;
}
/**
* (Re)start the timer.
*/
void start(long timeout) {
m_timeout = timeout;
if (Thread.currentThread() != t) {
stop();
}
t = new Thread(this, "LDAPCache-TTLTimer");
t.setDaemon(true);
t.start();
}
/**
* Stop the timer.
*/
void stop() {
if (t !=null) {
t.interrupt();
}
}
/**
* The runnable waits until the timeout period has elapsed. It then notify
* the registered listener who listens for the timeout event.
*/
public void run() {
synchronized(this) {
try {
this.wait(m_timeout);
} catch (InterruptedException e) {
// This happens if the timer is stopped
return;
}
}
m_cache.scheduleTTLTimer();
}
}

View File

@@ -0,0 +1,66 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
/**
* This static class checks if the caller is an applet running in
* Netscape Communicator. If so, it returns the appropriate method.
*/
class LDAPCheckComm {
/**
* Returns the method whose name matches the specified argument.
* @param classPackage the class package
* @param name the method name
* @return the method.
* @exception LDAPException Gets thrown if the method is not found or
* the caller is not an applet running in Netscape
* Communicator.
*/
static java.lang.reflect.Method getMethod(String classPackage, String name) throws LDAPException {
SecurityManager sec = System.getSecurityManager();
if ( sec == null ) {
/* Not an applet, we can do what we want to */
return null;
} else if ( sec.toString().startsWith("java.lang.NullSecurityManager") ) {
/* Not an applet, we can do what we want to */
return null;
} else if (sec.toString().startsWith("netscape.security.AppletSecurity")) {
/* Running as applet. Is PrivilegeManager around? */
try {
Class c = Class.forName(classPackage);
java.lang.reflect.Method[] m = c.getMethods();
for( int i = 0; i < m.length; i++ ) {
if ( m[i].getName().equals(name) ) {
return m[i];
}
}
throw new LDAPException("no enable privilege in " + classPackage);
} catch (ClassNotFoundException e) {
throw new LDAPException("Class not found");
}
}
return null;
}
}

View File

@@ -0,0 +1,345 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import java.text.*;
/**
* Compares LDAP entries based on one or more attribute values.
* <P>
*
* To use this comparison for sorting search results, pass
* an object of this class to the <CODE>sort</CODE> method in
* <CODE>LDAPSearchResults</CODE>.
* <P>
*
* @version 1.0
* @see LDAPEntryComparator
* @see LDAPSearchResults#sort
*/
public class LDAPCompareAttrNames
implements LDAPEntryComparator, java.io.Serializable {
static final long serialVersionUID = -2567450425231175944L;
private String m_attrs[];
private boolean m_ascending[];
private Locale m_locale = null;
private Collator m_collator = null;
private boolean m_sensitive = true;
/**
* Constructs a comparator that compares the string values of
* a named attribute in LDAP entries and sorts the entries in
* ascending order.
* <P>
*
* @param attribute name of attribute for comparisons
*/
public LDAPCompareAttrNames (String attribute) {
m_attrs = new String[1];
m_attrs[0] = attribute;
m_ascending = new boolean[1];
m_ascending[0] = true;
}
/**
* Constructs a comparator that compares the string values of
* a named attribute in LDAP entries and that allows you to sort
* entries either in ascending or descending order.
* <P>
*
* @param attribute name of attribute for comparisons
* @param ascendingFlag if <CODE>true</CODE>, sort in ascending order
*/
public LDAPCompareAttrNames (String attribute,
boolean ascendingFlag) {
m_attrs = new String[1];
m_attrs[0] = attribute;
m_ascending = new boolean[1];
m_ascending[0] = ascendingFlag;
}
/**
* Constructs a comparator that compares the string values of
* a set of named attributes in LDAP entries and that sort
* the entries in ascending order.
* <P>
*
* Use an array of strings to specify the set of attributes
* to use for sorting. If the values of the first attribute
* (the name specified in <CODE>attribute[0]</CODE>) are equal,
* then the values of the next attribute are compared.
* <P>
*
* For example, if <CODE>attributes[0] = "cn"</CODE> and
* <CODE>attributes[1]="uid"</CODE>, results are first sorted
* by the <CODE>cn</CODE> attribute. If two entries have the
* same value for <CODE>cn</CODE>, then the <CODE>uid</CODE>
* attribute is used to sort the entries.
* <P>
*
* @param attributes array of the attribute names used for comparisons
*/
public LDAPCompareAttrNames (String[] attributes) {
m_attrs = attributes;
m_ascending = new boolean[attributes.length];
for( int i = 0; i < attributes.length; i++ )
m_ascending[i] = true;
}
/**
* Constructs a comparator that compares the string values of
* a set of named attributes in LDAP entries and allows you
* to sort the entries in ascending or descending order.
* <P>
*
* Use an array of strings to specify the set of attributes
* to use for sorting. If the values of the first attribute
* (the name specified in <CODE>attribute[0]</CODE>)
* are equal, then the values of the next attribute are compared.
* <P>
*
* For example, if <CODE>attributes[0] = "cn"</CODE> and
* <CODE>attributes[1]="uid"</CODE>, results are first sorted
* by the <CODE>cn</CODE> attribute. If two entries have the
* same value for <CODE>cn</CODE>, then the <CODE>uid</CODE>
* attribute is used to sort the entries.
* <P>
*
* Use an array of boolean values to specify whether each attribute
* should be sorted in ascending or descending order. For example,
* suppose that <CODE>attributes[0] = "cn"</CODE> and
* <CODE>attributes[1]="roomNumber"</CODE>. If
* <CODE>ascendingFlags[0]=true</CODE> and
* <CODE>ascendingFlags[1]=false</CODE>, attributes are sorted first by
* <CODE>cn</CODE> in ascending order, then by <CODE>roomNumber</CODE>
* in descending order.
* <P>
*
* If the size of the array of attribute names is not the same as
* the size of the array of boolean values, an
* <CODE>LDAPException</CODE> is thrown.
* <P>
*
* @param attribute array of the attribute names to use for comparisons
* @param ascendingFlags array of boolean values specifying ascending
* or descending order to use for each attribute name. If
* <CODE>true</CODE>, the attributes are sorted in ascending order.
*/
public LDAPCompareAttrNames (String[] attributes,
boolean[] ascendingFlags) {
m_attrs = attributes;
m_ascending = ascendingFlags;
if ( m_ascending == null ) {
m_ascending = new boolean[attributes.length];
for( int i = 0; i < attributes.length; i++ )
m_ascending[i] = true;
}
}
/**
* Gets the locale, if any, used for collation. If the locale is null,
* an ordinary string comparison is used for sorting.
*
* @return the locale used for collation, or null.
*/
public Locale getLocale() {
return m_locale;
}
/**
* Set the locale, if any, used for collation. If the locale is null,
* an ordinary string comparison is used for sorting. If sorting
* has been set to case-insensitive, the collation strength is set
* to Collator.PRIMARY, otherwise to Collator.IDENTICAL. If a
* different collation strength setting is required, use the signature
* that takes a collation strength parameter.
*
* @param locale the locale used for collation, or null.
*/
public void setLocale( Locale locale ) {
if ( m_sensitive ) {
setLocale( locale, Collator.IDENTICAL );
} else {
setLocale( locale, Collator.PRIMARY );
}
}
/**
* Sets the locale, if any, used for collation. If the locale is null,
* an ordinary string comparison is used for sorting.
*
* @param locale the locale used for collation, or null.
* @param strength collation strength: Collator.PRIMARY,
* Collator.SECONDARY, Collator.TERTIARY, or Collator.IDENTICAL
*/
public void setLocale( Locale locale, int strength ) {
m_locale = locale;
if ( m_locale == null ) {
m_collator = null;
} else {
m_collator = Collator.getInstance( m_locale );
m_collator.setStrength(strength);
}
}
/**
* Gets the state of the case-sensitivity flag. This only applies to
* Unicode sort order; for locale-specific sorting, case-sensitivity
* is controlled by the collation strength.
*
* @return <code>true</code> for case-sensitive sorting; this is
* the default
*/
public boolean getCaseSensitive() {
return m_sensitive;
}
/**
* Sets the state of the case-sensitivity flag. This only applies to
* Unicode sort order; for locale-specific sorting, case-sensitivity
* is controlled by the collation strength.
*
* @param sensitive <code>true</code> for case-sensitive sorting;
* this is the default
*/
public void setCaseSensitive( boolean sensitive ) {
m_sensitive = sensitive;
}
/**
* Returns <CODE>true</CODE> if the value of the attribute in the first entry is greater
* than the value of the attribute in the second entry.
* <P>
*
* If one of the entries is missing the attribute, the other is
* considered greater. By default, the first entry is greater.
* <P>
*
* If either entry contains multiple values, only the first value
* is used for comparisons.
* <P>
*
* @param greater entry against which to test
* @param less entry to test
* @return <CODE>true</CODE> if (<CODE>greater &gt; less</CODE>).
*/
public boolean isGreater (LDAPEntry greater, LDAPEntry less) {
if (greater.equals (less)) return false;
return attrGreater (greater, less, 0);
}
/**
* Compares a particular attribute in both entries. If equal,
* moves on to the next.
* @param greater greater arg from isGreater
* @param less less arg from isGreater
* @param attrPos the index in an array of attributes, indicating
* the attribute to compare
* @return (greater > less)
*/
boolean attrGreater (LDAPEntry greater, LDAPEntry less,
int attrPos) {
Enumeration greaterAttrSet =
greater.getAttributeSet().getAttributes();
Enumeration lessAttrSet =
less.getAttributeSet().getAttributes();
String greaterValue = null;
String lessValue = null;
String attrName = m_attrs[attrPos];
boolean ascending = m_ascending[attrPos];
try {
while (lessAttrSet.hasMoreElements()) {
LDAPAttribute currAttr =
(LDAPAttribute)(lessAttrSet.nextElement());
if (!attrName.equalsIgnoreCase (currAttr.getName()))
continue;
lessValue =
(String)(currAttr.getStringValues().nextElement());
break;
}
while (greaterAttrSet.hasMoreElements()) {
LDAPAttribute currAttr =
(LDAPAttribute)(greaterAttrSet.nextElement());
if (!attrName.equalsIgnoreCase (currAttr.getName()))
continue;
greaterValue =
(String)(currAttr.getStringValues().nextElement());
break;
}
}
catch (ClassCastException cce) {
// i.e. one of the enumerations did not contain the
// right type !?
return false;
}
catch (NoSuchElementException nse) {
// i.e. one of the attributes had no values !?
return false;
}
if ((lessValue == null) ^ (greaterValue == null))
return greaterValue != null;
// Check for equality
if ( (lessValue == null) ||
((m_collator != null) &&
(m_collator.compare( greaterValue, lessValue ) == 0) ) ||
((m_collator == null) && m_sensitive &&
lessValue.equals(greaterValue)) ||
((m_collator == null) && !m_sensitive &&
lessValue.equalsIgnoreCase(greaterValue)) ) {
if (attrPos == m_attrs.length - 1) {
return false;
} else {
return attrGreater (greater, less, attrPos+1);
}
}
// Not equal, check for order
if ( ascending ) {
if ( m_collator != null ) {
return ( m_collator.compare( greaterValue, lessValue ) > 0 );
} else if ( m_sensitive ) {
return (greaterValue.compareTo (lessValue) > 0);
} else {
return (greaterValue.toLowerCase().compareTo (
lessValue.toLowerCase()) > 0);
}
} else {
if ( m_collator != null ) {
return ( m_collator.compare( greaterValue, lessValue ) < 0 );
} else if ( m_sensitive ) {
return (greaterValue.compareTo (lessValue) < 0);
} else {
return (greaterValue.toLowerCase().compareTo (
lessValue.toLowerCase()) < 0);
}
}
}
}

View File

@@ -0,0 +1,526 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import java.io.*;
import java.net.*;
/**
* Makes 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.
* <P>
* The total time spent opening a connection can be limited with the
* <CODE>ConnectTimeout</CODE> property.
* <P>
* 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, java.io.Serializable {
static final long serialVersionUID = 1519402748245755306L;
/**
* 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 INTERRUPTED = 3;
private static final int FAILED = 4;
/**
* 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 = SERIAL;
/**
* Delay in ms before another connection setup thread is started.
*/
int m_connSetupDelay = -1;
/**
* The maximum time to wait to established the connection
*/
int m_connectTimeout = 0;
/**
* During connection setup, the current count of servers to which
* connection attmpt has been made
*/
private transient int m_attemptCnt = 0;
/**
* Constructor
* @param host list of host names to which to connect
* @param port list of port numbers corresponding to the host list
* @param factory socket factory for SSL connections
*/
LDAPConnSetupMgr(String[] hosts, int[] ports, LDAPSocketFactory factory) {
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;
}
/**
* Try to open the connection to any of the servers in the list, limiting
* the time waiting for the connection to be established
* @return connection socket
*/
synchronized Socket openConnection() throws LDAPException{
long tcur=0, tmax = Long.MAX_VALUE;
Thread th = null;
reset();
// If reconnecting, sort dsList so that servers more likly to
// be available are tried first
sortDsList();
if (m_connectTimeout == 0) {
// No need for a separate thread, connect time not limited
connect();
}
else {
// Wait for connection at most m_connectTimeout milliseconds
// Run connection setup in a separate thread to monitor the time
tmax = System.currentTimeMillis() + m_connectTimeout;
th = new Thread (new Runnable() {
public void run() {
connect();
}
}, "ConnSetupMgr");
th.setDaemon(true);
th.start();
while (m_socket==null && (m_attemptCnt < m_dsList.length) &&
(tcur = System.currentTimeMillis()) < tmax) {
try {
wait(tmax - tcur);
}
catch (InterruptedException e) {
th.interrupt();
cleanup();
throw new LDAPInterruptedException("Interrupted connect operation");
}
}
}
if (m_socket != null) {
return m_socket;
}
if ( th != null && (tcur = System.currentTimeMillis()) >= tmax) {
// We have timed out
th.interrupt();
cleanup();
throw new LDAPException(
"connect timeout, " + getServerList() + " might be unreachable",
LDAPException.CONNECT_ERROR);
}
if (m_connException != null && m_dsList.length == 1) {
throw m_connException;
}
throw new LDAPException(
"failed to connect to server " + getServerList(),
LDAPException.CONNECT_ERROR);
}
private void reset() {
m_socket = null;
m_connException = null;
m_attemptCnt = 0;
for (int i=0; i < m_dsList.length; i++) {
m_dsList[i].connSetupThread = null;
}
}
private String getServerList() {
StringBuffer sb = new StringBuffer();
for (int i=0; i < m_dsList.length; i++) {
sb.append(i==0 ? "" : " ");
sb.append(m_dsList[i].host);
sb.append(":");
sb.append(m_dsList[i].port);
}
return sb.toString();
}
private void connect() {
if (m_policy == SERIAL || m_dsList.length == 1) {
openSerial();
}
else {
openParallel();
}
}
/**
* Called when the current connection is lost.
* Put the connected server at the end of the server list for
* the next connect attempt.
*/
synchronized 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;
}
/**
* 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;
}
int getConnSetupDelay() {
return m_connSetupDelay/1000;
}
/**
* Selects the connection failover policy
* @param 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
*/
void setConnSetupDelay(int delay) {
m_policy = (delay < 0) ? SERIAL : PARALLEL;
m_connSetupDelay = delay*1000;
}
int getConnectTimeout() {
return m_connectTimeout/1000;
}
/**
* Sets the maximum time to spend in the openConnection() call
* @param timeout in seconds to wait for the connection to be established
*/
void setConnectTimeout(int timeout) {
m_connectTimeout = timeout*1000;
}
/**
* 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) {
return;
}
}
}
// At this point all threads are started. Wait until first thread
// succeeds to connect or all threads terminate
while (m_socket == null && (m_attemptCnt < m_dsList.length)) {
// Wait for a thread to terminate
try {
wait();
}
catch (InterruptedException e) {}
}
}
/**
* Connect to the server at the given index
*/
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;
}
m_attemptCnt++;
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 = INTERRUPTED;
//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;
}
}
}
/**
* Sorts 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) interrupted connection attempt
* (4) 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;
}
}
}
}
/**
* This is used only by the ldapjdk test libaray to simulate a
* server problem and to test fail-over and rebind
* @return A flag whether the connection was closed
*/
boolean breakConnection() {
try {
m_socket.close();
return true;
}
catch (Exception e) {
return false;
}
}
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() {
try {
LDAPConnSetupMgr cloneMgr = (LDAPConnSetupMgr) super.clone();
cloneMgr.m_dsList = new ServerEntry[m_dsList.length];
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;
}
catch (CloneNotSupportedException ex) {
return null;
}
}
}

View File

@@ -0,0 +1,629 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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_doRun = true;
private Socket m_socket = null;
transient private Thread m_thread = null;
transient Object m_sendRequestLock = new Object();
transient LDAPConnSetupMgr m_connMgr = null;
transient Object m_traceOutput = 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, Object traceOutput)
throws LDAPException {
super("LDAPConnThread " + connMgr.getHost() +":"+ connMgr.getPort());
m_requests = new Hashtable ();
m_registered = new Vector ();
m_connMgr = connMgr;
m_socket = connMgr.getSocket();
setCache( cache );
setTraceOutput(traceOutput);
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_doRun is set to false.
m_doRun = false;
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;
}
void setTraceOutput(Object traceOutput) {
synchronized (m_sendRequestLock) {
if (traceOutput == null) {
m_traceOutput = null;
}
else if (traceOutput instanceof OutputStream) {
m_traceOutput = new PrintWriter((OutputStream)traceOutput);
}
else if (traceOutput instanceof LDAPTraceWriter) {
m_traceOutput = traceOutput;
}
}
}
void logLDAPMessage(LDAPMessage msg) {
synchronized( m_sendRequestLock ) {
if (m_traceOutput instanceof PrintWriter) {
PrintWriter traceOutput = (PrintWriter)m_traceOutput;
traceOutput.println(msg.toTraceString());
traceOutput.flush();
}
else if (m_traceOutput instanceof LDAPTraceWriter) {
((LDAPTraceWriter)m_traceOutput).write(msg.toTraceString());
}
}
}
/**
* 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;
}
/**
* Allocates a new LDAP message ID. These are arbitrary numbers used to
* correlate client requests with server responses.
* @return new unique msgId
*/
private int allocateId () {
synchronized (m_sendRequestLock) {
m_highMsgId = (m_highMsgId + 1) % MAXMSGID;
return m_highMsgId;
}
}
/**
* Sends LDAP request via this connection thread.
* @param request request to send
* @param toNotify response listener to invoke when the response
* is ready
*/
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.getMessageID()), toNotify);
/* Notify the backlog checker that there may be another outstanding
request */
resultRetrieved();
}
toNotify.addRequest(msg.getMessageID(), conn, this, cons.getTimeLimit());
}
synchronized( m_sendRequestLock ) {
try {
if (m_traceOutput != null) {
logLDAPMessage(msg);
}
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 {
m_doRun =false;
if (!m_disconnected) {
LDAPSearchConstraints cons = conn.getSearchConstraints();
sendRequest (null, new JDAPUnbindRequest (), null, cons);
}
if ( m_thread != null && m_thread != Thread.currentThread()) {
m_thread.interrupt();
// Wait up to 1 sec for thread to accept disconnect
// notification. When the interrupt is accepted,
// m_thread is set to null. See run() method.
try {
wait(1000);
}
catch (InterruptedException e) {
}
}
cleanUp();
} 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();
/**
* Cancel all outstanding requests
*/
if (m_requests != null) {
Enumeration requests = m_requests.elements();
while (requests.hasMoreElements()) {
LDAPMessageQueue listener =
(LDAPMessageQueue)requests.nextElement();
listener.removeAllRequests(this);
}
}
/**
* 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();
m_cache = null;
}
}
/**
* Sleep if there is a backlog of search results
*/
private void checkBacklog() throws InterruptedException{
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.getSearchConstraints().getMaxBacklog()) {
doWait = true;
}
}
// synch op with non-zero batch size ?
else if (sl.getSearchConstraints().getBatchSize() != 0) {
if (sl.getMessageCount() >= sl.getSearchConstraints().getMaxBacklog()) {
doWait = true;
}
}
}
if ( doWait ) {
synchronized(this) {
wait();
}
}
} 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_doRun) {
return;
}
m_thread = Thread.currentThread();
LDAPMessage msg = null;
JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
while (m_doRun) {
yield();
int[] nread = new int[1];
nread[0] = 0;
try {
// Avoid too great a backlog of results
checkBacklog();
BERElement element = BERElement.getElement(decoder,
m_serverInput,
nread);
msg = LDAPMessage.parseMessage(element);
if (m_traceOutput != null) {
logLDAPMessage(msg);
}
// 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) {
if (m_doRun) {
networkError(e);
m_doRun =false;
}
else {
synchronized (this) {
m_thread = null;
notifyAll();
}
}
}
}
}
/**
* 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 msg New message from LDAP server
*/
private void processResponse (LDAPMessage msg, int size) {
Integer messageID = new Integer (msg.getMessageID());
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 = msg.getControls();
if (con != null) {
int msgid = msg.getMessageID();
LDAPConnection ldc = l.getConnection(msgid);
if (ldc != null) {
ldc.setResponseControls( this,
new LDAPResponseControl(ldc, msgid, con));
}
}
}
if (m_cache != null && (l instanceof LDAPSearchListener)) {
cacheSearchResult((LDAPSearchListener)l, msg, size);
}
l.addMessage (msg);
if (msg instanceof LDAPResponse) {
m_requests.remove (messageID);
}
}
/**
* Collect search results to be added to the LDAPCache. Search results are
* packaged in a vector and temporary stored into a hashtable m_messages
* using the message id as the key. The vector first element (at index 0)
* is a Long integer representing the total size of all LDAPEntries entries.
* It is followed by the actual LDAPEntries.
* If the total size of entries exceeds the LDAPCache max size, or a referral
* has been received, caching of search results is disabled and the entry is
* not added to the LDAPCache. A disabled search request is denoted by setting
* the entry size to -1.
*/
private synchronized void cacheSearchResult (LDAPSearchListener l, LDAPMessage msg, int size) {
Integer messageID = new Integer (msg.getMessageID());
Long key = l.getKey();
Vector v = null;
if ((m_cache == null) || (key == null)) {
return;
}
if (msg instanceof LDAPSearchResult) {
// get the vector containing the LDAPMessages for the specified messageID
v = (Vector)m_messages.get(messageID);
if (v == null) {
m_messages.put(messageID, v = new Vector());
v.addElement(new Long(0));
}
// Return if the entry size is -1, i.e. the caching is disabled
if (((Long)v.firstElement()).longValue() == -1L) {
return;
}
// 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;
// If the entrySize exceeds the cache size, discard the collected
// entries and disble collecting of entries for this search request
// by setting the entry size to -1.
if (entrySize > m_cache.getSize()) {
v.removeAllElements();
v.addElement(new Long(-1L));
return;
}
// 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)msg).getEntry());
} else if (msg instanceof LDAPSearchResultReference) {
// If a search reference is received disable caching of
// this search request
v = (Vector)m_messages.get(messageID);
if (v == null) {
m_messages.put(messageID, v = new Vector());
}
else {
v.removeAllElements();
}
v.addElement(new Long(-1L));
} else if (msg instanceof LDAPResponse) {
// The search request has completed. Store the cache entry
// in the LDAPCache if the operation has succeded and caching
// is not disabled due to the entry size or referrals
boolean fail = ((LDAPResponse)msg).getResultCode() > 0;
v = (Vector)m_messages.remove(messageID);
if (!fail) {
// If v is null, meaning there are no search results from the
// server
if (v == null) {
v = new Vector();
v.addElement(new Long(0));
}
// add the new entry if the entry size is not -1 (caching diabled)
if (((Long)v.firstElement()).longValue() != -1L) {
m_cache.addEntry(key, v);
}
}
}
}
/**
* Stop dispatching responses for a particular message ID.
* @param id Message ID for which to discard responses.
*/
void abandon (int id ) {
LDAPMessageQueue l = (LDAPMessageQueue)m_requests.remove(new Integer(id));
// Clean up cache if enabled
if (m_messages != null) {
m_messages.remove(new Integer(id));
}
if (l != null) {
l.removeRequest(id);
}
resultRetrieved(); // 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) {
// notify the Connection Setup Manager that the connection is lost
m_connMgr.invalidateConnection();
try {
// 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));
}
} catch (NullPointerException ee) {
System.err.println("Exception: "+ee.toString());
}
cleanUp();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,389 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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, java.io.Serializable {
static final long serialVersionUID = 6506767263918312029L;
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 Mmaximum 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 use 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 use 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 for the client to apply 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 for the server to apply 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. If the time limit is exceeded,
* an LDAPException with the result code <CODE>LDAPException.TIME_LIMIT
* </CODE> is thrown.
* @param msLimit Maximum number of milliseconds to wait for operation
* results (0 by default, which means that there is no maximum time
* limit.)
* @see netscape.ldap.LDAPException#LDAP_TIMEOUT
*/
public void setTimeLimit( int msLimit ) {
m_time_limit = msLimit;
}
/**
* Specifies whether or not referrals are followed automatically.
* Specify <CODE>true</CODE> if referrals are to be followed automatically,
* or <CODE>false</CODE> if referrals are to 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</CODE> 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 use 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 use 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;
}
/**
* Return a string representation of the object for debugging
*
* @return A string representation of the object
*/
public String toString() {
StringBuffer sb = new StringBuffer("LDAPConstraints {");
sb.append("time limit " + getTimeLimit() + ", ");
sb.append("referrals " + getReferrals() + ", ");
sb.append("hop limit " + getHopLimit() + ", ");
sb.append("bind_proc " + getBindProc() + ", ");
sb.append("rebind_proc " + getRebindProc());
LDAPControl[] controls = getClientControls();
if ( controls != null ) {
sb.append(", client controls ");
for (int i =0; i < controls.length; i++) {
sb.append(controls[i].toString());
if ( i < (controls.length - 1) ) {
sb.append(" ");
}
}
}
controls = getServerControls();
if ( controls != null ) {
sb.append(", server controls ");
for (int i =0; i < controls.length; i++) {
sb.append(controls[i].toString());
if ( i < (controls.length - 1) ) {
sb.append(" ");
}
}
}
sb.append('}');
return sb.toString();
}
/**
* 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

@@ -0,0 +1,510 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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
* a particular LDAP operation. LDAP controls are part of version 3
* of the LDAP protocol.
* <P>
*
* LDAP controls allow you to extend the functionality of
* an LDAP operation. For example, you can use an LDAP control
* for the search operation to sort search results on an LDAP server.
* <P>
*
* An LDAP control can be either a <B>server control</B> or
* a <B>client control</B>:
* <P>
* <UL>
* <LI><B>Server controls</B> can be sent to the LDAP server or returned
* by the server on any operation.
* <LI><B>Client controls</B> are intended to affect only the client side
* of the operation.
* </UL>
* <P>
*
* An LDAP control consists of the following information:
* <P>
* <UL>
* <LI>A unique object ID (OID) that identifies the control.<P>
* <LI>A &quot;criticality&quot; field, which indicates whether or
* not the control is critical to the operation. (If the control is
* critical to the operation and the server does not support the control,
* the server should not execute the operation.)<P>
* <LI>Data pertaining to the control.<P>
* </UL>
* <P>
*
* To determine which server controls are supported by a particular server,
* you need to search for the root DSE (DSA-specific entry, where DSA is
* another term for &quot;LDAP server&quot;) and find the values of the
* <CODE>supportedControl</CODE> attribute. This attribute contains the
* object IDs (OIDs) of the controls supported by this server.
* <P>
*
* The following section of code demonstrates how to get the list
* of the server controls supported by an LDAP server.
* <P>
*
* <PRE>
* public static void main( String[] args )
* {
* LDAPConnection ld = new LDAPConnection();
* try {
* String MY_HOST = "localhost";
* int MY_PORT = 389;
* ld.connect( MY_HOST, MY_PORT );
* try {
* ld.authenticate( 3, "cn=Directory Manager", "23skidoo" );
* } catch( LDAPException e ) {
* System.out.println( "LDAP server does not support v3." );
* ld.disconnect();
* System.exit(1);
* }
*
* String MY_FILT = "(objectclass=*)";
* String MY_BASE = "";
* String getAttrs[] = { "supportedControl" };
* LDAPSearchResults res = ld.search( MY_BASE,
* LDAPConnection.SCOPE_BASE, MY_FILT, getAttrs, false );
*
* while ( res.hasMoreElements() ) {
* LDAPEntry findEntry = (LDAPEntry)res.nextElement();
* LDAPAttributeSet findAttrs = findEntry.getAttributeSet();
* Enumeration enumAttrs = findAttrs.getAttributes();
*
* while ( enumAttrs.hasMoreElements() ) {
* LDAPAttribute anAttr = (LDAPAttribute)enumAttrs.nextElement();
* String attrName = anAttr.getName();
* System.out.println( attrName );
* Enumeration enumVals = anAttr.getStringValues();
*
* while ( enumVals.hasMoreElements() ) {
* String aVal = ( String )enumVals.nextElement();
* System.out.println( "\t" + aVal );
* }
* }
* }
* }
* catch( LDAPException e ) {
* System.out.println( "Error: " + e.toString() );
* }
* try {
* ld.disconnect();
* }
* catch( LDAPException e ) {
* System.exit(1);
* }
* System.exit(0);
* }
* </PRE>
* <P>
*
* If you compile and run this example against an LDAP server that
* supports v3 of the protocol, you might receive the following results:
* <P>
*
* <PRE>
* supportedcontrol
* 2.16.840.1.113730.3.4.2
* 2.16.840.1.113730.3.4.3
* 2.16.840.1.113730.3.4.4
* 2.16.840.1.113730.3.4.5
* 1.2.840.113556.1.4.473
* </PRE>
* <P>
*
* For more information on LDAP controls, see the Internet-Draft on
* the LDAP v3 protocol. (Note that this internet draft is still a
* work in progress. You can find the latest draft at the <A
* HREF="http://www.ietf.cnri.reston.va.us/html.charters/asid-charter.html"
* TARGET="_blank">ASID home page</A>.
* <P>
*
* @version 1.0
* @see netscape.ldap.LDAPv3#CLIENTCONTROLS
* @see netscape.ldap.LDAPv3#SERVERCONTROLS
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
* @see netscape.ldap.LDAPConnection#getResponseControls
* @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, java.io.Serializable {
static final long serialVersionUID = 5149887553272603753L;
public final static String MANAGEDSAIT = "2.16.840.1.113730.3.4.2";
/* Password information sent back to client */
public final static String PWEXPIRED = "2.16.840.1.113730.3.4.4";
public final static String PWEXPIRING = "2.16.840.1.113730.3.4.5";
/**
* Default constructor for the <CODE>LDAPControl</CODE> class.
*/
public LDAPControl()
{
}
/**
* Constructs a new <CODE>LDAPControl</CODE> object using the
* specified object ID (OID), &quot;criticality&quot; field, and
* data to be used by the control.
* <P>
*
* @param id the object ID (OID) identifying the control
* @param critical <CODE>true</CODE> if the LDAP operation should be
* 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.LDAPConstraints#setClientControls
* @see netscape.ldap.LDAPConstraints#setServerControls
*/
public LDAPControl(String id,
boolean critical,
byte vals[]) {
m_oid = id;
m_critical = critical;
m_value = vals;
}
/**
* Gets the object ID (OID) of the control.
* @return object ID (OID) of the control.
*/
public String getID() {
return m_oid;
}
/**
* Specifies whether or not the control is critical to the LDAP operation.
* @return <CODE>true</CODE> if the LDAP operation should be cancelled when
* the server does not support this control.
*/
public boolean isCritical() {
return m_critical;
}
/**
* Gets the data in the control.
* @return the data in the control as a byte array.
*/
public byte[] getValue() {
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 instantiate
* @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 an <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.
*/
public Object clone() {
byte[] vals = null;
if ( m_value != null ) {
vals = new byte[m_value.length];
for( int i = 0; i < m_value.length; i++ )
vals[i] = m_value[i];
}
LDAPControl control = new LDAPControl( m_oid, m_critical, vals );
return control;
}
/**
* Create a "flattened" BER encoding from a BER,
* and return it as a byte array.
* @param ber a BER encoded sequence
* @return the byte array of encoded data.
*/
protected byte[] flattenBER( BERSequence ber ) {
/* Suck out the data and return it */
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
try {
ber.write( outStream );
} catch ( IOException e ) {
return null;
}
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

@@ -0,0 +1,395 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* The definition of a DIT content rule in the schema.
* <A HREF="http://www.ietf.org/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* DIT Content Rule Description</A> covers the types of information
* to specify when defining a DIT content rule. According to the RFC,
* the description of a DIT content rule can include the following:
* <P>
*
* <UL>
* <LI>an OID identifying the attribute type
* <LI>a name identifying the attribute type
* <LI>a description of the attribute type
* <LI>the name of the parent attribute type
* <LI>the syntax used by the attribute (for example,
* <CODE>cis</CODE> or <CODE>int</CODE>)
* <LI>an indication of whether the attribute type is single-valued
* or multi-valued
* </UL>
* <P>
*
* When you construct an <CODE>LDAPDITContentRuleSchema</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
* returns schema information as an object with attribute values in this
* format.
* <P>
*
* There are a number of additional optional description fields which
* are not explicitly accessible through LDAPDITContentRuleSchema, but which
* can be managed with setQualifier, getQualifier, and getQualifierNames:
* <P>
*
* <UL>
* <LI>OBSOLETE
* </UL>
* <P>
*
* To get the name, OID, and description of this DIT content rule
* , use the <CODE>getName</CODE>, <CODE>getOID</CODE>, and
* <CODE>getDescription</CODE> methods inherited from the abstract class
* <CODE>LDAPSchemaElement</CODE>. Optional and custom qualifiers are
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
* from <CODE>LDAPSchemaElement</CODE>.
* <P>
*
* 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 DITContentRuleDescription as follows:
* <P>
* <PRE>
* DITContentRuleDescription = "("
* numericoid ; Structural ObjectClass identifier
* [ "NAME" qdescrs ]
* [ "DESC" qdstring ]
* [ "OBSOLETE" ]
* [ "AUX" oids ] ; Auxiliary ObjectClasses
* [ "MUST" oids ] ; AttributeType identifiers
* [ "MAY" oids ] ; AttributeType identifiers
* [ "NOT" oids ] ; AttributeType identifiers
* ")"
* </PRE>
*
* @version 1.0
* @see netscape.ldap.LDAPSchemaElement
**/
public class LDAPDITContentRuleSchema extends LDAPSchemaElement {
static final long serialVersionUID = -8588488481097270056L;
/**
* Constructs a blank element.
*/
protected LDAPDITContentRuleSchema() {
super();
}
/**
* Constructs a DIT content rule 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 obsolete <code>true</code> if the rule is obsolete
* @param auxiliary a list of auxiliary object classes
* allowed for an entry to which this content rule applies.
* These may either be specified by name or numeric oid.
* @param required a list of user attribute types that an entry
* to which this content rule applies must contain in addition to
* its normal set of mandatory attributes. These may either be
* specified by name or numeric oid.
* @param optional a list of user attribute types that an entry
* to which this content rule applies may contain in addition to
* its normal set of optional attributes. These may either be
* specified by name or numeric oid.
* @param precluded a list consisting of a subset of the optional
* user attribute types of the structural and auxiliary object
* classes which are precluded from an entry to which this content rule
* applies. These may either be specified by name or numeric oid.
*/
public LDAPDITContentRuleSchema( String name, String oid,
String description, boolean obsolete,
String[] auxiliary,
String[] required,
String[] optional,
String[] precluded ) {
super( name, oid, description, null );
if ( required != null ) {
for( int i = 0; i < required.length; i++ ) {
must.addElement( required[i] );
}
}
if ( optional != null ) {
for( int i = 0; i < optional.length; i++ ) {
may.addElement( optional[i] );
}
}
if ( auxiliary != null ) {
for( int i = 0; i < auxiliary.length; i++ ) {
aux.addElement( auxiliary[i] );
}
}
if ( precluded != null ) {
for( int i = 0; i < precluded.length; i++ ) {
not.addElement( precluded[i] );
}
}
if ( obsolete ) {
setQualifier( OBSOLETE, "" );
}
}
/**
* Constructs a DIT content rule definition based on a description in
* the DITContentRuleDescription format. For information on this format,
* (see <A HREF="http://www.ietf.org/rfc/rfc2252.txt"
* >RFC 2252, Lightweight Directory Access Protocol (v3):
* DIT Content Rule Description</A>. 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 "attributetypes" are attribute type descriptions
* in this format.)
* <P>
*
* @param raw definition of the DIT content rule in the
* DITContentRuleDescription format
*/
public LDAPDITContentRuleSchema( String raw ) {
attrName = "ditContentRules";
parseValue( raw );
Object o = properties.get( MAY );
if ( o != null ) {
if ( o instanceof Vector ) {
may = (Vector)o;
} else {
may.addElement( o );
}
}
o = properties.get( MUST );
if ( o != null ) {
if ( o instanceof Vector ) {
must = (Vector)o;
} else {
must.addElement( o );
}
}
o = properties.get( NOT );
if ( o != null ) {
if ( o instanceof Vector ) {
not = (Vector)o;
} else {
not.addElement( o );
}
}
o = properties.get( AUX );
if ( o != null ) {
if ( o instanceof Vector ) {
aux = (Vector)o;
} else {
aux.addElement( o );
}
}
}
/**
* Gets the names of the required attributes for
* this content rule.
* @return the names of the required attributes
* for this content rule.
*/
public String[] getRequiredAttributes() {
String[] vals = new String[must.size()];
must.copyInto( vals );
return vals;
}
/**
* Gets the names of optional attributes allowed
* in this content rule.
* @return the names of optional attributes
* allowed in this content rule.
*/
public String[] getOptionalAttributes() {
String[] vals = new String[may.size()];
may.copyInto( vals );
return vals;
}
/**
* Gets the names of the precluded attributes for
* this content rule.
* @return the names of the precluded attributes
* for this content rule.
*/
public String[] getPrecludedAttributes() {
String[] vals = new String[not.size()];
not.copyInto( vals );
return vals;
}
/**
* Gets the names of the auxiliary object classes allowed
* in this content rule.
* @return the names of auxiliary object classes
* allowed in this content rule.
*/
public String[] getAuxiliaryClasses() {
String[] vals = new String[aux.size()];
aux.copyInto( vals );
return vals;
}
/**
* Prepares a value in RFC 2252 format for submission to a server
*
* @return a String ready for submission to an LDAP server.
*/
public String getValue() {
String s = getValuePrefix();
String val;
val = getOptionalValues( NOVALS );
if ( val.length() > 0 ) {
s += val + ' ';
}
if ( aux.size() > 0 ) {
s += AUX + " " + vectorToList( aux );
s += ' ';
}
if ( must.size() > 0 ) {
s += MUST + " " + vectorToList( must );
s += ' ';
}
if ( may.size() > 0 ) {
s += MAY + " " + vectorToList( may );
s += ' ';
}
if ( not.size() > 0 ) {
s += NOT + " " + vectorToList( not );
s += ' ';
}
val = getCustomValues();
if ( val.length() > 0 ) {
s += val + ' ';
}
s += ')';
return s;
}
/**
* Creates a list within parentheses, with $ as delimiter
*
* @param vals values for list
* @return a String with a list of values.
*/
protected String vectorToList( Vector vals ) {
String val = "( ";
for( int i = 0; i < vals.size(); i++ ) {
val += (String)vals.elementAt(i) + ' ';
if ( i < (vals.size() - 1) ) {
val += "$ ";
}
}
val += ')';
return val;
}
/**
* Gets the definition of the rule in a user friendly format.
* This is the format that the rule definition uses when
* printing the attribute type or the schema.
* @return definition of the rule in a user friendly format.
*/
public String toString() {
String s = "Name: " + name + "; OID: " + oid;
s += "; Description: " + description + "; Required: ";
int i = 0;
Enumeration e = must.elements();
while( e.hasMoreElements() ) {
if ( i > 0 )
s += ", ";
i++;
s += (String)e.nextElement();
}
s += "; Optional: ";
e = may.elements();
i = 0;
while( e.hasMoreElements() ) {
if ( i > 0 )
s += ", ";
i++;
s += (String)e.nextElement();
}
s += "; Auxiliary: ";
e = aux.elements();
i = 0;
while( e.hasMoreElements() ) {
if ( i > 0 )
s += ", ";
i++;
s += (String)e.nextElement();
}
s += "; Precluded: ";
e = not.elements();
i = 0;
while( e.hasMoreElements() ) {
if ( i > 0 )
s += ", ";
i++;
s += (String)e.nextElement();
}
if ( isObsolete() ) {
s += "; OBSOLETE";
}
s += getQualifierString( IGNOREVALS );
return s;
}
public final static String AUX = "AUX";
public final static String MUST = "MUST";
public final static String MAY = "MAY";
public final static String NOT = "NOT";
// Qualifiers known to not have values; prepare a Hashtable
static final String[] NOVALS = { "OBSOLETE" };
static {
for( int i = 0; i < NOVALS.length; i++ ) {
novalsTable.put( NOVALS[i], NOVALS[i] );
}
}
// Qualifiers which we output explicitly in toString()
static final String[] IGNOREVALS = { OBSOLETE,
AUX,
MUST,
MAY,
NOT
};
private Vector must = new Vector();
private Vector may = new Vector();
private Vector aux = new Vector();
private Vector not = new Vector();
}

View File

@@ -0,0 +1,276 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The structures of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* The definition of a DIT structure rule in the schema.
* <A HREF="http://www.ietf.org/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* DIT Structure Rule Description</A> covers the types of information
* to specify when defining a DIT structure rule. According to the RFC,
* the description of a DIT structure rule can include the following:
* <P>
*
* <UL>
* <LI>an OID identifying the attribute type
* <LI>a name identifying the attribute type
* <LI>a description of the attribute type
* <LI>the name of the parent attribute type
* <LI>the syntax used by the attribute (for example,
* <CODE>cis</CODE> or <CODE>int</CODE>)
* <LI>an indication of whether the attribute type is single-valued
* or multi-valued
* </UL>
* <P>
*
* When you construct an <CODE>LDAPDITStructureRuleSchema</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
* returns schema information as an object with attribute values in this
* format.
* <P>
*
* There are a number of additional optional description fields which
* are not explicitly accessible through LDAPDITStructureRuleSchema, but which
* can be managed with setQualifier, getQualifier, and getQualifierNames:
* <P>
*
* <UL>
* <LI>OBSOLETE
* </UL>
* <P>
*
* To get the name, OID, and description of this DIT structure rule
* , use the <CODE>getName</CODE>, <CODE>getOID</CODE>, and
* <CODE>getDescription</CODE> methods inherited from the abstract class
* <CODE>LDAPSchemaElement</CODE>. Optional and custom qualifiers are
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
* from <CODE>LDAPSchemaElement</CODE>.
* <P>
*
* 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 DITStructureRuleDescription as follows:
* <P>
* <PRE>
* DITStructureRuleDescription = "(" whsp
* ruleidentifier whsp ; DITStructureRule identifier
* [ "NAME" qdescrs ]
* [ "DESC" qdstring ]
* [ "OBSOLETE" whsp ]
* "FORM" woid whsp ; NameForm
* [ "SUP" ruleidentifiers whsp ] ; superior DITStructureRules
* ")"
* </PRE>
*
* @version 1.0
* @see netscape.ldap.LDAPSchemaElement
**/
public class LDAPDITStructureRuleSchema extends LDAPSchemaElement {
static final long serialVersionUID = -2823317246039655811L;
/**
* Constructs a blank element.
*/
protected LDAPDITStructureRuleSchema() {
super();
}
/**
* Constructs a DIT structure rule definition, using the specified
* information.
* @param name name of the attribute type
* @param ruleID unique identifier of the structure rule.<BR>
* NOTE: this is an integer, not a dotted numerical identifier.
* Structure rules aren't identified by OID.
* @param description description of attribute type
* @param obsolete <code>true</code> if the rule is obsolete
* @param nameForm either the identifier or name of a name form.
* This is used to indirectly refer to the object class that this
* structure rule applies to.
* @param superiors list of superior structure rules - specified
* by their integer ID. The object class specified by this structure
* rule (via the nameForm parameter) may only be subordinate in
* the DIT to object classes of those represented by the structure
* rules here.
*/
public LDAPDITStructureRuleSchema( String name, int ruleID,
String description, boolean obsolete,
String nameForm,
String[] superiors ) {
super( name, "", description, null );
this.nameForm = nameForm;
this.ruleID = ruleID;
if ( obsolete ) {
setQualifier( OBSOLETE, "" );
}
if ( (superiors != null) && (superiors.length > 0) ) {
setQualifier( SUPERIOR, superiors );
}
}
/**
* Constructs a DIT structure rule definition based on a description in
* the DITStructureRuleDescription format. For information on this format,
* (see <A HREF="http://www.ietf.org/rfc/rfc2252.txt"
* >RFC 2252, Lightweight Directory Access Protocol (v3):
* DIT Structure Rule Description</A>. 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 "attributetypes" are attribute type descriptions
* in this format.)
* <P>
*
* @param raw definition of the DIT structure rule in the
* DITStructureRuleDescription format
*/
public LDAPDITStructureRuleSchema( String raw ) {
attrName = "ditStructureRules";
parseValue( raw );
Object o = properties.get( FORM );
if ( o != null ) {
nameForm = (String)o;
}
try {
ruleID = Integer.parseInt( oid );
} catch ( Exception e ) {
}
}
/**
* Returns a list of all structure rules that are superior to this
* structure rule. To resolve to an object class, you need to first
* resolve the superior id to another structure rule, then call
* getNameForm().getObjectClass() on that structure rule.
* @return the structure rules that are superior to this
* structure rule.
*/
public String[] getSuperiors() {
return getQualifier( SUPERIOR );
}
/**
* Returns the rule ID for this structure rule. Note that this returns
* an integer rather than a dotted decimal OID. Objects of this class do
* not have an OID, thus getID will return null.
*
* @return the rule ID for this structure rule.
*/
public int getRuleID() {
return ruleID;
}
/**
* Returns the NameForm that this structure rule controls. You can get
* the actual object class that this structure rule controls by calling
* getNameForm().getObjectClass().
*
* @return the NameForm that this structure rule controls.
*/
public String getNameForm() {
return nameForm;
}
/**
* Prepares a value in RFC 2252 format for submission to a server
*
* @return a String ready for submission to an LDAP server.
*/
public String getValue() {
String s = "( " + ruleID + ' ';
if ( name != null ) {
s += "NAME " + '\'' + name + "\' ";
}
if ( description != null ) {
s += "DESC \'" + description + "\' ";
}
if ( isObsolete() ) {
s += OBSOLETE + ' ';
}
s += FORM + " " + nameForm + ' ';
String val = getValue( SUPERIOR, false );
if ( (val != null) && (val.length() > 1) ) {
s += val + ' ';
}
val = getCustomValues();
if ( val.length() > 0 ) {
s += val + ' ';
}
s += ')';
return s;
}
/**
* Gets the definition of the rule in a user friendly format.
* This is the format that the rule definition uses when
* printing the attribute type or the schema.
* @return definition of the rule in a user friendly format.
*/
public String toString() {
String s = "Name: " + name + "; ruleID: " + ruleID + "; ";
s += "Description: " + description;
if ( isObsolete() ) {
s += "; OBSOLETE";
}
String[] superiors = getSuperiors();
if ( superiors != null ) {
for( int i = 0; i < superiors.length; i++ ) {
s += superiors[i];
if ( i < (superiors.length-1) ) {
s += ", ";
}
}
}
s += "Name form: " + nameForm + "; ";
s += getQualifierString( IGNOREVALS );
return s;
}
public final static String FORM = "FORM";
// Qualifiers known to not have values; prepare a Hashtable
static final String[] NOVALS = { "OBSOLETE" };
static {
for( int i = 0; i < NOVALS.length; i++ ) {
novalsTable.put( NOVALS[i], NOVALS[i] );
}
}
// Qualifiers which we output explicitly in toString()
static final String[] IGNOREVALS = { OBSOLETE,
FORM,
"SUP"
};
private String nameForm = null;
private int ruleID = 0;
}

View File

@@ -0,0 +1,174 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import netscape.ldap.util.*;
import java.io.*;
/**
* Represents a distinguished name in LDAP.
* <P>
*
* You can use objects of this class to split a distinguished name
* (DN) into its individual components. You can also escape the
* characters in a DN.
* <P>
*
* @version 1.0
*/
public class LDAPDN {
/**
* Returns the individual components of a distinguished name (DN).
* @param dn distinguished name of which you want to get the components.
* @param noTypes if <CODE>true</CODE>, returns only the values of the
* components and not the names (such as 'cn=')
* @return an array of strings representing the components of the DN.
* @see netscape.ldap.LDAPDN#explodeRDN(java.lang.String, boolean)
*/
public static String[] explodeDN (String dn, boolean noTypes) {
DN name = new DN(dn);
return name.explodeDN(noTypes);
}
/**
* Returns the individual components of a relative distinguished name (RDN).
* @param rdn relative distinguished name of which you want to get the components.
* @param noTypes if <CODE>true</CODE>, returns only the values of the
* components and not the names (such as 'cn=')
* @return an array of strings representing the components of the RDN.
* @see netscape.ldap.LDAPDN#explodeDN(java.lang.String, boolean)
*/
public static String[] explodeRDN (String rdn, boolean noTypes) {
RDN name = new RDN(rdn);
if ( noTypes ) {
return name.getValues();
} else {
String[] str = new String[1];
str[0] = name.toString();
return str;
}
}
/**
* Returns the RDN after escaping the characters specified
* by <CODE>netscape.ldap.util.DN.ESCAPED_CHAR</CODE>.
* <P>
*
* @param rdn the RDN to escape
* @return the RDN with the characters escaped.
* @see netscape.ldap.util.DN#ESCAPED_CHAR
* @see netscape.ldap.LDAPDN#unEscapeRDN(java.lang.String)
*/
public static String escapeRDN(String rdn) {
RDN name = new RDN(rdn);
String[] val = name.getValues();
if (val == null)
return rdn;
StringBuffer[] buffer = new StringBuffer[val.length];
StringBuffer retbuf = new StringBuffer();
String[] types = name.getTypes();
for (int j = 0; j < val.length; j++ ) {
buffer[j] = new StringBuffer(val[j]);
int i=0;
while (i<buffer[j].length()) {
if (isEscape(buffer[j].charAt(i))) {
buffer[j].insert(i, '\\');
i++;
}
i++;
}
retbuf.append( ((retbuf.length() > 0) ? " + " : "") + types[j] + "=" +
( new String( buffer[j] ) ) );
}
return new String( retbuf );
}
/**
* Returns the RDN after unescaping any escaped characters.
* For a list of characters that are typically escaped in a
* DN, see <CODE>netscape.ldap.LDAPDN.ESCAPED_CHAR</CODE>.
* <P>
*
* @param rdn the RDN to unescape
* @return the unescaped RDN.
* @see netscape.ldap.util.DN#ESCAPED_CHAR
* @see netscape.ldap.LDAPDN#escapeRDN(java.lang.String)
*/
public static String unEscapeRDN(String rdn) {
RDN name = new RDN(rdn);
String[] vals = name.getValues();
if ( (vals == null) || (vals.length < 1) )
return rdn;
StringBuffer buffer = new StringBuffer(vals[0]);
StringBuffer copy = new StringBuffer();
int i=0;
while (i<buffer.length()) {
char c = buffer.charAt(i++);
if (c != '\\') {
copy.append(c);
}
else { // copy the escaped char following the back slash
if (i<buffer.length()) {
copy.append(buffer.charAt(i++));
}
}
}
return name.getTypes()[0]+"="+(new String(copy));
}
/**
* Normalizes the dn.
* @param dn the DN to normalize
* @return the normalized DN
*/
public static String normalize(String dn) {
return (new DN(dn)).toString();
}
/**
* Compares two dn's for equality.
* @param dn1 the first dn to compare
* @param dn2 the second dn to compare
* @return true if the two dn's are equal
*/
public static boolean equals(String dn1, String dn2) {
return normalize(dn1).equals(normalize(dn2));
}
private static boolean isEscape(char c) {
for (int i=0; i<DN.ESCAPED_CHAR.length; i++)
if (c == DN.ESCAPED_CHAR[i])
return true;
return false;
}
}

View File

@@ -0,0 +1,206 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* Represents an entry in the directory.
*
* @version 1.0
*/
public class LDAPEntry implements java.io.Serializable {
static final long serialVersionUID = -5563306228920012807L;
private String dn = null;
private LDAPAttributeSet attrSet = null;
/**
* Constructs an empty entry.
*/
public LDAPEntry() {
dn = null;
attrSet = new LDAPAttributeSet();
}
/**
* Constructs a new entry with the specified distinguished name and with
* an empty attribute set.
* @param distinguishedName the distinguished name of the new entry
*/
public LDAPEntry( String distinguishedName ) {
dn = distinguishedName;
attrSet = new LDAPAttributeSet();
}
/**
* Constructs a new entry with the specified distinguished name and
* set of attributes.
* @param distinguishedName the distinguished name of the new entry
* @param attrs the set of attributes to assign to the new entry
* @see netscape.ldap.LDAPAttributeSet
*/
public LDAPEntry( String distinguishedName, LDAPAttributeSet attrs ) {
dn = distinguishedName;
attrSet = attrs;
}
/**
* Returns the distinguished name of the current entry.
* @return distinguished name of the current entry.
*/
public String getDN() {
return dn;
}
void setDN(String name) {
dn = name;
}
/**
* Returns the attribute set of the entry.
* @return set of attributes in the entry.
* @see netscape.ldap.LDAPAttributeSet
*/
public LDAPAttributeSet getAttributeSet() {
return attrSet;
}
/**
* Creates a new attribute set containing only the attributes
* that have the specified subtypes.
* <P>
*
* For example, suppose an entry contains the following attributes:
* <P>
*
* <PRE>
* cn
* cn;lang-ja
* sn;phonetic;lang-ja
* sn;lang-us
* </PRE>
*
* If you call the <CODE>getAttributeSet</CODE> method and pass
* <CODE>lang-ja</CODE> as the argument, the method returns
* an attribute set containing the following attributes:
* <P>
*
* <PRE>
* cn;lang-ja
* sn;phonetic;lang-ja
* </PRE>
*
* @param subtype semi-colon delimited list of subtypes
* that you want to find in attribute names.
*<PRE>
* "lang-ja" // Only Japanese language subtypes
* "binary" // Only binary subtypes
* "binary;lang-ja" // Only Japanese language subtypes
* which also are binary
*</PRE>
* @return attribute set containing the attributes that have
* the specified subtypes.
* @see netscape.ldap.LDAPAttributeSet
* @see netscape.ldap.LDAPAttributeSet#getSubset
*/
public LDAPAttributeSet getAttributeSet(String subtype) {
return attrSet.getSubset(subtype);
}
/**
* In an entry, returns the single attribute that exactly matches the
* specified attribute name.
* @param attrName name of attribute to return
* For example:
*<PRE>
* "cn" // Only a non-subtyped version of cn
* "cn;lang-ja" // Only a Japanese version of cn, will not
* // return "cn;lang-ja-JP-kanji", for example
*</PRE>
* @return attribute in the current entry that has exactly the same name,
* or null (if no attribute in the entry matches the specified name).
* @see netscape.ldap.LDAPAttribute
*/
public LDAPAttribute getAttribute(String attrName) {
return attrSet.getAttribute(attrName);
}
/**
* Returns the subtype that matches "attrName" and that best matches
* a language specification "lang". If there are subtypes other than
* "lang" subtypes included in attrName, e.g. "cn;binary", only
* attributes with all of those subtypes are returned. If lang is
* null or empty, the method behaves as getAttribute(attrName). If
* there are no matching attributes, null is returned.
*
* Example:<PRE>
* Assume the entry contains only the following attributes:
* <CODE>cn;lang-en</CODE>
* <CODE>cn;lang-ja-JP-kanji</CODE>
* <CODE>sn</CODE>
* getAttribute( "cn" ) returns <CODE>null</CODE>.
* getAttribute( "sn" ) returns the "<CODE>sn</CODE>" attribute.
* getAttribute( "cn", "lang-en-us" ) returns the "<CODE>cn;lang-en</CODE>" attribute.
* getAttribute( "cn", "lang-en" ) returns the "<CODE>cn;lang-en</CODE>" attribute.
* getAttribute( "cn", "lang-ja" ) returns <CODE>null</CODE>.
* getAttribute( "sn", "lang-en" ) returns the "<CODE>sn</CODE>" attribute.
*</PRE>
* <P>
* @param attrName name of attribute to find in the entry
* @param lang a language specification (for example, <CODE>lang-en</CODE>)
* @return the attribute that matches the base name and that best
* matches any specified language subtype.
* @see netscape.ldap.LDAPAttribute
*/
public LDAPAttribute getAttribute( String attrName, String lang ) {
return attrSet.getAttribute( attrName, lang );
}
/**
* Retrieves the string representation of the entry's
* distinguished name (DN) and its attributes.
* For example:
*
* <PRE>
* LDAPEntry: uid=bjensen, ou=People, o=airius.com; LDAPAttributeSet:
* LDAPAttribute {type='cn', values='Barbara Jensen,Babs Jensen'}
* LDAPAttribute {type='sn', values='Jensen'}LDAPAttribute {type='givenname',
* values='Barbara'}LDAPAttribute {type='objectclass', values='top,person,
* organizationalPerson,inetOrgPerson'}LDAPAttribute {type='ou',
* values='Product Development,People'}
* </PRE>
*
* @return string representation of the entry's DN and its attributes.
*/
public String toString() {
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

@@ -0,0 +1,66 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
/**
* The <CODE>LDAPEntryComparator</CODE> interface represents the
* algorithm used to sort the search results. This interface specifies
* one method, <CODE>isGreater</CODE>, which compares two entries and
* determines the order in which the two entries should be sorted.
* <P>
*
* The <CODE>netscape.ldap</CODE> package includes a class that
* implements this interface. The <CODE>LDAPCompareAttrNames</CODE>
* class represents a comparator that sorts the two entries alphabetically,
* based on the value of one or more attributes.
* <P>
*
* When calling the <CODE>sort</CODE> method of the
* <CODE>LDAPSearchResults</CODE> class, you need to specify
* a class that implements the <CODE>LDAPEntryComparator</CODE>
* interface.
* <P>
*
* @version 1.0
* @see netscape.ldap.LDAPCompareAttrNames
* @see netscape.ldap.LDAPSearchResults#sort
*/
public interface LDAPEntryComparator {
/**
* Specifies the algorithm used to
* compare entries when sorting search results.
* <P>
*
* <CODE>isGreater</CODE> returns <CODE>true</CODE>
* if the entry specified in the first argument should
* be sorted before the entry specified in the second
* argument.
* <P>
*
* @version 1.0
* @see netscape.ldap.LDAPCompareAttrNames
* @see netscape.ldap.LDAPSearchResults#sort
*/
public boolean isGreater (LDAPEntry greater, LDAPEntry less);
}

View File

@@ -0,0 +1,900 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import netscape.ldap.client.*;
import netscape.ldap.client.opers.*;
import java.io.*;
/**
* Indicates that an error has occurred. An <CODE>LDAPException</CODE>
* can result from physical problems (such as network errors) as well as
* problems with LDAP operations (for example, if the LDAP add operation
* fails because of duplicate entry).
* <P>
*
* Most errors that occur throw this type of exception. In order to determine
* the cause of the error, you can call the <CODE>getLDAPResultCode()</CODE>
* method to get the specific result code and compare this code against
* the result codes defined as fields in this class. (For example, if
* the result code matches the value of the field
* <CODE>LDAPException.TIME_LIMIT_EXCEEDED</CODE>, the time limit passed
* before the search operation could be completed.)
* <P>
*
* This exception includes methods for getting an error message that
* corresponds to the LDAP result code (for example, "Timelimit exceeded"
* for <CODE>LDAPException.TIME_LIMIT_EXCEEDED</CODE>). These error
* messages are specified in the following files:
* <PRE>netscape/ldap/errors/ErrorCodes_<I>locale_string</I>.props</PRE>
* where <I>locale_string</I> is the name of the locale that includes
* the language and country, but not the variant.
* <P>
*
* For example:
* <PRE>netscape/ldap/errors/ErrorCodes_en_US.props</PRE>
*
* The LDAP Java classes get this locale name by calling the
* <CODE>java.util.Locale.toString</CODE> method for the specified
* locale and ignoring the variant. If no locale is specified, the
* LDAP Java classes use the <CODE>java.util.Locale.getDefault</CODE>
* method to get the locale of the local host system.
* <P>
*
* In order to get error messages for different locales, you need to
* provide files containing the error messages for those locales.
* The files should be located in the <CODE>netscape/ldap/errors</CODE>
* directory and should use the naming convention specified above.
* <P>
*
* The following is a list of LDAP result codes:
* <PRE>
* Result
* Code Defined Value
* ====== =============
* 0 <A HREF="#SUCCESS">SUCCESS</A>
* 1 <A HREF="#OPERATION_ERROR">OPERATION_ERROR</A>
* 2 <A HREF="#PROTOCOL_ERROR">PROTOCOL_ERROR</A>
* 3 <A HREF="#TIME_LIMIT_EXCEEDED">TIME_LIMIT_EXCEEDED</A>
* 4 <A HREF="#SIZE_LIMIT_EXCEEDED">SIZE_LIMIT_EXCEEDED</A>
* 5 <A HREF="#COMPARE_FALSE">COMPARE_FALSE</A>
* 6 <A HREF="#COMPARE_TRUE">COMPARE_TRUE</A>
* 7 <A HREF="#AUTH_METHOD_NOT_SUPPORTED">AUTH_METHOD_NOT_SUPPORTED</A>
* 8 <A HREF="#STRONG_AUTH_REQUIRED">STRONG_AUTH_REQUIRED</A>
* 9 <A HREF="#LDAP_PARTIAL_RESULTS">LDAP_PARTIAL_RESULTS</A>
* 10 <A HREF="#REFERRAL">REFERRAL</A> (LDAP v3)
* 11 <A HREF="#ADMIN_LIMIT_EXCEEDED">ADMIN_LIMIT_EXCEEDED</A> (LDAP v3)
* 12 <A HREF="#UNAVAILABLE_CRITICAL_EXTENSION">UNAVAILABLE_CRITICAL_EXTENSION</A> (LDAP v3)
* 13 <A HREF="#CONFIDENTIALITY_REQUIRED">CONFIDENTIALITY_REQUIRED</A> (LDAP v3)
* 14 <A HREF="#SASL_BIND_IN_PROGRESS">SASL_BIND_IN_PROGRESS</A> (LDAP v3)
* 16 <A HREF="#NO_SUCH_ATTRIBUTE">NO_SUCH_ATTRIBUTE</A>
* 17 <A HREF="#UNDEFINED_ATTRIBUTE_TYPE">UNDEFINED_ATTRIBUTE_TYPE</A>
* 18 <A HREF="#INAPPROPRIATE_MATCHING">INAPPROPRIATE_MATCHING</A>
* 19 <A HREF="#CONSTRAINT_VIOLATION">CONSTRAINT_VIOLATION</A>
* 20 <A HREF="#ATTRIBUTE_OR_VALUE_EXISTS">ATTRIBUTE_OR_VALUE_EXISTS</A>
* 21 <A HREF="#INVALID_ATTRIBUTE_SYNTAX">INVALID_ATTRIBUTE_SYNTAX</A>
* 32 <A HREF="#NO_SUCH_OBJECT">NO_SUCH_OBJECT</A>
* 33 <A HREF="#ALIAS_PROBLEM">ALIAS_PROBLEM</A>
* 34 <A HREF="#INVALID_DN_SYNTAX">INVALID_DN_SYNTAX</A>
* 35 <A HREF="#IS_LEAF">IS_LEAF</A>
* 36 <A HREF="#ALIAS_DEREFERENCING_PROBLEM">ALIAS_DEREFERENCING_PROBLEM</A>
* 48 <A HREF="#INAPPROPRIATE_AUTHENTICATION">INAPPROPRIATE_AUTHENTICATION</A>
* 49 <A HREF="#INVALID_CREDENTIALS">INVALID_CREDENTIALS</A>
* 50 <A HREF="#INSUFFICIENT_ACCESS_RIGHTS">INSUFFICIENT_ACCESS_RIGHTS</A>
* 51 <A HREF="#BUSY">BUSY</A>
* 52 <A HREF="#UNAVAILABLE">UNAVAILABLE</A>
* 53 <A HREF="#UNWILLING_TO_PERFORM">UNWILLING_TO_PERFORM</A>
* 54 <A HREF="#LOOP_DETECT">LOOP_DETECT</A>
* 64 <A HREF="#NAMING_VIOLATION">NAMING_VIOLATION</A>
* 65 <A HREF="#OBJECT_CLASS_VIOLATION">OBJECT_CLASS_VIOLATION</A>
* 66 <A HREF="#NOT_ALLOWED_ON_NONLEAF">NOT_ALLOWED_ON_NONLEAF</A>
* 67 <A HREF="#NOT_ALLOWED_ON_RDN">NOT_ALLOWED_ON_RDN</A>
* 68 <A HREF="#ENTRY_ALREADY_EXISTS">ENTRY_ALREADY_EXISTS</A>
* 69 <A HREF="#OBJECT_CLASS_MODS_PROHIBITED">OBJECT_CLASS_MODS_PROHIBITED</A>
* 71 <A HREF="#AFFECTS_MULTIPLE_DSAS">AFFECTS_MULTIPLE_DSAS</A> (LDAP v3)
* 80 <A HREF="#OTHER">OTHER</A>
* 81 <A HREF="#SERVER_DOWN">SERVER_DOWN</A>
* 85 <A HREF="#LDAP_TIMEOUT">LDAP_TIMEOUT</A>
* 89 <A HREF="#PARAM_ERROR">PARAM_ERROR</A>
* 91 <A HREF="#CONNECT_ERROR">CONNECT_ERROR</A>
* 92 <A HREF="#LDAP_NOT_SUPPORTED">LDAP_NOT_SUPPORTED</A>
* 93 <A HREF="#CONTROL_NOT_FOUND">CONTROL_NOT_FOUND</A>
* 94 <A HREF="#NO_RESULTS_RETURNED">NO_RESULTS_RETURNED</A>
* 95 <A HREF="#MORE_RESULTS_TO_RETURN">MORE_RESULTS_TO_RETURN</A>
* 96 <A HREF="#CLIENT_LOOP">CLIENT_LOOP</A>
* 97 <A HREF="#REFERRAL_LIMIT_EXCEEDED">REFERRAL_LIMIT_EXCEEDED</A>
* </PRE>
* <P>
*
* @version 1.0
* @see netscape.ldap.LDAPReferralException
*/
public class LDAPException extends java.lang.Exception
implements java.io.Serializable {
static final long serialVersionUID = -9215007872184847924L;
/**
* (0) The operation completed successfully.
*/
public final static int SUCCESS = 0;
/**
* (1) An internal error occurred in the LDAP server.
*/
public final static int OPERATION_ERROR = 1;
/**
* (2) A LDAP server could not correctly interpret the request
* sent by your client because the request does not strictly
* comply with the LDAP protocol. (For example, the data
* was not correctly BER-encoded, or a specified value -- such
* as the search scope or modification type -- does not
* comply with the LDAP protocol. If you invent your own
* search scope, for instance, this result code might be returned.<P>
*/
public final static int PROTOCOL_ERROR = 2;
/**
* (3) The search operation could not be completed within
* the maximum time limit. You can specify the maximum time
* limit by calling the <CODE>LDAPConnection.setOption</CODE>
* method or the <CODE>LDAPSearchConstraints.setServerTimeLimit</CODE>
* method.<P>
*
* @see netscape.ldap.LDAPConnection#setOption
* @see netscape.ldap.LDAPSearchConstraints#setServerTimeLimit
*/
public final static int TIME_LIMIT_EXCEEDED = 3;
/**
* (4) The search found more than the maximum number of results.
* You can specify the maximum number of results by calling the
* <CODE>LDAPConnection.setOption</CODE> method or the
* <CODE>LDAPSearchConstraints.setSizeLimit</CODE> method.<P>
*
* @see netscape.ldap.LDAPConnection#setOption
* @see netscape.ldap.LDAPSearchConstraints#setMaxResults
*/
public final static int SIZE_LIMIT_EXCEEDED = 4;
/**
* (5) Value returned by an LDAP compare operation if the
* specified attribute and value is not found in the entry
* (no matching value found).
*
* @see netscape.ldap.LDAPConnection#compare
*/
public final static int COMPARE_FALSE = 5;
/**
* (6) Value returned by an LDAP compare operation if the
* specified attribute and value is found in the entry
* (matching value found).
*
* @see netscape.ldap.LDAPConnection#compare
*/
public final static int COMPARE_TRUE = 6;
/**
* (7) The specified authentication method is not supported
* by the LDAP server that you are connecting to. The
* <CODE>LDAPConnection</CODE> class is implemented so that
* <CODE>LDAPConnection.authenticate</CODE> always
* uses the LDAP_AUTH_SIMPLE method of authentication.
* (<CODE>LDAPConnection.authenticate</CODE> does not
* allow you to select the method of authentication.)<P>
*/
public final static int AUTH_METHOD_NOT_SUPPORTED = 7;
/**
* (8) A stronger authentication method (more than LDAP_AUTH_SIMPLE)
* is required by the LDAP server that you are connecting to.
* The <CODE>LDAPConnection</CODE> class is implemented so that
* <CODE>LDAPConnection.authenticate</CODE> always
* uses the LDAP_AUTH_SIMPLE method of authentication.
* (<CODE>LDAPConnection.authenticate</CODE> does not
* allow you to select the method of authentication.)<P>
*/
public final static int STRONG_AUTH_REQUIRED = 8;
/**
* (9) The LDAP server is referring your client to another
* LDAP server. If you set up the <CODE>LDAPConnection</CODE>
* 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.)
* <P>
*
* (To set up automatic referrals in an <CODE>LDAPConnection</CODE>
* object, set the <CODE>LDAPConnection.REFERRALS</CODE> option
* to <CODE>true</CODE> and the LDAPConnection.REFERRALS_REBIND_PROC</CODE>
* option to the object containing the method for retrieving
* authentication information (in other words, the distinguished
* name and password to use when authenticating to other LDAP servers).
* <P>
*
* If instead you set <CODE>LDAPConnection.REFERRALS</CODE>
* to <CODE>false</CODE> (or if you set
* <CODE>LDAPConstraints.setReferrals</CODE> to <CODE>false</CODE>,
* an <CODE>LDAPReferralException</CODE> is raised.
* <P>
*
* If an error occurs during the referral process, an
* <CODE>LDAPException</CODE> with this result code
* (<CODE>LDAP_PARTIAL_RESULTS</CODE>) is raised.
* <P>
*
* @see netscape.ldap.LDAPConnection#setOption
* @see netscape.ldap.LDAPConstraints#setReferrals
* @see netscape.ldap.LDAPConstraints#setRebindProc
* @see netscape.ldap.LDAPRebind
* @see netscape.ldap.LDAPRebindAuth
* @see netscape.ldap.LDAPReferralException
*/
public final static int LDAP_PARTIAL_RESULTS = 9;
/**
* (10) [LDAP v3] The server does not hold the requested entry.
* The referral field of the server's response contains a
* reference to another server (or set of servers), which
* your client can access through LDAP or other protocols.
* Typically, these references are LDAP URLs that identify
* the server that may contain the requested entry.
* <P>
*
* When this occurs, a <CODE>LDAPReferralException</CODE>
* is thrown. You can catch this exception and call the
* <CODE>getURLs</CODE> method to get the list of LDAP
* URLs from the exception.
* <P>
*
* @see netscape.ldap.LDAPReferralException
*/
public final static int REFERRAL = 10;
/**
* (11) [LDAP v3] The adminstrative limit on the
* maximum number of entries to return was exceeded.
* In the Netscape Directory Server 3.0, this
* corresponds to the "look through limit" for
* the server. This is the maximum number of
* entries that the server will check through
* when determining which entries match the
* search filter and scope.
* <P>
*/
public final static int ADMIN_LIMIT_EXCEEDED = 11;
/**
* (12) [LDAP v3] The server received an LDAP v3 control
* that is marked critical and either (1) is not
* recognized or supported by the server, or
* (2) is inappropriate for the operation requested.
* The Netscape Directory Server 3.0 also returns
* this result code if the client specifies a
* matching rule that is not supported by the server.
* <P>
*
* @see netscape.ldap.LDAPControl
*/
public final static int UNAVAILABLE_CRITICAL_EXTENSION = 12;
/**
* (13) [LDAP v3] A secure connection is required for
* this operation.
*/
public final static int CONFIDENTIALITY_REQUIRED = 13;
/**
* (14) [LDAP v3] While authenticating your client
* by using a SASL (Simple Authentication Security Layer)
* mechanism, the server requires the client to send
* a new SASL bind request (specifying the same SASL
* mechanism) to continue the authentication process.
*/
public final static int SASL_BIND_IN_PROGRESS = 14;
/**
* (16) The specified attribute could not be found.
*/
public final static int NO_SUCH_ATTRIBUTE = 16;
/**
* (17) The specified attribute is not defined.
*/
public final static int UNDEFINED_ATTRIBUTE_TYPE = 17;
/**
* (18) An inappropriate type of matching was used.
*/
public final static int INAPPROPRIATE_MATCHING = 18;
/**
* (19) An internal error occurred in the LDAP server.
*/
public final static int CONSTRAINT_VIOLATION = 19;
/**
* (20) The value that you are adding to an attribute
* already exists in the attribute.
*/
public final static int ATTRIBUTE_OR_VALUE_EXISTS = 20;
/**
* (21) The request contains invalid syntax.
*/
public final static int INVALID_ATTRIBUTE_SYNTAX = 21;
/**
* (32) The entry specified in the request does not exist.
*/
public final static int NO_SUCH_OBJECT = 32;
/**
* (33) An problem occurred with an alias.
*/
public final static int ALIAS_PROBLEM = 33;
/**
* (34) The specified distinguished name (DN) uses invalid syntax.
*/
public final static int INVALID_DN_SYNTAX = 34;
/**
* (35) The specified entry is a "leaf" entry (it has no entries
* beneath it in the directory tree).
*/
public final static int IS_LEAF = 35;
/**
* (36) An error occurred when dereferencing an alias.
*/
public final static int ALIAS_DEREFERENCING_PROBLEM = 36;
/**
* (48) The authentication presented to the server is inappropriate.
* This result code might occur, for example, if your client
* presents a password and the corresponding entry has no
* userpassword attribute.
*/
public final static int INAPPROPRIATE_AUTHENTICATION = 48;
/**
* (49) The credentials presented to the server for authentication
* are not valid. (For example, the password sent to the server
* does not match the user's password in the directory.)
*/
public final static int INVALID_CREDENTIALS = 49;
/**
* (50) The client is authenticated as a user who does not have the
* access privileges to perform this operation.
*/
public final static int INSUFFICIENT_ACCESS_RIGHTS = 50;
/**
* (51) The LDAP server is busy.
*/
public final static int BUSY = 51;
/**
* (52) The LDAP server is unavailable.
*/
public final static int UNAVAILABLE = 52;
/**
* (53) The LDAP server is unable to perform the specified operation.
*/
public final static int UNWILLING_TO_PERFORM = 53;
/**
* (54) A loop has been detected.
*/
public final static int LOOP_DETECT = 54;
/**
* (60) The "server-side sorting" control
* was not included with the "virtual list view"
* control in the search request.
*/
public final static int SORT_CONTROL_MISSING = 60;
/**
* (61) An index range error occurred.
*/
public final static int INDEX_RANGE_ERROR = 61;
/**
* (64) A naming violation has occurred.
*/
public final static int NAMING_VIOLATION = 64;
/**
* (65) The requested operation will add or change
* data so that the data no longer complies with
* the schema.
*/
public final static int OBJECT_CLASS_VIOLATION = 65;
/**
* (66) The requested operation can only be performed
* on an entry that has no entries beneath it in the
* directory tree (in other words, a "leaf" entry).
* <P>
*
* For example, you cannot delete or rename an entry
* if the entry has subentries beneath it.
* <P>
*/
public final static int NOT_ALLOWED_ON_NONLEAF = 66;
/**
* (67) The specified operation cannot be performed on
* a relative distinguished name (RDN).
*/
public final static int NOT_ALLOWED_ON_RDN = 67;
/**
* (68) The specified entry already exists. You might receive
* this error if, for example, you attempt to add an entry
* that already exists or if you attempt to change the name
* of an entry to the name of an entry that already exists.
*/
public final static int ENTRY_ALREADY_EXISTS = 68;
/**
* (69) You cannot modify the specified object class.
*/
public final static int OBJECT_CLASS_MODS_PROHIBITED = 69;
/**
* (71) [LDAP v3] The client attempted to move an entry
* from one LDAP server to another by requesting a "modify
* DN" operation. In general, clients should not be able
* to arbitrarily move entries and subtrees between servers.
* <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, LDAPConstraints)
*/
public final static int AFFECTS_MULTIPLE_DSAS = 71;
/**
* (80) General result code for other types of errors
* that may occur.
*/
public final static int OTHER = 80;
/**
* (81) The LDAP server cannot be contacted.
*/
public final static int SERVER_DOWN = 0x51;
/**
* (85) The operation could not be completed within the
* maximum time limit. You can specify the maximum time limit
* by calling the <CODE>LDAPConstraints.setTimeLimit</CODE>
* method.<P>
*
* @see netscape.ldap.LDAPConstraints#setTimeLimit
*/
public final static int LDAP_TIMEOUT = 0x55;
/**
* (89) When calling a constructor or method from your client,
* one or more parameters were incorrectly specified.
*/
public final static int PARAM_ERROR = 0x59;
/**
* (91) Your LDAP client failed to connect to the LDAP server.
*/
public final static int CONNECT_ERROR = 0x5b;
/**
* (92) The request is not supported by this version of the LDAP protocol.
*/
public final static int LDAP_NOT_SUPPORTED = 0x5c;
/**
* (93) The requested control is not found.
* <P>
*
* @see netscape.ldap.LDAPControl
*/
public final static int CONTROL_NOT_FOUND = 0x5d;
/**
* (94) No results have been returned from the server.
*/
public final static int NO_RESULTS_RETURNED = 0x5e;
/**
* (95) More results are being returned from the server.
*/
public final static int MORE_RESULTS_TO_RETURN = 0x5f;
/**
* (96) Your LDAP client detected a loop in the referral.
*/
public final static int CLIENT_LOOP = 0x60;
/**
* (97) The number of sequential referrals (for example,
* the client may be referred first from LDAP server A to
* LDAP server B, then from LDAP server B to LDAP server C,
* and so on) has exceeded the maximum number of referrals
* (the <CODE>LDAPv2.REFERRALS_HOP_LIMIT</CODE> option).
* <P>
*
* @see netscape.ldap.LDAPv2#REFERRALS_HOP_LIMIT
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public final static int REFERRAL_LIMIT_EXCEEDED = 0x61;
/**
* Internal variables
*/
private int resultCode = -1;
private String errorMessage = null;
private String matchedDN = null;
private Locale m_locale = Locale.getDefault();
private static Hashtable cacheResource = new Hashtable();
private static final String baseName = "netscape/ldap/errors/ErrorCodes";
/**
* Constructs a default exception with no specific error information.
*/
public LDAPException() {
}
/**
* Constructs a default exception with a specified string of
* additional information. This string appears if you call
* the <CODE>toString()</CODE> method.
* <P>
*
* This form is used for lower-level errors.
* It is recommended that you always use one of the constructors
* that takes a result code as a parameter. (If your exception is
* thrown, any code that catches the exception may need to extract
* the result code from the exception.)
* <P>
* @param message the additional error information
* @see netscape.ldap.LDAPException#toString()
*/
public LDAPException( String message ) {
super( message );
}
/**
* Constructs a default exception with a result code and
* a specified string of additional information. This string
* appears if you call the <CODE>toString()</CODE> method.
* The result code that you set is accessible through the
* <CODE>getLDAPResultCode()</CODE> method.
* <P>
*
* @param message the additional error information to specify
* @param resultCode the result code returned from the
* operation that caused this exception
* @see netscape.ldap.LDAPException#toString()
* @see netscape.ldap.LDAPException#getLDAPResultCode()
*/
public LDAPException( String message, int resultCode ) {
super( message );
this.resultCode = resultCode;
}
/**
* Constructs a default exception with a result code, a specified
* string of additional information, and a string containing
* information passed back from the server.
* <P>
*
* After you construct the <CODE>LDAPException</CODE> object,
* the result code and messages will be accessible through the
* following ways:
* <P>
* <UL>
* <LI>The first string of additional information appears if you
* call the <CODE>toString()</CODE> method. <P>
* <LI>The result code that you set is accessible through the
* <CODE>getLDAPResultCode()</CODE> method. <P>
* <LI>The string of server error information that you set
* is accessible through the <CODE>getLDAPErrorMessage</CODE>
* method. <P>
* </UL>
* <P>
*
* Use this form of the constructor
* for higher-level LDAP operational errors.
* @param message the additional error information to specify
* @param resultCode the result code returned from the
* operation that caused this exception
* @param serverErrorMessage error message specifying additional
* information returned from the server
* @see netscape.ldap.LDAPException#toString()
* @see netscape.ldap.LDAPException#getLDAPResultCode()
* @see netscape.ldap.LDAPException#getLDAPErrorMessage()
*/
public LDAPException( String message, int resultCode,
String serverErrorMessage ) {
super( message );
this.resultCode = resultCode;
this.errorMessage = serverErrorMessage;
}
/**
* Constructs a default exception with a result code, a specified
* string of additional information, a string containing
* information passed back from the server, and the DN of the
* closest matching entry, if the exception was thrown because
* an entry could not be found (for example, if <CODE>cn=Babs Jensen,
* ou=People, c=Airius.com</CODE> could not be found but
* <CODE>ou=People, c=Airius.com</CODE> is a valid directory entry,
* the &quot;matched DN&quot; is <CODE>ou=People, c=Airius.com</CODE>.
* <P>
*
* After you construct the <CODE>LDAPException</CODE> object,
* the result code and messages will be accessible through the
* following ways:
* <P>
* <UL>
* <LI>This string of additional information appears if you
* call the <CODE>toString()</CODE> method. <P>
* <LI>The result code that you set is accessible through the
* <CODE>getLDAPResultCode()</CODE> method. <P>
* <LI>The string of server error information that you set
* is accessible through the <CODE>getLDAPErrorMessage</CODE>
* method. <P>
* <LI>The matched DN that you set is accessible through the
* <CODE>getMatchedDN</CODE> method.<P>
* </UL>
* <P>
*
* This form is used for higher-level LDAP operational errors.
* @param message the additional error information
* @param resultCode the result code returned
* @param serverErrorMessage error message specifying additional information
* returned from the server
* @param matchedDN maximal subset of a specified DN which could be
* matched by the server
* @see netscape.ldap.LDAPException#toString()
* @see netscape.ldap.LDAPException#getLDAPResultCode()
* @see netscape.ldap.LDAPException#getLDAPErrorMessage()
* @see netscape.ldap.LDAPException#getMatchedDN()
*/
public LDAPException( String message, int resultCode,
String serverErrorMessage, String matchedDN ) {
super( message );
this.resultCode = resultCode;
this.errorMessage = serverErrorMessage;
this.matchedDN = matchedDN;
}
/**
* Returns the result code from the last error that occurred.
* This result code is defined as a public final static int member
* of this class. Note that this value is not always valid.
* -1 indicates that the result code is invalid.
* @return the LDAP result code of the last operation.
*/
public int getLDAPResultCode () {
return resultCode;
}
/**
* Returns the error message from the last error, if this message
* is available (that is, if this message was set). If the message
* was not set, this method returns <CODE>null</CODE>.
* <P>
*
* Note that this message is rarely set. (In order to set this message,
* the code constructing this exception must have called the constructor
* <CODE>LDAPException(String, int, String)</CODE>. The last argument,
* which is additional error information returned from the server,
* is the string returned by <CODE>getLDAPErrorMessage</CODE>.
* <P>
*
* In most cases, if you want information about
* the error generated, you should call the <CODE>toString()</CODE>
* method instead.
* <P>
*
* @return the error message of the last error (or <CODE>null</CODE>
* if no message was set).
* @see netscape.ldap.LDAPException#toString()
*/
public String getLDAPErrorMessage () {
return errorMessage;
}
/**
* Returns the maximal subset of a DN which could be matched by the
* server, if the server returned one of the following errors:
* <UL>
* <LI><CODE>NO_SUCH_OBJECT</CODE>
* <LI><CODE>ALIAS_PROBLEM</CODE>
* <LI><CODE>INVALID_DN_SYNTAX</CODE>
* <LI><CODE>ALIAS_DEREFERENCING_PROBLEM</CODE>
* </UL>
* </PRE>
* For example, if the DN <CODE>cn=Babs Jensen, o=People, c=Airius.com</CODE>
* could not be found by the DN <CODE>o=People, c=Airius.com</CODE>
* could be found, the matched DN is
* <CODE>o=People, c=Airius.com</CODE>.
* <P>
*
* If the exception does not specify a matching DN,
* this method returns <CODE>null</CODE>.
* @return the maximal subset of a DN which could be matched,
* or <CODE>null</CODE> if the error is not one of the above.
*/
public String getMatchedDN () {
return matchedDN;
}
/**
* Gets the string representation of the exception, which
* includes the result code, the message sent back from
* the LDAP server, the portion of the DN that the server
* could find in the directory (if applicable), and the
* error message corresponding to this result code.
* <P>
*
* For example:
*
* <PRE>netscape.ldap.LDAPException: error result (32); server error message; matchedDN = ou=people,o=airius.com; No such object</PRE>
*
* In this example, <CODE>error result</CODE> is the string of
* additional information specified in the exception, <CODE>32</CODE> is
* the result code, <CODE>server error message</CODE> is the additional
* information from the server specified in the exception, the
* matched DN is <CODE>ou=people,o=airius.com</CODE>, and the error message
* corresponding to the result code <CODE>32</CODE> is <CODE>No such
* object</CODE>.
* <P>
*
* The error message corresponding to the error code can also be
* retrieved by using the <CODE>errorCodeToString</CODE> method.
* Note that this method can generate error messages specific to
* a current locale.
* <P>
*
* @return string representation of exception.
* @see netscape.ldap.LDAPException#errorCodeToString(int)
*/
public String toString() {
String str = super.toString() + " (" + resultCode + ")" ;
if ( (errorMessage != null) && (errorMessage.length() > 0) )
str += "; " + errorMessage;
if ( (matchedDN != null) && (matchedDN.length() > 0) )
str += "; matchedDN = " + matchedDN;
String errorStr = null;
if (((errorStr = errorCodeToString(m_locale)) != null) &&
(errorStr.length() > 0))
str += "; " + errorStr;
return str;
}
/**
* Returns the error message describing the error code (for this
* exception). The error message is specific to the default locale
* for this system. (The LDAP Java classes determine the default
* locale by calling the <CODE>java.util.Locale.getDefault</CODE>
* method and retrieve the error messages from the following file:
* <PRE>netscape/ldap/error/ErrorCodes_<I>locale_name</I>.props</PRE>
* where <I>locale_name</I> is the language and country (concatenated
* and delimited by an underscore) of the default locale. For example:
* <PRE>netscape/ldap/error/ErrorCodes_en_US.props</PRE>
*
* @return the error message describing the error code for this
* exception in the default locale.
*/
public String errorCodeToString() {
return errorCodeToString(resultCode, m_locale);
}
/**
* Returns the error message describing the error code for this
* exception. The error message for the specified locale is retrieved
* from the following file:
* <PRE>netscape/ldap/error/ErrorCodes_<I>locale_name</I>.props</PRE>
* where <I>locale_name</I> is the language and country (concatenated
* and delimited by an underscore) of the default locale. For example:
* <PRE>netscape/ldap/error/ErrorCodes_en_US.props</PRE>
*
* @param l the <CODE>java.util.Locale</CODE> object representing the
* locale of the error message to retrieve
* @return the error message describing the current error code
* in the specified locale.
*/
public String errorCodeToString(Locale l) {
return errorCodeToString(resultCode, l);
}
/**
* Returns the error message describing the specified error code.
* The error message is specific to the default locale
* for this system. (The LDAP Java classes determine the default
* locale by calling the <CODE>java.util.Locale.getDefault</CODE>
* method and retrieve the error messages from the following file:
* <PRE>netscape/ldap/error/ErrorCodes_<I>locale_name</I>.props</PRE>
* where <I>locale_name</I> is the language and country (concatenated
* and delimited by an underscore) of the default locale. For example:
* <PRE>netscape/ldap/error/ErrorCodes_en_US.props</PRE>
*
* @param code the error code for which to get the
* corresponding error message
* @return error message describing the specified error code for
* the default locale.
*/
public static String errorCodeToString(int code) {
return errorCodeToString(code, Locale.getDefault());
}
/**
* Returns the error message describing the specified error code.
* The error message for the specified locale is retrieved from
* the following file:
* <PRE>netscape/ldap/error/ErrorCodes_<I>locale_name</I>.props</PRE>
* where <I>locale_name</I> is the language and country (concatenated
* and delimited by an underscore) of the default locale. For example:
* <PRE>netscape/ldap/error/ErrorCodes_en_US.props</PRE>
*
* @param code the error code for which to get the
* corresponding error
* @param locale the <CODE>java.util.Locale</CODE> object representing the
* locale of the error message that you want to retrieve
* @return error message describing the specified error code for
* the specified locale.
*/
public synchronized static String errorCodeToString(int code, Locale locale) {
try {
String localeStr = locale.toString();
PropertyResourceBundle p =
(PropertyResourceBundle)cacheResource.get(localeStr);
if (p == null) {
p = LDAPResourceBundle.getBundle(baseName);
if (p != null)
cacheResource.put(localeStr, p);
}
if (p != null) {
return (String)p.handleGetObject(Integer.toString(code));
}
} catch (IOException e) {
System.out.println("Cannot open resource file for LDAPException "+
baseName);
}
return null;
}
}

View File

@@ -0,0 +1,158 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
/**
* Version 3 of the LDAP protocol include the means to define additional
* operations (&quot;extended operations&quot;) beyond the standard LDAP
* operations. An LDAP v3 client can send an extended operation request,
* identifying the operation by its unique object ID (OID). The server
* receives the request and if OID corresponds to an operation supported
* by the server, the server procoess the request and sends an extended
* operation response back to the client.
* <P>
*
* Objects of this class can be used to represent extended operation
* requests (sent by your client) or extended operation responses
* (returned by an LDAP v3 server).
* <P>
*
* To determine which extended operations are supported by a server,
* you need to search for the root DSE (DSA-specific entry, where DSA is
* another term for &quot;LDAP server&quot;) and find the values of the
* <CODE>supportedExtension</CODE> attribute. This attribute contains the
* object IDs (OIDs) of the extended operations supported by this server.
* <P>
*
* The following section of code demonstrates how to get the list
* of the extended operations supported by an LDAP server.
* <P>
*
* <PRE>
* public static void main( String[] args )
* {
* LDAPConnection ld = new LDAPConnection();
* try {
* String MY_HOST = "localhost";
* int MY_PORT = 389;
* ld.connect( MY_HOST, MY_PORT );
* try {
* ld.authenticate( 3, "cn=Directory Manager", "23skidoo" );
* } catch( LDAPException e ) {
* System.out.println( "LDAP server does not support v3." );
* ld.disconnect();
* System.exit(1);
* }
*
* String MY_FILT = "(objectclass=*)";
* String MY_BASE = "";
* String getAttrs[] = { "supportedExtension" };
* LDAPSearchResults res = ld.search( MY_BASE,
* LDAPConnection.SCOPE_BASE, MY_FILT, getAttrs, false );
*
* while ( res.hasMoreElements() ) {
* LDAPEntry findEntry = (LDAPEntry)res.nextElement();
* LDAPAttributeSet findAttrs = findEntry.getAttributeSet();
* Enumeration enumAttrs = findAttrs.getAttributes();
*
* while ( enumAttrs.hasMoreElements() ) {
* LDAPAttribute anAttr = (LDAPAttribute)enumAttrs.nextElement();
* String attrName = anAttr.getName();
* System.out.println( attrName );
* Enumeration enumVals = anAttr.getStringValues();
*
* while ( enumVals.hasMoreElements() ) {
* String aVal = ( String )enumVals.nextElement();
* System.out.println( "\t" + aVal );
* }
* }
* }
* }
* catch( LDAPException e ) {
* System.out.println( "Error: " + e.toString() );
* }
* try {
* ld.disconnect();
* }
* catch( LDAPException e ) {
* System.exit(1);
* }
* System.exit(0);
* }
* </PRE>
* <P>
*
* If you compile and run this example against an LDAP server that
* supports v3 of the protocol, you might receive the following results:
* <P>
*
* <PRE>
* supportedextension
* 1.2.3.4
* </PRE>
* <P>
*
* For more information on LDAP controls, see the Internet-Draft on
* the LDAP v3 protocol. (Note that this internet draft is still a
* work in progress. You can find the latest draft at the <A
* HREF="http://www.ietf.cnri.reston.va.us/html.charters/asid-charter.html"
* TARGET="_blank">ASID home page</A>.
* <P>
*
* @version 1.0
* @see netscape.ldap.LDAPConnection#extendedOperation(netscape.ldap.LDAPExtendedOperation)
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
*
*/
public class LDAPExtendedOperation implements java.io.Serializable {
static final long serialVersionUID = 4010382829133611945L;
/**
* Construct an object
* @param oid identifier for the particular operation
* @param vals operation-specific data
*/
public LDAPExtendedOperation( String oid, byte[] vals ) {
m_oid = oid;
m_vals = vals;
}
/**
* Get the identifier for this operation.
* @return oid identifier for the particular operation.
*/
public String getID() {
return m_oid;
}
/**
* Get the data for this operation.
* @return vals operation-specific data.
*/
public byte[] getValue() {
return m_vals;
}
private String m_oid;
private byte[] m_vals;
}

View File

@@ -0,0 +1,76 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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
implements java.io.Serializable {
static final long serialVersionUID = -3813049515964705320L;
/**
* Constructor
*
* @param msgid message identifier
* @param rsp extended operation response
* @paarm controls array of controls or null
*/
LDAPExtendedResponse(int msgid, JDAPExtendedResponse rsp, LDAPControl controls[]) {
super(msgid, rsp, controls);
}
/**
* Returns the OID of the response.
*
* @return the response OID.
*/
public String getID() {
JDAPExtendedResponse result = (JDAPExtendedResponse)getProtocolOp();
return result.getID();
}
/**
* Returns the OID of the response.
*
* @return the response OID.
* @deprecated Use <CODE>LDAPExtendedResponse.getID()</CODE>
*/
public String getOID() {
return 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,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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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 {
static final long serialVersionUID = 5267455101797397456L;
/**
* 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

@@ -0,0 +1,380 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* The definition of a matching rule in the schema.
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* Attribute Syntax Definitions</A> covers the types of information
* that need to be specified in the definition of a matching rule.
* According to the RFC, the description of a matching rule can
* include the following information:
* <P>
*
* <UL>
* <LI>an OID identifying the matching rule
* <LI>a name identifying the matching rule
* <LI>a description of the matching rule
* <LI>the syntax of the matching rule
* </UL>
* <P>
*
* The <CODE>LDAPMatchingRuleSchema</CODE> class also specifies
* the matching rule "use description", which describes the
* attributes which can be used with the matching rule.
* <P>
*
* When you construct an <CODE>LDAPMatchingRuleSchema</CODE> object, you can
* 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
* returns schema information as an object with attribute values in this
* 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>. Custom qualifiers are
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
* from <CODE>LDAPSchemaElement</CODE>.
* <P>
*
* 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>
* <PRE>
* 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>
* <P>
* <CODE>LDAPMatchingRuleSchema</CODE> abstracts away from the two types and
* manages their relationships transparently.
*
* @version 1.0
* @see netscape.ldap.LDAPSchemaElement
**/
public class LDAPMatchingRuleSchema extends LDAPAttributeSchema {
static final long serialVersionUID = 6466155218986944131L;
/**
* Constructs a matching rule definition, using the specified
* information.
* @param name name of the matching rule
* @param oid object identifier (OID) of the matching rule
* in dotted-decimal format (for example, "1.2.3.4")
* @param description description of the matching rule
* @param attributes array of the OIDs of the attributes for which
* the matching rule is applicable
* @param syntax syntax of this matching rule. The value of this
* argument can be one of the following:
* <UL>
* <LI><CODE>cis</CODE> (case-insensitive string)
* <LI><CODE>ces</CODE> (case-exact string)
* <LI><CODE>binary</CODE> (binary data)
* <LI><CODE>int</CODE> (integer)
* <LI><CODE>telephone</CODE> (telephone number -- identical to cis,
* but blanks and dashes are ignored during comparisons)
* <LI><CODE>dn</CODE> (distinguished name)
* </UL>
*/
public LDAPMatchingRuleSchema( String name, String oid,
String description,
String[] attributes, int syntax ) {
this( name, oid, description, attributes, cisString );
syntaxElement.syntax = syntax;
String syntaxType = syntaxElement.internalSyntaxToString( syntax );
if ( syntaxType != null ) {
syntaxElement.syntaxString = syntaxType;
}
setQualifier( SYNTAX, syntaxElement.syntaxString );
}
/**
* Constructs a matching rule definition, using the specified
* information.
* @param name name of the matching rule.
* @param oid object identifier (OID) of the matching rule
* in dotted-decimal format (for example, "1.2.3.4").
* @param description description of the matching rule.
* @param attributes array of the OIDs of the attributes for which
* the matching rule is applicable.
* @param syntaxString syntax of this matching rule in dotted-decimal
* format
*/
public LDAPMatchingRuleSchema( String name, String oid,
String description,
String[] attributes,
String syntaxString ) {
this( name, oid, description, attributes, syntaxString, null );
}
/**
* Constructs a matching rule definition, using the specified
* information.
* @param name name of the matching rule.
* @param oid object identifier (OID) of the matching rule
* in dotted-decimal format (for example, "1.2.3.4").
* @param description description of the matching rule.
* @param attributes array of the OIDs of the attributes for which
* the matching rule is applicable.
* @param syntaxString syntax of this matching rule in dotted-decimal
* format
* @param aliases names which are to be considered aliases for this
* matching rule; <CODE>null</CODE> if there are no aliases
*/
public LDAPMatchingRuleSchema( String name, String oid,
String description,
String[] attributes,
String syntaxString,
String[] aliases ) {
if ( (oid == null) || (oid.trim().length() < 1) ) {
throw new IllegalArgumentException( "OID required" );
}
this.name = name;
this.oid = oid;
this.description = description;
attrName = "matchingrules";
syntaxElement.syntax = syntaxElement.syntaxCheck( syntaxString );
syntaxElement.syntaxString = syntaxString;
setQualifier( SYNTAX, syntaxElement.syntaxString );
this.attributes = new String[attributes.length];
for( int i = 0; i < attributes.length; i++ ) {
this.attributes[i] = attributes[i];
}
if ( (aliases != null) && (aliases.length > 0) ) {
this.aliases = aliases;
}
}
/**
* Constructs a matching rule definition based on descriptions in
* the MatchingRuleDescription format and MatchingRuleUseDescription
* format. For information on this format,
* (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
* 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.
* <P>
*
* @param raw definition of the matching rule in the
* MatchingRuleDescription format
* @param use definition of the use of the matching rule in the
* MatchingRuleUseDescription format
*/
public LDAPMatchingRuleSchema( String raw, String use ) {
attrName = "matchingrules";
if ( raw != null ) {
parseValue( raw );
}
if ( use != null ) {
parseValue( use );
}
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 ) {
syntaxElement.syntaxString = val;
syntaxElement.syntax = syntaxElement.syntaxCheck( val );
}
}
/**
* Gets the list of the OIDs of the attribute types which can be used
* with the matching rule.
* @return array of the OIDs of the attribute types which can be used
* with the matching rule.
*/
public String[] getAttributes() {
return attributes;
}
/**
* 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();
if ( syntaxElement.syntaxString != null ) {
s += "SYNTAX ";
if ( quotingBug ) {
s += '\'';
}
s += syntaxElement.syntaxString;
if ( quotingBug ) {
s += '\'';
}
s += ' ';
}
String val = getCustomValues();
if ( val.length() > 0 ) {
s += val + ' ';
}
s += ')';
return s;
}
/**
* Gets the matching rule definition in the string representation
* of the MatchingRuleDescription 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 these formats).
* 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 "matchingrules" and "matchingruleuse". The
* values of these attributes are matching rule description and
* matching rule use description in these formats.)
* <P>
*
* @return a string in a format that can be used as the value of
* the <CODE>matchingrule</CODE> attribute (which describes
* a matching rule in the schema) of a <CODE>subschema</CODE> object
*/
public String getValue() {
return getValue( false );
}
/**
* Gets the matching rule use definition in the string representation
* of the MatchingRuleUseDescription 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 these formats).
* 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 "matchingrules" and "matchingruleuse". The
* values of these attributes are matching rule description and
* matching rule use description in these formats.)
* <P>
*
* @return a string in a format that can be used as the value of
* the <CODE>matchingruleuse</CODE> attribute (which describes the use of
* a matching rule in the schema) of a <CODE>subschema</CODE> object
*/
public String getUseValue() {
String s = getValuePrefix();
if ( (attributes != null) && (attributes.length > 0) ) {
s += "APPLIES ( ";
for( int i = 0; i < attributes.length; i++ ) {
if ( i > 0 )
s += " $ ";
s += attributes[i];
}
s += " ) ";
}
s += ')';
return s;
}
/**
* Adds, removes or modifies the definition from a Directory.
* @param ld an open connection to a Directory Server. Typically the
* connection must have been authenticated to add a definition.
* @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, String dn )
throws LDAPException {
LDAPAttribute[] attrs = new LDAPAttribute[2];
attrs[0] = new LDAPAttribute( "matchingRules",
getValue() );
/* Must update the matchingRuleUse value as well */
attrs[1] = new LDAPAttribute( "matchingRuleUse",
getUseValue() );
update( ld, op, attrs, dn );
}
/**
* Gets the definition of the matching rule in a user friendly format.
* This is the format that the matching rule definition uses when
* you print the matching rule or the schema.
* @return definition of the matching rule in a user friendly format.
*/
public String toString() {
String s = "Name: " + name + "; OID: " + oid + "; Type: ";
s += syntaxElement.syntaxToString();
s += "; Description: " + description;
if ( attributes != null ) {
s += "; Applies to: ";
for( int i = 0; i < attributes.length; i++ ) {
if ( i > 0 )
s += ", ";
s += attributes[i];
}
}
s += getQualifierString( EXPLICIT );
s += getAliasString();
return s;
}
// Qualifiers tracked explicitly
static final String[] EXPLICIT = { OBSOLETE,
SYNTAX };
private String[] attributes = null;
}

View File

@@ -0,0 +1,212 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* The definition of a matching rule use in the schema.
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* Attribute Syntax Definitions</A> covers the types of information
* that need to be specified in the definition of a matching rule use.
* According to the RFC, the description of a matching rule use can
* include the following information:
* <P>
*
* <UL>
* <LI>an OID identifying the matching rule
* <LI>a name identifying the matching rule use
* <LI>a description of the matching rule use
* <LI>a list of attributes the matching rule applies to
* </UL>
* <P>
*
* When you construct an <CODE>LDAPMatchingRuleUseSchema</CODE> object, you can
* specify these types of information as arguments to the constructor or
* in the MatchingRuleUseDescription format specified in RFC 2252.
* When an LDAP client searches an LDAP server for the schema, the server
* returns schema information as an object with values in this
* format.
* <P>
*
* You can get the name, OID, and description of this matching rule use
* definition by using the <CODE>getName</CODE>, <CODE>getOID</CODE>, and
* <CODE>getDescription</CODE> methods inherited from the abstract class
* <CODE>LDAPSchemaElement</CODE>. Custom qualifiers are
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
* from <CODE>LDAPSchemaElement</CODE>.
* <P>
*
* 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 MatchingRuleUseDescription follows:
* <P>
* <PRE>
* 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>
* <P>
*
* @version 1.0
* @see netscape.ldap.LDAPSchemaElement
* @see netscape.ldap.LDAPMatchingRuleSchema
**/
public class LDAPMatchingRuleUseSchema extends LDAPAttributeSchema {
/**
* Constructs a matching rule use definition, using the specified
* information.
* @param name name of the matching rule
* @param oid object identifier (OID) of the matching rule
* in dotted-decimal format (for example, "1.2.3.4")
* @param description description of the matching rule
* @param attributes array of the OIDs of the attributes for which
* the matching rule is applicable
*/
public LDAPMatchingRuleUseSchema( String name, String oid,
String description,
String[] attributes ) {
if ( (oid == null) || (oid.trim().length() < 1) ) {
throw new IllegalArgumentException( "OID required" );
}
this.name = name;
this.oid = oid;
this.description = description;
attrName = "matchingruleuse";
this.attributes = new String[attributes.length];
for( int i = 0; i < attributes.length; i++ ) {
this.attributes[i] = attributes[i];
}
}
/**
* Constructs a matching rule use definition based on descriptions in
* the MatchingRuleUseDescription format. For information on this format,
* (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
* 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.
* <P>
*
* @param use definition of the use of the matching rule in the
* MatchingRuleUseDescription format
*/
public LDAPMatchingRuleUseSchema( String use ) {
attrName = "matchingruleuse";
parseValue( use );
Vector v = (Vector)properties.get( "APPLIES" );
if ( v != null ) {
attributes = new String[v.size()];
v.copyInto( attributes );
v.removeAllElements();
}
}
/**
* Gets the list of the OIDs of the attribute types which can be used
* with the matching rule.
* @return array of the OIDs of the attribute types which can be used
* with the matching rule.
*/
public String[] getApplicableAttributes() {
return attributes;
}
/**
* Gets the matching rule use definition in the string representation
* of the MatchingRuleUseDescription 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 these formats).
* 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 "matchingrules" and "matchingruleuse". The
* values of these attributes are matching rule description and
* matching rule use description in these formats.)
* <P>
*
* @return a string in a format that can be used as the value of
* the <CODE>matchingruleuse</CODE> attribute (which describes the use of
* a matching rule in the schema) of a <CODE>subschema</CODE> object
*/
public String getValue() {
String s = getValuePrefix();
if ( (attributes != null) && (attributes.length > 0) ) {
s += "APPLIES ( ";
for( int i = 0; i < attributes.length; i++ ) {
if ( i > 0 )
s += " $ ";
s += attributes[i];
}
s += " ) ";
}
s += ')';
return s;
}
/**
* Gets the definition of the matching rule use in a user friendly format.
* This is the format that the matching rule use definition uses when
* you print the matching rule or the schema.
* @return definition of the matching rule in a user friendly format.
*/
public String toString() {
String s = "Name: " + name + "; OID: " + oid;
s += "; Description: " + description;
if ( attributes != null ) {
s += "; Applies to: ";
for( int i = 0; i < attributes.length; i++ ) {
if ( i > 0 )
s += ", ";
s += attributes[i];
}
}
s += getQualifierString( EXPLICIT );
return s;
}
// Qualifiers tracked explicitly
static final String[] EXPLICIT = { OBSOLETE };
private String[] attributes = null;
}

View File

@@ -0,0 +1,286 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import netscape.ldap.client.opers.*;
import netscape.ldap.ber.stream.*;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
/**
* 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 ::= SEQUENCE {
* messageID MessageID,
* protocolOp CHOICE {
* bindRequest BindRequest,
* ...
* }
* controls [0] Controls OPTIONAL
* }
* </pre>
*
* @version 1.0
*/
public class LDAPMessage implements java.io.Serializable {
static final long serialVersionUID = -1364094245850026720L;
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
*/
private int m_msgid;
private JDAPProtocolOp m_protocolOp = null;
private LDAPControl m_controls[] = null;
// Time Stemp format Hour(0-23):Minute:Second.Milliseconds used for trace msgs
static SimpleDateFormat m_timeFormat = new SimpleDateFormat("HH:mm:ss.SSS");
/**
* Constructs a ldap message.
* @param msgid message identifier
* @param op operation protocol
*/
LDAPMessage(int msgid, JDAPProtocolOp op) {
m_msgid = msgid;
m_protocolOp = op;
}
LDAPMessage(int msgid, JDAPProtocolOp op, LDAPControl controls[]) {
m_msgid = msgid;
m_protocolOp = op;
m_controls = controls; /* LDAPv3 additions */
}
/**
* 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
*/
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);
l_msgid = msgid.getValue();
BERElement protocolOp = (BERElement)seq.elementAt(1);
if (protocolOp.getType() != BERElement.TAG) {
throw new IOException("TAG in protocol operation is expected");
}
BERTag tag = (BERTag)protocolOp;
switch (tag.getTag()&0x1f) {
case JDAPProtocolOp.BIND_RESPONSE:
l_protocolOp = new JDAPBindResponse(protocolOp);
break;
case JDAPProtocolOp.SEARCH_RESPONSE:
l_protocolOp = new JDAPSearchResponse(protocolOp);
break;
/*
* If doing search without bind,
* x500.arc.nasa.gov returns tag SEARCH_REQUEST tag
* in SEARCH_RESULT.
*/
case JDAPProtocolOp.SEARCH_REQUEST:
case JDAPProtocolOp.SEARCH_RESULT:
l_protocolOp = new JDAPSearchResult(protocolOp);
break;
case JDAPProtocolOp.MODIFY_RESPONSE:
l_protocolOp = new JDAPModifyResponse(protocolOp);
break;
case JDAPProtocolOp.ADD_RESPONSE:
l_protocolOp = new JDAPAddResponse(protocolOp);
break;
case JDAPProtocolOp.DEL_RESPONSE:
l_protocolOp = new JDAPDeleteResponse(protocolOp);
break;
case JDAPProtocolOp.MODIFY_RDN_RESPONSE:
l_protocolOp = new JDAPModifyRDNResponse(protocolOp);
break;
case JDAPProtocolOp.COMPARE_RESPONSE:
l_protocolOp = new JDAPCompareResponse(protocolOp);
break;
case JDAPProtocolOp.SEARCH_RESULT_REFERENCE:
l_protocolOp = new JDAPSearchResultReference(protocolOp);
break;
case JDAPProtocolOp.EXTENDED_RESPONSE:
l_protocolOp = new JDAPExtendedResponse(protocolOp);
break;
default:
throw new IOException("Unknown protocol operation");
}
/* parse control */
if (seq.size() >= 3) {
tag = (BERTag)seq.elementAt(2);
if ( tag.getTag() == (BERTag.CONSTRUCTED|BERTag.CONTEXT|0) ) {
BERSequence controls = (BERSequence)tag.getValue();
l_controls = new LDAPControl[controls.size()];
for (int i = 0; i < controls.size(); 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);
}
}
/**
* Returns the message identifer.
* @return message identifer.
*/
public int getMessageID(){
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.
*/
JDAPProtocolOp getProtocolOp() {
return m_protocolOp;
}
/**
* Retrieves list of controls.
* @return controls.
*/
public LDAPControl[] getControls() {
return m_controls;
}
/**
* Writes the ber encoding to stream.
* @param s output stream
*/
void write(OutputStream s) throws IOException {
BERSequence seq = new BERSequence();
BERInteger i = new BERInteger(m_msgid);
seq.addElement(i);
BERElement e = m_protocolOp.getBERElement();
if (e == null) {
throw new IOException("Bad BER element");
}
seq.addElement(e);
if (m_controls != null) { /* LDAPv3 additions */
BERSequence c = new BERSequence();
for (int j = 0; j < m_controls.length; j++) {
c.addElement(m_controls[j].getBERElement());
}
BERTag t = new BERTag(BERTag.CONTEXT|BERTag.CONSTRUCTED|0, c, true);
seq.addElement(t);
}
seq.write(s);
}
/**
* Returns string representation of an LDAP message.
* @return LDAP message.
*/
public String toString() {
StringBuffer sb = new StringBuffer("[LDAPMessage] ");
sb.append(m_msgid);
sb.append(" ");
sb.append(m_protocolOp.toString());
for (int i =0; m_controls != null && i < m_controls.length; i++) {
sb.append(" ");
sb.append(m_controls[i].toString());
}
return sb.toString();
}
/**
* Returns string representation of a ldap message with
* the time stamp. Used for message trace
* @return ldap message with the time stamp
*/
String toTraceString() {
String timeStamp = m_timeFormat.format(new Date());
StringBuffer sb = new StringBuffer(timeStamp);
sb.append(" ");
sb.append(m_msgid);
sb.append(" ");
sb.append(m_protocolOp.toString());
for (int i =0; m_controls != null && i < m_controls.length; i++) {
sb.append(" ");
sb.append(m_controls[i].toString());
}
return sb.toString();
}
}

View File

@@ -0,0 +1,492 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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 implements java.io.Serializable {
static final long serialVersionUID = -7163312406176592277L;
/**
* Request entry encapsulates request parameters
*/
private static class RequestEntry {
int id;
LDAPConnection connection;
LDAPConnThread connThread;
long timeToComplete;
RequestEntry(int id, LDAPConnection connection,
LDAPConnThread connThread, int timeLimit) {
this.id= id;
this.connection = connection;
this.connThread = connThread;
this.timeToComplete = (timeLimit == 0) ?
Long.MAX_VALUE : (System.currentTimeMillis() + timeLimit);
}
}
/**
* 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;
// A flag whether there are time constrained requests
private boolean m_timeConstrained;
/**
* Constructor
* @param asynchOp a boolean flag that is true if 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 are 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) {
waitForMessage();
}
// 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.getMessageID());
}
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 are 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) {
waitForMessage();
}
// 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
waitForMessage();
}
}
/**
* Wait for a response message. Process interrupts and honor
* time limit if set for any request
*/
synchronized private void waitForMessage () throws LDAPException{
if (!m_timeConstrained) {
try {
wait ();
return;
} catch (InterruptedException e) {
throw new LDAPInterruptedException("Interrupted LDAP operation");
}
}
/**
* Perform time constrained wait
*/
long minTimeToComplete = Long.MAX_VALUE;
long now = System.currentTimeMillis();
for (int i=0; i < m_requestList.size(); i++) {
RequestEntry entry = (RequestEntry)m_requestList.elementAt(i);
// time limit exceeded ?
if (entry.timeToComplete <= now) {
entry.connection.abandon(entry.id);
throw new LDAPException("Time to complete operation exceeded",
LDAPException.LDAP_TIMEOUT);
}
if (entry.timeToComplete < minTimeToComplete) {
minTimeToComplete = entry.timeToComplete;
}
}
long timeLimit = (minTimeToComplete == Long.MAX_VALUE)?
0 :(minTimeToComplete - now);
try {
m_timeConstrained = (timeLimit != 0);
wait (timeLimit);
} 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.getMessageIDs(), 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.getMessageIDs().
* The proper way to handle this scenario is to create a separate listener
* for each new request, and after l.getMessageIDs() has been invoked,
* merge the
* new request with the existing one.
* @param mq2 message queue to merge 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
* @return 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);
// Mark conn as bound for asych bind operations
if (isAsynchOp() && msg.getType() == msg.BIND_RESPONSE) {
if (((LDAPResponse) msg).getResultCode() == 0) {
getConnection(msg.getMessageID()).markConnAsBound();
}
}
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.getMessageID() == 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();
m_timeConstrained = false;
}
/**
* Returns the connection associated with the specified request id
* @param 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
* @param 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 getMessageID() {
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[] getMessageIDs() {
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
* @param timeLimit the maximum number of milliseconds to wait for
* the request to complete
*/
synchronized void addRequest(int id, LDAPConnection connection,
LDAPConnThread connThread, int timeLimit) {
m_requestList.addElement(new RequestEntry(id, connection,
connThread, timeLimit));
if (timeLimit != 0) {
m_timeConstrained = true;
}
notifyAll();
}
/**
* 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 indicating 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 requests.
*/
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

@@ -0,0 +1,148 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import netscape.ldap.ber.stream.*;
/**
* Specifies changes to be made to the values of an attribute. The change is
* specified in terms of the following aspects:
* <P>
*
* <UL>
* <LI>the type of modification (add, replace, or delete the value of an attribute)
* <LI>the type of value being modified (string or binary)
* <LI>the name of the attribute being modified
* <LI>the actual value
* </UL>
* <P>
*
* After you specify a change to an attribute, you can execute the change
* by calling the <CODE>LDAPConnection.modify</CODE> method and specifying
* the DN of the entry that you want to modify.
* <P>
*
* @version 1.0
* @see netscape.ldap.LDAPConnection#modify(java.lang.String, netscape.ldap.LDAPModification)
*/
public class LDAPModification implements java.io.Serializable {
static final long serialVersionUID = 4836472112866826595L;
/**
* Specifies that a value should be added to an attribute.
*/
public static final int ADD = 0;
/**
* Specifies that a value should be removed from an attribute.
*/
public static final int DELETE = 1;
/**
* Specifies that a value should replace the existing value in an attribute.
*/
public static final int REPLACE = 2;
/**
* Internal variables
*/
private int operation;
private LDAPAttribute attribute;
/**
* Specifies a modification to be made to an attribute.
* @param op the type of modification to make. This can be one of the following:
* <P>
* <UL>
* <LI><CODE>LDAPModification.ADD</CODE> (the value should be added to the attribute)
* <LI><CODE>LDAPModification.DELETE</CODE> (the value should be removed from the attribute)
* <LI><CODE>LDAPModification.REPLACE</CODE> (the value should replace the existing value of the attribute)
* </UL><P>
* @param attr the attribute (possibly with values) to modify
* @see netscape.ldap.LDAPAttribute
*/
public LDAPModification( int op, LDAPAttribute attr ) {
operation = op;
attribute = attr;
}
/**
* Returns the type of modification specified by this object.
* @return one of the following types of modifications:
* <P>
* <UL>
* <LI><CODE>LDAPModification.ADD</CODE> (the value should be added to the attribute)
* <LI><CODE>LDAPModification.DELETE</CODE> (the value should be removed from the attribute)
* <LI><CODE>LDAPModification.REPLACE</CODE> (the value should replace the existing value of the attribute)
* </UL><P>
*/
public int getOp() {
return operation;
}
/**
* Returns the attribute (possibly with values) to be modified.
* @return the attribute to be modified.
* @see netscape.ldap.LDAPAttribute
*/
public LDAPAttribute getAttribute() {
return attribute;
}
/**
* Retrieves the BER (Basic Encoding Rules) representation
* of the current modification.
* @return BER representation of the modification.
*/
public BERElement getBERElement() {
BERSequence seq = new BERSequence();
seq.addElement(new BEREnumerated(operation));
seq.addElement(attribute.getBERElement());
return seq;
}
/**
* Retrieves the string representation of the current
* modification. For example:
*
* <PRE>
* LDAPModification: REPLACE, LDAPAttribute {type='mail', values='babs@ace.com'}
* LDAPModification: ADD, LDAPAttribute {type='description', values='This entry was modified with the modattrs program'}
* </PRE>
*
* @return string representation of the current modification.
*/
public String toString() {
String s = "LDAPModification: ";
if ( operation == ADD )
s += "ADD, ";
else if ( operation == DELETE )
s += "DELETE, ";
else if ( operation == REPLACE )
s += "REPLACE, ";
else
s += "INVALID OP, ";
s += attribute;
return s;
}
}

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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* Represents a set of modifications to be made to attributes in an entry.
* A set of modifications is made up of <CODE>LDAPModification</CODE> objects.
* <P>
*
* After you specify a change to an attribute, you can execute the change
* by calling the <CODE>LDAPConnection.modify</CODE> method and specifying
* the DN of the entry that you want to modify.
* <P>
*
* @version 1.0
* @see netscape.ldap.LDAPModification
* @see netscape.ldap.LDAPConnection#modify(java.lang.String, netscape.ldap.LDAPModificationSet)
*/
public class LDAPModificationSet implements java.io.Serializable {
static final long serialVersionUID = 4650238666753391214L;
private int current = 0;
private Vector modifications;
/**
* Constructs a new, empty set of modifications.
* You can add modifications to this set by calling the
* <CODE>LDAPModificationsSet.add</CODE> method.
*/
public LDAPModificationSet() {
modifications = new Vector();
current = 0;
}
/**
* Retrieves the number of <CODE>LDAPModification</CODE>
* objects in this set.
* @return the number of <CODE>LDAPModification</CODE>
* objects in this set.
*/
public int size () {
return modifications.size();
}
/**
* Retrieves a particular <CODE>LDAPModification</CODE> object at
* the position specified by the index.
* @param index position of the <CODE>LDAPModification</CODE>
* object that you want to retrieve.
* @return <CODE>LDAPModification</CODE> object representing
* a change to make to an attribute.
*/
public LDAPModification elementAt (int index) {
return (LDAPModification)modifications.elementAt(index);
}
/**
* Removes a particular <CODE>LDAPModification</CODE> object at
* the position specified by the index.
* @param index position of the <CODE>LDAPModification</CODE>
* object that you want to remove
*/
public void removeElementAt( int index ) {
modifications.removeElementAt(index);
}
/**
* Specifies another modification to be added to the set of modifications.
* @param op the type of modification to make. This can be one of the following:
* <P>
* <UL>
* <LI><CODE>LDAPModification.ADD</CODE> (the value should be added to the attribute)
* <LI><CODE>LDAPModification.DELETE</CODE> (the value should be removed from the attribute)
* <LI><CODE>LDAPModification.REPLACE</CODE> (the value should replace the existing value of the attribute)
* </UL><P>
* If you are working with a binary value (not a string value), you need to bitwise OR (|) the
* modification type with <CODE>LDAPModification.BVALUES</CODE>.
* <P>
*
* @param attr the attribute (possibly with values) to modify
*/
public synchronized void add( int op, LDAPAttribute attr ) {
LDAPModification mod = new LDAPModification( op, attr );
modifications.addElement( mod );
}
/**
* Removes the first attribute with the specified name in the set of modifications.
* @param name name of the attribute to remove
*/
public synchronized void remove( String name ) {
for( int i = 0; i < modifications.size(); i++ ) {
LDAPModification mod = (LDAPModification)modifications.elementAt( i );
LDAPAttribute attr = mod.getAttribute();
if ( name.equalsIgnoreCase( attr.getName() ) ) {
modifications.removeElementAt( i );
break;
}
}
}
/**
* Retrieves the string representation of the
* modification set.
*
* @return string representation of the modification set.
*/
public String toString() {
String s = "LDAPModificationSet: {";
for( int i = 0; i < modifications.size(); i++ ) {
s += (LDAPModification)modifications.elementAt(i);
if ( i < modifications.size()-1 ) {
s += ", ";
}
}
s += "}";
return s;
}
}

View File

@@ -0,0 +1,295 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* The definition of a name form in the schema.
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* Attribute Syntax Definitions</A> covers the types of information
* that need to be specified in the definition of a name form.
* According to the RFC, the description of a name form can
* include the following information:
* <P>
*
* <UL>
* <LI>an OID identifying the name form
* <LI>a name identifying the name form
* <LI>a description of the name form
* <LI>the structural object class of this name form
* <LI>the list of attribute types that are required in this name form
* <LI>the list of attribute types that are allowed (optional) in this
* name form
* </UL>
* <P>
*
* When you construct an <CODE>LDAPNameFormSchema</CODE> object,
* you can specify
* these types of information as arguments to the constructor or in the
* NameFormDescription format specified in RFC 2252.
* 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.
* <P>
*
* You can get the name, OID, and description of this name form
* definition by using the <CODE>getName</CODE>, <CODE>getOID</CODE>, and
* <CODE>getDescription</CODE> methods inherited from the abstract class
* <CODE>LDAPSchemaElement</CODE>. Optional and custom qualifiers are
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
* from <CODE>LDAPSchemaElement</CODE>.
* <P>
*
* To add or remove this name form 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 NameFormDescription as follows:
* <P>
* <PRE>
* NameFormDescription = "(" whsp
* numericoid whsp ; NameForm identifier
* [ "NAME" qdescrs ]
* [ "DESC" qdstring ]
* [ "OBSOLETE" whsp ]
* "OC" woid ; Structural ObjectClass
* [ "MUST" oids ] ; AttributeTypes
* [ "MAY" oids ] ; AttributeTypes
* whsp ")"
* </PRE>
*
* @version 1.0
* @see netscape.ldap.LDAPSchemaElement
**/
public class LDAPNameFormSchema extends LDAPSchemaElement {
static final long serialVersionUID = 1665316286199590403L;
/**
* Constructs a name form definition, using the specified
* information.
* @param name name of the name form
* @param oid object identifier (OID) of the name form
* in dotted-string format (for example, "1.2.3.4")
* @param description description of the name form
* @param obsolete <code>true</code> if the rule is obsolete
* @param objectClass the object to which this name form applies.
* This may either be specified by name or numeric oid.
* @param required array of names of attributes required
* in this name form
* @param optional array of names of optional attributes
* allowed in this name form
*/
public LDAPNameFormSchema( String name, String oid,
String description, boolean obsolete,
String objectClass,
String[] required, String[] optional ) {
super( name, oid, description, null );
attrName = "nameforms";
if ( obsolete ) {
setQualifier( OBSOLETE, "" );
}
this.objectClass = objectClass;
if ( required != null ) {
for( int i = 0; i < required.length; i++ ) {
must.addElement( required[i] );
}
}
if ( optional != null ) {
for( int i = 0; i < optional.length; i++ ) {
may.addElement( optional[i] );
}
}
}
/**
* Constructs a name form definition based on a description in
* the NameFormDescription format. For information on this format,
* (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
* 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 name form descriptions
* in this format.)
* <P>
*
* @param raw definition of the object in the NameFormDescription
* format
*/
public LDAPNameFormSchema( String raw ) {
attrName = "objectclasses";
parseValue( raw );
Object o = properties.get( "MAY" );
if ( o != null ) {
if ( o instanceof Vector ) {
may = (Vector)o;
} else {
may.addElement( o );
}
}
o = properties.get( "MUST" );
if ( o != null ) {
if ( o instanceof Vector ) {
must = (Vector)o;
} else {
must.addElement( o );
}
}
o = properties.get( "OC" );
if ( o != null ) {
objectClass = (String)o;
}
}
/**
* Gets the names of the required attributes for
* this name form.
* @return the names of the required attributes
* for this name form.
*/
public String[] getRequiredNamingAttributes() {
String[] vals = new String[must.size()];
must.copyInto( vals );
return vals;
}
/**
* Gets the names of optional attributes allowed
* in this name form.
* @return the names of optional attributes
* allowed in this name form.
*/
public String[] getOptionalNamingAttributes() {
String[] vals = new String[may.size()];
may.copyInto( vals );
return vals;
}
/**
* Returns the name of the object class that this name form applies to.
*
* @return the name of the object class that this name form applies to.
*/
public String getObjectClass() {
return objectClass;
}
/**
* Prepares 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 for submission to an LDAP server.
*/
String getValue( boolean quotingBug ) {
String s = getValuePrefix();
String val = getOptionalValues( NOVALS );
if ( val.length() > 0 ) {
s += val + ' ';
}
s += "OC " + objectClass + ' ';
if ( must.size() > 0 ) {
s += "MUST " + vectorToList( must );
s += ' ';
}
if ( may.size() > 0 ) {
s += "MAY " + vectorToList( may );
s += ' ';
}
val = getCustomValues();
if ( val.length() > 0 ) {
s += val + ' ';
}
s += ')';
return s;
}
/**
* Gets the definition of the name form in a user friendly format.
* This is the format that the name form definition uses when
* you print the name form or the schema.
* @return definition of the name form in a user friendly format.
*/
public String toString() {
String s = "Name: " + name + "; OID: " + oid;
s += "; Description: " + description + "; Required: ";
String[] vals = getRequiredNamingAttributes();
for( int i = 0; i < vals.length; i++ ) {
if ( i > 0 )
s += ", ";
s += vals[i];
}
s += "; Optional: ";
vals = getOptionalNamingAttributes();
for( int i = 0; i < vals.length; i++ ) {
if ( i > 0 )
s += ", ";
s += vals[i];
}
if ( isObsolete() ) {
s += "; OBSOLETE";
}
s += getQualifierString( IGNOREVALS );
return s;
}
/**
* Creates a list within parentheses, with $ as delimiter
*
* @param vals values for list
* @return a String with a list of values.
*/
protected String vectorToList( Vector vals ) {
String val = "( ";
for( int i = 0; i < vals.size(); i++ ) {
val += (String)vals.elementAt(i) + ' ';
if ( i < (vals.size() - 1) ) {
val += "$ ";
}
}
val += ')';
return val;
}
private Vector must = new Vector();
private Vector may = new Vector();
private String objectClass = null;
// Qualifiers known to not have values; prepare a Hashtable
static final String[] NOVALS = { "OBSOLETE" };
static {
for( int i = 0; i < NOVALS.length; i++ ) {
novalsTable.put( NOVALS[i], NOVALS[i] );
}
}
// Qualifiers which we output explicitly in toString()
static final String[] IGNOREVALS = { "MUST", "MAY",
"OBJECTCLASS", "OBSOLETE"};
}

View File

@@ -0,0 +1,432 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* The definition of an object class in the schema.
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* Attribute Syntax Definitions</A> covers the types of information
* that need to be specified in the definition of an object class.
* According to the RFC, the description of an object class can
* include the following information:
* <P>
*
* <UL>
* <LI>an OID identifying the object class
* <LI>a name identifying the object class
* <LI>a description of the object class
* <LI>the name of the parent object class
* <LI>the list of attribute types that are required in this object class
* <LI>the list of attribute types that are allowed (optional) in this
* object class
* </UL>
* <P>
*
* 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
* returns schema information as an object with attribute values in this
* 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.
* Entries cannot belong to an abstract object class. <CODE>top</CODE>
* 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
* 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.
* <P>
*
* 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>. Optional and custom qualifiers are
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
* from <CODE>LDAPSchemaElement</CODE>.
* <P>
*
* 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
**/
public class LDAPObjectClassSchema extends LDAPSchemaElement {
static final long serialVersionUID = -1732784695071118656L;
/**
* Constructs an object class definition, using the specified
* information. The type of the object class will be STRUCTURAL.
* @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 superior name of the parent object class
* (the object class that the new object class inherits from)
* @param required array of names of attributes required
* in this object class
* @param optional array of names of optional attributes
* allowed in this object class
*/
public LDAPObjectClassSchema( String name, String oid, String superior,
String description,
String[] required, String[] optional ) {
this( name, oid, superior, description, required, optional, null );
}
/**
* 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 names of parent object classes
* (the object classes that this object class inherits from)
* @param required array of names of attributes required
* in this object class
* @param optional array of names of optional attributes
* allowed in this object class
* @param type either ABSTRACT, STRUCTURAL, or AUXILIARY
* @param aliases names which are to be considered aliases for this
* object class; <CODE>null</CODE> if there are no aliases
*/
public LDAPObjectClassSchema( String name, String oid,
String[] superiors,
String description,
String[] required, String[] optional,
int type, String[] aliases ) {
this( name, oid,
((superiors != null) && (superiors.length > 0)) ?
superiors[0] : null,
description, required, optional, aliases );
if ( (superiors != null) && (superiors.length > 1) ) {
setQualifier( SUPERIOR, superiors );
}
setQualifier( TYPE, typeToString( type ) );
}
/**
* Constructs an object class definition, using the specified
* information. The type of the object class will be STRUCTURAL.
* @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 superior name of the parent object class
* (the object class that the new object class inherits from)
* @param required array of names of attributes required
* in this object class
* @param optional array of names of optional attributes
* allowed in this object class
*/
protected LDAPObjectClassSchema( String name, String oid, String superior,
String description,
String[] required, String[] optional,
String[] aliases ) {
super( name, oid, description, aliases );
attrName = "objectclasses";
setQualifier( SUPERIOR, superior );
if ( required != null ) {
for( int i = 0; i < required.length; i++ ) {
must.addElement( required[i] );
}
}
if ( optional != null ) {
for( int i = 0; i < optional.length; i++ ) {
may.addElement( optional[i] );
}
}
}
/**
* Constructs an object class definition based on a description in
* the ObjectClassDescription format. For information on this format,
* (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
* 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>
*
* @param raw definition of the object in the ObjectClassDescription
* format
*/
public LDAPObjectClassSchema( String raw ) {
attrName = "objectclasses";
parseValue( raw );
setQualifier( TYPE, typeToString( getType() ) );
Object o = properties.get( "MAY" );
if ( o != null ) {
if ( o instanceof Vector ) {
may = (Vector)o;
} else {
may.addElement( o );
}
}
o = properties.get( "MUST" );
if ( o != null ) {
if ( o instanceof Vector ) {
must = (Vector)o;
} else {
must.addElement( o );
}
}
}
/**
* Gets the name of the object class from which this class inherits.
* @return the name of the object class from which this class
* inherits. If it inherits from more than one class, only one
* is returned.
* @see netscape.ldap.LDAPObjectClassSchema#getSuperiors
*/
public String getSuperior() {
String[] superiors = getSuperiors();
return (superiors != null) ? superiors[0] : null;
}
/**
* Gets 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 from which this class
* inherits.
*/
public String[] getSuperiors() {
return getQualifier( SUPERIOR );
}
/**
* Gets an enumeration of the names of the required attributes for
* this object class.
* @return an enumeration of the names of the required attributes
* for this object class.
*/
public Enumeration getRequiredAttributes() {
return must.elements();
}
/**
* Gets an enumeration of names of optional attributes allowed
* in this object class.
* @return an enumeration of the names of optional attributes
* allowed in this object class.
*/
public Enumeration getOptionalAttributes() {
return may.elements();
}
/**
* Gets the type of the object class.
* @return STRUCTURAL, ABSTRACT, or AUXILIARY.
*/
public int getType() {
int type = STRUCTURAL;
if ( properties.containsKey( "AUXILIARY" ) ) {
type = AUXILIARY;
} else if ( properties.containsKey( "ABSTRACT" ) ) {
type = ABSTRACT;
}
return type;
}
/**
* Prepares 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 for submission to an LDAP server.
*/
String getValue( boolean quotingBug ) {
String s = getValuePrefix();
String val = getValue( SUPERIOR, quotingBug );
if ( (val != null) && (val.length() > 0) ) {
s += val + ' ';
}
String[] vals = getQualifier( TYPE );
if ( (vals != null) && (vals.length > 0) ) {
s += vals[0] + ' ';
}
val = getOptionalValues( NOVALS );
if ( val.length() > 0 ) {
s += val + ' ';
}
if ( must.size() > 0 ) {
s += "MUST " + vectorToList( must );
s += ' ';
}
if ( may.size() > 0 ) {
s += "MAY " + vectorToList( may );
s += ' ';
}
val = getCustomValues();
if ( val.length() > 0 ) {
s += val + ' ';
}
s += ')';
return s;
}
/**
* Gets the definition of the object class in a user friendly format.
* This is the format that the object class definition uses when
* you print the object class or the schema.
* @return definition of the object class in a user friendly format.
*/
public String toString() {
String s = "Name: " + name + "; OID: " + oid +
"; Superior: ";
String[] superiors = getSuperiors();
if ( superiors != null ) {
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() ) {
if ( i > 0 )
s += ", ";
i++;
s += (String)e.nextElement();
}
s += "; Optional: ";
e = getOptionalAttributes();
i = 0;
while( e.hasMoreElements() ) {
if ( i > 0 )
s += ", ";
i++;
s += (String)e.nextElement();
}
String[] vals = getQualifier( TYPE );
if ( (vals != null) && (vals.length > 0) ) {
s += "; " + vals[0];
}
if ( isObsolete() ) {
s += "; OBSOLETE";
}
s += getQualifierString( IGNOREVALS );
s += getAliasString();
return s;
}
/**
* Creates a list within parentheses, with $ as delimiter
*
* @param vals values for list
* @return a String with a list of values.
*/
protected String vectorToList( Vector vals ) {
String val = "( ";
for( int i = 0; i < vals.size(); i++ ) {
val += (String)vals.elementAt(i) + ' ';
if ( i < (vals.size() - 1) ) {
val += "$ ";
}
}
val += ')';
return val;
}
/**
* Returns the object class type as a String
*
* @param type one of STRUCTURAL, ABSTRACT, or AUXILIARY
* @return one of "STRUCTURAL", "ABSTRACT", "AUXILIARY", or <CODE>null</CODE>
*/
protected String typeToString( int type ) {
switch( type ) {
case STRUCTURAL: return "STRUCTURAL";
case ABSTRACT: return "ABSTRACT";
case AUXILIARY: return "AUXILIARY";
default: return null;
}
}
public static final int STRUCTURAL = 0;
public static final int ABSTRACT = 1;
public static final int AUXILIARY = 2;
private Vector must = new Vector();
private Vector may = new Vector();
private int type = STRUCTURAL;
// Qualifiers known to not have values; prepare a Hashtable
static final String[] NOVALS = { "ABSTRACT", "STRUCTURAL",
"AUXILIARY", "OBSOLETE" };
static {
for( int i = 0; i < NOVALS.length; i++ ) {
novalsTable.put( NOVALS[i], NOVALS[i] );
}
}
// Qualifiers which we output explicitly in toString()
static final String[] IGNOREVALS = { "ABSTRACT", "STRUCTURAL",
"AUXILIARY", "MUST", "MAY",
"SUP", "OBSOLETE"};
// Key for type in the properties Hashtable
static final String TYPE = "TYPE";
}

View File

@@ -0,0 +1,78 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import java.io.*;
/**
* Specifies how to retrieve authentication information automatically
* for referrals. If you have set up the search constraints (or the options
* in the <CODE>LDAPConnection</CODE> object) to use automatic referral,
* you must define a class that implements this interface.
* <P>
*
* If no class implements this interface, clients that follow automatic
* referrals are authenticated anonymously to subsequent LDAP servers.
* The following example is a simple class that implements this interface.
* Objects of the myLDAPRebind class check the host and port of the
* referred LDAP server. If the host and port are "alway.mcom.com:389",
* the directory manager's name and password are used to authenticate.
* For all other LDAP servers, anonymous authentication is used.
*
* <PRE>
* public class myLDAPRebind implements netscape.ldap.LDAPRebind
* {
* private String myDN;
* private String myPW;
* private LDAPRebindAuth myRebindInfo;
* public myLDAPRebind () {
* myDN = "c=Directory Manager,o=Universal Exports,c=UK";
* myPW = "alway4444";
* }
*
* public LDAPRebindAuth getRebindAuthentication( String host, int port ) {
* if ( host.equalsIgnoreCase( "alway.mcom.com" ) && ( port == 389 ) ) {
* myRebindInfo = new LDAPRebindAuth( myDN, myPW );
* } else {
* myRebindInfo = new LDAPRebindAuth( "", "" );
* }
* return myRebindInfo;
* }
* } </PRE>
*
*
* @version 1.0
*/
public interface LDAPRebind {
/**
* Returns an <CODE>LDAPRebindAuth</CODE> object, which the calling function
* can use to get the DN and password to use for authentication (if the client
* is set up to follow referrals automatically).
* @return LDAPRebindAuth object containing authentication information.
* @see netscape.ldap.LDAPRebindAuth
*/
public LDAPRebindAuth getRebindAuthentication(String host,
int port);
}

View File

@@ -0,0 +1,96 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import java.io.*;
/**
* Represents information used to authenticate the client in cases where
* the client follows referrals automatically. If you are defining a class
* that implements the <CODE>LDAPRebind</CODE> interface, your implementation
* of the <CODE>LDAPRebind.getRebindAuthentication</CODE> method needs to
* construct and return an object of this class.
* <P>
*
* For example, the following method sets up authentication information based
* on the LDAP server identified in the referral. Ideally, this method would be
* defined as part of a class implementing the <CODE>LDAPRebind</CODE> interface.
*
* <PRE>
* private String myDN = "cn=Directory Manager,o=Ace Industry,c=US";
* private String myPW = "alway4444";
* private LDAPRebindAuth myRebindInfo;
* ...
* public LDAPRebindAuth getRebindAuthentication( String host, int port ) {
* if ( host.equalsIgnoreCase( "alway.mcom.com" ) && ( port == 389 ) ) {
* myRebindInfo = new LDAPRebindAuth( myDN, myPW );
* } else {
* myRebindInfo = new LDAPRebindAuth( "", "" );
* }
* return myRebindInfo;
* } </PRE>
*
* @version 1.0
* @see netscape.ldap.LDAPRebind
*/
public class LDAPRebindAuth implements java.io.Serializable {
static final long serialVersionUID = 7161655313564756294L;
private String m_dn;
private String m_password;
/**
* Constructs information that is used by the client
* for authentication when following referrals automatically.
* @param dn distinguished name to use for authenticating to
* the LDAP server during an automatic referral (if the client
* is set up to follow referrals automatically)
* @param password password to use for authenticating to
* the LDAP server during an automatic referral (if the client
* is set up to follow referrals automatically)
*/
public LDAPRebindAuth(String dn, String password) {
m_dn = dn;
m_password = password;
}
/**
* Returns the distinguished name to be used for reauthentication,
* if the client is set up to follow referrals automatically.
* @return distinguished name to use when authenticating to
* other LDAP servers during referrals.
*/
public String getDN() {
return m_dn;
}
/**
* Returns the password to be used for reauthentication,
* if the client is set up to follow referrals automatically.
* @return password to use when authenticating to other
* LDAP servers during referrals.
*/
public String getPassword() {
return m_password;
}
}

View File

@@ -0,0 +1,152 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import netscape.ldap.client.*;
import netscape.ldap.client.opers.*;
import java.io.*;
/**
* Represents the situation in which the LDAP server refers the client to
* another LDAP server. This exception constructs a list of referral URLs from
* the LDAP error message returned by the server. You can get this list by
* using the <CODE>getURLs</CODE> method.
*
* @version 1.0
* @see netscape.ldap.LDAPException
*/
public class LDAPReferralException extends LDAPException {
static final long serialVersionUID = 1771536577344289897L;
private String m_referrals[] = null; /* modified for LDAPv3 */
/**
* Constructs a default exception with no specific error information.
*/
public LDAPReferralException() {
}
/**
* Constructs a default exception with a specified string as
* additional information. This form is used for lower-level errors.
* @param message the additional error information
*/
public LDAPReferralException( String message ) {
super( message );
}
/**
* Constructs a default exception with a specified string as
* additional information. This form is used for higher-level LDAP
* operational errors.
* @param message the additional error information
* @param resultCode result code
* @param serverErrorMessage error message
*/
public LDAPReferralException( String message, int resultCode,
String serverErrorMessage ) {
super(message, resultCode, serverErrorMessage);
}
/**
* Constructs an exception with a list of LDAP URLs to other LDAP servers.
* This list of referrals points the client to LDAP servers that may
* contain the requested entries.
* @param message the additional error information
* @param resultCode result code
* @param referrals array of LDAP URLs identifying other LDAP servers that
* may contain the requested entries
*/
public LDAPReferralException( String message, int resultCode,
String referrals[] ) {
super(message, resultCode, null);
m_referrals = referrals;
}
/**
* Gets the list of referrals (LDAP URLs to other servers) returned by the LDAP server.
* You can use this list to find the LDAP server that can fulfill your request.
*
* If you have set up your search constraints (or the <CODE>LDAPConnection</CODE> object)
* to follow referrals automatically, any operation that results in a referral will use
* this list to create new connections to the LDAP servers in this list.
*
* @return list of LDAP URLs to other LDAP servers.
*/
public LDAPUrl[] getURLs() {
if (getLDAPErrorMessage() == null) {
return constructsURL(m_referrals);
} else {
return constructsURL(extractReferrals(getLDAPErrorMessage()));
}
}
private LDAPUrl[] constructsURL(String referrals[]) {
if (referrals == null) {
return null;
}
LDAPUrl u[] = new LDAPUrl[referrals.length];
if (u == null) {
return null;
}
for (int i = 0; i < referrals.length; i++) {
try {
u[i] = new LDAPUrl(referrals[i]);
} catch (Exception e) {
return null;
}
}
return u;
}
/**
* Extract referral string from the error message. The
* error string is based on "Referrals Within the
* LDAPv2 Protocol".
* @param error string
*/
private String[] extractReferrals(String error) {
if (error == null)
return null;
StringTokenizer st = new StringTokenizer(error, "\n");
Vector v = new Vector();
boolean referrals = false;
while (st.hasMoreTokens()) {
String token = st.nextToken();
if (referrals) {
v.addElement(token);
} else {
if (token.startsWith("Referral:"))
referrals = true;
}
}
if (v.size() == 0)
return null;
String res[] = new String[v.size()];
for (int i = 0; i < v.size(); i++) {
res[i] = (String)v.elementAt(i);
}
return res;
}
}

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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import java.io.*;
/**
* This class represents a locale-specific resource for a property file.
* It retrieves the property file for the given base name including the
* absolute path name and locale. The property file has to be located in the
* CLASSPATH and the property file's suffix is .props.
* <p>
* If the specified locale is en and us and the base name of the file is
* netscape/ldap/errors/ErrorCodes, then the class loader will search for
* the file in the following order:
* <pre>
*
* ErrorCodes_en_us.props
* ErrorCodes_en.props
* ErrorCodes.props
*
* </pre>
* @see java.util.Locale
*/
class LDAPResourceBundle implements java.io.Serializable {
static final long serialVersionUID = -5903986665461157980L;
private static final boolean m_debug = false;
private static final String m_suffix = ".props";
private static final String m_locale_separator = "_";
/**
* Return the property resource bundle according to the base name of the
* property file and the locale. The class loader will find the closest match
* with the given locale.
* @return the property resource bundle.
* @exception IOException Gets thrown when failed to open the resource
* bundle file.
*/
static PropertyResourceBundle getBundle(String baseName)
throws IOException {
return getBundle(baseName, Locale.getDefault());
}
/**
* Return the property resource bundle according to the base name of the
* property file and the locale. The class loader will find the closest match
* with the given locale.
* @param baseName the base name of the property file. The base name contains
* no locale context and no . suffix.
* @param l the locale
* @return the property resource bundle.
* @exception IOException Gets thrown when failed to create a property
* resource
*/
static PropertyResourceBundle getBundle(String baseName, Locale l)
throws IOException {
String localeStr = m_locale_separator+l.toString();
InputStream fin = null;
while (true) {
if ((fin=getStream(baseName, localeStr)) != null) {
PropertyResourceBundle p = new PropertyResourceBundle(fin);
return p;
} else {
int index = localeStr.lastIndexOf(m_locale_separator);
if (index == -1) {
printDebug("File "+baseName+localeStr+m_suffix+" not found");
return null;
} else
localeStr = localeStr.substring(0, index);
}
}
}
/**
* Constructs the whole absolute path name of a property file and retrieves
* an input stream on the file.
* @param baseName the base name of the property file. The base name contains
* no locale context and no . suffix.
* @param the locale string to insert into the file name
* @return the input stream of the property file.
*/
private static InputStream getStream(String baseName, String locale) {
String fStr = baseName+locale+m_suffix;
return (ClassLoader.getSystemResourceAsStream(fStr));
}
/**
* Prints debug messages if the debug mode is on.
* @param str the message that is printed
*/
private static void printDebug(String str) {
if (m_debug)
System.out.println(str);
}
}

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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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 {
static final long serialVersionUID = 5822205242593427418L;
/**
* Constructor
*
* @param msgid message identifier
* @param rsp operation response
* @param controls array of controls or 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 to match,
* 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,56 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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 implements java.io.Serializable {
static final long serialVersionUID = 389472019686058593L;
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

@@ -0,0 +1,98 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
/**
* Represents the message queue associated with a particular LDAP
* operation or operations.
*
*/
public class LDAPResponseListener extends LDAPMessageQueue{
static final long serialVersionUID = 901897097111294329L;
/**
* Constructor
* @param asynchOp a boolean flag that is true if the object is used for
* asynchronous LDAP operations
* @see netscape.ldap.LDAPAsynchronousConnection
*/
LDAPResponseListener(boolean asynchOp) {
super(asynchOp);
}
/**
* 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 an LDAP operation or null if there are no
* more outstanding requests.
* @exception LDAPException Network error exception
* @exception LDAPInterruptedException The invoking thread was interrupted
*/
public LDAPResponse getResponse() throws LDAPException {
return (LDAPResponse)nextMessage();
}
/**
* Merge two response listeners.
* Move/append the content from another response listener to this one.
* <P>
* To be used for synchronization of asynchronous LDAP operations where
* requests are sent by one thread but processed by another one.
* <P>
* A client may be implemented in such a way that one thread makes LDAP
* requests and calls l.getMessageIDs(), 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.getMessageIDs().
* The proper way to handle this scenario is to create a separate listener
* for each new request, and after l.getMessageIDs() has been invoked, merge the
* new request with the existing one.
* @param listener2 the listener with which to merge
*/
public void merge(LDAPResponseListener listener2) {
super.merge(listener2);
}
/**
* Reports true if a response has been received from the server.
*
* @return a flag indicating whether the response message queue is empty.
*/
public boolean isResponseReceived() {
return super.isMessageReceived();
}
/**
* Returns message IDs for all outstanding requests
* @return message ID array.
*/
public int[] getMessageIDs() {
return super.getMessageIDs();
}
}

View File

@@ -0,0 +1,314 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.io.*;
import java.net.*;
/**
* Creates an SSL socket connection to an LDAP Server. This class
* implements the <CODE>LDAPSSLSocketFactoryExt</CODE> interface.
* <P>
*
* To construct an object of this class, you need to specify the
* name of a class that implements the <CODE>javax.net.ssl.SSLSocket</CODE>
* interface. If you do not specify a class name, the class
* <CODE>netscape.net.SSLSocket</CODE> is used by default. This
* class is included with Netscape Communicator 4.05 and up.
* <P>
*
* If you are using a Java VM that provides certificate database
* management (such as Netscape Communicator), you can authenticate
* your client to a secure LDAP server by using certificates.
* <P>
*
* @version 1.0
* @see LDAPSSLSocketFactoryExt
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
*/
public class LDAPSSLSocketFactory
implements LDAPSSLSocketFactoryExt, java.io.Serializable {
static final long serialVersionUID = -3331456736649381427L;
/**
* Indicates if client authentication is on.
*/
private boolean m_clientAuth = false;
/**
* Name of class implementing SSLSocket.
*/
private String m_packageName = "netscape.net.SSLSocket";
/**
* The cipher suites
*/
private Object m_cipherSuites = null;
/**
* Constructs an <CODE>LDAPSSLSocketFactory</CODE> object using
* the default SSL socket implementation,
* <CODE>netscape.net.SSLSocket</CODE>. (This class is provided
* with Netscape Communicator 4.05 and higher.)
*/
public LDAPSSLSocketFactory() {
}
/**
* Constructs an <CODE>LDAPSSLSocketFactory</CODE> object using
* the default SSL socket implementation,
* <CODE>netscape.net.SSLSocket</CODE>. (This class is provided
* with Netscape Communicator 4.05 and up.)
* @param clientAuth <CODE>true</CODE> if certificate-based client
* authentication is desired. By default, client authentication is
* not used.
*/
public LDAPSSLSocketFactory(boolean clientAuth) {
m_clientAuth = clientAuth;
}
/**
* Constructs an <CODE>LDAPSSLSocketFactory</CODE> object using
* the specified class. The class must implement the interface
* <CODE>javax.net.ssl.SSLSocket</CODE>.
* @param className the name of a class implementing
* the <CODE>javax.net.ssl.SSLSocket</CODE> interface.
* Pass <code>null</code> for this parameter to use the
* default SSL socket implementation,
* <CODE>netscape.net.SSLSocket</CODE>, which is included with
* Netscape Communicator 4.05 and higher.
*/
public LDAPSSLSocketFactory(String className) {
m_packageName = new String(className);
}
/**
* Constructs an <CODE>LDAPSSLSocketFactory</CODE> object using
* the specified class. The class must implement the interface
* <CODE>javax.net.ssl.SSLSocket</CODE>.
* @param className the name of a class implementing
* the <CODE>javax.net.ssl.SSLSocket</CODE> interface.
* Pass <code>null</code> for this parameter to use the
* default SSL socket implementation,
* <CODE>netscape.net.SSLSocket</CODE>, which is included with
* Netscape Communicator 4.05 and higher.
* @param clientAuth <CODE>true</CODE> if certificate-based client
* authentication is desired. By default, client authentication is
* not used.
*/
public LDAPSSLSocketFactory(String className, boolean clientAuth) {
m_packageName = new String(className);
m_clientAuth = clientAuth;
}
/**
* The constructor with the specified package for security and the specified
* cipher suites.
* @param className the name of a class implementing the interface
* <CODE>javax.net.ssl.SSLSocket</CODE>.
* Pass <code>null</code> for this parameter to use the
* default SSL socket implementation,
* <CODE>netscape.net.SSLSocket</CODE>, which is included with
* Netscape Communicator 4.05 and higher.
* @param cipherSuites the cipher suites to use for SSL connections
*/
public LDAPSSLSocketFactory(String className, Object cipherSuites) {
m_packageName = new String(className);
m_cipherSuites = cipherSuites;
}
/**
* The constructor with the specified package for security and the specified
* cipher suites.
* @param className the name of a class implementing the interface
* <CODE>javax.net.ssl.SSLSocket</CODE>.
* Pass <code>null</code> for this parameter to use the
* default SSL socket implementation,
* <CODE>netscape.net.SSLSocket</CODE>, which is included with
* Netscape Communicator 4.05 and higher.
* @param cipherSuites the cipher suites to use for SSL connections
* @param clientAuth <CODE>true</CODE> if certificate-based client
* authentication is desired. By default, client authentication is
* not used.
*/
public LDAPSSLSocketFactory(String className, Object cipherSuites,
boolean clientAuth) {
m_packageName = new String(className);
m_cipherSuites = cipherSuites;
m_clientAuth = clientAuth;
}
/**
* Enables certificate-based client authentication for an
* application. The application must be running in a Java VM
* that provides transparent certificate database management
* (for example, Netscape Communicator's Java VM).
* Call this method before you call <CODE>makeSocket</CODE>.
* @see netscape.ldap.LDAPSSLSocketFactory#isClientAuth
* @see netscape.ldap.LDAPSSLSocketFactory#makeSocket
* Note: enableClientAuth() is deprecated. This method is replaced
* by any one of the following constructors:
* <p>
* <CODE>LDAPSSLSocketFactory(boolean)</CODE>
* <CODE>LDAPSSLSocketFactory(java.lang.String, boolean)</CODE>
* <CODE>LDAPSSLSocketFactory(java.lang.String, java.lang.Object, boolean)</CODE>
*/
public void enableClientAuth() {
m_clientAuth = true;
}
/**
* <B>This method is currently not implemented.</B>
* Enables client authentication for an application that uses
* an external (file-based) certificate database.
* Call this method before you call <CODE>makeSocket</CODE>.
* @param certdb the pathname for the certificate database
* @param keydb the pathname for the private key database
* @param keypwd the password for the private key database
* @param certnickname the alias for the certificate
* @param keynickname the alias for the key
* @see netscape.ldap.LDAPSSLSocketFactory#isClientAuth
* @see netscape.ldap.LDAPSSLSocketFactory#makeSocket
* @exception LDAPException Since this method is not yet implemented,
* calling this method throws an exception.
* Note: <CODE>enableClientAuth(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)</CODE> is deprecated.
* This method is replaced by any one of the following constructors:
* <p>
* <CODE>LDAPSSLSocketFactory(boolean)</CODE>
* <CODE>LDAPSSLSocketFactory(java.lang.String, boolean)</CODE>
* <CODE>LDAPSSLSocketFactory(java.lang.String, java.lang.Object, boolean)</CODE>
*/
public void enableClientAuth(String certdb, String keydb, String keypwd,
String certnickname, String keynickname) throws LDAPException {
throw new LDAPException("Client auth not supported now");
}
/**
* Returns <code>true</code> if client authentication is enabled.
* @see netscape.ldap.LDAPSSLSocketFactory
*/
public boolean isClientAuth() {
return m_clientAuth;
}
/**
* Returns the name of the class that implements SSL sockets for this factory.
*
* @return the name of the class that implements SSL sockets for this factory.
*/
public String getSSLSocketImpl() {
return m_packageName;
}
/**
* Returns the suite of ciphers used for SSL connections made through
* sockets created by this factory.
*
* @return the suite of ciphers used.
*/
public Object getCipherSuites() {
return m_cipherSuites;
}
/**
* Returns a socket to the LDAP server with the specified
* host name and port number.
* @param host the host to connect to
* @param port the port number
* @return the socket to the host name and port number.
* @exception LDAPException A socket to the specified host and port
* could not be created.
* @see netscape.ldap.LDAPSSLSocketFactory
*/
public Socket makeSocket(String host, int port)
throws LDAPException {
Socket s = null;
if (m_clientAuth) {
try {
/* 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) {
String msg = "LDAPSSLSocketFactory.makeSocket: invoking " +
"enablePrivilege: " + e.toString();
throw new LDAPException(msg, LDAPException.PARAM_ERROR);
}
}
try {
String cipherClassName = null;
if (m_cipherSuites != null)
cipherClassName = m_cipherSuites.getClass().getName();
/* Instantiate the SSLSocketFactory implementation, and
find the right constructor */
Class c = Class.forName(m_packageName);
java.lang.reflect.Constructor[] m = c.getConstructors();
for (int i = 0; i < m.length; i++) {
/* Check if the signature is right: String, int */
Class[] params = m[i].getParameterTypes();
if ( (m_cipherSuites == null) && (params.length == 2) &&
(params[0].getName().equals("java.lang.String")) &&
(params[1].getName().equals("int")) ) {
Object[] args = new Object[2];
args[0] = host;
args[1] = new Integer(port);
s = (Socket)(m[i].newInstance(args));
return s;
} else if ( (m_cipherSuites != null) && (params.length == 3) &&
(params[0].getName().equals("java.lang.String")) &&
(params[1].getName().equals("int")) &&
(params[2].getName().equals(cipherClassName)) ) {
Object[] args = new Object[3];
args[0] = host;
args[1] = new Integer(port);
args[2] = m_cipherSuites;
s = (Socket)(m[i].newInstance(args));
return s;
}
}
throw new LDAPException("No appropriate constructor in " +
m_packageName,
LDAPException.PARAM_ERROR);
} catch (ClassNotFoundException e) {
throw new LDAPException("Class " + m_packageName + " not found",
LDAPException.PARAM_ERROR);
} catch (Exception e) {
throw new LDAPException("Failed to create SSL socket",
LDAPException.CONNECT_ERROR);
}
}
}

View File

@@ -0,0 +1,50 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
/**
* Represents an SSL socket connection that you can use to connect to an
* LDAP server. This interface extends the base interface LDAPSocketFactory
* and provides SSL-specific methods.
* <P>
*
* @version 1.0
* @see LDAPSocketFactory
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
*/
public interface LDAPSSLSocketFactoryExt extends LDAPSocketFactory {
/**
* Returns the suite of ciphers used for SSL connections. These connections
* are made through sockets created by the LDAPSSLSocketFactory.
*
* @return the suite of ciphers used.
*/
public Object getCipherSuites();
/**
* Returns <code>true</code> if client authentication is enabled.
* @see netscape.ldap.LDAPSSLSocketFactory#enableClientAuth
*/
public boolean isClientAuth();
}

View File

@@ -0,0 +1,355 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.io.*;
import java.net.*;
import java.util.Hashtable;
/**
* Creates an SSL socket connection to an LDAP Server. This class is provided
* by the package in which the SSL socket does not extend Socket object.
* The class internally provides a wrapper to convert the SSL socket extending
* the Object class to the one extending the Socket class.
* This factory class implements the <CODE>LDAPSocketFactory</CODE> interface.
* <P>
*
* To use this class, pass the instance of this factory object to the
* <CODE>LDAPConnection</CODE> constructor.
*
* @version 1.0
* @see LDAPSocketFactory
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
*/
public class LDAPSSLSocketWrapFactory
implements LDAPSSLSocketFactoryExt, java.io.Serializable {
static final long serialVersionUID = -4171548771815037740L;
/**
* The constructor with the specified package for security
* @param className the name of a class which has an implementation
* of the SSL Socket extending Object class
*/
public LDAPSSLSocketWrapFactory(String className) {
m_packageName = new String(className);
}
/**
* The constructor with the specified package for security and the
* specified cipher suites.
* @param className the name of a class which has an implementation
* of the SSL Socket extending Object class
* @param cipherSuites the cipher suites
*/
public LDAPSSLSocketWrapFactory(String className, Object cipherSuites) {
m_packageName = new String(className);
m_cipherSuites = cipherSuites;
}
/**
* Returns socket to the specified host name and port number.
* @param host the host to connect to
* @param port the port number
* @return the socket to the host name and port number as passed in.
* @exception LDAPException A socket to the specified host and port
* could not be created.
*/
public Socket makeSocket(String host, int port) throws LDAPException {
LDAPSSLSocket s = null;
try {
if (m_cipherSuites == null)
s = new LDAPSSLSocket(host, port, m_packageName);
else
s = new LDAPSSLSocket(host, port, m_packageName,
m_cipherSuites);
return s;
} catch (Exception e) {
System.err.println("Exception: "+e.toString());
throw new LDAPException("Failed to create SSL socket",
LDAPException.CONNECT_ERROR);
}
}
/**
* Returns <code>true</code> if client authentication is to be used.
* @return <code>true</code> if client authentication is enabled;
* <code>false</code>if client authentication is disabled.
*/
public boolean isClientAuth() {
return m_clientAuth;
}
/**
* <B>(Not implemented yet)</B> <BR>
* Enables client authentication for an application running in
* a java VM which provides transparent certificate database management.
* Calling this method has no effect after makeSocket() has been
* called.
* @exception LDAPException Since this method is not yet implemented,
* calling this method throws an exception.
*/
public void enableClientAuth() throws LDAPException {
throw new LDAPException("Client Authentication is not implemented yet.");
}
/**
* Returns the name of the class that implements SSL sockets for this factory.
*
* @return the name of the class that implements SSL sockets for this factory.
*/
public String getSSLSocketImpl() {
return m_packageName;
}
/**
* Returns the suite of ciphers used for SSL connections made through
* sockets created by this factory.
*
* @return the suite of ciphers used.
*/
public Object getCipherSuites() {
return m_cipherSuites;
}
/**
* Indicates if client authentication is on.
*/
private boolean m_clientAuth = false;
/**
* Name of class implementing SSLSocket.
*/
private String m_packageName = null;
/**
* The cipher suites
*/
private Object m_cipherSuites = null;
}
// LDAPSSLSocket class wraps the implementation of the SSL socket
class LDAPSSLSocket extends Socket {
public LDAPSSLSocket(String host, int port, String packageName)
throws LDAPException {
super();
m_packageName = packageName;
try {
// instantiate the SSLSocketFactory implementation, and
// find the right constructor
Class c = Class.forName(m_packageName);
java.lang.reflect.Constructor[] m = c.getConstructors();
for (int i = 0; i < m.length; i++) {
/* Check if the signature is right: String, int */
Class[] params = m[i].getParameterTypes();
if ((params.length == 2) &&
(params[0].getName().equals("java.lang.String")) &&
(params[1].getName().equals("int"))) {
Object[] args = new Object[2];
args[0] = host;
args[1] = new Integer(port);
m_socket = (Object)(m[i].newInstance(args));
return;
}
}
throw new LDAPException("No appropriate constructor in " +
m_packageName, LDAPException.PARAM_ERROR);
} catch (ClassNotFoundException e) {
throw new LDAPException("Class " + m_packageName + " not found",
LDAPException.OTHER);
} catch (Exception e) {
throw new LDAPException("Failed to create SSL socket",
LDAPException.CONNECT_ERROR);
}
}
public LDAPSSLSocket(String host, int port, String packageName,
Object cipherSuites) throws LDAPException {
super();
m_packageName = packageName;
String cipherClassName = null;
if (cipherSuites != null)
cipherClassName = cipherSuites.getClass().getName();
try {
// instantiate the SSLSocketFactory implementation, and
// find the right constructor
Class c = Class.forName(m_packageName);
java.lang.reflect.Constructor[] m = c.getConstructors();
for (int i = 0; i < m.length; i++) {
/* Check if the signature is right: String, int */
Class[] params = m[i].getParameterTypes();
if (cipherSuites == null)
throw new LDAPException("Cipher Suites is required");
if ((params.length == 3) &&
(params[0].getName().equals("java.lang.String")) &&
(params[1].getName().equals("int")) &&
(params[2].getName().equals(cipherClassName))) {
Object[] args = new Object[3];
args[0] = host;
args[1] = new Integer(port);
args[2] = cipherSuites;
m_socket = (Object)(m[i].newInstance(args));
return;
}
}
throw new LDAPException("No appropriate constructor in " +
m_packageName, LDAPException.PARAM_ERROR);
} catch (ClassNotFoundException e) {
throw new LDAPException("Class " + m_packageName + " not found",
LDAPException.OTHER);
} catch (Exception e) {
throw new LDAPException("Failed to create SSL socket",
LDAPException.CONNECT_ERROR);
}
}
public InputStream getInputStream() {
try {
Object obj = invokeMethod(m_socket, "getInputStream", null);
return (InputStream)obj;
} catch (LDAPException e) {
printDebug(e.toString());
}
return null;
}
public OutputStream getOutputStream() {
try {
Object obj = invokeMethod(m_socket, "getOutputStream", null);
return (OutputStream)obj;
} catch (LDAPException e) {
printDebug(e.toString());
}
return null;
}
public void close() throws IOException {
try {
invokeMethod(m_socket, "close", null);
} catch (LDAPException e) {
printDebug(e.toString());
}
}
public void close(boolean wait) throws IOException {
try {
Object[] args = new Object[1];
args[0] = new Boolean(wait);
invokeMethod(m_socket, "close", args);
} catch (LDAPException e) {
printDebug(e.toString());
}
}
public InetAddress getInetAddress() {
try {
Object obj = invokeMethod(m_socket, "getInetAddress", null);
return (InetAddress)obj;
} catch (LDAPException e) {
printDebug(e.toString());
}
return null;
}
public int getLocalPort() {
try {
Object obj = invokeMethod(m_socket, "getLocalPort", null);
return ((Integer)obj).intValue();
} catch (LDAPException e) {
printDebug(e.toString());
}
return -1;
}
public int getPort() {
try {
Object obj = invokeMethod(m_socket, "getPort", null);
return ((Integer)obj).intValue();
} catch (LDAPException e) {
printDebug(e.toString());
}
return -1;
}
private Object invokeMethod(Object obj, String name, Object[] args) throws
LDAPException {
try {
java.lang.reflect.Method m = getMethod(name);
if (m != null) {
return (m.invoke(obj, args));
}
} catch (Exception e) {
throw new LDAPException("Invoking "+name+": "+
e.toString(), LDAPException.PARAM_ERROR);
}
return null;
}
private java.lang.reflect.Method getMethod(String name) throws
LDAPException {
try {
java.lang.reflect.Method method = null;
if ((method = (java.lang.reflect.Method)(m_methodLookup.get(name)))
!= null)
return method;
Class c = Class.forName(m_packageName);
java.lang.reflect.Method[] m = c.getMethods();
for (int i = 0; i < m.length; i++ ) {
if (m[i].getName().equals(name)) {
m_methodLookup.put(name, m[i]);
return m[i];
}
}
throw new LDAPException("Method " + name + " not found in " +
m_packageName);
} catch (ClassNotFoundException e) {
throw new LDAPException("Class "+ m_packageName + " not found");
}
}
private void printDebug(String msg) {
if (m_debug) {
System.out.println(msg);
}
}
private final boolean m_debug = true;
private Object m_socket;
private Hashtable m_methodLookup = new Hashtable();
private String m_packageName = null;
}

View File

@@ -0,0 +1,291 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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, java.io.Serializable {
static final long serialVersionUID = -7615315715163655443L;
/**
* 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 authenticate 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 required information
*/
public LDAPSaslBind( String dn,
String[] mechanisms,
String packageName,
Hashtable props,
/*CallbackHandler*/ Object cbh ) {
_dn = dn;
_mechanisms = mechanisms;
_packageName = packageName;
_props = props;
_cbh = cbh;
// 12-01-99 Disabled check for instanceof CallbackHandler so that
// there is no dependency on the extenal jaas.jar package. This is
// reqired for Communicator build where the ldap java package does not
// include any sasl classes.
/*if ( (cbh != null) &&
!(cbh instanceof javax.security.auth.callback.CallbackHandler) ) {
throw new IllegalArgumentException(
"Callback argument must implement " +
"javax.security.auth.callback.CallbackHandler" );
}*/
}
/**
* 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;
}
byte[] b = response.getCredentials();
Object[] args = {b};
String[] argNames = {"[B"}; // class name for byte array
outVals =
(byte[])DynamicInvoker.invokeMethod(
_saslClient,
className, "evaluateChallenge",
args, argNames);
}
// Make sure authentication REALLY is complete
Boolean bool =
(Boolean)DynamicInvoker.invokeMethod(
_saslClient,
className, "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,
className, "getInputStream", args, argNames);
ldc.setInputStream(is);
args[0] = ldc.getOutputStream();
argNames[0] = "java.io.OutputStream";
OutputStream os =
(OutputStream)DynamicInvoker.invokeMethod(
_saslClient,
className, "getOutputStream", args, argNames);
ldc.setOutputStream(os);
ldc.markConnAsBound();
} 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*/ Object _cbh;
private Object _saslClient = null;
}

View File

@@ -0,0 +1,936 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* This object represents the schema of an LDAP v3 server.
* You can use the <CODE>fetchSchema</CODE> method to retrieve
* the schema used by a server. (The server must support LDAP v3
* and the capability to retrieve the schema over the LDAP protocol.)
* <P>
*
* After you retrieve the schema, you can use this object to get
* the object class, attribute type, and matching rule descriptions
* in the schema. You can also add your own object classes,
* attribute types, and matching rules to the schema.
* <P>
*
* To remove any object classes, attribute types, and matching rules
* that you added, call the <CODE>remove</CODE> methods of the
* <CODE>LDAPObjectClassSchema</CODE>, <CODE>LDAPAttributeSchema</CODE>,
* and <CODE>LDAPMatchingRuleSchema</CODE> classes. (This method is
* inherited from the <CODE>LDAPSchemaElement</CODE> class.)
* <P>
*
* The following class is an example of an LDAP client that can
* fetch the schema, get and print object class descriptions and
* attribute type descriptions, and add object classes and attribute
* types to the schema over the LDAP protocol.
* <P>
*
* <PRE>
* import netscape.ldap.*;
* public class TestSchema {
* public static void main( String[] args ) {
* String HOSTNAME = "ldap.netscape.com";
* int PORT_NUMBER = DEFAULT_PORT;
* String ROOT_DN = "cn=Directory Manager";
* String ROOT_PASSWORD = "23skidoo";
*
* LDAPConnection ld = new LDAPConnection();
*
* // Construct a new <CODE>LDAPSchema</CODE> object to get the schema.
* LDAPSchema dirSchema = new LDAPSchema();
*
* try {
* // Connect to the server.
* ld.connect( HOSTNAME, PORT_NUMBER );
*
* // Get the schema from the directory.
* dirSchema.fetchSchema( ld );
*
* // Get and print the inetOrgPerson object class description.
* LDAPObjectClassSchema objClass = dirSchema.getObjectClass(
* "inetOrgPerson" );
* if ( objClass != null ) {
* System.out.println("inetOrgPerson := "+objClass.toString());
* }
*
* // Get and print the definition of the userPassword attribute.
* LDAPAttributeSchema attrType = dirSchema.getAttribute(
* "userpassword" );
* if ( attrType != null ) {
* System.out.println("userPassword := " + attrType.toString());
* }
*
* // 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 );
*
* // Authenticate as root DN to get permissions to edit the schema.
* ld.authenticate( ROOT_DN, ROOT_PASSWORD );
*
* // Add the new object class to the schema.
* 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 );
* // Add a custom qualifier
* newObjClass.setQualifier( "X-OWNER", "John Jacobson" );
*
* // Add the new attribute type to the schema.
* newAttrType.add( ld );
*
* // Fetch the schema again to verify that changes were made.
* dirSchema.fetchSchema( ld );
*
* // Get and print the new attribute type.
* newAttrType = dirSchema.getAttribute( "hairColor" );
* 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());
* }
*
* ld.disconnect();
*
* } catch ( Exception e ) {
* System.err.println( e.toString() );
* System.exit( 1 );
* }
*
* System.exit( 0 );
* }
* }
* </PRE>
*
* If you are using the Netscape Directory Server 3.0, you can also
* verify that the class and attribute type have been added through
* the directory server manager (go to Schema | Edit or View Attributes
* or Schema | Edit or View Object Classes).
* <P>
*
* To remove the classes and attribute types added by the example,
* see the examples under the <CODE>LDAPSchemaElement</CODE> class.
* <P>
*
* @see netscape.ldap.LDAPAttributeSchema
* @see netscape.ldap.LDAPObjectClassSchema
* @see netscape.ldap.LDAPMatchingRuleSchema
* @see netscape.ldap.LDAPSchemaElement
* @version 1.0
* @author Rob Weltman
**/
public class LDAPSchema implements java.io.Serializable {
static final long serialVersionUID = -3911737419783579398L;
/**
* Constructs a new <CODE>LDAPSchema</CODE> object.
* Once you construct the object, you can get
* the schema by calling <CODE>fetchSchema</CODE>.
* <P>
*
* You can also print out the schema by using the
* <CODE>main</CODE> method. For example, you can enter
* the following command:
* <PRE>
* java netscape.ldap.LDAPSchema myhost.mydomain.com 389
* </PRE>
*
* Note that you need to call <CODE>fetchSchema</CODE>
* to get the schema from the server. Constructing the
* object does not fetch the schema.
* <P>
*
* @see netscape.ldap.LDAPSchema#fetchSchema
* @see netscape.ldap.LDAPSchema#main
*/
public LDAPSchema() {
}
public LDAPSchema( LDAPEntry entry ) {
initialize( entry );
}
/**
* Adds an object class schema definition to the current schema.
* You can also add object class schema definitions by calling the
* <CODE>add</CODE> method of your newly constructed
* <CODE>LDAPObjectClassSchema</CODE> object.
* <P>
*
* To remove an object class schema definition that you have added,
* call the <CODE>getObjectClass</CODE> method to get the
* <CODE>LDAPObjectClassSchema</CODE> object representing your
* object class and call the <CODE>remove</CODE> method.
* <P>
*
* <B>NOTE: </B>For information on the <CODE>add</CODE> and
* <CODE>remove</CODE> methods of <CODE>LDAPObjectClassSchema</CODE>,
* see the documentation for <CODE>LDAPSchemaElement</CODE>.
* (These methods are inherited from <CODE>LDAPSchemaElement</CODE>.)
* <P>
*
* @param objectSchema <CODE>LDAPObjectClassSchema</CODE> object
* representing the object class schema definition to add
* @see netscape.ldap.LDAPObjectClassSchema
* @see netscape.ldap.LDAPSchemaElement#add
* @see netscape.ldap.LDAPSchemaElement#remove
*/
public void addObjectClass( LDAPObjectClassSchema objectSchema ) {
objectClasses.put( objectSchema.getName().toLowerCase(),
objectSchema );
}
/**
* Add an attribute type schema definition to the current schema.
* You can also add attribute type schema definitions by calling the
* <CODE>add</CODE> method of your newly constructed
* <CODE>LDAPAttributeSchema</CODE> object.
* <P>
*
* To remove an attribute type schema definition that you have added,
* call the <CODE>getAttribute</CODE> method to get the
* <CODE>LDAPAttributeSchema</CODE> object representing your
* attribute type and call the <CODE>remove</CODE> method.
* <P>
*
* <B>NOTE: </B>For information on the <CODE>add</CODE> and
* <CODE>remove</CODE> methods of <CODE>LDAPAttributeSchema</CODE>,
* see the documentation for <CODE>LDAPSchemaElement</CODE>.
* (These methods are inherited from <CODE>LDAPSchemaElement</CODE>.)
* <P>
*
* @param attrSchema <CODE>LDAPAttributeSchema</CODE> object
* representing the attribute type schema definition to add
* @see netscape.ldap.LDAPAttributeSchema
* @see netscape.ldap.LDAPSchemaElement#add
* @see netscape.ldap.LDAPSchemaElement#remove
*/
public void addAttribute( LDAPAttributeSchema attrSchema ) {
attributes.put( attrSchema.getName().toLowerCase(), attrSchema );
}
/**
* Add a matching rule schema definition to the current schema.
* You can also add matching rule schema definitions by calling the
* <CODE>add</CODE> method of your newly constructed
* <CODE>LDAPMatchingRuleSchema</CODE> object.
* <P>
*
* To remove an attribute type schema definition that you have added,
* call the <CODE>getMatchingRule</CODE> method to get the
* <CODE>LDAPMatchingRuleSchema</CODE> object representing your
* matching rule and call the <CODE>remove</CODE> method.
* <P>
*
* <B>NOTE: </B>For information on the <CODE>add</CODE> and
* <CODE>remove</CODE> methods of <CODE>LDAPMatchingRuleSchema</CODE>,
* see the documentation for <CODE>LDAPSchemaElement</CODE>.
* (These methods are inherited from <CODE>LDAPSchemaElement</CODE>.)
* <P>
*
* @param matchSchema <CODE>LDAPMatchingRuleSchema</CODE> object
* representing the matching rule schema definition to add
* @see netscape.ldap.LDAPMatchingRuleSchema
* @see netscape.ldap.LDAPSchemaElement#add
* @see netscape.ldap.LDAPSchemaElement#remove
*/
public void addMatchingRule( LDAPMatchingRuleSchema matchSchema ) {
matchingRules.put( matchSchema.getName().toLowerCase(), matchSchema );
}
/**
* Add a syntax schema definition to the current schema.
* You can also add syntax schema definitions by calling the
* <CODE>add</CODE> method of your newly constructed
* <CODE>LDAPSyntaxSchema</CODE> object.
* <P>
*
* To remove a syntax schema definition that you have added,
* call the <CODE>getSyntax</CODE> method to get the
* <CODE>LDAPSyntaxSchema</CODE> object representing your
* syntax type and call the <CODE>remove</CODE> method.
* <P>
*
* <B>NOTE: </B>For information on the <CODE>add</CODE> and
* <CODE>remove</CODE> methods of <CODE>LDAPSyntaxSchema</CODE>,
* see the documentation for <CODE>LDAPSchemaElement</CODE>.
* (These methods are inherited from <CODE>LDAPSchemaElement</CODE>.)
* <P>
*
* @param syntaxSchema <CODE>LDAPSyntaxSchema</CODE> object
* representing the syntax schema definition to add
* @see netscape.ldap.LDAPSyntaxSchema
* @see netscape.ldap.LDAPSchemaElement#add
* @see netscape.ldap.LDAPSchemaElement#remove
*/
public void addSyntax( LDAPSyntaxSchema syntaxSchema ) {
String name = syntaxSchema.getName().toLowerCase();
if ( name.length() < 1 ) {
name = syntaxSchema.getOID();
}
syntaxes.put( name, syntaxSchema );
}
/**
* Add a structure rule definition to the current schema.
* You can also add structure rule definitions by calling the
* <CODE>add</CODE> method of your newly constructed
* <CODE>LDAPDITStructureRuleSchema</CODE> object.
* <P>
*
* To remove a structure rule definition that you have added,
* call the <CODE>getDITStructureRule</CODE> method to get the
* <CODE>LDAPDITStructureRuleSchema</CODE> object representing your
* rule and call the <CODE>remove</CODE> method.
* <P>
*
* <B>NOTE: </B>For information on the <CODE>add</CODE> and
* <CODE>remove</CODE> methods of <CODE>LDAPSyntaxSchema</CODE>,
* see the documentation for <CODE>LDAPSchemaElement</CODE>.
* (These methods are inherited from <CODE>LDAPSchemaElement</CODE>.)
* <P>
*
* @param rule <CODE>LDAPDITStructureRuleSchema</CODE> object
* representing the structure rule definition to add
* @see netscape.ldap.LDAPDITStructureRuleSchema
* @see netscape.ldap.LDAPSchemaElement#add
* @see netscape.ldap.LDAPSchemaElement#remove
*/
public void addDITStructureRule( LDAPDITStructureRuleSchema rule ) {
String name = rule.getName().toLowerCase();
structureRulesByName.put( name, rule );
structureRulesById.put( new Integer( rule.getRuleID() ), rule );
}
/**
* Add a content rule definition to the current schema.
* You can also add content rule definitions by calling the
* <CODE>add</CODE> method of your newly constructed
* <CODE>LDAPDITContentRuleSchema</CODE> object.
* <P>
*
* To remove a content rule definition that you have added,
* call the <CODE>getDITContentRule</CODE> method to get the
* <CODE>LDAPDITContentRuleSchema</CODE> object representing your
* rule and call the <CODE>remove</CODE> method.
* <P>
*
* <B>NOTE: </B>For information on the <CODE>add</CODE> and
* <CODE>remove</CODE> methods of <CODE>LDAPSyntaxSchema</CODE>,
* see the documentation for <CODE>LDAPSchemaElement</CODE>.
* (These methods are inherited from <CODE>LDAPSchemaElement</CODE>.)
* <P>
*
* @param rule <CODE>LDAPDITContentRuleSchema</CODE> object
* representing the content rule definition to add
* @see netscape.ldap.LDAPDITContentRuleSchema
* @see netscape.ldap.LDAPSchemaElement#add
* @see netscape.ldap.LDAPSchemaElement#remove
*/
public void addDITContentRule( LDAPDITContentRuleSchema rule ) {
String name = rule.getName().toLowerCase();
contentRules.put( name, rule );
}
/**
* Add a name form definition to the current schema.
* You can also add name form definitions by calling the
* <CODE>add</CODE> method of your newly constructed
* <CODE>LDAPNameFormSchema</CODE> object.
* <P>
*
* To remove a name form definition that you have added,
* call the <CODE>getNameForm</CODE> method to get the
* <CODE>LDAPNameFormSchema</CODE> object representing your
* nameForm type and call the <CODE>remove</CODE> method.
* <P>
*
* <B>NOTE: </B>For information on the <CODE>add</CODE> and
* <CODE>remove</CODE> methods of <CODE>LDAPNameFormSchema</CODE>,
* see the documentation for <CODE>LDAPSchemaElement</CODE>.
* (These methods are inherited from <CODE>LDAPSchemaElement</CODE>.)
* <P>
*
* @param nameForm <CODE>LDAPNameFormSchema</CODE> object
* representing the name form definition to add
* @see netscape.ldap.LDAPNameFormSchema
* @see netscape.ldap.LDAPSchemaElement#add
* @see netscape.ldap.LDAPSchemaElement#remove
*/
public void addNameForm( LDAPNameFormSchema nameForm ) {
String name = nameForm.getName().toLowerCase();
nameForms.put( name, nameForm );
}
/**
* Gets an enumeration ofthe object class definitions in this schema.
* @return an enumeration of object class definitions.
*/
public Enumeration getObjectClasses() {
return objectClasses.elements();
}
/**
* Gets an enumeration ofthe attribute type definitions in this schema.
* @return an enumeration of attribute type definitions.
*/
public Enumeration getAttributes() {
return attributes.elements();
}
/**
* Gets an enumeration ofthe matching rule definitions in this schema.
* @return an enumeration of matching rule definitions.
*/
public Enumeration getMatchingRules() {
return matchingRules.elements();
}
/**
* Get an enumeration of the syntaxes in this schema.
* @return an enumeration of syntax objects
*/
public Enumeration getSyntaxes() {
return syntaxes.elements();
}
/**
* Get an enumeration of the structure rules in this schema.
* @return an enumeration of structure rule objects
*/
public Enumeration getDITStructureRules() {
return structureRulesByName.elements();
}
/**
* Get an enumeration of the content rules in this schema.
* @return an enumeration of content rule objects
*/
public Enumeration getDITContentRules() {
return contentRules.elements();
}
/**
* Get an enumeration of the name forms in this schema.
* @return an enumeration of name form objects
*/
public Enumeration getNameForms() {
return nameForms.elements();
}
/**
* Gets the definition of the object class with the specified name.
* @param name name of the object class to find
* @return an <CODE>LDAPObjectClassSchema</CODE> object representing
* the object class definition, or <CODE>null</CODE> if not found.
*/
public LDAPObjectClassSchema getObjectClass( String name ) {
return (LDAPObjectClassSchema)objectClasses.get( name.toLowerCase() );
}
/**
* Gets the definition of the attribute type with the specified name.
* @param name name of the attribute type to find
* @return an <CODE>LDAPAttributeSchema</CODE> object representing
* the attribute type definition, or <CODE>null</CODE> if not found.
*/
public LDAPAttributeSchema getAttribute( String name ) {
return (LDAPAttributeSchema)attributes.get( name.toLowerCase() );
}
/**
* Gets the definition of a matching rule with the specified name.
* @param name name of the matching rule to find
* @return an <CODE>LDAPMatchingRuleSchema</CODE> object representing
* the matching rule definition, or <CODE>null</CODE> if not found.
*/
public LDAPMatchingRuleSchema getMatchingRule( String name ) {
return (LDAPMatchingRuleSchema)matchingRules.get( name.toLowerCase() );
}
/**
* Gets the definition of a syntax with the specified name.
* @param name name of the syntax to find
* @return an <CODE>LDAPSyntaxSchema</CODE> object representing
* the syntax definition, or <CODE>null</CODE> if not found.
*/
public LDAPSyntaxSchema getSyntax( String name ) {
return (LDAPSyntaxSchema)syntaxes.get( name.toLowerCase() );
}
/**
* Gets the definition of a structure rule with the specified name.
* @param name name of the rule to find
* @return an <CODE>LDAPDITStructureRuleSchema</CODE> object representing
* the rule, or <CODE>null</CODE> if not found.
*/
public LDAPDITStructureRuleSchema getDITStructureRule( String name ) {
return (LDAPDITStructureRuleSchema)structureRulesByName.get(
name.toLowerCase() );
}
/**
* Gets the definition of a structure rule with the specified name.
* @param ID ID of the rule to find
* @return an <CODE>LDAPDITStructureRuleSchema</CODE> object representing
* the rule, or <CODE>null</CODE> if not found.
*/
public LDAPDITStructureRuleSchema getDITStructureRule( int ID ) {
return (LDAPDITStructureRuleSchema)structureRulesById.get(
new Integer( ID ) );
}
/**
* Gets the definition of a content rule with the specified name.
* @param name name of the rule to find
* @return an <CODE>LDAPDITContentRuleSchema</CODE> object representing
* the rule, or <CODE>null</CODE> if not found.
*/
public LDAPDITContentRuleSchema getDITContentRule( String name ) {
return (LDAPDITContentRuleSchema)contentRules.get(
name.toLowerCase() );
}
/**
* Gets the definition of a name form with the specified name.
* @param name name of the name form to find
* @return an <CODE>LDAPNameFormSchema</CODE> object representing
* the syntax definition, or <CODE>null</CODE> if not found.
*/
public LDAPNameFormSchema getNameForm( String name ) {
return (LDAPNameFormSchema)nameForms.get( name.toLowerCase() );
}
/**
* Get an enumeration of the names of the object classes in this schema.
* @return an enumeration of object class names (all lower-case).
*/
public Enumeration getObjectClassNames() {
return objectClasses.keys();
}
/**
* Get an enumeration of the names of the attribute types in this schema.
* @return an enumeration of attribute names (all lower-case).
*/
public Enumeration getAttributeNames() {
return attributes.keys();
}
/**
* Get an enumeration of the names of the matching rules in this schema.
* @return an enumeration of matching rule names (all lower-case).
*/
public Enumeration getMatchingRuleNames() {
return matchingRules.keys();
}
/**
* Get an enumeration of the names of the syntaxes in this schema.
* @return an enumeration of syntax names (all lower-case).
*/
public Enumeration getSyntaxNames() {
return syntaxes.keys();
}
/**
* Get an enumeration of the names of the structure rules in this schema.
* @return an enumeration of names of the structure rule objects
*/
public Enumeration getDITStructureRuleNames() {
return structureRulesByName.keys();
}
/**
* Get an enumeration of the names of the content rules in this schema.
* @return an enumeration of names of the content rule objects
*/
public Enumeration getDITContentRuleNames() {
return contentRules.keys();
}
/**
* Get an enumeration of the names of the name forms in this schema.
* @return an enumeration of names of name form objects
*/
public Enumeration getNameFormNames() {
return nameForms.keys();
}
/**
* 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, String dn )
throws LDAPException {
/* Find the subschemasubentry value for this DN */
String entryName = getSchemaDN( ld, dn );
Enumeration en;
/* Get the entire schema definition entry */
LDAPEntry entry = readSchema( ld, entryName );
initialize( entry );
}
/**
* Extract all schema elements from subschema entry
*
* @param entry entry containing schema definitions
*/
protected void initialize( LDAPEntry entry ) {
/* Get all object class definitions */
LDAPAttribute attr = entry.getAttribute( "objectclasses" );
Enumeration en;
if ( attr != null ) {
en = attr.getStringValues();
while( en.hasMoreElements() ) {
LDAPObjectClassSchema sch =
new LDAPObjectClassSchema( (String)en.nextElement() );
addObjectClass( sch );
}
}
/* Get all attribute definitions */
attr = entry.getAttribute( "attributetypes" );
if ( attr != null ) {
en = attr.getStringValues();
while( en.hasMoreElements() ) {
LDAPAttributeSchema sch =
new LDAPAttributeSchema( (String)en.nextElement() );
addAttribute( sch );
}
}
/* Get all syntax definitions */
attr = entry.getAttribute( "ldapsyntaxes" );
if ( attr != null ) {
en = attr.getStringValues();
while( en.hasMoreElements() ) {
LDAPSyntaxSchema sch =
new LDAPSyntaxSchema( (String)en.nextElement() );
addSyntax( sch );
}
}
/* Get all structure rule definitions */
attr = entry.getAttribute( "ldapditstructurerules" );
if ( attr != null ) {
en = attr.getStringValues();
while( en.hasMoreElements() ) {
LDAPDITStructureRuleSchema sch =
new LDAPDITStructureRuleSchema(
(String)en.nextElement() );
addDITStructureRule( sch );
}
}
/* Get all content rule definitions */
attr = entry.getAttribute( "ldapditcontentrules" );
if ( attr != null ) {
en = attr.getStringValues();
while( en.hasMoreElements() ) {
LDAPDITContentRuleSchema sch =
new LDAPDITContentRuleSchema(
(String)en.nextElement() );
addDITContentRule( sch );
}
}
/* Get all name form definitions */
attr = entry.getAttribute( "nameforms" );
if ( attr != null ) {
en = attr.getStringValues();
while( en.hasMoreElements() ) {
LDAPNameFormSchema sch =
new LDAPNameFormSchema(
(String)en.nextElement() );
addNameForm( sch );
}
}
/* Matching rules are tricky, because we have to match up a
rule with its use. First get all the uses. */
Hashtable h = new Hashtable();
attr = entry.getAttribute( "matchingruleuse" );
if ( attr != null ) {
en = attr.getStringValues();
while( en.hasMoreElements() ) {
String use = (String)en.nextElement();
LDAPMatchingRuleSchema sch =
new LDAPMatchingRuleSchema( null, use );
h.put( sch.getOID(), use );
}
}
/* Now get the rules, and assign uses to them */
attr = entry.getAttribute( "matchingrules" );
if ( attr != null ) {
en = attr.getStringValues();
while( en.hasMoreElements() ) {
String raw = (String)en.nextElement();
LDAPMatchingRuleSchema sch =
new LDAPMatchingRuleSchema( raw, null );
String use = (String)h.get( sch.getOID() );
if ( use != null )
sch = new LDAPMatchingRuleSchema( raw, use );
addMatchingRule( sch );
}
}
}
/**
* 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 = ld.read( 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 = !isSyntaxQuoted( (String)en.nextElement() );
}
}
ld.setProperty( ld.SCHEMA_BUG_PROPERTY, compliant ? "standard" :
"NetscapeBug" );
return compliant;
}
/**
* 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;
}
/**
* Displays the schema (including the descriptions of its object
* classes, attribute types, and matching rules) in an easily
* readable format (not the same as the format expected by
* an LDAP server).
* @return a string containing the schema in printable format.
*/
public String toString() {
String s = "Object classes:\n";
Enumeration en = getObjectClasses();
while( en.hasMoreElements() ) {
s += en.nextElement().toString();
s += '\n';
}
s += "Attributes:\n";
en = getAttributes();
while( en.hasMoreElements() ) {
s += en.nextElement().toString();
s += '\n';
}
s += "Matching rules:\n";
en = getMatchingRules();
while( en.hasMoreElements() ) {
s += en.nextElement().toString();
s += '\n';
}
s += "Syntaxes:\n";
en = getSyntaxes();
while( en.hasMoreElements() ) {
s += en.nextElement().toString();
s += '\n';
}
return s;
}
/**
* 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 = ld.read( 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",
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, new String[] { "*", "ldapsyntaxes" } );
}
/**
* Helper for "main" to print out schema elements.
* @param en enumeration of schema elements
*/
private static void printEnum( Enumeration en ) {
while( en.hasMoreElements() ) {
LDAPSchemaElement s = (LDAPSchemaElement)en.nextElement();
System.out.println( " " + s );
// System.out.println( " " + s.getValue() );
}
}
/**
* Fetch the schema from the LDAP server at the specified
* host and port, and print out the schema (including descriptions
* of its object classes, attribute types, and matching rules).
* The schema is printed in an easily readable format (not the
* same as the format expected by an LDAP server). For example,
* you can enter the following command to print the schema:
* <PRE>
* java netscape.ldap.LDAPSchema myhost.mydomain.com 389
* </PRE>
*
* @param args the host name and the port number of the LDAP server
* (for example, <CODE>netscape.ldap.LDAPSchema directory.netscape.com
* 389</CODE>)
*/
public static void main( String[] args ) {
if ( args.length < 2 ) {
System.err.println( "Usage: netscape.ldap.LDAPSchema HOST PORT" );
System.exit(1 );
}
int port = Integer.parseInt( args[1] );
LDAPConnection ld = new LDAPConnection();
try {
ld.connect( args[0], port );
LDAPSchema schema = new LDAPSchema();
schema.fetchSchema( ld );
ld.disconnect();
System.out.println( "Object classes: " );
printEnum( schema.getObjectClasses() );
System.out.println( "\nAttributes: " );
printEnum( schema.getAttributes() );
System.out.println( "\nMatching rules: " );
printEnum( schema.getMatchingRules() );
System.out.println( "\nSyntaxes: " );
printEnum( schema.getSyntaxes() );
System.exit( 0 );
} catch ( LDAPException e ) {
System.err.println( e );
}
}
private Hashtable objectClasses = new Hashtable();
private Hashtable attributes = new Hashtable();
private Hashtable matchingRules = new Hashtable();
private Hashtable syntaxes = new Hashtable();
private Hashtable structureRulesByName = new Hashtable();
private Hashtable structureRulesById = new Hashtable();
private Hashtable contentRules = new Hashtable();
private Hashtable nameForms = new Hashtable();
}

View File

@@ -0,0 +1,802 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
*
* Abstract class representing an element (such as an object class
* definition, an attribute type definition, or a matching rule
* definition) in the schema. The specific types of elements are
* represented by the <CODE>LDAPObjectClassSchema</CODE>,
* <CODE>LDAPAttributeSchema</CODE>, and <CODE>LDAPMatchingRuleSchema</CODE>
* subclasses.
* <P>
*
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* Attribute Syntax Definitions</A> covers the types of information
* that need to be specified in the definition of an object class,
* attribute type, or matching rule. All of these schema elements
* can specify the following information:
* <P>
*
* <UL>
* <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).
* You can do the following:
* <UL>
* <LI>get the name of a schema element
* <LI>get the OID of a schema element
* <LI>get the description of a schema element
* <LI>add an element to the schema
* <LI>remove an element from the schema
* </UL>
* <P>
*
* @see netscape.ldap.LDAPObjectClassSchema
* @see netscape.ldap.LDAPAttributeSchema
* @see netscape.ldap.LDAPMatchingRuleSchema
* @version 1.0
**/
public abstract class LDAPSchemaElement implements java.io.Serializable {
static final long serialVersionUID = -3972153461950418863L;
/**
* Constructs a blank element.
*/
protected LDAPSchemaElement() {
}
/**
* Constructs a definition explicitly.
* @param name name of element
* @param oid dotted-string object identifier
* @param description description of element
*/
protected LDAPSchemaElement( String name, String oid,
String description ) {
this( name, oid, description, null );
}
/**
* Constructs a definition explicitly.
* @param name name of element
* @param oid dotted-string object identifier
* @param description description of element
* @param aliases names which are to be considered aliases for this
* element; <CODE>null</CODE> if there are no aliases
*/
protected LDAPSchemaElement( String name, String oid,
String description, String[] aliases ) {
if ( oid == null ) {
throw new IllegalArgumentException( "OID required" );
}
this.name = name;
this.oid = oid;
this.description = description;
if ( (aliases != null) && (aliases.length > 0) ) {
this.aliases = aliases;
}
}
/**
* Gets the name of the object class, attribute type, or matching rule.
* @return the name of the object class, attribute type, or
* matching rule.
*/
public String getName() {
return name;
}
/**
* Gets the object ID (OID) of the object class, attribute type,
* or matching rule in dotted-string format (for example, "1.2.3.4").
* @return the OID of the object class, attribute type,
* or matching rule.
*/
public String getID() {
return oid;
}
/**
* Gets the object ID (OID) of the object class, attribute type,
* or matching rule in dotted-string format (for example, "1.2.3.4").
* @return the OID of the object class, attribute type,
* or matching rule.
* @deprecated Use <CODE>LDAPSchemaElement.getID()</CODE>
*/
public String getOID() {
return getID();
}
/**
* Gets the description of the object class, attribute type,
* or matching rule.
* @return the description of the object class, attribute type,
* or matching rule.
*/
public String getDescription() {
return description;
}
/**
* Adds, removes or modifies the definition from a Directory.
* @param ld an open connection to a Directory Server. Typically the
* connection must have been authenticated to add a definition.
* @param op type of modification to make
* @param attr 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,
String dn )
throws LDAPException {
LDAPAttribute[] attrs = new LDAPAttribute[1];
attrs[0] = attr;
update( ld, op, attrs, dn );
}
/**
* Adds, removes or modifies the definition from a Directory.
* @param ld an open connection to a Directory Server. Typically the
* connection must have been authenticated to add a definition.
* @param op type of modification to make
* @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,
String dn )
throws LDAPException {
LDAPModificationSet mods = new LDAPModificationSet();
for( int i = 0; i < attrs.length; i++ ) {
mods.add( op, attrs[i] );
}
String entryName = LDAPSchema.getSchemaDN( ld, dn );
ld.modify( entryName, mods );
}
/**
* Adds, removes or modifies the definition from a Directory.
* @param ld an open connection to a Directory Server. Typically the
* connection must have been authenticated to add a definition.
* @param op type of modification to make
* @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,
String dn )
throws LDAPException {
boolean quotingBug =
!LDAPSchema.isAttributeSyntaxStandardsCompliant( ld );
LDAPAttribute attr = new LDAPAttribute( name,
getValue( quotingBug ) );
update( ld, op, attr, dn );
}
/**
* Adds the current object class, attribute type, or matching rule
* definition to the schema. 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 dn the entry at which to add the schema definition
* @exception LDAPException if 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 if the specified definition cannot be
* added to the schema.
*/
public void add( LDAPConnection ld ) throws LDAPException {
add( ld, "" );
}
/**
* Replaces a single value of the object class, attribute type,
* or matching rule definition in the schema. 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
* @param dn the entry at which to modify the schema definition
* @exception LDAPException if 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 );
}
/**
* Replaces 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 if the specified definition cannot be
* modified.
*/
public void modify( LDAPConnection ld, LDAPSchemaElement newValue )
throws LDAPException {
modify( ld, newValue, "" );
}
/**
* Removes the current object class, attribute type, or matching rule
* definition from the schema. 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 dn the entry at which to remove the schema definition
* @exception LDAPException if 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 if the specified definition cannot be
* removed from the schema
*/
public void remove( LDAPConnection ld ) throws LDAPException {
remove( ld, "" );
}
/**
* Reports if the element is marked as obsolete.
* @return <CODE>true<CODE> if the element is defined as obsolete.
*/
public boolean isObsolete() {
return (properties == null) ? false :
properties.containsKey(OBSOLETE);
}
/**
* Parses 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();
if ( ch[ind] == ' ' ) {
ind++;
}
val = new String( ch, ind, last-ind-1 );
// Is this a quoted list? If so, use ' as delimiter,
// otherwise use ' '. The space between quoted
// values will be returned as tokens containing only
// white space. White space is not valid in a list
// value, so we just remove all tokens containing
// only white space.
String delim = (val.indexOf( '\'' ) >= 0) ? "'" : " ";
StringTokenizer st = new StringTokenizer( val, delim );
while ( st.hasMoreTokens() ) {
String tok = st.nextToken().trim();
if ( (tok.length() > 0) && !tok.equals( "$" ) ) {
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;
}
// Aliases end up as values of NAME
String[] vals = getQualifier( "NAME" );
if ( (vals != null) && (vals.length > 0) ) {
name = vals[0];
if ( vals.length > 1 ) {
aliases = new String[vals.length-1];
System.arraycopy( vals, 1, aliases, 0, aliases.length );
}
}
}
/**
* Formats 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 );
}
String getValue( boolean quotingBug ) {
return null;
}
/**
* Prepares 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 + ' ';
if ( (name != null) && (name.length() > 0) ) {
s += "NAME ";
if ( aliases != null ) {
s += "( " + '\'' + name + "\' ";
for( int i = 0; i < aliases.length; i++ ) {
s += '\'' + aliases[i] + "\' ";
}
s += ") ";
} else {
s += '\'' + name + "\' ";
}
}
if ( description != null ) {
s += "DESC \'" + description + "\' ";
}
if ( isObsolete() ) {
s += OBSOLETE + ' ';
}
return s;
}
/**
* Gets 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;
}
/**
* Gets any qualifiers marked as custom (starting with "X-")
*
* @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, false ) + ' ';
}
// Strip trailing ' '
if ( (s.length() > 0) && (s.charAt( s.length() - 1 ) == ' ') ) {
s = s.substring( 0, s.length() - 1 );
}
return s;
}
/**
* Gets a qualifier's value or values, if present, and formats
* the String according to RFC 2252
*
* @param key the qualifier to get
* @param doQuote <CODE>true</CODE> if values should be enveloped
* with single quotes
* @param doDollar <CODE>true</CODE> if a list of values should use
* " $ " as separator; that is true for object class attribute lists
* @return String in RFC 2252 format, without a terminating
* ' '.
*/
String getValue( String key, boolean doQuote, boolean doDollar ) {
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 ( doDollar && (i < (v.size() - 1)) ) {
s += "$ ";
}
}
s += ')';
}
return s;
}
/**
* Gets a qualifier's value or values, if present, and format
* the String according to RFC 2252.
*
* @param key the qualifier to get
* @param doQuote <CODE>true</CODE> if values should be enveloped
* with single quotes
* @return String in RFC 2252 format, without a terminating
* ' '.
*/
String getValue( String key, boolean doQuote ) {
return getValue( key, doQuote, true );
}
/**
* Keeps track of qualifiers which are not predefined.
* @param name name of qualifier
* @param value value of qualifier. "" for no value, <CODE>null</CODE>
* to remove the qualifier
*/
public void setQualifier( String name, String value ) {
if ( properties == null ) {
properties = new Hashtable();
}
if ( value != null ) {
properties.put( name, value );
} else {
properties.remove( name );
}
}
/**
* Keeps 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 < values.length; i++ ) {
v.addElement( values[i] );
}
properties.put( name, v );
}
/**
* Gets 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 };
}
}
/**
* Gets an enumeration of all qualifiers which are not predefined.
* @return enumeration of qualifiers.
*/
public Enumeration getQualifierNames() {
return properties.keys();
}
/**
* Gets the aliases of the attribute, if any
* @return the aliases of the attribute, or <CODE>null</CODE> if
* it does not have any aliases
*/
public String[] getAliases() {
return aliases;
}
/**
* Creates 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] + ' ';
}
}
// Strip trailing ' '
if ( (s.length() > 0) && (s.charAt( s.length() - 1 ) == ' ') ) {
s = s.substring( 0, s.length() - 1 );
}
return s;
}
/**
* Gets any aliases for this element
*
* @return a string with any aliases, for use in toString()
*/
String getAliasString() {
if ( aliases != null ) {
String s = "; aliases:";
for( int i = 0; i < aliases.length; i++ ) {
s += ' ' + aliases[i];
}
return s;
}
return "";
}
// Constants for known syntax types
public static final int unknown = 0;
public static final int cis = 1;
public static final int binary = 2;
public static final int telephone = 3;
public static final int ces = 4;
public static final int dn = 5;
public static final int integer = 6;
protected static final String cisString =
"1.3.6.1.4.1.1466.115.121.1.15";
protected static final String binaryString =
"1.3.6.1.4.1.1466.115.121.1.5";
protected static final String telephoneString =
"1.3.6.1.4.1.1466.115.121.1.50";
protected static final String cesString =
"1.3.6.1.4.1.1466.115.121.1.26";
protected static final String intString =
"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";
// Predefined qualifiers which apply to any schema element type
public static final String OBSOLETE = "OBSOLETE";
public static final String SUPERIOR = "SUP";
// Predefined qualifiers
public static final String SYNTAX = "SYNTAX";
// Properties which are common to all schema elements
protected String oid = null;
protected String name = "";
protected String description = "";
protected String attrName = null;
protected String rawValue = null;
protected String[] aliases = null;
// Additional qualifiers
protected Hashtable properties = null;
// Qualifiers known to not have values
static protected Hashtable novalsTable = new Hashtable();
}

View File

@@ -0,0 +1,362 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
/**
* Represents a set of search preferences.
* You can set these preferences for a particular search
* by creating an <CODE>LDAPSearchConstraints</CODE> object,
* specifying your preferences, and passing the object to
* the <CODE>LDAPConnection.search</CODE> method.
* <P>
*
* @version 1.0
*/
public class LDAPSearchConstraints extends LDAPConstraints
implements Cloneable {
private int deref;
private int maxRes;
private int batch;
private int serverTimeLimit;
private int m_maxBacklog = 100;
/**
* Constructs an <CODE>LDAPSearchConstraints</CODE> object that specifies
* the default set of search constraints.
*/
public LDAPSearchConstraints() {
super();
deref = 0;
maxRes = 1000;
batch = 1;
serverTimeLimit = 0;
}
/**
* 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 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 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 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)
* @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 LDAPSearchConstraints( int msLimit, int dereference,
int maxResults, boolean doReferrals, int batchSize,
LDAPRebind rebind_proc, int hop_limit) {
super(msLimit, doReferrals, rebind_proc, hop_limit);
deref = dereference;
maxRes = maxResults;
batch = batchSize;
}
/**
* 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 (the default value is 0, indicating that there
* is 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 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.
* (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 LDAPSearchConstraints( int msLimit, int timeLimit,
int dereference,
int maxResults, boolean doReferrals,
int batchSize,
LDAPRebind rebind_proc,
int hop_limit) {
super(msLimit, doReferrals, rebind_proc, hop_limit);
serverTimeLimit = timeLimit;
deref = dereference;
maxRes = maxResults;
batch = batchSize;
}
/**
* 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 (the default value is 0, indicating that there
* is 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 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;
}
/**
* Returns the maximum number of seconds to wait for the server to
* spend on a search operation.If 0, there is no time limit.
* @return maximum number of seconds for the server to spend.
*/
public int getServerTimeLimit() {
return serverTimeLimit;
}
/**
* Specifies how aliases should be dereferenced.
* @return <CODE>LDAPv2.DEREF_NEVER</CODE> to
* never follow ("dereference") aliases,
* <CODE>LDAPv2.DEREF_FINDING</CODE> to dereference when finding
* the starting point for the search (but not when searching
* under that starting entry), <CODE>LDAPv2.DEREF_SEARCHING</CODE>
* to dereference when searching the entries beneath the
* starting point of the search (but not when finding the starting
* entry), or <CODE>LDAPv2.DEREF_ALWAYS</CODE> to always
* dereference aliases.
*/
public int getDereference() {
return deref;
}
/**
* Returns the maximum number of search results that are to be returned; 0 means
* there is no limit.
* @return maximum number of search results to be returned.
*/
public int getMaxResults() {
return maxRes;
}
/**
* Returns 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 results are to be processed as they come in.
* @return number of results to return at a time.
*/
public int getBatchSize() {
return batch;
}
/**
* Sets the maximum number of seconds for the server to spend
* returning search results. If 0, there is no time limit.
* @param limit maximum number of seconds for the server to spend.
* (0 by default, which means that there is no maximum time limit.)
*/
public void setServerTimeLimit( int limit ) {
serverTimeLimit = limit;
}
/**
* Sets a preference indicating how aliases should be dereferenced.
* @param dereference <CODE>LDAPv2.DEREF_NEVER</CODE> to
* never follow ("dereference") aliases,
* <CODE>LDAPv2.DEREF_FINDING</CODE> to dereference when finding
* the starting point for the search (but not when searching
* under that starting entry), <CODE>LDAPv2.DEREF_SEARCHING</CODE>
* to dereference when searching the entries beneath the
* starting point of the search (but not when finding the starting
* entry), or <CODE>LDAPv2.DEREF_ALWAYS</CODE> to always
* dereference aliases
*/
public void setDereference( int dereference ) {
deref = dereference;
}
/**
* Sets the maximum number of search results to return; 0 means
* there is no limit. (By default, this is set to 1000.)
* @param maxResults maximum number of search results to return
*/
public void setMaxResults( int maxResults ) {
maxRes = maxResults;
}
/**
* 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
* results are to be processed as they come in. (By default, this is 1.)
* @param batchSize number of results to return at a time
*/
public void setBatchSize( int batchSize ) {
batch = batchSize;
}
/**
* 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;
}
/**
* 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;
}
/**
* Makes a copy of an existing set of search constraints.
* @return a copy of an existing set of search constraints.
*/
public Object clone() {
LDAPSearchConstraints o = new LDAPSearchConstraints();
o.serverTimeLimit = this.serverTimeLimit;
o.deref = this.deref;
o.maxRes = this.maxRes;
o.batch = this.batch;
o.setHopLimit(this.getHopLimit());
o.setReferrals(this.getReferrals());
o.setTimeLimit(this.getTimeLimit());
if (this.getBindProc() != null) {
o.setBindProc(this.getBindProc());
} else {
o.setRebindProc(this.getRebindProc());
}
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;
}
/**
* Return a string representation of the object for debugging
*
* @return A string representation of the object
*/
public String toString() {
StringBuffer sb = new StringBuffer("LDAPSearchConstraints {");
sb.append( super.toString() + ' ' );
sb.append("size limit " + maxRes + ", ");
sb.append("server time limit " + serverTimeLimit + ", ");
sb.append("aliases " + deref + ", ");
sb.append("batch size " + batch);
sb.append('}');
return sb.toString();
}
}

View File

@@ -0,0 +1,164 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import netscape.ldap.client.*;
/**
* Manages search results, references and responses returned on one or
* more search requests
*
*/
public class LDAPSearchListener extends LDAPMessageQueue {
static final long serialVersionUID = -7163312406176592277L;
// this instance variable is only for cache purpose
private Long m_key = null;
private LDAPSearchConstraints m_constraints;
/**
* Constructs a LDAP search listener.
* @param asynchOp a boolean flag indicating whether the object is used
* for asynchronous LDAP operations
* @param cons LDAP search constraints
* @see netscape.ldap.LDAPAsynchronousConnection
*/
LDAPSearchListener ( boolean asynchOp,
LDAPSearchConstraints cons ) {
super ( asynchOp );
m_constraints = cons;
}
/**
* Block until all results are in. Used for synchronous search with
* batch size of zero.
* @return search response message.
* @exception Network exception error
*/
LDAPResponse completeSearchOperation () throws LDAPException{
return completeRequest();
}
/**
* 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, search response message,
* or null if there are no more outstanding requests.
* @exception LDAPException Network error exception
* @exception LDAPInterruptedException The invoking thread was interrupted
* @see LDAPResponse
* @see LDAPSearchResult
* @see LDAPSearchResultReference
*/
public LDAPMessage getResponse () throws LDAPException{
return nextMessage();
}
/**
* Override nextMessage to wake up the LDAPConnThread if
* backlog limit has been reached
*/
LDAPMessage nextMessage() throws LDAPException{
LDAPMessage result = super.nextMessage();
// Notify LDAPConnThread to wake up if backlog limit has been reached
if (result instanceof LDAPSearchResult || result instanceof LDAPSearchResultReference) {
LDAPConnection ld = getConnection(result.getMessageID());
if (ld != null) {
ld.resultRetrieved();
}
}
return result;
}
/**
* Merge two response listeners.
* Move/append the content from another response listener to this one.
* <P>
* To be used for synchronization of asynchronous LDAP operations where
* requests are sent by one thread but processed by another one.
* <P>
* A client may be implemented in such a way that one thread makes LDAP
* requests and calls l.getMessageIDs(), 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.getMessageIDs().
* The proper way to handle this scenario is to create a separate listener
* for each new request, and after l.getMessageIDs() has been invoked,
* merge the new request with the existing one.
* @param listener2 the listener with which to merge
*/
public void merge(LDAPSearchListener listener2) {
super.merge(listener2);
}
/**
* Reports true if a response has been received from the server.
*
* @return a flag indicating whether the response message queue is empty.
*/
public boolean isResponseReceived() {
return super.isMessageReceived();
}
/**
* Returns message IDs for all outstanding requests
* @return message ID array.
*/
public int[] getMessageIDs() {
return super.getMessageIDs();
}
/**
* Return the search constraints used to create this object.
* @return the search constraints used to create this object.
*/
LDAPSearchConstraints getSearchConstraints() {
return m_constraints;
}
/**
* Set the key of the cache entry. The listener needs to know this value
* when the results get processed in the queue. After the results have been
* saved in the vector, then the key and a vector of results are put in
* the cache.
* @param key the key of the cache entry
*/
void setKey(Long key) {
m_key = key;
}
/**
* Get the key of the cache entry.
* @return the key of the cache entry.
*/
Long getKey() {
return m_key;

View File

@@ -0,0 +1,74 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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 {
static final long serialVersionUID = 36890821518462301L;
/**
* LDAPEntry
*/
private LDAPEntry m_entry;
/**
* Constructor
*
* @param msgid message identifier
* @param rsp search operation response
* @param controls array of controls or 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,60 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
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 {
static final long serialVersionUID = -7816778029315223117L;
/**
* A list of LDAP URLs that are referred to.
*/
private String m_URLs[];
/**
* Constructor
*
* @param msgid message identifier
* @param resRef search result reference response
* @param controls array of controls or null
* @see netscape.ldap.LDAPEntry
*/
LDAPSearchResultReference(int msgid, JDAPSearchResultReference resRef, LDAPControl[]controls) {
super(msgid, resRef, controls);
m_URLs = resRef.getUrls();
}
/**
* Returns a list of LDAP URLs that are referred to.
* @return a list of URLs.
*/
public String[] getUrls() {
return m_URLs;
}
}

View File

@@ -0,0 +1,570 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import netscape.ldap.client.*;
import netscape.ldap.client.opers.*;
import java.io.*;
/**
* The results of an LDAP search operation, represented as an enumeration.
* Note that you can only iterate through this enumeration once: if you
* need to use these results more than once, make sure to save the
* results in a separate location.
* <P>
*
* You can also use the results of a search in progress to abandon that search
* operation.
* <P>
*
* @version 1.0
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
* @see netscape.ldap.LDAPConnection#abandon(netscape.ldap.LDAPSearchResults)
*/
public class LDAPSearchResults implements Enumeration, java.io.Serializable {
static final long serialVersionUID = -501692208613904825L;
private Vector entries = null;
private LDAPSearchListener resultSource;
private boolean searchComplete = false;
private LDAPConnection connectionToClose;
private LDAPConnection currConn;
private boolean persistentSearch = false;
private LDAPSearchConstraints currCons;
private String currBase;
private int currScope;
private String currFilter;
private String[] currAttrs;
private boolean currAttrsOnly;
private Vector referralResults = new Vector();
private Vector exceptions;
private int msgID = -1;
// only used for the persistent search
private boolean firstResult = false;
/**
* Constructs an enumeration of search results.
* Note that this does not actually generate the results;
* you need to call <CODE>LDAPConnection.search</CODE> to
* perform the search and get the results.
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
*/
public LDAPSearchResults() {
entries = new Vector();
connectionToClose = null;
searchComplete = true;
currCons = new LDAPSearchConstraints();
}
LDAPSearchResults(LDAPConnection conn, LDAPSearchConstraints cons,
String base, int scope, String filter, String[] attrs, boolean attrsOnly) {
this();
currConn = conn;
currCons = cons;
currBase = base;
currScope = scope;
currFilter = filter;
currAttrs = attrs;
currAttrsOnly = attrsOnly;
}
/**
* Constructs an enumeration of search results. Used when returning results
* from a cache.
* @param v the vector containing LDAPEntries
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
*/
LDAPSearchResults(Vector v) {
this();
entries = (Vector)v.clone();
if ((entries != null) && (entries.size() >= 1)) {
// Each cache value is represented by a vector. The first element
// represents the size of all the LDAPEntries. This needs to be
// removed before we iterate through each LDAPEntry.
entries.removeElementAt(0);
}
}
LDAPSearchResults(Vector v, LDAPConnection conn,
LDAPSearchConstraints cons,
String base, int scope, String filter,
String[] attrs, boolean attrsOnly) {
this(v);
currConn = conn;
currCons = cons;
currBase = base;
currScope = scope;
currFilter = filter;
currAttrs = attrs;
currAttrsOnly = attrsOnly;
}
/**
* 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));
}
}
}
/**
* Add exception
* @param e exception
*/
void add(LDAPException e) {
if (exceptions == null) {
exceptions = new Vector();
}
exceptions.addElement(e);
}
/**
* Prepares to return asynchronous results from a search
* @param l Listener which will provide results
*/
void associate( LDAPSearchListener l) {
resultSource = l;
searchComplete = false;
}
void associatePersistentSearch( LDAPSearchListener l) {
resultSource = l;
persistentSearch = true;
searchComplete = false;
firstResult = true;
}
void addReferralEntries(LDAPSearchResults res) {
referralResults.addElement(res);
}
/**
* For asynchronous search, this mechanism allows the programmer to
* close a connection whenever the search completes.
* @param toClose connection to close when the search terminates
*/
void closeOnCompletion (LDAPConnection toClose) {
if (searchComplete) {
try {
toClose.disconnect();
} catch (LDAPException e) {
}
} else {
connectionToClose = toClose;
}
}
/**
* Basic quicksort algorithm.
*/
void quicksort (LDAPEntry[] toSort, LDAPEntryComparator compare,
int low, int high) {
if (low >= high) {
return;
}
LDAPEntry pivot = toSort[low];
int slow = low-1, shigh = high+1;
while (true) {
do {
shigh--;
} while (compare.isGreater (toSort[shigh], pivot));
do {
slow++;
} while (compare.isGreater (pivot, toSort[slow]));
if (slow >= shigh) {
break;
}
LDAPEntry temp = toSort[slow];
toSort[slow] = toSort[shigh];
toSort[shigh] = temp;
}
quicksort (toSort, compare, low, shigh);
quicksort (toSort, compare, shigh+1, high);
}
/**
* Sets the message ID for this search request. msgID is used
* to retrieve response controls.
* @param msgID Message ID for this search request
*/
void setMsgID(int msgID) {
this.msgID = msgID;
}
/**
* 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 currConn.getResponseControls(msgID);
}
/**
* Sorts the search results.
* <P>
*
* The comparator (<CODE>LDAPEntryComparator</CODE>) determines the
* sort order used. For example, if the comparator uses the <CODE>uid</CODE>
* attribute for comparison, the search results are sorted according to
* <CODE>uid</CODE>.
* <P>
*
* The following section of code sorts results in ascending order,
* first by surname and then by common name.
*
* <PRE>
* String[] sortAttrs = {"sn", "cn"};
* boolean[] ascending = {true, true};
*
* LDAPConnection ld = new LDAPConnection();
* ld.connect( ... );
* LDAPSearchResults res = ld.search( ... );
* res.sort( new LDAPCompareAttrNames(sortAttrs, ascending) );
* </PRE>
* NOTE: If the search results arrive asynchronously, the <CODE>sort</CODE>
* method blocks until all the results are returned.
* <P>
*
* If some of the elements of the Enumeration have already been fetched,
* the cursor is reset to the (new) first element.
* <P>
*
* @param compare comparator used to determine the sort order of the results
* @see LDAPEntryComparator
*/
public synchronized void sort(LDAPEntryComparator compare) {
while (!searchComplete) {
fetchResult();
}
// if automatic referral, then add to the entries, otherwise, dont do it
// since the elements in referralResults are LDAPReferralException.
if (currCons.getReferrals()) {
while (referralResults.size() > 0) {
Object obj = null;
if ((obj=nextReferralElement()) != null) {
entries.addElement(obj);
}
}
}
int numEntries = entries.size();
if (numEntries <= 0) {
return;
}
LDAPEntry[] toSort = new LDAPEntry[numEntries];
entries.copyInto (toSort);
if (toSort.length > 1) {
quicksort (toSort, compare, 0, numEntries-1);
}
entries.removeAllElements();
for (int i = 0; i < numEntries; i++) {
entries.addElement (toSort[i]);
}
}
/**
* Returns the next LDAP entry from the search results
* and throws an exception if the next result is a referral, or
* if a sizelimit or timelimit error occurred.
* <P>
*
* You can use this method in conjunction with the
* <CODE>hasMoreElements</CODE> method to iterate through
* each entry in the search results. For example:
* <PRE>
* LDAPSearchResults res = ld.search( MY_SEARCHBASE,
* LDAPConnection.SCOPE_BASE, MY_FILTER,
* null, false );
* while ( res.hasMoreElements() ) {
* try {
* LDAPEntry findEntry = res.next();
* } catch ( LDAPReferralException e ) {
* LDAPUrl refUrls[] = e.getURLs();
* for ( int i = 0; i < refUrls.length; i++ ) {
* // Your code for handling referrals
* }
* continue;
* } catch ( LDAPException e ) {
* // Your code for handling errors on limits exceeded
* continue;
* }
* ...
* }
* </PRE>
* @return the next LDAP entry in the search results.
* @exception LDAPReferralException A referral (thrown
* if the next result is a referral), or LDAPException
* if a limit on the number of entries or the time was
* exceeded.
* @see netscape.ldap.LDAPSearchResults#hasMoreElements()
*/
public LDAPEntry next() throws LDAPException {
Object o = nextElement();
if ((o instanceof LDAPReferralException) ||
(o instanceof LDAPException)) {
throw (LDAPException)o;
}
if (o instanceof LDAPEntry) {
return (LDAPEntry)o;
}
return null;
}
/**
* Returns the next result from a search. You can use this method
* in conjunction with the <CODE>hasMoreElements</CODE> method to
* iterate through all elements in the search results.
* <P>
*
* Make sure to cast the
* returned element as the correct type. For example:
* <PRE>
* LDAPSearchResults res = ld.search( MY_SEARCHBASE,
* LDAPConnection.SCOPE_BASE, MY_FILTER,
* null, false );
* while ( res.hasMoreElements() ) {
* Object o = res.nextElement();
* if ( o instanceof LDAPEntry ) {
* LDAPEntry findEntry = (LDAPEntry)o;
* ...
* } else if ( o instanceof LDAPReferralException ) {
* LDAPReferralException e = (LDAPReferralException)o;
* LDAPUrl refUrls[] = e.getURLs();
* ...
* } else if ( o instanceof LDAPException ) {
* LDAPException e = (LDAPException)o;
* ...
* }
* }
* </PRE>
* @return the next element in the search results.
* @see netscape.ldap.LDAPSearchResults#hasMoreElements()
*/
public Object nextElement() {
if ( entries.size() > 0 ) {
Object obj = entries.elementAt(0);
entries.removeElementAt(0);
return obj;
}
if (referralResults.size() > 0) {
return nextReferralElement();
}
if ((exceptions != null) && (exceptions.size() > 0)) {
Object obj = exceptions.elementAt(0);
exceptions.removeElementAt(0);
return obj;
}
return null;
}
Object nextReferralElement() {
LDAPSearchResults res =
(LDAPSearchResults)referralResults.elementAt(0);
if ((!res.persistentSearch && res.hasMoreElements()) ||
(res.persistentSearch)) {
Object obj = res.nextElement();
if (obj != null) {
return obj;
}
if ((obj == null) || (!res.hasMoreElements())) {
referralResults.removeElementAt(0);
}
} else {
referralResults.removeElementAt(0);
}
return null;
}
/**
* Returns <CODE>true</CODE> if there are more search results
* to be returned. You can use this method in conjunction with the
* <CODE>nextElement</CODE> or <CODE>next</CODE> methods to iterate
* through each entry in the results. For example:
* <PRE>
* LDAPSearchResults res = ld.search( MY_SEARCHBASE,
* LDAPConnection.SCOPE_BASE, MY_FILTER,
* null, false );
* while ( res.hasMoreElements() ) {
* LDAPEntry findEntry = (LDAPEntry)res.nextElement();
* ...
* }
* </PRE>
* @return <CODE>true</CODE> if there are more search results.
* @see netscape.ldap.LDAPSearchResults#nextElement()
* @see netscape.ldap.LDAPSearchResults#next()
*/
public boolean hasMoreElements() {
while ((entries.size() == 0) && (!searchComplete)) {
fetchResult();
}
if ((entries.size() == 0) &&
((exceptions == null) || (exceptions.size() == 0))) {
while (referralResults.size() > 0) {
LDAPSearchResults res =
(LDAPSearchResults)referralResults.elementAt(0);
if (res.hasMoreElements())
return true;
else
referralResults.removeElementAt(0);
}
}
return ((entries.size() > 0) ||
((exceptions != null) && (exceptions.size() > 0)));
}
/**
* Returns a count of queued search results immediately available for
* processing.
* A search result is either a search entry or an exception. If the
* search is asynchronous (batch size not 0), this reports the number
* of results received so far.
* @return count of search results immediatly available for processing
*/
public int getCount() {
int count = entries.size();
for ( int i = 0; i < referralResults.size(); i++ ) {
LDAPSearchResults res =
(LDAPSearchResults)referralResults.elementAt(i);
count += res.getCount();
}
if ( resultSource != null ) {
count += resultSource.getMessageCount();
}
if ( exceptions != null ) {
count += exceptions.size();
}
return count;
}
/**
* Returns message ID.
* @return Message ID.
*/
int getMessageID() {
if ( resultSource == null ) {
return -1;
}
return resultSource.getMessageID();
}
/**
* Fetchs the next result, for asynchronous searches.
*/
private synchronized void fetchResult() {
/* Asynchronous case */
if ( resultSource != null ) {
synchronized( this ) {
if (searchComplete || firstResult) {
firstResult = false;
return;
}
LDAPMessage msg = null;
try {
msg = resultSource.nextMessage();
} catch (LDAPException e) {
add(e);
currConn.releaseSearchListener(resultSource);
searchComplete = true;
return;
}
if (msg == null) { // Request abandoned
searchComplete = true;
currConn.releaseSearchListener(resultSource);
return;
} else if (msg instanceof LDAPResponse) {
try {
// check response and see if we need to do referral
// v2: referral stored in the JDAPResult
currConn.checkSearchMsg(this, msg, currCons,
currBase, currScope, currFilter,
currAttrs, currAttrsOnly);
} catch (LDAPException e) {
System.err.println("LDAPSearchResults.fetchResult: "+e);
} finally {
currConn.releaseSearchListener(resultSource);
}
searchComplete = true;
if (connectionToClose != null) {
try {
connectionToClose.disconnect ();
} catch (LDAPException e) {
}
connectionToClose = null;
}
return;
} else {
try {
currConn.checkSearchMsg(this, msg, currCons,
currBase, currScope, currFilter, currAttrs, currAttrsOnly);
} catch (LDAPException e) {
System.err.println("Exception: "+e);
}
}
}
}
}
}

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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import java.io.*;
import java.net.*;
/**
* Represents a socket connection that you can use to connect to an
* LDAP server. You can write a class that implements this interface
* if you want to use a TLS socket to connect to a secure server.
* (The <CODE>LDAPSSLSocketFactory class</CODE>, which is included
* in the <CODE>netscape.ldap</CODE> package, implements this
* interface for SSL connections.)
* <P>
*
* When you construct a new <CODE>LDAPConnection</CODE>
* object, you can specify that the connection use this socket.
* To do this, pass the constructor an object of the class that
* implements this interface.
* <P>
*
* @version 1.0
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
* @see LDAPSSLSocketFactory
*/
public interface LDAPSocketFactory {
/**
* Returns a socket to the specified host name and port number.
* <P>
*
* @param host name of the host to which you want to connect
* @param port port number to which you want to connect
* @exception LDAPException Failed to create the socket.
* @see LDAPSSLSocketFactory#makeSocket(java.lang.String,int)
*/
public Socket makeSocket(String host, int port)
throws LDAPException;
}

View File

@@ -0,0 +1,169 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
/**
* Represents sorting instructions for a particular attribute.
*
* @version 1.0
*/
public class LDAPSortKey implements java.io.Serializable {
static final long serialVersionUID = -7044232342344864405L;
public final static int REVERSE = 0x81;
/**
* Constructs a new <CODE>LDAPSortKey</CODE> object that will
* sort based on the specified instructions.
* @param keyDescription a single attribute specification by which to sort
* If preceded by a hyphen ("-"), the attribute is sorted in reverse order.
* You can also specify the object ID (OID) of a matching rule after
* a colon (":"). For example:
* <P>
* <UL>
* <LI><CODE>"cn"</CODE> (sort by the <CODE>cn</CODE> attribute) <P>
* <LI><CODE>"-cn"</CODE> (sort by the <CODE>cn</CODE> attribute in
* reverse order) <P>
* <LI><CODE>"-cn:1.2.3.4"</CODE> (sort by the <CODE>cn</CODE>
* attribute in reverse order and use the matching rule identified
* by the OID 1.2.3.4) <P>
*</UL>
* @see netscape.ldap.controls.LDAPSortControl
* @see netscape.ldap.controls.LDAPVirtualListControl
*/
public LDAPSortKey( String keyDescription ) {
if ( (keyDescription != null) && (keyDescription.length() > 0) ) {
if ( keyDescription.charAt( 0 ) == '-' ) {
m_reverse = true;
m_key = keyDescription.substring( 1 );
} else {
m_reverse = false;
m_key = keyDescription;
}
int colonIndex = m_key.indexOf( ':' );
if ( colonIndex == 0 )
m_key = null;
else if ( colonIndex > 0 ) {
m_matchRule = m_key.substring( colonIndex+1 );
m_key = m_key.substring( 0, colonIndex );
}
}
}
/**
* Constructs a new <CODE>LDAPSortKey</CODE> object that will
* sort based on the specified attribute and sort order.
* @param key a single attribute by which to sort. For example:
* <P>
* <UL>
* <LI><CODE>"cn"</CODE> (sort by the <CODE>cn</CODE> attribute)
* <LI><CODE>"givenname"</CODE> (sort by the <CODE>givenname</CODE>
* attribute)
* </UL>
* @param reverse if <CODE>true</CODE>, the sorting is done in
* descending order
* @see netscape.ldap.controls.LDAPSortControl
* @see netscape.ldap.controls.LDAPVirtualListControl
*/
public LDAPSortKey( String key,
boolean reverse) {
m_key = key;
m_reverse = reverse;
m_matchRule = null;
}
/**
* Constructs a new <CODE>LDAPSortKey</CODE> object that will
* sort based on the specified attribute, sort order, and matching
* rule.
* @param key a single attribute by which to sort. For example:
* <P>
* <UL>
* <LI><CODE>"cn"</CODE> (sort by the <CODE>cn</CODE> attribute)
* <LI><CODE>"givenname"</CODE> (sort by the <CODE>givenname</CODE>
* attribute)
* </UL>
* @param reverse if <CODE>true</CODE>, the sorting is done in
* 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.LDAPSortControl
* @see netscape.ldap.controls.LDAPVirtualListControl
*/
public LDAPSortKey( String key,
boolean reverse,
String matchRule) {
m_key = key;
m_reverse = reverse;
m_matchRule = matchRule;
}
/**
* Returns the attribute by which to sort.
* @return a single attribute by which to sort.
*/
public String getKey() {
return m_key;
}
/**
* Returns <CODE>true</CODE> if sorting is to be done in descending order.
* @return <CODE>true</CODE> if sorting is to be done in descending order.
*/
public boolean getReverse() {
return m_reverse;
}
/**
* Returns the object ID (OID) of the matching rule used for sorting.
* If no matching rule is specified, <CODE>null</CODE> is returned.
* @return the object ID (OID) of the matching rule, or <CODE>null</CODE>
* if the sorting instructions specify no matching rule.
*/
public String getMatchRule() {
return m_matchRule;
}
public String toString() {
StringBuffer sb = new StringBuffer("{SortKey:");
sb.append(" key=");
sb.append(m_key);
sb.append(" reverse=");
sb.append(m_reverse);
if (m_matchRule != null) {
sb.append(" matchRule=");
sb.append(m_matchRule);
}
sb.append("}");
return sb.toString();
}
private String m_key;
private boolean m_reverse;
private String m_matchRule;
}

View File

@@ -0,0 +1,177 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* The definition of a syntax type in the schema.
* <A HREF="http://www.ietf.org/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* LDAP Subschema Attribute</A> covers the types of information
* to specify when defining a syntax.
* The description of a syntax can include the following:
* <P>
*
* <UL>
* <LI>an OID identifying the syntax
* <LI>a description of the attribute type
* </UL>
* <P>
*
* When you construct an <CODE>LDAPSyntaxSchema</CODE> object, you can
* specify these types of information as arguments to the constructor or
* in the ldapSyntaxes format specified in RFC 2252.
* 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.
* <P>
* RFC 2252 defines SyntaxDescription as follows:
* <P>
* <PRE>
* SyntaxDescription = "(" whsp
* numericoid whsp
* [ "DESC" qdstring ]
* whsp ")"
* </PRE>
*<P>
* Syntax definitions do not have a name, so the <CODE>getName</CODE>
* method inherited from <CODE>LDAPSchemaElement</CODE> returns "".
* To get the OID and description of this syntax type
* definition, use the <CODE>getOID</CODE> and
* <CODE>getDescription</CODE> methods inherited from the abstract class
* <CODE>LDAPSchemaElement</CODE>.
* <P>
*
* To add or remove this syntax 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.
*
* @version 1.0
* @see netscape.ldap.LDAPSchemaElement
**/
public class LDAPSyntaxSchema extends LDAPSchemaElement {
static final long serialVersionUID = 3590667117475688132L;
/**
* Constructs a blank element.
*/
protected LDAPSyntaxSchema() {
super();
}
/**
* Constructs a syntax type definition, using the specified
* information.
* @param oid object identifier (OID) of the syntax type
* in dotted-string format (for example, "1.2.3.4")
* @param description description of syntax type
*/
public LDAPSyntaxSchema( String oid, String description ) {
super( "", oid, description );
attrName = "ldapSyntaxes";
syntaxElement.syntax = syntaxElement.syntaxCheck( oid );
syntaxElement.syntaxString = oid;
}
/**
* Constructs a syntax type definition based on a description in
* the ldapSyntaxes format. For information on this format,
* (see <A HREF="http://www.ietf.org/rfc/rfc2252.txt"
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
* LDAP Subschema Attribute</A>. 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 syntaxs "objectclasses" and "ldapSyntaxes". The
* values of "ldapSyntaxes" are syntax type descriptions
* in this format.)
* <P>
*
* @param raw definition of the syntax type in the
* ldapSyntaxes format
*/
public LDAPSyntaxSchema( String raw ) {
attrName = "ldapSyntaxes";
parseValue( raw );
}
/**
* Gets the syntax of the schema element
* @return one of the following values:
* <UL>
* <LI><CODE>cis</CODE> (case-insensitive string)
* <LI><CODE>ces</CODE> (case-exact string)
* <LI><CODE>binary</CODE> (binary data)
* <LI><CODE>int</CODE> (integer)
* <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 syntaxElement.syntax;
}
/**
* Gets the syntax of the syntax type in dotted-decimal format,
* for example "1.2.3.4.5"
* @return The syntax syntax in dotted-decimal format.
*/
public String getSyntaxString() {
return syntaxElement.syntaxString;
}
/**
* Prepares a value in RFC 2252 format for submission to a server
*
* @return a String ready for submission to an LDAP server.
*/
public String getValue() {
String s = getValuePrefix();
String val = getCustomValues();
if ( val.length() > 0 ) {
s += val + ' ';
}
s += ')';
return s;
}
/**
* Gets the definition of the syntax type in a user friendly format.
* This is the format that the syntax type definition uses when
* printing the syntax type or the schema.
* @return definition of the syntax type in a user friendly format.
*/
public String toString() {
String s = "OID: " + oid;
s += "; Description: " + description;
s += getQualifierString( null );
return s;
}
protected LDAPSyntaxSchemaElement syntaxElement =
new LDAPSyntaxSchemaElement();
}

View File

@@ -0,0 +1,153 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
/**
* Helper class supporting schema elements that include syntax
* definitions - attributes and matching rules
*
* @version 1.0
* @see netscape.ldap.LDAPAttributeSchema
* @see netscape.ldap.LDAPMatchingRuleSchema
**/
class LDAPSyntaxSchemaElement extends LDAPSchemaElement {
static final long serialVersionUID = 6086340702503710702L;
/**
* Construct a blank element.
*/
LDAPSyntaxSchemaElement() {
super();
}
/**
* Gets the syntax of the schema element
* @return One of the following values:
* <UL>
* <LI><CODE>cis</CODE> (case-insensitive string)
* <LI><CODE>ces</CODE> (case-exact string)
* <LI><CODE>binary</CODE> (binary data)
* <LI><CODE>int</CODE> (integer)
* <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>
*/
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.
*/
String getSyntaxString() {
return syntaxString;
}
/**
* Convert from enumerated syntax types to an OID
* @param syntax One of the enumerated syntax types
* @return The OID corresponding to the internal type
*/
static String internalSyntaxToString( int syntax ) {
String s;
if ( syntax == cis ) {
s = cisString;
} else if ( syntax == binary ) {
s = binaryString;
} else if ( syntax == ces ) {
s = cesString;
} else if ( syntax == telephone ) {
s = telephoneString;
} else if ( syntax == dn ) {
s = dnString;
} else if ( syntax == integer ) {
s = intString;
} else {
s = null;
}
return s;
}
/**
* Convert from enumerated syntax type to a user-friendly
* string
* @param syntax One of the enumerated syntax types
* @return A user-friendly syntax description
*/
String syntaxToString() {
String s;
if ( syntax == cis ) {
s = "case-insensitive string";
} else if ( syntax == binary ) {
s = "binary";
} else if ( syntax == integer ) {
s = "integer";
} else if ( syntax == ces ) {
s = "case-exact string";
} else if ( syntax == telephone ) {
s = "telephone";
} else if ( syntax == dn ) {
s = "distinguished name";
} else {
s = syntaxString;
}
return s;
}
/**
* Convert from an OID to one of the enumerated syntax types
* @param syntax A dotted-decimal OID
* @return The internal enumerated type corresponding to the
* OID; <CODE>unknown</CODE> if it is not one of the known
* types
*/
int syntaxCheck( String syntax ) {
int i = unknown;
if ( syntax == null ) {
} else if ( syntax.equals( cisString ) ) {
i = cis;
} else if ( syntax.equals( binaryString ) ) {
i = binary;
} else if ( syntax.equals( cesString ) ) {
i = ces;
} else if ( syntax.equals( intString ) ) {
i = integer;
} else if ( syntax.equals( telephoneString ) ) {
i = telephone;
} else if ( syntax.equals( dnString ) ) {
i = dn;
}
return i;
}
int syntax = unknown;
String syntaxString = null;
}

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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
/**
* The <CODE>LDAPTraceWriter</CODE> interface enables logging of LDAP
* trace messages in environments where an OutputStream can not be used.
* <P>
* The interface is primarily meant for integrating LDAP tracing with the
* servlet log facility:
* <P>
* <PRE>
* servletCtx = config.getServletContext();
* ...
* LDAPConnection ld = new LDAPConnection();
* ld.setProperty(ld.TRACE_PROPERTY,
* new LDAPTraceWriter() {
* public void write (String msg) {
* servletCtx.log(msg);
* }
* });
* <PRE>
* <P>
*
* @version 1.0
* @see netscape.ldap.LDAPConnection#setProperty(java.lang.String, java.lang.Object)
*/
public interface LDAPTraceWriter {
/**
* Writes an LDAP trace message.
*
* @param msg An incoming or outgoing LDAP message
*
* @version 1.0
* @see netscape.ldap.LDAPConnection#setProperty(java.lang.String, java.lang.Object)
*/
public void write (String msg);
}

View File

@@ -0,0 +1,668 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import java.io.*;
import java.net.MalformedURLException;
/**
* Represents an LDAP URL. The complete specification for LDAP URLs is in
* <A HREF="http://ds.internic.net/rfc/rfc1959.txt"
* TARGET="_blank">RFC 1959</A>. LDAP URLs have the following format:
*
* <PRE>
* "ldap://" [ <I>hostName</I> [":" <I>portNumber</I>] ] "/"
* <I>distinguishedName</I>
* ["?" <I>attributeList</I> ["?" <I>scope</I>
* "?" <I>filterString</I> ] ]
* </PRE>
* where
* <P>
* <UL>
* <LI>all text within double-quotes are literal<P>
* <LI><CODE><I>hostName</I></CODE> and <CODE><I>portNumber</I></CODE>
* identify the location of the LDAP server.<P>
* <LI><CODE><I>distinguishedName</I></CODE> is the name of an entry
* within the given directory (the entry represents the starting point
* of the search)<P>
* <LI><CODE><I>attributeList</I></CODE> contains a list of attributes
* to retrieve (if null, fetch all attributes). This is a comma-delimited
* list of attribute names.<P>
* <LI><CODE><I>scope</I></CODE> is one of the following:
* <UL>
* <LI><CODE>base</CODE> indicates that this is a search only for the
* specified entry
* <LI><CODE>one</CODE> indicates that this is a search for matching entries
* one level under the specified entry (and not including the entry itself)
* <LI><CODE>sub</CODE> indicates that this is a search for matching entries
* at all levels under the specified entry (including the entry itself)
* </UL>
* <P>
* If not specified, <CODE><I>scope</I></CODE> is <CODE>base</CODE> by
* default. <P>
* <LI><CODE><I>filterString</I></CODE> is a human-readable representation
* of the search criteria. This value is used only for one-level or subtree
* searches.<P>
* </UL>
* <P>
* Note that if <CODE><I>scope</I></CODE> and <CODE><I>filterString</I></CODE>
* are not specified, an LDAP URL identifies exactly one entry in the
* directory. <P>
* The same encoding rules for other URLs (e.g. HTTP) apply for LDAP
* URLs. Specifically, any "illegal" characters are escaped with
* <CODE>%<I>HH</I></CODE>, where <CODE><I>HH</I></CODE> represent the
* two hex digits which correspond to the ASCII value of the character.
* This encoding is only legal (or necessary) on the DN and filter portions
* of the URL.
*
* @version 1.0
*/
public class LDAPUrl implements java.io.Serializable {
static final long serialVersionUID = -3245440798565713640L;
public static String defaultFilter = "(objectClass=*)";
private String hostName;
private int portNumber;
private String DN;
private Vector attributes;
private int scope;
private String filter;
private String URL;
/**
* Constructs a URL object with the specified string as URL.
* @param url LDAP search expression in URL form
* @exception MalformedURLException failed to parse URL
*/
public LDAPUrl (String url) throws java.net.MalformedURLException {
attributes = null;
scope = LDAPv2.SCOPE_BASE;
filter = defaultFilter;
URL = url;
parseUrl(url);
}
/**
* Parse URL as defined in RFC 1959
*/
private void parseUrl(String url) throws MalformedURLException {
StringTokenizer urlParser = new StringTokenizer (url, ":/?", true);
String currentToken;
String str = null;
currentToken = urlParser.nextToken();
if (!currentToken.equalsIgnoreCase ("LDAP"))
throw new MalformedURLException ();
currentToken = urlParser.nextToken();
if (!currentToken.equals(":")) {
throw new MalformedURLException ();
}
currentToken = urlParser.nextToken();
if (!currentToken.equals("/")) {
throw new MalformedURLException ();
}
currentToken = urlParser.nextToken();
if (!currentToken.equals("/")) {
throw new MalformedURLException ();
}
currentToken = urlParser.nextToken();
if (currentToken.equals ("/")) {
hostName = null;
portNumber = LDAPv2.DEFAULT_PORT;
} else {
hostName = currentToken;
if (urlParser.countTokens() == 0) {
portNumber = LDAPv2.DEFAULT_PORT;
return;
}
currentToken = urlParser.nextToken (); // either ":" or "/"
if (currentToken.equals (":")) {
try {
portNumber = Integer.parseInt (urlParser.nextToken());
} catch (NumberFormatException nf) {
throw new MalformedURLException ();
}
if (urlParser.countTokens() == 0) {
return;
}
urlParser.nextToken (); // "/"
} else
portNumber = LDAPv2.DEFAULT_PORT;
}
// DN
if (!urlParser.hasMoreTokens ()) {
return;
}
DN = decode(readNextConstruct(urlParser));
if (DN.equals("?")) {
DN = "";
}
else if (DN.equals("/")) {
throw new MalformedURLException ();
}
// attribute
if (!urlParser.hasMoreTokens ()) {
return;
}
str = readNextConstruct(urlParser);
if (!str.equals("?")) {
StringTokenizer attributeParser = new
StringTokenizer (decode(str), ", ");
attributes = new Vector ();
while (attributeParser.hasMoreTokens()) {
attributes.addElement (attributeParser.nextToken());
}
}
// scope
if (!urlParser.hasMoreTokens ()) {
return;
}
str = readNextConstruct(urlParser);
if (!str.equals("?")) {
scope = getScope(str);
if (scope < 0) {
throw new MalformedURLException("Bad scope:" + str);
}
}
// filter
if (!urlParser.hasMoreTokens ()) {
return;
}
str = readNextConstruct(urlParser);
filter = decode(str);
checkBalancedParentheses(filter);
if (!filter.startsWith("(") && !filter.endsWith(")")) {
filter = "(" + filter + ")";
}
// Nothing after the filter is allowed
if (urlParser.hasMoreTokens()) {
throw new MalformedURLException();
}
}
private void checkBalancedParentheses(String filter) throws MalformedURLException {
int parenCnt =0;
StringTokenizer filterParser = new StringTokenizer (filter, "()", true);
while (filterParser.hasMoreElements()) {
String token = filterParser.nextToken();
if (token.equals("(")) {
parenCnt++;
}
else if (token.equals(")")) {
if (--parenCnt < 0) {
throw new MalformedURLException("Unbalanced filter parentheses");
}
}
}
if (parenCnt != 0) {
throw new MalformedURLException("Unbalanced filter parentheses");
}
}
/**
* Constructs with the specified host, port, and DN. This form is used to
* create URL references to a particular object in the directory.
* @param host host name of the LDAP server, or null for "nearest X.500/LDAP"
* @param port port number of the LDAP server (use LDAPv2.DEFAULT_PORT for
* the default port)
* @param DN distinguished name of the object
*/
public LDAPUrl (String host, int port, String DN) {
if (host != null) {
if (port != LDAPv2.DEFAULT_PORT)
URL = "LDAP://" + host + ":" + String.valueOf (port) +
"/" + encode (DN);
else
URL = "LDAP://" + host + "/" + encode (DN);
} else
URL = "LDAP:///" + encode (DN);
this.hostName = host;
this.DN = DN;
portNumber = port;
filter = defaultFilter;
attributes = null;
scope = LDAPv2.SCOPE_BASE;
}
/**
* Constructs a full-blown LDAP URL to specify an LDAP search operation.
* @param host host name of the LDAP server, or null for "nearest X.500/LDAP"
* @param port port number of the LDAP server (use LDAPv2.DEFAULT_PORT for
* the default port)
* @param DN distinguished name of the object
* @param attributes list of attributes to return. Use null for "all
* attributes."
* @param scope depth of search (in DN namespace). Use one of the LDAPv2 scopes:
* SCOPE_BASE, SCOPE_ONE, or SCOPE_SUB.
* @param filter LDAP filter string (as defined in RFC 1558). Use null for
* no filter (this effectively makes the URL reference a single object).
*/
public LDAPUrl (String host, int port, String DN,
String attributes[], int scope, String filter) {
if (attributes != null) {
Vector list = new Vector();
for (int k = 0; k < attributes.length; k++) {
list.addElement(attributes[k]);
}
initialize(host, port, DN, list.elements(), scope, filter);
} else {
initialize(host, port, DN, null, scope, filter);
}
}
/**
* Constructs a full-blown LDAP URL to specify an LDAP search operation.
* @param host host name of the LDAP server, or null for "nearest X.500/LDAP"
* @param port port number of the LDAP server (use LDAPv2.DEFAULT_PORT for
* the default port)
* @param DN distinguished name of the object
* @param attributes list of the attributes to return. Use null for "all
* attributes."
* @param scope depth of the search (in DN namespace). Use one of the LDAPv2 scopes:
* SCOPE_BASE, SCOPE_ONE, or SCOPE_SUB.
* @param filter LDAP filter string (as defined in RFC 1558). Use null for
* no filter (this effectively makes the URL reference a single object).
*/
public LDAPUrl (String host, int port, String DN,
Enumeration attributes, int scope, String filter) {
initialize(host, port, DN, attributes, scope, filter);
}
/**
* Initializes URL object.
*/
private void initialize (String host, int port, String DN,
Enumeration attributes, int scope, String filter) {
this.hostName = host;
this.DN = DN;
portNumber = port;
this.filter = (filter != null) ? filter : defaultFilter;
this.scope = scope;
if (attributes != null) {
this.attributes = new Vector ();
while (attributes.hasMoreElements()) {
this.attributes.addElement (attributes.nextElement());
}
} else
this.attributes = null;
StringBuffer url = new StringBuffer ("LDAP://");
if (host != null) {
url.append (host);
if (port != LDAPv2.DEFAULT_PORT) {
url.append (':');
url.append (String.valueOf (port));
}
}
url.append ('/');
url.append (encode (DN));
if (attributes != null) {
url.append ('?');
Enumeration attrList = this.attributes.elements();
boolean firstElement = true;
while (attrList.hasMoreElements()) {
if (!firstElement)
url.append (',');
else
firstElement = false;
url.append ((String)attrList.nextElement());
}
}
if (filter != null) {
if (attributes == null)
url.append ('?');
url.append ('?');
switch (scope) {
default:
case LDAPv2.SCOPE_BASE:
url.append ("base"); break;
case LDAPv2.SCOPE_ONE:
url.append ("one"); break;
case LDAPv2.SCOPE_SUB:
url.append ("sub"); break;
}
url.append ('?');
url.append (filter);
}
URL = url.toString();
}
/**
* Return the host name of the LDAP server
* @return LDAP host.
*/
public String getHost () {
return hostName;
}
/**
* Return the port number for the LDAP server
* @return port number.
*/
public int getPort () {
return portNumber;
}
/**
* Return the distinguished name encapsulated in the URL
* @return target distinguished name.
*/
public String getDN () {
return DN;
}
/**
* Return the collection of attributes specified in the URL, or null
* for "every attribute"
* @return enumeration of attributes.
*/
public Enumeration getAttributes () {
if (attributes == null)
return null;
else
return attributes.elements();
}
/**
* Return the collection of attributes specified in the URL, or null
* for "every attribute"
* @return string array of attributes.
*/
public String[] getAttributeArray () {
if (attributes == null)
return null;
else {
String[] attrNames = new String[attributes.size()];
Enumeration attrs = getAttributes();
int i = 0;
while (attrs.hasMoreElements())
attrNames[i++] = (String)attrs.nextElement();
return attrNames;
}
}
/**
* Returns the scope of the search, according to the values
* SCOPE_BASE, SCOPE_ONE, SCOPE_SUB as defined in LDAPv2. This refers
* to how deep within the directory namespace the search will look
* @return search scope.
*/
public int getScope () {
return scope;
}
/**
* Returns the scope of the search. If the scope returned is -1, then
* the given string is not for the scope.
* @param str the string against which to compare the scope type
* @returns the scope of the search, -1 is returned if the given string is
* not SUB, ONE or BASE (the acceptable LDAPv2 values for scope).
*/
private int getScope(String str) {
int s = -1;
if (str.equalsIgnoreCase("base"))
s = LDAPv2.SCOPE_BASE;
else if (str.equalsIgnoreCase("one"))
s = LDAPv2.SCOPE_ONE;
else if (str.equalsIgnoreCase("sub"))
s = LDAPv2.SCOPE_SUB;
return s;
}
/**
* Returns the search filter (RFC 1558), or the default if none was
* specified.
* @return the search filter.
*/
public String getFilter () {
return filter;
}
/**
* Returns a valid string representation of this LDAP URL.
* @return the LDAP search expression in URL form.
*/
public String getUrl () {
return URL;
}
/**
* Reads next construct from the given string parser.
* @param parser the string parser
* @return the next construct which can be an attribute, scope or filter.
* @exception java.net.MalformedURLException Get thrown when the url format
* is incorrect.
*/
private String readNextConstruct(StringTokenizer parser) throws
MalformedURLException {
try {
if (parser.hasMoreTokens()) {
String tkn = parser.nextToken();
if (tkn.equals("?")) { // empty construct
return tkn;
}
else if (parser.hasMoreTokens()){
// Remove '?' delimiter
String delim = parser.nextToken();
if (!delim.equals("?")) {
throw new MalformedURLException();
}
}
return tkn;
}
} catch (NoSuchElementException e) {
throw new MalformedURLException();
}
return null;
}
/**
* Parses hex character into integer.
*/
private static int hexValue (char hexChar) throws MalformedURLException {
if (hexChar >= '0' && hexChar <= '9')
return hexChar - '0';
if (hexChar >= 'A' && hexChar <= 'F')
return hexChar - 'A' + 10;
if (hexChar >= 'a' && hexChar <= 'f')
return hexChar - 'a' + 10;
throw new MalformedURLException ();
}
private static char hexChar (int hexValue) {
if (hexValue < 0 || hexValue > 0xF)
return 'x';
if (hexValue < 10)
return (char)(hexValue + '0');
return (char)((hexValue - 10) + 'a');
}
/**
* Decodes a URL-encoded string. Any occurences of %HH are decoded to the
* hex value represented. However, this routine does NOT decode "+"
* into " ". See RFC 1738 for full details about URL encoding/decoding.
* @param URLEncoded a segment of a URL which was encoded using the URL
* encoding rules
* @exception MalformedURLException failed to parse URL
*/
public static String decode (String URLEncoded) throws
MalformedURLException {
StringBuffer decoded = new StringBuffer (URLEncoded);
int srcPos = 0, dstPos = 0;
try {
while (srcPos < decoded.length()) {
if (decoded.charAt (srcPos) != '%') {
if (srcPos != dstPos)
decoded.setCharAt (dstPos, decoded.charAt (srcPos));
srcPos++;
dstPos++;
continue;
}
decoded.setCharAt (dstPos, (char)
((hexValue(decoded.charAt (srcPos+1))<<4) |
(hexValue(decoded.charAt (srcPos+2)))));
dstPos++;
srcPos += 3;
}
} catch (StringIndexOutOfBoundsException sioob) {
// Indicates that a "%" character occured without the following HH
throw new MalformedURLException ();
}
/* 070497 Url problems submitted by Netscape */
/* decoded.setLength (dstPos+1); */
decoded.setLength (dstPos);
return decoded.toString ();
}
/**
* Encodes an arbitrary string. Any illegal characters are encoded as
* %HH. However, this routine does NOT decode "+" into " " (this is a HTTP
* thing, not a general URL thing). Note that, because Sun's URLEncoder
* does do this encoding, we can't use it.
* See RFC 1738 for full details about URL encoding/decoding.
* @param toEncode an arbitrary string to encode for embedding within a URL
*/
public static String encode (String toEncode) {
StringBuffer encoded = new StringBuffer (toEncode.length()+10);
for (int currPos = 0; currPos < toEncode.length(); currPos++) {
char currChar = toEncode.charAt (currPos);
if ((currChar >= 'a' && currChar <= 'z') ||
(currChar >= 'A' && currChar <= 'Z') ||
(currChar >= '0' && currChar <= '9') ||
("$-_.+!*'(),".indexOf (currChar) > 0)) {
// this is the criteria for "doesn't need to be encoded" (whew!)
encoded.append (currChar);
} else {
encoded.append ("%");
encoded.append (hexChar ((currChar & 0xF0) >> 4));
encoded.append (hexChar (currChar & 0x0F));
}
}
return encoded.toString();
}
/**
* Returns the URL in String format
*
* @return the URL in String format
*/
public String toString() {
return getUrl();
}
/**
* Reports if the two objects represent the same URL
*
* @param url the object to be compared to
* @return <CODE>true</CODE> if the two are equivalent
*/
public boolean equals( LDAPUrl url ) {
if ( getHost() == null ) {
if ( url.getHost() != null ) {
return false;
}
} else if ( !getHost().equals( url.getHost() ) ) {
return false;
}
if ( getPort() != url.getPort() ) {
return false;
}
if ( getDN() == null ) {
if ( url.getDN() != null ) {
return false;
}
} else if ( !getDN().equals( url.getDN() ) ) {
return false;
}
if ( getFilter() == null ) {
if ( url.getFilter() != null ) {
return false;
}
} else if ( !getFilter().equals( url.getFilter() ) ) {
return false;
}
if ( getScope() != url.getScope() ) {
return false;
}
if ( attributes == null ) {
if ( url.attributes != null ) {
return false;
}
} else if ( attributes.size() != url.attributes.size() ) {
return false;
} else {
for( int i = 0; i < attributes.size(); i++ ) {
if ( attributes.elementAt( i ) !=
url.attributes.elementAt( i ) ) {
return false;
}
}
}
return true;
}
}

View File

@@ -0,0 +1,483 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import java.io.*;
/**
* This interface summarizes the basic functionality available in the
* Lightweight Directory Access Protocol (LDAP) version 2. (See
* <A HREF="http://www.cis.ohio-state.edu/htbin/rfc/rfc1777.html" TARGET="_blank">RFC 1777</A>
* for the definition of the protocol.)
* <P>
*
* In the general model for this protocol, objects exist under a directory
* in a particular server. Objects are identified by unique, hierarchical names
* called Distinguished Names, commonly abreviated "DN". An example of a DN:
* <pre>
* cn=Barbara Jensen,ou=Product Development,o=Ace Industry,c=us
* </pre>
* Objects have attributes, of the form
* <pre>
* attributeName = attributeValue(s)
* </pre>
* Attribute names must be Strings, and attribute values can be any 8-bit
* sequence (Strings or binary values).
*
* @version 1.0
*/
public interface LDAPv2 {
/**
* The default port number for LDAP servers. You can specify
* this identifier when calling the <CODE>LDAPConnection.connect</CODE>
* method to connect to an LDAP server.
* @see netscape.ldap.LDAPConnection#connect
*/
public final static int DEFAULT_PORT = 389;
/**
* Option specifying how aliases are dereferenced.
* <P>
*
* This option can have one of the following values:
* <UL>
* <LI><A HREF="#DEREF_NEVER"><CODE>DEREF_NEVER</CODE></A>
* <LI><A HREF="#DEREF_FINDING"><CODE>DEREF_FINDING</CODE></A>
* <LI><A HREF="#DEREF_SEARCHING"><CODE>DEREF_SEARCHING</CODE></A>
* <LI><A HREF="#DEREF_ALWAYS"><CODE>DEREF_ALWAYS</CODE></A>
* </UL>
* <P>
*
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int DEREF = 2;
/**
* Option specifying the maximum number of search results to
* return.
* <P>
*
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int SIZELIMIT = 3;
/**
* Option specifying the maximum number of milliseconds to
* wait for an operation to complete.
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int TIMELIMIT = 4;
/**
* Option specifying the maximum number of milliseconds the
* server should spend returning search results before aborting
* the search.
* @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.
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
* @see netscape.ldap.LDAPRebind
* @see netscape.ldap.LDAPRebindAuth
*/
public static final int REFERRALS = 8;
/**
* Option specifying the object containing the method for
* getting authentication information (the distinguished name
* and password) used during a referral. For example, when
* referred to another LDAP server, your client uses this object
* to obtain the DN and password. Your client authenticates to
* the LDAP server using this DN and password.
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
* @see netscape.ldap.LDAPRebind
* @see netscape.ldap.LDAPRebindAuth
*/
public static final int REFERRALS_REBIND_PROC = 9;
/**
* Option specifying the maximum number of referrals to follow
* in a sequence when requesting an LDAP operation.
* @see netscape.ldap.LDAPConnection#getOption
* @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
* used by your client when interacting with the LDAP server.
* If no version is set, the default version is 2. If you
* are planning to use LDAP v3 features (such as controls
* or extended operations), you should set this version to 3
* or specify version 3 as an argument to the <CODE>authenticate</CODE>
* method of the <CODE>LDAPConnection</CODE> object.
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
* @see netscape.ldap.LDAPConnection#authenticate(int, java.lang.String, java.lang.String)
*/
public static final int PROTOCOL_VERSION = 17;
/**
* Option specifying the number of results to return at a time.
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int BATCHSIZE = 20;
/*
* Valid options for Scope
*/
/**
* Specifies that the scope of a search includes
* only the base DN (distinguished name).
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
*/
public static final int SCOPE_BASE = 0;
/**
* Specifies that the scope of a search includes
* only the entries one level below the base DN (distinguished name).
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints) */
public static final int SCOPE_ONE = 1;
/**
* Specifies that the scope of a search includes
* the base DN (distinguished name) and all entries at all levels
* beneath that base.
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints) */
public static final int SCOPE_SUB = 2;
/*
* Valid options for Dereference
*/
/**
* Specifies that aliases are never dereferenced.
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int DEREF_NEVER = 0;
/**
* Specifies that aliases are dereferenced when searching the
* entries beneath the starting point of the search (but
* not when finding the starting entry).
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int DEREF_SEARCHING = 1;
/**
* Specifies that aliases are dereferenced when finding the
* starting point for the search (but not when searching
* under that starting entry).
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int DEREF_FINDING = 2;
/**
* Specifies that aliases are always dereferenced.
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int DEREF_ALWAYS = 3;
/**
* Connects to the LDAP server.
* @param host hostname of the LDAP server
* @param port port number of the LDAP server. To specify the
* default port, use <CODE>DEFAULT_PORT</CODE>.
* @exception LDAPException Failed to connect to the server.
*/
public void connect (String host, int port) throws LDAPException;
/**
* Connects and authenticates to the LDAP server.
* @param host hostname of the LDAP server
* @param port port number of the LDAP server. To specify the
* default port, use <CODE>DEFAULT_PORT</CODE>.
* @param dn distinguished name to use for authentication
* @param passwd password for authentication
* @exception LDAPException Failed to connect and authenticate to the server.
*/
public void connect (String host, int port, String dn, String passwd)
throws LDAPException;
/**
* Disconnects from the LDAP server. Subsequent operational calls
* will first try to re-establish the connection to the same LDAP server.
* @exception LDAPException Failed to disconnect from the server.
*/
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
* @param passwd password for authentication
* @exception LDAPException Failed to authenticate to the server.
*/
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
* @exception LDAPException Failed to retrieve the specified entry.
*/
public LDAPEntry read (String DN) throws LDAPException;
/**
* Read the entry corresponding to the specified distinguished name (DN),
* and retrieve only the specified attributes.
* @param DN distinguished name of the entry to retrieve
* @param attrs names of attributes to retrieve
* @exception LDAPException Failed to retrieve the specified entry.
*/
public LDAPEntry read (String DN, String attrs[]) throws LDAPException;
/**
* Read the entry corresponding to the specified distinguished name (DN),
* and retrieve only the specified attributes.
* @param DN distinguished name of the entry to retrieve
* @param attrs names of attributes to retrieve
* @param cons the constraints set for the read operation
* @exception LDAPException Failed to retrieve the specified entry.
*/
public LDAPEntry read (String DN, String attrs[], LDAPSearchConstraints cons)
throws LDAPException;
/**
* Searches for entries in the directory.
* @param base starting point for the search in the directory
* (distinguished name)
* @param scope indicates whether the scope of the search includes
* only the base DN (equivalent to a read operation), only the entries
* one level below the base DN, or all entries at all levels beneath
* the base DN (including the base DN itself)
* @param filter String which describes the search criteria. The format
* of the string is described fully in
* <A HREF="http://www.cis.ohio-state.edu/htbin/rfc/rfc1558.html" TARGET="_blank">RFC 1558</A>.
* @param attrs names of the attributes to return for each matching
* directory entry. If <CODE>null</CODE>, all attributes are returned.
* @param attrsOnly if <CODE>true</CODE>, the search will return only the names of
* the attributes (and not their values)
* @exception LDAPException Failed to complete the requested search.
*/
public LDAPSearchResults search (String base, int scope, String filter,
String[] attrs, boolean attrsOnly) throws LDAPException;
/**
* Searches for entries in the directory.
* @param base starting point for the search in the directory
* (distinguished name)
* @param scope indicates whether the scope of the search includes
* only the base DN (equivalent to a read operation), only the entries
* one level below the base DN, or all entries at all levels beneath
* the base DN (including the base DN itself)
* @param filter String which describes the search criteria. The format
* of the string is described fully in
* <A HREF="http://www.cis.ohio-state.edu/htbin/rfc/rfc1558.html" TARGET="_blank">RFC 1558</A>.
* @param attrs names of the attributes to return for each matching
* directory entry. If <CODE>null</CODE>, all attributes are returned.
* @param attrsOnly if <CODE>true</CODE>, the search will return only the names of
* the attributes (and not their values)
* @param cons constraints specific to the search (for example, the maximum number
* of entries to return or the maximum time to wait for the search operation to complete)
* @exception LDAPException Failed to complete the requested search.
*/
public LDAPSearchResults search (String base, int scope, String filter,
String[] attrs, boolean attrsOnly, LDAPSearchConstraints cons)
throws LDAPException;
/**
* Compares the given entry's attribute value to the specified
* attribute value.
* @param DN distinguished name of the entry that you want compared
* against the specified attribute value
* @param attr attribute name and value to use in the comparison
* @exception LDAPException Failed to perform the comparison.
*/
public boolean compare (String DN, LDAPAttribute attr) throws LDAPException;
/**
* Compares the given entry's attribute value to the specified
* attribute value.
* @param DN distinguished name of the entry that you want compared
* against the specified attribute value
* @param attr attribute name and value to use in the comparison
* @param cons the constraints set for the compare operation
* @exception LDAPException Failed to perform the comparison.
*/
public boolean compare (String DN, LDAPAttribute attr,
LDAPConstraints cons) throws LDAPException;
/**
* Adds an entry to the directory.
* @param entry new entry to add to the directory
* @exception LDAPException Failed to add the entry to the directory.
*/
public void add (LDAPEntry entry) throws LDAPException;
/**
* Adds an entry to the directory.
* @param entry new entry to add to the directory
* @param cons the constraints set for the add operation
* @exception LDAPException Failed to add the entry to the directory.
*/
public void add (LDAPEntry entry, LDAPConstraints cons)
throws LDAPException;
/**
* Modifies an attribute of a directory entry.
* @param DN distinguished name identifying the entry to modify
* @param mod the modification to make
* @exception LDAPException Failed to modify the specified entry.
*/
public void modify (String DN, LDAPModification mod) throws LDAPException;
/**
* Modifies an attribute of a directory entry.
* @param DN distinguished name identifying the entry to modify
* @param mod the modification to make
* @param cons the constraints set for the modify operation
* @exception LDAPException Failed to modify the specified entry.
*/
public void modify (String DN, LDAPModification mod,
LDAPConstraints cons) throws LDAPException;
/**
* Modifies the attributes of a directory entry.
* @param DN distinguished name identifying the entry to modify
* @param mod list of the modifications to make
* @exception LDAPException Failed to modify the specified entry.
*/
public void modify (String DN, LDAPModificationSet mods ) throws LDAPException;
/**
* Modifies the attributes of a directory entry.
* @param DN distinguished name identifying the entry to modify
* @param mod list of the modifications to make
* @param cons the constraints set for the modify operation
* @exception LDAPException Failed to modify the specified entry.
*/
public void modify (String DN, LDAPModificationSet mods,
LDAPConstraints cons ) throws LDAPException;
/**
* Removes an entry from the directory.
* @param DN distinguished name identifying the entry to remove
* @exception LDAPException Failed to remove the entry from the directory.
*/
public void delete( String DN ) throws LDAPException;
/**
* Removes an entry from the directory.
* @param DN distinguished name identifying the entry to remove
* @param cons the constraints set for the delete operation
* @exception LDAPException Failed to remove the entry from the directory.
*/
public void delete( String DN, LDAPConstraints cons )
throws LDAPException;
/**
* Changes the name of an entry in the directory.
* @param DN distinguished name (DN) of entry
* @param newRDN the new relative distinguished name (RDN) of the entry
* @param deleteOldRDN <CODE>true</CODE> if the original RDN should no longer
* be an attribute of the entry; <CODE>false</CODE> if it should
* @exception LDAPException Failed to rename the entry in the directory.
*/
public void rename ( String DN, String newRDN, boolean deleteOldRDN )
throws LDAPException;
/**
* Changes the name of an entry in the directory.
* @param DN distinguished name (DN) of entry
* @param newRDN new relative distinguished name (RDN) of the entry
* @param deleteOldRDN specifies whether or not the original RDN remains
* as an attribute of the entry. If <CODE>true</CODE>, the original RDN
* is no longer an attribute of the entry.
* @param cons the constraints set for the rename operation
* @exception LDAPException Failed to rename the entry in the directory.
*/
public void rename ( String DN, String newRDN, boolean deleteOldRDN,
LDAPConstraints cons ) throws LDAPException;
/**
* Retrieves an option that applies to the connection.
* The particular meaning may be implementation-dependent.
* 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;
/**
* Sets an option that applies to the connection.
* The particular meaning may be implementation-dependent.
* 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

@@ -0,0 +1,197 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap;
import java.util.*;
import netscape.ldap.client.*;
import netscape.ldap.client.opers.*;
import java.io.*;
/**
* Specifies additional features available in version 3 of the
* LDAP protocol. (To view preliminary information on this work
* in progress, see the LDAP v3 internet draft. You can find the
* latest version of this document listed under the Internet-Drafts
* section of the
* <A HREF="http://www.ietf.cnri.reston.va.us/html.charters/asid-charter.html"
* TARGET=_blank">ASID home page</A>.)
*
* @version 1.0
*/
public interface LDAPv3 extends LDAPv2 {
/**
* Connects and authenticates to the LDAP server using the specified version of the
* LDAP protocol.
* @param version requested version of the LDAP protocol: currently 2 or 3
* @param host hostname of the LDAP server
* @param port port number of the LDAP server. To specify the
* default port, use <CODE>DEFAULT_PORT</CODE>.
* @param dn distinguished name to use for authentication
* @param passwd password for authentication
* @exception LDAPException Failed to connect and authenticate to the server.
*/
public void connect(int version, String host, int port, String dn,
String passwd) throws LDAPException;
/**
* Authenticates to the LDAP server (to which the object is currently
* connected) using the specified name, password, and version
* of the LDAP protocol. 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 requested LDAP protocol version: currently 2 or 3.
* @param dn if non-null and non-empty, specifies that the
* connection and all operations through it should
* authenticate with dn as the distinguished name
* @param passwd if non-null and non-empty, specifies that the
* connection and all operations through it should
* authenticated with passwd as password
* @exception LDAPException Failed to authenticate to the LDAP server.
*/
public void authenticate(int version,
String dn,
String passwd)
throws LDAPException;
/**
* Authenticates to the LDAP server (to which the object is currently
* connected) using the specified name, password, and version of the
* LDAP protocol. If the server does not support the requested
* version of the protocol, 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 requested LDAP protocol version: currently 2 or 3.
* @param dn if non-null and non-empty, specifies that the
* connection and all operations through it should authenticate
* with dn as the distinguished name
* @param passwd if non-null and non-empty, specifies that the
* connection and all operations through it should authenticate
* 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.
* <P>
*
* @param op LDAPExtendedOperation object specifying the OID of the
* extended operation and the data to use in the operation
* @exception LDAPException Failed to execute the operation
* @return LDAPExtendedOperation object representing the extended response
* returned by the server.
* @see LDAPExtendedOperation
*/
public LDAPExtendedOperation extendedOperation( LDAPExtendedOperation op )
throws LDAPException;
/**
* Renames and moves an entry in the directory.
* @param DN original distinguished name (DN) for the entry
* @param newRDN new relative distinguished name (RDN) for the entry
* @param newParentDN distinguished name of the new parent entry of the
* specified entry
* @param deleteOldRDN specifies whether or not to remove the old RDN
* when renaming and moving the entry. If <code>true</code>, the old RDN will be deleted.
* @exception LDAPException Failed to rename the specified entry.
*/
public void rename( String DN, String newRDN, String newParentDN,
boolean deleteOldRDN ) throws LDAPException;
/**
* Renames and moves an entry in the directory.
* @param DN original distinguished name (DN) for the entry
* @param newRDN new relative distinguished name (RDN) for the entry
* @param newParentDN distinguished name of the new parent entry of the
* specified entry
* @param deleteOldRDN specifies whether or not to remove the old RDN
* when renaming and moving the entry. If <code>true</code>, the old RDN will be deleted.
* @param cons the constraints set for the rename operation
* @exception LDAPException Failed to rename the specified entry.
*/
public void rename( String DN, String newRDN, String newParentDN,
boolean deleteOldRDN, LDAPConstraints cons ) throws LDAPException;
/**
* Returns an array of the latest controls (if any) from the server.
* @return an array of the controls returned by an operation,
* or <CODE>null</CODE> if none.
* @see netscape.ldap.LDAPControl
*/
public LDAPControl[] getResponseControls();
/**
* Option specifying client controls for LDAP operations. These
* controls are interpreted by the client and are not passed
* to the LDAP server.
* @see netscape.ldap.LDAPControl
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int CLIENTCONTROLS = 11;
/**
* Option specifying server controls for LDAP operations. These
* controls are passed to the LDAP server. They may also be returned by
* the server.
* @see netscape.ldap.LDAPControl
* @see netscape.ldap.LDAPConnection#getOption
* @see netscape.ldap.LDAPConnection#setOption
*/
public static final int SERVERCONTROLS = 12;
/**
* Attribute type that you can specify in the LDAPConnection
* search method if you don't want to retrieve any of the
* attribute types for entries found by the search.
* @see netscape.ldap.LDAPConnection#search
*/
public static final String NO_ATTRS = "1.1";
/**
* Attribute type that you can specify in the LDAPConnection
* search method if you want to retrieve all attribute types.
* You can use this if you want to retrieve all attributes in
* addition to an operational attribute. For example:
* <P>
*
* <PRE>
* ...
* String [] MY_ATTRS = { LDAPv3.ALL_USER_ATTRS, "modifiersName",
* "modifyTimestamp" };
* LDAPSearchResults res = ld.search( MY_SEARCHBASE,
* LDAPConnection.SCOPE_SUB, MY_FILTER, MY_ATTRS, false, cons );
* ...
* </PRE>
* @see netscape.ldap.LDAPConnection#search
*/
public static final String ALL_USER_ATTRS = "*";
}

View File

@@ -0,0 +1,91 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* 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 that of the particular implementation.
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
*/
public class BERAny extends BERElement {
/**
* Internal variables
*/
private BERElement m_value = null;
/**
* Constructs an "any" element.
* @param value BERElement value
*/
public BERAny(BERElement value) {
m_value = value;
}
/**
* 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
* @exception IOException failed to construct
*/
public BERAny(BERTagDecoder decoder, InputStream stream,
int[] bytes_read) throws IOException {
m_value = getElement(decoder, stream, bytes_read);
}
/**
* Sends the BER encoding directly to an output stream.
* @param stream output stream
*/
public void write(OutputStream stream) throws IOException {
m_value.write(stream);
}
/**
* Gets the element type.
* @param element type
*/
public int getType() {
return BERElement.ANY;
}
/**
* Gets the string representation.
* @return string representation of tag.
*/
public String toString() {
return "ANY {" + m_value + "}";
}
}

View File

@@ -0,0 +1,283 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.ber.stream;
import java.util.*;
import java.util.BitSet;
import java.io.*;
/**
* This class is for the BitString object. Note that the BitSet class
* has a bug: size() returns the size of the internal allocated memory
* rather than the number of bits. Current work-around is to maintain
* 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
*/
public class BERBitString extends BERElement {
/**
* Internal variables
*/
private BitSet m_value;
private int m_value_num_bits;
/**
* Constructs a boolean element.
* @param value boolean value
*/
public BERBitString(BitSet value) {
m_value = value;
}
/**
* Constructs a bitstring element from an input stream
* (for constructed encodings).
* @param stream source
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
* @exception IOException failed to construct
*/
public BERBitString(BERTagDecoder decoder, InputStream stream,
int[] bytes_read) throws IOException {
int octet;
int contents_length = super.readLengthOctets(stream, bytes_read);
int[] component_length = new int[1];
BERElement element = null;
if (contents_length == -1) {
/* Constructed - indefinite length. */
{
component_length[0] = 0;
element = getElement(decoder,stream,component_length);
if (element != null) {
/* element is a bitstring - add it to the existing BitSet */
BERBitString bit_string_element = (BERBitString)element;
BitSet new_bit_set = new BitSet(m_value_num_bits +
bit_string_element.getSize());
for (int i = 0; i<m_value_num_bits; i++)
if (m_value.get(i))
new_bit_set.set(i);
for (int j = 0; j<bit_string_element.getSize(); j++)
if (bit_string_element.getValue().get(j))
new_bit_set.set(m_value_num_bits+j);
m_value = new_bit_set;
m_value_num_bits += bit_string_element.getSize();
}
} while (element != null);
} else {
/* Constructed - definite length */
bytes_read[0] += contents_length;
while (contents_length > 0) {
component_length[0] = 0;
element = getElement(decoder,stream,component_length);
if (element != null) {
/* element is a bitstring - add it to the existing BitSet */
BERBitString bit_string_element = (BERBitString)element;
BitSet new_bit_set = new BitSet(m_value_num_bits +
bit_string_element.getSize());
for (int i = 0; i<m_value_num_bits; i++)
if (m_value.get(i))
new_bit_set.set(i);
for (int j = 0; j<bit_string_element.getSize(); j++)
if (bit_string_element.getValue().get(j))
new_bit_set.set(m_value_num_bits+j);
m_value = new_bit_set;
m_value_num_bits += bit_string_element.getSize();
}
contents_length -= component_length[0];
}
}
}
/**
* Constructs a bitstring element from an input stream
* (for primitive encodings).
* @param stream source
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
* @exception IOException failed to construct
*/
public BERBitString(InputStream stream, int[] bytes_read)
throws IOException {
/* Primitive - definite length content octets string. */
int octet;
int contents_length = super.readLengthOctets(stream, bytes_read);
/* First content octect doesn't encode any of
* the string - it encodes the number of unused
* bits in the final content octet.
*/
int last_unused_bits = stream.read();
bytes_read[0]++;
contents_length--;
m_value_num_bits = ((contents_length-1)*8) + (8-last_unused_bits);
m_value = new BitSet();
int bit_num = 0;
for (int i = 0; i < contents_length-1; i++) {
octet = stream.read();
int mask = 0x80;
for (int j = 0; j < 8; j++) {
if ((octet & mask) > 0) {
m_value.set(bit_num);
}
else
m_value.clear(bit_num);
bit_num++;
mask = mask / 2;
}
}
octet = stream.read(); /* last content octet */
int mask = 0x80;
for (int j = 0; j < 8-last_unused_bits; j++) {
if ((octet & mask) > 0)
m_value.set(bit_num);
else
m_value.clear(bit_num);
bit_num++;
mask = mask / 2;
}
bytes_read[0] += contents_length;
}
/**
* Sends the BER encoding directly to a stream.
* Always sends in primitive form.
* @param stream output stream
*/
public void write(OutputStream stream) throws IOException {
stream.write(BERElement.BITSTRING);
//int num_bits = m_value.size(); /* number of bits to send */
int num_bits = m_value_num_bits;
/* Number of bits unused int the last contents octet */
int last_unused_bits = 8 - (num_bits % 8);
/* Figure out the number of content octets */
int num_content_octets = (int)(num_bits/8) + 1;
if (last_unused_bits > 0)
num_content_octets += 1;
stream.write(num_content_octets); /* length octet */
stream.write(last_unused_bits); /* first content octet */
for (int i = 0; i < (int)(num_bits/8); i++) {
int new_octet = 0;
int bit = 0x80;
for (int j = 0; j < 8; j++) {
if (m_value.get(i*8+j))
new_octet += bit;
bit = bit/2;
}
stream.write(new_octet);
}
/*
* Last octet may not use all bits. If last octet DOES use all
* bits then it has already been written above.
*/
if (last_unused_bits > 0) {
int new_octet = 0;
int bit = 0x80;
for (int j = 0; j < last_unused_bits; j++) {
if (m_value.get(((int)(num_bits/8))*8+j))
new_octet += bit;
bit = bit/2;
}
stream.write(new_octet);
}
}
/**
* Gets the bitstring value.
* @param element type
*/
public BitSet getValue() {
return m_value;
}
/**
* Gets the number of bits.
* @return bit numbers.
*/
public int getSize() {
return m_value_num_bits;
}
/**
* Gets the element type.
* @param element type
*/
public int getType() {
return BERElement.BITSTRING;
}
/**
* Gets the string representation.
* @return string representation of tag.
*/
public String toString() {
String hex_string = "";
int octet;
//int num_bits = m_value.size();
int num_bits = m_value_num_bits;
for (int i = 0; i < (int)(num_bits/8); i++) {
octet = 0;
int bit = 0x80;
for (int j = 0; j < 8; j++) {
if (m_value.get(i*8+j))
octet += bit;
bit = bit/2;
}
hex_string += " " + (byte)octet;
}
int bit = 0x80;
octet = 0;
for (int k = 0; k < num_bits-(int)(num_bits/8); k++) {
if (m_value.get(((int)(num_bits/8))*8+k))
octet += bit;
bit = bit/2;
}
hex_string += " " + (byte)octet;
return "Bitstring {" + hex_string + " }";
}
}

View File

@@ -0,0 +1,114 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the Boolean object.
*
* <pre>
* ENCODING RULE:
* tag = 0x01
* length = 0x01
* one contents octet (non-zero indicates TRUE).
*
* Example 1: (false)
* 01 01 00
* Example 2: (true)
* 01 01 FF
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
*/
public class BERBoolean extends BERElement {
/**
* Internal variables
*/
private boolean m_value = true;
/**
* Constructs a boolean element.
* @param value boolean value
*/
public BERBoolean(boolean value) {
m_value = value;
}
/**
* 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
*/
public BERBoolean(InputStream stream, int[] bytes_read) throws IOException {
int octet = stream.read(); /* skip length */
bytes_read[0]++;
octet = stream.read(); /* content octet */
bytes_read[0]++;
if (octet > 0)
m_value = true;
else
m_value = false;
}
/**
* Sends the BER encoding directly to a stream.
* @param stream output stream
*/
public void write(OutputStream stream) throws IOException {
stream.write(BERElement.BOOLEAN);
stream.write(0x01);
if (m_value)
stream.write(0xFF); /* non-zero means true. */
else
stream.write(0x00); /* zero means false. */
}
/**
* Gets the boolean value.
* @param element type
*/
public boolean getValue() {
return m_value;
}
/**
* Gets the element type.
* @param element type
*/
public int getType() {
return BERElement.BOOLEAN;
}
/**
* Gets the string representation.
* @return string representation of tag.
*/
public String toString() {
return "Boolean {" + m_value + "}";
}
}

View File

@@ -0,0 +1,181 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This is an abstract base class for character string types.
*
* @version 1.0
* @seeAlso CCITT X.209
*/
public abstract class BERCharacterString extends BERElement {
/**
* Internal variables
*/
protected String m_value = null;
/**
* Constructs a character string element containing a buffer.
*/
public BERCharacterString() {
}
/**
* Constructs a character string element containing buffer.
* @param buffer a string value
*/
public BERCharacterString(String string) {
m_value = string;
}
/**
* Constructs a character string element from a byte array.
* @param buffer buffer containing UTF8 data
*/
public BERCharacterString(byte[] buffer) {
try{
m_value = new String(buffer,"UTF8");
} catch(Throwable x)
{}
}
/**
* 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
* @exception IOException failed to construct
*/
public BERCharacterString(BERTagDecoder decoder, InputStream stream,
int[] bytes_read) throws IOException {
int octet;
int contents_length = super.readLengthOctets(stream, bytes_read);
int[] component_length = new int[1];
BERElement element = null;
if (contents_length == -1) {
/* Constructed - indefinite length content octets. */
do {
component_length[0] = 0;
element = getElement(decoder,stream,component_length);
if (element != null) {
/* element is a string of same type
* - add it to the existing buffer */
BERCharacterString octet_element = (BERCharacterString)element;
String string_buffer = octet_element.getValue();
if (m_value == null) {
m_value = string_buffer;
} else {
m_value = m_value + string_buffer;
}
}
} while (element != null);
} else {
/* Definite length content octets string. */
bytes_read[0] += contents_length;
while (contents_length > 0) {
component_length[0] = 0;
element = getElement(decoder,stream,component_length);
if (element != null) {
/* element is a string of the same type
* - add it to the existing buffer */
BERCharacterString octet_element = (BERCharacterString)element;
String string_buffer = octet_element.getValue();
if (m_value == null) {
m_value = string_buffer;
} else {
m_value = m_value + string_buffer;
}
}
contents_length -= component_length[0];
}
}
}
/**
* Constructs a character string element from an input stream
* (for primitive encoding)
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read
* @exception IOException failed to construct
*/
public BERCharacterString(InputStream stream, int[] bytes_read)
throws IOException {
int contents_length = super.readLengthOctets(stream, bytes_read);
/* Definite length content octets string. */
if (contents_length > 0) {
byte[] buffer = new byte[contents_length];
for (int i = 0; i < contents_length; i++) {
buffer[i] = (byte) stream.read();
}
bytes_read[0] += contents_length;
try {
m_value = new String(buffer,"UTF8");
} catch(Throwable x)
{}
}
}
private byte[] byte_buf;
/**
* Writes BER to stream.
* @param stream output stream
*/
public void write(OutputStream stream) throws IOException {
stream.write(getType()); /* tag */
if (m_value == null) {
sendDefiniteLength(stream, 0);
} else {
try {
byte_buf = m_value.getBytes("UTF8");
sendDefiniteLength(stream, byte_buf.length); /* length */
} catch(Throwable x)
{}
stream.write(byte_buf,0,byte_buf.length); /* contents */
}
}
/**
* Gets the element value.
* @param element value
*/
public String getValue() {
return m_value;
}
/**
* Gets the element type.
* @param element type
*/
public abstract int getType();
/**
* Gets the string representation.
* @return string representation.
*/
public abstract String toString();
}

View File

@@ -0,0 +1,100 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* 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 specific type used.
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
*/
public class BERChoice extends BERElement {
/**
* Internal variables
*/
private BERElement m_value = null;
/**
* Constructs a choice element.
* @param value any BERElement value
*/
public BERChoice(BERElement value) {
m_value = value;
}
/**
* 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 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
* @exception IOException failed to construct
*/
public BERChoice(BERTagDecoder decoder, InputStream stream,
int[] bytes_read) throws IOException {
m_value = getElement(decoder, stream, bytes_read);
}
/**
* Sends the BER encoding of the chosen type directly to a stream.
* @param stream output stream
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
m_value.write(stream);
}
/**
* Gets the value of the chosen type.
* @param element type
*/
public BERElement getValue() {
return m_value;
}
/**
* Gets the element type.
* @param element type
*/
public int getType() {
return BERElement.CHOICE;
}
/**
* Gets the string representation.
* @return string representation of tag.
*/
public String toString() {
return "CHOICE {" + m_value + "}";
}
}

View File

@@ -0,0 +1,134 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This abstract class serves as a based class for constructed
* types such as sequence or set.
*
* @version 1.0
* @seeAlso CCITT X.209
*/
public abstract class BERConstruct extends BERElement {
/**
* List of BER elements in the construct.
*/
private Vector m_elements = new Vector();
/**
* Constructs a construct element.
*/
public BERConstruct() {
}
/**
* 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
* of bytes read from stream
* @exception IOException failed to construct
*/
public BERConstruct(BERTagDecoder decoder, InputStream stream,
int[] bytes_read) throws IOException {
int contents_length = super.readLengthOctets(stream,bytes_read);
int[] component_length = new int[1];
if (contents_length == -1) {
/* Constructed - indefinite length */
BERElement element = null;
{
component_length[0] = 0;
element = getElement(decoder, stream, component_length);
if (element != null)
addElement(element);
} while (element != null);
} else {
/* Constructed - definite length */
bytes_read[0] += contents_length;
while (contents_length > 0)
{
component_length[0] = 0;
addElement(getElement(decoder, stream,component_length));
contents_length -= component_length[0];
}
}
}
/**
* Adds an element to the list.
* @return BER encoding of the element.
*/
public void addElement(BERElement element) {
m_elements.addElement(element);
}
/**
* Retrieves number of elements.
* @return number of elements.
*/
public int size() {
return m_elements.size();
}
/**
* Gets ber element at specific position.
* @param index index of the element to get
* @return BER element.
*/
public BERElement elementAt(int index) {
return (BERElement)m_elements.elementAt(index);
}
/**
* Sends the BER encoding directly to a stream.
* @param stream output stream
* @exception IOException failed to send
*/
public void write(OutputStream stream) throws IOException {
stream.write(getType());
ByteArrayOutputStream contents_stream = new ByteArrayOutputStream();
for (int i = 0; i < m_elements.size(); i++) {
BERElement e = elementAt(i);
e.write(contents_stream);
}
byte[] contents_buffer = contents_stream.toByteArray();
sendDefiniteLength(stream, contents_buffer.length);
stream.write(contents_buffer);
}
/**
* Gets the element type.
* @param element type
*/
public abstract int getType();
/**
* Gets the string representation.
* @return string representation of tag.
*/
public abstract String toString();
}

View File

@@ -0,0 +1,322 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* 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 implements Serializable {
/**
* Possible element types.
*/
public final static int BOOLEAN = 0x01;
public final static int INTEGER = 0x02;
public final static int BITSTRING = 0x03;
public final static int OCTETSTRING = 0x04;
public final static int NULL = 0x05;
public final static int OBJECTID = 0x06;
public final static int REAL = 0x09;
public final static int ENUMERATED = 0x0a;
public final static int SET = 0x31; /* always constructed */
public final static int SEQUENCE = 0x30; /* always constructed */
public final static int NUMERICSTRING = 0x12;
public final static int PRINTABLESTRING = 0x13;
public final static int TELETEXSTRING = 0x14;
public final static int VIDEOTEXSTRING = 0x15;
public final static int IA5STRING = 0x16;
public final static int UTCTIME = 0x17;
public final static int GRAPHICSTRING = 0x19;
public final static int VISIBLESTRING = 0x1A;
public final static int GENERALSTRING = 0x1B;
/**
* Internal (non-transmitted) tags.
*/
public final static int TAG = -1;
public final static int CHOICE = -2;
public final static int ANY = -3;
/**
* Possible tags.
*/
public final static int EOC = 0x00; /* End Of Construction */
public final static int UNIVERSAL = 0x00;
public final static int APPLICATION = 0x40;
public final static int CONTEXT = 0x80;
public final static int SASLCONTEXT = 0xa0;
public final static int PRIVATE = 0xC0;
public final static int PRIMITIVE = 0x00;
public final static int CONSTRUCTED = 0x20;
public final static int MRA_OID = 0x01;
public final static int MRA_TYPE = 0x02;
public final static int MRA_VALUE = 0x03;
public final static int MRA_DNATTRS = 0x04;
public final static int EXOP_REQ_OID = 0x00;
public final static int EXOP_REQ_VALUE = 0x01;
public final static int EXOP_RES_OID = 0x0a;
public final static int EXOP_RES_VALUE = 0x0b;
public final static int SK_MATCHRULE = 0x00;
public final static int SK_REVERSE = 0x01;
public final static int SR_ATTRTYPE = 0x00;
/**
* Gets a ber element from the input stream.
* @param decoder decoder for application specific BER
* @param stream source of ber encoding
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
* @exception IOException failed to decode an element.
*/
public static BERElement getElement(BERTagDecoder decoder,
InputStream stream, int[] bytes_read) throws IOException {
BERElement element = null;
int tag = stream.read();
bytes_read[0] = 1;
if (tag == EOC) {
stream.read(); /* length octet (always zero) */
bytes_read[0] = 1;
element = null;
} else if (tag == BOOLEAN) {
element = new BERBoolean(stream, bytes_read);
} else if (tag == INTEGER) {
element = new BERInteger(stream, bytes_read);
} else if (tag == BITSTRING) {
element = new BERBitString(stream, bytes_read);
} else if (tag == (BITSTRING | CONSTRUCTED)) {
element = new BERBitString(decoder, stream, bytes_read);
} else if (tag == OCTETSTRING) {
element = new BEROctetString(stream, bytes_read);
} else if (tag == (OCTETSTRING | CONSTRUCTED)) {
element = new BEROctetString(decoder, stream, bytes_read);
} else if (tag == NULL) {
element = new BERNull(stream, bytes_read);
} else if (tag == OBJECTID) {
element = new BERObjectId(stream, bytes_read);
} else if (tag == REAL) {
element = new BERReal(stream, bytes_read);
} else if (tag == ENUMERATED) {
element = new BEREnumerated(stream, bytes_read);
} else if (tag == SEQUENCE) {
element = new BERSequence(decoder, stream, bytes_read);
} else if (tag == SET) {
element = new BERSet(decoder, stream, bytes_read);
} else if (tag == NUMERICSTRING) {
element = new BERNumericString(stream, bytes_read);
} else if (tag == (NUMERICSTRING | CONSTRUCTED)) {
element = new BERNumericString(decoder, stream, bytes_read);
} else if (tag == PRINTABLESTRING) {
element = new BERPrintableString(stream, bytes_read);
} else if (tag == (PRINTABLESTRING | CONSTRUCTED)) {
element = new BERPrintableString(decoder, stream, bytes_read);
} else if (tag == UTCTIME) {
element = new BERUTCTime(stream, bytes_read);
} else if (tag == (UTCTIME | CONSTRUCTED)) {
element = new BERUTCTime(decoder, stream, bytes_read);
} else if (tag == VISIBLESTRING) {
element = new BERVisibleString(stream, bytes_read);
} else if (tag == (VISIBLESTRING | CONSTRUCTED)) {
element = new BERVisibleString(decoder, stream, bytes_read);
} else if ((tag & (APPLICATION | PRIVATE | CONTEXT)) > 0) {
element = new BERTag(decoder, tag, stream, bytes_read);
} else
throw new IOException("invalid tag " + tag);
return element;
}
/**
* Reads and decodes a length byte and then that many octets
* from the input stream.
* @param stream input stream from which to read
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
* @return length of contents or -1 if indefinite length.
* @exception IOException failed to read octets
*/
public static int readLengthOctets(InputStream stream, int[] bytes_read)
throws IOException {
int contents_length = 0;
int octet = stream.read();
bytes_read[0]++;
if (octet == 0x80)
/* Indefinite length */
contents_length = -1;
else if ((octet & 0x80) > 0) {
/* Definite (long form) - num octets encoded in 7 rightmost bits */
int num_length_octets = (octet & 0x7F);
for (int i = 0; i < num_length_octets; i++) {
octet = stream.read();
bytes_read[0]++;
contents_length = (contents_length<<8) + octet;
}
} else {
/* Definite (short form) - one length octet. Value encoded in */
/* 7 rightmost bits. */
contents_length = octet;
}
return contents_length;
}
/**
* Writes length octets (definite length only) to stream.
* Uses shortform whenever possible.
* @param stream output stream to write to
* @param num_content_octets value to be encode into length octets
* @return number of bytes sent to stream.
* @exception IOException failed to read octets
*/
public static void sendDefiniteLength(OutputStream stream,
int num_content_octets) throws IOException {
int bytes_written = 0;
if (num_content_octets <= 127) {
/* Use short form */
stream.write(num_content_octets);
} else {
/* Using long form:
* Need to determine how many octets are required to
* encode the length.
*/
int num_length_octets = 0;
int num = num_content_octets;
while (num >= 0) {
num_length_octets++;
num = (num>>8);
if (num <= 0)
break;
}
byte[] buffer = new byte[num_length_octets+1];
buffer[0] = (byte)(0x80 | num_length_octets);
num = num_content_octets;
for (int i = num_length_octets; i > 0; i--) {
buffer[i] = (byte)(num & 0xFF);
num = (num>>8);
}
stream.write(buffer);
}
}
/**
* 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 to 4)
* @return the value of the data as two's complement.
* @exception IOException failed to read octets
*/
protected int readUnsignedBinary(InputStream stream,
int[] bytes_read, int length) throws IOException {
int value = 0;
int octet;
for (int i = 0; i < length; i++) {
octet = stream.read();
bytes_read[0]++;
value = (value<<8) + octet;
}
return value;
}
/**
* 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,
int[] bytes_read, int length) throws IOException {
int value = 0;
if (length > 0) {
boolean negative = false;
int octet = stream.read();
bytes_read[0]++;
if ((octet & 0x80) > 0) /* left-most bit is 1. */
negative = true;
for (int i = 0; i < length; i++) {
if (i > 0) {
octet = stream.read();
bytes_read[0]++;
}
if (negative)
value = (value<<8) + (int)(octet^0xFF)&0xFF;
else
value = (value<<8) + (int)(octet&0xFF);
}
if (negative) /* convert to 2's complement */
value = (value + 1) * -1;
}
return value;
}
/**
* Converts byte to hex string.
* @param value byte value
* @return string representation of Hex String
*/
public String byteToHexString(byte value) {
if (value < 0)
return Integer.toHexString((value & 0x7F) + 128);
else
return Integer.toHexString(value);
}
/**
* Sends the BER encoding directly to a stream.
* @param stream output stream
* @return bytes written to stream.
*/
public abstract void write(OutputStream stream) throws IOException;
/**
* Gets the element type.
* @return element type.
*/
public abstract int getType();
/**
* Gets the string representation.
* @return string representation of an element.
*/
public abstract String toString();
}

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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.ber.stream;
import java.util.*;
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 a value.
* @param value integral value
*/
public BEREnumerated(int value) {
super(value);
}
/**
* Constructs an enumerated element with the input stream.
* @param stream input stream from which to decode
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from array
* @exception IOException failed to construct
*/
public BEREnumerated(InputStream stream, int[] bytes_read)
throws IOException {
super(stream, bytes_read);
}
/**
* Gets the element type.
* @param element type
*/
public int getType() {
return BERElement.ENUMERATED;
}
/**
* Gets the string representation.
* @return string representation of tag.
*/
public String toString() {
return "Enumerated {" + getValue() + "}";
}
}

View File

@@ -0,0 +1,87 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the Integer object.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x02
* length = (short or long form)
* one or more contents octets hold integer
* value in two's complement
*
* Example 1: (zero)
* 02 01 00
* Example 2: (1)
* 02 01 01
* Example 3: (300 - short form)
* 02 02 01 2C
* Example 4: (300 - long form)
* 02 84 00 00 01 2C
* </pre>
*
* @version 1.0
* @seeAlso CCITT X.209
*/
public class BERInteger extends BERIntegral {
/**
* Constructs a integer element.
* @param value integer value
*/
public BERInteger(int value) {
super(value);
}
/**
* Constructs an integer element with the input stream.
* @param stream input stream
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
* @exception IOException failed to construct
*/
public BERInteger(InputStream stream, int[] bytes_read) throws IOException {
super(stream, bytes_read);
}
/**
* Gets the element type.
* @param element type
*/
public int getType() {
return BERElement.INTEGER;
}
/**
* Gets the string representation.
* @return string representation of tag.
*/
public String toString() {
return "Integer {" + getValue() + "}";
}
}

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