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.extras.controls.syncrepl_impl; 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.extras.controls.SynchronizationModeEnum; 036import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncRequestValue; 037import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncRequestValueImpl; 038import org.apache.directory.api.util.Strings; 039 040 041/** 042 * A syncRequestValue object, as defined in RFC 4533 043 * 044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 045 */ 046public class SyncRequestValueDecorator extends ControlDecorator<SyncRequestValue> implements SyncRequestValue 047{ 048 /** The global length for this control */ 049 private int syncRequestValueLength; 050 051 /** An instance of this decoder */ 052 private static final Asn1Decoder DECODER = new Asn1Decoder(); 053 054 055 /** 056 * Create a new SyncRequestValueDecorator instance 057 * 058 * @param codec The LDAP API service to use 059 */ 060 public SyncRequestValueDecorator( LdapApiService codec ) 061 { 062 super( codec, new SyncRequestValueImpl() ); 063 } 064 065 066 /** 067 * Create a new SyncRequestValueDecorator instance 068 * 069 * @param codec The LDAP API service to use 070 * @param control The decorated SyncRequestValue control 071 */ 072 public SyncRequestValueDecorator( LdapApiService codec, SyncRequestValue control ) 073 { 074 super( codec, control ); 075 } 076 077 078 /** 079 * {@inheritDoc} 080 */ 081 @Override 082 public SynchronizationModeEnum getMode() 083 { 084 return getDecorated().getMode(); 085 } 086 087 088 /** 089 * {@inheritDoc} 090 */ 091 @Override 092 public void setMode( SynchronizationModeEnum mode ) 093 { 094 getDecorated().setMode( mode ); 095 } 096 097 098 /** 099 * {@inheritDoc} 100 */ 101 @Override 102 public byte[] getCookie() 103 { 104 return getDecorated().getCookie(); 105 } 106 107 108 /** 109 * {@inheritDoc} 110 */ 111 @Override 112 public void setCookie( byte[] cookie ) 113 { 114 // Copy the bytes 115 if ( !Strings.isEmpty( cookie ) ) 116 { 117 byte[] copy = new byte[cookie.length]; 118 System.arraycopy( cookie, 0, copy, 0, cookie.length ); 119 getDecorated().setCookie( copy ); 120 } 121 else 122 { 123 getDecorated().setCookie( null ); 124 } 125 } 126 127 128 /** 129 * {@inheritDoc} 130 */ 131 @Override 132 public boolean isReloadHint() 133 { 134 return getDecorated().isReloadHint(); 135 } 136 137 138 /** 139 * {@inheritDoc} 140 */ 141 @Override 142 public void setReloadHint( boolean reloadHint ) 143 { 144 getDecorated().setReloadHint( reloadHint ); 145 } 146 147 148 /** 149 * Compute the SyncRequestValue length. 150 * <br> 151 * SyncRequestValue : 152 * <pre> 153 * 0x30 L1 154 * | 155 * +--> 0x0A 0x01 [0x00|0x01|0x02|0x03] (mode) 156 * [+--> 0x04 L2 abcd... (cookie) 157 * +--> 0x01 0x01 [0x00|0xFF] (reloadHint) 158 * </pre> 159 * 160 * @return The computed length 161 */ 162 @Override 163 public int computeLength() 164 { 165 // The mode length 166 syncRequestValueLength = 1 + 1 + 1; 167 168 // The cookie length, if we have a cookie 169 if ( getCookie() != null ) 170 { 171 syncRequestValueLength += 1 + TLV.getNbBytes( getCookie().length ) + getCookie().length; 172 } 173 174 // The reloadHint length, default to false 175 if ( isReloadHint() ) 176 { 177 syncRequestValueLength += 1 + 1 + 1; 178 } 179 180 valueLength = 1 + TLV.getNbBytes( syncRequestValueLength ) + syncRequestValueLength; 181 182 // Call the super class to compute the global control length 183 return valueLength; 184 } 185 186 187 /** 188 * Encode the SyncRequestValue control 189 * 190 * @param buffer The encoded sink 191 * @return A ByteBuffer that contains the encoded PDU 192 * @throws EncoderException If anything goes wrong. 193 */ 194 @Override 195 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 196 { 197 if ( buffer == null ) 198 { 199 throw new EncoderException( I18n.err( I18n.ERR_04023 ) ); 200 } 201 202 // Encode the SEQ 203 buffer.put( UniversalTag.SEQUENCE.getValue() ); 204 buffer.put( TLV.getBytes( syncRequestValueLength ) ); 205 206 // The mode 207 buffer.put( UniversalTag.ENUMERATED.getValue() ); 208 buffer.put( ( byte ) 0x01 ); 209 buffer.put( BerValue.getBytes( getMode().getValue() ) ); 210 211 // The cookie 212 if ( getCookie() != null ) 213 { 214 BerValue.encode( buffer, getCookie() ); 215 } 216 217 // The reloadHint if not false 218 if ( isReloadHint() ) 219 { 220 BerValue.encode( buffer, isReloadHint() ); 221 } 222 223 return buffer; 224 } 225 226 227 /** 228 * {@inheritDoc} 229 */ 230 @Override 231 public byte[] getValue() 232 { 233 if ( value == null ) 234 { 235 try 236 { 237 computeLength(); 238 ByteBuffer buffer = ByteBuffer.allocate( valueLength ); 239 240 // Encode the SEQ 241 buffer.put( UniversalTag.SEQUENCE.getValue() ); 242 buffer.put( TLV.getBytes( syncRequestValueLength ) ); 243 244 // The mode 245 buffer.put( UniversalTag.ENUMERATED.getValue() ); 246 buffer.put( ( byte ) 0x01 ); 247 buffer.put( BerValue.getBytes( getMode().getValue() ) ); 248 249 // The cookie 250 if ( getCookie() != null ) 251 { 252 BerValue.encode( buffer, getCookie() ); 253 } 254 255 // The reloadHint if not false 256 if ( isReloadHint() ) 257 { 258 BerValue.encode( buffer, isReloadHint() ); 259 } 260 261 value = buffer.array(); 262 } 263 catch ( Exception e ) 264 { 265 return null; 266 } 267 } 268 269 return value; 270 } 271 272 273 /** 274 * {@inheritDoc} 275 */ 276 @Override 277 public Asn1Object decode( byte[] controlBytes ) throws DecoderException 278 { 279 ByteBuffer bb = ByteBuffer.wrap( controlBytes ); 280 SyncRequestValueContainer container = new SyncRequestValueContainer( this ); 281 DECODER.decode( bb, container ); 282 return this; 283 } 284}