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