KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > web > rewrite > RewriteRule


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2006, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22
23
24 package org.jboss.web.rewrite;
25
26 import java.util.Map JavaDoc;
27 import java.util.regex.Matcher JavaDoc;
28 import java.util.regex.Pattern JavaDoc;
29
30 public class RewriteRule {
31     
32     protected RewriteCond[] conditions = new RewriteCond[0];
33     
34     protected ThreadLocal JavaDoc pattern = new ThreadLocal JavaDoc();
35     protected Substitution substitution = null;
36     
37     protected String JavaDoc patternString = null;
38     protected String JavaDoc substitutionString = null;
39     
40     public void parse(Map JavaDoc maps) {
41         // Parse the substitution
42
if (!"-".equals(substitutionString)) {
43             substitution = new Substitution();
44             substitution.setSub(substitutionString);
45             substitution.parse(maps);
46         }
47         // Parse the pattern
48
int flags = 0;
49         if (isNocase()) {
50             flags |= Pattern.CASE_INSENSITIVE;
51         }
52         Pattern.compile(patternString, flags);
53         // Parse conditions
54
for (int i = 0; i < conditions.length; i++) {
55             conditions[i].parse(maps);
56         }
57     }
58     
59     public void addCondition(RewriteCond condition) {
60         RewriteCond[] conditions = new RewriteCond[this.conditions.length + 1];
61         for (int i = 0; i < this.conditions.length; i++) {
62             conditions[i] = this.conditions[i];
63         }
64         conditions[this.conditions.length] = condition;
65         this.conditions = conditions;
66     }
67     
68     /**
69      * Evaluate the rule based on the context
70      *
71      * @return null if no rewrite took place
72      */

73     public CharSequence JavaDoc evaluate(CharSequence JavaDoc url, Resolver resolver) {
74         Pattern JavaDoc pattern = (Pattern JavaDoc) this.pattern.get();
75         if (pattern == null) {
76             // Parse the pattern
77
int flags = 0;
78             if (isNocase()) {
79                 flags |= Pattern.CASE_INSENSITIVE;
80             }
81             pattern = Pattern.compile(patternString, flags);
82             this.pattern.set(pattern);
83         }
84         Matcher JavaDoc matcher = pattern.matcher(url);
85         if (!matcher.matches()) {
86             // Evaluation done
87
return null;
88         }
89         // Evaluate conditions
90
boolean done = false;
91         boolean rewrite = true;
92         Matcher JavaDoc lastMatcher = null;
93         int pos = 0;
94         while (!done) {
95             if (pos < conditions.length) {
96                 rewrite = conditions[pos].evaluate(matcher, lastMatcher, resolver);
97                 if (rewrite) {
98                     Matcher JavaDoc lastMatcher2 = conditions[pos].getMatcher();
99                     if (lastMatcher2 != null) {
100                         lastMatcher = lastMatcher2;
101                     }
102                 } else if (!conditions[pos].isOrnext()) {
103                     done = true;
104                 }
105                 pos++;
106             } else {
107                 done = true;
108             }
109         }
110         // Use the substitution to rewrite the url
111
if (rewrite) {
112             if (substitution != null) {
113                 return substitution.evaluate(matcher, lastMatcher, resolver);
114             } else {
115                 return url;
116             }
117         } else {
118             return null;
119         }
120     }
121
122     
123     /**
124      * String representation.
125      */

126     public String JavaDoc toString() {
127         // FIXME: Add flags if possible
128
return "RewriteRule " + patternString + " " + substitutionString;
129     }
130     
131     
132     /**
133      * This flag chains the current rule with the next rule (which itself
134      * can be chained with the following rule, etc.). This has the following
135      * effect: if a rule matches, then processing continues as usual, i.e.,
136      * the flag has no effect. If the rule does not match, then all following
137      * chained rules are skipped. For instance, use it to remove the ``.www''
138      * part inside a per-directory rule set when you let an external redirect
139      * happen (where the ``.www'' part should not to occur!).
140      */

141     protected boolean chain = false;
142     
143     /**
144      * This sets a cookie on the client's browser. The cookie's name is
145      * specified by NAME and the value is VAL. The domain field is the domain
146      * of the cookie, such as '.apache.org',the optional lifetime
147      * is the lifetime of the cookie in minutes, and the optional path is the
148      * path of the cookie
149      */

150     protected boolean cookie = false;
151     protected String JavaDoc cookieName = null;
152     protected String JavaDoc cookieValue = null;
153     
154     /**
155      * This forces an environment variable named VAR to be set to the value VAL,
156      * where VAL can contain regexp backreferences $N and %N which will be
157      * expanded. You can use this flag more than once to set more than one variable.
158      * The variables can be later dereferenced in many situations, but usually
159      * from within XSSI (via <!--#echo var="VAR"-->) or CGI (e.g. $ENV{'VAR'}).
160      * Additionally you can dereference it in a following RewriteCond pattern via
161      * %{ENV:VAR}. Use this to strip but remember information from URLs.
162      */

163     protected boolean env = false;
164     protected String JavaDoc envName = null;
165     protected String JavaDoc envValue = null;
166     
167     /**
168      * This forces the current URL to be forbidden, i.e., it immediately sends
169      * back a HTTP response of 403 (FORBIDDEN). Use this flag in conjunction
170      * with appropriate RewriteConds to conditionally block some URLs.
171      */

172     protected boolean forbidden = false;
173     
174     /**
175      * This forces the current URL to be gone, i.e., it immediately sends
176      * back a HTTP response of 410 (GONE). Use this flag to mark pages which
177      * no longer exist as gone.
178      */

179     protected boolean gone = false;
180     
181     /**
182      * Host. This means this rule and its associated conditions will apply to
183      * host, allowing host rewriting (ex: redirecting internally *.foo.com to
184      * bar.foo.com).
185      */

186     protected boolean host = false;
187     
188     /**
189      * Stop the rewriting process here and don't apply any more rewriting
190      * rules. This corresponds to the Perl last command or the break command
191      * from the C language. Use this flag to prevent the currently rewritten
192      * URL from being rewritten further by following rules. For example, use
193      * it to rewrite the root-path URL ('/') to a real one, e.g., '/e/www/'.
194      */

195     protected boolean last = false;
196     
197     /**
198      * Re-run the rewriting process (starting again with the first rewriting
199      * rule). Here the URL to match is again not the original URL but the URL
200      * from the last rewriting rule. This corresponds to the Perl next
201      * command or the continue command from the C language. Use this flag to
202      * restart the rewriting process, i.e., to immediately go to the top of
203      * the loop. But be careful not to create an infinite loop!
204      */

205     protected boolean next = false;
206     
207     /**
208      * This makes the Pattern case-insensitive, i.e., there is no difference
209      * between 'A-Z' and 'a-z' when Pattern is matched against the current
210      * URL.
211      */

212     protected boolean nocase = false;
213     
214     /**
215      * This flag keeps mod_rewrite from applying the usual URI escaping rules
216      * to the result of a rewrite. Ordinarily, special characters (such as
217      * '%', '$', ';', and so on) will be escaped into their hexcode
218      * equivalents ('%25', '%24', and '%3B', respectively); this flag
219      * prevents this from being done. This allows percent symbols to appear
220      * in the output, as in
221      * RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]
222      * which would turn '/foo/zed' into a safe request for '/bar?arg=P1=zed'.
223      */

224     protected boolean noescape = false;
225     
226     /**
227      * This flag forces the rewriting engine to skip a rewriting rule if the
228      * current request is an internal sub-request. For instance, sub-requests
229      * occur internally in Apache when mod_include tries to find out
230      * information about possible directory default files (index.xxx). On
231      * sub-requests it is not always useful and even sometimes causes a
232      * failure to if the complete set of rules are applied. Use this flag to
233      * exclude some rules. Use the following rule for your decision: whenever
234      * you prefix some URLs with CGI-scripts to force them to be processed by
235      * the CGI-script, the chance is high that you will run into problems (or
236      * even overhead) on sub-requests. In these cases, use this flag.
237      */

238     protected boolean nosubreq = false;
239     
240     /**
241      * This flag forces the substitution part to be internally forced as a proxy
242      * request and immediately (i.e., rewriting rule processing stops here) put
243      * through the proxy module. You have to make sure that the substitution string
244      * is a valid URI (e.g., typically starting with http://hostname) which can be
245      * handled by the Apache proxy module. If not you get an error from the proxy
246      * module. Use this flag to achieve a more powerful implementation of the
247      * ProxyPass directive, to map some remote stuff into the namespace of
248      * the local server.
249      * FIXME: Likely no impl for this, so replace with a redirect
250      */

251
252     /**
253      * FIMXE: No passthrough ?
254      */

255     
256     /**
257      * This flag forces the rewriting engine to append a query string part in
258      * the substitution string to the existing one instead of replacing it.
259      * Use this when you want to add more data to the query string via
260      * a rewrite rule.
261      */

262     protected boolean qsappend = false;
263     
264     /**
265      * Prefix Substitution with http://thishost[:thisport]/ (which makes the
266      * new URL a URI) to force a external redirection. If no code is given
267      * a HTTP response of 302 (MOVED TEMPORARILY) is used. If you want to
268      * use other response codes in the range 300-400 just specify them as
269      * a number or use one of the following symbolic names: temp (default),
270      * permanent, seeother. Use it for rules which should canonicalize the
271      * URL and give it back to the client, e.g., translate ``/~'' into ``/u/''
272      * or always append a slash to /u/user, etc. Note: When you use this flag,
273      * make sure that the substitution field is a valid URL! If not, you are
274      * redirecting to an invalid location! And remember that this flag itself
275      * only prefixes the URL with http://thishost[:thisport]/, rewriting
276      * continues. Usually you also want to stop and do the redirection
277      * immediately. To stop the rewriting you also have to provide the
278      * 'L' flag.
279      */

280     protected boolean redirect = false;
281     protected int redirectCode = 0;
282     
283     /**
284      * This flag forces the rewriting engine to skip the next num rules in
285      * sequence when the current rule matches. Use this to make pseudo
286      * if-then-else constructs: The last rule of the then-clause becomes
287      * skip=N where N is the number of rules in the else-clause.
288      * (This is not the same as the 'chain|C' flag!)
289      */

290     protected int skip = 0;
291     
292     /**
293      * Force the MIME-type of the target file to be MIME-type. For instance,
294      * this can be used to setup the content-type based on some conditions.
295      * For example, the following snippet allows .php files to be displayed
296      * by mod_php if they are called with the .phps extension:
297      * RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]
298      */

299     protected boolean type = false;
300     protected String JavaDoc typeValue = null;
301     public boolean isChain() {
302         return chain;
303     }
304     public void setChain(boolean chain) {
305         this.chain = chain;
306     }
307     public RewriteCond[] getConditions() {
308         return conditions;
309     }
310     public void setConditions(RewriteCond[] conditions) {
311         this.conditions = conditions;
312     }
313     public boolean isCookie() {
314         return cookie;
315     }
316     public void setCookie(boolean cookie) {
317         this.cookie = cookie;
318     }
319     public String JavaDoc getCookieName() {
320         return cookieName;
321     }
322     public void setCookieName(String JavaDoc cookieName) {
323         this.cookieName = cookieName;
324     }
325     public String JavaDoc getCookieValue() {
326         return cookieValue;
327     }
328     public void setCookieValue(String JavaDoc cookieValue) {
329         this.cookieValue = cookieValue;
330     }
331     public boolean isEnv() {
332         return env;
333     }
334     public void setEnv(boolean env) {
335         this.env = env;
336     }
337     public String JavaDoc getEnvName() {
338         return envName;
339     }
340     public void setEnvName(String JavaDoc envName) {
341         this.envName = envName;
342     }
343     public String JavaDoc getEnvValue() {
344         return envValue;
345     }
346     public void setEnvValue(String JavaDoc envValue) {
347         this.envValue = envValue;
348     }
349     public boolean isForbidden() {
350         return forbidden;
351     }
352     public void setForbidden(boolean forbidden) {
353         this.forbidden = forbidden;
354     }
355     public boolean isGone() {
356         return gone;
357     }
358     public void setGone(boolean gone) {
359         this.gone = gone;
360     }
361     public boolean isLast() {
362         return last;
363     }
364     public void setLast(boolean last) {
365         this.last = last;
366     }
367     public boolean isNext() {
368         return next;
369     }
370     public void setNext(boolean next) {
371         this.next = next;
372     }
373     public boolean isNocase() {
374         return nocase;
375     }
376     public void setNocase(boolean nocase) {
377         this.nocase = nocase;
378     }
379     public boolean isNoescape() {
380         return noescape;
381     }
382     public void setNoescape(boolean noescape) {
383         this.noescape = noescape;
384     }
385     public boolean isNosubreq() {
386         return nosubreq;
387     }
388     public void setNosubreq(boolean nosubreq) {
389         this.nosubreq = nosubreq;
390     }
391     public boolean isQsappend() {
392         return qsappend;
393     }
394     public void setQsappend(boolean qsappend) {
395         this.qsappend = qsappend;
396     }
397     public boolean isRedirect() {
398         return redirect;
399     }
400     public void setRedirect(boolean redirect) {
401         this.redirect = redirect;
402     }
403     public int getRedirectCode() {
404         return redirectCode;
405     }
406     public void setRedirectCode(int redirectCode) {
407         this.redirectCode = redirectCode;
408     }
409     public int getSkip() {
410         return skip;
411     }
412     public void setSkip(int skip) {
413         this.skip = skip;
414     }
415     public Substitution getSubstitution() {
416         return substitution;
417     }
418     public void setSubstitution(Substitution substitution) {
419         this.substitution = substitution;
420     }
421     public boolean isType() {
422         return type;
423     }
424     public void setType(boolean type) {
425         this.type = type;
426     }
427     public String JavaDoc getTypeValue() {
428         return typeValue;
429     }
430     public void setTypeValue(String JavaDoc typeValue) {
431         this.typeValue = typeValue;
432     }
433
434     public String JavaDoc getPatternString() {
435         return patternString;
436     }
437
438     public void setPatternString(String JavaDoc patternString) {
439         this.patternString = patternString;
440     }
441
442     public String JavaDoc getSubstitutionString() {
443         return substitutionString;
444     }
445
446     public void setSubstitutionString(String JavaDoc substitutionString) {
447         this.substitutionString = substitutionString;
448     }
449
450     public boolean isHost() {
451         return host;
452     }
453
454     public void setHost(boolean host) {
455         this.host = host;
456     }
457     
458 }
459
Popular Tags