08efde40def1808505d38ec0f2b78b8505a5f707
[knox.git] / gateway-provider-rewrite / src / main / java / org / apache / knox / gateway / filter / rewrite / ext / ScopedMatcher.java
1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 * <p>
10 * http://www.apache.org/licenses/LICENSE-2.0
11 * <p>
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package org.apache.knox.gateway.filter.rewrite.ext;
19
20 import org.apache.knox.gateway.filter.rewrite.impl.UrlRewriteRuleProcessorHolder;
21 import org.apache.knox.gateway.util.urltemplate.Matcher;
22 import org.apache.knox.gateway.util.urltemplate.Template;
23
24 import java.util.ArrayList;
25 import java.util.List;
26
27 /**
28 * A simple extension to the matcher that takes into account scopes for rules along with the templates themselves.
29 * This matcher maintains a list of matchers and delegates to an appropriate matcher based on scope information for the
30 * associated rules.
31 */
32 public class ScopedMatcher extends Matcher<UrlRewriteRuleProcessorHolder> {
33
34 public static final String GLOBAL_SCOPE = "GLOBAL";
35
36 private List<Matcher<UrlRewriteRuleProcessorHolder>> matchers;
37
38 public ScopedMatcher() {
39 super();
40 matchers = new ArrayList<>();
41 matchers.add(new Matcher<UrlRewriteRuleProcessorHolder>());
42 }
43
44 @Override
45 public UrlRewriteRuleProcessorHolder get(Template template) {
46 return super.get(template);
47 }
48
49 @Override
50 public void add(Template template, UrlRewriteRuleProcessorHolder value) {
51 Matcher<UrlRewriteRuleProcessorHolder> matcher = getMatcher(template, value);
52 matcher.add( template, value );
53 }
54
55 @Override
56 public Match match(Template input) {
57 return match(input, null);
58 }
59
60 public Match match(Template input, String scope) {
61 List<Match> matches = new ArrayList<>();
62 for (Matcher<UrlRewriteRuleProcessorHolder> matcher : matchers) {
63 Match match = matcher.match(input);
64 if (match != null) {
65 matches.add(match);
66 }
67 }
68 if (matches.size() == 0) {
69 return null;
70 }
71 if (matches.size() == 1) {
72 return getMatch(matches, scope);
73 }
74 return findBestMatch(matches, scope);
75 }
76
77 private Match findBestMatch(List<Match> matches, String scope) {
78 if (scope != null) {
79 //when multiple matches are found, find the first one that matches in scope
80 for ( Match match : matches ) {
81 String matchedScope = match.getValue().getScope();
82 if ( matchedScope != null && matchedScope.equals(scope) ) {
83 return match;
84 }
85 }
86 }
87 //since no scope match was found return the first global scopeed match
88 for ( Match match : matches ) {
89 String matchedScope = match.getValue().getScope();
90 if ( matchedScope != null && matchedScope.equals(GLOBAL_SCOPE) ) {
91 return match;
92 }
93 }
94 //return the first match from the list
95 return getMatch(matches, scope);
96 }
97
98 private Match getMatch(List<Match> matches, String scope) {
99 Match match = matches.get(0);
100 String matchedScope = match.getValue().getScope();
101 if (matchedScope != null && scope != null && !matchedScope.equals(scope) && !matchedScope.equals(GLOBAL_SCOPE)) {
102 return null;
103 }
104 return match;
105 }
106
107 /**
108 * Returns a matcher for a given template and processor holder. This method takes into account different scopes in
109 * addition to template values. If a matcher exists for a template but the scope is different, a new matcher is
110 * created and returned.
111 * @param template the template for which a matcher is needed
112 * @param holder the rule holder that goes along with the template.
113 * @return a matcher
114 */
115 private Matcher<UrlRewriteRuleProcessorHolder> getMatcher(Template template, UrlRewriteRuleProcessorHolder holder) {
116 for (Matcher<UrlRewriteRuleProcessorHolder> matcher : matchers) {
117 UrlRewriteRuleProcessorHolder matchersHolder = matcher.get(template);
118 if (matchersHolder == null) {
119 return matcher;
120 } else if (holder.getScope() == null && matchersHolder.getScope() == null) {
121 return matcher;
122 }
123 }
124 Matcher<UrlRewriteRuleProcessorHolder> matcher = new Matcher<>();
125 matchers.add(matcher);
126 return matcher;
127 }
128
129 }