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.ad; 021 022import java.nio.ByteBuffer; 023 024import org.apache.directory.api.asn1.Asn1Object; 025import org.apache.directory.api.asn1.DecoderException; 026import org.apache.directory.api.asn1.EncoderException; 027import org.apache.directory.api.asn1.ber.Asn1Decoder; 028import org.apache.directory.api.asn1.ber.tlv.BerValue; 029import org.apache.directory.api.asn1.ber.tlv.TLV; 030import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 031import org.apache.directory.api.i18n.I18n; 032import org.apache.directory.api.ldap.codec.api.ControlDecorator; 033import org.apache.directory.api.ldap.codec.api.LdapApiService; 034import org.apache.directory.api.util.Strings; 035 036/** 037 * A decorator around AdDirSync control. It will encode and decode this control. 038 * 039 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 040 */ 041public class AdDirSyncDecorator extends ControlDecorator<AdDirSync> implements AdDirSync 042{ 043 /** The global length for this control */ 044 private int adDirSyncLength; 045 046 /** An instance of this decoder */ 047 private static final Asn1Decoder decoder = new Asn1Decoder(); 048 049 050 /** 051 * Creates a new instance of AdDirSyncControlCodec. 052 */ 053 public AdDirSyncDecorator( LdapApiService codec ) 054 { 055 super( codec, new AdDirSyncImpl() ); 056 } 057 058 059 /** 060 * Creates a new instance of AdDirSyncDecorator. 061 * 062 * @param codec The LDAP codec 063 * @param control The control to be decorated 064 */ 065 public AdDirSyncDecorator( LdapApiService codec, AdDirSync control ) 066 { 067 super( codec, control ); 068 } 069 070 071 /** 072 * {@inheritDoc} 073 */ 074 public int getParentFirst() 075 { 076 return getDecorated().getParentFirst(); 077 } 078 079 080 /** 081 * {@inheritDoc} 082 */ 083 public void setParentFirst( int parentFirst ) 084 { 085 getDecorated().setParentFirst( parentFirst ); 086 } 087 088 089 /** 090 * {@inheritDoc} 091 */ 092 public AdDirSyncFlag getFlag() 093 { 094 return getDecorated().getFlag(); 095 } 096 097 098 /** 099 * {@inheritDoc} 100 */ 101 public void setFlag( AdDirSyncFlag flag ) 102 { 103 getDecorated().setFlag( flag ); 104 } 105 106 107 /** 108 * {@inheritDoc} 109 */ 110 public int getMaxReturnLength() 111 { 112 return getDecorated().getMaxReturnLength(); 113 } 114 115 116 /** 117 * {@inheritDoc} 118 */ 119 public void setMaxReturnLength( int maxReturnLength ) 120 { 121 getDecorated().setMaxReturnLength( maxReturnLength ); 122 } 123 124 125 /** 126 * {@inheritDoc} 127 */ 128 public byte[] getCookie() 129 { 130 return getDecorated().getCookie(); 131 } 132 133 134 /** 135 * {@inheritDoc} 136 */ 137 public void setCookie( byte[] cookie ) 138 { 139 // Copy the bytes 140 if ( !Strings.isEmpty( cookie ) ) 141 { 142 byte[] copy = new byte[cookie.length]; 143 System.arraycopy( cookie, 0, copy, 0, cookie.length ); 144 getDecorated().setCookie( copy ); 145 } 146 else 147 { 148 getDecorated().setCookie( null ); 149 } 150 } 151 152 153 /** 154 * Compute the AdDirSync length. We use the client side control. 155 * 0x30 L1 156 * | 157 * +--> 0x02 0x0(1-4) nnn (parentFirst) 158 * +--> 0x02 0x0(1-4) nnn (maxReturnLength) 159 * +--> 0x04 L2 xkcd!!!... (cookie) 160 */ 161 @Override 162 public int computeLength() 163 { 164 // the parentFirst flag length 165 adDirSyncLength = 1 + TLV.getNbBytes( getParentFirst() ) + BerValue.getNbBytes( getParentFirst() ); 166 167 // the maxReturnLength length 168 adDirSyncLength += 1 + TLV.getNbBytes( getMaxReturnLength() ) + BerValue.getNbBytes( getMaxReturnLength() ); 169 170 // cookie's length 171 byte[] cookie = getCookie(); 172 173 if ( cookie == null ) 174 { 175 adDirSyncLength += 1 + 1; 176 } 177 else 178 { 179 adDirSyncLength += 1 + TLV.getNbBytes( cookie.length ) + cookie.length; 180 } 181 182 valueLength = 1 + TLV.getNbBytes( adDirSyncLength ) + adDirSyncLength; 183 184 // Call the super class to compute the global control length 185 return valueLength; 186 } 187 188 189 /** 190 * Encode the AdDirSync control. We use the client side control. 191 * 192 * @param buffer The encoded sink 193 * @return A ByteBuffer that contains the encoded PDU 194 * @throws EncoderException If anything goes wrong while encoding. 195 */ 196 @Override 197 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 198 { 199 if ( buffer == null ) 200 { 201 throw new EncoderException( I18n.err( I18n.ERR_04023 ) ); 202 } 203 204 // Encode the SEQ 205 buffer.put( UniversalTag.SEQUENCE.getValue() ); 206 buffer.put( TLV.getBytes( adDirSyncLength ) ); 207 208 // Encode the ParentFirst flag 209 BerValue.encode( buffer, getParentFirst() ); 210 211 // Encode the MaxReturnLength 212 BerValue.encode( buffer, getMaxReturnLength() ); 213 214 // Encode the cookie 215 BerValue.encode( buffer, getCookie() ); 216 217 return buffer; 218 } 219 220 221 /** 222 * {@inheritDoc} 223 */ 224 @Override 225 public byte[] getValue() 226 { 227 if ( value == null ) 228 { 229 try 230 { 231 computeLength(); 232 ByteBuffer buffer = ByteBuffer.allocate( valueLength ); 233 234 // Encode the SEQ 235 buffer.put( UniversalTag.SEQUENCE.getValue() ); 236 buffer.put( TLV.getBytes( adDirSyncLength ) ); 237 238 // Encode the ParentFirst flag 239 BerValue.encode( buffer, getParentFirst() ); 240 241 // Encode the MaxReturnLength 242 BerValue.encode( buffer, getMaxReturnLength() ); 243 244 // Encode the cookie 245 BerValue.encode( buffer, getCookie() ); 246 247 value = buffer.array(); 248 } 249 catch ( Exception e ) 250 { 251 return null; 252 } 253 } 254 255 return value; 256 } 257 258 259 /** 260 * {@inheritDoc} 261 */ 262 public Asn1Object decode( byte[] controlBytes ) throws DecoderException 263 { 264 ByteBuffer bb = ByteBuffer.wrap( controlBytes ); 265 AdDirSyncContainer container = new AdDirSyncContainer( getCodecService(), this ); 266 decoder.decode( bb, container ); 267 return this; 268 } 269}