| /* |
| * 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 |
| * |
| * https://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.ldap.client.template; |
| |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.apache.directory.api.i18n.I18n; |
| import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicyResponse; |
| import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicyResponseImpl; |
| import org.apache.directory.api.ldap.model.entry.Attribute; |
| import org.apache.directory.api.ldap.model.entry.Entry; |
| import org.apache.directory.api.ldap.model.entry.Value; |
| import org.apache.directory.api.ldap.model.exception.LdapException; |
| import org.apache.directory.api.ldap.model.message.AddRequest; |
| import org.apache.directory.api.ldap.model.message.AddResponse; |
| import org.apache.directory.api.ldap.model.message.BindRequest; |
| import org.apache.directory.api.ldap.model.message.BindRequestImpl; |
| import org.apache.directory.api.ldap.model.message.DeleteRequest; |
| import org.apache.directory.api.ldap.model.message.DeleteResponse; |
| import org.apache.directory.api.ldap.model.message.ModifyRequest; |
| import org.apache.directory.api.ldap.model.message.ModifyRequestImpl; |
| import org.apache.directory.api.ldap.model.message.ModifyResponse; |
| import org.apache.directory.api.ldap.model.message.ResultCodeEnum; |
| import org.apache.directory.api.ldap.model.message.ResultResponse; |
| import org.apache.directory.api.ldap.model.message.SearchRequest; |
| import org.apache.directory.api.ldap.model.message.SearchScope; |
| import org.apache.directory.api.ldap.model.name.Dn; |
| import org.apache.directory.ldap.client.api.EntryCursorImpl; |
| import org.apache.directory.ldap.client.api.LdapConnection; |
| import org.apache.directory.ldap.client.api.LdapConnectionPool; |
| import org.apache.directory.ldap.client.api.search.FilterBuilder; |
| import org.apache.directory.ldap.client.template.exception.LdapRequestUnsuccessfulException; |
| import org.apache.directory.ldap.client.template.exception.LdapRuntimeException; |
| import org.apache.directory.ldap.client.template.exception.PasswordException; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| |
| /** |
| * A facade for LDAP operations that handles all of the boiler plate code for |
| * you allowing more concise operations through the use of callbacks. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| * |
| * @see <a href="http://en.wikipedia.org/wiki/Template_method_pattern">Template method pattern</a> |
| */ |
| public class LdapConnectionTemplate implements LdapConnectionOperations, ModelFactory |
| { |
| private static final Logger LOG = LoggerFactory.getLogger( LdapConnectionTemplate.class ); |
| private static final EntryMapper<Dn> DN_ENTRY_MAPPER = new EntryMapper<Dn>() |
| { |
| @Override |
| public Dn map( Entry entry ) throws LdapException |
| { |
| return entry.getDn(); |
| } |
| }; |
| |
| private LdapConnectionPool connectionPool; |
| private final PasswordPolicyResponse passwordPolicyRequestControl; |
| private PasswordPolicyResponder passwordPolicyResponder; |
| private ModelFactory modelFactory; |
| |
| |
| /** |
| * Creates a new instance of LdapConnectionTemplate. |
| * |
| * @param connectionPool The pool to obtain connections from. |
| */ |
| public LdapConnectionTemplate( LdapConnectionPool connectionPool ) |
| { |
| if ( LOG.isDebugEnabled() ) |
| { |
| LOG.debug( I18n.msg( I18n.MSG_04174_CREATING_NEW_CONNECTION_TEMPLATE ) ); |
| } |
| |
| this.connectionPool = connectionPool; |
| this.passwordPolicyRequestControl = new PasswordPolicyResponseImpl(); |
| this.passwordPolicyResponder = new PasswordPolicyResponderImpl( |
| connectionPool.getLdapApiService() ); |
| this.modelFactory = new ModelFactoryImpl(); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public AddResponse add( Dn dn, final Attribute... attributes ) |
| { |
| return add( dn, |
| new RequestBuilder<AddRequest>() |
| { |
| @Override |
| public void buildRequest( AddRequest request ) throws LdapException |
| { |
| request.getEntry().add( attributes ); |
| } |
| } ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public AddResponse add( Dn dn, RequestBuilder<AddRequest> requestBuilder ) |
| { |
| AddRequest addRequest = newAddRequest( newEntry( dn ) ); |
| try |
| { |
| requestBuilder.buildRequest( addRequest ); |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| return add( addRequest ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public AddResponse add( AddRequest addRequest ) |
| { |
| LdapConnection connection = null; |
| try |
| { |
| connection = connectionPool.getConnection(); |
| return connection.add( addRequest ); |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| finally |
| { |
| returnLdapConnection( connection ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public PasswordWarning authenticate( String baseDn, String filter, SearchScope scope, char[] password ) |
| throws PasswordException |
| { |
| return authenticate( newSearchRequest( baseDn, filter, scope ), password ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public PasswordWarning authenticate( Dn baseDn, String filter, SearchScope scope, char[] password ) |
| throws PasswordException |
| { |
| return authenticate( newSearchRequest( baseDn, filter, scope ), password ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public PasswordWarning authenticate( SearchRequest searchRequest, char[] password ) throws PasswordException |
| { |
| Dn userDn = searchFirst( searchRequest, DN_ENTRY_MAPPER ); |
| if ( userDn == null ) |
| { |
| throw new PasswordException().setResultCode( ResultCodeEnum.INVALID_CREDENTIALS ); |
| } |
| |
| return authenticate( userDn, password ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public PasswordWarning authenticate( Dn userDn, char[] password ) throws PasswordException |
| { |
| LdapConnection connection = null; |
| try |
| { |
| connection = connectionPool.getConnection(); |
| return authenticateConnection( connection, userDn, password ); |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| finally |
| { |
| returnLdapConnection( connection ); |
| } |
| } |
| |
| |
| private PasswordWarning authenticateConnection( final LdapConnection connection, |
| final Dn userDn, final char[] password ) throws PasswordException |
| { |
| return passwordPolicyResponder.process( |
| new PasswordPolicyOperation() |
| { |
| @Override |
| public ResultResponse process() throws LdapException |
| { |
| MemoryClearingBuffer passwordBuffer = MemoryClearingBuffer.newInstance( password ); |
| try |
| { |
| BindRequest bindRequest = new BindRequestImpl() |
| .setDn( userDn ) |
| .setCredentials( passwordBuffer.getBytes() ) |
| .addControl( passwordPolicyRequestControl ); |
| |
| return connection.bind( bindRequest ); |
| } |
| finally |
| { |
| passwordBuffer.clear(); |
| } |
| } |
| } ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public DeleteResponse delete( Dn dn ) |
| { |
| return delete( dn, null ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public DeleteResponse delete( Dn dn, RequestBuilder<DeleteRequest> requestBuilder ) |
| { |
| DeleteRequest deleteRequest = newDeleteRequest( dn ); |
| if ( requestBuilder != null ) |
| { |
| try |
| { |
| requestBuilder.buildRequest( deleteRequest ); |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| } |
| return delete( deleteRequest ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public DeleteResponse delete( DeleteRequest deleteRequest ) |
| { |
| LdapConnection connection = null; |
| try |
| { |
| connection = connectionPool.getConnection(); |
| return connection.delete( deleteRequest ); |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| finally |
| { |
| returnLdapConnection( connection ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T execute( ConnectionCallback<T> connectionCallback ) |
| { |
| LdapConnection connection = null; |
| try |
| { |
| connection = connectionPool.getConnection(); |
| return connectionCallback.doWithConnection( connection ); |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| finally |
| { |
| returnLdapConnection( connection ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T lookup( Dn dn, EntryMapper<T> entryMapper ) |
| { |
| return lookup( dn, null, entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T lookup( Dn dn, String[] attributes, EntryMapper<T> entryMapper ) |
| { |
| LdapConnection connection = null; |
| try |
| { |
| connection = connectionPool.getConnection(); |
| Entry entry = attributes == null |
| ? connection.lookup( dn ) |
| : connection.lookup( dn, attributes ); |
| return entry == null ? null : entryMapper.map( entry ); |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| finally |
| { |
| returnLdapConnection( connection ); |
| } |
| } |
| |
| |
| private void modifyPassword( final LdapConnection connection, final Dn userDn, |
| final char[] newPassword ) throws PasswordException |
| { |
| passwordPolicyResponder.process( |
| new PasswordPolicyOperation() |
| { |
| @Override |
| public ResultResponse process() throws PasswordException, LdapException |
| { |
| // Can't use Password Modify: |
| // https://issues.apache.org/jira/browse/DIRSERVER-1935 |
| // So revert to regular Modify |
| MemoryClearingBuffer newPasswordBuffer = MemoryClearingBuffer.newInstance( newPassword ); |
| try |
| { |
| ModifyRequest modifyRequest = new ModifyRequestImpl() |
| .setName( userDn ) |
| .replace( "userPassword", newPasswordBuffer.getComputedBytes() ) |
| .addControl( passwordPolicyRequestControl ); |
| |
| return connection.modify( modifyRequest ); |
| } |
| finally |
| { |
| newPasswordBuffer.clear(); |
| } |
| } |
| } ); |
| |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void modifyPassword( Dn userDn, char[] newPassword ) |
| throws PasswordException |
| { |
| modifyPassword( userDn, null, newPassword, true ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void modifyPassword( Dn userDn, char[] oldPassword, |
| char[] newPassword ) throws PasswordException |
| { |
| modifyPassword( userDn, oldPassword, newPassword, false ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void modifyPassword( Dn userDn, char[] oldPassword, |
| char[] newPassword, boolean asAdmin ) throws PasswordException |
| { |
| LdapConnection connection = null; |
| try |
| { |
| connection = connectionPool.getConnection(); |
| if ( !asAdmin ) |
| { |
| authenticateConnection( connection, userDn, oldPassword ); |
| } |
| |
| modifyPassword( connection, userDn, newPassword ); |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| finally |
| { |
| returnLdapConnection( connection ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public ModifyResponse modify( Dn dn, RequestBuilder<ModifyRequest> requestBuilder ) |
| { |
| ModifyRequest modifyRequest = newModifyRequest( dn ); |
| try |
| { |
| requestBuilder.buildRequest( modifyRequest ); |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| return modify( modifyRequest ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public ModifyResponse modify( ModifyRequest modifyRequest ) |
| { |
| LdapConnection connection = null; |
| try |
| { |
| connection = connectionPool.getConnection(); |
| return connection.modify( modifyRequest ); |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| finally |
| { |
| returnLdapConnection( connection ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public AddRequest newAddRequest( Entry entry ) |
| { |
| return modelFactory.newAddRequest( entry ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Attribute newAttribute( String name ) |
| { |
| return modelFactory.newAttribute( name ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Attribute newAttribute( String name, byte[]... values ) |
| { |
| return modelFactory.newAttribute( name, values ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Attribute newAttribute( String name, String... values ) |
| { |
| return modelFactory.newAttribute( name, values ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Attribute newAttribute( String name, Value... values ) |
| { |
| return modelFactory.newAttribute( name, values ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public DeleteRequest newDeleteRequest( Dn dn ) |
| { |
| return modelFactory.newDeleteRequest( dn ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Dn newDn( String dn ) |
| { |
| return modelFactory.newDn( dn ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Entry newEntry( String dn ) |
| { |
| return modelFactory.newEntry( dn ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Entry newEntry( Dn dn ) |
| { |
| return modelFactory.newEntry( dn ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public ModifyRequest newModifyRequest( String dn ) |
| { |
| return modelFactory.newModifyRequest( dn ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public ModifyRequest newModifyRequest( Dn dn ) |
| { |
| return modelFactory.newModifyRequest( dn ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public SearchRequest newSearchRequest( String baseDn, FilterBuilder filter, SearchScope scope ) |
| { |
| return modelFactory.newSearchRequest( baseDn, filter, scope ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public SearchRequest newSearchRequest( String baseDn, String filter, SearchScope scope ) |
| { |
| return modelFactory.newSearchRequest( baseDn, filter, scope ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public SearchRequest newSearchRequest( Dn baseDn, FilterBuilder filter, SearchScope scope ) |
| { |
| return modelFactory.newSearchRequest( baseDn, filter, scope ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public SearchRequest newSearchRequest( Dn baseDn, String filter, SearchScope scope ) |
| { |
| return modelFactory.newSearchRequest( baseDn, filter, scope ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public SearchRequest newSearchRequest( String baseDn, FilterBuilder filter, SearchScope scope, String... attributes ) |
| { |
| return modelFactory.newSearchRequest( baseDn, filter, scope, attributes ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public SearchRequest newSearchRequest( String baseDn, String filter, SearchScope scope, String... attributes ) |
| { |
| return modelFactory.newSearchRequest( baseDn, filter, scope, attributes ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public SearchRequest newSearchRequest( Dn baseDn, FilterBuilder filter, SearchScope scope, String... attributes ) |
| { |
| return modelFactory.newSearchRequest( baseDn, filter, scope, attributes ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public SearchRequest newSearchRequest( Dn baseDn, String filter, SearchScope scope, String... attributes ) |
| { |
| return modelFactory.newSearchRequest( baseDn, filter, scope, attributes ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T extends ResultResponse> T responseOrException( T response ) |
| { |
| if ( ResultCodeEnum.SUCCESS != response.getLdapResult().getResultCode() ) |
| { |
| throw new LdapRequestUnsuccessfulException( response ); |
| } |
| return response; |
| } |
| |
| |
| private void returnLdapConnection( LdapConnection connection ) |
| { |
| if ( connection != null ) |
| { |
| try |
| { |
| connectionPool.releaseConnection( connection ); |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> List<T> search( String baseDn, FilterBuilder filter, SearchScope scope, |
| EntryMapper<T> entryMapper ) |
| { |
| return search( |
| modelFactory.newSearchRequest( baseDn, filter, scope ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> List<T> search( String baseDn, String filter, SearchScope scope, |
| EntryMapper<T> entryMapper ) |
| { |
| return search( |
| modelFactory.newSearchRequest( baseDn, filter, scope ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> List<T> search( Dn baseDn, FilterBuilder filter, SearchScope scope, |
| EntryMapper<T> entryMapper ) |
| { |
| return search( |
| modelFactory.newSearchRequest( baseDn, filter, scope ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> List<T> search( Dn baseDn, String filter, SearchScope scope, |
| EntryMapper<T> entryMapper ) |
| { |
| return search( |
| modelFactory.newSearchRequest( baseDn, filter, scope ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> List<T> search( String baseDn, FilterBuilder filter, SearchScope scope, |
| String[] attributes, EntryMapper<T> entryMapper ) |
| { |
| return search( |
| modelFactory.newSearchRequest( baseDn, filter, scope, attributes ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> List<T> search( String baseDn, String filter, SearchScope scope, |
| String[] attributes, EntryMapper<T> entryMapper ) |
| { |
| return search( |
| modelFactory.newSearchRequest( baseDn, filter, scope, attributes ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> List<T> search( Dn baseDn, FilterBuilder filter, SearchScope scope, |
| String[] attributes, EntryMapper<T> entryMapper ) |
| { |
| return search( |
| modelFactory.newSearchRequest( baseDn, filter, scope, attributes ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> List<T> search( Dn baseDn, String filter, SearchScope scope, |
| String[] attributes, EntryMapper<T> entryMapper ) |
| { |
| return search( |
| modelFactory.newSearchRequest( baseDn, filter, scope, attributes ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> List<T> search( SearchRequest searchRequest, |
| EntryMapper<T> entryMapper ) |
| { |
| List<T> entries = new ArrayList<>(); |
| |
| LdapConnection connection = null; |
| try |
| { |
| connection = connectionPool.getConnection(); |
| |
| for ( Entry entry : new EntryCursorImpl( connection.search( searchRequest ) ) ) |
| { |
| entries.add( entryMapper.map( entry ) ); |
| } |
| } |
| catch ( LdapException e ) |
| { |
| throw new LdapRuntimeException( e ); |
| } |
| finally |
| { |
| returnLdapConnection( connection ); |
| } |
| |
| return entries; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T searchFirst( String baseDn, FilterBuilder filter, SearchScope scope, |
| EntryMapper<T> entryMapper ) |
| { |
| return searchFirst( |
| modelFactory.newSearchRequest( baseDn, filter, scope ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T searchFirst( String baseDn, String filter, SearchScope scope, |
| EntryMapper<T> entryMapper ) |
| { |
| return searchFirst( |
| modelFactory.newSearchRequest( baseDn, filter, scope ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T searchFirst( Dn baseDn, FilterBuilder filter, SearchScope scope, |
| EntryMapper<T> entryMapper ) |
| { |
| return searchFirst( |
| modelFactory.newSearchRequest( baseDn, filter, scope ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T searchFirst( Dn baseDn, String filter, SearchScope scope, |
| EntryMapper<T> entryMapper ) |
| { |
| return searchFirst( |
| modelFactory.newSearchRequest( baseDn, filter, scope ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T searchFirst( String baseDn, FilterBuilder filter, SearchScope scope, |
| String[] attributes, EntryMapper<T> entryMapper ) |
| { |
| return searchFirst( |
| modelFactory.newSearchRequest( baseDn, filter, scope, attributes ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T searchFirst( String baseDn, String filter, SearchScope scope, |
| String[] attributes, EntryMapper<T> entryMapper ) |
| { |
| return searchFirst( |
| modelFactory.newSearchRequest( baseDn, filter, scope, attributes ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T searchFirst( Dn baseDn, FilterBuilder filter, SearchScope scope, |
| String[] attributes, EntryMapper<T> entryMapper ) |
| { |
| return searchFirst( |
| modelFactory.newSearchRequest( baseDn, filter, scope, attributes ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T searchFirst( Dn baseDn, String filter, SearchScope scope, |
| String[] attributes, EntryMapper<T> entryMapper ) |
| { |
| return searchFirst( |
| modelFactory.newSearchRequest( baseDn, filter, scope, attributes ), |
| entryMapper ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T searchFirst( SearchRequest searchRequest, |
| EntryMapper<T> entryMapper ) |
| { |
| // in case the caller did not set size limit, we cache original value, |
| // set to 1, then set back to original value before returning... |
| long originalSizeLimit = searchRequest.getSizeLimit(); |
| try |
| { |
| searchRequest.setSizeLimit( 1 ); |
| List<T> entries = search( searchRequest, entryMapper ); |
| return entries.isEmpty() ? null : entries.get( 0 ); |
| } |
| finally |
| { |
| searchRequest.setSizeLimit( originalSizeLimit ); |
| } |
| } |
| |
| |
| /** |
| * Sets the <code>modelFactory</code> implementation for this facade. |
| * |
| * @param modelFactory The model factory implementation |
| */ |
| public void setModelFactory( ModelFactory modelFactory ) |
| { |
| this.modelFactory = modelFactory; |
| } |
| |
| |
| /** |
| * Sets the <code>passwordPolicyResponder</code> implementation for this |
| * facade. |
| * |
| * @param passwordPolicyResponder The password policy responder |
| * implementation |
| */ |
| public void setPasswordPolicyResponder( PasswordPolicyResponder passwordPolicyResponder ) |
| { |
| this.passwordPolicyResponder = passwordPolicyResponder; |
| } |
| } |