2009/05/20 - Apache Shale has been retired.
For more information, please explore the Attic.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shale.remoting.impl;
19
20 import java.io.IOException;
21 import java.io.StreamTokenizer;
22 import java.io.StringReader;
23 import java.util.ArrayList;
24 import java.util.List;
25 import org.apache.shale.remoting.Processor;
26
27 /***
28 * <p>Abstract base class for {@link Processor} implementations that filter
29 * requests based on matching the resource identifier against a set of
30 * <code>includes</code> and <code>excludes</code> regular expressions.</p>
31 *
32 * @since 1.0.4
33 */
34 public abstract class FilteringProcessor implements Processor {
35
36
37
38
39
40 /***
41 * <p>Comma-delimited regular expression patterns to exclude remote host
42 * names that match.</p>
43 */
44 private String excludes = null;
45
46
47 /***
48 * <p>Array of regular expression patterns for the excludes list.</p>
49 */
50 private String excludesPatterns[] = new String[0];
51
52
53 /***
54 * <p>Comma-delimited regular expression patterns to include remote host
55 * names that match.</p>
56 */
57 private String includes = null;
58
59
60 /***
61 * <p>Array of regular expression patterns for the includes list.</p>
62 */
63 private String includesPatterns[] = new String[0];
64
65
66
67
68
69 /***
70 * <p>Return the comma-delimited regular expresson patterns to exclude
71 * remote host names that match, if any; otherwise, return
72 * <code>null</code>.</p>
73 */
74 public String getExcludes() { return this.excludes; }
75
76
77 /***
78 * <p>Set the comma-delimited regular expression patterns to exclude
79 * remote host names that match, if any; or <code>null</code> for no
80 * restrictions.</p>
81 *
82 * @param excludes New exclude pattern(s)
83 */
84 public void setExcludes(String excludes) {
85 this.excludes = excludes;
86 this.excludesPatterns = precompile(excludes);
87 }
88
89
90 /***
91 * <p>Return the comma-delimited regular expresson patterns to include
92 * remote host names that match, if any; otherwise, return
93 * <code>null</code>.</p>
94 */
95 public String getIncludes() { return this.includes; }
96
97
98 /***
99 * <p>Set the comma-delimited regular expression patterns to include
100 * remote host names that match, if any; or <code>null</code> for no
101 * restrictions.</p>
102 *
103 * @param includes New include pattern(s)
104 */
105 public void setIncludes(String includes) {
106 this.includes = includes;
107 this.includesPatterns = precompile(includes);
108 }
109
110
111
112
113
114 /***
115 * <p>Return <code>true</code> if we should accept a request for the
116 * specified resource identifier, based upon our configured includes
117 * and excludes patterns (if any).</p>
118 *
119 * @param resourceId Resource identifier to validate
120 */
121 protected boolean accept(String resourceId) {
122
123
124 if (matches(resourceId, excludesPatterns, false)) {
125 return false;
126 }
127
128
129 if (matches(resourceId, includesPatterns, true)) {
130 return true;
131 }
132
133
134
135 if ((includesPatterns != null) && (includesPatterns.length > 0)) {
136 return false;
137 }
138
139
140 return true;
141
142 }
143
144
145
146
147
148 /***
149 * <p>Match the specified expression against the specified precompiled
150 * patterns. If there are no patterns, return the specified unrestricted
151 * return value; otherwise, return <code>true</code> if the expression
152 * matches one of the patterns, or <code>false</code> otherwise.</p>
153 *
154 * @param expr Expression to be tested
155 * @param patterns Array of <code>Pattern</code> to be tested against
156 * @param unrestricted Result to be returned if there are no matches
157 */
158 private boolean matches(String expr, String patterns[],
159 boolean unrestricted) {
160
161
162 if ((patterns == null) || (patterns.length == 0)) {
163 return unrestricted;
164 }
165
166
167 for (int i = 0; i < patterns.length; i++) {
168 if (patterns[i].startsWith("*")) {
169 if (expr.endsWith(patterns[i].substring(1))) {
170 return true;
171 }
172 } else if (patterns[i].endsWith("*")) {
173 if (expr.startsWith(patterns[i].substring(0, patterns[i].length() - 1))) {
174 return true;
175 }
176 } else {
177 if (patterns[i].equals(expr)) {
178 return true;
179 }
180 }
181 }
182
183
184 return false;
185
186 }
187
188
189 /***
190 * <p>Parse the specified string of comma-delimited URL pattern
191 * matching expressions into an array of patterns that can be processed
192 * at runtime more quickly. Valid patterns are the same as those
193 * supported for matching a request URI to a Processor instance:</p>
194 * <ul>
195 * <li>Must not be null or zero-length string</li>
196 * <li>EITHER must start with "/" and end with "/*"</li>
197 * <li>OR must start with "*." and not have any other period</li>
198 * </ul>
199 *
200 * @param expr Comma-delimited URL pattern matching expressions
201 *
202 * @exception IllegalArgumentException if an invalid pattern is encountered
203 */
204 private String[] precompile(String expr) {
205
206 if (expr == null) {
207 return new String[0];
208 }
209
210
211 String pattern = null;
212 StreamTokenizer st =
213 new StreamTokenizer(new StringReader(expr));
214 st.eolIsSignificant(false);
215 st.lowerCaseMode(false);
216 st.slashSlashComments(false);
217 st.slashStarComments(false);
218 st.wordChars(0x00, 0xff);
219 st.quoteChar('\'');
220 st.quoteChar('"');
221 st.whitespaceChars(0, ' ');
222 st.whitespaceChars(',', ',');
223 List list = new ArrayList();
224 int type = 0;
225
226
227 while (true) {
228
229
230 try {
231 type = st.nextToken();
232 } catch (IOException e) {
233 ;
234 }
235 if (type == StreamTokenizer.TT_EOF) {
236 break;
237 } else if (type == StreamTokenizer.TT_NUMBER) {
238 pattern = "" + st.nval;
239 } else if (type == StreamTokenizer.TT_WORD) {
240 pattern = st.sval.trim();
241 } else {
242 throw new IllegalArgumentException(expr);
243 }
244
245
246 if (pattern.length() < 1) {
247 throw new IllegalArgumentException(pattern);
248 }
249 if (pattern.startsWith("/")) {
250 if (!pattern.endsWith("/*")) {
251 throw new IllegalArgumentException(pattern);
252 }
253 } else if (pattern.startsWith("*.")) {
254 if (pattern.substring(2).indexOf('.') > 0) {
255 throw new IllegalArgumentException(pattern);
256 }
257 } else {
258 throw new IllegalArgumentException(pattern);
259 }
260
261
262 list.add(pattern);
263
264 }
265
266
267 return (String[]) list.toArray(new String[list.size()]);
268
269 }
270
271
272 }