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.server.kerberos.shared.messages.value;
021
022
023 import java.nio.BufferOverflowException;
024 import java.nio.ByteBuffer;
025 import java.util.ArrayList;
026 import java.util.Arrays;
027 import java.util.List;
028
029 import org.apache.directory.server.i18n.I18n;
030 import org.apache.directory.shared.asn1.AbstractAsn1Object;
031 import org.apache.directory.shared.asn1.ber.tlv.TLV;
032 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
033 import org.apache.directory.shared.asn1.codec.EncoderException;
034 import org.apache.directory.shared.ldap.util.StringTools;
035 import org.slf4j.Logger;
036 import org.slf4j.LoggerFactory;
037
038
039 /**
040 * Store a list of addresses.
041 *
042 * The ASN.1 grammar is :
043 *
044 * -- NOTE: HostAddresses is always used as an OPTIONAL field and
045 * -- should not be empty.
046 * HostAddresses -- NOTE: subtly different from rfc1510,
047 * -- but has a value mapping and encodes the same
048 * ::= SEQUENCE OF HostAddress
049 *
050 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
051 * @version $Rev: 902575 $, $Date: 2010-01-24 16:38:06 +0200 (Sun, 24 Jan 2010) $
052 */
053 public class HostAddresses extends AbstractAsn1Object
054 {
055 /** The logger */
056 private static final Logger LOG = LoggerFactory.getLogger( HostAddresses.class );
057
058 /** Speedup for logs */
059 private static final boolean IS_DEBUG = LOG.isDebugEnabled();
060
061 /** List of all HostAddress stored */
062 private List<HostAddress> addresses;
063
064 // Storage for computed lengths
065 private transient int addressesLength;
066
067
068 /**
069 * Creates a new instance of HostAddresses.
070 */
071 public HostAddresses()
072 {
073 this.addresses = new ArrayList<HostAddress>();
074 }
075
076
077 /**
078 * Creates a new instance of HostAddresses.
079 *
080 * @param addresses The associated addresses
081 */
082 public HostAddresses( HostAddress[] addresses )
083 {
084 if ( addresses == null )
085 {
086 this.addresses = new ArrayList<HostAddress>();
087 }
088 else
089 {
090 this.addresses = Arrays.asList( addresses );
091 }
092 }
093
094
095 public void addHostAddress( HostAddress hostAddress )
096 {
097 addresses.add( hostAddress );
098 }
099
100
101 /**
102 * Returns true if this {@link HostAddresses} contains a specified {@link HostAddress}.
103 *
104 * @param address
105 * @return true if this {@link HostAddresses} contains a specified {@link HostAddress}.
106 */
107 public boolean contains( HostAddress address )
108 {
109 if ( addresses != null )
110 {
111 return addresses.contains( address );
112 }
113
114 return false;
115 }
116
117
118 /**
119 * Returns true if two {@link HostAddresses} are equal.
120 *
121 * @param that
122 * @return true if two {@link HostAddresses} are equal.
123 */
124 public boolean equals( HostAddresses that )
125 {
126 if ( ( addresses == null && that.addresses != null )
127 || ( addresses != null && that.addresses == null ) )
128 {
129 return false;
130 }
131
132 if ( addresses != null && that.addresses != null )
133 {
134 if ( addresses.size() != that.addresses.size() )
135 {
136 return false;
137 }
138
139 HostAddress[] thisHostAddresses = ( HostAddress[] ) addresses.toArray();
140 HostAddress[] thatHostAddresses = ( HostAddress[] ) that.addresses.toArray();
141
142 for ( int i = 0; i < thisHostAddresses.length; i++ )
143 {
144 if ( !thisHostAddresses[i].equals( thatHostAddresses[i] ) )
145 {
146 return false;
147 }
148 }
149 }
150
151 return true;
152 }
153
154
155 /**
156 * Returns the contained {@link HostAddress}s as an array.
157 *
158 * @return An array of {@link HostAddress}s.
159 */
160 public HostAddress[] getAddresses()
161 {
162 return ( HostAddress[] ) addresses.toArray();
163 }
164
165
166 /**
167 * Compute the hostAddresses length
168 *
169 * HostAddresses :
170 *
171 * 0x30 L1 hostAddresses sequence of HostAddresses
172 * |
173 * +--> 0x30 L2[1] Hostaddress[1]
174 * |
175 * +--> 0x30 L2[2] Hostaddress[2]
176 * |
177 * ...
178 * |
179 * +--> 0x30 L2[n] Hostaddress[n]
180 *
181 * where L1 = sum( L2[1], l2[2], ..., L2[n] )
182 */
183 public int computeLength()
184 {
185 // Compute the addresses length.
186 addressesLength = 0;
187
188 if ( ( addresses != null ) && ( addresses.size() != 0 ) )
189 {
190 for ( HostAddress hostAddress : addresses )
191 {
192 int length = hostAddress.computeLength();
193 addressesLength += length;
194 }
195 }
196
197 return 1 + TLV.getNbBytes( addressesLength ) + addressesLength;
198 }
199
200
201 /**
202 * Encode the HostAddress message to a PDU.
203 *
204 * HostAddress :
205 *
206 * 0x30 LL
207 * 0x30 LL hostaddress[1]
208 * 0x30 LL hostaddress[1]
209 * ...
210 * 0x30 LL hostaddress[1]
211 *
212 * @param buffer The buffer where to put the PDU. It should have been allocated
213 * before, with the right size.
214 * @return The constructed PDU.
215 */
216 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
217 {
218 if ( buffer == null )
219 {
220 throw new EncoderException( I18n.err( I18n.ERR_148 ) );
221 }
222
223 try
224 {
225 // The HostAddresses SEQ Tag
226 buffer.put( UniversalTag.SEQUENCE_TAG );
227 buffer.put( TLV.getBytes( addressesLength ) );
228
229 // The hostAddress list, if it's not empty
230 if ( ( addresses != null ) && ( addresses.size() != 0 ) )
231 {
232 for ( HostAddress hostAddress : addresses )
233 {
234 hostAddress.encode( buffer );
235 }
236 }
237 }
238 catch ( BufferOverflowException boe )
239 {
240 LOG.error( I18n.err( I18n.ERR_144, 1 + TLV.getNbBytes( addressesLength )
241 + addressesLength, buffer.capacity() ) );
242 throw new EncoderException( I18n.err( I18n.ERR_138 ) );
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 }