View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2024 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.Deque;
23  import java.util.LinkedList;
24  
25  /**
26   * Represents a tree of import rules for controlling whether packages or
27   * classes are allowed to be used. Each instance must have a single parent or
28   * be the root node.
29   */
30  abstract class AbstractImportControl {
31  
32      /** List of {@link AbstractImportRule} objects to check. */
33      private final Deque<AbstractImportRule> rules = new LinkedList<>();
34      /** The parent. Null indicates we are the root node. */
35      private final AbstractImportControl parent;
36      /** Strategy in a case if matching allow/disallow rule was not found. */
37      private final MismatchStrategy strategyOnMismatch;
38  
39      /**
40       * Construct a child node.
41       *
42       * @param parent the parent node.
43       * @param strategyOnMismatch strategy in a case if matching allow/disallow rule was not found.
44       */
45      protected AbstractImportControl(AbstractImportControl parent,
46              MismatchStrategy strategyOnMismatch) {
47          this.parent = parent;
48          this.strategyOnMismatch = strategyOnMismatch;
49      }
50  
51      /**
52       * Search down the tree to locate the finest match for a supplied package.
53       *
54       * @param forPkg the package to search for.
55       * @param forFileName the file name to search for.
56       * @return the finest match, or null if no match at all.
57       */
58      public abstract AbstractImportControl locateFinest(String forPkg, String forFileName);
59  
60      /**
61       * Check for equality of this with pkg.
62       *
63       * @param pkg the package to compare with.
64       * @param fileName the file name to compare with.
65       * @return if it matches.
66       */
67      protected abstract boolean matchesExactly(String pkg, String fileName);
68  
69      /**
70       * Adds an {@link AbstractImportRule} to the node.
71       *
72       * @param rule the rule to be added.
73       */
74      protected void addImportRule(AbstractImportRule rule) {
75          rules.addLast(rule);
76      }
77  
78      /**
79       * Returns whether a package or class is allowed to be imported.
80       * The algorithm checks with the current node for a result, and if none is
81       * found then calls its parent looking for a match. This will recurse
82       * looking for match. If there is no clear result then
83       * {@link AccessResult#UNKNOWN} is returned.
84       *
85       * @param inPkg the package doing the import.
86       * @param inFileName the file name doing the import.
87       * @param forImport the import to check on.
88       * @return an {@link AccessResult}.
89       */
90      public AccessResult checkAccess(String inPkg, String inFileName, String forImport) {
91          final AccessResult result;
92          final AccessResult returnValue = localCheckAccess(inPkg, inFileName, forImport);
93          if (returnValue != AccessResult.UNKNOWN) {
94              result = returnValue;
95          }
96          else if (parent == null) {
97              if (strategyOnMismatch == MismatchStrategy.ALLOWED) {
98                  result = AccessResult.ALLOWED;
99              }
100             else {
101                 result = AccessResult.DISALLOWED;
102             }
103         }
104         else {
105             if (strategyOnMismatch == MismatchStrategy.ALLOWED) {
106                 result = AccessResult.ALLOWED;
107             }
108             else if (strategyOnMismatch == MismatchStrategy.DISALLOWED) {
109                 result = AccessResult.DISALLOWED;
110             }
111             else {
112                 result = parent.checkAccess(inPkg, inFileName, forImport);
113             }
114         }
115         return result;
116     }
117 
118     /**
119      * Checks whether any of the rules for this node control access to
120      * a specified package or file.
121      *
122      * @param inPkg the package doing the import.
123      * @param inFileName the file name doing the import.
124      * @param forImport the import to check on.
125      * @return an {@link AccessResult}.
126      */
127     private AccessResult localCheckAccess(String inPkg, String inFileName, String forImport) {
128         AccessResult localCheckAccessResult = AccessResult.UNKNOWN;
129         for (AbstractImportRule importRule : rules) {
130             // Check if an import rule is only meant to be applied locally.
131             if (!importRule.isLocalOnly() || matchesExactly(inPkg, inFileName)) {
132                 final AccessResult result = importRule.verifyImport(forImport);
133                 if (result != AccessResult.UNKNOWN) {
134                     localCheckAccessResult = result;
135                     break;
136                 }
137             }
138         }
139         return localCheckAccessResult;
140     }
141 
142 }