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 }