Initial checkin of org.ietf.ldap classes

This commit is contained in:
rweltman%netscape.com 2001-11-09 01:36:04 +00:00
Родитель 2575676e90
Коммит c69f6d09cf
151 изменённых файлов: 38065 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,115 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.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 );
} else {
System.err.println( "No such method: " +
packageName + "." + methodName );
}
} catch ( Exception e ) {
e.printStackTrace();
throw new LDAPException( "Invoking " + methodName + ": " +
e.toString(),
LDAPException.PARAM_ERROR );
}
return null;
}
static Method getMethod( String packageName,
String methodName,
String[] args ) throws LDAPException {
try {
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 = (Method)(m_methodLookup.get(key))) != null ) {
return method;
}
Class c = Class.forName( packageName );
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 ) {
System.err.println( params.length + " method parameters vs " +
args.length + " expected" );
return false;
}
for ( int i = 0; i < params.length; i++ ) {
if ( !params[i].getName().equals(args[i]) ) {
System.err.println( params[i].getName() +
" method parameter vs " +
args[i] + " expected" );
return false;
}
}
return true;
}
private static Hashtable m_methodLookup = new Hashtable();
}

Просмотреть файл

@ -0,0 +1,560 @@
/* -*- 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 org.ietf.ldap;
import java.io.*;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
/**
* Represents the name and values of an attribute in an entry.
*
* @version 1.0
* @see org.ietf.ldap.LDAPAttributeSet
*/
public class LDAPAttribute implements Cloneable, 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();
if (vals[i] == null) {
vals[i] = new byte[0];
}
}
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 org.ietf.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 org.ietf.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 org.ietf.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 org.ietf.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 org.ietf.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 {
String sval = new String(val, "UTF8");
if (sval.length() == 0 && val.length > 0) {
sb.append("<binary value, length:");
sb.append(val.length);
sb.append(">");
}
else {
sb.append(sval);
}
} catch (Exception e) {
if (val != null) {
sb.append("<binary value, length:");
sb.append(val.length);
sb.append(">");
}
else {
sb.append("null value");
}
}
}
}
return "{type='" + getName() + "', values='" + sb.toString() + "'}";
}
/**
* Creates and returns a new <CODE>LDAPAttribute</CODE> object that
* contains the same information as this one. The cloned object has
* a deep copy of the contents of the original.
*
* @return A deep copy of this object
*/
public synchronized Object clone() {
return new LDAPAttribute( this );
}
/**
* 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();
}
}

Просмотреть файл

@ -0,0 +1,468 @@
/* -*- 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 org.ietf.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 org.ietf.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 names names 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 obsolete true if this attribute is obsolete
* @param equality Object Identifier of the equality matching rule
* for the attribute in dotted-decimal format; MAY be null
* @param ordering Object Identifier of the ordering matching rule
* for the attribute in dotted-decimal format; MAY be null
* @param substring Object Identifier of the substring matching rule
* for the attribute in dotted-decimal format; MAY be null
* @param collective true if this is a collective attribute.
* @param userMod true if the attribute is modifiable by users.
* @param usage One of the following:
* <UL>
* <LI>USER_APPLICATIONS
* <LI>DIRECTORY_OPERATION
* <LI>DISTRIBUTED_OPERATION
* <LI>DSA_OPERATION
* </UL>
*/
public LDAPAttributeSchema( String[] names,
String oid,
String description,
String syntaxString,
boolean single,
String superior,
boolean obsolete,
String equality,
String ordering,
String substring,
String collective,
boolean userMod,
int usage ) {
super( names, oid, description );
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 );
}
if ( obsolete ) {
setQualifier( OBSOLETE, "" );
}
if ( (equality != null) && (equality.length() > 0) ) {
setQualifier( EQUALITY, equality );
}
if ( (ordering != null) && (ordering.length() > 0) ) {
setQualifier( ORDERING, ordering );
}
if ( (substring != null) && (substring.length() > 0) ) {
setQualifier( SUBSTR, substring );
}
if ( (collective != null) && (collective.length() > 0) ) {
setQualifier( COLLECTIVE, collective );
}
if ( !userMod ) {
setQualifier( NO_USER_MODIFICATION, "" );
}
setQualifier( USAGE, String.valueOf( usage ) );
}
/**
* 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 );
}
}
/**
* Returns the value of a property of the object or null if there is none
*
* @param key the name of the property
* @return the value of a property of the object or null if there is none
*/
private String getStringProperty( String key ) {
String[] val = getQualifier( key );
return ((val != null) && (val.length > 0)) ? val[0] : null;
}
/**
* Returns the Object Identifier of the equality matching rule in effect
* for this attribute, or null if there is none
* @return the Object Identifier of the equality matching rule in effect
* for this attribute, or null if there is none
*/
public String getEqualityMatchingRule() {
return getStringProperty( EQUALITY );
}
/**
* Returns the Object Identifier of the order matching rule in effect
* for this attribute, or null if there is none
* @return the Object Identifier of the order matching rule in effect
* for this attribute, or null if there is none
*/
public String getOrderMatchingRule() {
return getStringProperty( ORDERING );
}
/**
* Returns the Object Identifier of the substring matching rule in effect
* for this attribute, or null if there is none
* @return the Object Identifier of the substring matching rule in effect
* for this attribute, or null if there is none
*/
public String getSubstringMatchingRule() {
return getStringProperty( SUBSTR );
}
/**
* 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() {
return getStringProperty( SUPERIOR );
}
/**
* 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>
* @deprecated use getSyntaxString instead
*/
public int getSyntax() {
return syntaxElement.syntax;
}
/**
* Gets the usage property of the object
*
* @return the usage property of the object; one of the following:
* <UL>
* <LI>USER_APPLICATIONS
* <LI>DIRECTORY_OPERATION
* <LI>DISTRIBUTED_OPERATION
* <LI>DSA_OPERATION
* </UL>
*/
public int getUsage() {
int usage;
try {
usage = Integer.parseInt( getStringProperty( USAGE ) );
} catch ( Exception e ) {
usage = USER_APPLICATIONS;
}
return usage;
}
/**
* 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;
}
/**
* Determines if the attribute type is collective
*
* @return <code>true</code> if collective
*/
public boolean isCollective() {
return (properties != null) ? properties.containsKey( COLLECTIVE ) :
false;
}
/**
* 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;
}
/**
* Determines if the attribute type is modifiable by users
*
* @return <code>true</code> if modifiable by users
*/
public boolean isUserModifiable() {
return (properties != null) ?
!properties.containsKey( NO_USER_MODIFICATION ) :
true;
}
/**
* Gets the definition of the attribute type in Directory format
*
* @return definition of the attribute type in Directory format
*/
public String toString() {
return getValue( false );
}
/**
* Gets the attribute name for a schema element
*
* @return The attribute name of the element
*/
String getAttributeName() {
return "attributetypes";
}
// 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";
// Usage constants
/** An ordinary user attribute
*/
public static final int USER_APPLICATIONS = 0;
/** An operational attribute used for a directory operation or which
* holds a directory specific value
*/
public static final int DIRECTORY_OPERATION = 1;
/** An operational attribute used to hold server (DSA) information that
* is shared among servers holding replicas of the entry
*/
public static final int DISTRIBUTED_OPERATION = 2;
/** An operational attribute used to hold server (DSA) information that
* is local to a server
*/
public static final int DSA_OPERATION = 3;
// 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();
}

Просмотреть файл

@ -0,0 +1,618 @@
/* -*- 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 org.ietf.ldap;
import java.io.Serializable;
import java.util.*;
import org.ietf.ldap.client.*;
import org.ietf.ldap.client.opers.*;
/**
* Represents a set of attributes (for example, the set of attributes
* in an entry).
*
* @version 1.0
* @see org.ietf.ldap.LDAPAttribute
*/
public class LDAPAttributeSet implements Cloneable, Serializable, Set {
static final long serialVersionUID = 5018474561697778100L;
HashMap _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 do 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() {
// For now, always create the hashtable
prepareHashtable( true );
}
/**
* Constructs an attribute set.
* @param attrs the list of attributes
*/
public LDAPAttributeSet( LDAPAttribute[] attrs ) {
this();
if ( attrs == null ) {
attrs = new LDAPAttribute[0];
}
_attrs = attrs;
if ( _attrs.length > 0 ) {
for( int i = 0; i < _attrs.length; i++ ) {
add( _attrs[i] );
}
}
}
/**
* Removes all mappings from this attribute set
*/
public void clear() {
_attrHash = null;
if ( _attrs.length > 0 ) {
_attrs = new LDAPAttribute[0];
}
}
/**
* Adds the specified attribute to this attribute set, overriding
* any previous definition with the same attribute name
*
* @param attr attribute to add to this set
* @return true if this set changed as a result of the call
*/
public synchronized boolean add( Object attr ) {
if ( attr instanceof LDAPAttribute ) {
if ( contains( attr ) ) {
return false;
}
LDAPAttribute attrib = (LDAPAttribute)attr;
LDAPAttribute[] vals = new LDAPAttribute[_attrs.length+1];
for ( int i = 0; i < _attrs.length; i++ ) {
vals[i] = _attrs[i];
}
vals[_attrs.length] = attrib;
_attrs = vals;
if ( _attrHash != null ) {
_attrHash.put( attrib.getName().toLowerCase(), attr );
}
return true;
} else {
throw new ClassCastException( "Requires LDAPAttribute");
}
}
/**
* Adds the collection of attributes to this attribute set, overriding
* any previous definition with the same attribute names
*
* @param attrs attributes to add to this set
* @return true if any attribute was added
*/
public synchronized boolean addAll( Collection attrs ) {
if ( attrs == null ) {
return false;
}
boolean present = true;
Iterator it = attrs.iterator();
while( it.hasNext() ) {
Object attr = it.next();
if ( !contains( attr ) ) {
present = true;
add( attr );
}
}
return !present;
}
/**
* Returns a deep copy of this attribute set
*
* @return a deep copy of this attribute set
*/
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 true if this attribute set contains the specified attribute
*
* @param attr attribute whose presence in this set is to be tested
* @return true if the attribute set contains the specified attribute
*/
public boolean contains( Object attr ) {
if ( !(attr instanceof LDAPAttribute) ) {
return false;
} else {
if ( _attrHash != null ) {
return _attrHash.containsValue( attr );
} else {
for ( int i = 0; i < _attrs.length; i++ ) {
if ( attr.equals(_attrs[i]) ) {
return true;
}
}
}
return false;
}
}
/**
* Returns true if this attribute set contains all the specified attributes
*
* @param attrs attributes whose presence in this set is to be tested
* @return true if the attribute set contains the specified attributes
*/
public boolean containsAll( Collection attrs ) {
if ( _attrHash != null ) {
Iterator it = attrs.iterator();
while( it.hasNext() ) {
if ( !_attrHash.containsValue( it.next() ) ) {
return false;
}
}
return true;
} else {
return false;
}
}
/**
* Returns true if this attribute set contains the specified attribute name
*
* @param attrName attribute name whose presence in this set is to be tested
* @return true if the attribute set contains the specified attribute
*/
public boolean containsKey( Object attrName ) {
if ( !(attrName instanceof String) ) {
return false;
} else {
return ( getAttribute( (String)attrName ) != null );
}
}
/**
* Returns true if this attribute set equals a specified set
*
* @param attrSet attribute set to compare to
* @return true if this attribute set equals a specified set
*/
public boolean equals( Object attrSet ) {
if ( !(attrSet instanceof LDAPAttributeSet) ) {
return false;
}
return ((LDAPAttributeSet)attrSet)._attrHash.equals( _attrHash );
}
/**
* Returns the hash code for this attribute set
*
* @return the hash code for this attribute set
*/
public int hashCode() {
return _attrHash.hashCode();
}
/**
* Returns true if there are no attributes in this attribute set
*
* @return true if there are no attributes in this attribute set
*/
public boolean isEmpty() {
return ( _attrs.length < 1 );
}
/**
* Returns an iterator over the attributes in this attribute set
*
* @return an iterator over the attributes in this attribute set
*/
public Iterator iterator() {
return _attrHash.values().iterator();
}
/**
* Removes the specified attribute
*
* @param attr the attribute to remove
* @return true if the attribute was removed
*/
public boolean remove( Object attr ) {
if ( !(attr instanceof LDAPAttribute) ) {
return false;
}
boolean present = contains( attr );
if ( present ) {
synchronized(this) {
LDAPAttribute[] vals = new LDAPAttribute[_attrs.length-1];
int j = 0;
for (int i = 0; i < _attrs.length; i++) {
if ( !attr.equals(_attrs[i] ) ) {
vals[j++] = _attrs[i];
}
}
if (_attrHash != null) {
_attrHash.remove(
((LDAPAttribute)attr).getName().toLowerCase() );
}
_attrs = vals;
}
}
return present;
}
/**
* Removes the specified attributes
*
* @param attrs the attributes to remove
* @return true if any attribute was removed
*/
public boolean removeAll( Collection attrs ) {
if ( attrs == null ) {
return false;
}
boolean present = true;
Iterator it = attrs.iterator();
while( it.hasNext() ) {
Object attr = it.next();
if ( !contains( attr ) ) {
present = true;
remove( attr );
}
}
return !present;
}
/**
* Retains only the attributes in this set that are contained in the
* specified collection
*
* @param attrs attributes to retain
* @return true if the attribute set was changed as a result of the
* operation
*/
public boolean retainAll( Collection attrs ) {
HashMap newmap = new HashMap();
Iterator it = attrs.iterator();
while( it.hasNext() ) {
Object attr = it.next();
if ( attr instanceof LDAPAttribute ) {
newmap.put( ((LDAPAttribute)attr).getName().toLowerCase(),
attr );
}
}
if ( newmap.equals( _attrHash ) ) {
return false;
} else {
_attrHash = newmap;
_attrs = (LDAPAttribute[])_attrHash.values().toArray(
new LDAPAttribute[0] );
return true;
}
}
/**
* Returns the number of attributes in this set.
* @return number of attributes in this attribute set.
*/
public int size() {
return _attrs.length;
}
/**
* Returns the attributes of the set as an array
*
* @return the attributes of the set as an array
*/
public Object[] toArray() {
return _attrs;
}
/**
* Returns the attributes of the set as an array
*
* @param attrs an attribute array to fill with the attributes of this
* set. If the array is not large enough, a new array is allocated.
* @return the attributes of the set as an array
*/
public Object[] toArray( Object[] attrs ) {
if ( !(attrs instanceof LDAPAttribute[]) ) {
throw new ArrayStoreException(
"Must provide an LDAPAttribute array" );
} else if ( attrs.length >= _attrs.length ) {
for( int i = 0; i < _attrs.length; i++ ) {
attrs[i] = _attrs[i];
}
return attrs;
} else {
return _attrs;
}
}
/**
* 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 org.ietf.ldap.LDAPAttribute
* @see org.ietf.ldap.LDAPAttributeSet#getAttribute
* @see org.ietf.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.hasMoreTokens() ) {
searchTypes[i] = (String)st.nextToken();
i++;
}
Iterator it = _attrHash.values().iterator();
while( it.hasNext() ) {
LDAPAttribute attr = (LDAPAttribute)it.next();
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 org.ietf.ldap.LDAPAttribute
*/
public LDAPAttribute getAttribute( String attrName ) {
if ( attrName == null ) {
return null;
} else 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( boolean force ) {
if ( (_attrHash == null) &&
(force || (_attrs.length >= ATTR_COUNT_REQUIRES_HASH)) ) {
if ( _attrHash == null ) {
_attrHash = new HashMap();
} else {
_attrHash.clear();
}
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 org.ietf.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;
}
/**
* 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();
}
}

Просмотреть файл

@ -0,0 +1,75 @@
/* -*- 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 org.ietf.ldap;
/**
* 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 myLDAPAuthHandler 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 myLDAPAuthHandler implements org.ietf.ldap.LDAPAuthHandler
* {
* private String myDN;
* private String myPW;
* private LDAPAuthHandlerAuth myRebindInfo;
* public myLDAPAuthHandler () {
* myDN = "c=Directory Manager,o=Universal Exports,c=UK";
* myPW = "alway4444";
* }
*
* public LDAPAuthHandlerAuth getRebindAuthentication( String host, int port ) {
* if ( host.equalsIgnoreCase( "alway.mcom.com" ) && ( port == 389 ) ) {
* myRebindInfo = new LDAPAuthHandlerAuth( myDN, myPW );
* } else {
* myRebindInfo = new LDAPAuthHandlerAuth( "", "" );
* }
* return myRebindInfo;
* }
* } </PRE>
*
*
* @version 1.0
*/
public interface LDAPAuthHandler extends LDAPReferralHandler {
/**
* Returns an <CODE>LDAPAuthProvider</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 LDAPAuthProvider object containing authentication information.
* @see org.ietf.ldap.LDAPAuthProvider
*/
public LDAPAuthProvider getAuthProvider( String host,
int port );
}

Просмотреть файл

@ -0,0 +1,95 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.io.Serializable;
/**
* 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 LDAPAuthProvider myRebindInfo;
* ...
* public LDAPAuthProvider getRebindAuthentication( String host, int port ) {
* if ( host.equalsIgnoreCase( "alway.mcom.com" ) && ( port == 389 ) ) {
* myRebindInfo = new LDAPAuthProvider( myDN, myPW );
* } else {
* myRebindInfo = new LDAPAuthProvider( "", "" );
* }
* return myRebindInfo;
* } </PRE>
*
* @version 1.0
* @see org.ietf.ldap.LDAPAuthHandler
*/
public class LDAPAuthProvider implements Serializable {
static final long serialVersionUID = 7161655313564756294L;
private String _dn;
private byte[] _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 LDAPAuthProvider( String dn, byte[] password ) {
_dn = dn;
_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 _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 byte[] getPassword() {
return _password;
}
}

Просмотреть файл

@ -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 org.ietf.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 LDAPBindHandler {
/**
* This method is called by <CODE>LDAPConnection</CODE> when
* authenticating. An implementation of <CODE>LDAPBindHandler</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 org.ietf.ldap.LDAPReferralException
* @see org.ietf.ldap.LDAPConnection#bind
* @param ldapurls urls which may be selected to connect and bind to
* @param conn an established connection to an LDAP server
*/
public void bind( String[] ldapurls,
LDAPConnection conn ) throws LDAPReferralException;
}

Просмотреть файл

@ -0,0 +1,819 @@
/* -*- 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 org.ietf.ldap;
import java.util.*;
import java.io.*;
import org.ietf.ldap.client.*;
import org.ietf.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 org.ietf.ldap.LDAPConnection#setCache(org.ietf.ldap.LDAPCache)
* @see org.ietf.ldap.LDAPConnection#getCache
*/
public class LDAPCache implements Serializable {
static final long serialVersionUID = 6275167993337814294L;
/**
* A hashtable of search results. The key is created from the search
* request parameters (see createKey() method). The value is a Vector
* where the first element is a Long integer representing the size
* of all entries, followed by the actual search result entries (of type
* LDAPEntry).
*/
private Hashtable m_cache;
/**
* A list of cached entries ordered by time (augments m_cache). Each
* element in the list is a 2 element Vector where the element at index
* 0 is the key in the m_cache table, and the element at index 1 is the
* time when the entry was created.
* The list is used to track the time-to-live limit and to implement the
* FIFO algorithm when adding new entries; if the size of the new entry
* exceeds the cache available space, the extra space is made by removing
* existing cached results in the order of their entry in the cache.
*/
private Vector m_orderedStruct;
private long m_timeToLive;
private long m_maxSize;
private String[] m_dns;
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>LDAPConnection.SCOPE_BASE</CODE> (to remove the entry identified
* by <CODE>dn</CODE>)
* <LI><CODE>LDAPConnection.SCOPE_ONE</CODE> (to remove the entries that
* have <CODE>dn</CODE> as their parent entry)
* <LI><CODE>LDAPConnection.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);
// LDAPEntries start at idx 1, at idx 0 is a Long
// (size of all LDAPEntries returned by search())
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;
}
}
Vector entry = (Vector)m_cache.remove(key);
m_remainingSize += ((Long)entry.firstElement()).longValue();
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;
// get server and client controls
if (cons != null) {
serverControls = cons.getControls();
}
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);
}
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 += ((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 += ((Long)val.elementAt(0)).longValue();
if (m_remainingSize >= size)
break;
}
}
m_remainingSize -= size;
m_cache.put(key, v);
Vector element = new Vector(2);
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();
}
}

Просмотреть файл

@ -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 org.ietf.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;
}
}

Просмотреть файл

@ -0,0 +1,337 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.io.Serializable;
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 LDAPSearchResults#sort
*/
public class LDAPCompareAttrNames
implements Comparator, Serializable {
static final long serialVersionUID = -2567450425231175944L;
private String _attrs[];
private boolean _ascending[];
private Locale _locale = null;
private Collator _collator = null;
private boolean _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) {
_attrs = new String[1];
_attrs[0] = attribute;
_ascending = new boolean[1];
_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) {
_attrs = new String[1];
_attrs[0] = attribute;
_ascending = new boolean[1];
_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) {
_attrs = attributes;
_ascending = new boolean[attributes.length];
for( int i = 0; i < attributes.length; i++ )
_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) {
_attrs = attributes;
_ascending = ascendingFlags;
if ( _ascending == null ) {
_ascending = new boolean[attributes.length];
for( int i = 0; i < attributes.length; i++ )
_ascending[i] = true;
}
}
/**
* Indicates if some other object is "equal to" this Comparator
*
* @param obj the object to compare
* @return true if the object equals this object
*/
public boolean equals( Object obj ) {
return super.equals( obj );
}
/**
* 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 _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 ( _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 ) {
_locale = locale;
if ( _locale == null ) {
_collator = null;
} else {
_collator = Collator.getInstance( _locale );
_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 _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 ) {
_sensitive = sensitive;
}
/**
* Compares its two arguments for order
*
* @param entry1 the first entry to be compared
* @param entry2 the second entry to be compared
* @return a negative integer, zero, or a positive integer if the first
* argument is less than, equal to, or greater than the second
* @exception ClassCastException if either of the arguments is not
* an LDAPEntry
*/
public int compare( Object entry1, Object entry2 ) {
if ( !(entry1 instanceof LDAPEntry) ||
!(entry2 instanceof LDAPEntry) ) {
throw new ClassCastException( "Must compare LDAPEntry objects" );
}
return attrGreater( (LDAPEntry)entry1, (LDAPEntry)entry2, 0 );
}
/**
* Compares a particular attribute in both entries. If equal,
* moves on to the next.
* @param entry1 the first entry to be compared
* @param entry2 the second entry to be compared
* @return a negative integer, zero, or a positive integer if the first
* argument is less than, equal to, or greater than the second
*/
int attrGreater( LDAPEntry entry1, LDAPEntry entry2,
int attrPos ) {
Iterator attrSet1 =
entry1.getAttributeSet().iterator();
Iterator attrSet2 =
entry2.getAttributeSet().iterator();
String value1 = null;
String value2 = null;
String attrName = _attrs[attrPos];
boolean ascending = _ascending[attrPos];
while ( attrSet2.hasNext() ) {
LDAPAttribute currAttr = (LDAPAttribute)(attrSet2.next());
if ( !attrName.equalsIgnoreCase (currAttr.getName()) ) {
continue;
}
value2 = (String)(currAttr.getStringValues().nextElement());
break;
}
while ( attrSet1.hasNext() ) {
LDAPAttribute currAttr = (LDAPAttribute)(attrSet1.next());
if ( !attrName.equalsIgnoreCase(currAttr.getName()) ) {
continue;
}
value1 = (String)(currAttr.getStringValues().nextElement());
break;
}
if ( (value2 == null) ^ (value1 == null) ) {
return (value1 != null) ? 1 : -1;
}
// Check for equality
if ( (value2 == null) ||
((_collator != null) &&
(_collator.compare( value1, value2 ) == 0) ) ||
((_collator == null) && _sensitive &&
value2.equals(value1)) ||
((_collator == null) && !_sensitive &&
value2.equalsIgnoreCase(value1)) ) {
if ( attrPos == _attrs.length - 1 ) {
return -1;
} else {
return attrGreater ( entry1, entry2, attrPos+1 );
}
}
// Not equal, check for order
if ( ascending ) {
if ( _collator != null ) {
return _collator.compare( value1, value2 );
} else if ( _sensitive ) {
return value1.compareTo( value2 );
} else {
return value1.toLowerCase().compareTo( value2.toLowerCase() );
}
} else {
if ( _collator != null ) {
return _collator.compare( value1, value2 );
} else if ( _sensitive ) {
return value1.compareTo( value2 );
} else {
return value1.toLowerCase().compareTo( value2.toLowerCase() );
}
}
}
}

Просмотреть файл

@ -0,0 +1,542 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.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, 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 _socket = null;
/**
* Last exception occured during connection setup
*/
private LDAPException _connException = null;
/**
* List of server to use for the connection setup
*/
ServerEntry[] _dsList;
/**
* Index of the last connected server
*/
private int _dsIdx = -1;
/**
* Socket factory for SSL connections
*/
LDAPSocketFactory _factory;
/**
* Connection setup policy (PARALLEL or SERIAL)
*/
int _policy = SERIAL;
/**
* Delay in ms before another connection setup thread is started.
*/
int _connSetupDelay = -1;
/**
* The maximum time to wait to established the connection
*/
int _connectTimeout = 0;
/**
* During connection setup, the current count of servers to which
* connection attmpt has been made
*/
private transient int _attemptCnt = 0;
/**
* Connection IDs for ldap trace messages
*/
private static int _nextId;
private int _id;
/**
* 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) {
_dsList = new ServerEntry[hosts.length];
for (int i=0; i < hosts.length; i++) {
_dsList[i] = new ServerEntry(hosts[i], ports[i], NEVER_USED);
}
_factory = factory;
_id = _nextId++;
}
/**
* 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 (_connectTimeout == 0) {
// No need for a separate thread, connect time not limited
connect();
}
else {
// Wait for connection at most _connectTimeout milliseconds
// Run connection setup in a separate thread to monitor the time
tmax = System.currentTimeMillis() + _connectTimeout;
th = new Thread (new Runnable() {
public void run() {
connect();
}
}, "ConnSetupMgr");
th.setDaemon(true);
th.start();
while (_socket==null && (_attemptCnt < _dsList.length) &&
(tcur = System.currentTimeMillis()) < tmax) {
try {
wait(tmax - tcur);
}
catch (InterruptedException e) {
th.interrupt();
cleanup();
throw new LDAPInterruptedException("Interrupted connect operation");
}
}
}
if (_socket != null) {
return _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 (_connException != null && _dsList.length == 1) {
throw _connException;
}
throw new LDAPException(
"failed to connect to server " + getServerList(),
LDAPException.CONNECT_ERROR);
}
private void reset() {
_socket = null;
_connException = null;
_attemptCnt = 0;
for (int i=0; i < _dsList.length; i++) {
_dsList[i].connSetupThread = null;
}
}
private String getServerList() {
StringBuffer sb = new StringBuffer();
for (int i=0; i < _dsList.length; i++) {
sb.append(i==0 ? "" : " ");
sb.append(_dsList[i].host);
sb.append(":");
sb.append(_dsList[i].port);
}
return sb.toString();
}
private void connect() {
if (_policy == SERIAL || _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 (_socket != null) {
_dsList[_dsIdx].connSetupStatus = FAILED;
// Move the entry to the end of the list
int srvCnt = _dsList.length, j=0;
ServerEntry[] newDsList = new ServerEntry[_dsList.length];
for (int i=0; i < srvCnt; i++) {
if (i != _dsIdx) {
newDsList[j++] = _dsList[i];
}
}
newDsList[j] = _dsList[_dsIdx];
_dsList = newDsList;
_dsIdx = j;
}
_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 (_socket != null) {
_dsList[_dsIdx].connSetupStatus = DISCONNECTED;
}
_socket = null;
}
Socket getSocket() {
return _socket;
}
String getHost() {
if (_dsIdx >= 0) {
return _dsList[_dsIdx].host;
}
return _dsList[0].host;
}
int getPort() {
if (_dsIdx >= 0) {
return _dsList[_dsIdx].port;
}
return _dsList[0].port;
}
int getConnSetupDelay() {
return _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) {
_policy = (delay < 0) ? SERIAL : PARALLEL;
_connSetupDelay = delay*1000;
}
int getConnectTimeout() {
return _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) {
_connectTimeout = timeout*1000;
}
/**
* Check if the user has voluntarily closed the connection
*/
boolean isUserDisconnected() {
return (_dsIdx >=0 &&
_dsList[_dsIdx].connSetupStatus == DISCONNECTED);
}
/**
* Try sequentially to open a new connection to a server.
*/
private void openSerial() {
for (int i=0; i < _dsList.length; i++) {
_dsList[i].connSetupThread = Thread.currentThread();
connectServer(i);
if (_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; _socket==null && i < _dsList.length; i++) {
//Create a Thread to execute connectSetver()
final int dsIdx = i;
String threadName = "ConnSetupMgr " +
_dsList[dsIdx].host + ":" + _dsList[dsIdx].port;
Thread t = new Thread(new Runnable() {
public void run() {
connectServer(dsIdx);
}
}, threadName);
_dsList[dsIdx].connSetupThread = t;
t.setDaemon(true);
t.start();
// Wait before starting another thread if the delay is not zero
if (_connSetupDelay != 0 && i < (_dsList.length-1)) {
try {
wait(_connSetupDelay);
}
catch (InterruptedException e) {
return;
}
}
}
// At this point all threads are started. Wait until first thread
// succeeds to connect or all threads terminate
while (_socket == null && (_attemptCnt < _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 = _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 (_factory == null) {
sock = new Socket (entry.host, entry.port);
//s.setSoLinger( false, -1 );
} else {
sock = _factory.createSocket(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 (_socket == null && entry.connSetupThread == currThread) {
entry.connSetupThread = null;
if (sock != null) {
entry.connSetupStatus = CONNECTED;
_socket = sock;
_dsIdx = idx;
cleanup(); // Signal other concurrent threads to terminate
}
else {
entry.connSetupStatus = FAILED;
_connException = conex;
}
_attemptCnt++;
notifyAll();
}
}
}
/**
* Terminate all concurrently running connection setup threads
*/
private synchronized void cleanup() {
Thread currThread = Thread.currentThread();
for (int i=0; i < _dsList.length; i++) {
ServerEntry entry = _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 = _dsList.length;
for (int i=1; i < srvCnt; i++) {
for (int j=0; j < i; j++) {
if (_dsList[i].connSetupStatus < _dsList[j].connSetupStatus) {
// swap entries
ServerEntry entry = _dsList[j];
_dsList[j] = _dsList[i];
_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 {
_socket.close();
return true;
}
catch (Exception e) {
return false;
}
}
public String toString() {
String str = "dsIdx="+_dsIdx+ " dsList=";
for (int i=0; i < _dsList.length; i++) {
str += _dsList[i]+ " ";
}
return str;
}
int getID() {
return _id;
}
String getLDAPUrl() {
return ((_factory == null) ? "ldap" : "ldaps") +
"://" + getHost() + ":" + getPort();
}
public Object clone() {
try {
LDAPConnSetupMgr cloneMgr = (LDAPConnSetupMgr) super.clone();
cloneMgr._dsList = new ServerEntry[_dsList.length];
for (int i=0; i<_dsList.length; i++) {
ServerEntry e = _dsList[i];
cloneMgr._dsList[i] = new ServerEntry(e.host, e.port, e.connSetupStatus);
}
return cloneMgr;
}
catch (CloneNotSupportedException ex) {
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,721 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.util.*;
import org.ietf.ldap.client.*;
import org.ietf.ldap.client.opers.*;
import org.ietf.ldap.ber.stream.*;
import org.ietf.ldap.util.*;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
/**
* 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;
private final static int BACKLOG_CHKCNT = 50;
/**
* Internal variables
*/
transient private static int _highMsgId;
transient private InputStream _serverInput;
transient private OutputStream _serverOutput;
transient private Hashtable _requests;
transient private Hashtable _messages = null;
transient private Vector _registered;
transient private boolean _disconnected = false;
transient private LDAPCache _cache = null;
transient private boolean _doRun = true;
private Socket _socket = null;
transient private Thread _thread = null;
transient Object _sendRequestLock = new Object();
transient LDAPConnSetupMgr _connMgr = null;
transient Object _traceOutput = null;
transient private int _backlogCheckCounter = BACKLOG_CHKCNT;
// Time Stamp format Hour(0-23):Minute:Second.Milliseconds used for
// trace msgs
static SimpleDateFormat _timeFormat =
new SimpleDateFormat( "HH:mm:ss.SSS" );
/**
* Constructs a connection thread that maintains connection to the
* LDAP server
*
* @param connMgr
* @param cache
* @param traceOutput
*/
public LDAPConnThread( LDAPConnSetupMgr connMgr,
LDAPCache cache,
Object traceOutput )
throws LDAPException {
super( "LDAPConnThread " + connMgr.getHost() +
":" + connMgr.getPort() );
_requests = new Hashtable ();
_registered = new Vector ();
_connMgr = connMgr;
_socket = connMgr.getSocket();
setCache( cache );
setTraceOutput( traceOutput );
// Allow the application to exit if only LDAPConnThread threads are
// running
setDaemon( true );
try {
_serverInput =
new BufferedInputStream( _socket.getInputStream() );
_serverOutput =
new BufferedOutputStream( _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, stop
// is called right away if _doRun is false.
_doRun = false;
start();
throw new LDAPException ( "failed to connect to server " +
_connMgr.getHost(),
LDAPException.CONNECT_ERROR );
}
if ( traceOutput != null ) {
StringBuffer sb = new StringBuffer( " connected to " );
sb.append( _connMgr.getLDAPUrl() );
logTraceMessage( sb );
}
start(); /* start the thread */
}
InputStream getInputStream() {
return _serverInput;
}
void setInputStream( InputStream is ) {
_serverInput = is;
}
OutputStream getOutputStream() {
return _serverOutput;
}
void setOutputStream( OutputStream os ) {
_serverOutput = os;
}
void setTraceOutput( Object traceOutput ) {
synchronized ( _sendRequestLock ) {
if ( traceOutput == null ) {
_traceOutput = null;
} else if ( traceOutput instanceof OutputStream ) {
_traceOutput = new PrintWriter( (OutputStream)traceOutput );
} else if ( traceOutput instanceof LDAPTraceWriter ) {
_traceOutput = traceOutput;
}
}
}
void logTraceMessage( StringBuffer msg ) {
if ( _traceOutput == null ) {
return;
}
String timeStamp = _timeFormat.format( new Date() );
StringBuffer sb = new StringBuffer( timeStamp );
sb.append( " ldc=" );
sb.append( _connMgr.getID() );
synchronized( _sendRequestLock ) {
if ( _traceOutput instanceof PrintWriter ) {
PrintWriter traceOutput = (PrintWriter)_traceOutput;
traceOutput.print( sb ); // header
traceOutput.println( msg );
traceOutput.flush();
} else if ( _traceOutput instanceof LDAPTraceWriter ) {
sb.append( msg );
((LDAPTraceWriter)_traceOutput).write( sb.toString() );
}
}
}
/**
* 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 ) {
_cache = cache;
_messages = (_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( _sendRequestLock ) {
_highMsgId = (_highMsgId + 1) % MAXMSGID;
return _highMsgId;
}
}
/**
* Sends an LDAP request via this connection thread
*
* @param request request to send
* @param toNotify response queue to receive the response
* when ready
*/
void sendRequest( LDAPConnection conn, JDAPProtocolOp request,
LDAPMessageQueue toNotify, LDAPConstraints cons )
throws LDAPException {
if ( !_doRun ) {
throw new LDAPException ( "not connected to a server",
LDAPException.SERVER_DOWN );
}
LDAPMessage msg =
new LDAPMessage( allocateId(), request, cons.getControls() );
LDAPMessageQueueImpl queue = (LDAPMessageQueueImpl)toNotify;
if ( queue != null ) {
if ( !(request instanceof JDAPAbandonRequest ||
request instanceof JDAPUnbindRequest) ) {
/* Only worry about toNotify if we expect a response... */
this._requests.put( new Integer( msg.getMessageID()),
queue );
/* Notify the backlog checker that there may be another
outstanding request */
resultRetrieved();
}
queue.addRequest( msg.getMessageID(), conn, this,
cons.getTimeLimit() );
}
synchronized( _sendRequestLock ) {
try {
if ( _traceOutput != null ) {
logTraceMessage( msg.toTraceString() );
}
msg.write( _serverOutput );
_serverOutput.flush();
} catch ( IOException e ) {
networkError( e );
}
}
}
/**
* Registers with this connection thread
*
* @param conn LDAP connection
*/
public synchronized void register( LDAPConnection conn ) {
if ( !_registered.contains( conn ) )
_registered.addElement( conn );
}
int getClientCount() {
return _registered.size();
}
boolean isRunning() {
return _doRun;
}
/**
* Deregisters with this connection thread. If all connections
* are deregistered, this thread is to be killed.
*
* @param conn LDAP connection
*/
public synchronized void deregister(LDAPConnection conn) {
_registered.removeElement( conn );
if ( _registered.size() == 0 ) {
try {
if ( !_disconnected ) {
LDAPSearchConstraints cons = conn.getSearchConstraints();
sendRequest( null, new JDAPUnbindRequest(), null, cons );
}
// must be set after the call to sendRequest
_doRun =false;
if ( (_thread != null) &&
(_thread != Thread.currentThread()) ) {
_thread.interrupt();
// Wait up to 1 sec for thread to accept disconnect
// notification. When the interrupt is accepted,
// _thread is set to null. See run() method.
try {
wait( 1000 );
}
catch ( InterruptedException e ) {
}
}
} catch( Exception e ) {
LDAPConnection.printDebug( e.toString() );
}
finally {
cleanUp();
}
}
}
/**
* Cleans up before shutting down the thread
*/
private void cleanUp() {
if ( !_disconnected ) {
try {
_serverOutput.close();
} catch ( Exception e ) {
} finally {
_serverOutput = null;
}
try {
_serverInput.close ();
} catch ( Exception e ) {
} finally {
_serverInput = null;
}
try {
_socket.close ();
} catch ( Exception e ) {
} finally {
_socket = null;
}
_disconnected = true;
/**
* Notify the Connection Setup Manager that the connection was
* terminated by the user
*/
_connMgr.disconnect();
/**
* Cancel all outstanding requests
*/
if ( _requests != null ) {
Enumeration requests = _requests.elements();
while ( requests.hasMoreElements() ) {
LDAPMessageQueueImpl queue =
(LDAPMessageQueueImpl)requests.nextElement();
queue.removeAllRequests( this );
}
}
/**
* Notify all the registered queues of this mishap.
* IMPORTANT: This needs to be done last. Otherwise, the socket
* input stream and output stream might never get closed and the
* whole task will get stuck when trying to stop the
* LDAPConnThread.
*/
if ( _registered != null ) {
Vector registerCopy = (Vector)_registered.clone();
Enumeration cancelled = registerCopy.elements();
while ( cancelled.hasMoreElements() ) {
LDAPConnection c = (LDAPConnection)cancelled.nextElement();
c.deregisterConnection();
}
}
_registered.clear();
_registered = null;
_messages = null;
_requests.clear();
_cache = null;
}
}
/**
* Sleep if there is a backlog of search results
*/
private void checkBacklog() throws InterruptedException{
while ( true ) {
if ( _requests.size() == 0 ) {
return;
}
Enumeration queues = _requests.elements();
while( queues.hasMoreElements() ) {
LDAPMessageQueue l = (LDAPMessageQueue)queues.nextElement();
// If there are any threads waiting for a regular response
// message, we have to go read the next incoming message
if ( !(l instanceof LDAPSearchQueue ) ) {
return;
}
LDAPSearchQueue sl = (LDAPSearchQueue)l;
// should never happen, but just in case
if ( sl.getSearchConstraints() == null ) {
return;
}
int slMaxBacklog = sl.getSearchConstraints().getMaxBacklog();
int slBatchSize = sl.getSearchConstraints().getBatchSize();
// Disabled backlog check ?
if ( slMaxBacklog == 0 ) {
return;
}
// Synch op with zero batch size ?
if ( !sl.isAsynchOp() && slBatchSize == 0 ) {
return;
}
// Max backlog not reached for at least one queue ?
// (if multiple requests are in progress)
if ( sl.getMessageCount() < slMaxBacklog ) {
return;
}
}
synchronized( this ) {
wait( 3000 );
}
}
}
/**
* This is called when a search result has been retrieved from the incoming
* queue. We use the notification to unblock the queue 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 establishing a connection to the server,
// stop the thread right away...
if ( !_doRun ) {
return;
}
_thread = Thread.currentThread();
LDAPMessage msg = null;
JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
while ( _doRun ) {
yield();
int[] nread = new int[1];
nread[0] = 0;
try {
// Check after every BACKLOG_CHKCNT number of messages if the
// backlog is too high
if ( --_backlogCheckCounter <= 0 ) {
_backlogCheckCounter = BACKLOG_CHKCNT;
checkBacklog();
}
BERElement element = BERElement.getElement( decoder,
_serverInput,
nread );
msg = LDAPMessage.parseMessage( element );
if ( _traceOutput != null ) {
logTraceMessage( msg.toTraceString() );
}
// pass 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 (_doRun) {
networkError( e );
} else {
// interrupted from deregister()
synchronized( this ) {
_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() );
LDAPMessageQueueImpl l =
(LDAPMessageQueueImpl)_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 ( (_cache != null) && (l instanceof LDAPSearchQueue) ) {
cacheSearchResult( (LDAPSearchQueue)l, msg, size );
}
l.addMessage( msg );
if ( msg instanceof LDAPResponse ) {
_requests.remove( messageID );
if ( _requests.size() == 0 ) {
_backlogCheckCounter = BACKLOG_CHKCNT;
}
}
}
/**
* Collects search results to be added to the LDAPCache. Search results are
* packaged in a vector and temporary stored into a hashtable _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( LDAPSearchQueue l,
LDAPMessage msg, int size ) {
Integer messageID = new Integer( msg.getMessageID() );
Long key = l.getKey();
Vector v = null;
if ( (_cache == null) || (key == null) ) {
return;
}
if ( msg instanceof LDAPSearchResult ) {
// Get the vector containing the LDAPMessages for the specified
// messageID
v = (Vector)_messages.get( messageID );
if ( v == null ) {
_messages.put( messageID, v = new Vector() );
v.addElement( new Long(0) );
}
// Return if the entry size is -1, i.e. 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 an LDAPEntry object gets
// stored in the cache instead of the 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 > _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)_messages.get(messageID);
if ( v == null ) {
_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)_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
// disabled)
if ( ((Long)v.firstElement()).longValue() != -1L ) {
_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 ) {
if ( !_doRun ) {
return;
}
LDAPMessageQueueImpl l =
(LDAPMessageQueueImpl)_requests.remove( new Integer(id) );
// Clean up cache if enabled
if ( _messages != null ) {
_messages.remove( new Integer(id) );
}
if ( l != null ) {
l.removeRequest( id );
}
resultRetrieved(); // If LDAPConnThread is blocked in checkBacklog()
}
/**
* Changes the queue for a message ID. Required when
* LDAPMessageQueue.merge() is invoked.
*
* @param id Message ID for which to change the queue
* @return Previous queue
*/
LDAPMessageQueue changeQueue( int id, LDAPMessageQueue toNotify ) {
if ( !_doRun ) {
LDAPMessageQueueImpl queue = (LDAPMessageQueueImpl)toNotify;
queue.setException( this,
new LDAPException( "Server down",
LDAPException.OTHER ) );
return null;
}
return (LDAPMessageQueue)_requests.put( new Integer(id), toNotify );
}
/**
* 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 ) {
_doRun = false;
// notify the Connection Setup Manager that the connection is lost
_connMgr.invalidateConnection();
try {
// notify each queue that the server is down.
Enumeration requests = _requests.elements();
while ( requests.hasMoreElements() ) {
LDAPMessageQueueImpl queue =
(LDAPMessageQueueImpl)requests.nextElement();
queue.setException( this,
new LDAPException( "Server down",
LDAPException.OTHER) );
}
} catch( NullPointerException ee ) {
System.err.println( "Exception: " + ee.toString() );
}
cleanUp();
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,299 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.io.Serializable;
import java.util.Hashtable;
/**
* 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, Serializable {
static final long serialVersionUID = 6506767263918312029L;
private int _hop_limit = 5;
private LDAPReferralHandler _referralHandler = null;
private boolean referrals = false;
private int _time_limit = 0;
private LDAPControl[] _serverControls = null;
private Hashtable _properties = null;
/**
* Constructs an <CODE>LDAPConstraints</CODE> object that specifies
* the default set of constraints.
*/
public LDAPConstraints() {
}
/**
* 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 handler specifies the object that
* implements the <CODE>LDAPReferralHandler</CODE> interface (you need to
* define this class). The object will be used when the client
* follows referrals automatically. See org.ietf.ldap.LDAPAuthHandler
* and org.ietf.ldap.LDAPReferralHandler.
* (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 org.ietf.ldap.LDAPConnection#setOption(int, java.lang.Object)
*/
public LDAPConstraints( int msLimit, boolean doReferrals,
LDAPReferralHandler handler,
int hop_limit ) {
_time_limit = msLimit;
referrals = doReferrals;
_referralHandler = handler;
_hop_limit = hop_limit;
_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 _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 getReferralFollowing() {
return referrals;
}
/**
* Returns the object that provides the mechanism for authenticating to the
* server on referrals. This object must implement the
* <CODE>LDAPReferralHandler</CODE> interface.
* @return object to use to authenticate to the server on referrals
* @see org.ietf.ldap.LDAPReferralHandler
*/
public LDAPReferralHandler getReferralHandler() {
return _referralHandler;
}
/**
* 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 _hop_limit;
}
/**
* 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 org.ietf.ldap.LDAPControl
* @see org.ietf.ldap.LDAPConnection#getOption
* @see org.ietf.ldap.LDAPConnection#setOption
*/
public LDAPControl[] getControls() {
return _serverControls;
}
/**
* Gets a property of a constraints object which has been assigned with
* setProperty. Null is returned if the property is not defined.
*
* @param name Name of the property to retrieve
*/
public Object getProperty( String name ) {
if ( _properties == null ) {
return null;
}
return _properties.get( name );
}
/**
* 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 org.ietf.ldap.LDAPException#LDAP_TIMEOUT
*/
public void setTimeLimit( int msLimit ) {
_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>LDAPAuthHandler</CODE> or
* <CODE>LDAPBind</CODE> interface. The <CODE>LDAPAuthProvider</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>setReferralHandler</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>setBindHandler</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 org.ietf.ldap.LDAPBindHandler
* @see org.ietf.ldap.LDAPAuthHandler
* @see org.ietf.ldap.LDAPAuthProvider
*/
public void setReferralFollowing( boolean doReferrals ) {
referrals = doReferrals;
}
/**
* Specifies the object that provides the method for getting
* authentication information. This object must belong to a class
* that implements the <CODE>LDAPReferralHandler</CODE> interface.
* (By default, this is <CODE>null</CODE>.) This method sets the
* <CODE>LDAPReferralHandler</CODE> object to null for this constraint.
* @param handler object to use to obtain information for
* authenticating to other LDAP servers during referrals
*/
public void setReferralHandler( LDAPReferralHandler handler ) {
_referralHandler = handler;
}
/**
* 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 ) {
_hop_limit = hop_limit;
}
/**
* Sets a server control for LDAP operations.
* @param control server control for LDAP operations
* @see org.ietf.ldap.LDAPControl
*/
public void setControls( LDAPControl control ) {
_serverControls = new LDAPControl[1];
_serverControls[0] = control;
}
/**
* Sets an array of server controls for LDAP operations.
* @param controls an array of server controls for LDAP operations
* @see org.ietf.ldap.LDAPControl
*/
public void setControls( LDAPControl[] controls ) {
_serverControls = controls;
}
/**
* Sets a property of the constraints object.
* No property names have been defined at this time, but the mechanism
* is in place in order to support revisional as well as dynamic and
* proprietary extensions to operation modifiers.
*
* @param name Name of the property to set
* @param value Value to assign to the property
*/
public void setProperty( String name, Object value ) throws LDAPException {
if ( _properties == null ) {
_properties = new Hashtable();
}
_properties.put( name, value );
}
/**
* 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 " + getReferralFollowing() + ", ");
sb.append("hop limit " + getHopLimit() + ", ");
sb.append("referral handler " + getReferralHandler() + ", ");
LDAPControl[] controls = getControls();
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.
* @return a copy of an existing set of constraints
*/
public Object clone() {
LDAPConstraints o = new LDAPConstraints();
o._time_limit = this._time_limit;
o.referrals = this.referrals;
o._referralHandler = this._referralHandler;
o._hop_limit = this._hop_limit;
if ( (this._serverControls != null) &&
(this._serverControls.length > 0) ) {
o._serverControls = new LDAPControl[this._serverControls.length];
for( int i = 0; i < this._serverControls.length; i++ )
o._serverControls[i] =
(LDAPControl)this._serverControls[i].clone();
}
return o;
}
}

Просмотреть файл

@ -0,0 +1,506 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
import org.ietf.ldap.ber.stream.*;
import org.ietf.ldap.client.*;
import org.ietf.ldap.util.*;
import org.ietf.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 org.ietf.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
* @see org.ietf.ldap.LDAPConnection#getOption
* @see org.ietf.ldap.LDAPConnection#setOption
* @see org.ietf.ldap.LDAPConnection#getResponseControls
* @see org.ietf.ldap.LDAPConstraints#getControls
* @see org.ietf.ldap.LDAPConstraints#setControls
*/
public class LDAPControl implements Cloneable, 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 org.ietf.ldap.LDAPConstraints#setControls
*/
public LDAPControl( String id,
boolean critical,
byte vals[] ) {
_oid = id;
_critical = critical;
_value = vals;
}
/**
* Gets the object ID (OID) of the control.
* @return object ID (OID) of the control.
*/
public String getID() {
return _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 _critical;
}
/**
* Gets the data in the control.
* @return the data in the control as a byte array.
*/
public byte[] getValue() {
return _value;
}
/**
* Gets the ber representation of control.
* @return ber representation of control.
*/
BERElement getBERElement() {
BERSequence seq = new BERSequence();
seq.addElement(new BEROctetString (_oid));
seq.addElement(new BERBoolean (_critical));
if ( (_value == null) || (_value.length < 1) )
seq.addElement(new BEROctetString ((byte[])null));
else {
seq.addElement(new BEROctetString (_value, 0, _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 org.ietf.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 (_controlClassHash == null) {
_controlClassHash = new Hashtable();
}
// 4. add the controlClass
_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 org.ietf.ldap.LDAPControl#register
*
*/
protected static Class lookupControlClass( String oid ) {
if ( _controlClassHash == null ) {
return null;
}
return (Class)_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 org.ietf.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 org.ietf.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 org.ietf.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 ( _value != null ) {
vals = new byte[_value.length];
for( int i = 0; i < _value.length; i++ )
vals[i] = _value[i];
}
LDAPControl control = new LDAPControl( _oid, _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 ( _value != null ) {
s += ' ' + LDIF.toPrintableString( _value );
}
return "LDAPControl {" + s + '}';
}
private String _oid;
protected boolean _critical = false;
protected byte[] _value = null;
static private Hashtable _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) {
}
}
}

Просмотреть файл

@ -0,0 +1,363 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.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 org.ietf.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 names names 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[] names,
String oid,
String description,
boolean obsolete,
String[] auxiliary,
String[] required,
String[] optional,
String[] precluded ) {
super( names, oid, description );
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 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;
}
/**
* 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 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 attribute name for a schema element
*
* @return The attribute name of the element
*/
String getAttributeName() {
return "ldapditcontentrules";
}
/**
* Prepares a value in RFC 2252 format for submission to a server
*
* @return a String ready for submission to an LDAP server.
*/
String getValue() {
String s = getValuePrefix();
String 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 Directory format
*
* @return definition of the rule in Directory format
*/
public String toString() {
return getValue();
}
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();
}

Просмотреть файл

@ -0,0 +1,269 @@
/* -*- 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 org.ietf.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 org.ietf.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 names names of the element
* @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[] names,
int ruleID,
String description,
boolean obsolete,
String nameForm,
String[] superiors ) {
super( names, "", description );
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 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;
}
/**
* 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 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 );
}
/**
* Prepares a value in RFC 2252 format for submission to a server
*
* @return a String ready for submission to an LDAP server.
*/
String getValue() {
String s = "( " + ruleID + ' ';
s += getNameField();
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 Directory format
*
* @return definition of the rule in Directory format
*/
public String toString() {
return getValue();
}
/**
* Gets the attribute name for a schema element
*
* @return The attribute name of the element
*/
String getAttributeName() {
return "ldapditstructurerules";
}
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;
}

Просмотреть файл

@ -0,0 +1,185 @@
/* -*- 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 org.ietf.ldap;
import java.util.*;
import org.ietf.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 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 org.ietf.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;
}
}
/**
* 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));
}
/**
* Returns the RDN after escaping the characters specified
* by <CODE>org.ietf.ldap.util.DN.ESCAPED_CHAR</CODE>.
* <P>
*
* @param rdn the RDN to escape
* @return the RDN with the characters escaped.
* @see org.ietf.ldap.util.DN#ESCAPED_CHAR
* @see org.ietf.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 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 org.ietf.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 true if the string conforms to distinguished name syntax;
* NOT IMPLEMENTED YET
*
* @param dn string to evaluate for distinguished name syntax
* @return true if the string conforms to distinguished name syntax
*/
public boolean isValid( String dn ) {
return true;
}
/**
* Normalizes the dn.
* @param dn the DN to normalize
* @return the normalized DN
*/
public static String normalize(String dn) {
return (new DN(dn)).toString();
}
/**
* Returns the RDN after unescaping any escaped characters.
* For a list of characters that are typically escaped in a
* DN, see <CODE>org.ietf.ldap.LDAPDN.ESCAPED_CHAR</CODE>.
* <P>
*
* @param rdn the RDN to unescape
* @return the unescaped RDN.
* @see org.ietf.ldap.util.DN#ESCAPED_CHAR
* @see org.ietf.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));
}
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;
}
}

Просмотреть файл

@ -0,0 +1,207 @@
/* -*- 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 org.ietf.ldap;
import java.io.Serializable;
import java.util.*;
/**
* Represents an entry in the directory.
*
* @version 1.0
*/
public class LDAPEntry implements 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 org.ietf.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;
}
/**
* 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 org.ietf.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 org.ietf.ldap.LDAPAttribute
*/
public LDAPAttribute getAttribute( String attrName, String lang ) {
return attrSet.getAttribute( attrName, lang );
}
/**
* Returns the attribute set of the entry.
* @return set of attributes in the entry.
* @see org.ietf.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 org.ietf.ldap.LDAPAttributeSet
* @see org.ietf.ldap.LDAPAttributeSet#getSubset
*/
public LDAPAttributeSet getAttributeSet(String subtype) {
return attrSet.getSubset(subtype);
}
/**
* 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();
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,171 @@
/* -*- 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 org.ietf.ldap;
import java.io.Serializable;
/**
* 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 org.ietf.ldap.LDAPConnection#extendedOperation(org.ietf.ldap.LDAPExtendedOperation)
* @see org.ietf.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
*
*/
public class LDAPExtendedOperation implements 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 ) {
_oid = oid;
_vals = vals;
}
/**
* Gets the identifier for this operation
*
* @return identifier for the operation
*/
public String getID() {
return _oid;
}
/**
* Gets the data for this operation
*
* @return operation-specific data
*/
public byte[] getValue() {
return _vals;
}
/**
* Sets the data for this operation
*
* @param vals operation-specific data
*/
public void setValue( byte[] vals ) {
_vals = vals;
}
private String _oid;
private byte[] _vals;
}

Просмотреть файл

@ -0,0 +1,70 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.io.Serializable;
import org.ietf.ldap.client.opers.JDAPExtendedResponse;
/**
* Represents a server response to an extended operation request.
*
* @version 1.0
*/
public class LDAPExtendedResponse extends LDAPResponse
implements 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 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();
}
}

Просмотреть файл

@ -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 org.ietf.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 org.ietf.ldap.LDAPInterruptedException#toString()
*/
LDAPInterruptedException( String message ) {
super( message, LDAPException.OTHER, (Throwable)null);
}
/**
* Gets the string representation of the exception.
*/
public String toString() {
String str = "org.ietf.ldap.LDAPInterruptedException: ";
String msg = super.getMessage();
if (msg != null) {
str +=msg;
}
return str;
}
}

Просмотреть файл

@ -0,0 +1,302 @@
/* -*- 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 org.ietf.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 org.ietf.ldap.LDAPSchemaElement
**/
public class LDAPMatchingRuleSchema extends LDAPAttributeSchema {
static final long serialVersionUID = 6466155218986944131L;
/**
* Constructs a matching rule definition, using the specified
* information.
* @param names 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 obsolete <CODE>true</CODE> if the element is obsolete
* @param syntaxString syntax of this matching rule in dotted-decimal
* format
*/
public LDAPMatchingRuleSchema( String[] names,
String oid,
String description,
String[] attributes,
boolean obsolete,
String syntaxString ) {
if ( (oid == null) || (oid.trim().length() < 1) ) {
throw new IllegalArgumentException( "OID required" );
}
this.names = names;
this.oid = oid;
this.description = description;
attrName = "matchingrules";
syntaxElement.syntax = syntaxElement.syntaxCheck( syntaxString );
syntaxElement.syntaxString = syntaxString;
setQualifier( SYNTAX, syntaxElement.syntaxString );
_attributes = new String[attributes.length];
for( int i = 0; i < attributes.length; i++ ) {
this._attributes[i] = attributes[i];
}
if ( obsolete ) {
setQualifier( OBSOLETE, "" );
}
}
/**
* 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 attribute name for a schema element
*
* @return The attribute name of the element
*/
String getAttributeName() {
return "matchingrules";
}
/**
* 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
*/
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;
}
/**
* Gets the definition of the matching rule in Directory format
*
* @return definition of the matching rule in Directory format
*/
public String toString() {
return getValue( false );
}
// Qualifiers tracked explicitly
static final String[] EXPLICIT = { OBSOLETE,
SYNTAX };
private String[] _attributes = null;
}

Просмотреть файл

@ -0,0 +1,215 @@
/* -*- 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 org.ietf.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 org.ietf.ldap.LDAPSchemaElement
* @see org.ietf.ldap.LDAPMatchingRuleSchema
**/
public class LDAPMatchingRuleUseSchema extends LDAPAttributeSchema {
/**
* Constructs a matching rule use definition, using the specified
* information.
* @param names names 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 obsolete <CODE>true</CODE> if the element is obsolete
* @param attributes array of the OIDs of the attributes for which
* the matching rule is applicable
*/
public LDAPMatchingRuleUseSchema( String[] names,
String oid,
String description,
boolean obsolete,
String[] attributes ) {
if ( (oid == null) || (oid.trim().length() < 1) ) {
throw new IllegalArgumentException( "OID required" );
}
this.names = names;
this.oid = oid;
this.description = description;
attrName = "matchingruleuse";
_attributes = new String[attributes.length];
for( int i = 0; i < attributes.length; i++ ) {
_attributes[i] = attributes[i];
}
if ( obsolete ) {
setQualifier( OBSOLETE, "" );
}
}
/**
* 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 attribute name for a schema element
*
* @return The attribute name of the element
*/
String getAttributeName() {
return "matchingruleuse";
}
/**
* 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 Directory format
*
* @return definition of the matching rule use in Directory format
*/
public String toString() {
return getValue();
}
// Qualifiers tracked explicitly
static final String[] EXPLICIT = { OBSOLETE };
private String[] _attributes = null;
}

Просмотреть файл

@ -0,0 +1,280 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.util.*;
import org.ietf.ldap.client.opers.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
import java.net.*;
/**
* 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 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 _msgid;
private JDAPProtocolOp _protocolOp = null;
private LDAPControl _controls[] = null;
/**
* Constructs a ldap message.
* @param msgid message identifier
* @param op operation protocol
*/
LDAPMessage(int msgid, JDAPProtocolOp op) {
_msgid = msgid;
_protocolOp = op;
}
LDAPMessage(int msgid, JDAPProtocolOp op, LDAPControl controls[]) {
_msgid = msgid;
_protocolOp = op;
_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);
}
}
/**
* Retrieves list of controls.
* @return controls.
*/
public LDAPControl[] getControls() {
return (_controls != null) ? _controls : new LDAPControl[0];
}
/**
* Returns the message identifer.
* @return message identifer.
*/
public int getMessageID(){
return _msgid;
}
/**
* Returns the LDAP operation type of the message
* @return message type.
*/
public int getType(){
return _protocolOp.getType();
}
/**
* Retrieves the protocol operation.
* @return protocol operation.
*/
JDAPProtocolOp getProtocolOp() {
return _protocolOp;
}
/**
* Writes the ber encoding to stream.
* @param s output stream
*/
void write(OutputStream s) throws IOException {
BERSequence seq = new BERSequence();
BERInteger i = new BERInteger(_msgid);
seq.addElement(i);
BERElement e = _protocolOp.getBERElement();
if (e == null) {
throw new IOException("Bad BER element");
}
seq.addElement(e);
if (_controls != null) { /* LDAPv3 additions */
BERSequence c = new BERSequence();
for (int j = 0; j < _controls.length; j++) {
c.addElement(_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(_msgid);
sb.append(" ");
sb.append(_protocolOp.toString());
for (int i =0; _controls != null && i < _controls.length; i++) {
sb.append(" ");
sb.append(_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
*/
StringBuffer toTraceString() {
StringBuffer sb = new StringBuffer(" op=");
sb.append(_msgid);
sb.append(" ");
sb.append(_protocolOp.toString());
for (int i =0; _controls != null && i < _controls.length; i++) {
sb.append(" ");
sb.append(_controls[i].toString());
}
return sb;
}
}

Просмотреть файл

@ -0,0 +1,116 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.io.Serializable;
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.
*
*/
public interface LDAPMessageQueue {
/**
* Returns the count of queued messages
* @return message count
*/
public int getMessageCount();
/**
* Returns a list of message IDs for all outstanding requests
* @return message ID array.
*/
public int[] getMessageIDs();
/**
* 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
*/
public LDAPMessage getResponse() throws LDAPException;
/**
* Blocks until a response is available for a particular message ID, or
* until all operations associated with the message ID have completed or
* been canceled, and returns the response. If there is no outstanding
* operation for the message ID (or if it is zero or a negative number),
* IllegalArgumentException is thrown.
*
* @param msgid A particular message to query for responses available
* @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 LDAPMessage getResponse( int msgid )
throws LDAPException;
/**
* Checks if a response message has been received
*
* @return true or false.
*/
public boolean isResponseReceived();
/**
* Reports true if a response has been received from the server for a
* particular message ID. If there is no outstanding operation for the
* message ID (or if it is zero or a negative number),
* IllegalArgumentException is thrown.
*
* @param msgid A particular message to query for responses available
* @return a flag indicating whether the response message queue is empty
*/
public boolean isResponseReceived( int msgid );
/**
* 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 queue 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 queue
* 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
*/
public void merge( LDAPMessageQueue mq2 );
}

Просмотреть файл

@ -0,0 +1,663 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.io.Serializable;
import java.util.ArrayList;
/**
* 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.
*
* Used as a delegate by LDAResponseListener and LDAPSearchListener
*
*/
class LDAPMessageQueueImpl implements Serializable, LDAPMessageQueue {
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
*/
protected /*LDAPMessage */ ArrayList _messageQueue = new ArrayList(1);
private /*RequestEntry*/ ArrayList _requestList = new ArrayList(1);
private LDAPException _exception; /* For network errors */
private boolean _asynchOp;
// A flag to indicate if there are time constrained requests
private boolean _timeConstrained;
/**
* Constructor
*
* @param asynchOp <CODE>true</CODE> if the object is used
* for asynchronous LDAP operations
* @see org.ietf.ldap.LDAPAsynchronousConnection
*/
LDAPMessageQueueImpl( boolean asynchOp ) {
_asynchOp = asynchOp;
}
/**
* Returns the count of queued messages
*
* @return message count
*/
public int getMessageCount() {
return _messageQueue.size();
}
/**
* Returns a list of message IDs for all outstanding requests
*
* @return message ID array
*/
synchronized public int[] getMessageIDs() {
int[] ids = new int[_requestList.size()];
for ( int i = 0; i < ids.length; i++ ) {
RequestEntry entry = (RequestEntry)_requestList.get(i);
ids[i] = entry.id;
}
return ids;
}
/**
* Blocks until a message 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
*/
public synchronized LDAPMessage getResponse() throws LDAPException {
while( true ) {
if ( !waitForSomething() ) {
return null; // No outstanding requests
}
// Dequeue the first entry
LDAPMessage msg = (LDAPMessage)_messageQueue.get( 0 );
_messageQueue.remove( 0 );
// Has the operation completed?
if ( msg instanceof LDAPResponse ) {
removeRequest( msg.getMessageID() );
}
return msg;
}
}
/**
* Blocks until a message is available for a particular message ID, or
* until all operations associated with the message ID have completed or
* been canceled, and returns the response. If there is no outstanding
* operation for the message ID (or if it is zero or a negative number),
* IllegalArgumentException is thrown.
*
* @param msgid A particular message to query for responses available
* @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 synchronized LDAPMessage getResponse( int msgid )
throws LDAPException {
if ( !isValidMessageID( msgid ) ) {
throw new IllegalArgumentException( "Invalid msg ID: " + msgid );
}
LDAPMessage msg = null;
while( ( _requestList.size() != 0 ) &&
( _exception == null ) &&
( (msg = getMessageForID( msgid, true )) == null ) ) {
waitForMessage();
}
// Network exception occurred?
if ( _exception != null ) {
LDAPException ex = _exception;
_exception = null;
throw ex;
}
// Are there any outstanding requests left?
if ( _requestList.size() == 0 ) {
return null; // No outstanding requests
}
// Has the operation completed?
if ( msg instanceof LDAPResponse ) {
removeRequest( msg.getMessageID() );
}
return msg;
}
/**
* Checks if a response message has been received
*
* @return true or false
*/
public boolean isResponseReceived() {
return ( _messageQueue.size() != 0 );
}
/**
* Reports true if a response has been received from the server for a
* particular message ID. If there is no outstanding operation for the
* message ID (or if it is zero or a negative number),
* IllegalArgumentException is thrown.
*
* @param msgid A particular message to query for responses available
* @return a flag indicating whether the response message queue is empty
*/
public boolean isResponseReceived( int msgid ) {
if ( !isValidMessageID( msgid ) ) {
throw new IllegalArgumentException( "Invalid msg ID: " + msgid );
}
return ( getMessageForID( msgid, false ) != null );
}
/**
* 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
*/
public void merge( LDAPMessageQueue mq2 ) {
// Yield just in case the LDAPConnThread is in the process of
// dispatching a message
Thread.yield();
synchronized( this ) {
LDAPMessageQueueImpl mq = (LDAPMessageQueueImpl)mq2;
synchronized( mq ) {
ArrayList queue2 = mq.getAllMessages();
for( int i = 0; i < queue2.size(); i++ ) {
_messageQueue.add( queue2.get( i ) );
}
if ( mq.getException() != null ) {
_exception = mq.getException();
}
ArrayList list2 = mq.getAllRequests();
for( int i = 0; i < list2.size(); i++ ) {
RequestEntry entry = (RequestEntry)list2.get( i );
_requestList.add( entry );
// Notify LDAPConnThread to redirect mq2 designated
// responses to this mq
entry.connThread.changeQueue( entry.id, this );
}
mq.reset();
notifyAll(); // notify for mq2
}
notifyAll(); // notify this mq
}
}
/**
* Gets String representation of the object
*
* @return String representation of the object
*/
synchronized public String toString() {
StringBuffer sb = new StringBuffer( "LDAPMessageQueueImpl:" );
sb.append(" requestIDs={");
for ( int i = 0; i < _requestList.size(); i++ ) {
if ( i > 0 ) {
sb.append( "," );
}
sb.append( ((RequestEntry)_requestList.get(i)).id );
}
sb.append( "} messageCount=" + _messageQueue.size() );
return sb.toString();
}
/**
* Retrieves the next response for a particular message ID, or null
* if there is none
*
* @param msgid A particular message to query for responses available
* @param remove <code>true</code> if the retrieved message is to be
* removed from the queue
* @return a flag indicating whether the response message queue is empty
*/
synchronized LDAPMessage getMessageForID( int msgid, boolean remove ) {
LDAPMessage msg = null;
for ( int i = 0; i < _messageQueue.size(); i++ ) {
msg = (LDAPMessage)_messageQueue.get(i);
if ( msg.getMessageID() == msgid ) {
if ( remove ) {
_messageQueue.remove( i );
}
break;
}
}
return msg;
}
/**
* Reports if the listener is used for asynchronous LDAP
* operations
*
* @return asynchronous operation flag.
* @see org.ietf.ldap.LDAPAsynchronousConnection
*/
boolean isAsynchOp() {
return _asynchOp;
}
/**
* Waits 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 ) {
if ( !waitForSomething() ) {
return null; // No outstanding requests
}
// Search for an instance of LDAPResponse
for ( int i = _messageQueue.size()-1; i >= 0; i-- ) {
Object msg = _messageQueue.get(i);
if ( msg instanceof LDAPResponse ) {
// Dequeue the entry and return
_messageQueue.remove( i );
return (LDAPResponse)msg;
}
}
// Not found, wait for the next message
}
}
/**
* Waits for any message. Processes interrupts and honors
* time limit if set for any request.
*/
synchronized private void waitForMessage() throws LDAPException {
if ( !_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 < _requestList.size(); i++ ) {
RequestEntry entry = (RequestEntry)_requestList.get( 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 {
_timeConstrained = ( timeLimit != 0 );
wait( timeLimit );
} catch ( InterruptedException e ) {
throw new LDAPInterruptedException( "Interrupted LDAP operation" );
}
}
/**
* Waits for a message, for the request list to be empty, or for
* an exception
*
* @return <CODE>true</CODE> if the request list is not empty
* @exception LDAPException Network error
*/
boolean waitForSomething() throws LDAPException {
while( (_requestList.size() != 0) &&
(_exception == null) &&
(_messageQueue.size() == 0) ) {
waitForMessage();
}
// Network exception occurred ?
if ( _exception != null ) {
LDAPException ex = _exception;
_exception = null;
throw ex;
}
// Are there any outstanding requests left
if ( _requestList.size() == 0 ) {
return false; // No outstanding requests
}
return true;
}
/**
* Retrieves all messages currently in the queue without blocking.
* The messages are removed from the queue.
*
* @return vector of messages
*/
synchronized ArrayList getAllMessages() {
ArrayList result = _messageQueue;
_messageQueue = new ArrayList(1);
return result;
}
/**
* Retrieves all requests currently in the queue.
* The requests are removed from the queue.
*
* @return vector of requests
*/
synchronized ArrayList getAllRequests() {
ArrayList result = _requestList;
_requestList = new ArrayList(1);
return result;
}
/**
* Queues the LDAP server's response. This causes anyone waiting
* in getResponse() to unblock.
*
* @param msg response message
*/
synchronized void addMessage( LDAPMessage msg ) {
_messageQueue.add(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();
}
/**
* Gets a possible exception from the queue
*
* @return a possibly null exception
*/
LDAPException getException() {
return _exception;
}
/**
* Reports if the message ID is in the request list
*
* @param msgid The message ID to validate
* @return <CODE>true</CODE> if the message ID is in the request list
*/
synchronized boolean isValidMessageID( int msgid ) {
return ( getRequestEntry( msgid ) != null );
}
/**
* Signals that a network exception occured while servicing the
* request. This exception will be throwm to any thread waiting
* in getResponse().
*
* @param connThread LDAPConnThread on which the exception occurred
* @param e exception
*/
synchronized void setException( LDAPConnThread connThread,
LDAPException e ) {
_exception = e;
removeAllRequests( connThread );
notifyAll();
}
/**
* Remove all queued messages associated with the request ID.
* Called when an LDAP operation is abandoned.
*
* Not synchronized as it is 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 = (_messageQueue.size()-1); i >= 0; i-- ) {
LDAPMessage msg = (LDAPMessage)_messageQueue.get( i );
if ( msg.getMessageID() == id ) {
_messageQueue.remove( i );
removeCount++;
}
}
return removeCount;
}
/**
* Resets the state of this object so it can be recycled.
* Used by LDAPConnection synchronous operations.
*
* @see org.ietf.ldap.LDAPConnection#getResponseListener
* @see org.ietf.ldap.LDAPConnection#getSearchListener
*/
void reset() {
_exception = null;
_messageQueue.clear();
_requestList.clear();
_timeConstrained = false;
}
/**
* Returns the connection associated with the specified request id
*
* @param id request id
* @return connection
*/
synchronized LDAPConnection getConnection( int id ) {
RequestEntry entry = getRequestEntry( id );
if ( entry != null ) {
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 ) {
RequestEntry entry = getRequestEntry( id );
if ( entry != null ) {
return entry.connThread;
}
return null;
}
/**
* Returns the request entry associated with the specified request id
*
* @param id request id
* @return request entry or null
*/
synchronized RequestEntry getRequestEntry( int id ) {
for ( int i = 0; i < _requestList.size(); i++ ) {
RequestEntry entry = (RequestEntry)_requestList.get( i );
if ( id == entry.id ) {
return entry;
}
}
return null;
}
/**
* Returns message ID of the last request
*
* @return message ID
*/
synchronized int getMessageID() {
int reqCnt = _requestList.size();
if ( reqCnt == 0 ) {
return -1;
} else {
RequestEntry entry =
(RequestEntry)_requestList.get( reqCnt-1 );
return entry.id;
}
}
/**
* Registers an 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 ) {
_requestList.add( new RequestEntry( id, connection,
connThread, timeLimit ) );
if ( timeLimit != 0 ) {
_timeConstrained = true;
}
notifyAll();
}
/**
* Returns the number of outstanding requests.
* @return outstanding request count.
*/
public int getRequestCount() {
return _requestList.size();
}
/**
* Removes the request with the specified ID.
* Called when a LDAP operation is abandoned (called from
* LDAPConnThread), or terminated (called by getResponse() when
* LDAPResponse message is received).
*
* @return flag indicating if the request was removed
*/
synchronized boolean removeRequest( int id ) {
for ( int i = 0; i < _requestList.size(); i++ ) {
RequestEntry entry = (RequestEntry)_requestList.get( i );
if ( id == entry.id ) {
_requestList.remove( i );
removeAllMessages( id );
notifyAll();
return true;
}
}
return false;
}
/**
* Removes 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 = (_requestList.size()-1); i >= 0; i-- ) {
RequestEntry entry = (RequestEntry)_requestList.get( i );
if ( connThread == entry.connThread ) {
_requestList.remove( i );
removeCount++;
// remove all queued messages as well
removeAllMessages( entry.id );
}
}
notifyAll();
return removeCount;
}
}

Просмотреть файл

@ -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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.io.Serializable;
import org.ietf.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 org.ietf.ldap.LDAPConnection#modify(java.lang.String, org.ietf.ldap.LDAPModification)
*/
public class LDAPModification implements 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 org.ietf.ldap.LDAPAttribute
*/
public LDAPModification( int op, LDAPAttribute attr ) {
operation = op;
attribute = attr;
}
/**
* Returns the attribute (possibly with values) to be modified.
* @return the attribute to be modified.
* @see org.ietf.ldap.LDAPAttribute
*/
public LDAPAttribute getAttribute() {
return attribute;
}
/**
* 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;
}
/**
* 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;
}
}

Просмотреть файл

@ -0,0 +1,287 @@
/* -*- 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 org.ietf.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 org.ietf.ldap.LDAPSchemaElement
**/
public class LDAPNameFormSchema extends LDAPSchemaElement {
static final long serialVersionUID = 1665316286199590403L;
/**
* Constructs a name form definition, using the specified
* information.
* @param names 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[] names,
String oid,
String description,
boolean obsolete,
String objectClass,
String[] required,
String[] optional ) {
super( names, oid, description );
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;
}
}
/**
* 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;
}
/**
* 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;
}
/**
* 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 attribute name for a schema element
*
* @return The attribute name of the element
*/
String getAttributeName() {
return "nameforms";
}
/**
* 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 Directory format
*
* @return definition of the name form in Directory format
*/
public String toString() {
return getValue( false );
}
/**
* 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"};
}

Просмотреть файл

@ -0,0 +1,350 @@
/* -*- 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 org.ietf.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 org.ietf.ldap.LDAPSchemaElement
**/
public class LDAPObjectClassSchema extends LDAPSchemaElement {
static final long serialVersionUID = -1732784695071118656L;
/**
* Constructs an object class definition, using the specified
* information.
* @param names names 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 obsolete <code>true</code> if the rule is obsolete
*/
public LDAPObjectClassSchema( String[] names,
String oid,
String[] superiors,
String description,
String[] required,
String[] optional,
int type,
boolean obsolete ) {
super( names, oid, description );
attrName = "objectclasses";
setQualifier( SUPERIOR, superiors );
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 ( (superiors != null) && (superiors.length > 1) ) {
setQualifier( SUPERIOR, superiors );
}
if ( obsolete ) {
setQualifier( OBSOLETE, "" );
}
}
/**
* 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 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 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 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 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 Directory format
*
* @return definition of the object class in Directory format
*/
public String toString() {
return getValue();
}
/**
* Gets the attribute name for a schema element
*
* @return The attribute name of the element
*/
String getAttributeName() {
return "objectclasses";
}
/**
* 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";
}

Просмотреть файл

@ -0,0 +1,213 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.util.*;
//import org.ietf.ldap.client.*;
//import org.ietf.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 org.ietf.ldap.LDAPException
*/
public class LDAPReferralException extends LDAPException {
static final long serialVersionUID = 1771536577344289897L;
private String _referrals[] = null;
/**
* 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, (String)null);
_referrals = referrals;
}
/**
* Constructs an exception with a result code, a specified
* string of additional information, a string containing
* information passed back from the server, and a possible root
* exception.
* <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>
* </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 rootException An exception which caused the failure, if any
* @see org.ietf.ldap.LDAPException#toString()
* @see org.ietf.ldap.LDAPException#getResultCode()
* @see org.ietf.ldap.LDAPException#getLDAPErrorMessage()
* @see org.ietf.ldap.LDAPException#getMatchedDN()
*/
public LDAPReferralException( String message,
int resultCode,
String serverErrorMessage,
Throwable rootException ) {
super( message, resultCode, serverErrorMessage, rootException );
}
/**
* 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 String[] getReferrals() {
if ( getLDAPErrorMessage() == null ) {
return (_referrals != null) ? _referrals : new String[0];
} else {
return extractReferrals( getLDAPErrorMessage() );
}
}
/**
* Gets the referral URL that could not be followed. If multiple URLs
* are in the list, and none could be followed, the method returns one
* of them.
*
* @return the referral URL that could not be followed
*/
public String getFailedReferral() {
String[] urls = getReferrals();
return (urls.length > 0) ? urls[0] : "";
}
/**
* Sets the referral URL that could not be followed
*
* @param referral the referral URL that could not be followed
*/
public void setFailedReferral( String referral ) {
_referrals = new String[] { referral };
}
/**
* Extract referral string from the error message. The
* error string is based on "Referrals Within the
* LDAPConnection 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;
}
/**
* Gets the string representation of the referral exception,
* which includes the result code, the message sent back
* from the LDAP server and the list of referrals.
*
* @return string representation of exception.
* @see org.ietf.ldap.LDAPException#resultCodeToString(int)
*/
public String toString() {
String str = super.toString();
for (int i=0; i < _referrals.length; i++) {
str += "\n" + _referrals[i];
}
return str;
}
}

Просмотреть файл

@ -0,0 +1,28 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
/**
* Common base interface for referral handlers
*/
public interface LDAPReferralHandler {
}

Просмотреть файл

@ -0,0 +1,123 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.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.properties
* ErrorCodes_en.properties
* ErrorCodes.properties
*
* </pre>
* @see java.util.Locale
*/
class LDAPResourceBundle implements java.io.Serializable {
static final long serialVersionUID = -5903986665461157980L;
private static final boolean _debug = false;
private static final String _suffix = ".properties";
private static final String _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 = _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( _locale_separator );
if ( index == -1 ) {
printDebug( "File " + baseName + localeStr + _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 + _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 ( _debug ) {
System.out.println( str );
}
}
}

Просмотреть файл

@ -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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import org.ietf.ldap.client.opers.JDAPProtocolOp;
import org.ietf.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();
}
}

Просмотреть файл

@ -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 org.ietf.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;
}
}

Просмотреть файл

@ -0,0 +1,46 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.io.Serializable;
import java.util.Vector;
/**
* Represents the message queue associated with a particular LDAP
* operation or operations.
*
*/
public class LDAPResponseQueue extends LDAPMessageQueueImpl {
static final long serialVersionUID = 901897097111294329L;
/**
* Constructor
*
* @param asynchOp a boolean flag that is true if the object is used for
* asynchronous LDAP operations
* @see org.ietf.ldap.LDAPAsynchronousConnection
*/
LDAPResponseQueue( boolean asynchOp ) {
super( asynchOp );
}
}

Просмотреть файл

@ -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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.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(org.ietf.ldap.LDAPSocketFactory)
*/
public class LDAPSSLSocketFactory
implements LDAPSSLSocketFactoryExt, Serializable {
static final long serialVersionUID = -3331456736649381427L;
/**
* Indicates if client authentication is on.
*/
private boolean _clientAuth = false;
/**
* Name of class implementing SSLSocket.
*/
private String _packageName = "netscape.net.SSLSocket";
/**
* The cipher suites
*/
private Object _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) {
_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) {
_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) {
_packageName = new String(className);
_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) {
_packageName = new String(className);
_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) {
_packageName = new String(className);
_cipherSuites = cipherSuites;
_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>createSocket</CODE>.
* @see org.ietf.ldap.LDAPSSLSocketFactory#isClientAuth
* @see org.ietf.ldap.LDAPSSLSocketFactory#createSocket
* 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() {
_clientAuth = true;
}
/**
* Enables client authentication for an application that uses
* an external (file-based) certificate database.
* <B>This method is currently not implemented.</B>
* Call this method before you call <CODE>createSocket</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 org.ietf.ldap.LDAPSSLSocketFactory#isClientAuth
* @see org.ietf.ldap.LDAPSSLSocketFactory#createSocket
* @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 org.ietf.ldap.LDAPSSLSocketFactory
*/
public boolean isClientAuth() {
return _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 _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 _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 org.ietf.ldap.LDAPSSLSocketFactory
*/
public Socket createSocket(String host, int port)
throws LDAPException {
Socket s = null;
if (_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.createSocket: invoking " +
"enablePrivilege: " + e.toString();
throw new LDAPException(msg, LDAPException.PARAM_ERROR);
}
}
try {
String cipherClassName = null;
if (_cipherSuites != null)
cipherClassName = _cipherSuites.getClass().getName();
/* Instantiate the SSLSocketFactory implementation, and
find the right constructor */
Class c = Class.forName(_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) && (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 ( (_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] = _cipherSuites;
s = (Socket)(m[i].newInstance(args));
return s;
}
}
throw new LDAPException("No appropriate constructor in " +
_packageName,
LDAPException.PARAM_ERROR);
} catch (ClassNotFoundException e) {
throw new LDAPException("Class " + _packageName + " not found",
LDAPException.PARAM_ERROR);
} catch (Exception e) {
throw new LDAPException("Failed to create SSL socket",
LDAPException.CONNECT_ERROR);
}
}
}

Просмотреть файл

@ -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 org.ietf.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(org.ietf.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 org.ietf.ldap.LDAPSSLSocketFactory#enableClientAuth
*/
public boolean isClientAuth();
}

Просмотреть файл

@ -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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.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(org.ietf.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) {
_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) {
_packageName = new String(className);
_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 createSocket(String host, int port) throws LDAPException {
LDAPSSLSocket s = null;
try {
if (_cipherSuites == null)
s = new LDAPSSLSocket(host, port, _packageName);
else
s = new LDAPSSLSocket(host, port, _packageName,
_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 _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 createSocket() 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 _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 _cipherSuites;
}
/**
* Indicates if client authentication is on.
*/
private boolean _clientAuth = false;
/**
* Name of class implementing SSLSocket.
*/
private String _packageName = null;
/**
* The cipher suites
*/
private Object _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();
_packageName = packageName;
try {
// instantiate the SSLSocketFactory implementation, and
// find the right constructor
Class c = Class.forName(_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);
_socket = (Object)(m[i].newInstance(args));
return;
}
}
throw new LDAPException("No appropriate constructor in " +
_packageName, LDAPException.PARAM_ERROR);
} catch (ClassNotFoundException e) {
throw new LDAPException("Class " + _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();
_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(_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;
_socket = (Object)(m[i].newInstance(args));
return;
}
}
throw new LDAPException("No appropriate constructor in " +
_packageName, LDAPException.PARAM_ERROR);
} catch (ClassNotFoundException e) {
throw new LDAPException("Class " + _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(_socket, "getInputStream", null);
return (InputStream)obj;
} catch (LDAPException e) {
printDebug(e.toString());
}
return null;
}
public OutputStream getOutputStream() {
try {
Object obj = invokeMethod(_socket, "getOutputStream", null);
return (OutputStream)obj;
} catch (LDAPException e) {
printDebug(e.toString());
}
return null;
}
public void close() throws IOException {
try {
invokeMethod(_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(_socket, "close", args);
} catch (LDAPException e) {
printDebug(e.toString());
}
}
public InetAddress getInetAddress() {
try {
Object obj = invokeMethod(_socket, "getInetAddress", null);
return (InetAddress)obj;
} catch (LDAPException e) {
printDebug(e.toString());
}
return null;
}
public int getLocalPort() {
try {
Object obj = invokeMethod(_socket, "getLocalPort", null);
return ((Integer)obj).intValue();
} catch (LDAPException e) {
printDebug(e.toString());
}
return -1;
}
public int getPort() {
try {
Object obj = invokeMethod(_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)(_methodLookup.get(name)))
!= null)
return method;
Class c = Class.forName(_packageName);
java.lang.reflect.Method[] m = c.getMethods();
for (int i = 0; i < m.length; i++ ) {
if (m[i].getName().equals(name)) {
_methodLookup.put(name, m[i]);
return m[i];
}
}
throw new LDAPException("Method " + name + " not found in " +
_packageName);
} catch (ClassNotFoundException e) {
throw new LDAPException("Class "+ _packageName + " not found");
}
}
private void printDebug(String msg) {
if (_debug) {
System.out.println(msg);
}
}
private final boolean _debug = true;
private Object _socket;
private Hashtable _methodLookup = new Hashtable();
private String _packageName = null;
}

Просмотреть файл

@ -0,0 +1,445 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.util.*;
import org.ietf.ldap.client.*;
import org.ietf.ldap.client.opers.*;
import org.ietf.ldap.ber.stream.*;
import org.ietf.ldap.util.*;
import java.io.*;
import java.net.*;
import javax.security.auth.callback.CallbackHandler;
//import javax.security.sasl.*;
import com.sun.security.sasl.preview.*;
/**
* Authenticates to a server using SASL
*/
public class LDAPSaslBind implements LDAPBindHandler, 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,
Map props,
CallbackHandler cbh ) {
_dn = dn;
_mechanisms = mechanisms;
_props = props;
_cbh = cbh;
}
/**
* Authenticates to the LDAP server (that the object is currently
* connected to) using the parameters 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 HashMap();
}
String packageNames = (String)_props.get( CLIENTPKGS );
if ( packageNames == null ) {
packageNames = System.getProperty( CLIENTPKGS );
}
if ( packageNames == null ) {
packageNames = ldc.DEFAULT_SASL_PACKAGE;
}
StringTokenizer st = new StringTokenizer( packageNames, "|" );
while( st.hasMoreTokens() ) {
String packageName = st.nextToken();
try {
_saslClient = getClient( ldc, packageName );
if ( _saslClient != null ) {
break;
}
} catch ( LDAPException e ) {
if ( !st.hasMoreTokens() ) {
throw e;
}
}
}
if ( _saslClient != null ) {
bind( ldc, true );
return;
} else {
ldc.printDebug( "LDAPSaslBind.bind: getClient " +
"returned null" );
}
}
/**
* Authenticates to the LDAP server (that the object is currently
* connected to) using the parameters 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 ldapurls urls which may be selected to connect and bind to
* @param ldc an active connection to a server, which will have
* the new authentication state on return from the method
* @exception LDAPReferralException Failed to authenticate to the LDAP server
*/
public void bind( String[] ldapurls,
LDAPConnection conn ) throws LDAPReferralException {
try {
// ??? What to do with the URLs?
bind( conn );
} catch ( LDAPReferralException ex ) {
throw ex;
} catch ( LDAPException ex ) {
// ???
throw new LDAPReferralException( ex.getMessage(),
ex.getResultCode(),
ex.getLDAPErrorMessage() );
}
}
/**
* 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.Map";
// argNames[4] = "java.util.Hashtable";
argNames[5] = CALLBACK_HANDLER;
// Get a mechanism driver
return DynamicInvoker.invokeMethod( null,
"javax.security.sasl.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 {
String className = _saslClient.getClass().getName();
ldc.printDebug( "LDAPSaslBind.bind: calling " +
className+".hasInitialResponse" );
// Get initial response if any
byte[] outVals = null;
if ( hasInitialResponse() ) {
outVals = evaluateChallenge( new byte[0] );
}
String mechanismName = getMechanismName();
ldc.printDebug( "LDAPSaslBind.bind: mechanism " +
"name is " +
mechanismName );
boolean isExternal = isExternalMechanism( mechanismName );
ldc.printDebug( "LDAPSaslBind.bind: calling " +
"saslBind" );
JDAPBindResponse response =
saslBind( ldc, mechanismName, outVals );
int resultCode = response.getResultCode();
while ( !checkForSASLBindCompletion( ldc, resultCode ) ) {
if ( isExternal ) {
continue;
}
byte[] b = response.getCredentials();
if ( b == null ) {
b = new byte[0];
}
outVals = evaluateChallenge( b );
System.out.println( "SaslClient.evaluateChallenge returned [" + ((outVals != null) ? new String( outVals ) : "null") + "] for [" +
new String( b ) + "]" );
if ( resultCode == LDAPException.SUCCESS ) {
// we're done; don't expect to send another BIND
if ( outVals != null ) {
throw new LDAPException(
"Protocol error: attempting to send " +
"response after completion" );
}
break;
}
response = saslBind( ldc, mechanismName, outVals );
resultCode = response.getResultCode();
}
// Make sure authentication REALLY is complete
if ( !isComplete() ) {
// 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 );
} else if ( resultCode == LDAPException.SUCCESS ) {
// Has a security layer been negotiated?
String qop = getNegotiatedProperty( QOP );
if ( (qop != null) &&
(qop.equalsIgnoreCase("auth-int") ||
qop.equalsIgnoreCase("auth-conf")) ) {
// Use SaslClient.wrap() and SaslClient.unwrap() for
// future communication with server
ldc.setInputStream(
new SecureInputStream( ldc.getInputStream(),
_saslClient ) );
ldc.setOutputStream(
new SecureOutputStream( ldc.getOutputStream(),
_saslClient ) );
}
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 );
}
// Wrapper functions for dynamically invoking methods of SaslClient
private boolean checkForSASLBindCompletion( LDAPConnection ldc,
int resultCode )
throws LDAPException {
ldc.printDebug( "LDAPSaslBind.bind: saslBind " +
"returned " + resultCode );
if ( isComplete() ) {
if ( (resultCode == LDAPException.SUCCESS) ||
(resultCode == LDAPException.SASL_BIND_IN_PROGRESS) ) {
return true;
} else {
throw new LDAPException( "Authentication failed", resultCode );
}
} else {
return false;
}
}
private boolean hasInitialResponse()
throws LDAPException {
if ( !_useReflection ) {
return ((SaslClient)_saslClient).hasInitialResponse();
} else {
return ((Boolean)DynamicInvoker.invokeMethod(
_saslClient,
_saslClient.getClass().getName(),
"hasInitialResponse",
null,
null)).booleanValue();
}
}
private String getMechanismName()
throws LDAPException {
if ( !_useReflection ) {
return ((SaslClient)_saslClient).getMechanismName();
} else {
return (String)DynamicInvoker.invokeMethod(
_saslClient,
_saslClient.getClass().getName(),
"getMechanismName",
null,
null );
}
}
private boolean isComplete()
throws LDAPException {
if ( !_useReflection ) {
return ((SaslClient)_saslClient).isComplete();
} else {
return ((Boolean)DynamicInvoker.invokeMethod(
_saslClient,
_saslClient.getClass().getName(),
"isComplete",
null,
null)).booleanValue();
}
}
private byte[] evaluateChallenge( byte[] b )
throws LDAPException {
try {
if ( !_useReflection ) {
return ((SaslClient)_saslClient).evaluateChallenge( b );
} else {
Object[] args = { b };
String[] argNames = { "[B" }; // class name for byte array
return (byte[])DynamicInvoker.invokeMethod(
_saslClient,
_saslClient.getClass().getName(),
"evaluateChallenge",
args,
argNames );
}
} catch ( Exception e ) {
throw new LDAPException( "",
LDAPException.PARAM_ERROR,
e );
}
}
private String getNegotiatedProperty( String propName )
throws LDAPException {
try {
if ( !_useReflection ) {
return ((SaslClient)_saslClient).getNegotiatedProperty( propName );
} else {
Object[] args = { propName };
String[] argNames = { "String" };
return (String)DynamicInvoker.invokeMethod(
_saslClient,
_saslClient.getClass().getName(),
"getNegotiatedProperty",
args,
argNames );
}
} catch ( Exception e ) {
throw new LDAPException( "",
LDAPException.PARAM_ERROR,
e );
}
}
private JDAPBindResponse saslBind( LDAPConnection ldc,
String mechanismName,
byte[] credentials )
throws LDAPException {
LDAPResponseQueue 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";
static final String CLIENTPKGS =
"javax.security.sasl.client.pkgs";
private static final String QOP = "javax.security.sasl.qop";
private static final String REFLECTION_PROP =
"org.ietf.ldap.sasl.reflect";
private String _dn;
private String[] _mechanisms;
private Map _props = null;
private CallbackHandler _cbh;
private Object _saslClient = null;
private static boolean _useReflection =
( System.getProperty(REFLECTION_PROP) != null );
// ??? Security layer support not implemented
class SecureInputStream extends InputStream {
public SecureInputStream( InputStream is, Object saslClient ) {
_input = is;
_saslClient = saslClient;
}
public int read() throws IOException {
return _input.read();
}
private InputStream _input;
private Object _saslClient;
}
class SecureOutputStream extends OutputStream {
public SecureOutputStream( OutputStream os, Object saslClient ) {
_output = os;
_saslClient = saslClient;
}
public void write( int b ) throws IOException {
_output.write( b );
}
private OutputStream _output;
private Object _saslClient;
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,619 @@
/* -*- 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 org.ietf.ldap;
import java.io.Serializable;
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 org.ietf.ldap.LDAPObjectClassSchema
* @see org.ietf.ldap.LDAPAttributeSchema
* @see org.ietf.ldap.LDAPMatchingRuleSchema
* @version 1.0
**/
public abstract class LDAPSchemaElement implements Serializable {
static final long serialVersionUID = -3972153461950418863L;
/**
* Constructs a blank element.
*/
protected LDAPSchemaElement() {
}
/**
* Constructs a definition explicitly
*
* @param names names of element
* @param oid dotted-string object identifier
* @param description description of element
*/
protected LDAPSchemaElement( String[] names,
String oid,
String description ) {
if ( oid == null ) {
throw new IllegalArgumentException( "OID required" );
}
this.names = names;
this.oid = oid;
this.description = description;
}
/**
* 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;
}
/**
* 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 names of the schema element
*
* @return the names of the schema element
*/
public String[] getNames() {
return names;
}
/**
* 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();
}
/**
* 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);
}
/**
* 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 );
}
/**
* Returns a String in a format suitable for directly adding to a
* Directory, as a value of the particular schema
* element attribute. See the format definition for each derived class
*
* @return Directory format of the schema element as a String
*/
public abstract String toString();
/**
* 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 ) {
names = null;
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" ) ) {
names = new String[] { val };
} else if ( s.equals( "DESC" ) ) {
description = val;
} else {
properties.put( s, val );
}
if ( quoted ) {
last++;
}
}
}
ind = last + 1;
}
if ( names == null ) {
names = getQualifier( "NAME" );
if ( names == null ) {
names = new String[0];
}
}
}
/**
* Gets the attribute name for a schema element
*
* @return The attribute name of the element
*/
String getAttributeName() {
return null;
}
/**
* 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.
*/
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 + ' ';
s += getNameField();
if ( description != null ) {
s += "DESC \'" + description + "\' ";
}
if ( isObsolete() ) {
s += OBSOLETE + ' ';
}
return s;
}
String getNameField() {
String s = "";
if ( (names != null) && (names.length > 0) ) {
s += "NAME ";
if ( names.length > 1 ) {
s += "( ";
}
for( int i = 0; i < names.length; i++ ) {
s += '\'' + names[i] + "\' ";
}
if ( names.length > 1 ) {
s += ") ";
}
}
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 );
}
/**
* 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;
}
// 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 description = "";
protected String attrName = null;
protected String rawValue = null;
protected String[] names = new String[0];
// Additional qualifiers
protected Hashtable properties = null;
// Qualifiers known to not have values
static protected Hashtable novalsTable = new Hashtable();
}

Просмотреть файл

@ -0,0 +1,268 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.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 {
private int deref;
private int maxRes;
private int batch;
private int serverTimeLimit;
private int maxBacklog = 100;
/**
* Constructs an object with the default set of search constraints
*/
public LDAPSearchConstraints() {
super();
deref = 0;
maxRes = 1000;
batch = 1;
serverTimeLimit = 0;
}
/**
* Constructs an object with the supplied constraints as template
*/
public LDAPSearchConstraints( LDAPConstraints cons ) {
this();
setHopLimit( cons.getHopLimit() );
setReferralFollowing( cons.getReferralFollowing() );
setTimeLimit( cons.getTimeLimit() );
setReferralHandler( cons.getReferralHandler());
LDAPControl[] tServerControls = cons.getControls();
if ( (tServerControls != null) &&
(tServerControls.length > 0) ) {
LDAPControl[] oServerControls =
new LDAPControl[tServerControls.length];
for( int i = 0; i < tServerControls.length; i++ ) {
oServerControls[i] = (LDAPControl)tServerControls[i].clone();
}
setControls(oServerControls);
}
if ( cons instanceof LDAPSearchConstraints ) {
LDAPSearchConstraints scons = (LDAPSearchConstraints)cons;
setServerTimeLimit( scons.getServerTimeLimit() );
setDereference( scons.getDereference() );
setMaxResults( scons.getMaxResults() );
setBatchSize( scons.getBatchSize() );
setMaxBacklog( scons.getMaxBacklog() );
}
}
/**
* 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>LDAPConnection.DEREF_NEVER</CODE>,
* <CODE>LDAPConnection.DEREF_FINDING</CODE>,
* <CODE>LDAPConnection.DEREF_SEARCHING</CODE>, or
* <CODE>LDAPConnection.DEREF_ALWAYS</CODE> (see LDAPConnection.setOption).
* <CODE>LDAPConnection.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 org.ietf.ldap.LDAPConnection#setOption(int, java.lang.Object)
* @see org.ietf.ldap.LDAPConnection#search(org.ietf.ldap.LDAPUrl, org.ietf.ldap.LDAPSearchConstraints)
* @see org.ietf.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, org.ietf.ldap.LDAPSearchConstraints)
*/
public LDAPSearchConstraints( int msLimit,
int timeLimit,
int dereference,
int maxResults,
boolean doReferrals,
int batchSize,
LDAPReferralHandler handler,
int hop_limit) {
super( msLimit, doReferrals, handler, hop_limit );
serverTimeLimit = timeLimit;
deref = dereference;
maxRes = maxResults;
batch = batchSize;
}
/**
* 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;
}
/**
* Specifies how aliases should be dereferenced.
* @return <CODE>LDAPConnection.DEREF_NEVER</CODE> to
* never follow ("dereference") aliases,
* <CODE>LDAPConnection.DEREF_FINDING</CODE> to dereference when finding
* the starting point for the search (but not when searching
* under that starting entry), <CODE>LDAPConnection.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>LDAPConnection.DEREF_ALWAYS</CODE> to always
* dereference aliases.
*/
public int getDereference() {
return deref;
}
/**
* 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.getOption()</CODE>
*/
public int getMaxBacklog() {
return maxBacklog;
}
/**
* 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 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;
}
/**
* 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;
}
/**
* Sets a preference indicating how aliases should be dereferenced.
* @param dereference <CODE>LDAPConnection.DEREF_NEVER</CODE> to
* never follow ("dereference") aliases,
* <CODE>LDAPConnection.DEREF_FINDING</CODE> to dereference when finding
* the starting point for the search (but not when searching
* under that starting entry), <CODE>LDAPConnection.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>LDAPConnection.DEREF_ALWAYS</CODE> to always
* dereference aliases
*/
public void setDereference( int dereference ) {
deref = dereference;
}
/**
* 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.setOption()</CODE>
*/
public void setMaxBacklog( int backlog ) {
maxBacklog = backlog;
}
/**
* 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 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;
}
/**
* Makes a copy of an existing set of search constraints.
* @return a copy of an existing set of search constraints.
*/
public Object clone() {
return new LDAPSearchConstraints( this );
}
/**
* 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("max backlog " + maxBacklog);
sb.append('}');
return sb.toString();
}
}

Просмотреть файл

@ -0,0 +1,202 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.io.Serializable;
import java.util.*;
import org.ietf.ldap.client.*;
/**
* Manages search results, references and responses returned on one or
* more search requests
*
*/
public class LDAPSearchQueue extends LDAPMessageQueueImpl {
static final long serialVersionUID = -7163312406176592277L;
/**
* Constructs a search message queue
*
* @param asynchOp a boolean flag indicating whether the object is used
* for asynchronous LDAP operations
* @param cons LDAP search constraints
* @see org.ietf.ldap.LDAPAsynchronousConnection
*/
LDAPSearchQueue( boolean asynchOp,
LDAPSearchConstraints cons ) {
super( asynchOp );
_constraints = cons;
}
/**
* Blocks until a search result, reference or response is available,
* or until all operations associated with the object have completed
* or been canceled.
* Wakes up the LDAPConnThread if the backlog limit has been reached.
*
* @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{
LDAPMessage result = super.getResponse();
// Notify LDAPConnThread to wake up if backlog limit has been reached
if ( result instanceof LDAPSearchResult ||
result instanceof LDAPSearchResultReference ) {
LDAPConnThread connThread =
getConnThread( result.getMessageID() );
if ( connThread != null ) {
connThread.resultRetrieved();
}
}
return result;
}
/**
* Blocks until a response is available for a particular message ID, or
* until all operations associated with the message ID have completed or
* been canceled, and returns the response. If there is no outstanding
* operation for the message ID (or if it is zero or a negative number),
* IllegalArgumentException is thrown.
*
* @param msgid A particular message to query for responses available
* @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 LDAPMessage getResponse( int msgid )
throws LDAPException {
LDAPMessage result = super.getResponse( msgid );
// Notify LDAPConnThread to wake up if backlog limit has been reached
if ( result instanceof LDAPSearchResult ||
result instanceof LDAPSearchResultReference ) {
LDAPConnThread connThread =
getConnThread( result.getMessageID() );
if ( connThread != null ) {
connThread.resultRetrieved();
}
}
return result;
}
/**
* Reports true if all results for a particular message ID have been
* received by the API implementation. That is the case if a
* searchResultDone response has been received by the SDK. There may
* still be messages queued in the object for retrieval by the
* application. If there is no outstanding operation for the message ID
* (or if it is zero or a negative number), IllegalArgumentException is
* thrown.
*
* @param msgid A particular message to query for completion
* @return true if all results for a particular message ID have been
* received
*/
public synchronized boolean isComplete( int msgid ) throws LDAPException {
boolean OK = false;
for ( int i = (_messageQueue.size()-1); i >= 0; i-- ) {
LDAPMessage msg = (LDAPMessage)_messageQueue.get(i);
if ( msg.getMessageID() == msgid ) {
OK = true;
break;
}
}
if ( !OK ) {
throw new IllegalArgumentException( "Invalid msg ID: " + msgid );
}
// Search an instance of LDAPResponse
for ( int i = _messageQueue.size()-1; i >= 0; i-- ) {
LDAPMessage msg = (LDAPMessage)_messageQueue.get(i);
if ( msg instanceof LDAPResponse ) {
return true;
}
}
return false;
}
/**
* Gets the key of the cache entry
*
* @return the key of the cache entry
*/
Long getKey() {
return _key;
}
/**
* Returns the search constraints used to create this object.
*
* @return the search constraints used to create this object.
*/
LDAPSearchConstraints getSearchConstraints() {
return _constraints;
}
/**
* Resets the state of this object so it can be recycled
* Used by LDAPConnection synchronous operations.
*/
void reset() {
super.reset();
_constraints = null;
}
/**
* Sets the key of the cache entry. The queue needs to know this value
* when the results get processed. 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 ) {
_key = key;
}
/**
* Sets search constraints
*
* @param cons LDAP search constraints
*/
void setSearchConstraints( LDAPSearchConstraints cons ) {
_constraints = cons;
}
// this instance variable is only for cache purposes
private Long _key = null;
private LDAPSearchConstraints _constraints;
}

Просмотреть файл

@ -0,0 +1,77 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import org.ietf.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 _entry;
/**
* Constructor
*
* @param msgid message identifier
* @param rsp search operation response
* @param controls array of controls or null
* @see org.ietf.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 org.ietf.ldap.LDAPEntry
*/
public LDAPEntry getEntry() {
if (_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();
_entry = new LDAPEntry( dn, attrs );
}
return _entry;
}
}

Просмотреть файл

@ -0,0 +1,63 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import org.ietf.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 _URLs[];
/**
* Constructor
*
* @param msgid message identifier
* @param resRef search result reference response
* @param controls array of controls or null
* @see org.ietf.ldap.LDAPEntry
*/
LDAPSearchResultReference( int msgid,
JDAPSearchResultReference resRef,
LDAPControl[]controls ) {
super( msgid, resRef, controls );
_URLs = resRef.getUrls();
}
/**
* Returns a list of LDAP URLs that are referred to
*
* @return a list of URLs.
*/
public String[] getReferrals() {
return _URLs;
}
}

Просмотреть файл

@ -0,0 +1,584 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.util.*;
import org.ietf.ldap.client.*;
import org.ietf.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 org.ietf.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
* @see org.ietf.ldap.LDAPConnection#abandon(org.ietf.ldap.LDAPSearchResults)
*/
public class LDAPSearchResults implements Serializable {
static final long serialVersionUID = -501692208613904825L;
private Vector entries = null;
private LDAPSearchQueue 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 org.ietf.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 org.ietf.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;
}
/**
* 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() {
while (resultSource != null && resultSource.getMessageCount() > 0) {
fetchResult();
}
int count = entries.size();
for ( int i = 0; i < referralResults.size(); i++ ) {
LDAPSearchResults res =
(LDAPSearchResults)referralResults.elementAt(i);
count += res.getCount();
}
if ( exceptions != null ) {
count += exceptions.size();
}
return count;
}
/**
* 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 org.ietf.ldap.LDAPControl#register
*/
public LDAPControl[] getResponseControls() {
return currConn.getResponseControls(msgID);
}
/**
* Returns <CODE>true</CODE> if there are more search results
* to be returned. You can use this method in conjunction with the
* <CODE>next</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.hasMore() ) {
* LDAPEntry findEntry = res.next();
* ...
* }
* </PRE>
* @return <CODE>true</CODE> if there are more search results.
* @see org.ietf.ldap.LDAPSearchResults#next()
*/
public boolean hasMore() {
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.hasMore())
return true;
else
referralResults.removeElementAt(0);
}
}
return ((entries.size() > 0) ||
((exceptions != null) && (exceptions.size() > 0)));
}
/**
* 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>hasMore</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.has() ) {
* try {
* LDAPEntry findEntry = res.next();
* } catch ( LDAPReferralException e ) {
* String refUrls[] = e.getReferrals();
* 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 org.ietf.ldap.LDAPSearchResults#hasMore()
*/
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;
}
/**
* Sorts the search results.
* <P>
*
* The comparator 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 LDAPCompareAttrNames
*/
public synchronized void sort(Comparator compare) {
// if automatic referral, then add to the entries, otherwise, dont do it
// since the elements in referralResults are LDAPReferralException.
if (currCons.getReferralFollowing()) {
while (referralResults.size() > 0) {
Object obj = null;
if ((obj=nextReferralElement()) != null) {
if (obj instanceof LDAPException) {
add((LDAPException)obj); // put it back
}
else {
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]);
}
}
/**
* Adds a search entry or 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).getReferrals();
if ( urls != null ) {
if (exceptions == null) {
exceptions = new Vector();
}
exceptions.addElement(
new LDAPReferralException(null, 0, urls) );
}
}
}
/**
* Adds and 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( LDAPSearchQueue l ) {
resultSource = l;
searchComplete = false;
}
void associatePersistentSearch( LDAPSearchQueue 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, Comparator 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.compare(toSort[shigh], pivot) > 0 );
do {
slow++;
} while ( compare.compare(pivot, toSort[slow]) > 0 );
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 next result from a search. You can use this method
* in conjunction with the <CODE>hasMore</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.hasMore() ) {
* Object o = res.next();
* if ( o instanceof LDAPEntry ) {
* LDAPEntry findEntry = (LDAPEntry)o;
* ...
* } else if ( o instanceof LDAPReferralException ) {
* LDAPReferralException e = (LDAPReferralException)o;
* String refUrls[] = e.getReferrals();
* ...
* } else if ( o instanceof LDAPException ) {
* LDAPException e = (LDAPException)o;
* ...
* }
* }
* </PRE>
* @return the next element in the search results.
* @see org.ietf.ldap.LDAPSearchResults#hasMore()
*/
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.hasMore()) ||
(res.persistentSearch)) {
Object obj = res.nextElement();
if (obj != null) {
return obj;
}
if ((obj == null) || (!res.hasMore())) {
referralResults.removeElementAt(0);
}
} else {
referralResults.removeElementAt(0);
}
return null;
}
/**
* 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.getResponse();
} 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);
}
}
}
}
}
}

Просмотреть файл

@ -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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.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>org.ietf.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(org.ietf.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#createSocket(java.lang.String,int)
*/
public Socket createSocket( String host, int port )
throws LDAPException;
}

Просмотреть файл

@ -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 org.ietf.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 org.ietf.ldap.controls.LDAPSortControl
* @see org.ietf.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 org.ietf.ldap.controls.LDAPSortControl
* @see org.ietf.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 org.ietf.ldap.controls.LDAPSortControl
* @see org.ietf.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;
}

Просмотреть файл

@ -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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.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 org.ietf.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( new String[] { "" }, 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;
}
/**
* Gets the attribute name for a schema element
*
* @return The attribute name of the element
*/
String getAttributeName() {
return "ldapsyntaxes";
}
/**
* Prepares a value in RFC 2252 format for submission to a server
*
* @return a String ready for submission to an LDAP server.
*/
String getValue() {
String s = getValuePrefix();
String val = getCustomValues();
if ( val.length() > 0 ) {
s += val + ' ';
}
s += ')';
return s;
}
/**
* Gets the definition of the syntax in Directory format
*
* @return definition of the syntax in Directory format
*/
public String toString() {
return getValue();
}
protected LDAPSyntaxSchemaElement syntaxElement =
new LDAPSyntaxSchemaElement();
}

Просмотреть файл

@ -0,0 +1,156 @@
/* -*- 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 org.ietf.ldap;
import java.util.*;
/**
* Helper class supporting schema elements that include syntax
* definitions - attributes and matching rules
*
* @version 1.0
* @see org.ietf.ldap.LDAPAttributeSchema
* @see org.ietf.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;
}
public String toString() {
return "LDAPSyntaxSchemaElement: " + getSyntaxString();
}
int syntax = unknown;
String syntaxString = null;
}

Просмотреть файл

@ -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 org.ietf.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 org.ietf.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 org.ietf.ldap.LDAPConnection#setProperty(java.lang.String, java.lang.Object)
*/
public void write (String msg);
}

Просмотреть файл

@ -0,0 +1,38 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
/**
* An object that implements this interface can be notified when
* unsolicited messages arrive from the server. A client registers the
* object with LDAPConnection.addUnsolicitedNotificationListener.
*/
public interface LDAPUnsolicitedNotificationListener {
/**
* The method is called when an unsolicited message arrives from a
* server, if the object has registered with
* LDAPConnection.addUnsolicitedNotificationListener.
*
* @param msg An unsolicited message received from the server
*/
public void messageReceived( LDAPExtendedResponse msg );
}

Просмотреть файл

@ -0,0 +1,759 @@
/* -*- 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) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package org.ietf.ldap;
import java.util.*;
import java.io.*;
import java.net.MalformedURLException;
import org.ietf.ldap.factory.*;
/**
* 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>. In addition, the secure ldap (ldaps://) is also
* supported. LDAP URLs have the following format:
*
* <PRE>
* "ldap[s]://" [ <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;
private boolean _secure;
private String[] _extensions;
private static LDAPSocketFactory _factory;
/**
* The default port number for secure LDAP connections.
* @see org.ietf.ldap.LDAPUrl#LDAPUrl(String, int, String, String[], int,
* String, String[])
*/
public static final int DEFAULT_SECURE_PORT = 636;
/**
* 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 = LDAPConnection.SCOPE_BASE;
_filter = defaultFilter;
_URL = url;
parseUrl(url);
}
/**
* 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 LDAPConnection.DEFAULT_PORT for
* the default port)
* @param DN distinguished name of the object
*/
public LDAPUrl( String host,
int port,
String DN ) {
initialize( host, port, DN, null,
LDAPConnection.SCOPE_BASE,
defaultFilter,
null );
}
/**
* 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 LDAPConnection.DEFAULT_PORT for
* the default non-secure port or LDAPUrl.DEFAULT_SECURE_PORT for the default
* secure 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 LDAPConnection 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).
* @param extensions LDAP URL extensions specified; may be null or
* empty. Each extension is a type=value expression.
* The =value part MAY be omitted. The expression
* may be prefixed with '!' if it is mandatory for
* evaluation of the URL.
*/
public LDAPUrl( String host,
int port,
String DN,
String[] attributes,
int scope,
String filter,
String[] extensions ) {
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,
extensions );
} else {
initialize( host, port, DN, null, scope, filter,
extensions );
}
}
/**
* 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();
}
/**
* 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 new String[0];
} else {
String[] attrNames = new String[_attributes.size()];
Enumeration attrs = getAttributes();
int i = 0;
while ( attrs.hasMoreElements() ) {
attrNames[i++] = (String)attrs.nextElement();
}
return attrNames;
}
}
/**
* 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 distinguished name encapsulated in the URL
* @return target distinguished name.
*/
public String getDN() {
return _DN;
}
/**
* Returns the search filter (RFC 1558), or the default if none was
* specified.
* @return the search filter.
*/
public String getFilter() {
return _filter;
}
/**
* 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;
}
/**
* Returns the scope of the search, according to the values
* SCOPE_BASE, SCOPE_ONE, SCOPE_SUB as defined in LDAPConnection. 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 LDAPConnection values for scope).
*/
private int getScope(String str) {
int s = -1;
if (str.equalsIgnoreCase("base"))
s = LDAPConnection.SCOPE_BASE;
else if (str.equalsIgnoreCase("one"))
s = LDAPConnection.SCOPE_ONE;
else if (str.equalsIgnoreCase("sub"))
s = LDAPConnection.SCOPE_SUB;
return s;
}
/**
* Gets the socket factory to be used for ldaps:// URLs.
* <P>
* If the factory is not explicitly specified with
* <CODE>LDAPUrl.setSocketFactory</CODE>, the method will
* attempt the determine the default factory based on the
* available factories in the org.ietf.ldap.factory package.
*
* @return the socket factory to be used for ldaps:// URLs
*/
public static LDAPSocketFactory getSocketFactory() {
if (_factory == null) {
// No factory explicity set, try to determine
// the default one.
try {
// First try iPlanet JSSSocketFactory
Class c = Class.forName("org.ietf.ldap.factory.JSSSocketFactory");
_factory = (LDAPSocketFactory) c.newInstance();
}
catch (Throwable e) {
}
if (_factory != null) {
return _factory;
}
try {
// then try Sun JSSESocketFactory
_factory = new JSSESocketFactory(null);
}
catch (Throwable e) {
}
}
return _factory;
}
/**
* Returns true if the secure ldap protocol is used.
* @return true if ldaps is used.
*/
public boolean isSecure() {
return _secure;
}
/**
* Sets the socket factory to be used for ldaps:// URLs.
* Overrides the default factory assigned by the LDAPUrl
* class.
* @param the socket factory to be used for ldaps:// URLs
* @see org.ietf.ldap.LDAPUrl#getSocketFactory
*/
public static void setSocketFactory( LDAPSocketFactory factory ) {
_factory = factory;
}
/**
* Sets the protocol to ldaps or ldap
*
* @param secure <CODE>true</CODE> for ldaps
*/
public void setSecure( boolean secure ) {
_secure = secure;
initialize( _hostName, _portNumber, _DN, getAttributes(), _scope,
_filter, _extensions );
}
/**
* Returns the URL in String format
*
* @return the URL in String format
*/
public String toString() {
return _URL;
}
/**
* Parse URL as defined in RFC 1959. Beyond the RFC, the secure ldap
* (ldaps) is also supported.
*/
private void parseUrl(String url) throws MalformedURLException {
StringTokenizer urlParser = new StringTokenizer (url, ":/?", true);
String currentToken;
String str = null;
try {
currentToken = urlParser.nextToken();
if (currentToken.equalsIgnoreCase ("LDAPS")) {
_secure = true;
}
else 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();
}
catch (NoSuchElementException e) {
throw new MalformedURLException ();
}
// host-port
if (currentToken.equals ("/")) {
_hostName = null;
_portNumber = _secure ? DEFAULT_SECURE_PORT : LDAPConnection.DEFAULT_PORT;
} else if (currentToken.equals (":")) {
// port number without host name is not allowed
throw new MalformedURLException ("No hostname");
} else if (currentToken.equals ("?")) {
throw new MalformedURLException ("No host[:port]");
} else {
_hostName = currentToken;
if (urlParser.countTokens() == 0) {
_portNumber = _secure ? DEFAULT_SECURE_PORT : LDAPConnection.DEFAULT_PORT;
return;
}
currentToken = urlParser.nextToken (); // either ":" or "/"
if (currentToken.equals (":")) {
try {
_portNumber = Integer.parseInt (urlParser.nextToken());
} catch (NumberFormatException nf) {
throw new MalformedURLException ("Port not a number");
} catch (NoSuchElementException ex) {
throw new MalformedURLException ("No port number");
}
if (urlParser.countTokens() == 0) {
return;
}
else if (! urlParser.nextToken().equals("/")) {
throw new MalformedURLException ();
}
} else if (currentToken.equals ("/")) {
_portNumber = _secure ? DEFAULT_SECURE_PORT : LDAPConnection.DEFAULT_PORT;
} else {
// expecting ":" or "/"
throw new MalformedURLException ();
}
}
// 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");
}
}
/**
* Initializes URL object.
*/
private void initialize( String host,
int port,
String DN,
Enumeration attributes,
int scope,
String filter,
String[] extensions ) {
_hostName = host;
_DN = DN;
_portNumber = port;
_filter = (filter != null) ? filter : defaultFilter;
_scope = scope;
_extensions = extensions;
if (attributes != null) {
_attributes = new Vector ();
while (attributes.hasMoreElements()) {
_attributes.addElement (attributes.nextElement());
}
} else
_attributes = null;
StringBuffer url = new StringBuffer (_secure ? "LDAPS://" :"LDAP://");
if (host != null) {
url.append (host);
url.append (':');
url.append (String.valueOf (port));
}
url.append ('/');
url.append (encode (DN));
if (attributes != null) {
url.append ('?');
Enumeration attrList = _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 LDAPConnection.SCOPE_BASE:
url.append ("base"); break;
case LDAPConnection.SCOPE_ONE:
url.append ("one"); break;
case LDAPConnection.SCOPE_SUB:
url.append ("sub"); break;
}
url.append ('?');
url.append (filter);
}
_URL = url.toString();
}
/**
* 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');
}
/**
* 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;
}
}

Просмотреть файл

@ -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 org.ietf.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.
* <P>See CCITT X.209.
*
*
* <pre>
* Encoding Rule:
* The encoding is that of the particular implementation.
* </pre>
*
* @version 1.0
*/
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 + "}";
}
}

Просмотреть файл

@ -0,0 +1,284 @@
/* -*- 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 org.ietf.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.
* <P>See CCITT X.209.
*
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x03
* </pre>
*
* @version 1.0
*/
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 + " }";
}
}

Просмотреть файл

@ -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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the Boolean object.
* <P>See CCITT X.209.
*
* <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
*/
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 + "}";
}
}

Просмотреть файл

@ -0,0 +1,180 @@
/* -*- 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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This is an abstract base class for character string types.
*
* @version 1.0
*/
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();
}

Просмотреть файл

@ -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 org.ietf.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.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* Encoding is the encoding of the specific type used.
* </pre>
*
* @version 1.0
*/
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 + "}";
}
}

Просмотреть файл

@ -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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This abstract class serves as a base class for constructed
* types such as sequence or set.
* <P>See CCITT X.209.
*
* @version 1.0
*/
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();
}

Просмотреть файл

@ -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 org.ietf.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.
* <P>See CCITT X.209.
*
* @version 1.0
*/
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();
}

Просмотреть файл

@ -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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the Enumerated object.
* <P>See CCITT X.209.
*
* <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
*/
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() + "}";
}
}

Просмотреть файл

@ -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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the Integer object.
* <P>See CCITT X.209.
*
* <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
*/
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() + "}";
}
}

Просмотреть файл

@ -0,0 +1,179 @@
/* -*- 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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This is the base class for integral types such as Integer and
* Enumerated.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = << depends on type >>
* length = (short or long form)
* one or more contents octets hold integral value
* value in two's complement
*
* Example 1: (Integer - zero)
* 02 01 00
* Example 2: (Enumerated - 1)
* 0A 01 01
* Example 3: (Integer - 300, short form)
* 02 02 01 2C
* Example 4: (Integer - 300, long form)
* 02 84 00 00 01 2C
* </pre>
*
* @version 1.0
*/
public abstract class BERIntegral extends BERElement {
/**
* Value of element
*/
private int m_value;
/**
* Constructs an integral type with a value.
* @param value integer value
*/
public BERIntegral(int value) {
m_value = value;
}
/**
* Constructs an integral element from an input stream.
* @param stream source
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
* @exception IOException failed to construct
*/
public BERIntegral(InputStream stream, int[] bytes_read) throws IOException {
int contents_length = super.readLengthOctets(stream, bytes_read);
/* Definite length content octets string. */
if (contents_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 < contents_length; i++) {
if (i > 0) {
octet = stream.read();
bytes_read[0]++;
}
if (negative)
m_value = (m_value<<8) + (int)(octet^0xFF)&0xFF;
else
m_value = (m_value<<8) + (int)(octet&0xFF);
}
if (negative) /* convert to 2's complement */
m_value = (m_value + 1) * -1;
}
}
/**
* Writes BER to stream.
* @param stream output stream
* @exception IOException on failure to write
*/
public void write(OutputStream stream) throws IOException {
int binary_value = m_value;
int num_content_octets = 0;
int total_ber_octets;
int offset=1;
int lead;
int i;
byte[] content_octets = new byte[10]; /* should be plenty big */
byte[] net_octets = new byte[10]; /* pse need this in network order */
/* Get content octets - need to determine length */
if (m_value == 0) {
num_content_octets = 1;
content_octets[offset] = (byte)0x00;
net_octets[offset] = (byte)0x00;
} else {
if (m_value < 0) /* convert from 2's complement */
binary_value = (m_value * -1) -1;
do {
if (m_value < 0)
content_octets[num_content_octets+offset] =
(byte)((binary_value^0xFF)&0xFF);
else
content_octets[num_content_octets+offset] =
(byte)(binary_value&0xFF);
binary_value = (binary_value>>8);
num_content_octets++;
} while (binary_value > 0);
/* pse 1/16/96 we've just created a string that is in non-network order
flip it for net order */
for (i=0; i<num_content_octets; i++)
net_octets[offset+num_content_octets-1-i] = content_octets[offset+i];
/* pse 1/16/96 if we have the value encoded and the leading encoding bit is set
then stuff in a leading zero byte */
lead = (int)net_octets[offset];
if ((m_value > 0) && ((lead & 0x80) > 0)) {
offset = 0;
net_octets[offset] = (byte)0x00;
num_content_octets++;
}
}
stream.write(getType());
sendDefiniteLength(stream, num_content_octets);
stream.write(net_octets,offset,num_content_octets); /* contents */
}
/**
* Gets the integral value.
* @return element value.
*/
public int getValue() {
return m_value;
}
/**
* Gets the element type.
* @return element type.
*/
public abstract int getType();
/**
* Gets the string representation.
* @return string representation of tag.
*/
public abstract String toString();
}

Просмотреть файл

@ -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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the NULL type.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* tag = 0x05
* length value is zero (short or long form).
* no contents
*
* Example 1: (short form)
* 05 00
* Example 2: (long form)
* 05 81 00
* </pre>
*
* @version 1.0
*/
public class BERNull extends BERElement {
/**
* Constructs a NULL element.
*/
public BERNull() {
}
/**
* Constructs a null element from an input stream.
* @param stream input stream from socket
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
* @exception IOException failed to construct
*/
public BERNull(InputStream stream, int[] bytes_read) throws IOException {
/* The result should be zero of course */
readLengthOctets(stream,bytes_read);
}
/**
* Sends the BER encoding directly to stream.
* @param stream output stream
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
byte[] buffer = new byte[2];
buffer[0] = (byte)BERElement.NULL; /* NULL tag */
buffer[1] = 0x00; /* length */
stream.write(buffer);
}
/**
* Gets the element type.
* @return element type.
*/
public int getType() {
return BERElement.NULL;
}
/**
* Gets the string representation.
* @return string representation of tag.
*/
public String toString() {
return "Null {}";
}
}

Просмотреть файл

@ -0,0 +1,102 @@
/* -*- 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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the NumericString type.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x12
* length = (short or long form)
* one or more contents octets
* </pre>
*
* @version 1.0
*/
public class BERNumericString extends BERCharacterString {
/**
* Constructs a numeric string element from a string
* @param buffer string with value of element
*/
public BERNumericString(String string) {
m_value = string;
}
/**
* Constructs a numeric string element from a byte array
* @param buffer buffer
*/
public BERNumericString(byte[] buffer) {
super(buffer);
}
/**
* Constructs a numeric string element from an input stream
* (for constructed encoding)
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read
* @exception IOException failed to construct
*/
public BERNumericString(BERTagDecoder decoder, InputStream stream,
int[] bytes_read) throws IOException {
super(decoder,stream,bytes_read);
}
/**
* Constructs a numericstring element from an input stream
* (for primitive encoding)
* @param stream input stream
* @param bytes_read array of 1 int, incremented by number of bytes read
* @exception IOException failed to construct
*/
public BERNumericString(InputStream stream, int[] bytes_read)
throws IOException {
super(stream,bytes_read);
}
/**
* Gets the element type.
* @return element type.
*/
public int getType() {
return BERElement.NUMERICSTRING;
}
/**
* Gets the string representation. Note that currently prints out
* values in decimal form.
* @return string representation of tag.
*/
public String toString() {
if (m_value == null)
return "NumericString (null)";
else
return "NumericString {" + m_value + "}";
}
}

Просмотреть файл

@ -0,0 +1,192 @@
/* -*- 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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.util.StringTokenizer;
import java.io.*;
/**
* This class is for the Object ID object.
* <P>See CCITT X.209.
*
* @version 1.0
*/
public class BERObjectId extends BERElement {
/**
* Values of each component of the OID
*/
private int[] m_value = null;
/**
* Constructs an object ID element from an array of values.
* @param value object ID value as array of components
*/
public BERObjectId(int[] value) {
m_value = new int[value.length];
System.arraycopy(value,0,m_value,0,value.length);
}
/**
* Constructs an object id element from a string.
* @param value object id value in format "2.100.3"
*/
public BERObjectId(String value) {
StringTokenizer tokenizer = new StringTokenizer(value, ".");
m_value = new int[tokenizer.countTokens()];
for (int i=0; i<m_value.length; i++)
m_value[i] = Integer.parseInt(tokenizer.nextToken());
}
/**
* Constructs an object id element from an input stream.
* @param stream source
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
* @exception IOException failed to construct
*/
public BERObjectId(InputStream stream, int[] bytes_read) throws IOException {
int contents_length = super.readLengthOctets(stream, bytes_read);
bytes_read[0] += contents_length;
int[] contents_read = new int[1];
Vector oid = new Vector(10);
contents_read[0] = 0;
int sub_id = readSubIdentifier(stream, contents_read);
contents_length -= contents_read[0];
if (sub_id < 40)
oid.addElement(new Integer(0));
else if (sub_id < 80)
oid.addElement(new Integer(1));
else
oid.addElement(new Integer(2));
oid.addElement(new Integer(
sub_id - (((Integer)oid.elementAt(
oid.size()-1)).intValue() * 40)));
while (contents_length > 0) {
contents_read[0] = 0;
sub_id = readSubIdentifier(stream, contents_read);
contents_length -= contents_read[0];
oid.addElement(new Integer(sub_id));
}
m_value = new int[oid.size()];
for (int i = 0; i<oid.size(); i++)
m_value[i] = ((Integer)oid.elementAt(i)).intValue();
}
/**
* Sends the BER encoding directly to a stream. Note that OID must
* have >= 2 identifier components (values).
* @param stream output stream
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
stream.write(BERElement.OBJECTID);
ByteArrayOutputStream contents_stream = new ByteArrayOutputStream();
/* first subidentifier packs two component values */
writeSubIdentifier(contents_stream,m_value[0]*40 + m_value[1]);
for (int i = 2; i < m_value.length; i++) {
writeSubIdentifier(contents_stream,m_value[i]);
}
byte[] contents_buffer = contents_stream.toByteArray();
sendDefiniteLength(stream, contents_buffer.length);
stream.write(contents_buffer);
}
/**
* Reads a sub identifier from stream.
* @param stream input stream
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
*/
private int readSubIdentifier(InputStream stream, int[] bytes_read)
throws IOException {
int octet;
int sub_id = 0;
do {
octet = stream.read();
bytes_read[0]++;
sub_id = (sub_id << 7) | (octet & 0x7F);
} while ((octet & 0x80) > 0);
return sub_id;
}
/**
* Sends the BER encoding of a sub identifier directly to stream.
* @param stream output stream
* @param value sub-identifier value
*/
private void writeSubIdentifier(OutputStream stream, int value)
throws IOException {
ByteArrayOutputStream sub_id_stream = new ByteArrayOutputStream();
/* gather octets in reverse order */
while (value > 0) {
sub_id_stream.write(value & 0x7F);
value = value >> 7;
}
byte[] sub_id_buffer = sub_id_stream.toByteArray();
for (int i=sub_id_buffer.length-1; i>0; i--) {
/* all but last octet have bit 8 = 1 */
stream.write(sub_id_buffer[i] | 0x80);
}
stream.write(sub_id_buffer[0]); /* last octet has bit 8 = 0 */
}
/**
* Gets the element value.
* @return element value.
*/
public int[] getValue() {
return m_value;
}
/**
* Gets the element type.
* @return element type.
*/
public int getType() {
return BERElement.OBJECTID;
}
/**
* Gets the string representation.
* @return string representation of element.
*/
public String toString() {
if (m_value == null)
return "ObjectIdentifier (null)";
String oid = "";
for (int i = 0; i < m_value.length; i++) {
if (i != 0)
oid = oid + " ";
oid = oid + m_value[i];
}
return "ObjectIdentifier {" + oid + "}";
}
}

Просмотреть файл

@ -0,0 +1,201 @@
/* -*- 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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the OctetString type.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x04
* length = (short or long form)
* one or more contents octets
* </pre>
*
* @version 1.0
*/
public class BEROctetString extends BERElement {
/**
* Raw value of element
*/
private byte[] m_value = null;
/**
* Constructs an octet string element containing a copy of
* the contents of buffer.
* @param buffer a UCS-2 String
*/
public BEROctetString(String buffer) {
if (buffer == null)
return;
try {
m_value = buffer.getBytes( "UTF8" );
} catch (Throwable xxx){};
}
/**
* Constructs an octet string element containing a reference to
* buffer.
* @param buffer a byte array, which must be in UTF-8 format if
* it is string data
*/
public BEROctetString(byte[] buffer) {
m_value = buffer;
}
/**
* Constructs an octet string element containing a
* subset of buffer.
* @param buffer buffer containing 'octets'
* @param start start of buffer range to copy
* @param end end of buffer range to copy
*/
public BEROctetString(byte[] buffer, int start, int end) {
m_value = new byte[end - start];
for (int i = 0; i < end - start; i++)
m_value[i] = buffer[start + i];
}
/**
* Constructs an octet string element from an input stream
* (for constructed encoding)
* @param decoder a decode that understands the specific tags
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read
* @exception IOException failed to construct
*/
public BEROctetString(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 an octetstring - add it to the existing buffer */
BEROctetString octet_element = (BEROctetString)element;
byte[] octet_buffer = octet_element.getValue();
if (m_value == null) {
m_value = new byte[octet_buffer.length];
System.arraycopy(octet_buffer,0,
m_value,0,octet_buffer.length);
} else {
byte[] new_buffer = new byte[m_value.length +
octet_buffer.length];
System.arraycopy(m_value,0,new_buffer,0,m_value.length);
System.arraycopy(octet_buffer,0,
new_buffer,m_value.length,
octet_buffer.length);
m_value = new_buffer;
}
}
} while (element != null);
} else {
/* Definite length content octets string. */
bytes_read[0] += contents_length;
m_value = new byte[contents_length];
stream.read(m_value, 0, contents_length);
}
}
/**
* Constructs an octet 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 BEROctetString(InputStream stream, int[] bytes_read)
throws IOException {
int contents_length = super.readLengthOctets(stream, bytes_read);
/* Definite length content octets string. */
if (contents_length > 0) {
m_value = new byte[contents_length];
for (int i = 0; i < contents_length; i++) {
m_value[i] = (byte) stream.read();
}
bytes_read[0] += contents_length;
}
}
/**
* Writes BER to stream
* @return number of bytes written to stream.
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
stream.write((byte)BERElement.OCTETSTRING); /* OCTETSTRING tag */
if (m_value == null) {
sendDefiniteLength(stream, 0);
} else {
sendDefiniteLength(stream, m_value.length); /* length */
stream.write(m_value,0,m_value.length); /* contents */
}
}
/**
* Gets the element value.
* @param element value
*/
public byte[] getValue() {
return m_value;
}
/**
* Gets the element type.
* @param element type
*/
public int getType() {
return BERElement.OCTETSTRING;
}
/**
* Gets the string representation.
* NOTE: currently prints out values in decimal form.
* @return string representation of tag.
*/
public String toString() {
if (m_value == null)
return "OctetString (null)";
String octets = "";
for (int i = 0; i < m_value.length; i++) {
if (i != 0)
octets = octets + " ";
octets = octets + byteToHexString(m_value[i]);
}
return "OctetString {" + octets + "}";
}
}

Просмотреть файл

@ -0,0 +1,102 @@
/* -*- 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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the PrintableString type.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x13
* length = (short or long form)
* one or more contents octets
* </pre>
*
* @version 1.0
*/
public class BERPrintableString extends BERCharacterString {
/**
* Constructs a printable string element containing buffer.
* @param buffer string value
*/
public BERPrintableString(String string) {
m_value = string;
}
/**
* Constructs a printables tring element from buffer.
* @param buffer byte array value
*/
public BERPrintableString(byte[] buffer) {
super(buffer);
}
/**
* Constructs a printable string element from an input stream
* (for constructed encoding)
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read
* @exception IOException failed to construct
*/
public BERPrintableString(BERTagDecoder decoder, InputStream stream,
int[] bytes_read) throws IOException {
super(decoder,stream,bytes_read);
}
/**
* Constructs a printablestring 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 BERPrintableString(InputStream stream, int[] bytes_read)
throws IOException {
super(stream,bytes_read);
}
/**
* Gets the element type.
* @return element type.
*/
public int getType() {
return BERElement.PRINTABLESTRING;
}
/**
* Gets the string representation. Note that it prints out
* values in decimal form.
* @return string representation of tag.
*/
public String toString() {
if (m_value == null)
return "PrintableString (null)";
else
return "PrintableString {" + m_value + "}";
}
}

Просмотреть файл

@ -0,0 +1,213 @@
/* -*- 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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the Real object.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* tag = 0x09
* </pre>
*
* @version 1.0
*/
public class BERReal extends BERElement {
/**
* Constants: special ASN.1 real values
*/
public final static float PLUS_INFINITY = 1.0f/0.0f;
public final static float MINUS_INFINITY = -1.0f/0.0f;
/**
* Value of element
*/
private float m_value = 0;
/**
* Constructs a real element with a value
* @param value float value
*/
public BERReal(float value) {
m_value = value;
}
/**
* Constructs a real element from an input stream.
* @param stream source
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream.
* @exception IOException failed to construct
*/
public BERReal(InputStream stream, int[] bytes_read) throws IOException {
int length = super.readLengthOctets(stream, bytes_read);
if (length == 0)
/* zero length indicates value is zero */
m_value = 0;
else {
int octet = stream.read(); /* first content octet */
bytes_read[0]++;
if (octet == 0x40) /* bit 8 = 1 */
m_value = PLUS_INFINITY;
else if (octet == 0x41) /* bit 8 = 1 and bit 1 = 1 */
m_value = MINUS_INFINITY;
else if ((octet & 0x80) > 0) {
/* bit 8 = 1 */
/* Binary encoding */
/* M = S*N*2F where S = -1 or 1, 0<= F <= 3. */
int sign;
int base;
int number;
int f; /* binary scaling factor */
int exponent;
int mantissa;
int num_exponent_octets;
int contents_length_left;
if ((octet & 0x40) > 0) sign = -1;
else sign = 1;
if ((octet & 0x20) > 0) {
if ((octet & 0x10) > 0) {
/* bits 6+5 = 11 */
/* reserved for future use */
base = 0;
} else {
/* bits 6+5 = 10 */
base = 16;
}
} else if ((octet & 0x10) > 0) {
/* bits 6+5 = 01 */
base = 8;
} else {
/* bits 6+5 = 00 */
base = 2;
}
if ((octet & 0x08) > 0) {
if ((octet & 0x04) > 0) {
/* bits 4+3 = 11 */
f = 3;
} else {
/* bits 4+3 = 10 */
f = 2;
}
} else if ((octet & 0x04) > 0) {
/* bits 4+3 = 01 */
f = 1;
} else {
/* bits 4+3 = 00 */
f = 0;
}
if ((octet & 0x02) > 0) {
if ((octet & 0x01) > 0) {
/* bits 2+1 = 11 */
/* Following octet encodes the number of octets used to
* encode the exponent.
*/
num_exponent_octets = stream.read();
bytes_read[0]++;
exponent = readTwosComplement(stream,bytes_read,num_exponent_octets);
} else {
/* bits 2+1 = 10 */
num_exponent_octets = 3;
exponent = readTwosComplement(stream,bytes_read,num_exponent_octets);
}
} else if ((octet & 0x01) > 0) {
/* bits 2+1 = 01 */
num_exponent_octets = 2;
exponent = readTwosComplement(stream,bytes_read,num_exponent_octets);
} else {
/* bits 2+1 = 00 */
num_exponent_octets = 1;
exponent = readTwosComplement(stream,bytes_read,num_exponent_octets);
}
contents_length_left = length - 1 - num_exponent_octets;
number = readUnsignedBinary(stream, bytes_read, contents_length_left);
mantissa = (int)(sign * number * Math.pow(2, f));
m_value = mantissa * (float)Math.pow((double)base,(double)exponent);
} else {
/* bits 8 + 7 = 00 */
/* ISO 6093 field */
/*** NOTE: It has been agreed that this feature will
* not be provided right now.
*/
throw new IOException("real ISO6093 not supported. ");
}
}
}
/**
* Sends the BER encoding directly to a stream.
* @param stream output stream
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
if (m_value == 0) {
stream.write(BERElement.REAL);
stream.write(0x00); /* length */
} else if (m_value == PLUS_INFINITY) {
stream.write(BERElement.REAL);
stream.write(0x01); /* length */
stream.write(0x40); /* contents */
} else if (m_value == MINUS_INFINITY) {
stream.write(BERElement.REAL);
stream.write(0x01); /* length */
stream.write(0x41); /* contents */
} else {
/* Non-special real value */
/* NOTE: currently always sends as a base 2 binary encoding
* (see X.2 09 section 10.5.)
*
* M = S * N * 2F
*
* Simple encoding always uses F = 1.
*/
// bcm - incomplete.
}
}
/**
* Gets the element type.
* @return element type
*/
public int getType() {
return BERElement.REAL;
}
/**
* Gets the string representation.
* @return string representation of tag
*/
public String toString() {
return "Real {" + m_value + "}";
}
}

Просмотреть файл

@ -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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the Sequence object. A sequence object can
* contains a sequence of BER Elements.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* tag = 0x30 (always constructed)
* </pre>
*
* @version 1.0
*/
public class BERSequence extends BERConstruct {
/**
* Constructs a sequence element.
*/
public BERSequence() {
super();
}
/**
* Constructs a sequence element from an input stream.
* @param decoder application-specific BER decoder
* @param stream input stream from which to read BER
* @param bytes_read array of 1 int; value is incremented by
* number of bytes read from stream
* @exception IOException failed to construct
*/
public BERSequence(BERTagDecoder decoder, InputStream stream,
int[] bytes_read) throws IOException {
super(decoder, stream, bytes_read);
}
/**
* Gets the element type.
* @return element type.
*/
public int getType() {
return BERElement.SEQUENCE;
}
/**
* Gets the string representation.
* @return string representation of tag.
*/
public String toString() {
String elements = "";
for (int i = 0; i < super.size(); i++) {
if (i != 0)
elements = elements + ", ";
elements = elements + ((BERElement)super.elementAt(i)).toString();
}
return "Sequence {" + elements + "}";
}
}

Просмотреть файл

@ -0,0 +1,90 @@
/* -*- 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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the Set object. A set object can contain
* a set of BER elements.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* tag = 0x31 (always constructed)
* </pre>
*
* @version 1.0
*/
public class BERSet extends BERConstruct {
/**
* Constructs a set element.
* @exception failed to construct
*/
public BERSet() throws IOException {
}
/**
* Constructs a set element from an input stream.
* @param decoder decoder for application-specific BER
* @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 BERSet(BERTagDecoder decoder, InputStream stream,
int[] bytes_read) throws IOException {
super(decoder, stream,bytes_read);
}
/**
* Sends the BER encoding directly to a stream.
* @param stream output stream
* @exception IOException failed to write
*/
public void write(OutputStream stream) throws IOException {
super.write(stream);
}
/**
* Gets the element type.
* @return element type.
*/
public int getType() {
return BERElement.SET;
}
/**
* Gets the string representation.
* @return string representation of tag.
*/
public String toString() {
String elements = "";
for (int i = 0; i < super.size(); i++) {
if (i != 0)
elements = elements + ", ";
elements = elements + ((BERElement)super.elementAt(i)).toString();
}
return "Set {" + elements + "}";
}
}

Просмотреть файл

@ -0,0 +1,168 @@
/* -*- 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 org.ietf.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.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* tag = whatever it is constructed with
* </pre>
*
* @version 1.0
*/
public class BERTag extends BERElement {
/**
* Value of tag
*/
private int m_tag = 0;
/**
* Value of element
*/
private BERElement m_element = null;
/**
* Implicit or not
*/
private boolean m_implicit = false;
/**
* Constructs a tag element.
* @param tag tag value
* @param element ber element
* @param implicit tagged implicitly
*/
public BERTag(int tag, BERElement element, boolean implicit) {
m_tag = tag;
m_element = element;
m_implicit = implicit;
}
/**
* Constructs a tag element from an input stream.
* @param decoder decoder object for application-specific tags
* @param tag tag value; already stripped from stream
* @param stream source
* @param bytes_read array of 1 int; incremented by number
* of bytes read from stream
* @exception IOException failed to construct
*/
public BERTag(BERTagDecoder decoder, int tag, InputStream stream,
int[] bytes_read) throws IOException {
m_tag = tag;
boolean[] implicit = new boolean[1];
/*
* Need to use user callback to decode contents of
* a non-universal tagged value.
*/
m_element = decoder.getElement(decoder, tag, stream, bytes_read,
implicit);
m_implicit = implicit[0];
}
/**
* Gets the element from the tagged object.
* @return BER element.
*/
public BERElement getValue() {
return m_element;
}
/**
* Sets the implicit tag. If it is an implicit tag,
* the next element tag can be omitted (it will
* not be sent to a stream or buffer).
* @param value implicit flag
*/
public void setImplicit(boolean value) {
m_implicit = value;
}
/**
* 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(m_tag); /* bcm - assuming tag is one byte */
ByteArrayOutputStream contents_stream = new ByteArrayOutputStream();
m_element.write(contents_stream);
byte[] contents_buffer = contents_stream.toByteArray();
if (m_implicit) {
/* Assumes tag is only one byte. Rest of buffer is */
/* length and contents of tagged element. */
stream.write(contents_buffer, 1, contents_buffer.length -1);
} else {
/* Send length */
sendDefiniteLength(stream, contents_buffer.length);
/* Send contents */
stream.write(contents_buffer);
}
}
/**
* Gets the element type.
* @return element type.
*/
public int getType() {
return BERElement.TAG;
}
/**
* Gets the element tag.
* @return element tag.
*/
public int getTag() {
return m_tag;
}
/**
* Gets the string representation.
* @return string representation of tag.
*/
public String toString() {
String s = "";
if ((m_tag & 0xC0) == 0)
/* bits 8 + 7 are zeros */
s = s + "UNIVERSAL-";
else if (((m_tag & 0x80) & (m_tag & 0x40)) > 0)
/* bits 8 + 7 are ones */
s = s + "PRIVATE-";
else if ((m_tag & 0x40) > 0)
/* bit 8 is zero, bit 7 is one */
s = s + "APPLICATION-";
else if ((m_tag & 0x80) > 0)
/* bit 8 is one, bit 7 is zero */
s = s + "CONTEXT-";
return "[" + s + (m_tag&0x1f) + "] " + m_element.toString();
}
}

Просмотреть файл

@ -0,0 +1,52 @@
/* -*- 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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This is an abstract class which should be extended
* for use by the BERTag class in decoding application
* specific BER tags. Since different applications may
* define their own tag, the BER package needs a tag decoder
* to give hints on how to decode implicitly tagged
* objects. Each application should extend this
* decoder.
*
* @version 1.0
*/
public abstract class BERTagDecoder {
/**
* Gets an application specific ber element from an input stream.
* @param decoder an instance of a BERTagDecoder
* @param tag element tag
* @param stream source stream
* @param bytes_read array of 1 int; value incremented by number
* of bytes read from stream
* @param implicit array of implicit flags
*/
public abstract BERElement getElement(BERTagDecoder decoder, int tag,
InputStream stream, int[] bytes_read, boolean[] implicit)
throws IOException;
}

Просмотреть файл

@ -0,0 +1,172 @@
/* -*- 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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the UTCTime object.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x17
* length = (short or long form)
* one or more contents octets
* </pre>
*
* @version 1.0
*/
public class BERUTCTime extends BERElement {
/**
* Internal variables
*/
private String m_value = null;
/**
* Constructs a UTC time element containing the specified string.
* @param utc_string string in UTC time format
*/
public BERUTCTime(String utc_string) {
m_value = utc_string;
}
/**
* Constructs a UTCTime element from an input stream
* (for constructed encoding)
* @param stream source
* @param bytes_read array of 1 int, incremented by number of bytes read
* @exception IOException failed to construct
*/
public BERUTCTime(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;
m_value = "";
if (contents_length == -1) {
/* Constructed - indefinite length content octets. */
{
component_length[0] = 0;
element = getElement(decoder,stream,component_length);
if (element != null) {
/* element is an octetstring - add it to the existing buffer */
BERUTCTime utc_element = (BERUTCTime)element;
m_value += utc_element.getValue();
}
} 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 an octetstring - add it to the existing buffer */
BERUTCTime utc_element = (BERUTCTime)element;
m_value += utc_element.getValue();
}
contents_length -= component_length[0];
}
}
}
/**
* Constructs a UTC time 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 BERUTCTime(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[] byte_buf = new byte[contents_length];
for (int i = 0; i < contents_length; i++) {
byte_buf[i] = (byte) stream.read();
}
bytes_read[0] += contents_length;
try{
m_value = new String(byte_buf, "UTF8");
} catch(Throwable x)
{}
}
}
/**
* Writes BER to a stream.
* @return number of bytes written to stream.
* @exception IOException failed to write
*/
private byte[] byte_buf;
public void write(OutputStream stream) throws IOException {
stream.write((byte)getType());
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 int getType() {
return BERElement.UTCTIME;
}
/**
* Gets the string representation.
* NOTE: currently prints out values in decimal form.
* @return string representation of tag.
*/
public String toString() {
if (m_value == null)
return "UTCTime (null)";
else
return "UTCTime {" + m_value + "}";
}
}

Просмотреть файл

@ -0,0 +1,102 @@
/* -*- 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 org.ietf.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the VisibleString object.
* <P>See CCITT X.209.
*
* <pre>
* ENCODING RULE:
* Primitive Definite length.
* tag = 0x1A
* length = (short or long form)
* one or more contents octets
* </pre>
*
* @version 1.0
*/
public class BERVisibleString extends BERCharacterString {
/**
* Constructs a visiblestring element.
* @param string string
*/
public BERVisibleString(String string) {
m_value = string;
}
/**
* Constructs a visiblestring element from buffer.
* @param buffer buffer
*/
public BERVisibleString(byte[] buffer) {
super(buffer);
}
/**
* Constructs a visiblestring element with the 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 BERVisibleString(BERTagDecoder decoder, InputStream stream,
int[] bytes_read) throws IOException {
super(decoder,stream,bytes_read);
}
/**
* Constructs a visiblestring element with the input stream.
* (for primitive encoding)
* @param stream input stream
* @param bytes_read array of 1 int, incremented by number of bytes read
* @exception IOException failed to construct
*/
public BERVisibleString(InputStream stream, int[] bytes_read)
throws IOException {
super(stream,bytes_read);
}
/**
* Gets the element type.
* @param element type
*/
public int getType() {
return BERElement.VISIBLESTRING;
}
/**
* Gets the string representation. Note that currently prints out
* values in decimal form.
* @return string representation of tag.
*/
public String toString() {
if (m_value == null)
return "VisibleString (null)";
return "VisibleString {" + m_value + "}";
}
}

Просмотреть файл

@ -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 org.ietf.ldap.client;
import java.util.*;
import java.io.*;
import org.ietf.ldap.ber.stream.*;
/**
* This class implements the attribute value assertion.
* This object is used with filters.
* <pre>
* AttributeValueAssertion ::= SEQUENCE {
* attributType AttributeType,
* attributValue AttributeValue
* }
* </pre>
*
* @version 1.0
*/
public class JDAPAVA {
/**
* Internal variables
*/
protected String m_type = null;
protected String m_val = null;
/**
* Constructs the attribute value assertion.
* @param type attribute type
* @param val attribute value
*/
public JDAPAVA(String type, String val) {
m_type = type;
m_val = val;
}
/**
* Retrieves the AVA type.
* @return AVA type
*/
public String getType() {
return m_type;
}
/**
* Retrieves the AVA value.
* @return AVA value
*/
public String getValue() {
return m_val;
}
/**
* Retrieves the ber representation.
* @return ber representation
*/
public BERElement getBERElement() {
BERSequence seq = new BERSequence();
seq.addElement(new BEROctetString(m_type));
seq.addElement(JDAPFilterOpers.getOctetString(m_val));
return seq;
}
/**
* Retrieves the string representation parameters.
* @return string representation parameters
*/
public String getParamString() {
return "{type=" + m_type + ", value=" + m_val + "}";
}
/**
* Retrieves the string representation.
* @return string representation
*/
public String toString() {
return "JDAPAVA " + getParamString();
}
}

Просмотреть файл

@ -0,0 +1,123 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class is to help BER libraries to make decision
* on how to decode an implicit object.
*/
public class JDAPBERTagDecoder extends BERTagDecoder {
/**
* Gets an application specific ber element from the stream.
* @param buffer ber encoding buffer
* @param stream input stream
* @param bytes_read number of bytes read
* @param implicit to indicate a tag implicit or not
*/
public BERElement getElement(BERTagDecoder decoder, int tag,
InputStream stream, int[] bytes_read, boolean[] implicit)
throws IOException {
BERElement element = null;
switch (tag) {
case 0x60: /* [APPLICATION 0] For Bind Request */
case 0x61: /* [APPLICATION 1] Bind Response */
case 0x63: /* [APPLICATION 3] Search Request
* If doing search without bind first,
* x500.arc.nasa.gov returns tag [APPLICATION 3]
* in Search Response. Gee.
*/
case 0x64: /* [APPLICATION 4] Search Response */
case 0x65: /* [APPLICATION 5] Search Result */
case 0x67: /* [APPLICATION 7] Modify Response */
case 0x69: /* [APPLICATION 9] Add Response */
case 0x6a: /* [APPLICATION 10] Del Request */
case 0x6b: /* [APPLICATION 11] Del Response */
case 0x6d: /* [APPLICATION 13] ModifyRDN Response */
case 0x6f: /* [APPLICATION 15] Compare Response */
case 0x78: /* [APPLICATION 23] Extended Response */
case 0x73: /* [APPLICATION 19] SearchResultReference */
element = new BERSequence(decoder, stream, bytes_read);
implicit[0] = true;
break;
case 0x80: /* [APPLICATION 16] 64+16 */
element = new BERInteger(stream, bytes_read);
implicit[0] = true;
break;
/* 16/02/97 MS specific */
case 0x85: /* Context Specific [5]:
* (a) Handle Microsoft v3 referral bugs! (Response)
* (b) Handle Microsoft v3 supportedVersion in Bind
* response
*/
element = new BERInteger(stream, bytes_read);
implicit[0] = true;
break;
case 0x87: /* Context Specific [7]:
* Handle Microsoft Filter "present" in
* search request.
*/
element = new BEROctetString(decoder, stream, bytes_read);
implicit[0] = true;
break;
case 0x8a: /* Context Specific [10]:
* Handle extended response
*/
element = new BEROctetString(decoder, stream, bytes_read);
implicit[0] = true;
break;
case 0x8b: /* Context Specific [11]:
* Handle extended response
*/
element = new BEROctetString(decoder, stream, bytes_read);
implicit[0] = true;
break;
case 0xa3: /* Context Specific <Construct> [3]:
* Handle Microsoft v3 sasl bind request
*/
element = new BERSequence(decoder, stream, bytes_read);
implicit[0] = true;
break;
case 0xa7: /* Context Specific <Construct> [7]:
* Handle Microsoft v3 serverCred in
* bind response. MS encodes it as SEQUENCE OF
* while it should be CHOICE OF.
*/
element = new BERSequence(decoder, stream, bytes_read);
implicit[0] = true;
break;
case 0xa0: /* Context Specific <Construct> [0]:
* v3 Server Control.
* SEQUENCE of SEQUENCE of {OID [critical] [value]}
*/
element = new BERSequence(decoder, stream, bytes_read);
implicit[0] = true;
break;
default:
throw new IOException();
}
return element;
}
}

Просмотреть файл

@ -0,0 +1,255 @@
/* -*- 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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the filter.
* <pre>
* Filter ::= CHOICE {
* and [0] SET OF Filter,
* or [1] SET OF Filter,
* not [2] Filter,
* equalityMatch [3] AttributeValueAssertion,
* substrings [4] SubstringFilter,
* greaterOrEqual [5] AttributeValueAssertion,
* lessOrEqual [6] AttributeValueAssertion,
* present [7] AttributeType,
* approxMatch [8] AttributeValueAssertion
* }
* </pre>
*
* @version 1.0
*/
public abstract class JDAPFilter {
/**
* Constructs a empty filter.
*/
public JDAPFilter() {
}
/**
* Constructs filter from filter string specified in RFC1558.
* <pre>
* <filter> ::= '(' <filtercomp> ')'
* <filtercomp> ::= <and> | <or> | <not> | <item>
* <and> ::= '&' <filterlist>
* <or> ::= '|' <filterlist>
* <not> ::= '!' <filter>
* <filterlist> ::= <filter> | <filter> <filterlist>
* <item> ::= <simple> | <present> | <substring>
* <simple> ::= <attr> <filtertype> <value>
* <filtertype> ::= <equal> | <approx> | <greater> | <less>
* <equal> ::= '='
* <approx> ::= '~='
* <greater> ::= '>='
* <less> ::= '<='
* <present> ::= <attr> '=*'
* <substring> ::= <attr> '=' <initial> <any> <final>
* <initial> ::= NULL | <value>
* <any> ::= '*' <starval>
* <starval> ::= NULL | <value> '*' <starval>
* <final> ::= NULL | <value>
* </pre>
* @param dn distinguished name of adding entry
* @param attrs list of attribute associated with entry
* @return filter
*/
public static JDAPFilter getFilter(String filter) {
String f = new String(filter);
f.trim();
if (f.startsWith("(") && f.endsWith(")")) {
return getFilterComp(f.substring(1,f.length()-1));
}
return getFilterComp(filter);
}
/**
* Constructs the filter computation.
* @param f filter string within brackets
* @return filter
*/
public static JDAPFilter getFilterComp(String f) {
f.trim();
if (f.startsWith("&")) { /* and */
JDAPFilter filters[] = getFilterList(f.substring(1, f.length()));
if (filters == null) {
throw new IllegalArgumentException("Bad search filter");
}
JDAPFilterAnd and = new JDAPFilterAnd();
for (int i = 0; i < filters.length; i++) {
and.addElement(filters[i]);
}
return and;
} else if (f.startsWith("|")) { /* or */
JDAPFilter filters[] = getFilterList(f.substring(1, f.length()));
if (filters == null) {
throw new IllegalArgumentException("Bad search filter");
}
JDAPFilterOr or = new JDAPFilterOr();
for (int i = 0; i < filters.length; i++) {
or.addElement(filters[i]);
}
return or;
} else if (f.startsWith("!")) { /* not */
JDAPFilter filter = getFilter(f.substring(1, f.length()));
if (filter == null) {
throw new IllegalArgumentException("Bad search filter");
}
return new JDAPFilterNot(filter);
} else { /* item */
return getFilterItem(f.substring(0, f.length()));
}
}
/**
* Parses a list of filters
* @param list filter list (i.e. (filter)(filter)...)
* @return list of filters
*/
public static JDAPFilter[] getFilterList(String list) {
list.trim();
int level = 0;
int start = 0;
int end = 0;
Vector v = new Vector();
for (int i = 0; i < list.length(); i++) {
if (list.charAt(i) == '(') {
if (level == 0) {
start = i;
}
level++;
}
if (list.charAt(i) == ')') {
level--;
if (level == 0) {
end = i;
v.addElement(JDAPFilter.getFilter(list.substring(start, end+1)));
}
}
}
if (v.size() == 0)
return null;
JDAPFilter f[] = new JDAPFilter[v.size()];
for (int i = 0; i < v.size(); i++) {
f[i] = (JDAPFilter)v.elementAt(i);
}
return f;
}
/**
* Gets filter item.
* @param item filter item string
* @return filter
*/
public static JDAPFilter getFilterItem(String item) {
item.trim();
int idx = item.indexOf('=');
if (idx == -1)
return null;
String type = item.substring(0, idx).trim();
String value = item.substring(idx+1).trim(); /* skip = */
// Only values can contain escape sequences
if (type.indexOf('\\') >= 0) {
throw new IllegalArgumentException("Bad search filter");
}
/* make decision by looking at the type */
type.trim();
if (type.endsWith("~")) {
JDAPAVA ava = new
JDAPAVA(type.substring(0, type.length()-1), value);
return new JDAPFilterApproxMatch(ava);
} else if (type.endsWith(">")) {
JDAPAVA ava = new
JDAPAVA(type.substring(0, type.length()-1), value);
return new JDAPFilterGreaterOrEqual(ava);
} else if (type.endsWith("<")) {
JDAPAVA ava = new
JDAPAVA(type.substring(0, type.length()-1), value);
return new JDAPFilterLessOrEqual(ava);
} else if (type.endsWith(":")) {
return new JDAPFilterExtensible(type.substring(0, type.length()-1), value);
}
/* for those that are not simple */
if (value.startsWith("*") && value.length() == 1) {
return new JDAPFilterPresent(type);
}
/* if value contains no '*', then it is equality */
if (value.indexOf('*') == -1) {
JDAPAVA ava = new JDAPAVA(type, value);
return new JDAPFilterEqualityMatch(ava);
}
/* must be substring at this point */
StringTokenizer st = new StringTokenizer(value, "*");
JDAPFilterSubString sub = new JDAPFilterSubString(type);
String initial = null;
if (!value.startsWith("*")) {
initial = st.nextToken();
initial.trim();
}
sub.addInitial(initial);
while (st.hasMoreTokens()) {
String any = st.nextToken();
any.trim();
if (st.hasMoreTokens()) {
sub.addAny(any);
} else {
if (value.endsWith("*")) {
sub.addAny(any);
sub.addFinal(null);
} else {
sub.addFinal(any);
}
}
}
return sub;
}
/**
* Gets the ber representation of filter.
* @return ber representation of filter
*/
public abstract BERElement getBERElement();
/**
* Retrieves the string representation of filter.
* @return string representation of filter
*/
public abstract String toString();
}

Просмотреть файл

@ -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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the attribute value assertion filter.
*
* @version 1.0
*/
public abstract class JDAPFilterAVA extends JDAPFilter {
/**
* Internal variables
*/
private int m_tag;
private JDAPAVA m_ava = null;
/**
* Constructs base filter for other attribute value assertion.
* @param tag attribute tag
* @param ava attribute value assertion
*/
public JDAPFilterAVA(int tag,
JDAPAVA ava) {
m_tag = tag;
m_ava = ava;
}
/**
* Get attribute value assertion.
* @return value assertion
*/
public JDAPAVA getAVA() {
return m_ava;
}
/**
* Gets the ber representation of the filter.
* @return ber representation
*/
public BERElement getBERElement() {
BERTag element = new BERTag(m_tag, m_ava.getBERElement(), true);
return element;
}
}

Просмотреть файл

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the filter And.
* <pre>
* and [0] SET OF Filter
* </pre>
*
* @version 1.0
*/
public class JDAPFilterAnd extends JDAPFilterSet {
/**
* Constructs the filter.
*/
public JDAPFilterAnd() {
super(BERTag.CONSTRUCTED|BERTag.CONTEXT|0);
}
/**
* Gets string reprensetation of the filter.
* @return string representation
*/
public String toString() {
return "JDAPFilterAnd {" + super.getParamString() + "}";
}
}

Просмотреть файл

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the approximate match filter.
* <pre>
* approxMatch [8] AttributeValueAssertion
* </pre>
*
* @version 1.0
*/
public class JDAPFilterApproxMatch extends JDAPFilterAVA {
/**
* Constructs approximate match filter.
* @param ava attribute value assertion
*/
public JDAPFilterApproxMatch(JDAPAVA ava) {
super(BERTag.CONSTRUCTED|BERTag.CONTEXT|8, ava);
}
/**
* Retrieves the string representation of the filter.
* @return string representation
*/
public String toString() {
return "JDAPFilterApproximateMatch {" +
super.getAVA().toString() + "}";
}
}

Просмотреть файл

@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the equality match filter.
* <P>See RFC 1777.
* <pre>
* equalityMatch [3] AttributeValueAssertion
* </pre>
*
* @version 1.0
*/
public class JDAPFilterEqualityMatch extends JDAPFilterAVA {
/**
* Constructs less or equal filter.
* @param ava attribute value assertion
*/
public JDAPFilterEqualityMatch(JDAPAVA ava) {
super(BERTag.CONSTRUCTED|BERTag.CONTEXT|3, ava);
}
/**
* Retrieves the string representation of the filter.
* @return string representation
*/
public String toString() {
return "JDAPFilterEqualityMatch {" +
super.getAVA().toString() + "}";
}
}

Просмотреть файл

@ -0,0 +1,132 @@
/* -*- 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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the extended match filter.
* <pre>
* extensibleMatch [9] AttributeValueAssertion
* </pre>
*
* @version 1.0
*/
public class JDAPFilterExtensible extends JDAPFilter {
/**
* Constructs extensible match filter.
* @param match Matching rule assertion
*/
public JDAPFilterExtensible(String type, String match) {
m_tag = BERTag.CONSTRUCTED|BERTag.CONTEXT|9;
m_type = type;
m_value = match;
}
/**
* Gets ber representation of the filter.
* <PRE>
* Extended filter: [type] [':dn'][':'oid]':='value
*
* BER: extensibleMatch [9] MatchingRuleAssertion
* MatchingRuleAssertion ::= SEQUENCE {
* matchingRule [1] MatchingRuleID OPTIONAL,
* type [2] AttributeDescription OPTIONAL,
* matchValue [3] AssertionValue,
* dnAttributes [4] BOOLEAN DEFAULT FALSE
* }
* </PRE>
* @return ber representation
*/
public BERElement getBERElement() {
String value = m_value;
String defs = m_type;
/* Need either ':dn' or ':'oid */
int colonIndex = defs.lastIndexOf(':');
if ( colonIndex == -1 ) {
return null;
}
/* Is it dn or oid? */
boolean isDN = false;
String oid = null;
if ( defs.regionMatches( true, colonIndex+1, "dn", 0, 2 ) )
isDN = true;
else
oid = defs.substring( colonIndex+1 );
/* Any more? */
defs = defs.substring( 0, colonIndex );
colonIndex = defs.lastIndexOf(':');
if ( colonIndex >= 0 ) {
/* Is it dn or oid? */
if ( defs.regionMatches( true, colonIndex+1, "dn", 0, 2 ) )
isDN = true;
else
oid = defs.substring( colonIndex+1 );
}
BERSequence seq = new BERSequence();
BERTag tag;
/* Was there an oid? */
if ( oid != null ) {
tag = new BERTag( BERTag.CONTEXT|BERTag.MRA_OID, new
BEROctetString(oid), true );
seq.addElement( tag );
}
/* Was there an attribute description? */
if ( defs.length() > 0 ) {
tag = new BERTag( BERTag.CONTEXT|BERTag.MRA_TYPE, new
BEROctetString(defs), true );
seq.addElement( tag );
}
/* Got to have a value */
tag = new BERTag( BERTag.CONTEXT|BERTag.MRA_VALUE, new
BEROctetString(value), true );
seq.addElement( tag );
/* Was ':dn' specified? */
tag = new BERTag( BERTag.CONTEXT|BERTag.MRA_DNATTRS, new
BERBoolean(isDN), true );
seq.addElement( tag );
BERTag element = new BERTag( m_tag, seq, true );
return element;
}
/**
* Retrieves the string representation of the filter.
* @return string representation
*/
public String toString() {
return "JDAPFilterExtensible {" + m_value + "}";
}
private int m_tag;
private String m_type = null;
private String m_value = null;
}

Просмотреть файл

@ -0,0 +1,55 @@
/* -*- 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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the greater or equal filter.
* <P>See RFC 1777.
*
* <pre>
* greaterOrEqual [5] AttributeValueAssertion
* </pre>
*
* @version 1.0
*/
public class JDAPFilterGreaterOrEqual extends JDAPFilterAVA {
/**
* Constructs greater or equal filter.
* @param ava attribute value assertion
*/
public JDAPFilterGreaterOrEqual(JDAPAVA ava) {
super(BERTag.CONSTRUCTED|BERTag.CONTEXT|5, ava);
}
/**
* Retrieves the string representation of the filter.
* @return string representation
*/
public String toString() {
return "JDAPFilterGreaterOrEqual {" +
super.getAVA().toString() + "}";
}
}

Просмотреть файл

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the less or equal filter.
* <pre>
* lessOrEqual [6] AttributeValueAssertion
* </pre>
*
* @version 1.0
*/
public class JDAPFilterLessOrEqual extends JDAPFilterAVA {
/**
* Constructs less or equal filter.
* @param ava attribute value assertion
*/
public JDAPFilterLessOrEqual(JDAPAVA ava) {
super(BERTag.CONSTRUCTED|BERTag.CONTEXT|6, ava);
}
/**
* Retrieves the string representation of the filter.
* @return string representation
*/
public String toString() {
return "JDAPFilterLessOrEqual {" +
super.getAVA().toString() + "}";
}
}

Просмотреть файл

@ -0,0 +1,70 @@
/* -*- 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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the filter not.
* <P>See RFC 1777.
*
* <pre>
* not [2] Filter
* </pre>
*
* @version 1.0
*/
public class JDAPFilterNot extends JDAPFilter {
/**
* Internal variables
*/
private JDAPFilter m_filter = null;
/**
* Constructs the filter.
*/
public JDAPFilterNot(JDAPFilter filter) {
super();
m_filter = filter;
}
/**
* Gets ber representation of the filter.
* @return ber representation
*/
public BERElement getBERElement() {
BERTag element = new BERTag(BERTag.CONSTRUCTED|BERTag.CONTEXT|2,
m_filter.getBERElement(), false /* true */);
return element;
}
/**
* Gets string reprensetation of the filter.
* @return string representation
*/
public String toString() {
return "JDAPFilterNot {" + m_filter.toString() + "}";
}
}

Просмотреть файл

@ -0,0 +1,179 @@
/* -*- 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 org.ietf.ldap.client;
import java.util.Vector;
import java.io.*;
import org.ietf.ldap.ber.stream.*;
/**
* This class provides miscellaneous operations for JDAPFilter object.
* It converts string with escape characters to the byte array. It also
* returns the ber octet string for the specified string with escape
* characters.
*/
public class JDAPFilterOpers {
private static final String escapeKey = "\\";
private static final boolean m_debug = false;
/**
* Returns the octetString for the given string
* @return The octetString for the given string
*/
static BEROctetString getOctetString(String str) {
if (str.indexOf(escapeKey) >= 0) {
byte[] byteVal = JDAPFilterOpers.getByteValues(str);
return new BEROctetString(byteVal);
}
else
return new BEROctetString(str);
}
/**
* Preprocess the LDAPv2 RFC1960 style filter escape sequences (precede
* a character with a a backslash) and convert them into the
* LDAPv3 style RFC2254 escape sequences (encode a character as a backslash
* followed by the two hex digits representing the character ASCII value).
*
* LDAPv3 style unescaping is done from the getByteValues()method. We must
* process LDAPv2 escaped characters earlier to get rid of possible "\(" \)"
* sequences which would make filter parsing in the JDAPFilter operate incorrectly.
*/
public static String convertLDAPv2Escape(String filter) {
if (filter.indexOf('\\') < 0) {
return filter;
}
StringBuffer sb = new StringBuffer();
int i=0, start=0, len=filter.length();
while(start < len && (i = filter.indexOf('\\', start)) >= 0 ) {
sb.append(filter.substring(start, i+1)); // include also '\'
try {
char c = filter.charAt(i+1);
if ((c >= ' ' && c < 127) && !isHexDigit(c)) {
sb.append(Integer.toHexString(c));
}
else {
sb.append(c);
}
start = i + 2;
}
catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException("Bad search filter");
}
}
if (start < len) {
sb.append(filter.substring(start));
}
return sb.toString();
}
private static boolean isHexDigit(char c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}
/**
* This method converts the given string into bytes. It also handles
* the escape characters embedded in the given string.
* @param str The given string being converted into a byte array
* @return A byte array
*/
static byte[] getByteValues(String str) {
int pos = 0;
Vector v = new Vector();
String val = new String(str);
int totalSize = 0;
// check if any escape character in the string
while ((pos = val.indexOf(escapeKey)) >= 0) {
String s1 = val.substring(0, pos);
try {
byte[] b = s1.getBytes("UTF8");
totalSize += b.length;
v.addElement(b);
} catch (UnsupportedEncodingException e) {
printDebug(e.toString());
return null;
}
Integer num = null;
// decode this number to integer, exception thrown when this is not the
// hex
try {
String hex = "0x"+val.substring(pos+1, pos+3);
num = Integer.decode(hex);
} catch (IndexOutOfBoundsException e) {
printDebug(e.toString());
throw new IllegalArgumentException("Bad search filter");
} catch (NumberFormatException e) {
printDebug(e.toString());
throw new IllegalArgumentException("Bad search filter");
}
byte[] b = {(byte)num.intValue()};
totalSize += b.length;
v.addElement(b);
// skip an escape and two chars after escape
val = val.substring(pos+3);
}
if (val.length() > 0) {
try {
byte[] b = val.getBytes("UTF8");
totalSize += b.length;
v.addElement(b);
} catch (UnsupportedEncodingException e) {
printDebug(e.toString());
return null;
}
}
byte[] result = new byte[totalSize];
pos = 0;
for (int i=0; i<v.size(); i++) {
byte[] b = (byte[])v.elementAt(i);
System.arraycopy(b, 0, result, pos, b.length);
pos = pos+b.length;
}
return result;
}
/**
* Print debug message
*/
private static void printDebug(String str) {
if (m_debug)
System.out.println(str);
}
}

Просмотреть файл

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the filter And.
* <P>See RFC 1777.
*
* <pre>
* or [1] SET OF Filter
* </pre>
*
* @version 1.0
*/
public class JDAPFilterOr extends JDAPFilterSet {
/**
* Constructs the filter.
*/
public JDAPFilterOr() {
super(BERTag.CONSTRUCTED|BERTag.CONTEXT|1);
}
/**
* Gets string reprensetation of the filter.
* @return string representation
*/
public String toString() {
return "JDAPFilterOr {" + super.getParamString() + "}";
}
}

Просмотреть файл

@ -0,0 +1,70 @@
/* -*- 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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the filter present.
* <P>See RFC 1777.
*
* <pre>
* present [7] AttributeType
* </pre>
*
* @version 1.0
*/
public class JDAPFilterPresent extends JDAPFilter {
/**
* Internal variables
*/
private String m_type = null;
/**
* Constructs the filter.
* @param type attribute type
*/
public JDAPFilterPresent(String type) {
super();
m_type = type;
}
/**
* Gets ber representation of the filter.
* @return ber representation
*/
public BERElement getBERElement() {
BEROctetString s = new BEROctetString(m_type);
BERTag element = new BERTag(BERTag.CONTEXT|7, s, true);
return element;
}
/**
* Gets string reprensetation of the filter.
* @return string representation
*/
public String toString() {
return "JDAPFilterPresent {" + m_type + "}";
}
}

Просмотреть файл

@ -0,0 +1,89 @@
/* -*- 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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the base class of filter "and" and filter "or".
*
* @version 1.0
*/
public abstract class JDAPFilterSet extends JDAPFilter {
/**
* Internal variables
*/
private int m_tag;
private Vector m_set = new Vector();
/**
* Constructs the filter set.
* @param tag tag
*/
public JDAPFilterSet(int tag) {
super();
m_tag = tag;
}
/**
* Adds filter into the filter set.
* @param filter adding filter
*/
public void addElement(JDAPFilter filter) {
m_set.addElement(filter);
}
/**
* Gets the ber representation of the filter.
* @return ber representation
*/
public BERElement getBERElement() {
try {
BERSet filters = new BERSet();
for (int i = 0; i < m_set.size(); i++) {
JDAPFilter f = (JDAPFilter)m_set.elementAt(i);
filters.addElement(f.getBERElement());
}
BERTag element = new BERTag(m_tag, filters, true);
return element;
} catch (IOException e) {
return null;
}
}
/**
* Gets the filter set parameters.
* @return set parameters
*/
public String getParamString() {
String s = "";
for (int i = 0; i < m_set.size(); i++) {
if (i != 0)
s = s + ",";
JDAPFilter f = (JDAPFilter)m_set.elementAt(i);
s = s + f.toString();
}
return s;
}
}

Просмотреть файл

@ -0,0 +1,154 @@
/* -*- 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 org.ietf.ldap.client;
import java.util.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the filter substring.
* <P>See RFC 1777.
*
* <pre>
* [4] SEQUENCE {
* type AttributeType,
* SEQUENCE OF CHOICE {
* initial [0] LDAPString,
* any [1] LDAPString,
* final [2] LDAPString
* }
* }
* </pre>
*
* @version 1.0
*/
public class JDAPFilterSubString extends JDAPFilter {
/**
* Internal variables
*/
private String m_type = null;
private Vector m_initial = new Vector();
private Vector m_any = new Vector();
private Vector m_final = new Vector();
/**
* Constructs the filter.
* @param type attribute type
*/
public JDAPFilterSubString(String type) {
super();
m_type = type;
}
/**
* Adds initial substring.
* @param s initial substring
*/
public void addInitial(String s) {
m_initial.addElement(s);
}
/**
* Adds any substring.
* @param s any substring
*/
public void addAny(String s) {
m_any.addElement(s);
}
/**
* Adds final substring.
* @param s final substring
*/
public void addFinal(String s) {
m_final.addElement(s);
}
/**
* Gets ber representation of the filter.
* @return ber representation
*/
public BERElement getBERElement() {
BERSequence seq = new BERSequence();
seq.addElement(new BEROctetString(m_type));
BERSequence str_seq = new BERSequence();
for (int i = 0; i < m_initial.size(); i++) {
String val = (String)m_initial.elementAt(i);
if (val == null)
continue;
BERTag str = new BERTag(BERTag.CONTEXT|0,
JDAPFilterOpers.getOctetString(val), true);
str_seq.addElement(str);
}
for (int i = 0; i < m_any.size(); i++) {
String val = (String)m_any.elementAt(i);
if (val == null)
continue;
BERTag str = new BERTag(BERTag.CONTEXT|1,
JDAPFilterOpers.getOctetString(val), true);
str_seq.addElement(str);
}
for (int i = 0; i < m_final.size(); i++) {
String val = (String)m_final.elementAt(i);
if (val == null)
continue;
BERTag str = new BERTag(BERTag.CONTEXT|2,
JDAPFilterOpers.getOctetString(val), true);
str_seq.addElement(str);
}
seq.addElement(str_seq);
BERTag element = new BERTag(BERTag.CONSTRUCTED|BERTag.CONTEXT|4,
seq, true);
return element;
}
/**
* Gets string reprensetation of the filter.
* @return string representation
*/
public String toString() {
String initial = "";
for (int i = 0; i < m_initial.size(); i++) {
if (i != 0)
initial = initial + ",";
initial = initial + (String)m_initial.elementAt(i);
}
String any = "";
for (int i = 0; i < m_any.size(); i++) {
if (i != 0)
any = any + ",";
any = any + (String)m_any.elementAt(i);
}
String s_final = "";
for (int i = 0; i < m_final.size(); i++) {
if (i != 0)
s_final = s_final + ",";
s_final = s_final + (String)m_final.elementAt(i);
}
return "JDAPFilterSubString {type=" + m_type + ", initial=" + initial +
", any=" + any + ", final=" + s_final + "}";
}
}

Просмотреть файл

@ -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 org.ietf.ldap.client.opers;
import java.util.*;
import org.ietf.ldap.client.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
import java.net.*;
/**
* This class implements the abandon request. This object
* is sent to the ldap server.
* <P>See RFC 1777.
*
* <pre>
* AbandonRequest ::= [APPLICATION 16] MessageID
* </pre>
*
* @version 1.0
*/
public class JDAPAbandonRequest implements JDAPProtocolOp {
/**
* Internal variables
*/
protected int m_msgid;
/**
* Constructs abandon request.
* @param msgid message identifier
*/
public JDAPAbandonRequest(int msgid) {
m_msgid = msgid;
}
/**
* Retrieves the protocol operation type.
* @return protocol type
*/
public int getType() {
return JDAPProtocolOp.ABANDON_REQUEST;
}
/**
* Gets the ber representation of abandon request.
* @return ber representation of request
*/
public BERElement getBERElement() {
/* Assumed m_msgid = 1. The BER encoding output
* should be
*
* [*] umich-ldap-v3.3:
* 0x50 (implicit tagged integer)
* 0x01 (length)
* 0x01 (message id)
*/
BERInteger i = new BERInteger(m_msgid);
BERTag element = new BERTag(BERTag.APPLICATION|16, i, true);
return element;
}
/**
* Retrieves the string representation of abandon request.
* @return string representation
*/
public String toString() {
return "AbandonRequest {msgid=" + m_msgid + "}";
}
}

Просмотреть файл

@ -0,0 +1,146 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.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 org.ietf.ldap.client.opers;
import java.util.*;
import org.ietf.ldap.*;
import org.ietf.ldap.client.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the add request. This object
* is sent to the ldap server.
* <P>See RFC 1777.
*
* <pre>
* AddRequest ::= [APPLICATION 8] SEQUENCE {
* entry LDAPDN,
* attrs SEQUENCE OF SEQUENCE {
* type AttributeType,
* values SET OF AttributeValue
* }
* }
* </pre>
*
* @version 1.0
*/
public class JDAPAddRequest extends JDAPBaseDNRequest
implements JDAPProtocolOp {
/**
* Internal variables
*/
protected String m_dn = null;
protected LDAPAttribute m_attrs[] = null;
/**
* Constructs add request.
* @param dn distinguished name of adding entry
* @param attrs list of attribute associated with entry
*/
public JDAPAddRequest(String dn, LDAPAttribute attrs[]) {
m_dn = dn;
m_attrs = attrs;
}
/**
* Retrieves protocol operation type.
* @return protcol type
*/
public int getType() {
return JDAPProtocolOp.ADD_REQUEST;
}
/**
* Sets the base dn component.
* @param basedn base dn
*/
public void setBaseDN(String basedn) {
m_dn = basedn;
}
/**
* Gets the base dn component.
* @return base dn
*/
public String getBaseDN() {
return m_dn;
}
/**
* Gets the ber representation of add request.
* @return ber representation of request
*/
public BERElement getBERElement() {
/* Assumed that adding cn=patrick,o=ncware,c=ca with
* following attributes:
* cn: patrick
* title: programmer
* [*] umich-ldap-v3.3:
* 0x68 0x46 ([APPLICATION8])
* 0x04 0x1a c n = p a t r i c k , 0x20
* o = n c w a r e , 0x20 c =
* c a (entry - OctetString)
* 0x30 0x28 (SEQUENCE)
* 0x30 0x0f (SEQUENCE)
* 0x04 0x02 c n (attribute type - OctetString)
* 0x31 0x09 (SET OF)
* 0x04 0x07 p a t r i c k (attribute value - OctetString)
* 0x30 0x15
* 0x04 0x05 t i t l e
* 0x31 0x0c (SET OF)
* 0x04 0x0a p r o g r a m m e r
*/
BERSequence seq = new BERSequence();
seq.addElement(new BEROctetString (m_dn));
BERSequence attrs_list = new BERSequence();
for (int i = 0; i < m_attrs.length; i++) {
attrs_list.addElement(m_attrs[i].getBERElement());
}
seq.addElement(attrs_list);
BERTag element = new BERTag(BERTag.APPLICATION|BERTag.CONSTRUCTED|8,
seq, true);
return element;
}
/**
* Retrieves the string representation of add request parameters.
* @return string representation of add request parameters
*/
public String getParamString() {
String s = "";
for (int i = 0; i < m_attrs.length; i++) {
if (i != 0)
s = s + " ";
s = s + m_attrs[i].toString();
}
return "{entry='" + m_dn + "', attrs='" + s + "'}";
}
/**
* Retrieves the string representation of add request.
* @return string representation of add request
*/
public String toString() {
return "AddRequest " + getParamString();
}
}

Просмотреть файл

@ -0,0 +1,65 @@
/* -*- 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 org.ietf.ldap.client.opers;
import java.util.*;
import org.ietf.ldap.client.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
import java.net.*;
/**
* This class implements the add response. This object
* is sent from the ldap server to the interface.
* <P>See RFC 1777.
*
* <pre>
* AddResponse ::= [APPLICATION 9] LDAPResult
* </pre>
*
* @version 1.0
*/
public class JDAPAddResponse extends JDAPResult implements JDAPProtocolOp {
/**
* Constructs add response.
* @param element ber element of add response
*/
public JDAPAddResponse(BERElement element) throws IOException {
super(((BERTag)element).getValue());
}
/**
* Retrieves the protocol operation type.
* @return protocol type
*/
public int getType() {
return JDAPProtocolOp.ADD_RESPONSE;
}
/**
* Retrieve the string representation.
* @return string representation
*/
public String toString() {
return "AddResponse " + super.getParamString();
}
}

Просмотреть файл

@ -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 org.ietf.ldap.client.opers;
import java.util.*;
import org.ietf.ldap.client.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
import java.net.*;
/**
* This is the base class for all the request that
* has a base dn component. The existence of this
* class is due to the JDAPReferralThread.
*
* @version 1.0
*/
public abstract class JDAPBaseDNRequest {
/**
* Sets the base dn component in the request.
* @param basedn base DN
*/
public abstract void setBaseDN(String basedn);
/**
* Gets the base dn component in the request.
* @return base dn
*/
public abstract String getBaseDN();
}

Просмотреть файл

@ -0,0 +1,193 @@
/* -*- 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 org.ietf.ldap.client.opers;
import java.util.*;
import org.ietf.ldap.client.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
import java.net.*;
/**
* This class implements the bind request. This object is
* sent to the ldap server.
* <pre>
* BindRequest ::= [APPLICATION 0] SEQUENCE {
* version INTEGER(1..127) ,
* name LDAPDN,
* authentication CHOICE {
* simple [0] OCTET STRING,
* krbv42LDAP [1] OCTET STRING,
* krbv42DSA [2] OCTET STRING
* }
* }
* </pre>
*
* Note that LDAPv3 bind reuqest is structured as follows:
* <pre>
* BindRequest ::= [APPLICATION 0] SEQUENCE {
* version INTEGER (1..127)
* name LDAPDN,
* authentication AuthenticationChoice
* }
* AuthenticationChoice ::= CHOICE {
* simple [0] OCTET STRING,
* -- 1 and 2 reserved
* sasl [3] SaslCredentials
* }
* SaslCredentials ::= SEQUENCE {
* mechanism LDAPString,
* credentials OCTET STRING
* }
* </pre>
*
* @version 1.0
*/
public class JDAPBindRequest implements JDAPProtocolOp {
/**
* Internal variables
*/
protected int m_version;
protected String m_name = null;
protected byte[] m_password = null;
protected String m_mechanism = null;
/**
* Constructs anonymous or simple bind request.
* @param version version
* @param name distinguished name
* @param password password
*/
public JDAPBindRequest(int version, String name, String password) {
m_version = version;
m_name = name;
try {
m_password = password.getBytes("UTF8");
} catch ( UnsupportedEncodingException e ) {
}
}
/**
* Constructs anonymous or simple bind request.
* @param version version
* @param name distinguished name
* @param password password
*/
public JDAPBindRequest(int version, String name, byte[] password) {
m_version = version;
m_name = name;
m_password = password;
}
/**
* Constructs a LDAP v3.0 SaslCredentials bind request.
* @param version version
* @param name distinguished name
* @param mechanism mechanism (must not be null)
* @param credentials credientials
*/
public JDAPBindRequest(int version, String name, String mechanism,
byte credentials[]) {
m_version = version;
m_name = name;
m_mechanism = mechanism;
m_password = credentials;
}
/**
* Retrieves the protocol operation type.
* @return protocol type
*/
public int getType() {
return JDAPProtocolOp.BIND_REQUEST;
}
/**
* Retrieves the ber representation of the request.
* @return ber representation
*/
public BERElement getBERElement() {
/* anonymous bind
* [*] umich-ldap-v3.3:
* 0x60 0x07 (implicit [Application 0] Sequence)
* 0x02 0x01 0x02 (Integer)
* 0x04 0x00 (OctetString)
* 0x80 0x00 (implicit OctetString)
* [*] zoomit server v1.0:
* 0x60 0x0b
* 0x30 0x09 (sequece)
* 0x02 0x01 0x02
* 0x04 0x00
* 0xa0 0x02 (explicit tag)
* 0x04 0x00
* simple bind with "cn=root,o=ncware,c=ca", "password"
* [*] umich-ldap-v3.3:
* 0x60 0x24 ([APPLICATION 0])
* 0x02 0x01 0x02 (version - Integer)
* 0x04 0x15 c n = r o o t , o = n c w a r e ,
* c = c a
* 0x80 0x08 p a s s w o r d
*/
BERSequence seq = new BERSequence();
seq.addElement(new BERInteger(m_version));
seq.addElement(new BEROctetString(m_name));
BERTag auth = null;
if (m_mechanism == null) {
auth = new BERTag(BERTag.CONTEXT, new BEROctetString(m_password),
true);
} else {
BERSequence sasl = new BERSequence();
sasl.addElement(new BEROctetString(m_mechanism));
if (m_password == null) {
sasl.addElement(new BEROctetString((byte[])null));
} else {
sasl.addElement(new BEROctetString(m_password, 0,
m_password.length));
}
auth = new BERTag(BERTag.SASLCONTEXT|3, /* SaslCredentials */
sasl, true);
}
seq.addElement(auth);
BERTag element = new BERTag(BERTag.APPLICATION|BERTag.CONSTRUCTED|0,
seq, true);
return element;
}
/**
* Retrieves the string representation of the request parameters.
* @return string representation parameters
*/
public String getParamString() {
return "{version=" + m_version + ", name=" + m_name +
", mechanism=" + m_mechanism +
", authentication=" +
((m_password == null) ? "null" : /*"********"*/new String(m_password)) + "}";
}
/**
* Retrieves the string representation of the request.
* @return string representation
*/
public String toString() {
return "BindRequest " + getParamString();
}
}

Просмотреть файл

@ -0,0 +1,119 @@
/* -*- 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 org.ietf.ldap.client.opers;
import java.util.*;
import org.ietf.ldap.client.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
/**
* This class implements the bind response. This object
* is sent from the ldap server to the interface.
* <pre>
* BindResponse = [APPLICATION 1] LDAPResult
* </pre>
*
* Note that LDAPv3.0 Bind Response is structured as follows:
* <pre>
* BindResponse ::= [APPLICATION 1] SEQUENCE {
* COMPONENTS OF LDAPResult,
* serverCreds [7] SaslCredentials OPTIONAL
* }
* </pre>
*
*/
public class JDAPBindResponse extends JDAPResult implements JDAPProtocolOp {
/**
* Internal variables
*/
protected byte[] m_credentials = null;
/**
* Constructs bind response.
* @param element ber element of bind response
*/
public JDAPBindResponse(BERElement element) throws IOException {
super(((BERTag)element).getValue());
/* LDAPv3 Sasl Credentials support */
BERSequence s = (BERSequence)((BERTag)element).getValue();
if (s.size() <= 3) {
return;
}
BERElement e = s.elementAt(3);
if (e.getType() == BERElement.TAG) {
BERElement el = ((BERTag)e).getValue();
if (el instanceof BERSequence) {
el = ((BERSequence)el).elementAt(0);
}
BEROctetString str = (BEROctetString)el;
try{
m_credentials = str.getValue();
} catch(Exception ex)
{}
}
}
/**
* Retrieves Sasl Credentials. LDAPv3 support.
* @return credentials
*/
public byte[] getCredentials() {
return m_credentials;
}
/**
* Retrieves the protocol operation type.
* @return protocol type
*/
public int getType() {
return JDAPProtocolOp.BIND_RESPONSE;
}
/**
* Retrieve the string representation.
* @return string representation
*/
public String toString() {
StringBuffer sb = new StringBuffer("BindResponse {resultCode=");
sb.append(m_result_code);
sb.append(", serverSaslCreds=" +
((m_credentials == null) ? "null" : /*"********"*/new String(m_credentials)));
if (m_matched_dn != null) {
sb.append(", matchedDN=");
sb.append(m_matched_dn);
}
if (m_error_message != null) {
sb.append(", errorMessage=");
sb.append(m_error_message);
}
if (m_referrals != null && m_referrals.length > 0) {
sb.append(", referrals=");
for (int i=0; i < m_referrals.length; i++) {
sb.append((i==0 ? "" : " "));
sb.append(m_referrals[i]);
}
}
sb.append("}");
return sb.toString();
}
}

Просмотреть файл

@ -0,0 +1,105 @@
/* -*- 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 org.ietf.ldap.client.opers;
import java.util.*;
import org.ietf.ldap.client.*;
import org.ietf.ldap.ber.stream.*;
import java.io.*;
import java.net.*;
/**
* This class implements the compare request. This object
* is sent to the ldap server.
* <pre>
* CompareRequest ::= [APPLICATION 14] SEQUENCE {
* entry LDAPDN,
* ava AttributeValueAssertion
* }
* </pre>
*
* @version 1.0
*/
public class JDAPCompareRequest extends JDAPBaseDNRequest
implements JDAPProtocolOp {
/**
* Internal variables
*/
protected String m_dn = null;
protected JDAPAVA m_ava = null;
/**
* Constructs the compare request.
* @param dn distinguished name of the entry to be compared
* @param ava attribut value assertion
*/
public JDAPCompareRequest(String dn, JDAPAVA ava) {
m_dn = dn;
m_ava = ava;
}
/**
* Retrieves the protocol operation type.
* @return operation type
*/
public int getType() {
return JDAPProtocolOp.COMPARE_REQUEST;
}
/**
* Sets the base dn.
* @param basedn base dn
*/
public void setBaseDN(String basedn) {
m_dn = basedn;
}
/**
* Gets the base dn.
* @return base dn
*/
public String getBaseDN() {
return m_dn;
}
/**
* Retrieves the ber representation of the request.
* @return ber request
*/
public BERElement getBERElement() {
BERSequence seq = new BERSequence();
seq.addElement(new BEROctetString(m_dn));
seq.addElement(m_ava.getBERElement());
BERTag element = new BERTag(BERTag.APPLICATION|BERTag.CONSTRUCTED|14,
seq, true);
return element;
}
/**
* Retrieves the string representation of the request.
* @return string representation
*/
public String toString() {
return "CompareRequest {entry=" + m_dn + ", ava=" + m_ava.toString() +
"}";
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше