Coverage Report - org.apache.commons.validator.routines.InetAddressValidator
 
Classes in this File Line Coverage Branch Coverage Complexity
InetAddressValidator
92%
58/63
90%
58/64
12.75
 
 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: 1783032 $
 35  
  * @since Validator 1.4
 36  
  */
 37  8
 public class InetAddressValidator implements Serializable {
 38  
 
 39  
     private static final int IPV4_MAX_OCTET_VALUE = 255;
 40  
 
 41  
     private static final int MAX_UNSIGNED_SHORT = 0xffff;
 42  
 
 43  
     private static final int BASE_16 = 16;
 44  
 
 45  
     private static final long serialVersionUID = -919201640201914789L;
 46  
 
 47  
     private static final String IPV4_REGEX =
 48  
             "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
 49  
 
 50  
     // Max number of hex groups (separated by :) in an IPV6 address
 51  
     private static final int IPV6_MAX_HEX_GROUPS = 8;
 52  
 
 53  
     // Max hex digits in each IPv6 group
 54  
     private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4;
 55  
 
 56  
     /**
 57  
      * Singleton instance of this class.
 58  
      */
 59  1
     private static final InetAddressValidator VALIDATOR = new InetAddressValidator();
 60  
 
 61  
     /** IPv4 RegexValidator */
 62  8
     private final RegexValidator ipv4Validator = new RegexValidator(IPV4_REGEX);
 63  
 
 64  
     /**
 65  
      * Returns the singleton instance of this validator.
 66  
      * @return the singleton instance of this validator
 67  
      */
 68  
     public static InetAddressValidator getInstance() {
 69  56866
         return VALIDATOR;
 70  
     }
 71  
 
 72  
     /**
 73  
      * Checks if the specified string is a valid IP address.
 74  
      * @param inetAddress the string to validate
 75  
      * @return true if the string validates as an IP address
 76  
      */
 77  
     public boolean isValid(String inetAddress) {
 78  28453
         return isValidInet4Address(inetAddress) || isValidInet6Address(inetAddress);
 79  
     }
 80  
 
 81  
     /**
 82  
      * Validates an IPv4 address. Returns true if valid.
 83  
      * @param inet4Address the IPv4 address to validate
 84  
      * @return true if the argument contains a valid IPv4 address
 85  
      */
 86  
     public boolean isValidInet4Address(String inet4Address) {
 87  
         // verify that address conforms to generic IPv4 format
 88  79104
         String[] groups = ipv4Validator.match(inet4Address);
 89  
 
 90  79104
         if (groups == null) {
 91  66599
             return false;
 92  
         }
 93  
 
 94  
         // verify that address subgroups are legal
 95  41664
         for (String ipSegment : groups) {
 96  34394
             if (ipSegment == null || ipSegment.length() == 0) {
 97  0
                 return false;
 98  
             }
 99  
 
 100  34394
             int iIpSegment = 0;
 101  
 
 102  
             try {
 103  34394
                 iIpSegment = Integer.parseInt(ipSegment);
 104  0
             } catch(NumberFormatException e) {
 105  0
                 return false;
 106  34394
             }
 107  
 
 108  34394
             if (iIpSegment > IPV4_MAX_OCTET_VALUE) {
 109  5232
                 return false;
 110  
             }
 111  
 
 112  29162
             if (ipSegment.length() > 1 && ipSegment.startsWith("0")) {
 113  3
                 return false;
 114  
             }
 115  
 
 116  
         }
 117  
 
 118  7270
         return true;
 119  
     }
 120  
 
 121  
     /**
 122  
      * Validates an IPv6 address. Returns true if valid.
 123  
      * @param inet6Address the IPv6 address to validate
 124  
      * @return true if the argument contains a valid IPv6 address
 125  
      * 
 126  
      * @since 1.4.1
 127  
      */
 128  
     public boolean isValidInet6Address(String inet6Address) {
 129  25763
         boolean containsCompressedZeroes = inet6Address.contains("::");
 130  25763
         if (containsCompressedZeroes && (inet6Address.indexOf("::") != inet6Address.lastIndexOf("::"))) {
 131  73
             return false;
 132  
         }
 133  25690
         if ((inet6Address.startsWith(":") && !inet6Address.startsWith("::"))
 134  
                 || (inet6Address.endsWith(":") && !inet6Address.endsWith("::"))) {
 135  105
             return false;
 136  
         }
 137  25585
         String[] octets = inet6Address.split(":");
 138  25585
         if (containsCompressedZeroes) {
 139  222
             List<String> octetList = new ArrayList<String>(Arrays.asList(octets));
 140  222
             if (inet6Address.endsWith("::")) {
 141  
                 // String.split() drops ending empty segments
 142  29
                 octetList.add("");
 143  193
             } else if (inet6Address.startsWith("::") && !octetList.isEmpty()) {
 144  75
                 octetList.remove(0);
 145  
             }
 146  222
             octets = octetList.toArray(new String[octetList.size()]);
 147  
         }
 148  25585
         if (octets.length > IPV6_MAX_HEX_GROUPS) {
 149  8
             return false;
 150  
         }
 151  25577
         int validOctets = 0;
 152  25577
         int emptyOctets = 0; // consecutive empty chunks
 153  30006
         for (int index = 0; index < octets.length; index++) {
 154  26651
             String octet = octets[index];
 155  26651
             if (octet.length() == 0) {
 156  1802
                 emptyOctets++;
 157  1802
                 if (emptyOctets > 1) {
 158  0
                     return false;
 159  
                 }
 160  
             } else {
 161  24849
                 emptyOctets = 0;
 162  
                 // Is last chunk an IPv4 address?
 163  24849
                 if (index == octets.length - 1 && octet.contains(".")) {
 164  22214
                     if (!isValidInet4Address(octet)) {
 165  22157
                         return false;
 166  
                     }
 167  57
                     validOctets += 2;
 168  57
                     continue;
 169  
                 }
 170  2635
                 if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) {
 171  52
                     return false;
 172  
                 }
 173  2583
                 int octetInt = 0;
 174  
                 try {
 175  2583
                     octetInt = Integer.parseInt(octet, BASE_16);
 176  13
                 } catch (NumberFormatException e) {
 177  13
                     return false;
 178  2570
                 }
 179  2570
                 if (octetInt < 0 || octetInt > MAX_UNSIGNED_SHORT) {
 180  0
                     return false;
 181  
                 }
 182  
             }
 183  4372
             validOctets++;
 184  
         }
 185  3355
         if (validOctets > IPV6_MAX_HEX_GROUPS || (validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes)) {
 186  3184
             return false;
 187  
         }
 188  171
         return true;
 189  
     }
 190  
 }