Changes to Prefix to support new PATRICIA Trie
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
index 9936cb7..f4ff6b1 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
@@ -450,7 +450,7 @@
 			} catch (NumberFormatException e) {
 				log.warn("Wrong mask format in RIB JSON: {}", mask1);
 				continue;
-			} catch (UnknownHostException e1) {
+			} catch (IllegalArgumentException e1) {
 				log.warn("Wrong prefix format in RIB JSON: {}", prefix1);
 				continue;
 			}
@@ -525,7 +525,7 @@
 		Prefix prefix = null;
 		try {
 			prefix = new Prefix(node.key, node.rib.masklen);
-		} catch (UnknownHostException e) {
+		} catch (IllegalArgumentException e) {
 			log.error(" ", e);
 		}
 
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
index 19b44c8..39a14cd 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
@@ -121,7 +121,7 @@
 				reply = "[POST: mask format is wrong]";
 				log.info(reply);
 				return reply + "\n";				
-			} catch (UnknownHostException e1) {
+			} catch (IllegalArgumentException e1) {
 				reply = "[POST: prefix format is wrong]";
 				log.info(reply);
 				return reply + "\n";
@@ -184,7 +184,7 @@
 				reply = "[DELE: mask format is wrong]";
 				log.info(reply);
 				return reply + "\n";
-			} catch (UnknownHostException e1) {
+			} catch (IllegalArgumentException e1) {
 				reply = "[DELE: prefix format is wrong]";
 				log.info(reply);
 				return reply + "\n";
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java
index 54775df..c40214b 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java
@@ -2,30 +2,89 @@
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.Arrays;
 
 public class Prefix {
-	private int prefixLength;
-	private InetAddress address;
+	private final int MAX_BYTES = 4;
+	
+	private final int prefixLength;
+	private final byte[] address;
+	
+	//For verifying the arguments and pretty printing
+	private final InetAddress inetAddress;
+	
+	public Prefix(byte[] addr, int prefixLength) {
+		if (addr == null || addr.length != MAX_BYTES || 
+				prefixLength < 0 || prefixLength > MAX_BYTES * Byte.SIZE) {
+			throw new IllegalArgumentException();
+		}
 
-	public Prefix(byte[] addr, int prefixLength) throws UnknownHostException {
-		//try {
-		address = InetAddress.getByAddress(addr);
-		//} catch (UnknownHostException e) {
-		//	System.out.println("InetAddress exception");
-		//	return;
-		//}
+		address = canonicalizeAddress(addr, prefixLength);
 		this.prefixLength = prefixLength;
-		//System.out.println(address.toString() + "/" + prefixLength);
+		
+		try {
+			inetAddress = InetAddress.getByAddress(address);
+		} catch (UnknownHostException e) {
+			throw new IllegalArgumentException();
+		}
 	}
 
-	public Prefix(String str, int prefixLength) throws UnknownHostException {
-		//try {
-		address = InetAddress.getByName(str);
-		//} catch (UnknownHostException e) {
-		//	System.out.println("InetAddress exception");
-		//	return;
-		//}
+	public Prefix(String strAddress, int prefixLength) {
+		byte[] addr = null;
+		try {
+			addr = InetAddress.getByName(strAddress).getAddress();
+		} catch (UnknownHostException e) {
+			throw new IllegalArgumentException("Invalid IP inetAddress argument");
+		}
+				
+		if (addr == null || addr.length != MAX_BYTES || 
+				prefixLength < 0 || prefixLength > MAX_BYTES * Byte.SIZE) {
+			throw new IllegalArgumentException();
+		}
+		
+		address = canonicalizeAddress(addr, prefixLength);
 		this.prefixLength = prefixLength;
+		
+		try {
+			inetAddress = InetAddress.getByAddress(address);
+		} catch (UnknownHostException e) {
+			throw new IllegalArgumentException();
+		}
+	}
+	
+	private byte[] canonicalizeAddress(byte[] address, int prefixLength) {
+		byte[] result = new byte[address.length];
+		
+		if (prefixLength == 0) {
+			for (int i = 0; i < MAX_BYTES; i++) {
+				result[i] = 0;
+			}
+			
+			return result;
+		}
+		
+		result = Arrays.copyOf(address, address.length);
+		
+		//Set all bytes after the end of the prefix to 0
+		int lastByteIndex = (prefixLength - 1) / Byte.SIZE;
+		for (int i = lastByteIndex; i < MAX_BYTES; i++) {
+			result[i] = 0;
+		}
+		
+		byte lastByte = address[lastByteIndex];
+		byte mask = 0;
+		byte lsb = 1;
+		int lastBit = (prefixLength - 1) % Byte.SIZE;
+		for (int i = 0; i < Byte.SIZE; i++) {
+			if (i <= lastBit + 1) {
+				mask |= lsb;
+			}
+			mask <<= 1;
+		}
+
+		result[lastByteIndex] = (byte) (lastByte & mask);
+		
+		return result;
 	}
 
 	public int getPrefixLength() {
@@ -33,7 +92,7 @@
 	}
 	
 	public byte[] getAddress() {
-		return address.getAddress();
+		return address;
 	}
 	
 	@Override
@@ -44,7 +103,7 @@
 		
 		Prefix otherPrefix = (Prefix) other;
 		
-		return (address.equals(otherPrefix.address)) && 
+		return (Arrays.equals(address, otherPrefix.address)) &&
 				(prefixLength == otherPrefix.prefixLength);
 	}
 	
@@ -52,12 +111,28 @@
 	public int hashCode() {
 		int hash = 17;
 		hash = 31 * hash + prefixLength;
-		hash = 31 * hash + (address == null ? 0 : address.hashCode());
+		hash = 31 * hash + Arrays.hashCode(address);
 		return hash;
 	}
 	
 	@Override
 	public String toString() {
-		return address.getHostAddress() + "/" + prefixLength;
+		return inetAddress.getHostAddress() + "/" + prefixLength;
+	}
+	
+	public String printAsBits() {
+		String result = "";
+		for (int i = 0; i < address.length; i++) {
+			byte b = address[i];
+			for (int j = 0; j < Byte.SIZE; j++) {
+				byte mask = (byte) (0x80 >>> j);
+				result += ((b & mask) == 0)? "0" : "1";
+				if (i*Byte.SIZE+j == prefixLength-1) {
+					return result;
+				}
+			}
+			result += " ";
+		}
+		return result.substring(0, result.length() - 1);
 	}
 }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
index f56934d..8ef388a 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
@@ -38,6 +38,7 @@
 import com.google.common.collect.Multimaps;
 import com.google.common.collect.SetMultimap;
 
+//TODO have L2 and also L3 mode, where it takes into account interface addresses
 public class ProxyArpManager implements IProxyArpService, IOFMessageListener {
 	private static Logger log = LoggerFactory.getLogger(ProxyArpManager.class);
 	
@@ -79,7 +80,7 @@
 			return retry;
 		}
 		
-		public synchronized void dispatchReply(InetAddress ipAddress, byte[] replyMacAddress) {
+		public void dispatchReply(InetAddress ipAddress, byte[] replyMacAddress) {
 			log.debug("Dispatching reply for {} to {}", ipAddress.getHostAddress(), 
 					requester);
 			requester.arpResponse(ipAddress, replyMacAddress);