KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.BufferedReader JavaDoc;
27 import java.io.File JavaDoc;
28 import java.io.FileInputStream JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.io.InputStream JavaDoc;
31 import java.io.InputStreamReader JavaDoc;
32 import java.io.StringReader JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.Hashtable JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.util.Map JavaDoc;
37 import java.util.StringTokenizer JavaDoc;
38
39 import javax.servlet.ServletException JavaDoc;
40 import javax.servlet.http.Cookie JavaDoc;
41 import javax.servlet.http.HttpServletResponse JavaDoc;
42
43 import org.apache.catalina.Container;
44 import org.apache.catalina.Context;
45 import org.apache.catalina.Engine;
46 import org.apache.catalina.Host;
47 import org.apache.catalina.Lifecycle;
48 import org.apache.catalina.LifecycleException;
49 import org.apache.catalina.LifecycleListener;
50 import org.apache.catalina.connector.Request;
51 import org.apache.catalina.connector.Response;
52 import org.apache.catalina.util.LifecycleSupport;
53 import org.apache.catalina.valves.ValveBase;
54 import org.apache.tomcat.util.buf.CharChunk;
55 import org.apache.tomcat.util.buf.MessageBytes;
56 import org.apache.tomcat.util.net.URL;
57
58 public class RewriteValve extends ValveBase
59     implements Lifecycle {
60
61     /**
62      * The lifecycle event support for this component.
63      */

64     protected LifecycleSupport lifecycle = new LifecycleSupport(this);
65
66     
67     /**
68      * The rewrite rules that the valve will use.
69      */

70     protected RewriteRule[] rules = null;
71     
72     
73     /**
74      * If rewriting occurs, the whole request will be processed again.
75      */

76     protected ThreadLocal JavaDoc invoked = new ThreadLocal JavaDoc();
77     
78     
79     /**
80      * Relative path to the configuration file.
81      * Note: If the valve's container is a context, this will be relative to
82      * /WEB-INF/.
83      */

84     protected String JavaDoc resourcePath = "rewrite.properties";
85
86     
87     /**
88      * Will be set to true if the valve is associated with a context.
89      */

90     protected boolean context = false;
91     
92     
93     /**
94      * Maps to be used by the rules.
95      */

96     protected Map JavaDoc maps = new Hashtable JavaDoc();
97     
98     
99     public void addLifecycleListener(LifecycleListener listener) {
100         lifecycle.addLifecycleListener(listener);
101     }
102
103     public LifecycleListener[] findLifecycleListeners() {
104         return lifecycle.findLifecycleListeners();
105     }
106
107     public void removeLifecycleListener(LifecycleListener listener) {
108         lifecycle.removeLifecycleListener(listener);
109     }
110
111     public void start() throws LifecycleException {
112
113         InputStream JavaDoc is = null;
114         
115         // Process configuration file for this valve
116
if (getContainer() instanceof Context) {
117             context = true;
118             is = ((Context) getContainer()).getServletContext()
119                 .getResourceAsStream("/WEB-INF/" + resourcePath);
120             if ((is == null) && (container.getLogger().isInfoEnabled())) {
121                 container.getLogger().info("No configuration resource found: /WEB-INF/" + resourcePath);
122             }
123         } else {
124             String JavaDoc resourceName = getHostConfigPath(resourcePath);
125             File JavaDoc file = new File JavaDoc(getConfigBase(), resourceName);
126             try {
127                 if (!file.exists()) {
128                     if (resourceName != null) {
129                         // Use getResource and getResourceAsStream
130
is = getClass().getClassLoader()
131                             .getResourceAsStream(resourceName);
132                         if (is != null && container.getLogger().isDebugEnabled()) {
133                             container.getLogger().debug("Read configuration from CL at " + resourceName);
134                         }
135                     }
136                 } else {
137                     if (container.getLogger().isDebugEnabled()) {
138                         container.getLogger().debug("Read configuration from " + file.getAbsolutePath());
139                     }
140                     is = new FileInputStream JavaDoc(file);
141                 }
142                 if ((is == null) && (container.getLogger().isInfoEnabled())) {
143                     container.getLogger().info("No configuration resource found: " + resourceName +
144                             " in " + getConfigBase().getAbsolutePath() + " or in the classloader");
145                 }
146             } catch (Exception JavaDoc e) {
147                 container.getLogger().error("Error opening configuration", e);
148             }
149         }
150         
151         if (is == null) {
152             // Will use management operations to configure the valve dynamically
153
return;
154         }
155         
156         BufferedReader JavaDoc reader = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(is));
157
158         try {
159             parse(reader);
160         } finally {
161             try {
162                 reader.close();
163             } catch (IOException JavaDoc e) {
164                 container.getLogger().error("Error closing configuration", e);
165             }
166             try {
167                 if (is != null) {
168                     is.close();
169                 }
170             } catch (IOException JavaDoc e) {
171                 container.getLogger().error("Error closing configuration", e);
172             }
173         }
174
175     }
176
177     public void setConfiguration(String JavaDoc configuration)
178         throws Exception JavaDoc {
179         maps.clear();
180         parse(new BufferedReader JavaDoc(new StringReader JavaDoc(configuration)));
181     }
182     
183     public String JavaDoc getConfiguration() {
184         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
185         // FIXME: Output maps if possible
186
for (int i = 0; i < rules.length; i++) {
187             for (int j = 0; j < rules[i].getConditions().length; j++) {
188                 buffer.append(rules[i].getConditions()[j].toString()).append("\r\n");
189             }
190             buffer.append(rules[i].toString()).append("\r\n").append("\r\n");
191         }
192         return buffer.toString();
193     }
194     
195     protected void parse(BufferedReader JavaDoc reader) throws LifecycleException {
196         ArrayList JavaDoc rules = new ArrayList JavaDoc();
197         ArrayList JavaDoc conditions = new ArrayList JavaDoc();
198         while (true) {
199             try {
200                 String JavaDoc line = reader.readLine();
201                 if (line == null) {
202                     break;
203                 }
204                 Object JavaDoc result = parse(line);
205                 if (result instanceof RewriteRule) {
206                     RewriteRule rule = (RewriteRule) result;
207                     if (container.getLogger().isDebugEnabled()) {
208                         container.getLogger().debug("Add rule with pattern " + rule.getPatternString()
209                                 + " and substitution " + rule.getSubstitutionString());
210                     }
211                     for (int i = 0; i < conditions.size(); i++) {
212                         if (container.getLogger().isDebugEnabled()) {
213                             RewriteCond cond = (RewriteCond) conditions.get(i);
214                             container.getLogger().debug("Add condition " + cond.getCondPattern()
215                                     + " test " + cond.getTestString() + " to rule with pattern "
216                                     + rule.getPatternString() + " and substitution "
217                                     + rule.getSubstitutionString());
218                         }
219                         rule.addCondition((RewriteCond) conditions.get(i));
220                     }
221                     conditions.clear();
222                     rules.add(rule);
223                 } else if (result instanceof RewriteCond) {
224                     conditions.add(result);
225                 } else if (result instanceof Object JavaDoc[]) {
226                     String JavaDoc mapName = (String JavaDoc) ((Object JavaDoc[]) result)[0];
227                     RewriteMap map = (RewriteMap) ((Object JavaDoc[]) result)[1];
228                     maps.put(mapName, map);
229                     if (map instanceof Lifecycle) {
230                         ((Lifecycle) map).start();
231                     }
232                 }
233             } catch (IOException JavaDoc e) {
234                 container.getLogger().error("Error reading configuration", e);
235             }
236         }
237         this.rules = (RewriteRule[]) rules.toArray(new RewriteRule[0]);
238         
239         // Finish parsing the rules
240
for (int i = 0; i < this.rules.length; i++) {
241             this.rules[i].parse(maps);
242         }
243     }
244
245     public void stop() throws LifecycleException {
246         Iterator JavaDoc values = maps.values().iterator();
247         while (values.hasNext()) {
248             RewriteMap map = (RewriteMap) values.next();
249             if (map instanceof Lifecycle) {
250                 ((Lifecycle) map).stop();
251             }
252         }
253         maps.clear();
254         rules = null;
255     }
256
257
258     public void invoke(Request request, Response JavaDoc response)
259         throws IOException JavaDoc, ServletException JavaDoc {
260
261         if (rules == null || rules.length == 0) {
262             getNext().invoke(request, response);
263             return;
264         }
265         
266         if (invoked.get() == Boolean.TRUE) {
267             getNext().invoke(request, response);
268             invoked.set(null);
269             return;
270         }
271         
272         TomcatResolver resolver = new TomcatResolver(request);
273         
274         invoked.set(Boolean.TRUE);
275         
276         // As long as MB isn't a char sequence or affiliated, this has to be
277
// converted to a string
278
MessageBytes urlMB = context ? request.getRequestPathMB() : request.getDecodedRequestURIMB();
279         urlMB.toChars();
280         CharSequence JavaDoc url = urlMB.getCharChunk();
281         CharSequence JavaDoc host = request.getServerName();
282         boolean rewritten = false;
283         boolean done = false;
284         for (int i = 0; i < rules.length; i++) {
285             CharSequence JavaDoc test = (rules[i].isHost()) ? host : url;
286             CharSequence JavaDoc newtest = rules[i].evaluate(test, resolver);
287             if (newtest != null && !test.equals(newtest.toString())) {
288                 if (container.getLogger().isDebugEnabled()) {
289                     container.getLogger().debug("Rewrote " + test + " as " + newtest
290                             + " with rule pattern " + rules[i].getPatternString());
291                 }
292                 if (rules[i].isHost()) {
293                     host = newtest;
294                 } else {
295                     url = newtest;
296                 }
297                 rewritten = true;
298             }
299
300             // Final reply
301

302             // - forbidden
303
if (rules[i].isForbidden() && newtest != null) {
304                 response.sendError(HttpServletResponse.SC_FORBIDDEN);
305                 done = true;
306                 break;
307             }
308             // - gone
309
if (rules[i].isGone() && newtest != null) {
310                 response.sendError(HttpServletResponse.SC_GONE);
311                 done = true;
312                 break;
313             }
314             // - redirect (code)
315
if (rules[i].isRedirect() && newtest != null) {
316                 // append the query string to the url if there is one and it hasn't been rewritten
317
String JavaDoc queryString = request.getQueryString();
318                 StringBuffer JavaDoc urlString = new StringBuffer JavaDoc(url);
319                 if (queryString != null && queryString.length() > 0) {
320                     int index = urlString.indexOf("?");
321                     if (index != -1) {
322                         // if qsa is specified append the query
323
if (rules[i].isQsappend()) {
324                             urlString.append('&');
325                             urlString.append(queryString);
326                         }
327                         // if the ? is the last character delete it, its only purpose was to
328
// prevent the rewrite module from appending the query string
329
else if (index == urlString.length() - 1) {
330                             urlString.deleteCharAt(index);
331                         }
332                     } else {
333                         urlString.append('?');
334                         urlString.append(queryString);
335                     }
336                 }
337                 // Insert the context if
338
// 1. this valve is associated with a context
339
// 2. the url starts with a leading slash
340
// 3. the url isn't absolute
341
if (context && urlString.charAt(0) == '/' && !hasScheme(urlString)) {
342                     urlString.insert(0, request.getContext().getEncodedPath());
343                 }
344                 response.sendRedirect(urlString.toString());
345                 done = true;
346                 break;
347             }
348             
349             // Reply modification
350

351             // - cookie
352
if (rules[i].isCookie() && newtest != null) {
353                 response.addCookie(new Cookie JavaDoc(rules[i].getCookieName(),
354                         rules[i].getCookieValue()));
355                 // FIXME: Cookie impl for other parameters
356
}
357             // - env (note: this sets a system property)
358
if (rules[i].isEnv() && newtest != null) {
359                 System.setProperty(rules[i].getEnvName(), rules[i].getEnvValue());
360             }
361             // - content type (note: this will not force the content type, use a filter
362
// to do that)
363
if (rules[i].isType() && newtest != null) {
364                 request.setContentType(rules[i].getTypeValue());
365             }
366             // - qsappend
367
if (rules[i].isQsappend() && newtest != null) {
368                 String JavaDoc queryString = request.getQueryString();
369                 String JavaDoc urlString = url.toString();
370                 if (urlString.indexOf('?') != -1 && queryString != null) {
371                     url = urlString + "&" + queryString;
372                 }
373             }
374             
375             // Control flow processing
376

377             // - chain (skip remaining chained rules if this one does not match)
378
if (rules[i].isChain() && newtest == null) {
379                 for (int j = i; j < rules.length; j++) {
380                     if (!rules[j].isChain()) {
381                         i = j;
382                         break;
383                     }
384                 }
385                 continue;
386             }
387             // - last (stop rewriting here)
388
if (rules[i].isLast() && newtest != null) {
389                 break;
390             }
391             // - next (redo again)
392
if (rules[i].isNext() && newtest != null) {
393                 i = 0;
394                 continue;
395             }
396             // - skip (n rules)
397
if (newtest != null) {
398                 i += rules[i].getSkip();
399             }
400             
401         }
402         
403         if (rewritten) {
404             if (!done) {
405                 // See if we need to replace the query string
406
String JavaDoc urlString = url.toString();
407                 String JavaDoc queryString = null;
408                 int queryIndex = urlString.indexOf('?');
409                 if (queryIndex != -1) {
410                     queryString = urlString.substring(queryIndex+1);
411                     urlString = urlString.substring(0, queryIndex);
412                 }
413                 // Set the new URL
414
CharChunk chunk = request.getCoyoteRequest().requestURI().getCharChunk();
415                 chunk.recycle();
416                 if (context) {
417                     chunk.append(request.getContextPath());
418                 }
419                 chunk.append(urlString);
420                 request.getCoyoteRequest().requestURI().toChars();
421                 // Set the new Query if there is one
422
if (queryString != null) {
423                     chunk = request.getCoyoteRequest().queryString().getCharChunk();
424                     chunk.recycle();
425                     chunk.append(queryString);
426                     request.getCoyoteRequest().queryString().toChars();
427                 }
428                 // Set the new host if it changed
429
if (!host.equals(request.getServerName())) {
430                     chunk = request.getCoyoteRequest().serverName().getCharChunk();
431                     chunk.recycle();
432                     chunk.append(host.toString());
433                     request.getCoyoteRequest().serverName().toChars();
434                 }
435                 request.getMappingData().recycle();
436                 // Reinvoke the whole request recursively
437
try {
438                     request.getConnector().getProtocolHandler().getAdapter().service
439                         (request.getCoyoteRequest(), response.getCoyoteResponse());
440                 } catch (Exception JavaDoc e) {
441                     // This doesn't actually happen in the Catalina adapter implementation
442
}
443             }
444         } else {
445             getNext().invoke(request, response);
446         }
447         
448         invoked.set(null);
449         
450     }
451     
452     
453     /**
454      * Get config base.
455      */

456     protected File JavaDoc getConfigBase() {
457         File JavaDoc configBase =
458             new File JavaDoc(System.getProperty("catalina.base"), "conf");
459         if (!configBase.exists()) {
460             return null;
461         } else {
462             return configBase;
463         }
464     }
465
466     
467     /**
468      * Find the configuration path where the rewrite configuration file
469      * will be stored.
470      *
471      * @param resourceName
472      * @return
473      */

474     protected String JavaDoc getHostConfigPath(String JavaDoc resourceName) {
475         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
476         Container container = getContainer();
477         Container host = null;
478         Container engine = null;
479         while (container != null) {
480             if (container instanceof Host)
481                 host = container;
482             if (container instanceof Engine)
483                 engine = container;
484             container = container.getParent();
485         }
486         if (engine != null) {
487             result.append(engine.getName()).append('/');
488         }
489         if (host != null) {
490             result.append(host.getName()).append('/');
491         }
492         result.append(resourceName);
493         return result.toString();
494     }
495
496     
497     /**
498      * This factory method will parse a line formed like:
499      *
500      * Example:
501      * RewriteCond %{REMOTE_HOST} ^host1.* [OR]
502      *
503      * @param line
504      * @return
505      */

506     public static Object JavaDoc parse(String JavaDoc line) {
507         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(line);
508         if (tokenizer.hasMoreTokens()) {
509             String JavaDoc token = tokenizer.nextToken();
510             if (token.equals("RewriteCond")) {
511                 // RewriteCond TestString CondPattern [Flags]
512
RewriteCond condition = new RewriteCond();
513                 if (tokenizer.countTokens() < 2) {
514                     throw new IllegalArgumentException JavaDoc("Ivalid line: " + line);
515                 }
516                 condition.setTestString(tokenizer.nextToken());
517                 condition.setCondPattern(tokenizer.nextToken());
518                 if (tokenizer.hasMoreTokens()) {
519                     String JavaDoc flags = tokenizer.nextToken();
520                     if (flags.startsWith("[") && flags.endsWith("]")) {
521                         flags = flags.substring(1, flags.length() - 1);
522                     }
523                     StringTokenizer JavaDoc flagsTokenizer = new StringTokenizer JavaDoc(flags, ",");
524                     while (flagsTokenizer.hasMoreElements()) {
525                         parseCondFlag(line, condition, flagsTokenizer.nextToken());
526                     }
527                 }
528                 return condition;
529             } else if (token.equals("RewriteRule")) {
530                 // RewriteRule Pattern Substitution [Flags]
531
RewriteRule rule = new RewriteRule();
532                 if (tokenizer.countTokens() < 2) {
533                     throw new IllegalArgumentException JavaDoc("Ivalid line: " + line);
534                 }
535                 rule.setPatternString(tokenizer.nextToken());
536                 rule.setSubstitutionString(tokenizer.nextToken());
537                 if (tokenizer.hasMoreTokens()) {
538                     String JavaDoc flags = tokenizer.nextToken();
539                     if (flags.startsWith("[") && flags.endsWith("]")) {
540                         flags = flags.substring(1, flags.length() - 1);
541                     }
542                     StringTokenizer JavaDoc flagsTokenizer = new StringTokenizer JavaDoc(flags, ",");
543                     while (flagsTokenizer.hasMoreElements()) {
544                         parseRuleFlag(line, rule, flagsTokenizer.nextToken());
545                     }
546                 }
547                 return rule;
548             } else if (token.equals("RewriteMap")) {
549                 // RewriteMap name rewriteMapClassName whateverOptionalParameterInWhateverFormat
550
if (tokenizer.countTokens() < 2) {
551                     throw new IllegalArgumentException JavaDoc("Ivalid line: " + line);
552                 }
553                 String JavaDoc name = tokenizer.nextToken();
554                 String JavaDoc rewriteMapClassName = tokenizer.nextToken();
555                 RewriteMap map = null;
556                 try {
557                     map = (RewriteMap) (Class.forName(rewriteMapClassName).newInstance());
558                 } catch (Exception JavaDoc e) {
559                     throw new IllegalArgumentException JavaDoc("Ivalid map className: " + line);
560                 }
561                 if (tokenizer.hasMoreTokens()) {
562                     map.setParameters(tokenizer.nextToken());
563                 }
564                 Object JavaDoc[] result = new Object JavaDoc[2];
565                 result[0] = name;
566                 result[1] = map;
567                 return result;
568             } else if (token.startsWith("#")) {
569                 // it's a comment, ignore it
570
} else {
571                 throw new IllegalArgumentException JavaDoc("Invalid line: " + line);
572             }
573         }
574         return null;
575     }
576     
577     
578     /**
579      * Parser for RewriteCond flags.
580      *
581      * @param condition
582      * @param flag
583      */

584     protected static void parseCondFlag(String JavaDoc line, RewriteCond condition, String JavaDoc flag) {
585         if (flag.equals("NC") || flag.equals("nocase")) {
586             condition.setNocase(true);
587         } else if (flag.equals("OR") || flag.equals("ornext")) {
588             condition.setOrnext(true);
589         } else {
590             throw new IllegalArgumentException JavaDoc("Ivalid flag in: " + line + " flags: " + flag);
591         }
592     }
593     
594     
595     /**
596      * Parser for ReweriteRule flags.
597      *
598      * @param rule
599      * @param flag
600      */

601     protected static void parseRuleFlag(String JavaDoc line, RewriteRule rule, String JavaDoc flag) {
602         if (flag.equals("chain") || flag.equals("C")) {
603             rule.setChain(true);
604         } else if (flag.startsWith("cookie=") || flag.startsWith("C=")) {
605             rule.setCookie(true);
606             if (flag.startsWith("cookie")) {
607                 flag = flag.substring("cookie=".length());
608             } else if (flag.startsWith("C=")) {
609                 flag = flag.substring("C=".length());
610             }
611             int pos = flag.indexOf(':');
612             if (pos == -1 || (pos + 1) == flag.length()) {
613                 throw new IllegalArgumentException JavaDoc("Ivalid flag in: " + line);
614             }
615             rule.setCookieName(flag.substring(0, pos));
616             rule.setCookieValue(flag.substring(pos + 1));
617         } else if (flag.startsWith("env=") || flag.startsWith("E=")) {
618             rule.setEnv(true);
619             if (flag.startsWith("env=")) {
620                 flag = flag.substring("env=".length());
621             } else if (flag.startsWith("E=")) {
622                 flag = flag.substring("E=".length());
623             }
624             int pos = flag.indexOf(':');
625             if (pos == -1 || (pos + 1) == flag.length()) {
626                 throw new IllegalArgumentException JavaDoc("Ivalid flag in: " + line);
627             }
628             rule.setEnvName(flag.substring(0, pos));
629             rule.setEnvValue(flag.substring(pos + 1));
630         } else if (flag.startsWith("forbidden") || flag.startsWith("F")) {
631             rule.setForbidden(true);
632         } else if (flag.startsWith("gone") || flag.startsWith("G")) {
633             rule.setGone(true);
634         } else if (flag.startsWith("host") || flag.startsWith("H")) {
635             rule.setHost(true);
636         } else if (flag.startsWith("last") || flag.startsWith("L")) {
637             rule.setLast(true);
638         } else if (flag.startsWith("next") || flag.startsWith("N")) {
639             rule.setNext(true);
640         } else if (flag.startsWith("nocase") || flag.startsWith("NC")) {
641             rule.setNocase(true);
642         } else if (flag.startsWith("noescape") || flag.startsWith("NE")) {
643             rule.setNoescape(true);
644         } else if (flag.startsWith("proxy") || flag.startsWith("P")) {
645             // FIXME: Proxy not supported at the moment, would require proxy
646
// capabilities
647
//rule.setProxy(true);
648
} else if (flag.startsWith("qsappend") || flag.startsWith("QSA")) {
649             rule.setQsappend(true);
650         } else if (flag.startsWith("redirect") || flag.startsWith("R")) {
651             if (flag.startsWith("redirect=")) {
652                 flag = flag.substring("redirect=".length());
653                 rule.setRedirect(true);
654                 rule.setRedirectCode(Integer.parseInt(flag));
655             } else if (flag.startsWith("R=")) {
656                 flag = flag.substring("R=".length());
657                 rule.setRedirect(true);
658                 rule.setRedirectCode(Integer.parseInt(flag));
659             } else {
660                 rule.setRedirect(true);
661                 rule.setRedirectCode(HttpServletResponse.SC_FOUND);
662             }
663         } else if (flag.startsWith("skip") || flag.startsWith("S")) {
664             if (flag.startsWith("skip=")) {
665                 flag = flag.substring("skip=".length());
666             } else if (flag.startsWith("S=")) {
667                 flag = flag.substring("S=".length());
668             }
669             rule.setSkip(Integer.parseInt(flag));
670         } else if (flag.startsWith("type") || flag.startsWith("T")) {
671             if (flag.startsWith("type=")) {
672                 flag = flag.substring("type=".length());
673             } else if (flag.startsWith("T=")) {
674                 flag = flag.substring("T=".length());
675             }
676             rule.setType(true);
677             rule.setTypeValue(flag);
678         } else {
679             throw new IllegalArgumentException JavaDoc("Invalid flag in: " + line + " flag: " + flag);
680         }
681     }
682     
683
684     /**
685      * Determine if a URI string has a <code>scheme</code> component.
686      */

687     protected static boolean hasScheme(StringBuffer JavaDoc uri) {
688         int len = uri.length();
689         for(int i=0; i < len ; i++) {
690             char c = uri.charAt(i);
691             if(c == ':') {
692                 return i > 0;
693             } else if(!URL.isSchemeChar(c)) {
694                 return false;
695             }
696         }
697         return false;
698     }
699
700 }
701
Popular Tags