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.controls.ad_impl;
021
022import java.util.Set;
023
024import org.apache.directory.api.asn1.DecoderException;
025import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
026import org.apache.directory.api.asn1.ber.grammar.Grammar;
027import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
028import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
029import org.apache.directory.api.asn1.ber.tlv.BerValue;
030import org.apache.directory.api.asn1.ber.tlv.IntegerDecoder;
031import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
032import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
033import org.apache.directory.api.i18n.I18n;
034import org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncResponseFlag;
035import org.apache.directory.api.util.Strings;
036import org.slf4j.Logger;
037import org.slf4j.LoggerFactory;
038
039
040/**
041 *
042 * Implementation of AdDirSync Response Control. All the actions are declared in
043 * this class. As it is a singleton, these declaration are only done once.
044 *
045 *  The decoded grammar is as follows :
046 *
047 *  <pre>
048 * realReplControlValue ::= SEQUENCE {
049 *     flag                  integer
050 *     maxReturnLength       integer
051 *     cookie                OCTET STRING
052 * }
053 * </pre>
054 *
055 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
056 */
057public final class AdDirSyncResponseGrammar extends AbstractGrammar<AdDirSyncResponseContainer>
058{
059
060    /** the logger */
061    private static final Logger LOG = LoggerFactory.getLogger( AdDirSyncResponseGrammar.class );
062
063    /** AdDirSyncResponseControlGrammar singleton instance */
064    private static final AdDirSyncResponseGrammar INSTANCE = new AdDirSyncResponseGrammar();
065
066
067    /**
068     *
069     * Creates a new instance of AdDirSyncResponseControlGrammar.
070     *
071     */
072    @SuppressWarnings("unchecked")
073    private AdDirSyncResponseGrammar()
074    {
075        setName( AdDirSyncResponseGrammar.class.getName() );
076
077        super.transitions = new GrammarTransition[AdDirSyncResponseStatesEnum.LAST_AD_DIR_SYNC_RESPONSE_STATE.ordinal()][256];
078
079        /**
080         * Transition from initial state to AdDirSyncResponse sequence
081         * AdDirSync ::= SEQUENCE {
082         *     ...
083         *
084         * Initialize the adDirSyncResponse object
085         */
086        super.transitions[AdDirSyncResponseStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
087            new GrammarTransition<AdDirSyncResponseContainer>(
088            AdDirSyncResponseStatesEnum.START_STATE, AdDirSyncResponseStatesEnum.AD_DIR_SYNC_RESPONSE_SEQUENCE_STATE,
089            UniversalTag.SEQUENCE.getValue(),
090            new GrammarAction<AdDirSyncResponseContainer>( "Initialization" )
091            {
092                @Override
093                public void action( AdDirSyncResponseContainer container ) throws DecoderException
094                {
095                }
096            } );
097
098
099        /**
100         * transition from start to flag
101         * realReplControlValue ::= SEQUENCE {
102         *     flag            integer
103         *    ....
104         * }
105         */
106        super.transitions[AdDirSyncResponseStatesEnum.AD_DIR_SYNC_RESPONSE_SEQUENCE_STATE.ordinal()][UniversalTag.INTEGER
107            .getValue()] =
108            new GrammarTransition<AdDirSyncResponseContainer>( AdDirSyncResponseStatesEnum.AD_DIR_SYNC_RESPONSE_SEQUENCE_STATE,
109                AdDirSyncResponseStatesEnum.FLAG_STATE, UniversalTag.INTEGER.getValue(),
110                new GrammarAction<AdDirSyncResponseContainer>( "Set AdDirSyncResponseControl flag" )
111                {
112                    @Override
113                    public void action( AdDirSyncResponseContainer container ) throws DecoderException
114                    {
115                        BerValue value = container.getCurrentTLV().getValue();
116
117                        try
118                        {
119                            int flagValue = IntegerDecoder.parse( value );
120
121                            Set<AdDirSyncResponseFlag> flags = AdDirSyncResponseFlag.getFlags( flagValue );
122
123                            if ( flags == null )
124                            {
125                                String msg = I18n.err( I18n.ERR_08104_AD_DIR_SYNC_FLAG_DECODING_FAILURE, flagValue );
126                                LOG.error( msg );
127                                throw new DecoderException( msg );
128                            }
129
130                            if ( LOG.isDebugEnabled() )
131                            {
132                                LOG.debug( I18n.msg( I18n.MSG_08101_FLAGS, flags.toString() ) );
133                            }
134
135                            container.getAdDirSyncResponseControl().setFlags( flags );
136                        }
137                        catch ( IntegerDecoderException ide )
138                        {
139                            String msg = I18n.err( I18n.ERR_08105_AD_DIR_SYNC_FLAG_DECODING_ERROR, ide.getMessage() );
140                            LOG.error( msg, ide );
141                            throw new DecoderException( msg, ide );
142                        }
143                    }
144                } );
145
146
147        /**
148         * transition from flag to maxReturnLength
149         * realReplControlValue ::= SEQUENCE {
150         *     flag                    integer
151         *     maxReturnLength         integer
152         *    ....
153         * }
154         */
155        super.transitions[AdDirSyncResponseStatesEnum.FLAG_STATE.ordinal()][UniversalTag.INTEGER
156            .getValue()] =
157            new GrammarTransition<AdDirSyncResponseContainer>( AdDirSyncResponseStatesEnum.FLAG_STATE,
158                AdDirSyncResponseStatesEnum.MAX_RETURN_LENGTH_STATE, UniversalTag.INTEGER.getValue(),
159                new GrammarAction<AdDirSyncResponseContainer>( "Set AdDirSyncResponseControl maxReturnLength" )
160                {
161                    @Override
162                    public void action( AdDirSyncResponseContainer container ) throws DecoderException
163                    {
164                        BerValue value = container.getCurrentTLV().getValue();
165
166                        try
167                        {
168                            int maxReturnLength = IntegerDecoder.parse( value );
169
170                            if ( LOG.isDebugEnabled() )
171                            {
172                                LOG.debug( I18n.msg( I18n.MSG_08102_MAX_RETURN_LENGTH, maxReturnLength ) );
173                            }
174
175                            container.getAdDirSyncResponseControl().setMaxReturnLength( maxReturnLength );
176                        }
177                        catch ( IntegerDecoderException ide )
178                        {
179                            String msg = I18n.err( I18n.ERR_08106_AD_DIR_SYNC_MAX_RETURN_LENGTH_DECODING_ERROR, ide.getMessage() );
180                            LOG.error( msg, ide );
181                            throw new DecoderException( msg, ide );
182                        }
183                    }
184                } );
185
186
187        /**
188         * transition from maxReturnLength to cookie
189         *     ...
190         *     maxReturnLength         integer
191         *     cookie                  OCTET STRING
192         * }
193         */
194        super.transitions[AdDirSyncResponseStatesEnum.MAX_RETURN_LENGTH_STATE.ordinal()][UniversalTag.OCTET_STRING
195            .getValue()] =
196            new GrammarTransition<AdDirSyncResponseContainer>( AdDirSyncResponseStatesEnum.MAX_RETURN_LENGTH_STATE,
197                AdDirSyncResponseStatesEnum.COOKIE_STATE, UniversalTag.OCTET_STRING.getValue(),
198                new GrammarAction<AdDirSyncResponseContainer>( "Set AdDirSyncResponseControl cookie" )
199                {
200                    @Override
201                    public void action( AdDirSyncResponseContainer container )
202                    {
203                        BerValue value = container.getCurrentTLV().getValue();
204
205                        byte[] cookie = value.getData();
206
207                        if ( LOG.isDebugEnabled() )
208                        {
209                            LOG.debug( I18n.msg( I18n.MSG_08000_COOKIE, Strings.dumpBytes( cookie ) ) );
210                        }
211
212                        container.getAdDirSyncResponseControl().setCookie( cookie );
213
214                        container.setGrammarEndAllowed( true );
215                    }
216                } );
217    }
218
219
220    /**
221     * @return the singleton instance of the AdDirSyncControlGrammar
222     */
223    public static Grammar<AdDirSyncResponseContainer> getInstance()
224    {
225        return INSTANCE;
226    }
227}