1919 */
2020package org .sonar .api .web ;
2121
22- import java .util .ArrayList ;
23- import java .util .Arrays ;
24- import java .util .Collection ;
25- import java .util .HashSet ;
26- import java .util .LinkedHashSet ;
27- import java .util .List ;
28- import java .util .Set ;
29- import java .util .function .Predicate ;
30- import java .util .stream .Collectors ;
3122import org .sonar .api .ExtensionPoint ;
3223import org .sonar .api .server .ServerSide ;
3324
34- import static java .util .Arrays .asList ;
35- import static java .util .Collections .unmodifiableList ;
36- import static org .apache .commons .lang .StringUtils .substringBeforeLast ;
37- import static org .sonar .api .utils .Preconditions .checkArgument ;
38-
3925/**
4026 * {@code @deprecated} since 9.16. Use {@link org.sonar.api.web.HttpFilter} instead.
27+ *
4128 * @since 3.1
4229 */
4330@ ServerSide
@@ -51,166 +38,4 @@ public abstract class ServletFilter implements javax.servlet.Filter {
5138 public UrlPattern doGetPattern () {
5239 return UrlPattern .builder ().build ();
5340 }
54-
55- public static final class UrlPattern {
56-
57- private static final String MATCH_ALL = "/*" ;
58-
59- private final List <String > inclusions ;
60- private final List <String > exclusions ;
61- private final Predicate <String >[] inclusionPredicates ;
62- private final Predicate <String >[] exclusionPredicates ;
63-
64- private UrlPattern (Builder builder ) {
65- this .inclusions = unmodifiableList (new ArrayList <>(builder .inclusions ));
66- this .exclusions = unmodifiableList (new ArrayList <>(builder .exclusions ));
67- if (builder .inclusionPredicates .isEmpty ()) {
68- // because Stream#anyMatch() returns false if stream is empty
69- this .inclusionPredicates = new Predicate []{s -> true };
70- } else {
71- this .inclusionPredicates = builder .inclusionPredicates .stream ().toArray (Predicate []::new );
72- }
73- this .exclusionPredicates = builder .exclusionPredicates .stream ().toArray (Predicate []::new );
74- }
75-
76- public boolean matches (String path ) {
77- return !Arrays .stream (exclusionPredicates ).anyMatch (pattern -> pattern .test (path )) &&
78- Arrays .stream (inclusionPredicates ).anyMatch (pattern -> pattern .test (path ));
79- }
80-
81- /**
82- * @since 6.0
83- */
84- public Collection <String > getInclusions () {
85- return inclusions ;
86- }
87-
88- /**
89- * @since 6.0
90- */
91- public Collection <String > getExclusions () {
92- return exclusions ;
93- }
94-
95- public String label () {
96- return "UrlPattern{" +
97- "inclusions=[" + convertPatternsToString (inclusions ) + "]" +
98- ", exclusions=[" + convertPatternsToString (exclusions ) + "]" +
99- '}' ;
100- }
101-
102- private static String convertPatternsToString (List <String > input ) {
103- StringBuilder output = new StringBuilder ();
104- if (input .isEmpty ()) {
105- return "" ;
106- }
107- if (input .size () == 1 ) {
108- return output .append (input .get (0 )).toString ();
109- }
110- return output .append (input .get (0 )).append (", ..." ).toString ();
111- }
112-
113- /**
114- * Defines only a single inclusion pattern. This is a shortcut for {@code builder().includes(inclusionPattern).build()}.
115- */
116- public static UrlPattern create (String inclusionPattern ) {
117- return builder ().includes (inclusionPattern ).build ();
118- }
119-
120- /**
121- * @since 6.0
122- */
123- public static Builder builder () {
124- return new Builder ();
125- }
126-
127- /**
128- * @since 6.0
129- */
130- public static class Builder {
131- private static final String WILDCARD_CHAR = "*" ;
132- private static final Collection <String > STATIC_RESOURCES = unmodifiableList (asList (
133- "*.css" , "*.css.map" , "*.ico" , "*.png" , "*.jpg" , "*.jpeg" , "*.gif" , "*.svg" , "*.js" , "*.js.map" , "*.pdf" , "/json/*" , "*.woff2" ,
134- "/static/*" , "/robots.txt" , "/favicon.ico" , "/apple-touch-icon*" , "/mstile*" ));
135-
136- private final Set <String > inclusions = new LinkedHashSet <>();
137- private final Set <String > exclusions = new LinkedHashSet <>();
138- private final Set <Predicate <String >> inclusionPredicates = new HashSet <>();
139- private final Set <Predicate <String >> exclusionPredicates = new HashSet <>();
140-
141- private Builder () {
142- }
143-
144- public static Collection <String > staticResourcePatterns () {
145- return STATIC_RESOURCES ;
146- }
147-
148- /**
149- * Add inclusion patterns. Supported formats are:
150- * <ul>
151- * <li>path prefixed by / and ended by * or /*, for example "/api/foo/*", to match all paths "/api/foo" and "api/api/foo/something/else"</li>
152- * <li>path prefixed by / and ended by .*, for example "/api/foo.*", to match exact path "/api/foo" with any suffix like "/api/foo.protobuf"</li>
153- * <li>path prefixed by *, for example "*\/foo", to match all paths "/api/foo" and "something/else/foo"</li>
154- * <li>path with leading slash and no wildcard, for example "/api/foo", to match exact path "/api/foo"</li>
155- * </ul>
156- */
157- public Builder includes (String ... includePatterns ) {
158- return includes (asList (includePatterns ));
159- }
160-
161- /**
162- * Add exclusion patterns. See format described in {@link #includes(String...)}
163- */
164- public Builder includes (Collection <String > includePatterns ) {
165- this .inclusions .addAll (includePatterns );
166- this .inclusionPredicates .addAll (includePatterns .stream ()
167- .filter (pattern -> !MATCH_ALL .equals (pattern ))
168- .map (Builder ::compile )
169- .collect (Collectors .toList ()));
170- return this ;
171- }
172-
173- public Builder excludes (String ... excludePatterns ) {
174- return excludes (asList (excludePatterns ));
175- }
176-
177- public Builder excludes (Collection <String > excludePatterns ) {
178- this .exclusions .addAll (excludePatterns );
179- this .exclusionPredicates .addAll (excludePatterns .stream ()
180- .map (Builder ::compile )
181- .collect (Collectors .toList ()));
182- return this ;
183- }
184-
185- public UrlPattern build () {
186- return new UrlPattern (this );
187- }
188-
189- private static Predicate <String > compile (String pattern ) {
190- int countStars = pattern .length () - pattern .replace (WILDCARD_CHAR , "" ).length ();
191- if (countStars == 0 ) {
192- checkArgument (pattern .startsWith ("/" ), "URL pattern must start with slash '/': %s" , pattern );
193- return url -> url .equals (pattern );
194- }
195- checkArgument (countStars == 1 , "URL pattern accepts only zero or one wildcard character '*': %s" , pattern );
196- if (pattern .charAt (0 ) == '/' ) {
197- checkArgument (pattern .endsWith (WILDCARD_CHAR ), "URL pattern must end with wildcard character '*': %s" , pattern );
198- if (pattern .endsWith ("/*" )) {
199- String path = pattern .substring (0 , pattern .length () - "/*" .length ());
200- return url -> url .startsWith (path );
201- }
202- if (pattern .endsWith (".*" )) {
203- String path = pattern .substring (0 , pattern .length () - ".*" .length ());
204- return url -> substringBeforeLast (url , "." ).equals (path );
205- }
206- String path = pattern .substring (0 , pattern .length () - "*" .length ());
207- return url -> url .startsWith (path );
208- }
209- checkArgument (pattern .startsWith (WILDCARD_CHAR ), "URL pattern must start with wildcard character '*': %s" , pattern );
210- // remove the leading *
211- String path = pattern .substring (1 );
212- return url -> url .endsWith (path );
213- }
214- }
215- }
21641}
0 commit comments