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.codec.controls.search.persistentSearch; 021 022 023import java.nio.ByteBuffer; 024 025import org.apache.directory.api.asn1.Asn1Object; 026import org.apache.directory.api.asn1.DecoderException; 027import org.apache.directory.api.asn1.EncoderException; 028import org.apache.directory.api.asn1.ber.Asn1Decoder; 029import org.apache.directory.api.asn1.ber.tlv.BerValue; 030import org.apache.directory.api.asn1.ber.tlv.TLV; 031import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 032import org.apache.directory.api.i18n.I18n; 033import org.apache.directory.api.ldap.codec.api.ControlDecorator; 034import org.apache.directory.api.ldap.codec.api.LdapApiService; 035import org.apache.directory.api.ldap.model.message.controls.ChangeType; 036import org.apache.directory.api.ldap.model.message.controls.PersistentSearch; 037import org.apache.directory.api.ldap.model.message.controls.PersistentSearchImpl; 038 039 040/** 041 * A persistence search object 042 * 043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 044 */ 045public class PersistentSearchDecorator extends ControlDecorator<PersistentSearch> implements PersistentSearch 046{ 047 /** A temporary storage for a psearch length */ 048 private int psearchSeqLength; 049 050 /** An instance of this decoder */ 051 private static final Asn1Decoder DECODER = new Asn1Decoder(); 052 053 054 /** 055 * Default constructor creates a PersistentSearch Control automatically 056 * wrapped in a decorator object inside this container. 057 * 058 * @param codec The LDAP service instance 059 */ 060 public PersistentSearchDecorator( LdapApiService codec ) 061 { 062 this( codec, new PersistentSearchImpl() ); 063 } 064 065 066 /** 067 * Creates a PersistentSearch Control wrapping a supplied PersistentSearch 068 * Control. 069 * 070 * @param codec The LDAP service instance 071 * @param control The PersistentSearch Control to wrap. 072 */ 073 public PersistentSearchDecorator( LdapApiService codec, PersistentSearch control ) 074 { 075 super( codec, control ); 076 } 077 078 079 /** 080 * Compute the PagedSearchControl length, which is the sum 081 * of the control length and the value length. 082 * 083 * <pre> 084 * PersistentSearchDecorator value length : 085 * 086 * 0x30 L1 087 * | 088 * +--> 0x02 0x0(1-4) [0..2^31-1] (changeTypes) 089 * +--> 0x01 0x01 [0x00 | 0xFF] (changeOnly) 090 * +--> 0x01 0x01 [0x00 | 0xFF] (returnRCs) 091 * </pre> 092 * 093 * @return the control length. 094 */ 095 @Override 096 public int computeLength() 097 { 098 int changeTypesLength = 1 + 1 + BerValue.getNbBytes( getChangeTypes() ); 099 int changesOnlyLength = 1 + 1 + 1; 100 int returnRCsLength = 1 + 1 + 1; 101 102 psearchSeqLength = changeTypesLength + changesOnlyLength + returnRCsLength; 103 104 return 1 + TLV.getNbBytes( psearchSeqLength ) + psearchSeqLength; 105 } 106 107 108 /** 109 * Encodes the persistent search control. 110 * 111 * @param buffer The encoded sink 112 * @return A ByteBuffer that contains the encoded PDU 113 * @throws EncoderException If anything goes wrong. 114 */ 115 @Override 116 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 117 { 118 if ( buffer == null ) 119 { 120 throw new EncoderException( I18n.err( I18n.ERR_04023 ) ); 121 } 122 123 // Now encode the PagedSearch specific part 124 buffer.put( UniversalTag.SEQUENCE.getValue() ); 125 buffer.put( TLV.getBytes( psearchSeqLength ) ); 126 127 BerValue.encode( buffer, getChangeTypes() ); 128 BerValue.encode( buffer, isChangesOnly() ); 129 BerValue.encode( buffer, isReturnECs() ); 130 131 return buffer; 132 } 133 134 135 /** 136 * {@inheritDoc} 137 */ 138 @Override 139 public byte[] getValue() 140 { 141 if ( value == null ) 142 { 143 try 144 { 145 valueLength = computeLength(); 146 ByteBuffer buffer = ByteBuffer.allocate( valueLength ); 147 148 // Now encode the PagedSearch specific part 149 buffer.put( UniversalTag.SEQUENCE.getValue() ); 150 buffer.put( TLV.getBytes( psearchSeqLength ) ); 151 152 BerValue.encode( buffer, getChangeTypes() ); 153 BerValue.encode( buffer, isChangesOnly() ); 154 BerValue.encode( buffer, isReturnECs() ); 155 156 value = buffer.array(); 157 } 158 catch ( EncoderException ee ) 159 { 160 return null; 161 } 162 } 163 164 return value; 165 } 166 167 168 private PersistentSearch getPersistentSearch() 169 { 170 return getDecorated(); 171 } 172 173 174 /** 175 * {@inheritDoc} 176 */ 177 @Override 178 public void setChangesOnly( boolean changesOnly ) 179 { 180 getPersistentSearch().setChangesOnly( changesOnly ); 181 } 182 183 184 /** 185 * {@inheritDoc} 186 */ 187 @Override 188 public boolean isChangesOnly() 189 { 190 return getPersistentSearch().isChangesOnly(); 191 } 192 193 194 /** 195 * {@inheritDoc} 196 */ 197 @Override 198 public void setReturnECs( boolean returnECs ) 199 { 200 getPersistentSearch().setReturnECs( returnECs ); 201 } 202 203 204 /** 205 * {@inheritDoc} 206 */ 207 @Override 208 public boolean isReturnECs() 209 { 210 return getPersistentSearch().isReturnECs(); 211 } 212 213 214 /** 215 * {@inheritDoc} 216 */ 217 @Override 218 public void setChangeTypes( int changeTypes ) 219 { 220 getPersistentSearch().setChangeTypes( changeTypes ); 221 } 222 223 224 /** 225 * {@inheritDoc} 226 */ 227 @Override 228 public int getChangeTypes() 229 { 230 return getPersistentSearch().getChangeTypes(); 231 } 232 233 234 /** 235 * {@inheritDoc} 236 */ 237 @Override 238 public boolean isNotificationEnabled( ChangeType changeType ) 239 { 240 return getPersistentSearch().isNotificationEnabled( changeType ); 241 } 242 243 244 /** 245 * {@inheritDoc} 246 */ 247 @Override 248 public void enableNotification( ChangeType changeType ) 249 { 250 getPersistentSearch().enableNotification( changeType ); 251 } 252 253 254 /** 255 * {@inheritDoc} 256 */ 257 @Override 258 public void disableNotification( ChangeType changeType ) 259 { 260 getPersistentSearch().disableNotification( changeType ); 261 } 262 263 264 /** 265 * {@inheritDoc} 266 */ 267 @Override 268 public Asn1Object decode( byte[] controlBytes ) throws DecoderException 269 { 270 ByteBuffer bb = ByteBuffer.wrap( controlBytes ); 271 PersistentSearchContainer container = new PersistentSearchContainer( getCodecService(), this ); 272 DECODER.decode( bb, container ); 273 return this; 274 } 275}