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    public PasswordModifyFactory( LdapApiService codec )
055    {
056        this.codec = codec;
057    }
058
059
060    /**
061     * {@inheritDoc}
062     */
063    public String getOid()
064    {
065        return PasswordModifyRequest.EXTENSION_OID;
066    }
067
068
069    /**
070     * {@inheritDoc}
071     */
072    public PasswordModifyResponse newResponse( byte[] encodedValue ) throws DecoderException
073    {
074        PasswordModifyResponseDecorator response = new PasswordModifyResponseDecorator( codec,
075            new PasswordModifyResponseImpl() );
076        response.setResponseValue( encodedValue );
077        return response;
078    }
079
080
081    /**
082     * {@inheritDoc}
083     */
084    public PasswordModifyRequest newRequest( byte[] value )
085    {
086        PasswordModifyRequestDecorator req = new PasswordModifyRequestDecorator( codec, new PasswordModifyRequestImpl() );
087
088        if ( value != null )
089        {
090            req.setRequestValue( value );
091        }
092
093        return req;
094    }
095
096
097    /**
098     * {@inheritDoc}
099     */
100    public PasswordModifyRequestDecorator decorate( ExtendedRequest modelRequest )
101    {
102        if ( modelRequest instanceof PasswordModifyRequestDecorator )
103        {
104            return ( PasswordModifyRequestDecorator ) modelRequest;
105        }
106
107        return new PasswordModifyRequestDecorator( codec, ( PasswordModifyRequest ) modelRequest );
108    }
109
110
111    /**
112     * {@inheritDoc}
113     */
114    public PasswordModifyResponseDecorator decorate( ExtendedResponse decoratedResponse )
115    {
116        if ( decoratedResponse instanceof PasswordModifyResponseDecorator )
117        {
118            return ( PasswordModifyResponseDecorator ) decoratedResponse;
119        }
120
121        if ( decoratedResponse instanceof PasswordModifyResponse )
122        {
123            return new PasswordModifyResponseDecorator( codec, ( PasswordModifyResponse ) decoratedResponse );
124        }
125
126        // It's an opaque extended operation
127        @SuppressWarnings("unchecked")
128        ExtendedResponseDecorator<ExtendedResponse> response = ( ExtendedResponseDecorator<ExtendedResponse> ) decoratedResponse;
129
130        // Decode the response, as it's an opaque operation
131        Asn1Decoder decoder = new Asn1Decoder();
132
133        byte[] value = response.getResponseValue();
134        PasswordModifyResponseContainer container = new PasswordModifyResponseContainer();
135        
136        PasswordModifyResponse pwdModifyResponse = null;
137        
138        if ( value != null )
139        {
140            ByteBuffer buffer = ByteBuffer.wrap( value );
141    
142            try
143            {
144                decoder.decode( buffer, container );
145                pwdModifyResponse = container.getPwdModifyResponse();
146
147                // Now, update the created response with what we got from the extendedResponse
148                pwdModifyResponse.getLdapResult().setResultCode( response.getLdapResult().getResultCode() );
149                pwdModifyResponse.getLdapResult().setDiagnosticMessage( response.getLdapResult().getDiagnosticMessage() );
150                pwdModifyResponse.getLdapResult().setMatchedDn( response.getLdapResult().getMatchedDn() );
151                pwdModifyResponse.getLdapResult().setReferral( response.getLdapResult().getReferral() );
152            }
153            catch ( DecoderException de )
154            {
155                StringWriter sw = new StringWriter();
156                de.printStackTrace( new PrintWriter( sw ) );
157                String stackTrace = sw.toString();
158    
159                // Error while decoding the value. 
160                pwdModifyResponse = new PasswordModifyResponseImpl(
161                    decoratedResponse.getMessageId(),
162                    ResultCodeEnum.OPERATIONS_ERROR,
163                    stackTrace );
164            }
165        }
166        else
167        {
168            pwdModifyResponse = new PasswordModifyResponseImpl();
169    
170            // Now, update the created response with what we got from the extendedResponse
171            pwdModifyResponse.getLdapResult().setResultCode( response.getLdapResult().getResultCode() );
172            pwdModifyResponse.getLdapResult().setDiagnosticMessage( response.getLdapResult().getDiagnosticMessage() );
173            pwdModifyResponse.getLdapResult().setMatchedDn( response.getLdapResult().getMatchedDn() );
174            pwdModifyResponse.getLdapResult().setReferral( response.getLdapResult().getReferral() );
175        }
176
177        PasswordModifyResponseDecorator decorated = new PasswordModifyResponseDecorator( codec, pwdModifyResponse );
178
179        Control ppolicyControl = response.getControl( PasswordPolicy.OID );
180
181        if ( ppolicyControl != null )
182        {
183            decorated.addControl( ppolicyControl );
184        }
185
186        return decorated;
187    }
188}