--- /dev/null
+// RuleParserException.java\r
+// $Id: RuleNode.java,v 1.1 2010/06/15 12:28:31 smhuang Exp $\r
+// (c) COPYRIGHT MIT and INRIA, 1998.\r
+// Please first read the full copyright statement in file COPYRIGHT.html\r
+\r
+package org.w3c.www.protocol.http.proxy ;\r
+\r
+import java.util.Hashtable;\r
+\r
+/**\r
+ * A RuleNode instance keeps track of one token within the lfh of a rule.\r
+ * This data structure is usually known as a <em>hash-trie</em>, check\r
+ * one of the Knuth books for more infos.\r
+ */\r
+public class RuleNode {\r
+ /**\r
+ * The token this node applies to.\r
+ */\r
+ String token = null;\r
+ /**\r
+ * It's optionally associated rule.\r
+ */\r
+ Rule rule = null;\r
+ /**\r
+ * A hashtable to keep track of children rules.\r
+ */\r
+ Hashtable children = null;\r
+\r
+ void setRule(Rule rule) {\r
+ this.rule = rule;\r
+ }\r
+\r
+ public Rule getRule() {\r
+ return rule;\r
+ }\r
+\r
+ public Hashtable getChildren(){ \r
+ return children;\r
+ }\r
+\r
+ /**\r
+ * Add a children rule node to this rule node.\r
+ * @param token The child token.\r
+ * @param rule The rule to map to this token.\r
+ * @return The newly created RuleNode instance.\r
+ */\r
+\r
+ synchronized RuleNode addChild(String tok, Rule rule) {\r
+ RuleNode node = new RuleNode(tok, rule);\r
+ if ( children == null ) \r
+ children = new Hashtable(5);\r
+ children.put(tok, node);\r
+ return node;\r
+ }\r
+\r
+ /**\r
+ * Add a children rule node to this node.\r
+ * This method does the same as above, except that it doesn't map\r
+ * the created node to a rule.\r
+ * @param tok The token this node applies to.\r
+ * @return The newly createed RuleNode instance.\r
+ */\r
+\r
+ synchronized RuleNode addChild(String tok) {\r
+ RuleNode node = new RuleNode(tok);\r
+ if ( children == null ) \r
+ children = new Hashtable(5);\r
+ children.put(tok, node);\r
+ return node;\r
+ }\r
+\r
+ /**\r
+ * Lookup a rule.\r
+ * Given a fully qualified host name, parse it into its components, and\r
+ * starting from this rule node, lookup for a matching rule.\r
+ * <p>The most precise rule is always returned.\r
+ * @return The best matching rule, as a Rule instance, or <strong>\r
+ * null</strong> if no matching rule was found.\r
+ */\r
+\r
+ public Rule lookupRule(String host) {\r
+ // Parse the host into it's components:\r
+ String parts[] = new String[32];\r
+ int hostlen = host.length();\r
+ int phost = 0;\r
+ int npart = 0; \r
+ boolean isip = true;\r
+ for (int i = 0 ; i < hostlen; i++) {\r
+ if ( host.charAt(i) == '.' ) {\r
+ if ( npart+1 >= parts.length ) {\r
+ // This is unlikely to happen, but anyway:\r
+ String newparts[] = new String[parts.length << 1];\r
+ System.arraycopy(parts, 0, newparts, 0, parts.length);\r
+ parts = newparts;\r
+ }\r
+ parts[npart++] = host.substring(phost, i);\r
+ phost = ++i;\r
+ } else {\r
+ if(isip)\r
+ isip = (host.charAt(i)>='0') && (host.charAt(i)<='9');\r
+ }\r
+ }\r
+ parts[npart++] = host.substring(phost);\r
+\r
+ RuleNode node = this;\r
+ Rule ret = rule;\r
+ if(isip)\r
+ for (int i = 0; i <= npart ; i++ ) {\r
+ node = node.lookup(parts[i]);\r
+ if (node != null) {\r
+ ret = (node.rule != null) ? node.rule : rule;\r
+ } else {\r
+ return ret;\r
+ }\r
+ }\r
+ else\r
+ for (int i = npart; --i >= 0 ; ) {\r
+ node = node.lookup(parts[i]);\r
+ if (node != null) {\r
+ ret = (node.rule != null) ? node.rule : ret;\r
+ } else {\r
+ return ret;\r
+ }\r
+ }\r
+ return ret;\r
+ }\r
+\r
+ /**\r
+ * Lookup a children rule node.\r
+ * @param tok The token for the child that is to be looked up.\r
+ * @return A RuleNode instance, if found, <strong>null</strong>\r
+ * otherwise.\r
+ */\r
+\r
+ public RuleNode lookup(String tok) {\r
+ return ((children != null) ? (RuleNode) children.get(tok) : null);\r
+ }\r
+\r
+ RuleNode(String token, Rule rule) {\r
+ this.token = token.toLowerCase();\r
+ this.rule = rule;\r
+ }\r
+\r
+ RuleNode(String token) {\r
+ this(token, null);\r
+ }\r
+\r
+ RuleNode() {\r
+ this("**ROOT**", null);\r
+ }\r
+}\r