View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.codec.controls.search.persistentSearch;
21  
22  
23  import java.nio.ByteBuffer;
24  
25  import org.apache.directory.api.asn1.Asn1Object;
26  import org.apache.directory.api.asn1.DecoderException;
27  import org.apache.directory.api.asn1.EncoderException;
28  import org.apache.directory.api.asn1.ber.Asn1Decoder;
29  import org.apache.directory.api.asn1.ber.tlv.BerValue;
30  import org.apache.directory.api.asn1.ber.tlv.TLV;
31  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
32  import org.apache.directory.api.i18n.I18n;
33  import org.apache.directory.api.ldap.codec.api.ControlDecorator;
34  import org.apache.directory.api.ldap.codec.api.LdapApiService;
35  import org.apache.directory.api.ldap.model.message.controls.ChangeType;
36  import org.apache.directory.api.ldap.model.message.controls.PersistentSearch;
37  import org.apache.directory.api.ldap.model.message.controls.PersistentSearchImpl;
38  
39  
40  /**
41   * A persistence search object
42   * 
43   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
44   */
45  public class PersistentSearchDecorator extends ControlDecorator<PersistentSearch> implements PersistentSearch
46  {
47      /** A temporary storage for a psearch length */
48      private int psearchSeqLength;
49  
50      /** An instance of this decoder */
51      private static final Asn1Decoder decoder = new Asn1Decoder();
52  
53  
54      /**
55       * Default constructor creates a PersistentSearch Control automatically
56       * wrapped in a decorator object inside this container.
57       */
58      public PersistentSearchDecorator( LdapApiService codec )
59      {
60          this( codec, new PersistentSearchImpl() );
61      }
62  
63  
64      /**
65       * Creates a PersistentSearch Control wrapping a supplied PersistentSearch
66       * Control.
67       *
68       * @param control The PersistentSearch Control to wrap.
69       */
70      public PersistentSearchDecorator( LdapApiService codec, PersistentSearch control )
71      {
72          super( codec, control );
73      }
74  
75  
76      /**
77       * Compute the PagedSearchControl length, which is the sum
78       * of the control length and the value length.
79       * 
80       * <pre>
81       * PersistentSearchDecorator value length :
82       * 
83       * 0x30 L1 
84       *   | 
85       *   +--> 0x02 0x0(1-4) [0..2^31-1] (changeTypes) 
86       *   +--> 0x01 0x01 [0x00 | 0xFF] (changeOnly) 
87       *   +--> 0x01 0x01 [0x00 | 0xFF] (returnRCs)
88       * </pre> 
89       */
90      public int computeLength()
91      {
92          int changeTypesLength = 1 + 1 + BerValue.getNbBytes( getChangeTypes() );
93          int changesOnlyLength = 1 + 1 + 1;
94          int returnRCsLength = 1 + 1 + 1;
95  
96          psearchSeqLength = changeTypesLength + changesOnlyLength + returnRCsLength;
97          int valueLength = 1 + TLV.getNbBytes( psearchSeqLength ) + psearchSeqLength;
98  
99          return valueLength;
100     }
101 
102 
103     /**
104      * Encodes the persistent search control.
105      * 
106      * @param buffer The encoded sink
107      * @return A ByteBuffer that contains the encoded PDU
108      * @throws EncoderException If anything goes wrong.
109      */
110     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
111     {
112         if ( buffer == null )
113         {
114             throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
115         }
116 
117         // Now encode the PagedSearch specific part
118         buffer.put( UniversalTag.SEQUENCE.getValue() );
119         buffer.put( TLV.getBytes( psearchSeqLength ) );
120 
121         BerValue.encode( buffer, getChangeTypes() );
122         BerValue.encode( buffer, isChangesOnly() );
123         BerValue.encode( buffer, isReturnECs() );
124 
125         return buffer;
126     }
127 
128 
129     /**
130      * {@inheritDoc}
131      */
132     public byte[] getValue()
133     {
134         if ( value == null )
135         {
136             try
137             {
138                 computeLength();
139                 ByteBuffer buffer = ByteBuffer.allocate( valueLength );
140 
141                 // Now encode the PagedSearch specific part
142                 buffer.put( UniversalTag.SEQUENCE.getValue() );
143                 buffer.put( TLV.getBytes( psearchSeqLength ) );
144 
145                 BerValue.encode( buffer, getChangeTypes() );
146                 BerValue.encode( buffer, isChangesOnly() );
147                 BerValue.encode( buffer, isReturnECs() );
148 
149                 value = buffer.array();
150             }
151             catch ( Exception e )
152             {
153                 return null;
154             }
155         }
156 
157         return value;
158     }
159 
160 
161     private PersistentSearch getPersistentSearch()
162     {
163         return ( PersistentSearch ) getDecorated();
164     }
165 
166 
167     public void setChangesOnly( boolean changesOnly )
168     {
169         getPersistentSearch().setChangesOnly( changesOnly );
170     }
171 
172 
173     public boolean isChangesOnly()
174     {
175         return getPersistentSearch().isChangesOnly();
176     }
177 
178 
179     public void setReturnECs( boolean returnECs )
180     {
181         getPersistentSearch().setReturnECs( returnECs );
182     }
183 
184 
185     public boolean isReturnECs()
186     {
187         return getPersistentSearch().isReturnECs();
188     }
189 
190 
191     public void setChangeTypes( int changeTypes )
192     {
193         getPersistentSearch().setChangeTypes( changeTypes );
194     }
195 
196 
197     public int getChangeTypes()
198     {
199         return getPersistentSearch().getChangeTypes();
200     }
201 
202 
203     public boolean isNotificationEnabled( ChangeType changeType )
204     {
205         return getPersistentSearch().isNotificationEnabled( changeType );
206     }
207 
208 
209     public void enableNotification( ChangeType changeType )
210     {
211         getPersistentSearch().enableNotification( changeType );
212     }
213 
214 
215     /**
216      * {@inheritDoc}
217      */
218     public Asn1Object decode( byte[] controlBytes ) throws DecoderException
219     {
220         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
221         PersistentSearchContainer container = new PersistentSearchContainer( getCodecService(), this );
222         decoder.decode( bb, container );
223         return this;
224     }
225 }