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.Arrays;
27  import java.util.List;
28  
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   * Store a list of addresses.
40   * 
41   * The ASN.1 grammar is :
42   * 
43   * -- NOTE: HostAddresses is always used as an OPTIONAL field and
44   * -- should not be empty.
45   * HostAddresses   -- NOTE: subtly different from rfc1510,
46   *                 -- but has a value mapping and encodes the same
47   *         ::= SEQUENCE OF HostAddress
48   *
49   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
50   * @version $Rev: 642496 $, $Date: 2008-03-29 04:09:22 +0100 (Sa, 29 Mär 2008) $
51   */
52  public class HostAddresses extends AbstractAsn1Object
53  {
54      /** The logger */
55      private static final Logger LOG = LoggerFactory.getLogger( HostAddresses.class );
56  
57      /** Speedup for logs */
58      private static final boolean IS_DEBUG = LOG.isDebugEnabled();
59  
60      /** List of all HostAddress stored */
61      private List<HostAddress> addresses;
62  
63      // Storage for computed lengths
64      private transient int addressesLength;
65  
66  
67      /**
68       * Creates a new instance of HostAddresses.
69       */
70      public HostAddresses()
71      {
72          this.addresses = new ArrayList<HostAddress>();
73      }
74      
75  
76      /**
77       * Creates a new instance of HostAddresses.
78       *
79       * @param addresses The associated addresses
80       */
81      public HostAddresses( HostAddress[] addresses )
82      {
83          if ( addresses == null )
84          {
85              this.addresses = new ArrayList<HostAddress>();
86          }
87          else
88          {
89              this.addresses = Arrays.asList( addresses );
90          }
91      }
92  
93  
94      public void addHostAddress( HostAddress hostAddress )
95      {
96          addresses.add( hostAddress );
97      }
98  
99  
100     /**
101      * Returns true if this {@link HostAddresses} contains a specified {@link HostAddress}.
102      *
103      * @param address
104      * @return true if this {@link HostAddresses} contains a specified {@link HostAddress}.
105      */
106     public boolean contains( HostAddress address )
107     {
108         if ( addresses != null )
109         {
110             return addresses.contains( address );
111         }
112 
113         return false;
114     }
115 
116 
117     /**
118      * Returns true if two {@link HostAddresses} are equal.
119      *
120      * @param that
121      * @return true if two {@link HostAddresses} are equal.
122      */
123     public boolean equals( HostAddresses that )
124     {
125         if ( ( addresses == null && that.addresses != null )
126             || ( addresses != null && that.addresses == null ) )
127         {
128             return false;
129         }
130 
131         if ( addresses != null && that.addresses != null )
132         {
133             if ( addresses.size() != that.addresses.size() )
134             {
135                 return false;
136             }
137 
138             HostAddress[] thisHostAddresses = ( HostAddress[] ) addresses.toArray();
139             HostAddress[] thatHostAddresses = ( HostAddress[] ) that.addresses.toArray();
140 
141             for ( int i = 0; i < thisHostAddresses.length; i++ )
142             {
143                 if ( !thisHostAddresses[i].equals( thatHostAddresses[i] ) )
144                 {
145                     return false;
146                 }
147             }
148         }
149 
150         return true;
151     }
152 
153 
154     /**
155      * Returns the contained {@link HostAddress}s as an array.
156      *
157      * @return An array of {@link HostAddress}s.
158      */
159     public HostAddress[] getAddresses()
160     {
161         return ( HostAddress[] ) addresses.toArray();
162     }
163 
164 
165     /**
166      * Compute the hostAddresses length
167      * 
168      * HostAddresses :
169      * 
170      * 0x30 L1 hostAddresses sequence of HostAddresses
171      *  |
172      *  +--> 0x30 L2[1] Hostaddress[1]
173      *  |
174      *  +--> 0x30 L2[2] Hostaddress[2]
175      *  |
176      *  ...
177      *  |
178      *  +--> 0x30 L2[n] Hostaddress[n]
179      *        
180      *  where L1 = sum( L2[1], l2[2], ..., L2[n] )
181      */
182     public int computeLength()
183     {
184         // Compute the addresses length.
185         addressesLength = 0;
186 
187         if ( ( addresses != null ) && ( addresses.size() != 0 ) )
188         {
189             for ( HostAddress hostAddress : addresses )
190             {
191                 int length = hostAddress.computeLength();
192                 addressesLength += length;
193             }
194         }
195 
196         return 1 + TLV.getNbBytes( addressesLength ) + addressesLength;
197     }
198 
199 
200     /**
201      * Encode the HostAddress message to a PDU. 
202      * 
203      * HostAddress :
204      * 
205      * 0x30 LL
206      *   0x30 LL hostaddress[1] 
207      *   0x30 LL hostaddress[1]
208      *   ... 
209      *   0x30 LL hostaddress[1] 
210      * 
211      * @param buffer The buffer where to put the PDU. It should have been allocated
212      * before, with the right size.
213      * @return The constructed PDU.
214      */
215     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
216     {
217         if ( buffer == null )
218         {
219             throw new EncoderException( "Cannot put a PDU in a null buffer !" );
220         }
221 
222         try
223         {
224             // The HostAddresses SEQ Tag
225             buffer.put( UniversalTag.SEQUENCE_TAG );
226             buffer.put( TLV.getBytes( addressesLength ) );
227 
228             // The hostAddress list, if it's not empty
229             if ( ( addresses != null ) && ( addresses.size() != 0 ) )
230             {
231                 for ( HostAddress hostAddress : addresses )
232                 {
233                     hostAddress.encode( buffer );
234                 }
235             }
236         }
237         catch ( BufferOverflowException boe )
238         {
239             LOG.error(
240                 "Cannot encode the HostAddresses object, the PDU size is {} when only {} bytes has been allocated", 1
241                     + TLV.getNbBytes( addressesLength ) + addressesLength, buffer.capacity() );
242             throw new EncoderException( "The PDU buffer size is too small !" );
243         }
244 
245         if ( IS_DEBUG )
246         {
247             LOG.debug( "HostAddresses encoding : {}", StringTools.dumpBytes( buffer.array() ) );
248             LOG.debug( "HostAddresses initial value : {}", toString() );
249         }
250 
251         return buffer;
252     }
253 
254 
255     /**
256      * @see Object#toString()
257      */
258     public String toString()
259     {
260         StringBuilder sb = new StringBuilder();
261         boolean isFirst = true;
262 
263         for ( HostAddress hostAddress : addresses )
264         {
265             if ( isFirst )
266             {
267                 isFirst = false;
268             }
269             else
270             {
271                 sb.append( ", " );
272             }
273 
274             sb.append( hostAddress.toString() );
275         }
276 
277         return sb.toString();
278     }
279 }