Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / jigsaw / src / org / w3c / jigadm / editors / DispatcherRulesEditor.java
diff --git a/JMCR-Stable/real-world application/jigsaw/src/org/w3c/jigadm/editors/DispatcherRulesEditor.java b/JMCR-Stable/real-world application/jigsaw/src/org/w3c/jigadm/editors/DispatcherRulesEditor.java
new file mode 100644 (file)
index 0000000..e8c14d5
--- /dev/null
@@ -0,0 +1,962 @@
+// DispatcherRulesEditor.java\r
+// $Id: DispatcherRulesEditor.java,v 1.1 2010/06/15 12:22:48 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.jigadm.editors;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.Button;\r
+import java.awt.Choice;\r
+import java.awt.Color;\r
+import java.awt.Component;\r
+import java.awt.Container;\r
+import java.awt.Dialog;\r
+import java.awt.Dimension;\r
+import java.awt.FlowLayout;\r
+import java.awt.Frame;\r
+import java.awt.GridLayout;\r
+import java.awt.Label;\r
+import java.awt.Menu;\r
+import java.awt.MenuBar;\r
+import java.awt.MenuItem;\r
+import java.awt.Panel;\r
+import java.awt.TextComponent;\r
+import java.awt.TextField;\r
+import java.awt.Window;\r
+\r
+import java.awt.List;\r
+\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.awt.event.ItemEvent;\r
+import java.awt.event.ItemListener;\r
+\r
+import java.util.Enumeration;\r
+import java.util.EventObject;\r
+import java.util.Hashtable;\r
+import java.util.Properties;\r
+import java.util.StringTokenizer;\r
+import java.util.Vector;\r
+\r
+import java.net.HttpURLConnection;\r
+import java.net.MalformedURLException;\r
+import java.net.URL;\r
+import java.net.URLConnection;\r
+\r
+import java.io.BufferedInputStream;\r
+import java.io.BufferedOutputStream;\r
+import java.io.DataOutputStream;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileOutputStream;\r
+import java.io.FilterOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+\r
+import org.w3c.tools.resources.Attribute;\r
+\r
+import org.w3c.tools.widgets.AnswerListener;\r
+import org.w3c.tools.widgets.BorderPanel;\r
+import org.w3c.tools.widgets.ClosableFrame;\r
+import org.w3c.tools.widgets.MessagePopup;\r
+import org.w3c.tools.widgets.PasswordPopup;\r
+import org.w3c.tools.widgets.QuestionPopup;\r
+\r
+import org.w3c.tools.sorter.Sorter;\r
+\r
+import org.w3c.tools.codec.Base64Encoder;\r
+\r
+import org.w3c.jigsaw.admin.RemoteAccessException;\r
+import org.w3c.jigsaw.admin.RemoteResource;\r
+\r
+import org.w3c.jigadm.RemoteResourceWrapper;\r
+\r
+import org.w3c.www.protocol.http.proxy.Rule;\r
+import org.w3c.www.protocol.http.proxy.RuleNode;\r
+import org.w3c.www.protocol.http.proxy.RuleParser;\r
+import org.w3c.www.protocol.http.proxy.RuleParserException;\r
+\r
+/**\r
+ * @version $Revision: 1.1 $\r
+ * @author  Benoît Mahé (bmahe@w3.org)\r
+ */\r
+public class DispatcherRulesEditor extends AttributeEditor {\r
+\r
+    class RulesEditorFrame extends ClosableFrame implements ActionListener,\r
+                                                           ItemListener,\r
+                                                            AnswerListener\r
+    {\r
+\r
+       class EditorMenu extends MenuBar implements ActionListener {\r
+           RulesEditorFrame frame = null;\r
+           \r
+           public void actionPerformed(ActionEvent evt) {\r
+               String command = evt.getActionCommand();\r
+               if (command.equals("save")) {\r
+                   frame.save();\r
+               } else if (command.equals("quit")) {\r
+                   frame.quit();\r
+               } else if (command.equals("add")) {\r
+                   frame.add();\r
+               } else if (command.equals("replace")) {\r
+                   frame.replace();\r
+               } else if (command.equals("remove")) {\r
+                   frame.remove();\r
+               }\r
+           }\r
+\r
+           EditorMenu(RulesEditorFrame frame) {\r
+               this.frame = frame;\r
+\r
+               //menu file\r
+               Menu file = new Menu("File");\r
+               this.add(file);\r
+\r
+               MenuItem save = new MenuItem("Save Rules");\r
+               save.setActionCommand("save");\r
+               save.addActionListener(this);\r
+               file.add( save );\r
+\r
+               MenuItem quit = new MenuItem("Quit");\r
+               quit.setActionCommand("quit");\r
+               quit.addActionListener(this);\r
+               file.add( quit );\r
+\r
+               //menu rules\r
+               Menu rules = new Menu("Rule");\r
+               this.add(rules);\r
+\r
+               MenuItem add = new MenuItem("Add Rule");\r
+               add.setActionCommand("add");\r
+               add.addActionListener(this);\r
+               rules.add( add );\r
+\r
+               MenuItem replace = new MenuItem("Replace Rule");\r
+               replace.setActionCommand("replace");\r
+               replace.addActionListener(this);\r
+               rules.add( replace );\r
+\r
+               MenuItem remove = new MenuItem("Remove Rule");\r
+               remove.setActionCommand("remove");\r
+               remove.addActionListener(this);\r
+               rules.add( remove );\r
+\r
+           }\r
+       }\r
+\r
+       protected Label     location   = null;\r
+       protected List      lrules     = null;\r
+       protected TextField thost      = null;\r
+       protected TextField trule      = null;\r
+       protected Choice    crule      = null;\r
+       protected Choice    cargs      = null;\r
+       protected TextField targs      = null;\r
+       protected Button    removeB    = null;\r
+       protected Button    addB       = null;\r
+       protected Button    replaceB   = null;\r
+\r
+       protected QuestionPopup exitAnyway = null;\r
+       \r
+       protected Hashtable hargs      = null; //<args, Boolean.TRUE>\r
+\r
+       protected RulesEditor editor   = null;\r
+       protected int         selected = -1;\r
+\r
+       protected boolean     modified = false;\r
+\r
+       /**\r
+        * ActionListsner implementation - One of our button was fired.\r
+        * @param evt The ActionEvent.\r
+        */\r
+\r
+       public void actionPerformed(ActionEvent evt) {\r
+           String command = evt.getActionCommand();\r
+\r
+           if ( command.equals("add" ) ) {\r
+               add();\r
+           } else if ( command.equals("remove" ) ) {\r
+               remove();\r
+           } else if ( command.equals("replace" ) ) {\r
+               replace();\r
+           } else if ( command.equals("save" ) ) {\r
+               save();\r
+           } else if ( command.equals("dismiss" ) ) {\r
+               quit();\r
+           }\r
+       }\r
+\r
+       protected void error(String msg) {\r
+           (new MessagePopup("Error: "+msg)).show();\r
+       }\r
+\r
+       protected void error(Exception ex) {\r
+           error(ex.getMessage());\r
+       }\r
+\r
+       protected void error(String msg, Exception ex) {\r
+           error(msg+": "+ex.getMessage());\r
+       }\r
+\r
+       protected void msg(String msg) {\r
+           (new MessagePopup(msg)).show();\r
+       }\r
+\r
+       protected void msg(String type, String msg) {\r
+           msg(type+": "+msg);\r
+       }\r
+\r
+       protected String getAuthFromDialog() {\r
+           PasswordPopup pp = new PasswordPopup();\r
+           Frame popup = new Frame("Authorization required");\r
+           popup.setBackground(Color.lightGray);\r
+           popup.setSize(new Dimension(300, 200));\r
+           popup.setLayout(new BorderLayout());\r
+           popup.add("Center", pp);\r
+           popup.show();\r
+           pp.init();\r
+           while(!pp.waitForCompletion());\r
+           popup.setVisible(false);\r
+           if (pp.canceled())\r
+               return null;\r
+           Base64Encoder encoder = \r
+               new Base64Encoder(pp.getUserName()+":"+pp.getPassword());\r
+           popup.dispose();\r
+           return encoder.processString();\r
+       }\r
+\r
+       protected void add() {\r
+           Rule added = null;\r
+           try {\r
+               String tokens[] = getTokens();\r
+               if (tokens != null)\r
+                   added = editor.addRule(tokens);\r
+           } catch (RuleParserException ex) {\r
+               error(ex);\r
+           }\r
+           //add at the end of the displayed list\r
+           if (added != null) {\r
+               lrules.addItem(added.toString());\r
+               updateArgsList(added.getRuleArgs());\r
+               setModified(true);\r
+           }\r
+       }\r
+\r
+       protected void remove() {\r
+           if (selected != -1) {\r
+               editor.removeRule(selected);\r
+               lrules.remove(selected);\r
+               setModified(true);\r
+           } else {\r
+               error("No rule selected");\r
+           }\r
+       }\r
+\r
+       protected void replace() {\r
+           if (selected == -1) {\r
+               error("No rule selected");\r
+               return;\r
+           }\r
+           Rule replaced = null;\r
+           try {\r
+               String tokens[] = getTokens();\r
+               if (tokens != null)\r
+                   replaced = editor.replaceRule(tokens, selected);\r
+           } catch (RuleParserException ex) {\r
+               error(ex);\r
+           }\r
+           if (replaced != null) {\r
+               lrules.replaceItem(replaced.toString(), selected);\r
+               setModified(true);\r
+           }\r
+       }\r
+\r
+       protected void save() {\r
+           editor.save();\r
+           setModified(false);\r
+       }\r
+\r
+       protected void close() {\r
+           quit();\r
+       }\r
+\r
+       protected void quit() {\r
+           if (getModified()) {\r
+               if (exitAnyway == null) {\r
+                   exitAnyway = \r
+                       new QuestionPopup(this, \r
+                                         "Rules Modified, Quit anyway?");\r
+                   exitAnyway.registerAnswerListener(this);\r
+               } \r
+               exitAnyway.show();\r
+           } else {\r
+               setVisible(false);\r
+           }\r
+       }\r
+\r
+       protected String[] getTokens() {\r
+           String rule = trule.getText();\r
+           String host = thost.getText();\r
+           if ((rule == null) || (rule.length() == 0)) {\r
+               error("You must specify a rule");\r
+               return null;\r
+           }\r
+           if ((host == null) || (host.length() == 0)) {\r
+               error("You must specify a host");\r
+               return null;\r
+           }\r
+           Vector vtokens = new Vector(3);\r
+           vtokens.addElement(host);\r
+           vtokens.addElement(rule);\r
+\r
+           String args = targs.getText();\r
+           if (args != null) {\r
+               StringTokenizer st = new StringTokenizer(args);\r
+               while (st.hasMoreTokens())\r
+                   vtokens.addElement(st.nextToken());\r
+           }\r
+           String tokens[] = new String[vtokens.size()];\r
+           vtokens.copyInto(tokens);\r
+           return tokens;\r
+       }\r
+       \r
+       protected void setModified(boolean onoff) {\r
+           this.modified = onoff;\r
+       }\r
+\r
+       protected boolean getModified() {\r
+           return modified;\r
+       }\r
+\r
+       /**\r
+        * ItemListener implementation - a rule type was selected.\r
+        */\r
+       public void itemStateChanged(ItemEvent e) {\r
+           Object source = e.getSource();\r
+           if (source == lrules) {\r
+               this.selected = ((Integer) e.getItem()).intValue();\r
+               showRule(selected);\r
+           } else if (source == crule) {\r
+               String rule = (String)e.getItem();\r
+               trule.setText(rule);\r
+               if (rule.equals("direct") || rule.equals("forbid")) {\r
+                   targs.setEditable(false);\r
+                   targs.setText("");\r
+               } else {\r
+                   targs.setEditable(true);\r
+               }\r
+           } else if (source == cargs) {\r
+               String arg = (String)e.getItem();\r
+               if (targs.isEditable())\r
+                   targs.setText(arg);\r
+           }\r
+       }\r
+\r
+       /**\r
+        * AnswerListener implemetation - yes\r
+        */\r
+       public void questionAnswered (Object source, int response) {\r
+           if (source == exitAnyway) {\r
+               exitAnyway.setVisible(false);\r
+               if (response == YES)\r
+                   setVisible(false);\r
+           }\r
+       }\r
+\r
+       protected void showRule(int idx) {\r
+           Rule rule = editor.getRule(idx);\r
+           thost.setText(rule.getHost());\r
+           trule.setText(rule.getRuleName());\r
+           String args = rule.getRuleArgs();\r
+           if (args != null) {\r
+               targs.setText(args);\r
+               targs.setEditable(true);\r
+           } else {\r
+               targs.setEditable(false);\r
+               targs.setText("");\r
+           }\r
+       }\r
+       \r
+\r
+       protected void createRulesChoice() {\r
+           crule = new Choice();\r
+           String names[] = Rule.getRulesName();\r
+           for (int i=0; i < names.length; i++) {\r
+               crule.add(names[i]);\r
+           }\r
+           crule.addItemListener(this);\r
+       }\r
+\r
+       protected void createArgsChoice() {\r
+           cargs = new Choice();\r
+           hargs = new Hashtable(10);\r
+           cargs.addItemListener(this);\r
+       }\r
+\r
+       protected void updateArgsList(String args) {\r
+           if ((args != null) && (hargs.get(args) == null)) {\r
+               hargs.put(args, Boolean.TRUE);\r
+               cargs.add(args);\r
+           }\r
+       }\r
+\r
+       protected void update() {\r
+           int       size  = editor.getSize();\r
+           Rule      rule  = null;\r
+\r
+           setModified(false);\r
+           selected = -1;\r
+           if (lrules != null) {\r
+               lrules.removeAll();\r
+               for (int i = 0; i < size; i++) {\r
+                   rule = editor.getRule(i);\r
+                   lrules.addItem(rule.toString(),i);\r
+                   updateArgsList(rule.getRuleArgs());\r
+               }\r
+           }\r
+           if (location != null)\r
+               location.setText("Rules location: "+\r
+                                editor.component.getRulesLocation());\r
+       }\r
+\r
+       RulesEditorFrame(RulesEditor editor) {\r
+           super("Proxy Dispatcher Rules Editor");\r
+\r
+           this.editor = editor;\r
+           lrules = new List(20, false);\r
+           lrules.setBackground(Color.white);\r
+           lrules.addItemListener(this);\r
+           createRulesChoice();\r
+           createArgsChoice();\r
+           update();\r
+           //Menu Bar\r
+           EditorMenu menu = new EditorMenu(this);\r
+           setMenuBar(menu);\r
+\r
+           //rules list\r
+           BorderPanel plrules = new BorderPanel(BorderPanel.OUT, 5);\r
+           plrules.setLayout(new BorderLayout());\r
+           plrules.add(lrules);\r
+\r
+           \r
+           thost = new TextField(20);\r
+           trule = new TextField(15);\r
+           trule.setEditable(false);\r
+\r
+           BorderPanel ptrule = new BorderPanel(BorderPanel.IN, 2);\r
+           ptrule.setLayout(new GridLayout(1,1));\r
+           ptrule.add(trule);\r
+\r
+           targs = new TextField(30);\r
+\r
+           // BAR 0\r
+           Panel plabel = new Panel();\r
+           plabel.add(new Label("Host: "));\r
+           Panel pcrule = new Panel(new BorderLayout());\r
+           pcrule.add(new Label("Rule: "), "West");\r
+           pcrule.add(crule, "Center");\r
+           Panel pcargs = new Panel(new BorderLayout());\r
+           pcargs.add(new Label("Args: "), "West");\r
+           pcargs.add(cargs, "Center");\r
+\r
+           BorderPanel phost = new BorderPanel(BorderPanel.IN,2);\r
+           phost.setLayout(new GridLayout(2,1));\r
+           phost.add(plabel);\r
+           phost.add(thost);\r
+\r
+           BorderPanel prule = new BorderPanel(BorderPanel.IN,2);\r
+           prule.setLayout(new GridLayout(2,1));\r
+           prule.add(pcrule);\r
+           prule.add(trule);\r
+\r
+           BorderPanel pargs = new BorderPanel(BorderPanel.IN,2);\r
+           pargs.setLayout(new GridLayout(2,1));\r
+           pargs.add(pcargs);\r
+           pargs.add(targs);\r
+\r
+           BorderPanel bar0 = new BorderPanel(BorderPanel.OUT,5);\r
+           bar0.setLayout(new GridLayout(1,3));\r
+           bar0.add(phost);\r
+           bar0.add(prule);\r
+           bar0.add(pargs);\r
+\r
+           // BAR 2\r
+           addB     = new Button("Add Rule");\r
+           addB.setActionCommand("add");\r
+           addB.addActionListener(this);\r
+\r
+           replaceB = new Button("Replace Rule");\r
+           replaceB.setActionCommand("replace");\r
+           replaceB.addActionListener(this);\r
+\r
+           removeB  = new Button("Remove Rule");\r
+           removeB.setActionCommand("remove");\r
+           removeB.addActionListener(this);\r
+\r
+           Panel bar2 = new Panel(new GridLayout(1,3));\r
+           bar2.add(addB);\r
+           bar2.add(replaceB);\r
+           bar2.add(removeB);\r
+\r
+           //Label location\r
+           location = new Label("Rules location: "+\r
+                                editor.component.getRulesLocation());\r
+           BorderPanel ploc = new BorderPanel(BorderPanel.RAISED, 1);\r
+           ploc.setLayout(new FlowLayout());\r
+           ploc.add(location);\r
+\r
+           //Bar 2 & 3\r
+           BorderPanel bar2_3 = new BorderPanel(BorderPanel.OUT, 5);\r
+           bar2_3.setLayout(new GridLayout(2,1));\r
+           bar2_3.add(bar2);\r
+           bar2_3.add(ploc);\r
+           \r
+           //subpanel\r
+           Panel subPanel = new Panel(new BorderLayout());\r
+           subPanel.add(plrules,"Center");\r
+           subPanel.add(bar0, "South");\r
+\r
+           add(subPanel, "Center");\r
+           add(bar2_3, "South");\r
+           \r
+           setSize(800,600);\r
+       }\r
+    }\r
+\r
+    class RulesEditor {\r
+\r
+       class Saver extends Thread {\r
+           RulesEditor editor = null;\r
+           \r
+           public void run() {\r
+               editor.saveRules();\r
+           }\r
+\r
+           Saver(RulesEditor editor) {\r
+               this.editor = editor;\r
+           }\r
+           \r
+       }\r
+\r
+       protected URL                   rulesUrl  = null;\r
+       protected File                  rulesFile = null;\r
+       protected RulesEditorFrame      gui       = null;\r
+       protected HttpURLConnection     con       = null;\r
+       protected String                auth      = null;\r
+       protected DispatcherComponent   component = null;\r
+\r
+       /**\r
+        * The current set of rules.\r
+        */\r
+       protected Vector rules   = null; //<Rule>\r
+\r
+       protected void setURL(URL url) {\r
+           this.rulesFile = null;\r
+           this.rulesUrl  = url;\r
+           parse();\r
+       }\r
+\r
+       protected void setAuthorization(String authorization) {\r
+           this.auth = authorization;\r
+       }\r
+\r
+       protected String getAuthorization() {\r
+           return auth;\r
+       }\r
+\r
+       protected boolean hasAuthorization() {\r
+           return (auth != null);\r
+       }\r
+\r
+       protected void setFile(File file) {\r
+           this.rulesUrl  = null;\r
+           this.rulesFile = file;\r
+           parse();\r
+       }\r
+\r
+       protected DataOutputStream getRulesOutputStream() \r
+           throws IOException\r
+       {\r
+           DataOutputStream out = null;\r
+           if (rulesUrl != null) {\r
+               con = (HttpURLConnection) rulesUrl.openConnection();\r
+               con.setRequestMethod("PUT");\r
+               con.setRequestProperty("content-type","text/plain");\r
+               if (hasAuthorization())\r
+                   con.setRequestProperty("Authorization","Basic "+\r
+                                          getAuthorization());\r
+               con.setDoOutput(true);\r
+               con.setDoInput(true);\r
+               con.setAllowUserInteraction(true);\r
+               out = new DataOutputStream(con.getOutputStream());\r
+           } else {\r
+               out = new DataOutputStream(\r
+                         new BufferedOutputStream(\r
+                             new FileOutputStream(rulesFile)));\r
+           }\r
+           return out;\r
+       }\r
+\r
+       protected boolean closeRulesOutputStream(DataOutputStream out) \r
+           throws IOException\r
+       {\r
+           out.flush();\r
+           out.close();\r
+           if ((rulesUrl != null) && (con != null)) {\r
+               con.getHeaderField(0);\r
+               int code = con.getResponseCode();\r
+               switch (code) {\r
+               case HttpURLConnection.HTTP_UNAUTHORIZED:\r
+                   //ask for a username/password\r
+                   String encoded = gui.getAuthFromDialog();\r
+                   if (encoded == null)\r
+                       return true;\r
+                   setAuthorization(encoded);\r
+                   return false;\r
+               case HttpURLConnection.HTTP_CREATED:\r
+               case HttpURLConnection.HTTP_OK:\r
+               case HttpURLConnection.HTTP_NO_CONTENT:\r
+                   gui.msg("Proxy dispatcher rules saved.");\r
+                   return true;\r
+               default:\r
+                   gui.msg("HTTP error",con.getResponseMessage());\r
+                   return true;\r
+               }\r
+           } else {\r
+               gui.msg("Proxy dispatcher rules saved.");\r
+               return true;\r
+           }\r
+       }\r
+\r
+       /**\r
+        * return the inputStream or null if the rules file doesn't exists.\r
+        * @return an InputStream.\r
+        */\r
+       protected InputStream getRulesInputStream() \r
+           throws IOException\r
+       {\r
+           InputStream in = null;\r
+           if (rulesUrl != null)\r
+               in = rulesUrl.openStream();\r
+           else if (rulesFile.exists()) {\r
+               in = new BufferedInputStream(\r
+                        new FileInputStream(rulesFile));\r
+           }\r
+           return in;\r
+       }\r
+\r
+       protected void save() {\r
+           (new Saver(this)).start();\r
+       }\r
+\r
+       protected void saveRules() {\r
+           DataOutputStream out = null;\r
+           try {\r
+               do {\r
+                   out = getRulesOutputStream();\r
+                   if (rules != null) {\r
+                       out.writeBytes("#\n# Generated by proxy "+\r
+                                      "dispatcher rules editor.\n#\n");\r
+                       //write content here\r
+                       for (int i=0; i < rules.size(); i++)\r
+                           ((Rule)rules.elementAt(i)).writeRule(out);\r
+                   }\r
+               } while (! closeRulesOutputStream(out));\r
+           } catch (Exception ex) {\r
+               gui.error("Unable to save rules",ex);\r
+           }\r
+       }\r
+\r
+       protected void parse() {\r
+           InputStream in = null;\r
+           // Try opening the rule file as a URL:\r
+           try {\r
+               in = getRulesInputStream();\r
+           } catch (Exception ex) {\r
+               gui.error("Unable to open input stream");\r
+               return;\r
+           }\r
+           try {\r
+               if (in != null) {\r
+                   RuleParser parser = new RuleParser(in);\r
+                   RuleNode   nroot  = parser.parse();\r
+                   rules = generateRuleVector(nroot);\r
+               } else {\r
+                   rules = new Vector(); //empty\r
+               }\r
+           } catch (Exception ex) {\r
+               gui.error("Rules parser error",ex);\r
+           }\r
+       }\r
+\r
+       protected Vector generateRuleVector(RuleNode root) {\r
+           Vector vrules = new Vector(20);\r
+           collectRules(root, vrules);\r
+           Rule srules [] = new Rule[vrules.size()];\r
+           vrules.copyInto(srules);\r
+           srules = (Rule[]) Sorter.sortComparableArray(srules, true);\r
+           for (int i=0; i < srules.length; i++)\r
+               vrules.setElementAt(srules[i], i);\r
+           return vrules;\r
+       }\r
+\r
+       protected void collectRules(RuleNode root, Vector vrules) {\r
+           Hashtable childrens = root.getChildren();\r
+           if (childrens != null) {\r
+               Enumeration childenum = childrens.keys();\r
+               while (childenum.hasMoreElements()) {\r
+                   RuleNode rnode = \r
+                       (RuleNode) childrens.get((String) childenum.nextElement());\r
+                   Rule rule = rnode.getRule();\r
+                   if (rule != null)\r
+                       vrules.addElement(rule);\r
+                   collectRules(rnode, vrules);\r
+               }\r
+           }\r
+       }\r
+\r
+       /**\r
+        * Add a Rule to the end of the rules array.\r
+        * @param tokens a tokens array, according to the Rule specification.\r
+        * @return the new added rule.\r
+        * @exception RuleParserException if the rule can't be created.\r
+        */\r
+       protected Rule addRule(String tokens[]) \r
+           throws RuleParserException\r
+       {\r
+           Rule newRule = null;\r
+           newRule = Rule.createRule(tokens, 1, tokens.length);\r
+           if (newRule != null) {\r
+               if (rules == null)\r
+                   rules = new Vector(10);\r
+               rules.addElement(newRule);\r
+           }\r
+           return newRule;\r
+       }\r
+       \r
+       /**\r
+        * Replace the Rule at the specified index .\r
+        * @param tokens a tokens array, according to the Rule specification.\r
+        * @param idx the index.\r
+        * @return the new added rule.\r
+        * @exception RuleParserException if the rule can't be created.\r
+        */\r
+       protected Rule replaceRule(String tokens[], int idx) \r
+           throws RuleParserException\r
+       {\r
+           Rule newRule = null;\r
+           newRule = Rule.createRule(tokens, 1, tokens.length);\r
+           if (newRule != null) {\r
+               if (rules == null)\r
+                   rules = new Vector(10);\r
+               rules.setElementAt(newRule, idx);\r
+           }\r
+           return newRule;\r
+       }\r
+\r
+       /**\r
+        * Deletes the rule at the specified index. Each rule with an index \r
+        * greater or equal to the specified index is shifted downward to \r
+        * have an index one smaller than the value it had previously.\r
+        * @param idx the rule index.\r
+        */\r
+       protected void removeRule(int idx) {\r
+           rules.removeElementAt(idx);\r
+       }\r
+\r
+       protected Rule getRule(int idx) {\r
+           return (Rule)rules.elementAt(idx);\r
+       }\r
+\r
+       /**\r
+        * return the number of rules.\r
+        */\r
+       protected int getSize() {\r
+           if (rules == null)\r
+               return 0;\r
+           return rules.size();\r
+       }\r
+\r
+       public void show() {\r
+           gui.update();\r
+           gui.show();\r
+       }\r
+\r
+       RulesEditor(DispatcherComponent comp, URL url) {\r
+           this.component = comp;\r
+           this.rulesUrl = url;\r
+           parse();\r
+           this.gui = new RulesEditorFrame(this);\r
+       }\r
+\r
+       RulesEditor(DispatcherComponent comp, File file) {\r
+           this.component = comp;\r
+           this.rulesFile = file;\r
+           parse();\r
+           this.gui = new RulesEditorFrame(this);\r
+       }\r
+    }\r
+\r
+    /**\r
+     * The TextField+Button component\r
+     */\r
+    class DispatcherComponent extends BorderPanel implements ActionListener {\r
+       protected RulesEditor           reditor    = null;\r
+       protected TextField             locationEd = null;\r
+       protected DispatcherRulesEditor editor     = null;\r
+\r
+       public void actionPerformed(ActionEvent e) {\r
+           String command = e.getActionCommand();\r
+           if (command != null) {\r
+               String loc = getRulesLocation();\r
+               if ((loc != null) && (loc.length() > 0)) {\r
+                   try {\r
+                       URL url = new URL(loc);\r
+                       if (url.getProtocol().equalsIgnoreCase("file")) {\r
+                           File file = new File(url.getFile());\r
+                           if (reditor == null)\r
+                               reditor = new RulesEditor(this, file);\r
+                           else\r
+                               reditor.setFile(file);\r
+                       } else {\r
+                           if (reditor == null)\r
+                               reditor = new RulesEditor(this, url);\r
+                           else \r
+                               reditor.setURL(url);\r
+                       }\r
+                   } catch (MalformedURLException ex) {\r
+                       //shoud be a file\r
+                       File file = new File(loc);\r
+                       if (reditor == null)\r
+                           reditor = new RulesEditor(this, file);\r
+                       else\r
+                           reditor.setFile(file);\r
+                   }\r
+                   reditor.show();\r
+               }\r
+           }\r
+       }\r
+       \r
+       public String getRulesLocation() {\r
+           return locationEd.getText();\r
+       }\r
+\r
+       public void setRulesLocation(String loc) {\r
+           locationEd.setText(loc);\r
+       }\r
+\r
+       DispatcherComponent (DispatcherRulesEditor parent, String location) {\r
+           super(IN, 2);\r
+           this.editor = parent;\r
+           this.locationEd  = new TextField(20);\r
+           if (location != null)\r
+               this.locationEd.setText(location);\r
+           Button editB = new Button("Edit Rules");\r
+           editB.setActionCommand("edit");\r
+           editB.addActionListener(this);\r
+           setLayout( new BorderLayout());\r
+           add(locationEd,"Center");\r
+           add(editB,"East");\r
+       }\r
+    }\r
+\r
+    //\r
+    // DispatcherRulesEditor \r
+    //\r
+\r
+    private   DispatcherComponent widget     = null;\r
+    protected String              origs      = null;\r
+\r
+    protected void createComponent(String location) {\r
+       widget = new DispatcherComponent(this, location);\r
+    }\r
+\r
+    /**\r
+     * get the Component created by the editor.\r
+     * @return a Component\r
+     */\r
+    public Component getComponent() {\r
+       return widget;\r
+    }\r
+\r
+    /**\r
+     * Tells if the edited value has changed\r
+     * @return true if the value changed.\r
+     */\r
+\r
+    public boolean hasChanged() {\r
+       return !origs.equals(widget.getRulesLocation());\r
+    }\r
+\r
+    /**\r
+     * set the current value to be the original value, ie: changed\r
+     * must return <strong>false</strong> after a reset.\r
+     */\r
+\r
+    public void clearChanged() {\r
+       origs = widget.getRulesLocation();\r
+    }\r
+\r
+    /**\r
+     * reset the changes (if any)\r
+     */\r
+\r
+    public void resetChanges() {\r
+       widget.setRulesLocation(origs);\r
+    }\r
+\r
+    /**\r
+     * Get the current value of the edited value\r
+     * @return an object or <strong>null</strong> if the object was not\r
+     * initialized\r
+     */\r
+\r
+    public Object getValue() {\r
+       return widget.getRulesLocation();\r
+    }\r
+\r
+    /**\r
+     * Set the value of the edited value\r
+     * @param o the new value.\r
+     */\r
+\r
+    public void setValue(Object o) {\r
+       widget.setRulesLocation(o.toString());\r
+    }\r
+\r
+    /**\r
+     * Initialize the editor\r
+     * @param w the ResourceWrapper father of the attribute\r
+     * @param a the Attribute we are editing\r
+     * @param o the value of the above attribute\r
+     * @param p some Properties, used to fine-tune the editor\r
+     * @exception RemoteAccessException if a remote access error occurs.\r
+     */\r
+\r
+    public void initialize(RemoteResourceWrapper w, Attribute a,  Object o,\r
+                          Properties p)\r
+       throws RemoteAccessException\r
+    {\r
+       RemoteResource r = w.getResource();\r
+       if(o == null) {\r
+           String v = null;\r
+           // FIXME\r
+           v = (String) r.getValue(a.getName());\r
+          \r
+           if(v == null)\r
+               if(a.getDefault() != null)\r
+                   v = a.getDefault().toString();\r
+           if ( v != null ) {\r
+               origs = v;\r
+           } \r
+       } else {\r
+           origs = o.toString();\r
+       }\r
+       createComponent(origs);\r
+    }\r
+\r
+    public DispatcherRulesEditor() {\r
+       origs = "";\r
+    }\r
+\r
+}\r