From: <jbo...@li...> - 2005-11-02 14:27:54
|
Author: rem...@jb... Date: 2005-11-02 09:27:40 -0500 (Wed, 02 Nov 2005) New Revision: 1486 Modified: trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/Resolver.java trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteCond.java trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteMap.java trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteRule.java trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteTestCase.java trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteValve.java trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/Substitution.java trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/TomcatResolver.java Log: - Add license. - Add some of the missing features (map parsing, some cookie support, host rewriting), but test cases are not done yet. Modified: trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/Resolver.java =================================================================== --- trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/Resolver.java 2005-11-02 14:04:15 UTC (rev 1485) +++ trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/Resolver.java 2005-11-02 14:27:40 UTC (rev 1486) @@ -1,3 +1,20 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package org.jboss.web.rewrite; public abstract class Resolver { @@ -12,4 +29,6 @@ public abstract String resolveHttp(String key); + public abstract boolean resolveResource(int type, String name); + } \ No newline at end of file Modified: trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteCond.java =================================================================== --- trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteCond.java 2005-11-02 14:04:15 UTC (rev 1485) +++ trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteCond.java 2005-11-02 14:27:40 UTC (rev 1486) @@ -1,3 +1,20 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package org.jboss.web.rewrite; import java.util.Map; @@ -48,6 +65,28 @@ } } + public class ResourceCondition extends Condition { + /** + * 0: -d (is directory ?) + * 1: -f (is regular file ?) + * 2: -s (is regular file with size ?) + */ + public int type = 0; + public boolean evaluate(String value, Resolver resolver) { + switch (type) { + case 0: + return true; + case 1: + return true; + case 2: + return true; + default: + return false; + } + + } + } + protected String testString = null; protected String condPattern = null; @@ -71,7 +110,6 @@ test = new Substitution(); test.setSub(testString); test.parse(maps); - // FIXME: Support for the other special condition patterns if (condPattern.startsWith("!")) { positive = false; condPattern = condPattern.substring(1); @@ -88,6 +126,15 @@ LexicalCondition condition = new LexicalCondition(); condition.type = 0; condition.condition = condPattern.substring(1); + } else if (condPattern.equals("-d")) { + ResourceCondition ncondition = new ResourceCondition(); + ncondition.type = 0; + } else if (condPattern.equals("-f")) { + ResourceCondition ncondition = new ResourceCondition(); + ncondition.type = 1; + } else if (condPattern.equals("-s")) { + ResourceCondition ncondition = new ResourceCondition(); + ncondition.type = 2; } else { PatternCondition condition = new PatternCondition(); int flags = 0; @@ -147,7 +194,6 @@ } Condition condition = (Condition) this.condition.get(); if (condition == null) { - // FIXME: Support for the other special condition patterns if (condPattern.startsWith("<")) { LexicalCondition ncondition = new LexicalCondition(); ncondition.type = -1; @@ -163,6 +209,18 @@ ncondition.type = 0; ncondition.condition = condPattern.substring(1); condition = ncondition; + } else if (condPattern.equals("-d")) { + ResourceCondition ncondition = new ResourceCondition(); + ncondition.type = 0; + condition = ncondition; + } else if (condPattern.equals("-f")) { + ResourceCondition ncondition = new ResourceCondition(); + ncondition.type = 1; + condition = ncondition; + } else if (condPattern.equals("-s")) { + ResourceCondition ncondition = new ResourceCondition(); + ncondition.type = 2; + condition = ncondition; } else { PatternCondition ncondition = new PatternCondition(); int flags = 0; Modified: trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteMap.java =================================================================== --- trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteMap.java 2005-11-02 14:04:15 UTC (rev 1485) +++ trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteMap.java 2005-11-02 14:27:40 UTC (rev 1486) @@ -1,3 +1,20 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package org.jboss.web.rewrite; public interface RewriteMap { @@ -2,2 +19,4 @@ + public String setParameters(String params); + public String lookup(String key); Modified: trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteRule.java =================================================================== --- trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteRule.java 2005-11-02 14:04:15 UTC (rev 1485) +++ trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteRule.java 2005-11-02 14:27:40 UTC (rev 1486) @@ -1,3 +1,20 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package org.jboss.web.rewrite; import java.util.Map; @@ -156,8 +173,11 @@ protected boolean gone = false; /** - * FIXME: Content handler ????? + * Host. This means this rule and its associated conditions will apply to + * host, allowing host rewriting (ex: redirecting internally *.foo.com to + * bar.foo.com). */ + protected boolean host = false; /** * Stop the rewriting process here and don't apply any more rewriting @@ -420,5 +440,13 @@ public void setSubstitutionString(String substitutionString) { this.substitutionString = substitutionString; } + + public boolean isHost() { + return host; + } + + public void setHost(boolean host) { + this.host = host; + } } Modified: trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteTestCase.java =================================================================== --- trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteTestCase.java 2005-11-02 14:04:15 UTC (rev 1485) +++ trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteTestCase.java 2005-11-02 14:27:40 UTC (rev 1486) @@ -1,3 +1,20 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package org.jboss.web.rewrite; import junit.framework.Test; @@ -20,6 +37,10 @@ return "ssl_property_value[" + key + "]"; } + public boolean resolveResource(int type, String name) { + return true; + } + } /** Modified: trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteValve.java =================================================================== --- trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteValve.java 2005-11-02 14:04:15 UTC (rev 1485) +++ trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/RewriteValve.java 2005-11-02 14:27:40 UTC (rev 1486) @@ -1,3 +1,20 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package org.jboss.web.rewrite; import java.io.BufferedReader; @@ -12,6 +29,7 @@ import java.util.StringTokenizer; import javax.servlet.ServletException; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import org.apache.catalina.Container; @@ -21,7 +39,6 @@ import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleListener; -import org.apache.catalina.connector.Connector; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.util.LifecycleSupport; @@ -219,23 +236,29 @@ // As long as MB isn't a char sequence or affiliated, this has to be // converted to a string String url = context ? request.getRequestPathMB().toString() : request.getDecodedRequestURI(); + String host = request.getServerName(); boolean rewritten = false; boolean done = false; for (int i = 0; i < rules.length; i++) { - CharSequence newurl = rules[i].evaluate(url, resolver); - if (newurl != null && !url.equals(newurl.toString())) { + String test = (rules[i].isHost()) ? host : url; + CharSequence newtest = rules[i].evaluate(test, resolver); + if (newtest != null && !test.equals(newtest.toString())) { if (container.getLogger().isDebugEnabled()) { - container.getLogger().debug("Rewrote " + url + " as " + newurl + container.getLogger().debug("Rewrote " + test + " as " + newtest + " with rule pattern " + rules[i].getPatternString()); } - url = newurl.toString(); + if (rules[i].isHost()) { + host = newtest.toString(); + } else { + url = newtest.toString(); + } rewritten = true; } // Control flow processing // - chain (skip remaining chained rules if this one does not match) - if (rules[i].isChain() && newurl == null) { + if (rules[i].isChain() && newtest == null) { for (int j = i; j < rules.length; j++) { if (!rules[j].isChain()) { i = j; @@ -244,33 +267,33 @@ } } // - last (stop rewriting here) - if (rules[i].isLast() && newurl != null) { + if (rules[i].isLast() && newtest != null) { break; } // - next (redo again) - if (rules[i].isNext() && newurl != null) { + if (rules[i].isNext() && newtest != null) { i = 0; } // - skip (n rules) - if (newurl != null) { + if (newtest != null) { i += rules[i].getSkip(); } // Final reply: // - forbidden - if (rules[i].isForbidden() && newurl != null) { + if (rules[i].isForbidden() && newtest != null) { response.sendError(HttpServletResponse.SC_FORBIDDEN); done = true; break; } // - gone - if (rules[i].isGone() && newurl != null) { + if (rules[i].isGone() && newtest != null) { response.sendError(HttpServletResponse.SC_GONE); done = true; break; } // - redirect (code) - if (rules[i].isRedirect() && newurl != null) { + if (rules[i].isRedirect() && newtest != null) { // Note: No way to specify the status code here response.sendRedirect(url); done = true; @@ -279,20 +302,24 @@ // Reply modification: // - cookie - if (rules[i].isCookie() && newurl != null) { - // FIXME: Cookie impl + if (rules[i].isCookie() && newtest != null) { + response.addCookie(new Cookie(rules[i].getCookieName(), + rules[i].getCookieValue())); + // FIXME: Cookie impl for other parameters } - // - env (note: this sets a request attribute) - if (rules[i].isEnv() && newurl != null) { - request.setAttribute(rules[i].getEnvName(), rules[i].getEnvValue()); + // - env (note: this sets a system property) + if (rules[i].isEnv() && newtest != null) { + System.setProperty(rules[i].getEnvName(), rules[i].getEnvValue()); } // - content type (note: this will not force the content type, use a filter // to do that) - if (rules[i].isType() && newurl != null) { + if (rules[i].isType() && newtest != null) { request.setContentType(rules[i].getTypeValue()); } // - qsappend - // FIXME: Append to query string ? + // FIXME: Append to query string ? In general, some query string handling is + // apparently needed, which feels weird (in Servlet API land, the query + // string is separate) } @@ -306,6 +333,13 @@ } chunk.append(url); request.getCoyoteRequest().requestURI().toChars(); + // Set the new host if it changed + if (!host.equals(request.getServerName())) { + chunk = request.getCoyoteRequest().serverName().getCharChunk(); + chunk.recycle(); + chunk.append(host); + request.getCoyoteRequest().serverName().toChars(); + } // Reinvoke the whole request recursively try { request.getConnector().getProtocolHandler().getAdapter().service @@ -369,21 +403,22 @@ /** * This factory method will parse a line formed like: - * RewriteCond TestString CondPattern [Flags] + * * Example: * RewriteCond %{REMOTE_HOST} ^host1.* [OR] * - * @param rewriteCond + * @param line * @return */ - public static Object parse(String rewriteCond) { - StringTokenizer tokenizer = new StringTokenizer(rewriteCond); + public static Object parse(String line) { + StringTokenizer tokenizer = new StringTokenizer(line); if (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); if (token.equals("RewriteCond")) { + // RewriteCond TestString CondPattern [Flags] RewriteCond condition = new RewriteCond(); if (tokenizer.countTokens() < 2) { - throw new IllegalArgumentException("Ivalid line: " + rewriteCond); + throw new IllegalArgumentException("Ivalid line: " + line); } condition.setTestString(tokenizer.nextToken()); condition.setCondPattern(tokenizer.nextToken()); @@ -394,14 +429,15 @@ } StringTokenizer flagsTokenizer = new StringTokenizer(flags, ","); while (flagsTokenizer.hasMoreElements()) { - parseCondFlag(rewriteCond, condition, flagsTokenizer.nextToken()); + parseCondFlag(line, condition, flagsTokenizer.nextToken()); } } return condition; } else if (token.equals("RewriteRule")) { + // RewriteRule Pattern Substitution [Flags] RewriteRule rule = new RewriteRule(); if (tokenizer.countTokens() < 2) { - throw new IllegalArgumentException("Ivalid line: " + rewriteCond); + throw new IllegalArgumentException("Ivalid line: " + line); } rule.setPatternString(tokenizer.nextToken()); rule.setSubstitutionString(tokenizer.nextToken()); @@ -412,15 +448,32 @@ } StringTokenizer flagsTokenizer = new StringTokenizer(flags, ","); while (flagsTokenizer.hasMoreElements()) { - parseRuleFlag(rewriteCond, rule, flagsTokenizer.nextToken()); + parseRuleFlag(line, rule, flagsTokenizer.nextToken()); } } return rule; } else if (token.equals("RewriteMap")) { - // FIXME: Map parsing: return an Object[2] with 0:name 1:RewriteMap - // RewriteMap name rewriteMapClassName;whateverParameterInWhateverFormat + // RewriteMap name rewriteMapClassName whateverOptionalParameterInWhateverFormat + if (tokenizer.countTokens() < 2) { + throw new IllegalArgumentException("Ivalid line: " + line); + } + String name = tokenizer.nextToken(); + String rewriteMapClassName = tokenizer.nextToken(); + RewriteMap map = null; + try { + map = (RewriteMap) (Class.forName(rewriteMapClassName).newInstance()); + } catch (Exception e) { + throw new IllegalArgumentException("Ivalid map className: " + line); + } + if (tokenizer.hasMoreTokens()) { + map.setParameters(tokenizer.nextToken()); + } + Object[] result = new Object[2]; + result[0] = name; + result[1] = map; + return result; } else { - throw new IllegalArgumentException("Ivalid line: " + rewriteCond); + throw new IllegalArgumentException("Ivalid line: " + line); } } return null; @@ -455,7 +508,17 @@ rule.setChain(true); } else if (flag.startsWith("cookie=") || flag.startsWith("C=")) { rule.setCookie(true); - // FIXME: Parse cookie + if (flag.startsWith("cookie")) { + flag = flag.substring("cookie=".length()); + } else if (flag.startsWith("C=")) { + flag = flag.substring("C=".length()); + } + int pos = flag.indexOf(':'); + if (pos == -1 || (pos + 1) == flag.length()) { + throw new IllegalArgumentException("Ivalid flag in: " + line); + } + rule.setCookieName(flag.substring(0, pos)); + rule.setCookieValue(flag.substring(pos + 1)); } else if (flag.startsWith("env=") || flag.startsWith("E=")) { rule.setEnv(true); if (flag.startsWith("env=")) { @@ -473,6 +536,8 @@ rule.setForbidden(true); } else if (flag.startsWith("gone") || flag.startsWith("G")) { rule.setGone(true); + } else if (flag.startsWith("host") || flag.startsWith("H")) { + rule.setHost(true); } else if (flag.startsWith("last") || flag.startsWith("L")) { rule.setLast(true); } else if (flag.startsWith("next") || flag.startsWith("N")) { Modified: trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/Substitution.java =================================================================== --- trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/Substitution.java 2005-11-02 14:04:15 UTC (rev 1485) +++ trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/Substitution.java 2005-11-02 14:27:40 UTC (rev 1486) @@ -1,3 +1,20 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package org.jboss.web.rewrite; import java.util.ArrayList; Modified: trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/TomcatResolver.java =================================================================== --- trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/TomcatResolver.java 2005-11-02 14:04:15 UTC (rev 1485) +++ trunk/labs/jbossweb/src/share/classes/org/jboss/web/rewrite/TomcatResolver.java 2005-11-02 14:27:40 UTC (rev 1486) @@ -1,3 +1,20 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package org.jboss.web.rewrite; import org.apache.catalina.connector.Request; @@ -2,2 +19,5 @@ +import org.apache.naming.resources.CacheEntry; +import org.apache.naming.resources.ProxyDirContext; + public class TomcatResolver extends Resolver { @@ -85,6 +105,10 @@ return null; } + public String resolveEnv(String key) { + return System.getProperty(key); + } + public String resolveSsl(String key) { // FIXME: Implement SSL environment variables return null; @@ -94,6 +118,26 @@ return request.getHeader(key); } + public boolean resolveResource(int type, String name) { + ProxyDirContext resources = (ProxyDirContext) request.getContext().getResources(); + CacheEntry cacheEntry = resources.lookupCache(name); + if (!cacheEntry.exists) { + return false; + } else { + switch (type) { + case 0: + return (cacheEntry.resource == null); + case 1: + return (cacheEntry.resource != null); + case 2: + return (cacheEntry.resource != null + && cacheEntry.attributes.getContentLength() > 0); + default: + return false; + } + } + } + private static final String emptyStringIfNull(String value) { if (value == null) { return ""; |