View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.validator.routines;
19  
20  import java.io.Serializable;
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.List;
24  
25  /**
26   * <p><b>InetAddress</b> validation and conversion routines (<code>java.net.InetAddress</code>).</p>
27   *
28   * <p>This class provides methods to validate a candidate IP address.
29   *
30   * <p>
31   * This class is a Singleton; you can retrieve the instance via the {@link #getInstance()} method.
32   * </p>
33   *
34   * @version $Revision: 1650785 $
35   * @since Validator 1.4
36   */
37  public class InetAddressValidator implements Serializable {
38  
39      private static final long serialVersionUID = -919201640201914789L;
40  
41      private static final String IPV4_REGEX =
42              "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
43  
44      /**
45       * Singleton instance of this class.
46       */
47      private static final InetAddressValidator VALIDATOR = new InetAddressValidator();
48  
49      /** IPv4 RegexValidator */
50      private final RegexValidator ipv4Validator = new RegexValidator(IPV4_REGEX);
51  
52      /**
53       * Returns the singleton instance of this validator.
54       * @return the singleton instance of this validator
55       */
56      public static InetAddressValidator getInstance() {
57          return VALIDATOR;
58      }
59  
60      /**
61       * Checks if the specified string is a valid IP address.
62       * @param inetAddress the string to validate
63       * @return true if the string validates as an IP address
64       */
65      public boolean isValid(String inetAddress) {
66          return isValidInet4Address(inetAddress) || isValidInet6Address(inetAddress);
67      }
68  
69      /**
70       * Validates an IPv4 address. Returns true if valid.
71       * @param inet4Address the IPv4 address to validate
72       * @return true if the argument contains a valid IPv4 address
73       */
74      public boolean isValidInet4Address(String inet4Address) {
75          // verify that address conforms to generic IPv4 format
76          String[] groups = ipv4Validator.match(inet4Address);
77  
78          if (groups == null) {
79              return false;
80          }
81  
82          // verify that address subgroups are legal
83          for (int i = 0; i <= 3; i++) {
84              String ipSegment = groups[i];
85              if (ipSegment == null || ipSegment.length() == 0) {
86                  return false;
87              }
88  
89              int iIpSegment = 0;
90  
91              try {
92                  iIpSegment = Integer.parseInt(ipSegment);
93              } catch(NumberFormatException e) {
94                  return false;
95              }
96  
97              if (iIpSegment > 255) {
98                  return false;
99              }
100 
101             if (ipSegment.length() > 1 && ipSegment.startsWith("0")) {
102                 return false;
103             }
104 
105         }
106 
107         return true;
108     }
109 
110     /**
111      * Validates an IPv6 address. Returns true if valid.
112      * @param inet6Address the IPv6 address to validate
113      * @return true if the argument contains a valid IPv6 address
114      * 
115      * @since 1.4.1
116      */
117     public boolean isValidInet6Address(String inet6Address) {
118         boolean containsCompressedZeroes = inet6Address.indexOf("::") > -1; // contains is Java 1.5
119         if (containsCompressedZeroes && (inet6Address.indexOf("::") != inet6Address.lastIndexOf("::"))) {
120             return false;
121         }
122         if ((inet6Address.startsWith(":") && !inet6Address.startsWith("::"))
123                 || (inet6Address.endsWith(":") && !inet6Address.endsWith("::"))) {
124             return false;
125         }
126         Object[] octets = inet6Address.split(":");
127         if (containsCompressedZeroes) {
128             List octetList = new ArrayList(Arrays.asList(octets));
129             if (inet6Address.endsWith("::")) {
130                 // String.split() drops ending empty segments
131                 octetList.add("");
132             } else if (inet6Address.startsWith("::") && !octetList.isEmpty()) {
133                 octetList.remove(0);
134             }
135             octets = octetList.toArray();
136         }
137         if (octets.length > 8) {
138             return false;
139         }
140         int validOctets = 0;
141         int emptyOctets = 0;
142         for (int index = 0; index < octets.length; index++) {
143             String octet = (String) octets[index];
144             if (octet.length() == 0) {
145                 emptyOctets++;
146                 if (emptyOctets > 1) {
147                     return false;
148                 }
149             } else {
150                 emptyOctets = 0;
151                 if (octet.indexOf(".") > -1) { // contains is Java 1.5+
152                     if (!inet6Address.endsWith(octet)) {
153                         return false;
154                     }
155                     if (index > octets.length - 1 || index > 6) {
156                         // IPV4 occupies last two octets
157                         return false;
158                     }
159                     if (!isValidInet4Address(octet)) {
160                         return false;
161                     }
162                     validOctets += 2;
163                     continue;
164                 }
165                 if (octet.length() > 4) {
166                     return false;
167                 }
168                 int octetInt = 0;
169                 try {
170                     octetInt = Integer.valueOf(octet, 16).intValue();
171                 } catch (NumberFormatException e) {
172                     return false;
173                 }
174                 if (octetInt < 0 || octetInt > 0xffff) {
175                     return false;
176                 }
177             }
178             validOctets++;
179         }
180         if (validOctets < 8 && !containsCompressedZeroes) {
181             return false;
182         }
183         return true;
184     }
185 }