blob: 068f0253118c11c405ca0f05ff7ae01391cd9921 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.server.core.jndi;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.authn.LdapPrincipal;
import org.apache.directory.server.core.entry.ServerEntry;
import org.apache.directory.server.core.entry.ServerEntryUtils;
import org.apache.directory.server.core.interceptor.context.EntryOperationContext;
import org.apache.directory.server.core.partition.PartitionNexusProxy;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.entry.Modification;
import org.apache.directory.shared.ldap.entry.client.ClientBinaryValue;
import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
import org.apache.directory.shared.ldap.filter.AndNode;
import org.apache.directory.shared.ldap.filter.BranchNode;
import org.apache.directory.shared.ldap.filter.EqualityNode;
import org.apache.directory.shared.ldap.filter.ExprNode;
import org.apache.directory.shared.ldap.filter.FilterParser;
import org.apache.directory.shared.ldap.filter.PresenceNode;
import org.apache.directory.shared.ldap.filter.SimpleNode;
import org.apache.directory.shared.ldap.message.AliasDerefMode;
import org.apache.directory.shared.ldap.message.ModificationItemImpl;
import org.apache.directory.shared.ldap.name.AttributeTypeAndValue;
import org.apache.directory.shared.ldap.name.LdapDN;
import org.apache.directory.shared.ldap.name.Rdn;
import org.apache.directory.shared.ldap.util.AttributeUtils;
import org.apache.directory.shared.ldap.util.StringTools;
import javax.naming.Name;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InvalidSearchFilterException;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.event.EventDirContext;
import javax.naming.event.NamingListener;
import javax.naming.spi.DirStateFactory;
import javax.naming.spi.DirectoryManager;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
/**
* The DirContext implementation for the Server Side JNDI LDAP provider.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev$
*/
public abstract class ServerDirContext extends ServerContext implements EventDirContext
{
// ------------------------------------------------------------------------
// Constructors
// ------------------------------------------------------------------------
/**
* Creates a new ServerDirContext by reading the PROVIDER_URL to resolve the
* distinguished name for this context.
*
* @param service the parent service that manages this context
* @param env the environment used for this context
* @throws NamingException if something goes wrong
*/
public ServerDirContext( DirectoryService service, Hashtable<String, Object> env ) throws NamingException
{
super( service, env );
}
/**
* Creates a new ServerDirContext with a distinguished name which is used to
* set the PROVIDER_URL to the distinguished name for this context.
*
* @param principal the principal which is propagated
* @param dn the distinguished name of this context
*/
public ServerDirContext( DirectoryService service, LdapPrincipal principal, Name dn ) throws NamingException
{
super( service, principal, dn );
}
// ------------------------------------------------------------------------
// DirContext Implementations
// ------------------------------------------------------------------------
/**
* @see javax.naming.directory.DirContext#getAttributes(java.lang.String)
*/
public Attributes getAttributes( String name ) throws NamingException
{
return getAttributes( new LdapDN( name ) );
}
/**
* @see javax.naming.directory.DirContext#getAttributes(javax.naming.Name)
*/
public Attributes getAttributes( Name name ) throws NamingException
{
return ServerEntryUtils.toAttributesImpl( doLookupOperation( buildTarget( name ) ) );
}
/**
* @see javax.naming.directory.DirContext#getAttributes(java.lang.String,
* java.lang.String[])
*/
public Attributes getAttributes( String name, String[] attrIds ) throws NamingException
{
return getAttributes( new LdapDN( name ), attrIds );
}
/**
* @see javax.naming.directory.DirContext#getAttributes(javax.naming.Name,
* java.lang.String[])
*/
public Attributes getAttributes( Name name, String[] attrIds ) throws NamingException
{
return ServerEntryUtils.toAttributesImpl( doLookupOperation( buildTarget( name ), attrIds ) );
}
/**
* @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String,
* int, javax.naming.directory.Attributes)
*/
public void modifyAttributes( String name, int modOp, Attributes attrs ) throws NamingException
{
modifyAttributes( new LdapDN( name ), modOp, AttributeUtils.toCaseInsensitive( attrs ) );
}
/**
* @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String,
* int, javax.naming.directory.Attributes)
*/
public void modifyAttributes( Name name, int modOp, Attributes attrs ) throws NamingException
{
List<ModificationItemImpl> modItems = null;
if ( attrs != null )
{
modItems = new ArrayList<ModificationItemImpl>( attrs.size() );
NamingEnumeration<? extends Attribute> e = ( NamingEnumeration<? extends Attribute> ) attrs.getAll();
while ( e.hasMore() )
{
modItems.add( new ModificationItemImpl( modOp, e.next() ) );
}
}
List<Modification> newMods = ServerEntryUtils.toServerModification( modItems, registries
.getAttributeTypeRegistry() );
if ( name instanceof LdapDN )
{
doModifyOperation( buildTarget( name ), newMods );
}
else
{
doModifyOperation( buildTarget( new LdapDN( name ) ), newMods );
}
}
/**
* @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String,
* javax.naming.directory.ModificationItem[])
*/
public void modifyAttributes( String name, ModificationItem[] mods ) throws NamingException
{
ModificationItemImpl[] newMods = new ModificationItemImpl[mods.length];
for ( int i = 0; i < mods.length; i++ )
{
newMods[i] = new ModificationItemImpl( mods[i] );
}
modifyAttributes( new LdapDN( name ), newMods );
}
/**
* @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String,
* javax.naming.directory.ModificationItem[])
*/
public void modifyAttributes( String name, ModificationItemImpl[] mods ) throws NamingException
{
modifyAttributes( new LdapDN( name ), mods );
}
/**
* @see javax.naming.directory.DirContext#modifyAttributes(
* javax.naming.Name, javax.naming.directory.ModificationItem[])
*/
public void modifyAttributes( Name name, ModificationItem[] mods ) throws NamingException
{
List<Modification> newMods = ServerEntryUtils
.toServerModification( mods, registries.getAttributeTypeRegistry() );
doModifyOperation( buildTarget( new LdapDN( name ) ), newMods );
}
/**
* @see javax.naming.directory.DirContext#modifyAttributes(
* javax.naming.Name, javax.naming.directory.ModificationItem[])
*/
public void modifyAttributes( Name name, List<ModificationItemImpl> mods ) throws NamingException
{
List<Modification> newMods = ServerEntryUtils
.toServerModification( mods, registries.getAttributeTypeRegistry() );
doModifyOperation( buildTarget( new LdapDN( name ) ), newMods );
}
/**
* @see javax.naming.directory.DirContext#bind(java.lang.String,
* java.lang.Object, javax.naming.directory.Attributes)
*/
public void bind( String name, Object obj, Attributes attrs ) throws NamingException
{
bind( new LdapDN( name ), obj, AttributeUtils.toCaseInsensitive( attrs ) );
}
/**
* @see javax.naming.directory.DirContext#bind(javax.naming.Name,
* java.lang.Object, javax.naming.directory.Attributes)
*/
public void bind( Name name, Object obj, Attributes attrs ) throws NamingException
{
if ( ( null == obj ) && ( null == attrs ) )
{
throw new NamingException( "Both obj and attrs args are null. "
+ "At least one of these parameters must not be null." );
}
// A null attrs defaults this to the Context.bind() operation
if ( null == attrs )
{
super.bind( name, obj );
return;
}
LdapDN target = buildTarget( name );
ServerEntry serverEntry = ServerEntryUtils.toServerEntry( AttributeUtils.toCaseInsensitive( attrs ), target,
registries );
// No object binding so we just add the attributes
if ( null == obj )
{
ServerEntry clone = ( ServerEntry ) serverEntry.clone();
doAddOperation( target, clone );
return;
}
// First, use state factories to do a transformation
DirStateFactory.Result res = DirectoryManager.getStateToBind( obj, name, this, getEnvironment(), attrs );
ServerEntry outServerEntry = ServerEntryUtils.toServerEntry( res.getAttributes(), target, registries );
if ( outServerEntry != serverEntry )
{
ServerEntry clone = ( ServerEntry ) serverEntry.clone();
if ( ( outServerEntry != null ) && ( outServerEntry.size() > 0 ) )
{
for ( EntryAttribute attribute : outServerEntry )
{
clone.put( attribute );
}
}
doAddOperation( target, clone );
return;
}
// Check for Referenceable
if ( obj instanceof Referenceable )
{
throw new NamingException( "Do not know how to store Referenceables yet!" );
}
// Store different formats
if ( obj instanceof Reference )
{
// Store as ref and add outAttrs
throw new NamingException( "Do not know how to store References yet!" );
}
else if ( obj instanceof Serializable )
{
// Serialize and add outAttrs
ServerEntry clone = ( ServerEntry ) serverEntry.clone();
if ( outServerEntry != null && outServerEntry.size() > 0 )
{
for ( EntryAttribute attribute : outServerEntry )
{
clone.put( attribute );
}
}
// Serialize object into entry attributes and add it.
JavaLdapSupport.serialize( serverEntry, obj, registries );
doAddOperation( target, clone );
}
else if ( obj instanceof DirContext )
{
// Grab attributes and merge with outAttrs
ServerEntry entry = ServerEntryUtils.toServerEntry( ( ( DirContext ) obj ).getAttributes( "" ), target,
registries );
if ( ( outServerEntry != null ) && ( outServerEntry.size() > 0 ) )
{
for ( EntryAttribute attribute : outServerEntry )
{
entry.put( attribute );
}
}
doAddOperation( target, entry );
}
else
{
throw new NamingException( "Can't find a way to bind: " + obj );
}
}
/**
* @see javax.naming.directory.DirContext#rebind(java.lang.String,
* java.lang.Object, javax.naming.directory.Attributes)
*/
public void rebind( String name, Object obj, Attributes attrs ) throws NamingException
{
rebind( new LdapDN( name ), obj, AttributeUtils.toCaseInsensitive( attrs ) );
}
/**
* @see javax.naming.directory.DirContext#rebind(javax.naming.Name,
* java.lang.Object, javax.naming.directory.Attributes)
*/
public void rebind( Name name, Object obj, Attributes attrs ) throws NamingException
{
LdapDN target = buildTarget( name );
if ( getNexusProxy().hasEntry( new EntryOperationContext( registries, target ) ) )
{
doDeleteOperation( target );
}
bind( name, obj, AttributeUtils.toCaseInsensitive( attrs ) );
}
/**
* @see javax.naming.directory.DirContext#createSubcontext(java.lang.String,
* javax.naming.directory.Attributes)
*/
public DirContext createSubcontext( String name, Attributes attrs ) throws NamingException
{
return createSubcontext( new LdapDN( name ), AttributeUtils.toCaseInsensitive( attrs ) );
}
/**
* @see javax.naming.directory.DirContext#createSubcontext(
* javax.naming.Name, javax.naming.directory.Attributes)
*/
public DirContext createSubcontext( Name name, Attributes attrs ) throws NamingException
{
if ( null == attrs )
{
return ( DirContext ) super.createSubcontext( name );
}
LdapDN target = buildTarget( name );
Rdn rdn = target.getRdn( target.size() - 1 );
attrs = AttributeUtils.toCaseInsensitive( attrs );
Attributes attributes = ( Attributes ) attrs.clone();
if ( rdn.size() == 1 )
{
String rdnAttribute = rdn.getUpType();
String rdnValue = ( String ) rdn.getValue();
// Add the Rdn attribute
boolean doRdnPut = attributes.get( rdnAttribute ) == null;
doRdnPut = doRdnPut || attributes.get( rdnAttribute ).size() == 0;
// TODO Fix DIRSERVER-832
doRdnPut = doRdnPut || !attributes.get( rdnAttribute ).contains( rdnValue );
if ( doRdnPut )
{
attributes.put( rdnAttribute, rdnValue );
}
}
else
{
for ( Iterator<AttributeTypeAndValue> ii = rdn.iterator(); ii.hasNext(); /**/)
{
AttributeTypeAndValue atav = ii.next();
// Add the Rdn attribute
boolean doRdnPut = attributes.get( atav.getNormType() ) == null;
doRdnPut = doRdnPut || attributes.get( atav.getNormType() ).size() == 0;
// TODO Fix DIRSERVER-832
doRdnPut = doRdnPut || !attributes.get( atav.getNormType() ).contains( atav.getNormValue() );
if ( doRdnPut )
{
attributes.put( atav.getNormType(), atav.getNormValue() );
}
}
}
// Add the new context to the server which as a side effect adds
doAddOperation( target, ServerEntryUtils.toServerEntry( attributes, target, registries ) );
// Initialize the new context
return new ServerLdapContext( getService(), getPrincipal(), target );
}
/**
* Presently unsupported operation!
*/
public DirContext getSchema( Name name ) throws NamingException
{
throw new UnsupportedOperationException();
}
/**
* Presently unsupported operation!
*/
public DirContext getSchema( String name ) throws NamingException
{
throw new UnsupportedOperationException();
}
/**
* Presently unsupported operation!
*/
public DirContext getSchemaClassDefinition( Name name ) throws NamingException
{
throw new UnsupportedOperationException();
}
/**
* Presently unsupported operation!
*/
public DirContext getSchemaClassDefinition( String name ) throws NamingException
{
throw new UnsupportedOperationException();
}
// ------------------------------------------------------------------------
// Search Operation Implementations
// ------------------------------------------------------------------------
/**
* @see javax.naming.directory.DirContext#search(java.lang.String,
* javax.naming.directory.Attributes)
*/
public NamingEnumeration<SearchResult> search( String name, Attributes matchingAttributes ) throws NamingException
{
return search( new LdapDN( name ), matchingAttributes, null );
}
/**
* @see javax.naming.directory.DirContext#search(javax.naming.Name,
* javax.naming.directory.Attributes)
*/
public NamingEnumeration<SearchResult> search( Name name, Attributes matchingAttributes ) throws NamingException
{
return search( name, AttributeUtils.toCaseInsensitive( matchingAttributes ), null );
}
/**
* @see javax.naming.directory.DirContext#search(java.lang.String,
* javax.naming.directory.Attributes, java.lang.String[])
*/
public NamingEnumeration<SearchResult> search( String name, Attributes matchingAttributes,
String[] attributesToReturn ) throws NamingException
{
return search( new LdapDN( name ), AttributeUtils.toCaseInsensitive( matchingAttributes ), attributesToReturn );
}
/**
* @see javax.naming.directory.DirContext#search(javax.naming.Name,
* javax.naming.directory.Attributes, java.lang.String[])
*/
public NamingEnumeration<SearchResult> search( Name name, Attributes matchingAttributes, String[] attributesToReturn )
throws NamingException
{
SearchControls ctls = new SearchControls();
LdapDN target = buildTarget( name );
// If we need to return specific attributes add em to the SearchControls
if ( null != attributesToReturn )
{
ctls.setReturningAttributes( attributesToReturn );
}
// If matchingAttributes is null/empty use a match for everything filter
matchingAttributes = AttributeUtils.toCaseInsensitive( matchingAttributes );
if ( ( null == matchingAttributes ) || ( matchingAttributes.size() <= 0 ) )
{
PresenceNode filter = new PresenceNode( SchemaConstants.OBJECT_CLASS_AT );
AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() );
return ServerEntryUtils.toSearchResultEnum( doSearchOperation( target, aliasDerefMode, filter, ctls ) );
}
// Handle simple filter expressions without multiple terms
if ( matchingAttributes.size() == 1 )
{
NamingEnumeration<? extends Attribute> list = matchingAttributes.getAll();
Attribute attr = list.next();
list.close();
if ( attr.size() == 1 )
{
Object value = attr.get();
SimpleNode node;
if ( value instanceof byte[] )
{
node = new EqualityNode( attr.getID(), new ClientBinaryValue( ( byte[] ) value ) );
}
else
{
node = new EqualityNode( attr.getID(), new ClientStringValue( ( String ) value ) );
}
AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() );
return ServerEntryUtils.toSearchResultEnum( doSearchOperation( target, aliasDerefMode, node, ctls ) );
}
}
/*
* Go through the set of attributes using each attribute value pair as
* an attribute value assertion within one big AND filter expression.
*/
Attribute attr;
SimpleNode node;
BranchNode filter = new AndNode();
NamingEnumeration<? extends Attribute> list = matchingAttributes.getAll();
// Loop through each attribute value pair
while ( list.hasMore() )
{
attr = list.next();
/*
* According to JNDI if an attribute in the matchingAttributes
* list does not have any values then we match for just the presence
* of the attribute in the entry
*/
if ( attr.size() == 0 )
{
filter.addNode( new PresenceNode( attr.getID() ) );
continue;
}
/*
* With 1 or more value we build a set of simple nodes and add them
* to the AND node - each attribute value pair is a simple AVA node.
*/
for ( int ii = 0; ii < attr.size(); ii++ )
{
Object val = attr.get( ii );
// Add simpel AVA node if its value is a String
if ( val instanceof String )
{
node = new EqualityNode( attr.getID(), new ClientStringValue( ( String ) val ) );
filter.addNode( node );
}
}
}
AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() );
return ServerEntryUtils.toSearchResultEnum( doSearchOperation( target, aliasDerefMode, filter, ctls ) );
}
/**
* @see javax.naming.directory.DirContext#search(java.lang.String,
* java.lang.String, javax.naming.directory.SearchControls)
*/
public NamingEnumeration<SearchResult> search( String name, String filter, SearchControls cons )
throws NamingException
{
return search( new LdapDN( name ), filter, cons );
}
/**
* A search overload that is used for optimizing search handling in the
* LDAP protocol provider which deals with an ExprNode instance rather than
* a String for the filter.
*
* @param name the relative name of the object serving as the search base
* @param filter the search filter as an expression tree
* @param cons the search controls to use
* @return an enumeration over the SearchResults
* @throws NamingException if there are problems performing the search
*/
public NamingEnumeration<SearchResult> search( Name name, ExprNode filter, SearchControls cons )
throws NamingException
{
LdapDN target = buildTarget( name );
AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() );
return ServerEntryUtils.toSearchResultEnum( doSearchOperation( target, aliasDerefMode, filter, cons ) );
}
/**
* A search overload that is used for optimizing search handling in the
* LDAP protocol provider which deals with an ExprNode instance rather than
* a String for the filter.
*
* @param name the relative name of the object serving as the search base
* @param filter the search filter as an expression tree
* @param cons the search controls to use
* @return an enumeration over the SearchResults
* @throws NamingException if there are problems performing the search
*/
public NamingEnumeration<SearchResult> search( Name name, ExprNode filter, SearchControls cons, InetSocketAddress clientAddress )
throws NamingException
{
LdapDN target = buildTarget( name );
AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() );
return ServerEntryUtils.toSearchResultEnum( doSearchOperation( target, aliasDerefMode, filter, cons, clientAddress ) );
}
/**
* @see javax.naming.directory.DirContext#search(javax.naming.Name,
* java.lang.String, javax.naming.directory.SearchControls)
*/
public NamingEnumeration<SearchResult> search( Name name, String filter, SearchControls cons )
throws NamingException
{
ExprNode filterNode;
LdapDN target = buildTarget( name );
try
{
filterNode = FilterParser.parse( filter );
}
catch ( ParseException pe )
{
InvalidSearchFilterException isfe = new InvalidSearchFilterException(
"Encountered parse exception while parsing the filter: '" + filter + "'" );
isfe.setRootCause( pe );
throw isfe;
}
AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() );
return ServerEntryUtils.toSearchResultEnum( doSearchOperation( target, aliasDerefMode, filterNode, cons ) );
}
/**
* @see javax.naming.directory.DirContext#search(java.lang.String,
* java.lang.String, java.lang.Object[],
* javax.naming.directory.SearchControls)
*/
public NamingEnumeration<SearchResult> search( String name, String filterExpr, Object[] filterArgs,
SearchControls cons ) throws NamingException
{
return search( new LdapDN( name ), filterExpr, filterArgs, cons );
}
/**
* @see javax.naming.directory.DirContext#search(javax.naming.Name,
* java.lang.String, java.lang.Object[],
* javax.naming.directory.SearchControls)
*/
public NamingEnumeration<SearchResult> search( Name name, String filterExpr, Object[] filterArgs,
SearchControls cons ) throws NamingException
{
int start;
int index;
StringBuffer buf = new StringBuffer( filterExpr );
// Scan until we hit the end of the string buffer
for ( int ii = 0; ii < buf.length(); ii++ )
{
try
{
// Advance until we hit the start of a variable
while ( ii < buf.length() && '{' != buf.charAt( ii ) )
{
ii++;
}
// Record start of variable at '{'
start = ii;
// Advance to the end of a variable at '}'
while ( '}' != buf.charAt( ii ) )
{
ii++;
}
}
catch ( IndexOutOfBoundsException e )
{
// End of filter so done.
break;
}
// Parse index
index = Integer.parseInt( buf.substring( start + 1, ii ) );
if ( filterArgs[index] instanceof String )
{
/*
* Replace the '{ i }' with the string representation of the value
* held in the filterArgs array at index index.
*/
buf.replace( start, ii + 1, ( String ) filterArgs[index] );
}
else if ( filterArgs[index] instanceof byte[] )
{
String hexstr = "#" + StringTools.toHexString( ( byte[] ) filterArgs[index] );
buf.replace( start, ii + 1, hexstr );
}
else
{
/*
* Replace the '{ i }' with the string representation of the value
* held in the filterArgs array at index index.
*/
buf.replace( start, ii + 1, filterArgs[index].toString() );
}
}
return search( name, buf.toString(), cons );
}
// ------------------------------------------------------------------------
// EventDirContext implementations
// ------------------------------------------------------------------------
public void addNamingListener( Name name, String filterStr, SearchControls searchControls,
NamingListener namingListener ) throws NamingException
{
ExprNode filter;
try
{
filter = FilterParser.parse( filterStr );
}
catch ( Exception e )
{
NamingException e2 = new NamingException( "could not parse filter: " + filterStr );
e2.setRootCause( e );
throw e2;
}
( ( PartitionNexusProxy ) getNexusProxy() ).addNamingListener( this, buildTarget( name ), filter,
searchControls, namingListener );
getListeners().add( namingListener );
}
public void addNamingListener( String name, String filter, SearchControls searchControls,
NamingListener namingListener ) throws NamingException
{
addNamingListener( new LdapDN( name ), filter, searchControls, namingListener );
}
public void addNamingListener( Name name, String filterExpr, Object[] filterArgs, SearchControls searchControls,
NamingListener namingListener ) throws NamingException
{
int start;
StringBuffer buf = new StringBuffer( filterExpr );
// Scan until we hit the end of the string buffer
for ( int ii = 0; ii < buf.length(); ii++ )
{
// Advance until we hit the start of a variable
while ( '{' != buf.charAt( ii ) )
{
ii++;
}
// Record start of variable at '{'
start = ii;
// Advance to the end of a variable at '}'
while ( '}' != buf.charAt( ii ) )
{
ii++;
}
/*
* Replace the '{ i }' with the string representation of the value
* held in the filterArgs array at index index.
*/
buf.replace( start, ii + 1, filterArgs[ii].toString() );
}
addNamingListener( name, buf.toString(), searchControls, namingListener );
}
public void addNamingListener( String name, String filter, Object[] objects, SearchControls searchControls,
NamingListener namingListener ) throws NamingException
{
addNamingListener( new LdapDN( name ), filter, objects, searchControls, namingListener );
}
}