View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.kerberos.shared.messages.value;
21  
22  
23  import java.nio.BufferOverflowException;
24  import java.nio.ByteBuffer;
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import org.apache.directory.server.kerberos.shared.messages.Encodable;
29  import org.apache.directory.shared.asn1.AbstractAsn1Object;
30  import org.apache.directory.shared.asn1.ber.tlv.TLV;
31  import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
32  import org.apache.directory.shared.asn1.codec.EncoderException;
33  import org.apache.directory.shared.ldap.util.StringTools;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  
38  /**
39   * An authorization data container.
40   * 
41   * The ASN.1 grammar is :
42   * 
43   * -- NOTE: AuthorizationData is always used as an OPTIONAL field and
44   * -- should not be empty.
45   * AuthorizationData       ::= SEQUENCE OF AuthorizationDataEntry
46   *
47   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
48   * @version $Rev: 587531 $, $Date: 2007-10-23 16:59:10 +0200 (Di, 23 Okt 2007) $
49   */
50  public class AuthorizationData extends AbstractAsn1Object implements Encodable
51  {
52      /** The logger */
53      private static final Logger log = LoggerFactory.getLogger( AuthorizationData.class );
54  
55      /** Speedup for logs */
56      private static final boolean IS_DEBUG = log.isDebugEnabled();
57  
58      /** The list of AuthrorizationData elements */
59      private List<AuthorizationDataEntry> entries = new ArrayList<AuthorizationDataEntry>();
60  
61      // Storage for computed lengths
62      private transient int authorizationDataLength;
63  
64  
65      /**
66       * Creates a new instance of AuthorizationData.
67       */
68      public AuthorizationData()
69      {
70          // used by ASN.1 decoder
71      }
72  
73  
74      /**
75       * Adds all {@link AuthorizationData} entries to this {@link AuthorizationData}.
76       *
77       * @param data
78       */
79      public void add( AuthorizationData data )
80      {
81          entries.addAll( data.entries );
82      }
83  
84  
85      /**
86       * Adds an {@link AuthorizationDataEntry} to this {@link AuthorizationData}.
87       *
88       * @param entry
89       */
90      public void add( AuthorizationDataEntry entry )
91      {
92          entries.add( entry );
93      }
94  
95  
96      /**
97       * @return The AuthorizationdataEntry list
98       */
99      public List<AuthorizationDataEntry> getEntries()
100     {
101         return entries;
102     }
103 
104 
105     /**
106      * Compute the AuthorizationData length
107      * 
108      * AuthorizationData :
109      * 
110      * 0x30 L1 AuthorizationData
111      *  |
112      *  +--> 0x30 L2 AuthorizationDataEntry
113      *  |
114      *  +--> 0x30 L2 AuthorizationDataEntry
115      *  |
116      *  ...
117      *  |
118      *  +--> 0x30 L2 AuthorizationDataEntry
119      */
120     public int computeLength()
121     {
122         if ( ( entries == null ) || ( entries.size() == 0 ) )
123         {
124             authorizationDataLength = 1;
125 
126             return authorizationDataLength + 1;
127         }
128         else
129         {
130             authorizationDataLength = 0;
131 
132             for ( AuthorizationDataEntry entry : entries )
133             {
134                 authorizationDataLength += entry.computeLength();
135             }
136 
137             return 1 + TLV.getNbBytes( authorizationDataLength ) + authorizationDataLength;
138         }
139     }
140 
141 
142     /**
143      * Encode the AuthorizationData message to a PDU. 
144      * 
145      * AuthorizationData :
146      * 
147      * 0x30 LL
148      *   0x30 LL AuthorizationDataEntry 
149      *   0x30 LL AuthorizationDataEntry
150      *   ... 
151      *   0x30 LL AuthorizationDataEntry 
152      * 
153      * @param buffer The buffer where to put the PDU. It should have been allocated
154      * before, with the right size.
155      * @return The constructed PDU.
156      */
157     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
158     {
159         if ( buffer == null )
160         {
161             throw new EncoderException( "Cannot put a PDU in a null buffer !" );
162         }
163 
164         try
165         {
166             // The AuthorizationData SEQ Tag
167             buffer.put( UniversalTag.SEQUENCE_TAG );
168             buffer.put( TLV.getBytes( authorizationDataLength ) );
169 
170             // Each entry, if any
171             if ( ( entries != null ) && ( entries.size() != 0 ) )
172             {
173                 for ( AuthorizationDataEntry entry : entries )
174                 {
175                     entry.encode( buffer );
176                 }
177             }
178         }
179         catch ( BufferOverflowException boe )
180         {
181             log.error(
182                 "Cannot encode the AuthorizationData object, the PDU size is {} when only {} bytes has been allocated",
183                 1 + TLV.getNbBytes( authorizationDataLength ) + authorizationDataLength, buffer.capacity() );
184             throw new EncoderException( "The PDU buffer size is too small !" );
185         }
186 
187         if ( IS_DEBUG )
188         {
189             log.debug( "AuthorizationData encoding : {}", StringTools.dumpBytes( buffer.array() ) );
190             log.debug( "AuthorizationData initial value : {}", toString() );
191         }
192 
193         return buffer;
194     }
195 
196 
197     /**
198      * @see Object#toString()
199      */
200     public String toString()
201     {
202         return toString( "" );
203     }
204 
205 
206     /**
207      * @see Object#toString()
208      */
209     public String toString( String tabs )
210     {
211         StringBuilder sb = new StringBuilder();
212 
213         if ( ( entries == null ) || ( entries.size() == 0 ) )
214         {
215             sb.append( tabs ).append( "AuthorizationData : {}\n" );
216         }
217         else
218         {
219             sb.append( tabs ).append( "AuthorizationData : {\n" );
220             boolean isFirst = true;
221 
222             for ( AuthorizationDataEntry entry : entries )
223             {
224                 if ( isFirst )
225                 {
226                     isFirst = false;
227                 }
228                 else
229                 {
230                     sb.append( '\n' );
231                 }
232 
233                 sb.append( entry.toString( tabs + "    " ) ).append( '\n' );
234             }
235 
236             sb.append( tabs + "}" );
237         }
238 
239         return sb.toString();
240     }
241 }