View Javadoc

1   package com.atlassian.ip;
2   
3   import java.net.InetAddress;
4   
5   /**
6    * IP subnet consisting of a network address and a network mask. Individual ip
7    * addresses are represented as all ones subnets. Zero subnets are also
8    * allowed.
9    */
10  public class Subnet
11  {
12      private final InetAddress ipAddress;
13      private final int mask;
14  
15      private Subnet(InetAddress ipAddress, int mask)
16      {
17          this.ipAddress = ipAddress;
18          this.mask = mask;
19      }
20  
21      /**
22       * Creates a subnet of the given pattern.
23       *
24       * Patterns can be IPv4/IPv6 addresses or subnets in both asterisk and CIDR
25       * notation. Examples of valid patterns:
26       * <pre>
27       * 192.168.1.10
28       * ::10
29       * 192.168.1.*
30       * 192.168.5.128/26
31       * 0:0:0:7b::/64
32       * </pre>
33       *
34       * @param pattern pattern to create a Subnet of
35       * @return Subnet based on the given pattern
36       */
37      public static Subnet forPattern(String pattern)
38      {
39          final InetAddress ipAddress;
40          final int mask;
41          if (pattern.matches("(\\d+\\.)*\\*(\\.\\*)*")) // Asterisk subnet notation
42          {
43              String[] parts = pattern.split("\\.");
44              int asteriskCount = 0;
45              for (int i = parts.length - 1; i >= 0 && parts[i].equals("*"); --i)
46              {
47                  ++asteriskCount;
48              }
49              ipAddress = InetAddresses.forString(pattern.replace("*", "0"));
50              mask = 32 - 8 * asteriskCount;
51          }
52          else if (pattern.contains("/")) // CIDR subnet notation
53          {
54              final String[] addressComponents = pattern.split("/", 2);
55              ipAddress = InetAddresses.forString(addressComponents[0]);
56              mask = Integer.parseInt(addressComponents[1]);
57          }
58          else // Plain IP address (Treated as all ones subnet for matching purposes)
59          {
60              ipAddress = InetAddresses.forString(pattern);
61              mask = 8 * ipAddress.getAddress().length;
62          }
63          return new Subnet(ipAddress, mask);
64      }
65  
66      /**
67       * Creates an all ones subnet of the given ip address.
68       *
69       * @param ipAddress ipAddress to create a subnet of
70       * @return all ones subnet based on the given ip address
71       */
72      public static Subnet forAddress(InetAddress ipAddress)
73      {
74          return new Subnet(ipAddress, ipAddress.getAddress().length * 8);
75      }
76  
77      /**
78       * Returns true if the given pattern is a valid subnet pattern.
79       *
80       * @param pattern pattern to validate
81       * @return true if the given pattern is a valid subnet pattern
82       */
83      public static boolean isValidPattern(String pattern)
84      {
85          try
86          {
87              forPattern(pattern);
88              return true;
89          }
90          catch (IllegalArgumentException e)
91          {
92              return false;
93          }
94      }
95  
96      /**
97       * Returns the network address of this subnet.
98       *
99       * @return network address of this subnet
100      */
101     public byte[] getAddress()
102     {
103         return ipAddress.getAddress();
104     }
105 
106     /**
107      * Returns the network mask of this subnet.
108      *
109      * @return network mask of this subnet
110      */
111     public int getMask()
112     {
113         return mask;
114     }
115 
116     @Override
117     public boolean equals(Object o)
118     {
119         if (this == o) return true;
120         if (o == null || getClass() != o.getClass()) return false;
121 
122         Subnet subnet = (Subnet) o;
123 
124         if (mask != subnet.mask) return false;
125         if (!ipAddress.equals(subnet.ipAddress)) return false;
126 
127         return true;
128     }
129 
130     @Override
131     public int hashCode()
132     {
133         int result = ipAddress.hashCode();
134         result = 31 * result + mask;
135         return result;
136     }
137 }