--- /dev/null
+// 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