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.api.ldap.extras.extended.ads_impl.pwdModify;
021
022
023import java.io.PrintWriter;
024import java.io.StringWriter;
025import java.nio.ByteBuffer;
026
027import org.apache.directory.api.asn1.DecoderException;
028import org.apache.directory.api.asn1.ber.Asn1Decoder;
029import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
030import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
031import org.apache.directory.api.ldap.codec.api.LdapApiService;
032import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
033import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequest;
034import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequestImpl;
035import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponse;
036import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponseImpl;
037import org.apache.directory.api.ldap.model.message.Control;
038import org.apache.directory.api.ldap.model.message.ExtendedRequest;
039import org.apache.directory.api.ldap.model.message.ExtendedResponse;
040import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
041
042
043/**
044 * An {@link ExtendedOperationFactory} for creating PwdModify extended request response 
045 * pairs.
046 *
047 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
048 */
049public class PasswordModifyFactory implements ExtendedOperationFactory
050{
051    private LdapApiService codec;
052
053
054    /**
055     * Creates a new instance of PasswordModifyFactory.
056     *
057     * @param codec The codec for this factory.
058     */
059    public PasswordModifyFactory( LdapApiService codec )
060    {
061        this.codec = codec;
062    }
063
064
065    /**
066     * {@inheritDoc}
067     */
068    @Override
069    public String getOid()
070    {
071        return PasswordModifyRequest.EXTENSION_OID;
072    }
073
074
075    /**
076     * {@inheritDoc}
077     */
078    @Override
079    public PasswordModifyResponse newResponse( byte[] encodedValue ) throws DecoderException
080    {
081        PasswordModifyResponseDecorator response = new PasswordModifyResponseDecorator( codec,
082            new PasswordModifyResponseImpl() );
083        response.setResponseValue( encodedValue );
084        return response;
085    }
086
087
088    /**
089     * {@inheritDoc}
090     */
091    @Override
092    public PasswordModifyRequest newRequest( byte[] value )
093    {
094        PasswordModifyRequestDecorator req = new PasswordModifyRequestDecorator( codec, new PasswordModifyRequestImpl() );
095
096        if ( value != null )
097        {
098            req.setRequestValue( value );
099        }
100
101        return req;
102    }
103
104
105    /**
106     * {@inheritDoc}
107     */
108    @Override
109    public PasswordModifyRequestDecorator decorate( ExtendedRequest modelRequest )
110    {
111        if ( modelRequest instanceof PasswordModifyRequestDecorator )
112        {
113            return ( PasswordModifyRequestDecorator ) modelRequest;
114        }
115
116        return new PasswordModifyRequestDecorator( codec, ( PasswordModifyRequest ) modelRequest );
117    }
118
119
120    /**
121     * {@inheritDoc}
122     */
123    @Override
124public PasswordModifyResponseDecorator decorate( ExtendedResponse decoratedResponse )
125    {
126        if ( decoratedResponse instanceof PasswordModifyResponseDecorator )
127        {
128            return ( PasswordModifyResponseDecorator ) decoratedResponse;
129        }
130
131        if ( decoratedResponse instanceof PasswordModifyResponse )
132        {
133            return new PasswordModifyResponseDecorator( codec, ( PasswordModifyResponse ) decoratedResponse );
134        }
135
136        // It's an opaque extended operation
137        @SuppressWarnings("unchecked")
138        ExtendedResponseDecorator<ExtendedResponse> response = ( ExtendedResponseDecorator<ExtendedResponse> ) decoratedResponse;
139
140        // Decode the response, as it's an opaque operation
141        Asn1Decoder decoder = new Asn1Decoder();
142
143        byte[] value = response.getResponseValue();
144        PasswordModifyResponseContainer container = new PasswordModifyResponseContainer();
145        
146        PasswordModifyResponse pwdModifyResponse;
147        
148        if ( value != null )
149        {
150            ByteBuffer buffer = ByteBuffer.wrap( value );
151    
152            try
153            {
154                decoder.decode( buffer, container );
155                pwdModifyResponse = container.getPwdModifyResponse();
156
157                // Now, update the created response with what we got from the extendedResponse
158                pwdModifyResponse.getLdapResult().setResultCode( response.getLdapResult().getResultCode() );
159                pwdModifyResponse.getLdapResult().setDiagnosticMessage( response.getLdapResult().getDiagnosticMessage() );
160                pwdModifyResponse.getLdapResult().setMatchedDn( response.getLdapResult().getMatchedDn() );
161                pwdModifyResponse.getLdapResult().setReferral( response.getLdapResult().getReferral() );
162            }
163            catch ( DecoderException de )
164            {
165                StringWriter sw = new StringWriter();
166                de.printStackTrace( new PrintWriter( sw ) );
167                String stackTrace = sw.toString();
168    
169                // Error while decoding the value. 
170                pwdModifyResponse = new PasswordModifyResponseImpl(
171                    decoratedResponse.getMessageId(),
172                    ResultCodeEnum.OPERATIONS_ERROR,
173                    stackTrace );
174            }
175        }
176        else
177        {
178            pwdModifyResponse = new PasswordModifyResponseImpl();
179    
180            // Now, update the created response with what we got from the extendedResponse
181            pwdModifyResponse.getLdapResult().setResultCode( response.getLdapResult().getResultCode() );
182            pwdModifyResponse.getLdapResult().setDiagnosticMessage( response.getLdapResult().getDiagnosticMessage() );
183            pwdModifyResponse.getLdapResult().setMatchedDn( response.getLdapResult().getMatchedDn() );
184            pwdModifyResponse.getLdapResult().setReferral( response.getLdapResult().getReferral() );
185        }
186
187        PasswordModifyResponseDecorator decorated = new PasswordModifyResponseDecorator( codec, pwdModifyResponse );
188
189        Control ppolicyControl = response.getControl( PasswordPolicy.OID );
190
191        if ( ppolicyControl != null )
192        {
193            decorated.addControl( ppolicyControl );
194        }
195
196        return decorated;
197    }
198}