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     */
020    package org.apache.directory.shared.ldap.codec.controls.replication.syncRequestValue;
021    
022    import java.nio.ByteBuffer;
023    
024    import org.apache.directory.shared.asn1.ber.tlv.TLV;
025    import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
026    import org.apache.directory.shared.asn1.ber.tlv.Value;
027    import org.apache.directory.shared.asn1.codec.EncoderException;
028    import org.apache.directory.shared.i18n.I18n;
029    import org.apache.directory.shared.ldap.codec.controls.AbstractControl;
030    import org.apache.directory.shared.ldap.message.control.replication.SynchronizationModeEnum;
031    import org.apache.directory.shared.ldap.util.StringTools;
032    
033    /**
034     * A syncRequestValue object, as defined in RFC 4533
035     * 
036     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
037     * @version $Rev:$, $Date: 
038     */
039    public class SyncRequestValueControl  extends AbstractControl
040    {
041        /** This control OID */
042        public static final String CONTROL_OID = "1.3.6.1.4.1.4203.1.9.1.1";
043    
044        /** The synchronization type */
045        private SynchronizationModeEnum mode;
046        
047        /** The Sync cookie */
048        private byte[] cookie;
049        
050        /** The reloadHint flag */
051        private boolean reloadHint;
052        
053        /** The global length for this control */
054        private int syncRequestValueLength;
055        
056        public SyncRequestValueControl()
057        {
058            super( CONTROL_OID );
059    
060            decoder = new SyncRequestValueControlDecoder();
061        }
062    
063        /**
064         * @return the mode
065         */
066        public SynchronizationModeEnum getMode()
067        {
068            return mode;
069        }
070    
071        
072        /**
073         * @param syncMode the syncMode to set
074         */
075        public void setMode( SynchronizationModeEnum mode )
076        {
077            this.mode = mode;
078        }
079    
080        
081        /**
082         * @return the cookie
083         */
084        public byte[] getCookie()
085        {
086            return cookie;
087        }
088    
089        
090        /**
091         * @param cookie the cookie to set
092         */
093        public void setCookie( byte[] cookie )
094        {
095            this.cookie = cookie;
096        }
097    
098        
099        /**
100         * @return the reloadHint
101         */
102        public boolean isReloadHint()
103        {
104            return reloadHint;
105        }
106    
107        
108        /**
109         * @param reloadHint the reloadHint to set
110         */
111        public void setReloadHint( boolean reloadHint )
112        {
113            this.reloadHint = reloadHint;
114        }
115    
116        /**
117         * Compute the SyncRequestValue length.
118         * 
119         * SyncRequestValue :
120         * 0x30 L1
121         *  | 
122         *  +--> 0x0A 0x01 [0x00|0x01|0x02|0x03] (mode)
123         * [+--> 0x04 L2 abcd...                 (cookie)
124         *  +--> 0x01 0x01 [0x00|0xFF]           (reloadHint)
125         *   
126         */
127        public int computeLength()
128        {
129            // The mode length
130            syncRequestValueLength = 1 + 1 + 1;
131            
132            // The cookie length, if we have a cookie
133            if ( cookie != null )
134            {
135                syncRequestValueLength += 1 + TLV.getNbBytes( cookie.length ) + cookie.length;
136            }
137            
138            // The reloadHint length, default to false
139            if ( reloadHint )
140            {
141                syncRequestValueLength += 1 + 1 + 1;
142            }
143    
144            valueLength =  1 + TLV.getNbBytes( syncRequestValueLength ) + syncRequestValueLength;
145    
146            // Call the super class to compute the global control length
147            return super.computeLength( valueLength );
148        }
149        
150        
151        /**
152         * Encode the SyncRequestValue control
153         * 
154         * @param buffer The encoded sink
155         * @return A ByteBuffer that contains the encoded PDU
156         * @throws EncoderException If anything goes wrong.
157         */
158        public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
159        {
160            if ( buffer == null )
161            {
162                throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
163            }
164    
165            // Encode the Control envelop
166            super.encode( buffer );
167            
168            // Encode the OCTET_STRING tag
169            buffer.put( UniversalTag.OCTET_STRING_TAG );
170            buffer.put( TLV.getBytes( valueLength ) );
171    
172            // Encode the SEQ 
173            buffer.put( UniversalTag.SEQUENCE_TAG );
174            buffer.put( TLV.getBytes( syncRequestValueLength ) );
175    
176            // The mode
177            buffer.put(  UniversalTag.ENUMERATED_TAG );
178            buffer.put( (byte)0x01 );
179            buffer.put( Value.getBytes( mode.getValue() ) );
180    
181            // The cookie
182            if ( cookie != null )
183            {
184                Value.encode( buffer, cookie );
185            }
186            
187            // The reloadHint if not false
188            if ( reloadHint )
189            {
190                Value.encode( buffer, reloadHint );
191            }
192            
193            return buffer;
194        }
195        
196        
197        /**
198         * {@inheritDoc}
199         */
200        public byte[] getValue()
201        {
202            if ( value == null )
203            {
204                try
205                { 
206                    computeLength();
207                    ByteBuffer buffer = ByteBuffer.allocate( valueLength );
208                    
209                    // Encode the SEQ 
210                    buffer.put( UniversalTag.SEQUENCE_TAG );
211                    buffer.put( TLV.getBytes( syncRequestValueLength ) );
212    
213                    // The mode
214                    buffer.put(  UniversalTag.ENUMERATED_TAG );
215                    buffer.put( (byte)0x01 );
216                    buffer.put( Value.getBytes( mode.getValue() ) );
217    
218                    // The cookie
219                    if ( cookie != null )
220                    {
221                        Value.encode( buffer, cookie );
222                    }
223                    
224                    // The reloadHint if not false
225                    if ( reloadHint )
226                    {
227                        Value.encode( buffer, reloadHint );
228                    }
229    
230                    value = buffer.array();
231                }
232                catch ( Exception e )
233                {
234                    return null;
235                }
236            }
237            
238            return value;
239        }
240    
241    
242        /**
243         * @see Object#toString()
244         */
245        public String toString()
246        {
247            StringBuilder sb = new StringBuilder();
248            
249            sb.append( "    SyncRequestValue control :\n" );
250            sb.append( "        oid : " ).append( getOid() ).append( '\n' );
251            sb.append( "        critical : " ).append( isCritical() ).append( '\n' );
252            sb.append( "        mode              : '" ).append( mode ).append( "'\n" );
253            sb.append( "        cookie            : '" ).
254                append( StringTools.dumpBytes( cookie ) ).append( "'\n" );
255            sb.append( "        refreshAndPersist : '" ).append( reloadHint ).append( "'\n" );
256    
257            return sb.toString();
258        }
259    }