001: // DispatcherRulesEditor.java
002: // $Id: DispatcherRulesEditor.java,v 1.16 2007/02/09 13:45:02 ylafon Exp $
003: // (c) COPYRIGHT MIT and INRIA, 1998.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.jigadm.editors;
007:
008: import java.awt.BorderLayout;
009: import java.awt.Button;
010: import java.awt.Choice;
011: import java.awt.Color;
012: import java.awt.Component;
013: import java.awt.Container;
014: import java.awt.Dialog;
015: import java.awt.Dimension;
016: import java.awt.FlowLayout;
017: import java.awt.Frame;
018: import java.awt.GridLayout;
019: import java.awt.Label;
020: import java.awt.Menu;
021: import java.awt.MenuBar;
022: import java.awt.MenuItem;
023: import java.awt.Panel;
024: import java.awt.TextComponent;
025: import java.awt.TextField;
026: import java.awt.Window;
027:
028: import java.awt.List;
029:
030: import java.awt.event.ActionEvent;
031: import java.awt.event.ActionListener;
032: import java.awt.event.ItemEvent;
033: import java.awt.event.ItemListener;
034:
035: import java.util.Enumeration;
036: import java.util.EventObject;
037: import java.util.Hashtable;
038: import java.util.Properties;
039: import java.util.StringTokenizer;
040: import java.util.Vector;
041:
042: import java.net.HttpURLConnection;
043: import java.net.MalformedURLException;
044: import java.net.URL;
045: import java.net.URLConnection;
046:
047: import java.io.BufferedInputStream;
048: import java.io.BufferedOutputStream;
049: import java.io.DataOutputStream;
050: import java.io.File;
051: import java.io.FileInputStream;
052: import java.io.FileOutputStream;
053: import java.io.FilterOutputStream;
054: import java.io.IOException;
055: import java.io.InputStream;
056:
057: import org.w3c.tools.resources.Attribute;
058:
059: import org.w3c.tools.widgets.AnswerListener;
060: import org.w3c.tools.widgets.BorderPanel;
061: import org.w3c.tools.widgets.ClosableFrame;
062: import org.w3c.tools.widgets.MessagePopup;
063: import org.w3c.tools.widgets.PasswordPopup;
064: import org.w3c.tools.widgets.QuestionPopup;
065:
066: import org.w3c.tools.sorter.Sorter;
067:
068: import org.w3c.tools.codec.Base64Encoder;
069:
070: import org.w3c.jigsaw.admin.RemoteAccessException;
071: import org.w3c.jigsaw.admin.RemoteResource;
072:
073: import org.w3c.jigadm.RemoteResourceWrapper;
074:
075: import org.w3c.www.protocol.http.proxy.Rule;
076: import org.w3c.www.protocol.http.proxy.RuleNode;
077: import org.w3c.www.protocol.http.proxy.RuleParser;
078: import org.w3c.www.protocol.http.proxy.RuleParserException;
079:
080: /**
081: * @version $Revision: 1.16 $
082: * @author Benoît Mahé (bmahe@w3.org)
083: */
084: public class DispatcherRulesEditor extends AttributeEditor {
085:
086: class RulesEditorFrame extends ClosableFrame implements
087: ActionListener, ItemListener, AnswerListener {
088:
089: class EditorMenu extends MenuBar implements ActionListener {
090: RulesEditorFrame frame = null;
091:
092: public void actionPerformed(ActionEvent evt) {
093: String command = evt.getActionCommand();
094: if (command.equals("save")) {
095: frame.save();
096: } else if (command.equals("quit")) {
097: frame.quit();
098: } else if (command.equals("add")) {
099: frame.add();
100: } else if (command.equals("replace")) {
101: frame.replace();
102: } else if (command.equals("remove")) {
103: frame.remove();
104: }
105: }
106:
107: EditorMenu(RulesEditorFrame frame) {
108: this .frame = frame;
109:
110: //menu file
111: Menu file = new Menu("File");
112: this .add(file);
113:
114: MenuItem save = new MenuItem("Save Rules");
115: save.setActionCommand("save");
116: save.addActionListener(this );
117: file.add(save);
118:
119: MenuItem quit = new MenuItem("Quit");
120: quit.setActionCommand("quit");
121: quit.addActionListener(this );
122: file.add(quit);
123:
124: //menu rules
125: Menu rules = new Menu("Rule");
126: this .add(rules);
127:
128: MenuItem add = new MenuItem("Add Rule");
129: add.setActionCommand("add");
130: add.addActionListener(this );
131: rules.add(add);
132:
133: MenuItem replace = new MenuItem("Replace Rule");
134: replace.setActionCommand("replace");
135: replace.addActionListener(this );
136: rules.add(replace);
137:
138: MenuItem remove = new MenuItem("Remove Rule");
139: remove.setActionCommand("remove");
140: remove.addActionListener(this );
141: rules.add(remove);
142:
143: }
144: }
145:
146: protected Label location = null;
147: protected List lrules = null;
148: protected TextField thost = null;
149: protected TextField trule = null;
150: protected Choice crule = null;
151: protected Choice cargs = null;
152: protected TextField targs = null;
153: protected Button removeB = null;
154: protected Button addB = null;
155: protected Button replaceB = null;
156:
157: protected QuestionPopup exitAnyway = null;
158:
159: protected Hashtable hargs = null; //<args, Boolean.TRUE>
160:
161: protected RulesEditor editor = null;
162: protected int selected = -1;
163:
164: protected boolean modified = false;
165:
166: /**
167: * ActionListsner implementation - One of our button was fired.
168: * @param evt The ActionEvent.
169: */
170:
171: public void actionPerformed(ActionEvent evt) {
172: String command = evt.getActionCommand();
173:
174: if (command.equals("add")) {
175: add();
176: } else if (command.equals("remove")) {
177: remove();
178: } else if (command.equals("replace")) {
179: replace();
180: } else if (command.equals("save")) {
181: save();
182: } else if (command.equals("dismiss")) {
183: quit();
184: }
185: }
186:
187: protected void error(String msg) {
188: (new MessagePopup("Error: " + msg)).show();
189: }
190:
191: protected void error(Exception ex) {
192: error(ex.getMessage());
193: }
194:
195: protected void error(String msg, Exception ex) {
196: error(msg + ": " + ex.getMessage());
197: }
198:
199: protected void msg(String msg) {
200: (new MessagePopup(msg)).show();
201: }
202:
203: protected void msg(String type, String msg) {
204: msg(type + ": " + msg);
205: }
206:
207: protected String getAuthFromDialog() {
208: PasswordPopup pp = new PasswordPopup();
209: Frame popup = new Frame("Authorization required");
210: popup.setBackground(Color.lightGray);
211: popup.setSize(new Dimension(300, 200));
212: popup.setLayout(new BorderLayout());
213: popup.add("Center", pp);
214: popup.show();
215: pp.init();
216: while (!pp.waitForCompletion())
217: ;
218: popup.setVisible(false);
219: if (pp.canceled())
220: return null;
221: Base64Encoder encoder = new Base64Encoder(pp.getUserName()
222: + ":" + pp.getPassword());
223: popup.dispose();
224: return encoder.processString();
225: }
226:
227: protected void add() {
228: Rule added = null;
229: try {
230: String tokens[] = getTokens();
231: if (tokens != null)
232: added = editor.addRule(tokens);
233: } catch (RuleParserException ex) {
234: error(ex);
235: }
236: //add at the end of the displayed list
237: if (added != null) {
238: lrules.addItem(added.toString());
239: updateArgsList(added.getRuleArgs());
240: setModified(true);
241: }
242: }
243:
244: protected void remove() {
245: if (selected != -1) {
246: editor.removeRule(selected);
247: lrules.remove(selected);
248: setModified(true);
249: } else {
250: error("No rule selected");
251: }
252: }
253:
254: protected void replace() {
255: if (selected == -1) {
256: error("No rule selected");
257: return;
258: }
259: Rule replaced = null;
260: try {
261: String tokens[] = getTokens();
262: if (tokens != null)
263: replaced = editor.replaceRule(tokens, selected);
264: } catch (RuleParserException ex) {
265: error(ex);
266: }
267: if (replaced != null) {
268: lrules.replaceItem(replaced.toString(), selected);
269: setModified(true);
270: }
271: }
272:
273: protected void save() {
274: editor.save();
275: setModified(false);
276: }
277:
278: protected void close() {
279: quit();
280: }
281:
282: protected void quit() {
283: if (getModified()) {
284: if (exitAnyway == null) {
285: exitAnyway = new QuestionPopup(this ,
286: "Rules Modified, Quit anyway?");
287: exitAnyway.registerAnswerListener(this );
288: }
289: exitAnyway.show();
290: } else {
291: setVisible(false);
292: }
293: }
294:
295: protected String[] getTokens() {
296: String rule = trule.getText();
297: String host = thost.getText();
298: if ((rule == null) || (rule.length() == 0)) {
299: error("You must specify a rule");
300: return null;
301: }
302: if ((host == null) || (host.length() == 0)) {
303: error("You must specify a host");
304: return null;
305: }
306: Vector vtokens = new Vector(3);
307: vtokens.addElement(host);
308: vtokens.addElement(rule);
309:
310: String args = targs.getText();
311: if (args != null) {
312: StringTokenizer st = new StringTokenizer(args);
313: while (st.hasMoreTokens())
314: vtokens.addElement(st.nextToken());
315: }
316: String tokens[] = new String[vtokens.size()];
317: vtokens.copyInto(tokens);
318: return tokens;
319: }
320:
321: protected void setModified(boolean onoff) {
322: this .modified = onoff;
323: }
324:
325: protected boolean getModified() {
326: return modified;
327: }
328:
329: /**
330: * ItemListener implementation - a rule type was selected.
331: */
332: public void itemStateChanged(ItemEvent e) {
333: Object source = e.getSource();
334: if (source == lrules) {
335: this .selected = ((Integer) e.getItem()).intValue();
336: showRule(selected);
337: } else if (source == crule) {
338: String rule = (String) e.getItem();
339: trule.setText(rule);
340: if (rule.equals("direct") || rule.equals("forbid")) {
341: targs.setEditable(false);
342: targs.setText("");
343: } else {
344: targs.setEditable(true);
345: }
346: } else if (source == cargs) {
347: String arg = (String) e.getItem();
348: if (targs.isEditable())
349: targs.setText(arg);
350: }
351: }
352:
353: /**
354: * AnswerListener implemetation - yes
355: */
356: public void questionAnswered(Object source, int response) {
357: if (source == exitAnyway) {
358: exitAnyway.setVisible(false);
359: if (response == YES)
360: setVisible(false);
361: }
362: }
363:
364: protected void showRule(int idx) {
365: Rule rule = editor.getRule(idx);
366: thost.setText(rule.getHost());
367: trule.setText(rule.getRuleName());
368: String args = rule.getRuleArgs();
369: if (args != null) {
370: targs.setText(args);
371: targs.setEditable(true);
372: } else {
373: targs.setEditable(false);
374: targs.setText("");
375: }
376: }
377:
378: protected void createRulesChoice() {
379: crule = new Choice();
380: String names[] = Rule.getRulesName();
381: for (int i = 0; i < names.length; i++) {
382: crule.add(names[i]);
383: }
384: crule.addItemListener(this );
385: }
386:
387: protected void createArgsChoice() {
388: cargs = new Choice();
389: hargs = new Hashtable(10);
390: cargs.addItemListener(this );
391: }
392:
393: protected void updateArgsList(String args) {
394: if ((args != null) && (hargs.get(args) == null)) {
395: hargs.put(args, Boolean.TRUE);
396: cargs.add(args);
397: }
398: }
399:
400: protected void update() {
401: int size = editor.getSize();
402: Rule rule = null;
403:
404: setModified(false);
405: selected = -1;
406: if (lrules != null) {
407: lrules.removeAll();
408: for (int i = 0; i < size; i++) {
409: rule = editor.getRule(i);
410: lrules.addItem(rule.toString(), i);
411: updateArgsList(rule.getRuleArgs());
412: }
413: }
414: if (location != null)
415: location.setText("Rules location: "
416: + editor.component.getRulesLocation());
417: }
418:
419: RulesEditorFrame(RulesEditor editor) {
420: super ("Proxy Dispatcher Rules Editor");
421:
422: this .editor = editor;
423: lrules = new List(20, false);
424: lrules.setBackground(Color.white);
425: lrules.addItemListener(this );
426: createRulesChoice();
427: createArgsChoice();
428: update();
429: //Menu Bar
430: EditorMenu menu = new EditorMenu(this );
431: setMenuBar(menu);
432:
433: //rules list
434: BorderPanel plrules = new BorderPanel(BorderPanel.OUT, 5);
435: plrules.setLayout(new BorderLayout());
436: plrules.add(lrules);
437:
438: thost = new TextField(20);
439: trule = new TextField(15);
440: trule.setEditable(false);
441:
442: BorderPanel ptrule = new BorderPanel(BorderPanel.IN, 2);
443: ptrule.setLayout(new GridLayout(1, 1));
444: ptrule.add(trule);
445:
446: targs = new TextField(30);
447:
448: // BAR 0
449: Panel plabel = new Panel();
450: plabel.add(new Label("Host: "));
451: Panel pcrule = new Panel(new BorderLayout());
452: pcrule.add(new Label("Rule: "), "West");
453: pcrule.add(crule, "Center");
454: Panel pcargs = new Panel(new BorderLayout());
455: pcargs.add(new Label("Args: "), "West");
456: pcargs.add(cargs, "Center");
457:
458: BorderPanel phost = new BorderPanel(BorderPanel.IN, 2);
459: phost.setLayout(new GridLayout(2, 1));
460: phost.add(plabel);
461: phost.add(thost);
462:
463: BorderPanel prule = new BorderPanel(BorderPanel.IN, 2);
464: prule.setLayout(new GridLayout(2, 1));
465: prule.add(pcrule);
466: prule.add(trule);
467:
468: BorderPanel pargs = new BorderPanel(BorderPanel.IN, 2);
469: pargs.setLayout(new GridLayout(2, 1));
470: pargs.add(pcargs);
471: pargs.add(targs);
472:
473: BorderPanel bar0 = new BorderPanel(BorderPanel.OUT, 5);
474: bar0.setLayout(new GridLayout(1, 3));
475: bar0.add(phost);
476: bar0.add(prule);
477: bar0.add(pargs);
478:
479: // BAR 2
480: addB = new Button("Add Rule");
481: addB.setActionCommand("add");
482: addB.addActionListener(this );
483:
484: replaceB = new Button("Replace Rule");
485: replaceB.setActionCommand("replace");
486: replaceB.addActionListener(this );
487:
488: removeB = new Button("Remove Rule");
489: removeB.setActionCommand("remove");
490: removeB.addActionListener(this );
491:
492: Panel bar2 = new Panel(new GridLayout(1, 3));
493: bar2.add(addB);
494: bar2.add(replaceB);
495: bar2.add(removeB);
496:
497: //Label location
498: location = new Label("Rules location: "
499: + editor.component.getRulesLocation());
500: BorderPanel ploc = new BorderPanel(BorderPanel.RAISED, 1);
501: ploc.setLayout(new FlowLayout());
502: ploc.add(location);
503:
504: //Bar 2 & 3
505: BorderPanel bar2_3 = new BorderPanel(BorderPanel.OUT, 5);
506: bar2_3.setLayout(new GridLayout(2, 1));
507: bar2_3.add(bar2);
508: bar2_3.add(ploc);
509:
510: //subpanel
511: Panel subPanel = new Panel(new BorderLayout());
512: subPanel.add(plrules, "Center");
513: subPanel.add(bar0, "South");
514:
515: add(subPanel, "Center");
516: add(bar2_3, "South");
517:
518: setSize(800, 600);
519: }
520: }
521:
522: class RulesEditor {
523:
524: class Saver extends Thread {
525: RulesEditor editor = null;
526:
527: public void run() {
528: editor.saveRules();
529: }
530:
531: Saver(RulesEditor editor) {
532: this .editor = editor;
533: }
534:
535: }
536:
537: protected URL rulesUrl = null;
538: protected File rulesFile = null;
539: protected RulesEditorFrame gui = null;
540: protected HttpURLConnection con = null;
541: protected String auth = null;
542: protected DispatcherComponent component = null;
543:
544: /**
545: * The current set of rules.
546: */
547: protected Vector rules = null; //<Rule>
548:
549: protected void setURL(URL url) {
550: this .rulesFile = null;
551: this .rulesUrl = url;
552: parse();
553: }
554:
555: protected void setAuthorization(String authorization) {
556: this .auth = authorization;
557: }
558:
559: protected String getAuthorization() {
560: return auth;
561: }
562:
563: protected boolean hasAuthorization() {
564: return (auth != null);
565: }
566:
567: protected void setFile(File file) {
568: this .rulesUrl = null;
569: this .rulesFile = file;
570: parse();
571: }
572:
573: protected DataOutputStream getRulesOutputStream()
574: throws IOException {
575: DataOutputStream out = null;
576: if (rulesUrl != null) {
577: con = (HttpURLConnection) rulesUrl.openConnection();
578: con.setRequestMethod("PUT");
579: con.setRequestProperty("content-type", "text/plain");
580: if (hasAuthorization())
581: con.setRequestProperty("Authorization", "Basic "
582: + getAuthorization());
583: con.setDoOutput(true);
584: con.setDoInput(true);
585: con.setAllowUserInteraction(true);
586: out = new DataOutputStream(con.getOutputStream());
587: } else {
588: out = new DataOutputStream(new BufferedOutputStream(
589: new FileOutputStream(rulesFile)));
590: }
591: return out;
592: }
593:
594: protected boolean closeRulesOutputStream(DataOutputStream out)
595: throws IOException {
596: out.flush();
597: out.close();
598: if ((rulesUrl != null) && (con != null)) {
599: con.getHeaderField(0);
600: int code = con.getResponseCode();
601: switch (code) {
602: case HttpURLConnection.HTTP_UNAUTHORIZED:
603: //ask for a username/password
604: String encoded = gui.getAuthFromDialog();
605: if (encoded == null)
606: return true;
607: setAuthorization(encoded);
608: return false;
609: case HttpURLConnection.HTTP_CREATED:
610: case HttpURLConnection.HTTP_OK:
611: case HttpURLConnection.HTTP_NO_CONTENT:
612: gui.msg("Proxy dispatcher rules saved.");
613: return true;
614: default:
615: gui.msg("HTTP error", con.getResponseMessage());
616: return true;
617: }
618: } else {
619: gui.msg("Proxy dispatcher rules saved.");
620: return true;
621: }
622: }
623:
624: /**
625: * return the inputStream or null if the rules file doesn't exists.
626: * @return an InputStream.
627: */
628: protected InputStream getRulesInputStream() throws IOException {
629: InputStream in = null;
630: if (rulesUrl != null)
631: in = rulesUrl.openStream();
632: else if (rulesFile.exists()) {
633: in = new BufferedInputStream(new FileInputStream(
634: rulesFile));
635: }
636: return in;
637: }
638:
639: protected void save() {
640: (new Saver(this )).start();
641: }
642:
643: protected void saveRules() {
644: DataOutputStream out = null;
645: try {
646: do {
647: out = getRulesOutputStream();
648: if (rules != null) {
649: out.writeBytes("#\n# Generated by proxy "
650: + "dispatcher rules editor.\n#\n");
651: //write content here
652: for (int i = 0; i < rules.size(); i++)
653: ((Rule) rules.elementAt(i)).writeRule(out);
654: }
655: } while (!closeRulesOutputStream(out));
656: } catch (Exception ex) {
657: gui.error("Unable to save rules", ex);
658: }
659: }
660:
661: protected void parse() {
662: InputStream in = null;
663: // Try opening the rule file as a URL:
664: try {
665: in = getRulesInputStream();
666: } catch (Exception ex) {
667: gui.error("Unable to open input stream");
668: return;
669: }
670: try {
671: if (in != null) {
672: RuleParser parser = new RuleParser(in);
673: RuleNode nroot = parser.parse();
674: rules = generateRuleVector(nroot);
675: } else {
676: rules = new Vector(); //empty
677: }
678: } catch (Exception ex) {
679: gui.error("Rules parser error", ex);
680: }
681: }
682:
683: protected Vector generateRuleVector(RuleNode root) {
684: Vector vrules = new Vector(20);
685: collectRules(root, vrules);
686: Rule srules[] = new Rule[vrules.size()];
687: vrules.copyInto(srules);
688: srules = (Rule[]) Sorter.sortComparableArray(srules, true);
689: for (int i = 0; i < srules.length; i++)
690: vrules.setElementAt(srules[i], i);
691: return vrules;
692: }
693:
694: protected void collectRules(RuleNode root, Vector vrules) {
695: Hashtable childrens = root.getChildren();
696: if (childrens != null) {
697: Enumeration childenum = childrens.keys();
698: while (childenum.hasMoreElements()) {
699: RuleNode rnode = (RuleNode) childrens
700: .get((String) childenum.nextElement());
701: Rule rule = rnode.getRule();
702: if (rule != null)
703: vrules.addElement(rule);
704: collectRules(rnode, vrules);
705: }
706: }
707: }
708:
709: /**
710: * Add a Rule to the end of the rules array.
711: * @param tokens a tokens array, according to the Rule specification.
712: * @return the new added rule.
713: * @exception RuleParserException if the rule can't be created.
714: */
715: protected Rule addRule(String tokens[])
716: throws RuleParserException {
717: Rule newRule = null;
718: newRule = Rule.createRule(tokens, 1, tokens.length);
719: if (newRule != null) {
720: if (rules == null)
721: rules = new Vector(10);
722: rules.addElement(newRule);
723: }
724: return newRule;
725: }
726:
727: /**
728: * Replace the Rule at the specified index .
729: * @param tokens a tokens array, according to the Rule specification.
730: * @param idx the index.
731: * @return the new added rule.
732: * @exception RuleParserException if the rule can't be created.
733: */
734: protected Rule replaceRule(String tokens[], int idx)
735: throws RuleParserException {
736: Rule newRule = null;
737: newRule = Rule.createRule(tokens, 1, tokens.length);
738: if (newRule != null) {
739: if (rules == null)
740: rules = new Vector(10);
741: rules.setElementAt(newRule, idx);
742: }
743: return newRule;
744: }
745:
746: /**
747: * Deletes the rule at the specified index. Each rule with an index
748: * greater or equal to the specified index is shifted downward to
749: * have an index one smaller than the value it had previously.
750: * @param idx the rule index.
751: */
752: protected void removeRule(int idx) {
753: rules.removeElementAt(idx);
754: }
755:
756: protected Rule getRule(int idx) {
757: return (Rule) rules.elementAt(idx);
758: }
759:
760: /**
761: * return the number of rules.
762: */
763: protected int getSize() {
764: if (rules == null)
765: return 0;
766: return rules.size();
767: }
768:
769: public void show() {
770: gui.update();
771: gui.show();
772: }
773:
774: RulesEditor(DispatcherComponent comp, URL url) {
775: this .component = comp;
776: this .rulesUrl = url;
777: parse();
778: this .gui = new RulesEditorFrame(this );
779: }
780:
781: RulesEditor(DispatcherComponent comp, File file) {
782: this .component = comp;
783: this .rulesFile = file;
784: parse();
785: this .gui = new RulesEditorFrame(this );
786: }
787: }
788:
789: /**
790: * The TextField+Button component
791: */
792: class DispatcherComponent extends BorderPanel implements
793: ActionListener {
794: protected RulesEditor reditor = null;
795: protected TextField locationEd = null;
796: protected DispatcherRulesEditor editor = null;
797:
798: public void actionPerformed(ActionEvent e) {
799: String command = e.getActionCommand();
800: if (command != null) {
801: String loc = getRulesLocation();
802: if ((loc != null) && (loc.length() > 0)) {
803: try {
804: URL url = new URL(loc);
805: if (url.getProtocol().equalsIgnoreCase("file")) {
806: File file = new File(url.getFile());
807: if (reditor == null)
808: reditor = new RulesEditor(this , file);
809: else
810: reditor.setFile(file);
811: } else {
812: if (reditor == null)
813: reditor = new RulesEditor(this , url);
814: else
815: reditor.setURL(url);
816: }
817: } catch (MalformedURLException ex) {
818: //shoud be a file
819: File file = new File(loc);
820: if (reditor == null)
821: reditor = new RulesEditor(this , file);
822: else
823: reditor.setFile(file);
824: }
825: reditor.show();
826: }
827: }
828: }
829:
830: public String getRulesLocation() {
831: return locationEd.getText();
832: }
833:
834: public void setRulesLocation(String loc) {
835: locationEd.setText(loc);
836: }
837:
838: DispatcherComponent(DispatcherRulesEditor parent,
839: String location) {
840: super (IN, 2);
841: this .editor = parent;
842: this .locationEd = new TextField(20);
843: if (location != null)
844: this .locationEd.setText(location);
845: Button editB = new Button("Edit Rules");
846: editB.setActionCommand("edit");
847: editB.addActionListener(this );
848: setLayout(new BorderLayout());
849: add(locationEd, "Center");
850: add(editB, "East");
851: }
852: }
853:
854: //
855: // DispatcherRulesEditor
856: //
857:
858: private DispatcherComponent widget = null;
859: protected String origs = null;
860:
861: protected void createComponent(String location) {
862: widget = new DispatcherComponent(this , location);
863: }
864:
865: /**
866: * get the Component created by the editor.
867: * @return a Component
868: */
869: public Component getComponent() {
870: return widget;
871: }
872:
873: /**
874: * Tells if the edited value has changed
875: * @return true if the value changed.
876: */
877:
878: public boolean hasChanged() {
879: return !origs.equals(widget.getRulesLocation());
880: }
881:
882: /**
883: * set the current value to be the original value, ie: changed
884: * must return <strong>false</strong> after a reset.
885: */
886:
887: public void clearChanged() {
888: origs = widget.getRulesLocation();
889: }
890:
891: /**
892: * reset the changes (if any)
893: */
894:
895: public void resetChanges() {
896: widget.setRulesLocation(origs);
897: }
898:
899: /**
900: * Get the current value of the edited value
901: * @return an object or <strong>null</strong> if the object was not
902: * initialized
903: */
904:
905: public Object getValue() {
906: return widget.getRulesLocation();
907: }
908:
909: /**
910: * Set the value of the edited value
911: * @param o the new value.
912: */
913:
914: public void setValue(Object o) {
915: widget.setRulesLocation(o.toString());
916: }
917:
918: /**
919: * Initialize the editor
920: * @param w the ResourceWrapper father of the attribute
921: * @param a the Attribute we are editing
922: * @param o the value of the above attribute
923: * @param p some Properties, used to fine-tune the editor
924: * @exception RemoteAccessException if a remote access error occurs.
925: */
926:
927: public void initialize(RemoteResourceWrapper w, Attribute a,
928: Object o, Properties p) throws RemoteAccessException {
929: RemoteResource r = w.getResource();
930: if (o == null) {
931: String v = null;
932: // FIXME
933: v = (String) r.getValue(a.getName());
934:
935: if (v == null)
936: if (a.getDefault() != null)
937: v = a.getDefault().toString();
938: if (v != null) {
939: origs = v;
940: }
941: } else {
942: origs = o.toString();
943: }
944: createComponent(origs);
945: }
946:
947: public DispatcherRulesEditor() {
948: origs = "";
949: }
950:
951: }
|