001/*
002 *   Licensed to the Apache Software Foundation (ASF) under one
003 *   or more contributor license agreements.  See the NOTICE file
004 *   distributed with this work for additional information
005 *   regarding copyright ownership.  The ASF licenses this file
006 *   to you under the Apache License, Version 2.0 (the
007 *   "License"); you may not use this file except in compliance
008 *   with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *   Unless required by applicable law or agreed to in writing,
013 *   software distributed under the License is distributed on an
014 *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *   KIND, either express or implied.  See the License for the
016 *   specific language governing permissions and limitations
017 *   under the License.
018 *
019 */
020package org.apache.directory.ldap.client.template;
021
022
023import org.apache.directory.api.ldap.codec.api.LdapApiService;
024import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
025import org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyDecorator;
026import org.apache.directory.api.ldap.model.exception.LdapException;
027import org.apache.directory.api.ldap.model.message.Control;
028import org.apache.directory.api.ldap.model.message.Response;
029import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
030import org.apache.directory.api.ldap.model.message.ResultResponse;
031import org.apache.directory.ldap.client.template.exception.PasswordException;
032
033
034/**
035 * A base, abstract, implementation of <code>PasswordPolicyResponder</code>.  
036 * Extend this class and override success(PasswordPolicy), 
037 * fail(ResultResponse, PasswordPolicy, ResultCodeEnum), or
038 * exception(LdapException).  If that does not offer enough
039 * flexibility, you must implement PasswordPolicyResponder yourself.
040 *
041 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
042 */
043public abstract class AbstractPasswordPolicyResponder implements PasswordPolicyResponder
044{
045    private final PasswordPolicyDecorator passwordPolicyRequestControl;
046
047
048    protected AbstractPasswordPolicyResponder( LdapApiService ldapApiService )
049    {
050        this.passwordPolicyRequestControl = new PasswordPolicyDecorator(
051            ldapApiService );
052    }
053    
054    
055    /**
056     * Translates an <code>LdapException</code> to a 
057     * <code>PasswordException</code> to be thrown when 
058     * {@link #process(PasswordPolicyOperation)} fails.
059     * 
060     * @param e The exception to set
061     * @return The created PasswordException
062     */
063    protected PasswordException exception( LdapException e )
064    {
065        return new PasswordException().setLdapException( e );
066    }
067    
068    
069    /**
070     * Returns an exception to be thrown in the case of a non SUCCESS 
071     * <code>resultCode</code>.
072     * 
073     * @param resultResponse The result response
074     * @param passwordPolicy The password policy in use
075     * @param resultCode The result
076     * @return The created PasswordException
077     */
078    protected PasswordException fail( ResultResponse resultResponse, 
079            PasswordPolicy passwordPolicy, ResultCodeEnum resultCode )
080    {
081        PasswordException exception = new PasswordException();
082        exception.setResultCode( resultCode );
083        if ( passwordPolicy != null
084            && passwordPolicy.getResponse() != null
085            && passwordPolicy.getResponse().getPasswordPolicyError() != null )
086        {
087            exception.setPasswordPolicyError( passwordPolicy.getResponse().getPasswordPolicyError() );
088        }
089        return exception;
090    }
091
092
093    private PasswordPolicy getPasswordPolicy( Response response )
094    {
095        Control control = response.getControls().get( passwordPolicyRequestControl.getOid() );
096        return control == null
097            ? null
098            : ( ( PasswordPolicyDecorator ) control ).getDecorated();
099    }
100
101
102    @Override
103    public final PasswordWarning process( PasswordPolicyOperation operation )
104        throws PasswordException
105    {
106        try
107        {
108            ResultResponse response = operation.process();
109            PasswordPolicy passwordPolicy = getPasswordPolicy( response );
110            ResultCodeEnum resultCode = response.getLdapResult().getResultCode();
111            if ( resultCode == ResultCodeEnum.SUCCESS )
112            {
113                return success( passwordPolicy );
114            }
115            else
116            {
117                throw fail( response, passwordPolicy, resultCode );
118            }
119        }
120        catch ( LdapException e )
121        {
122            throw new PasswordException().setLdapException( e );
123        }
124    }
125    
126    /**
127     * Returns a <code>PasswordWarning</code>, or <code>null</code> if no 
128     * warnings were present in the supplied <code>passwordPolicy</code>.
129     * 
130     * @param passwordPolicy The PasswordPolicy in use
131     * @return The created PasswordWarning
132     */
133    protected PasswordWarning success( PasswordPolicy passwordPolicy ) 
134    {
135        return passwordPolicy == null
136                ? null
137                : PasswordWarningImpl.newWarning( passwordPolicy );
138    }
139}