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.dhcp.messages;
21  
22  
23  import java.text.ParseException;
24  import java.util.Arrays;
25  import java.util.regex.Matcher;
26  import java.util.regex.Pattern;
27  
28  
29  /**
30   * A representation of a DHCP hardware address.
31   * 
32   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
33   * @version $Rev: 551805 $, $Date: 2007-06-29 00:57:04 -0500 (Fr, 29 Jun 2007) $
34   */
35  public final class HardwareAddress
36  {
37      /**
38       * [htype] Hardware address type, see ARP section in "Assigned Numbers" RFC;
39       * e.g., '1' = 10mb ethernet.
40       */
41      private final short type;
42  
43      /**
44       * [hlen] Hardware address length (e.g. '6' for 10mb ethernet).
45       */
46      private final short length;
47  
48      /**
49       * [chaddr] Client hardware address.
50       */
51      private final byte[] address;
52  
53  
54      /**
55       * @param type
56       * @param length
57       * @param address
58       */
59      public HardwareAddress(short type, short length, byte[] address)
60      {
61          this.type = type;
62          this.length = length;
63          this.address = address;
64      }
65  
66  
67      public byte[] getAddress()
68      {
69          return address;
70      }
71  
72  
73      public short getLength()
74      {
75          return length;
76      }
77  
78  
79      public short getType()
80      {
81          return type;
82      }
83  
84  
85      /**
86       * @see java.lang.Object#hashCode()
87       * @return the instance's hash code 
88       */
89      public int hashCode()
90      {
91          int hashCode = 98643532 ^ type ^ length;
92          for ( int i = 0; i < length; i++ )
93              hashCode ^= address[i];
94  
95          return hashCode;
96      }
97  
98  
99      /*
100      * @see java.lang.Object#equals(java.lang.Object)
101      */
102     public boolean equals( Object obj )
103     {
104         if ( null == obj || !( obj.getClass().equals( HardwareAddress.class ) ) )
105             return false;
106 
107         HardwareAddress hw = ( HardwareAddress ) obj;
108 
109         return length == hw.length && type == hw.type && Arrays.equals( address, hw.address );
110     }
111 
112 
113     /**
114      * Create the string representation of the hardware address native to the
115      * corresponding address type. This method currently supports only type
116      * 1==ethernet with the representation <code>a1:a2:a3:a4:a5:a6</code>.<br>
117      * For all other types, this method falls back to the representation created
118      * by toString().
119      * 
120      * @see java.lang.Object#toString()
121      */
122     public String getNativeRepresentation()
123     {
124         StringBuffer sb = new StringBuffer();
125         switch ( type )
126         {
127             case 1:
128                 for ( int i = 0; i < length; i++ )
129                 {
130                     if ( i > 0 )
131                         sb.append( ":" );
132                     String hex = Integer.toHexString( address[i] & 0xff );
133                     if ( hex.length() < 2 )
134                         sb.append( '0' );
135                     sb.append( hex );
136                 }
137                 break;
138             default:
139                 sb.append( toString() );
140         }
141 
142         return sb.toString();
143     }
144 
145 
146     /**
147      * Create a string representation of the hardware address. The string
148      * representation is in the format<br>
149      * <code>t/a1:a2:a3...</code><br>
150      * Where <code>t</code> represents the address type (decimal) and
151      * <code>a<sub>n</sub></code> represent the address bytes (hexadecimal).
152      * 
153      * @see java.lang.Object#toString()
154      */
155     public String toString()
156     {
157         StringBuffer sb = new StringBuffer();
158         sb.append( type );
159         sb.append( "/" );
160         for ( int i = 0; i < length; i++ )
161         {
162             if ( i > 0 )
163                 sb.append( ":" );
164             String hex = Integer.toHexString( address[i] & 0xff );
165             if ( hex.length() < 2 )
166                 sb.append( '0' );
167             sb.append( hex );
168         }
169 
170         return sb.toString();
171     }
172 
173     private static final Pattern PARSE_PATTERN = Pattern
174         .compile( "(\\d+)\\s+(?:(\\p{XDigit}{1,2}):)*(\\p{XDigit}{1,2})?" );
175 
176 
177     /**
178      * Parses a string representation of a hardware address according to the
179      * specification given in {@link #toString()}.
180      * 
181      * @param s
182      * @return HardwareAddress
183      * @throws ParseException
184      */
185     public static HardwareAddress valueOf( String s )
186     {
187         if ( null == s || s.length() == 0 )
188             return null;
189 
190         Matcher m = PARSE_PATTERN.matcher( s );
191         if ( !m.matches() )
192             throw new IllegalArgumentException( "Can't parse string representation: " + s );
193 
194         int type = Integer.parseInt( m.group( 1 ) );
195         int len = m.groupCount() - 1;
196 
197         byte addr[] = new byte[len];
198         for ( int i = 0; i < addr.length; i++ )
199             addr[i] = ( byte ) Integer.parseInt( m.group( i + 2 ), 16 );
200 
201         return new HardwareAddress( ( short ) type, ( short ) len, addr );
202     }
203 }