Coverage Report - com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
IllegalImportCheck
100%
56/56
100%
32/32
2.455
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2017 the original author or authors.
 4  
 //
 5  
 // This library is free software; you can redistribute it and/or
 6  
 // modify it under the terms of the GNU Lesser General Public
 7  
 // License as published by the Free Software Foundation; either
 8  
 // version 2.1 of the License, or (at your option) any later version.
 9  
 //
 10  
 // This library is distributed in the hope that it will be useful,
 11  
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 // Lesser General Public License for more details.
 14  
 //
 15  
 // You should have received a copy of the GNU Lesser General Public
 16  
 // License along with this library; if not, write to the Free Software
 17  
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 18  
 ////////////////////////////////////////////////////////////////////////////////
 19  
 
 20  
 package com.puppycrawl.tools.checkstyle.checks.imports;
 21  
 
 22  
 import java.util.ArrayList;
 23  
 import java.util.List;
 24  
 import java.util.regex.Pattern;
 25  
 
 26  
 import com.puppycrawl.tools.checkstyle.StatelessCheck;
 27  
 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
 28  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 29  
 import com.puppycrawl.tools.checkstyle.api.FullIdent;
 30  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 31  
 import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
 32  
 
 33  
 /**
 34  
  * <p>
 35  
  * Checks for imports from a set of illegal packages.
 36  
  * By default, the check rejects all {@code sun.*} packages
 37  
  * since programs that contain direct calls to the {@code sun.*} packages
 38  
  * are <a href="http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html">
 39  
  * not 100% Pure Java</a>.
 40  
  * </p>
 41  
  * <p>
 42  
  * To reject other packages, set property illegalPkgs to a comma-separated
 43  
  * list of the illegal packages.
 44  
  * </p>
 45  
  * <p>
 46  
  * An example of how to configure the check is:
 47  
  * </p>
 48  
  * <pre>
 49  
  * &lt;module name="IllegalImport"/&gt;
 50  
  * </pre>
 51  
  * <p>
 52  
  * An example of how to configure the check so that it rejects packages
 53  
  * {@code java.io.*} and {@code java.sql.*} is
 54  
  * </p>
 55  
  * <pre>
 56  
  * &lt;module name="IllegalImport"&gt;
 57  
  *    &lt;property name="illegalPkgs" value="java.io, java.sql"/&gt;
 58  
  * &lt;/module&gt;
 59  
  *
 60  
  * Compatible with Java 1.5 source.
 61  
  *
 62  
  * </pre>
 63  
  * @author Oliver Burn
 64  
  * @author Lars K├╝hne
 65  
  */
 66  
 @StatelessCheck
 67  
 public class IllegalImportCheck
 68  
     extends AbstractCheck {
 69  
 
 70  
     /**
 71  
      * A key is pointing to the warning message text in "messages.properties"
 72  
      * file.
 73  
      */
 74  
     public static final String MSG_KEY = "import.illegal";
 75  
 
 76  
     /** The compiled regular expressions for packages. */
 77  19
     private final List<Pattern> illegalPkgsRegexps = new ArrayList<>();
 78  
 
 79  
     /** The compiled regular expressions for classes. */
 80  19
     private final List<Pattern> illegalClassesRegexps = new ArrayList<>();
 81  
 
 82  
     /** List of illegal packages. */
 83  
     private String[] illegalPkgs;
 84  
 
 85  
     /** List of illegal classes. */
 86  
     private String[] illegalClasses;
 87  
 
 88  
     /**
 89  
      * Whether the packages or class names
 90  
      * should be interpreted as regular expressions.
 91  
      */
 92  
     private boolean regexp;
 93  
 
 94  
     /**
 95  
      * Creates a new {@code IllegalImportCheck} instance.
 96  
      */
 97  19
     public IllegalImportCheck() {
 98  19
         setIllegalPkgs("sun");
 99  19
     }
 100  
 
 101  
     /**
 102  
      * Set the list of illegal packages.
 103  
      * @param from array of illegal packages
 104  
      * @noinspection WeakerAccess
 105  
      */
 106  
     public final void setIllegalPkgs(String... from) {
 107  25
         illegalPkgs = from.clone();
 108  25
         illegalPkgsRegexps.clear();
 109  50
         for (String illegalPkg : illegalPkgs) {
 110  25
             illegalPkgsRegexps.add(CommonUtils.createPattern("^" + illegalPkg + "\\..*"));
 111  
         }
 112  25
     }
 113  
 
 114  
     /**
 115  
      * Set the list of illegal classes.
 116  
      * @param from array of illegal classes
 117  
      */
 118  
     public void setIllegalClasses(String... from) {
 119  5
         illegalClasses = from.clone();
 120  12
         for (String illegalClass : illegalClasses) {
 121  7
             illegalClassesRegexps.add(CommonUtils.createPattern(illegalClass));
 122  
         }
 123  5
     }
 124  
 
 125  
     /**
 126  
      * Controls whether the packages or class names
 127  
      * should be interpreted as regular expressions.
 128  
      * @param regexp a {@code Boolean} value
 129  
      */
 130  
     public void setRegexp(boolean regexp) {
 131  5
         this.regexp = regexp;
 132  5
     }
 133  
 
 134  
     @Override
 135  
     public int[] getDefaultTokens() {
 136  28
         return getRequiredTokens();
 137  
     }
 138  
 
 139  
     @Override
 140  
     public int[] getAcceptableTokens() {
 141  5
         return getRequiredTokens();
 142  
     }
 143  
 
 144  
     @Override
 145  
     public int[] getRequiredTokens() {
 146  62
         return new int[] {TokenTypes.IMPORT, TokenTypes.STATIC_IMPORT};
 147  
     }
 148  
 
 149  
     @Override
 150  
     public void visitToken(DetailAST ast) {
 151  
         final FullIdent imp;
 152  198
         if (ast.getType() == TokenTypes.IMPORT) {
 153  174
             imp = FullIdent.createFullIdentBelow(ast);
 154  
         }
 155  
         else {
 156  48
             imp = FullIdent.createFullIdent(
 157  24
                 ast.getFirstChild().getNextSibling());
 158  
         }
 159  198
         if (isIllegalImport(imp.getText())) {
 160  54
             log(ast.getLineNo(),
 161  27
                 ast.getColumnNo(),
 162  
                 MSG_KEY,
 163  27
                 imp.getText());
 164  
         }
 165  198
     }
 166  
 
 167  
     /**
 168  
      * Checks if an import matches one of the regular expressions
 169  
      * for illegal packages or illegal class names.
 170  
      * @param importText the argument of the import keyword
 171  
      * @return if {@code importText} matches one of the regular expressions
 172  
      *         for illegal packages or illegal class names
 173  
      */
 174  
     private boolean isIllegalImportByRegularExpressions(String importText) {
 175  99
         boolean result = false;
 176  99
         for (Pattern pattern : illegalPkgsRegexps) {
 177  66
             if (pattern.matcher(importText).matches()) {
 178  14
                 result = true;
 179  14
                 break;
 180  
             }
 181  52
         }
 182  99
         if (!result) {
 183  85
             for (Pattern pattern : illegalClassesRegexps) {
 184  59
                 if (pattern.matcher(importText).matches()) {
 185  5
                     result = true;
 186  5
                     break;
 187  
                 }
 188  54
             }
 189  
         }
 190  99
         return result;
 191  
     }
 192  
 
 193  
     /**
 194  
      * Checks if an import is from a package or class name that must not be used.
 195  
      * @param importText the argument of the import keyword
 196  
      * @return if {@code importText} contains an illegal package prefix or equals illegal class name
 197  
      */
 198  
     private boolean isIllegalImportByPackagesAndClassNames(String importText) {
 199  99
         boolean result = false;
 200  191
         for (String element : illegalPkgs) {
 201  99
             if (importText.startsWith(element + ".")) {
 202  7
                 result = true;
 203  7
                 break;
 204  
             }
 205  
         }
 206  99
         if (!result && illegalClasses != null) {
 207  61
             for (String element : illegalClasses) {
 208  31
                 if (importText.equals(element)) {
 209  1
                     result = true;
 210  1
                     break;
 211  
                 }
 212  
             }
 213  
         }
 214  99
         return result;
 215  
     }
 216  
 
 217  
     /**
 218  
      * Checks if an import is from a package or class name that must not be used.
 219  
      * @param importText the argument of the import keyword
 220  
      * @return if {@code importText} is illegal import
 221  
      */
 222  
     private boolean isIllegalImport(String importText) {
 223  
         final boolean result;
 224  198
         if (regexp) {
 225  99
             result = isIllegalImportByRegularExpressions(importText);
 226  
         }
 227  
         else {
 228  99
             result = isIllegalImportByPackagesAndClassNames(importText);
 229  
         }
 230  198
         return result;
 231  
     }
 232  
 }