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 public PersistentSearchDecorator( LdapApiService codec ) 059 { 060 this( codec, new PersistentSearchImpl() ); 061 } 062 063 064 /** 065 * Creates a PersistentSearch Control wrapping a supplied PersistentSearch 066 * Control. 067 * 068 * @param control The PersistentSearch Control to wrap. 069 */ 070 public PersistentSearchDecorator( LdapApiService codec, PersistentSearch control ) 071 { 072 super( codec, control ); 073 } 074 075 076 /** 077 * Compute the PagedSearchControl length, which is the sum 078 * of the control length and the value length. 079 * 080 * <pre> 081 * PersistentSearchDecorator value length : 082 * 083 * 0x30 L1 084 * | 085 * +--> 0x02 0x0(1-4) [0..2^31-1] (changeTypes) 086 * +--> 0x01 0x01 [0x00 | 0xFF] (changeOnly) 087 * +--> 0x01 0x01 [0x00 | 0xFF] (returnRCs) 088 * </pre> 089 */ 090 public int computeLength() 091 { 092 int changeTypesLength = 1 + 1 + BerValue.getNbBytes( getChangeTypes() ); 093 int changesOnlyLength = 1 + 1 + 1; 094 int returnRCsLength = 1 + 1 + 1; 095 096 psearchSeqLength = changeTypesLength + changesOnlyLength + returnRCsLength; 097 int valueLength = 1 + TLV.getNbBytes( psearchSeqLength ) + psearchSeqLength; 098 099 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}