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.dhcp.messages;
021
022
023 import java.text.ParseException;
024 import java.util.Arrays;
025 import java.util.regex.Matcher;
026 import java.util.regex.Pattern;
027
028 import org.apache.directory.server.i18n.I18n;
029
030
031 /**
032 * A representation of a DHCP hardware address.
033 *
034 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
035 * @version $Rev: 551805 $, $Date: 2007-06-29 00:57:04 -0500 (Fr, 29 Jun 2007) $
036 */
037 public final class HardwareAddress
038 {
039 /**
040 * [htype] Hardware address type, see ARP section in "Assigned Numbers" RFC;
041 * e.g., '1' = 10mb ethernet.
042 */
043 private final short type;
044
045 /**
046 * [hlen] Hardware address length (e.g. '6' for 10mb ethernet).
047 */
048 private final short length;
049
050 /**
051 * [chaddr] Client hardware address.
052 */
053 private final byte[] address;
054
055
056 /**
057 * @param type
058 * @param length
059 * @param address
060 */
061 public HardwareAddress(short type, short length, byte[] address)
062 {
063 this.type = type;
064 this.length = length;
065 this.address = address;
066 }
067
068
069 public byte[] getAddress()
070 {
071 return address;
072 }
073
074
075 public short getLength()
076 {
077 return length;
078 }
079
080
081 public short getType()
082 {
083 return type;
084 }
085
086
087 /**
088 * @see java.lang.Object#hashCode()
089 * @return the instance's hash code
090 */
091 public int hashCode()
092 {
093 int hashCode = 98643532 ^ type ^ length;
094 for ( int i = 0; i < length; i++ )
095 hashCode ^= address[i];
096
097 return hashCode;
098 }
099
100
101 /*
102 * @see java.lang.Object#equals(java.lang.Object)
103 */
104 public boolean equals( Object obj )
105 {
106 if ( null == obj || !( obj.getClass().equals( HardwareAddress.class ) ) )
107 return false;
108
109 HardwareAddress hw = ( HardwareAddress ) obj;
110
111 return length == hw.length && type == hw.type && Arrays.equals( address, hw.address );
112 }
113
114
115 /**
116 * Create the string representation of the hardware address native to the
117 * corresponding address type. This method currently supports only type
118 * 1==ethernet with the representation <code>a1:a2:a3:a4:a5:a6</code>.<br>
119 * For all other types, this method falls back to the representation created
120 * by toString().
121 *
122 * @see java.lang.Object#toString()
123 */
124 public String getNativeRepresentation()
125 {
126 StringBuffer sb = new StringBuffer();
127 switch ( type )
128 {
129 case 1:
130 for ( int i = 0; i < length; i++ )
131 {
132 if ( i > 0 )
133 sb.append( ":" );
134 String hex = Integer.toHexString( address[i] & 0xff );
135 if ( hex.length() < 2 )
136 sb.append( '0' );
137 sb.append( hex );
138 }
139 break;
140 default:
141 sb.append( toString() );
142 }
143
144 return sb.toString();
145 }
146
147
148 /**
149 * Create a string representation of the hardware address. The string
150 * representation is in the format<br>
151 * <code>t/a1:a2:a3...</code><br>
152 * Where <code>t</code> represents the address type (decimal) and
153 * <code>a<sub>n</sub></code> represent the address bytes (hexadecimal).
154 *
155 * @see java.lang.Object#toString()
156 */
157 public String toString()
158 {
159 StringBuffer sb = new StringBuffer();
160 sb.append( type );
161 sb.append( "/" );
162 for ( int i = 0; i < length; i++ )
163 {
164 if ( i > 0 )
165 sb.append( ":" );
166 String hex = Integer.toHexString( address[i] & 0xff );
167 if ( hex.length() < 2 )
168 sb.append( '0' );
169 sb.append( hex );
170 }
171
172 return sb.toString();
173 }
174
175 private static final Pattern PARSE_PATTERN = Pattern
176 .compile( "(\\d+)\\s+(?:(\\p{XDigit}{1,2}):)*(\\p{XDigit}{1,2})?" );
177
178
179 /**
180 * Parses a string representation of a hardware address according to the
181 * specification given in {@link #toString()}.
182 *
183 * @param s
184 * @return HardwareAddress
185 * @throws ParseException
186 */
187 public static HardwareAddress valueOf( String s )
188 {
189 if ( null == s || s.length() == 0 )
190 return null;
191
192 Matcher m = PARSE_PATTERN.matcher( s );
193 if ( !m.matches() )
194 throw new IllegalArgumentException( I18n.err( I18n.ERR_637, s ) );
195
196 int type = Integer.parseInt( m.group( 1 ) );
197 int len = m.groupCount() - 1;
198
199 byte addr[] = new byte[len];
200 for ( int i = 0; i < addr.length; i++ )
201 addr[i] = ( byte ) Integer.parseInt( m.group( i + 2 ), 16 );
202
203 return new HardwareAddress( ( short ) type, ( short ) len, addr );
204 }
205 }