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 */
020 package org.apache.directory.shared.ldap.codec.controls;
021
022
023 import java.nio.BufferOverflowException;
024 import java.nio.ByteBuffer;
025
026 import org.apache.directory.shared.asn1.AbstractAsn1Object;
027 import org.apache.directory.shared.asn1.ber.tlv.TLV;
028 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
029 import org.apache.directory.shared.asn1.ber.tlv.Value;
030 import org.apache.directory.shared.asn1.codec.EncoderException;
031 import org.apache.directory.shared.i18n.I18n;
032 import org.apache.directory.shared.ldap.message.control.Control;
033 import org.apache.directory.shared.ldap.util.StringTools;
034
035
036 /**
037 * A Asn1Object to store a Control.
038 *
039 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
040 * @version $Rev: 912399 $, $Date: 2010-02-21 22:52:31 +0200 (Sun, 21 Feb 2010) $,
041 */
042 public abstract class AbstractControl extends AbstractAsn1Object implements Control, CodecControl
043 {
044 // ~ Instance fields
045 // ----------------------------------------------------------------------------
046 /** The control type */
047 private String oid;
048
049 /** The criticality (default value is false) */
050 private boolean criticality = false;
051
052 /** Optional control value */
053 protected byte[] value;
054
055 /** The encoded value length */
056 protected int valueLength;
057
058 /** The control length */
059 private int controlLength;
060
061 protected ControlDecoder decoder;
062
063 // ~ Methods
064 // ------------------------------------------------------------------------------------
065
066 /**
067 * Default constructor.
068 */
069 public AbstractControl( String oid )
070 {
071 this.oid = oid;
072 }
073
074 /**
075 * Get the OID
076 *
077 * @return A string which represent the control oid
078 */
079 public String getOid()
080 {
081 return oid == null ? "" : oid;
082 }
083
084
085 /**
086 * Get the control value
087 *
088 * @return The control value
089 */
090 public byte[] getValue()
091 {
092 return value;
093 }
094
095
096 /**
097 * Set the encoded control value
098 *
099 * @param encodedValue The encoded control value to store
100 */
101 public void setValue( byte[] value )
102 {
103 if ( value != null )
104 {
105 this.value = new byte[ value.length ];
106 System.arraycopy( value, 0, this.value, 0, value.length );
107 }
108 else
109 {
110 this.value = null;
111 }
112 }
113
114
115 /**
116 * Get the criticality
117 *
118 * @return <code>true</code> if the criticality flag is true.
119 */
120 public boolean isCritical()
121 {
122 return criticality;
123 }
124
125
126 /**
127 * Set the criticality
128 *
129 * @param criticality The criticality value
130 */
131 public void setCritical( boolean criticality )
132 {
133 this.criticality = criticality;
134 }
135
136
137 /**
138 * {@inheritDoc}
139 */
140 public int computeLength()
141 {
142 return 0;
143 }
144
145
146 /**
147 * {@inheritDoc}
148 */
149 public int computeLength( int valueLength )
150 {
151 // The OID
152 int oidLengh = StringTools.getBytesUtf8( oid ).length;
153 controlLength = 1 + TLV.getNbBytes( oidLengh ) + oidLengh;
154
155 // The criticality, only if true
156 if ( criticality )
157 {
158 controlLength += 1 + 1 + 1; // Always 3 for a boolean
159 }
160
161 this.valueLength = valueLength;
162
163 if ( valueLength != 0 )
164 {
165 controlLength += 1 + TLV.getNbBytes( valueLength ) + valueLength;
166 }
167
168 return 1 + TLV.getNbBytes( controlLength ) + controlLength;
169 }
170
171
172 /**
173 * {@inheritDoc}
174 */
175 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
176 {
177 if ( buffer == null )
178 {
179 throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
180 }
181
182 try
183 {
184 // The LdapMessage Sequence
185 buffer.put( UniversalTag.SEQUENCE_TAG );
186
187 // The length has been calculated by the computeLength method
188 buffer.put( TLV.getBytes( controlLength ) );
189 }
190 catch ( BufferOverflowException boe )
191 {
192 throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
193 }
194
195 // The control type
196 Value.encode( buffer, getOid().getBytes() );
197
198 // The control criticality, if true
199 if ( criticality )
200 {
201 Value.encode( buffer, criticality );
202 }
203
204 return buffer;
205 }
206
207
208 /**
209 * {@inheritDoc}
210 */
211 public boolean hasValue()
212 {
213 return value != null;
214 }
215
216
217 public ControlDecoder getDecoder()
218 {
219 return decoder;
220 }
221
222
223 /**
224 * Return a String representing a Control
225 */
226 public String toString()
227 {
228 StringBuffer sb = new StringBuffer();
229
230 sb.append( " Control\n" );
231 sb.append( " Control oid : '" ).append( oid ).append(
232 "'\n" );
233 sb.append( " Criticality : '" ).append( criticality ).append( "'\n" );
234
235 if ( value != null )
236 {
237 sb.append( " Control value : '" ).append( StringTools.dumpBytes( value ) )
238 .append( "'\n" );
239 }
240
241 return sb.toString();
242 }
243 }