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.syncrepl.syncDone.SyncDoneValue; 036import org.apache.directory.api.ldap.extras.controls.syncrepl.syncDone.SyncDoneValueImpl; 037import org.apache.directory.api.util.Strings; 038 039 040/** 041 * A syncDoneValue object as described in rfc4533. 042 * 043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 044 */ 045public class SyncDoneValueDecorator extends ControlDecorator<SyncDoneValue> implements SyncDoneValue 046{ 047 /** The global length for this control */ 048 private int syncDoneValueLength; 049 050 /** An instance of this decoder */ 051 private static final Asn1Decoder decoder = new Asn1Decoder(); 052 053 054 /** 055 * Creates a new instance of SyncDoneValueControlCodec. 056 */ 057 public SyncDoneValueDecorator( LdapApiService codec ) 058 { 059 super( codec, new SyncDoneValueImpl() ); 060 } 061 062 063 /** 064 * Creates a new instance of SyncDoneValueDecorator. 065 * 066 * @param codec The LDAP codec 067 * @param control The control to be decorated 068 */ 069 public SyncDoneValueDecorator( LdapApiService codec, SyncDoneValue control ) 070 { 071 super( codec, control ); 072 } 073 074 075 /** 076 * Compute the syncDoneValue length. 077 * 0x30 L1 078 * | 079 * +--> 0x04 L2 xkcd!!!... (cookie) 080 * +--> 0x01 0x01 [0x00|0xFF] (refreshDeletes) 081 */ 082 @Override 083 public int computeLength() 084 { 085 // cookie's length 086 if ( getCookie() != null ) 087 { 088 syncDoneValueLength = 1 + TLV.getNbBytes( getCookie().length ) + getCookie().length; 089 } 090 091 // the refreshDeletes flag length 092 if ( isRefreshDeletes() ) 093 { 094 syncDoneValueLength += 1 + 1 + 1; 095 } 096 097 valueLength = 1 + TLV.getNbBytes( syncDoneValueLength ) + syncDoneValueLength; 098 099 // Call the super class to compute the global control length 100 return valueLength; 101 } 102 103 104 /** 105 * Encode the SyncDoneValue control 106 * 107 * @param buffer The encoded sink 108 * @return A ByteBuffer that contains the encoded PDU 109 * @throws EncoderException If anything goes wrong while encoding. 110 */ 111 @Override 112 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 113 { 114 if ( buffer == null ) 115 { 116 throw new EncoderException( I18n.err( I18n.ERR_04023 ) ); 117 } 118 119 // Encode the SEQ 120 buffer.put( UniversalTag.SEQUENCE.getValue() ); 121 buffer.put( TLV.getBytes( syncDoneValueLength ) ); 122 123 if ( getCookie() != null ) 124 { 125 BerValue.encode( buffer, getCookie() ); 126 } 127 128 if ( isRefreshDeletes() ) 129 { 130 BerValue.encode( buffer, isRefreshDeletes() ); 131 } 132 133 return buffer; 134 } 135 136 137 /** 138 * {@inheritDoc} 139 */ 140 @Override 141 public byte[] getValue() 142 { 143 if ( value == null ) 144 { 145 try 146 { 147 computeLength(); 148 ByteBuffer buffer = ByteBuffer.allocate( valueLength ); 149 150 // Encode the SEQ 151 buffer.put( UniversalTag.SEQUENCE.getValue() ); 152 buffer.put( TLV.getBytes( syncDoneValueLength ) ); 153 154 if ( getCookie() != null ) 155 { 156 BerValue.encode( buffer, getCookie() ); 157 } 158 159 if ( isRefreshDeletes() ) 160 { 161 BerValue.encode( buffer, isRefreshDeletes() ); 162 } 163 164 value = buffer.array(); 165 } 166 catch ( Exception e ) 167 { 168 return null; 169 } 170 } 171 172 return value; 173 } 174 175 176 /** 177 * {@inheritDoc} 178 */ 179 public byte[] getCookie() 180 { 181 return getDecorated().getCookie(); 182 } 183 184 185 /** 186 * {@inheritDoc} 187 */ 188 public void setCookie( byte[] cookie ) 189 { 190 // Copy the bytes 191 if ( !Strings.isEmpty( cookie ) ) 192 { 193 byte[] copy = new byte[cookie.length]; 194 System.arraycopy( cookie, 0, copy, 0, cookie.length ); 195 getDecorated().setCookie( copy ); 196 } 197 else 198 { 199 getDecorated().setCookie( null ); 200 } 201 } 202 203 204 /** 205 * {@inheritDoc} 206 */ 207 public boolean isRefreshDeletes() 208 { 209 return getDecorated().isRefreshDeletes(); 210 } 211 212 213 /** 214 * {@inheritDoc} 215 */ 216 public void setRefreshDeletes( boolean refreshDeletes ) 217 { 218 getDecorated().setRefreshDeletes( refreshDeletes ); 219 } 220 221 222 /** 223 * {@inheritDoc} 224 */ 225 public Asn1Object decode( byte[] controlBytes ) throws DecoderException 226 { 227 ByteBuffer bb = ByteBuffer.wrap( controlBytes ); 228 SyncDoneValueContainer container = new SyncDoneValueContainer( getCodecService(), this ); 229 decoder.decode( bb, container ); 230 return this; 231 } 232}