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 }