Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
PkgControl |
|
| 3.0;3 |
1 | //////////////////////////////////////////////////////////////////////////////// | |
2 | // checkstyle: Checks Java source code for adherence to a set of rules. | |
3 | // Copyright (C) 2001-2014 Oliver Burn | |
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 | package com.puppycrawl.tools.checkstyle.checks.imports; | |
20 | ||
21 | import com.google.common.collect.Lists; | |
22 | import java.util.LinkedList; | |
23 | import java.util.List; | |
24 | ||
25 | /** | |
26 | * Represents the a tree of guards for controlling whether packages are allowed | |
27 | * to be used. Each instance must have a single parent or be the root node. | |
28 | * Each instance may have zero or more children. | |
29 | * | |
30 | * @author Oliver Burn | |
31 | */ | |
32 | 1 | class PkgControl |
33 | { | |
34 | /** List of {@link Guard} objects to check. */ | |
35 | 27 | private final LinkedList<Guard> mGuards = Lists.newLinkedList(); |
36 | /** List of children {@link PkgControl} objects. */ | |
37 | 27 | private final List<PkgControl> mChildren = Lists.newArrayList(); |
38 | /** The parent. Null indicates we are the root node. */ | |
39 | private final PkgControl mParent; | |
40 | /** The full package name for the node. */ | |
41 | private final String mFullPackage; | |
42 | ||
43 | /** | |
44 | * Construct a root node. | |
45 | * @param aPkgName the name of the package. | |
46 | */ | |
47 | PkgControl(final String aPkgName) | |
48 | 14 | { |
49 | 14 | assert aPkgName != null; |
50 | 14 | mParent = null; |
51 | 14 | mFullPackage = aPkgName; |
52 | 14 | } |
53 | ||
54 | /** | |
55 | * Construct a child node. | |
56 | * @param aParent the parent node. | |
57 | * @param aSubPkg the sub package name. | |
58 | */ | |
59 | PkgControl(final PkgControl aParent, final String aSubPkg) | |
60 | 13 | { |
61 | 13 | assert aParent != null; |
62 | 13 | assert aSubPkg != null; |
63 | 13 | mParent = aParent; |
64 | 13 | mFullPackage = aParent.getFullPackage() + "." + aSubPkg; |
65 | 13 | mParent.mChildren.add(this); |
66 | 13 | } |
67 | ||
68 | /** | |
69 | * Adds a guard to the node. | |
70 | * @param aThug the guard to be added. | |
71 | */ | |
72 | void addGuard(final Guard aThug) | |
73 | { | |
74 | 57 | mGuards.addFirst(aThug); |
75 | 57 | } |
76 | ||
77 | /** | |
78 | * @return the full package name represented by the node. | |
79 | */ | |
80 | String getFullPackage() | |
81 | { | |
82 | 38 | return mFullPackage; |
83 | } | |
84 | ||
85 | /** | |
86 | * Search down the tree to locate the finest match for a supplied package. | |
87 | * @param aForPkg the package to search for. | |
88 | * @return the finest match, or null if no match at all. | |
89 | */ | |
90 | PkgControl locateFinest(final String aForPkg) | |
91 | { | |
92 | // Check if we are a match. | |
93 | // This algormithm should be improved to check for a trailing "." | |
94 | // or nothing following. | |
95 | 21 | if (!aForPkg.startsWith(getFullPackage())) { |
96 | 7 | return null; |
97 | } | |
98 | ||
99 | // Check if any of the children match. | |
100 | 14 | for (PkgControl pc : mChildren) { |
101 | 8 | final PkgControl match = pc.locateFinest(aForPkg); |
102 | 8 | if (match != null) { |
103 | 6 | return match; |
104 | } | |
105 | 2 | } |
106 | ||
107 | // No match so I am the best there is. | |
108 | 8 | return this; |
109 | } | |
110 | ||
111 | /** | |
112 | * Returns whether a package is allowed to be used. The algorithm checks | |
113 | * with the current node for a result, and if none is found then calls | |
114 | * its parent looking for a match. This will recurse looking for match. | |
115 | * If there is no clear result then {@link AccessResult#UNKNOWN} is | |
116 | * returned. | |
117 | * @param aForImport the package to check on. | |
118 | * @param aInPkg the package doing the import. | |
119 | * @return an {@link AccessResult}. | |
120 | */ | |
121 | AccessResult checkAccess(final String aForImport, final String aInPkg) | |
122 | { | |
123 | 56 | final AccessResult retVal = localCheckAccess(aForImport, aInPkg); |
124 | 56 | if (retVal != AccessResult.UNKNOWN) { |
125 | 22 | return retVal; |
126 | } | |
127 | 34 | else if (mParent == null) { |
128 | // we are the top, so default to not allowed. | |
129 | 11 | return AccessResult.DISALLOWED; |
130 | } | |
131 | ||
132 | 23 | return mParent.checkAccess(aForImport, aInPkg); |
133 | } | |
134 | ||
135 | /** | |
136 | * Checks whether any of the guards for this node control access to | |
137 | * a specified package. | |
138 | * @param aForImport the package to check. | |
139 | * @param aInPkg the package doing the import. | |
140 | * @return an {@link AccessResult}. | |
141 | */ | |
142 | private AccessResult localCheckAccess(final String aForImport, | |
143 | final String aInPkg) | |
144 | { | |
145 | 56 | for (Guard g : mGuards) { |
146 | // Check if a Guard is only meant to be applied locally. | |
147 | 104 | if (g.isLocalOnly() && !mFullPackage.equals(aInPkg)) { |
148 | 10 | continue; |
149 | } | |
150 | 94 | final AccessResult result = g.verifyImport(aForImport); |
151 | 94 | if (result != AccessResult.UNKNOWN) { |
152 | 22 | return result; |
153 | } | |
154 | 72 | } |
155 | 34 | return AccessResult.UNKNOWN; |
156 | } | |
157 | } |