зеркало из https://github.com/mozilla/pjs.git
Initial checkin of org.ietf.ldap classes
This commit is contained in:
Родитель
2575676e90
Коммит
c69f6d09cf
|
@ -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 "criticality" 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 "LDAP server") 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), "criticality" 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 ("extended operations") 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 "LDAP server") 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() +
|
||||
"}";
|
||||
}
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче