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