home *** CD-ROM | disk | FTP | other *** search
/ Java Developer's Companion / Java Developer's Companion.iso / Javacup / PR8ADPL7.TAR / productivity_tools / PR8ADPL7 / AdminComponent.java < prev    next >
Encoding:
Java Source  |  1996-05-23  |  23.4 KB  |  960 lines

  1. // AdminComponent.java
  2. // A JFS application for performing various admin tasks on a JFS server.
  3. // For example    - adding/deleting/changing users
  4. //        - adding/deleting/changing printers
  5. //        - monitoring connections
  6. //        - getting/setting server properties
  7. import java.awt.*;
  8. import java.util.Vector;
  9. import java.util.Date;
  10. import java.util.StringTokenizer;
  11. import java.io.IOException;
  12.  
  13. public class AdminComponent extends JFScomponent
  14. {
  15.     UsersPanel up;
  16.     PrintersPanel pp;
  17.     ConnectionsPanel cp;
  18.     PropertiesPanel rp;
  19.     DevicesPanel dp;
  20.  
  21.     // init
  22.     // Setup this component
  23.     void init(java.applet.Applet ap)
  24.     {
  25.     // create user interface
  26.     setLayout(new BorderLayout());
  27.     TabbedPanel t = new TabbedPanel();
  28.     t.addItem("Users",up = new UsersPanel());
  29.     t.addItem("Printers",pp = new PrintersPanel());
  30.     t.addItem("Connections",cp = new ConnectionsPanel());
  31.     t.addItem("Properties",rp = new PropertiesPanel());
  32.     t.addItem("Devices",dp = new DevicesPanel());
  33.     add("Center",t);
  34.     }
  35.  
  36.     // connect
  37.     // Use this client for talking to the server
  38.     void connect(JFSclient c)
  39.     {
  40.     super.connect(c);
  41.     if (!client.authname.equals("root")) {
  42.         new ErrorWindow("Only root can run the AdminComponent tool");
  43.         client = null;
  44.         return;
  45.         }
  46.     up.connect(client);
  47.     pp.connect(client);
  48.     cp.connect(client);
  49.     rp.connect(client);
  50.     dp.connect(client);
  51.     }
  52.  
  53.     Dimension wantedsize()
  54.     {
  55.     return new Dimension(500,300);
  56.     }
  57. }
  58.  
  59.  
  60. // UsersPanel
  61. // A panel displaying a list of all server users for addition, deletion and
  62. // modification.
  63. class UsersPanel extends Panel
  64. {
  65.     JFSclient client;
  66.     Vector users = new Vector();
  67.     DoubleListPanel list;
  68.     Button add,del,mod;
  69.  
  70.     UsersPanel()
  71.     {
  72.     setLayout(new BorderLayout());
  73.     add("Center",list = new DoubleListPanel("Username","Real name"));
  74.     Panel top = new Panel();
  75.     top.setLayout(new FlowLayout(FlowLayout.LEFT));
  76.     top.add(add = new Button("Add"));
  77.     top.add(del = new Button("Delete"));
  78.     top.add(mod = new Button("Modify"));
  79.     add("North",top);
  80.     }
  81.  
  82.     // connect
  83.     // Retrieve a list of users from the server
  84.     void connect(JFSclient c)
  85.     {
  86.     // Build list of JFSuser structures
  87.     client = c;
  88.     BufferInputStream buf = null;
  89.     try buf = new BufferInputStream(client.get("/etc/users",0));
  90.     catch(RequestException e) {
  91.         new ErrorWindow("Could not read /etc/users : "+e.getMessage());
  92.         return;
  93.         }
  94.     try {
  95.         while(true)
  96.             users.addElement(new JFSuser(buf.gets()));
  97.         }
  98.     catch(IOException e);
  99.     fill();
  100.     }
  101.  
  102.     // fill
  103.     // Fill the list with known users
  104.     void fill()
  105.     {
  106.     // Display the list
  107.     list.clear();
  108.     for(int i=0; i<users.size(); i++) {
  109.         JFSuser u = (JFSuser)users.elementAt(i);
  110.         list.addItem(u.name, u.realname);
  111.         }
  112.     }
  113.  
  114.     // write
  115.     // Write the list of users back to /etc/users
  116.     void write()
  117.     {
  118.     BufferOutputStream buf = new BufferOutputStream();
  119.     for(int i=0; i<users.size(); i++)
  120.         buf.puts(((JFSuser)users.elementAt(i)).output());
  121.     try client.put("/etc/users", 0, buf.getarray(), "text/plain");
  122.     catch(RequestException e)
  123.         new ErrorWindow("Failed to write to /etc/users : "+
  124.                 e.getMessage());
  125.     }
  126.  
  127.     public boolean action(Event evt, Object obj)
  128.     {
  129.     int sel = list.selected();
  130.     if (evt.target == add) {
  131.         // Add button clicked. Open new user details requestor.
  132.         new UserEditRequestor(this);
  133.         }
  134.     else if (evt.target == del) {
  135.         // Delete button clicked. Remove this user
  136.         if (sel < 0) return false;
  137.         users.removeElementAt(sel);
  138.         fill();
  139.         write();
  140.         }
  141.     else if (evt.target == mod ||
  142.          evt.target == list && ((String)evt.arg).equals("Double")) {
  143.         // Modify button clicked. Open requestor to edit user
  144.         if (sel < 0) return false;
  145.         new UserEditRequestor(this, sel);
  146.         }
  147.     return true;
  148.     }
  149. }
  150.  
  151. // UserEditRequestor
  152. // A window for editing or adding a user
  153. class UserEditRequestor extends FixedFrame
  154. {
  155.     UsersPanel parent;
  156.     int sel = -1;
  157.     TextField name, real, password, homedir, groups;
  158.     Checkbox homeyes, homeno;
  159.     Button ok,cancel;
  160.  
  161.     // Create a requestor for adding a new user
  162.     UserEditRequestor(UsersPanel p)
  163.     {
  164.     super(new Dimension(300, -1));
  165.     parent = p;
  166.     // create user interface
  167.     setLayout(new BorderLayout());
  168.     Panel top = new Panel();
  169.     top.setLayout(new BorderLayout());
  170.     Panel left = new Panel();
  171.     left.setLayout(new GridLayout(6,1));
  172.     left.add(new Label("Username"));
  173.     left.add(new Label("Real name"));
  174.     left.add(new Label("Password"));
  175.     left.add(new Label("Groups"));
  176.     left.add(new Label("Home dir"));
  177.     left.add(new Label("Create home dir"));
  178.     top.add("West",left);
  179.     Panel right = new Panel();
  180.     right.setLayout(new GridLayout(6,1));
  181.     right.add(name = new TextField());
  182.     right.add(real = new TextField());
  183.     right.add(password = new TextField());
  184.     right.add(groups = new TextField());
  185.     right.add(homedir = new TextField());
  186.     Panel hp = new Panel();
  187.     hp.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0));
  188.     CheckboxGroup hg = new CheckboxGroup();
  189.     hp.add(homeyes = new Checkbox("Yes", hg, true));
  190.     hp.add(homeno  = new Checkbox("No", hg, false));
  191.     right.add(hp);
  192.     top.add("Center",right);
  193.     add("North",top);
  194.     Panel bot = new Panel();
  195.     bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
  196.     bot.add(ok = new Button("Ok"));
  197.     bot.add(cancel = new Button("Cancel"));
  198.     add("South",bot);
  199.     setTitle("User details");
  200.     pack();
  201.     show();
  202.     }
  203.  
  204.     // Create a requestor for editing an existing user
  205.     UserEditRequestor(UsersPanel p, int s)
  206.     {
  207.     this(p);
  208.     sel = s;
  209.     JFSuser u = (JFSuser)parent.users.elementAt(sel);
  210.     name.setText(u.name);
  211.     name.setEditable(false);
  212.     real.setText(u.realname);
  213.     password.setText(u.password);
  214.     homedir.setText(u.home);
  215.     String g = "";
  216.     for(int i=0; i<u.groups.size(); i++) {
  217.         g += (String)u.groups.elementAt(i);
  218.         if (i != u.groups.size()-1)
  219.             g += ",";
  220.         }
  221.     groups.setText(g);
  222.     }
  223.  
  224.     public boolean handleEvent(Event evt)
  225.     {
  226.     if (evt.id == Event.WINDOW_DESTROY ||
  227.         evt.id == Event.ACTION_EVENT && evt.target == cancel)
  228.         dispose();
  229.     else if (evt.id == Event.ACTION_EVENT && evt.target == ok) {
  230.         // Add or update this user
  231.  
  232.         // Build a new user structure
  233.         JFSuser nu = new JFSuser();
  234.         nu.name = name.getText();
  235.         if (nu.name.trim().length() == 0) {
  236.             new ErrorWindow("Empty username");
  237.             return true;
  238.             }
  239.         nu.realname = real.getText();
  240.         nu.password = password.getText();
  241.         nu.home = homedir.getText();
  242.         StringSplitter tok = new StringSplitter(groups.getText(),',');
  243.         String gr;
  244.         while((gr = tok.nextToken()) != null) {
  245.             // Check and add each group name
  246.             if (gr.trim().length() == 0)
  247.                 continue;    // useless string
  248.             for(int i=0; i<parent.users.size(); i++) {
  249.                 JFSuser eu = (JFSuser)parent.users.elementAt(i);
  250.                 if (eu.name.equals(gr)) {
  251.                     // oh no! a user with this group name
  252.                     // already exists.
  253.                     new ErrorWindow("The group name "+gr+
  254.                             " cannot be used, as "+
  255.                             "it belongs to a user");
  256.                     return true;
  257.                     }
  258.                 }
  259.             nu.groups.addElement(gr);
  260.             }
  261.  
  262.         // Try to find a user with this name
  263.         JFSuser existing = null;
  264.         for(int i=0; i<parent.users.size(); i++) {
  265.             JFSuser eu = (JFSuser)parent.users.elementAt(i);
  266.             if (eu.name.equals(nu.name))
  267.                 existing = eu;
  268.             }
  269.  
  270.         if (sel < 0) {
  271.             // Create a new user
  272.             if (existing != null) {
  273.                 new ErrorWindow("A user with the name "+
  274.                         nu.name+" already exists");
  275.                 return true;
  276.                 }
  277.             }
  278.         else {
  279.             // modify an existing one
  280.             parent.users.removeElement(existing);
  281.             }
  282.         parent.users.addElement(nu);
  283.         parent.fill();
  284.         parent.write();
  285.  
  286.         // Create home directory if needed
  287.         if (homeyes.getState()) {
  288.             boolean made = true;
  289.             try parent.client.mkdir(homedir.getText());
  290.             catch(RequestException e)
  291.                 made = false;
  292.             if (made) {
  293.                 // chmod home dir
  294.                 try parent.client.chmod(homedir.getText(),
  295.                             name.getText(), "rwp");
  296.                 catch(RequestException e);
  297.                 }
  298.             }
  299.  
  300.         dispose();
  301.         }
  302.     return super.handleEvent(evt);
  303.     }
  304. }
  305.  
  306.  
  307. // PrintersPanel
  308. // Displays a list of all printers from /etc/printers, for addition,
  309. // modification and deletion
  310. class PrintersPanel extends Panel
  311. {
  312.     JFSclient client;
  313.     Vector name = new Vector(), type = new Vector(),
  314.            desc = new Vector(), comm = new Vector();
  315.     DoubleListPanel list;
  316.     Button add,del,mod;
  317.  
  318.     PrintersPanel()
  319.     {
  320.     setLayout(new BorderLayout());
  321.     add("Center",list = new DoubleListPanel("Name","Description"));
  322.     Panel top = new Panel();
  323.     top.setLayout(new FlowLayout(FlowLayout.LEFT));
  324.     top.add(add = new Button("Add"));
  325.     top.add(del = new Button("Delete"));
  326.     top.add(mod = new Button("Modify"));
  327.     add("North",top);
  328.     }
  329.  
  330.     // connect
  331.     // Read and display a list of printers from the server
  332.     void connect(JFSclient c)
  333.     {
  334.     client = c;
  335.     try client.getprinters(name, type, desc, comm);
  336.     catch(RequestException e) {
  337.         new ErrorWindow("Could not read /etc/printers : "+
  338.                 e.getMessage());
  339.         return;
  340.         }
  341.     fill();
  342.     }
  343.  
  344.     // fill
  345.     // Fill the list with known printers
  346.     void fill()
  347.     {
  348.     list.clear();
  349.     for(int i=0; i<name.size(); i++)
  350.         list.addItem((String)name.elementAt(i),
  351.                  (String)desc.elementAt(i));
  352.     }
  353.  
  354.     // write
  355.     // Output the list of printers to /etc/printers
  356.     void write()
  357.     {
  358.     BufferOutputStream buf = new BufferOutputStream();
  359.     for(int i=0; i<name.size(); i++) {
  360.         StringJoiner j = new StringJoiner(':');
  361.         j.add((String)name.elementAt(i));
  362.         j.add((String)type.elementAt(i));
  363.         j.add((String)desc.elementAt(i));
  364.         j.add((String)comm.elementAt(i));
  365.         buf.puts(j.toString());
  366.         }
  367.     try client.put("/etc/printers", 0, buf.getarray(), "text/plain");
  368.     catch(RequestException e)
  369.         new ErrorWindow("Failed to write to /etc/printer : "+
  370.                 e.getMessage());
  371.     }
  372.  
  373.     public boolean action(Event evt, Object obj)
  374.     {
  375.     int sel = list.selected();
  376.     if (evt.target == add) {
  377.         // Add printer button clicked. Open new printer details req.
  378.         new PrinterEditRequestor(this);
  379.         }
  380.     else if (evt.target == del) {
  381.         // Delete button clicked. Remove selected printer
  382.         if (sel < 0)  return false;
  383.         name.removeElementAt(sel);
  384.         type.removeElementAt(sel);
  385.         desc.removeElementAt(sel);
  386.         comm.removeElementAt(sel);
  387.         fill();
  388.         write();
  389.         }
  390.     else if (evt.target == mod ||
  391.          evt.target == list && ((String)evt.arg).equals("Double")) {
  392.         // Modify button clicked. Open requestor to edit printer
  393.         if (sel < 0) return false;
  394.         new PrinterEditRequestor(this, sel);
  395.         }
  396.     return true;
  397.     }
  398. }
  399.  
  400. // PrinterEditRequestor
  401. // A pop-up window for entering details of a new or existing printer
  402. class PrinterEditRequestor extends FixedFrame
  403. {
  404.     PrintersPanel parent;
  405.     int sel = -1;
  406.     TextField name, type, desc, comm;
  407.     Button ok, cancel;
  408.  
  409.     // Create a requestor for adding a new printer
  410.     PrinterEditRequestor(PrintersPanel p)
  411.     {
  412.     super(new Dimension(300, -1));
  413.     parent = p;
  414.     // create UI
  415.     setLayout(new BorderLayout());
  416.     Panel top = new Panel();
  417.     top.setLayout(new BorderLayout());
  418.     Panel left = new Panel();
  419.     left.setLayout(new GridLayout(4,1));
  420.     left.add(new Label("Name"));
  421.     left.add(new Label("Type"));
  422.     left.add(new Label("Description"));
  423.     left.add(new Label("Command"));
  424.     top.add("West",left);
  425.     Panel right = new Panel();
  426.     right.setLayout(new GridLayout(4,1));
  427.     right.add(name = new TextField());
  428.     right.add(type = new TextField());
  429.     right.add(desc = new TextField());
  430.     right.add(comm = new TextField());
  431.     top.add("Center",right);
  432.     add("North",top);
  433.     Panel bot = new Panel();
  434.     bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
  435.     bot.add(ok = new Button("Ok"));
  436.     bot.add(cancel = new Button("Cancel"));
  437.     add("South",bot);
  438.     setTitle("Printer details");
  439.     pack();
  440.     show();
  441.     }
  442.  
  443.     PrinterEditRequestor(PrintersPanel p, int s)
  444.     {
  445.     this(p);
  446.     sel = s;
  447.     name.setText((String)parent.name.elementAt(sel));
  448.     name.setEditable(false);
  449.     type.setText((String)parent.type.elementAt(sel));
  450.     desc.setText((String)parent.desc.elementAt(sel));
  451.     comm.setText((String)parent.comm.elementAt(sel));
  452.     }
  453.  
  454.     public boolean handleEvent(Event evt)
  455.     {
  456.     if (evt.id == Event.WINDOW_DESTROY ||
  457.         evt.id == Event.ACTION_EVENT && evt.target == cancel)
  458.         dispose();
  459.     else if (evt.id == Event.ACTION_EVENT && evt.target == ok) {
  460.         // Add or update this printer
  461.  
  462.         // Try to find a printer with this name
  463.         int old = -1;
  464.         for(int i=0; i<parent.name.size(); i++) {
  465.             String oldname = (String)parent.name.elementAt(i);
  466.             if (oldname.equals(name.getText()))
  467.                 old = i;
  468.             }
  469.  
  470.         if (sel < 0) {
  471.             // Is this a unique name?
  472.             if (old != -1) {
  473.                 new ErrorWindow("A printer with the name "+
  474.                         name.getText()+" exists");
  475.                 return true;
  476.                 }
  477.             }
  478.         else {
  479.             // Remove old printer
  480.             parent.name.removeElementAt(old);
  481.             parent.type.removeElementAt(old);
  482.             parent.desc.removeElementAt(old);
  483.             parent.comm.removeElementAt(old);
  484.             }
  485.         parent.name.addElement(name.getText());
  486.         parent.type.addElement(type.getText());
  487.         parent.desc.addElement(desc.getText());
  488.         parent.comm.addElement(comm.getText());
  489.         parent.fill();
  490.         parent.write();
  491.         dispose();
  492.         }
  493.     return super.handleEvent(evt);
  494.     }
  495. }
  496.  
  497.  
  498. // ConnectionsPanel
  499. // Displays the list of current connections to the server
  500. class ConnectionsPanel extends Panel
  501. {
  502.     JFSclient client;
  503.     DoubleListPanel clist;
  504.     Button cref, cinfo, ckill;
  505.  
  506.     Vector id, host, name, last, sent, recv;
  507.  
  508.     ConnectionsPanel()
  509.     {
  510.     // Create user interface
  511.     setLayout(new BorderLayout());
  512.     add("Center",clist = new DoubleListPanel("Host","User"));
  513.     Panel top = new Panel();
  514.     top.setLayout(new FlowLayout(FlowLayout.LEFT));
  515.     top.add(cref = new Button("Refresh"));
  516.     top.add(cinfo = new Button("Info"));
  517.     top.add(ckill = new Button("Kill"));
  518.     add("North",top);
  519.  
  520.     }
  521.  
  522.     // connect
  523.     // Read and display connections
  524.     void connect(JFSclient c)
  525.     {
  526.     client = c;
  527.     cread();
  528.     cfill();
  529.     }
  530.  
  531.     // cread
  532.     // Get the list of active connections from the server
  533.     void cread()
  534.     {
  535.     BufferInputStream buf = null;
  536.     Message head = new Message();
  537.     head.add("Command","Netstat");
  538.     try buf = new BufferInputStream(
  539.             client.devget("/dev/Server", head).getdata());
  540.     catch(RequestException e) {
  541.         new ErrorWindow("Could not read /dev/Server : "+
  542.                 e.getMessage());
  543.         return;
  544.         }
  545.     id = new Vector(); host = new Vector(); name = new Vector();
  546.     last = new Vector(); sent = new Vector(); recv = new Vector();
  547.     try {
  548.         while(true) {
  549.             String line = buf.gets();
  550.             StringSplitter tok = new StringSplitter(line, ':');
  551.             id.addElement(new Integer(tok.nextToken()));
  552.             host.addElement(tok.nextToken());
  553.             name.addElement(tok.nextToken());
  554.             last.addElement(new Long(tok.nextToken()));
  555.             sent.addElement(new Integer(tok.nextToken()));
  556.             recv.addElement(new Integer(tok.nextToken()));
  557.             }
  558.         }
  559.     catch(IOException e);
  560.     }
  561.  
  562.     // cfill
  563.     // Fill the connections list with current connections
  564.     void cfill()
  565.     {
  566.     clist.clear();
  567.     for(int i=0; i<id.size(); i++)
  568.         clist.addItem((String)host.elementAt(i),
  569.                   (String)name.elementAt(i));
  570.     }
  571.  
  572.     public boolean action(Event evt, Object obj)
  573.     {
  574.     int sel = clist.selected();
  575.     if (evt.target == cref) {
  576.         // refresh button clicked
  577.         cread();
  578.         cfill();
  579.         }
  580.     else if (evt.target == cinfo || 
  581.          evt.target == clist && ((String)evt.arg).equals("Double")) {
  582.         // Info button clicked
  583.         if (sel < 0) return true;
  584.         new ConnectionInfoRequestor(
  585.             ((Integer)id.elementAt(sel)).intValue(),
  586.             (String)host.elementAt(sel),
  587.             (String)name.elementAt(sel),
  588.             ((Long)last.elementAt(sel)).longValue(),
  589.             ((Integer)sent.elementAt(sel)).intValue(),
  590.             ((Integer)recv.elementAt(sel)).intValue() );
  591.         }
  592.     else if (evt.target == ckill) {
  593.         // Kill connection button clicked
  594.         if (sel < 0) return true;
  595.         int cid = ((Integer)id.elementAt(sel)).intValue();
  596.         Message head = new Message();
  597.         head.add("Command","Kill");
  598.         head.add("Id",String.valueOf(cid));
  599.         try client.devput("/dev/Server", null, head);
  600.         catch(RequestException e)
  601.             new ErrorWindow("Failed to kill connection : "+
  602.                     e.getMessage());
  603.         cread();
  604.         cfill();
  605.         }
  606.     return true;
  607.     }
  608. }
  609.  
  610. // ConnectionInfoRequestor
  611. // A window for displaying information about one connection to the server
  612. class ConnectionInfoRequestor extends FixedFrame
  613. {
  614.     Button close;
  615.  
  616.     ConnectionInfoRequestor(int id, String host, String name,
  617.                 long last, int sent, int recv)
  618.     {
  619.     super(new Dimension(300, -1));
  620.     setLayout(new BorderLayout());
  621.     Panel top = new Panel();
  622.     top.setLayout(new BorderLayout());
  623.     Panel left = new Panel();
  624.     left.setLayout(new GridLayout(6,1));
  625.     left.add(new Label("Connection ID"));
  626.     left.add(new Label("Hostname"));
  627.     left.add(new Label("Username"));
  628.     left.add(new Label("Last activity"));
  629.     left.add(new Label("Bytes sent"));
  630.     left.add(new Label("Bytes received"));
  631.     top.add("West",left);
  632.     Panel right = new Panel();
  633.     right.setLayout(new GridLayout(6,1));
  634.     right.add(new StaticTextField(String.valueOf(id)));
  635.     right.add(new StaticTextField(host));
  636.     right.add(new StaticTextField(name));
  637.     right.add(new StaticTextField(new Date(last).toString()));
  638.     right.add(new StaticTextField(String.valueOf(sent)));
  639.     right.add(new StaticTextField(String.valueOf(recv)));
  640.     top.add("Center",right);
  641.     add("North",top);
  642.     Panel bot = new Panel();
  643.     bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
  644.     bot.add(close = new Button("Close"));
  645.     add("South",bot);
  646.  
  647.     setTitle("Connection info");
  648.     pack();
  649.     show();
  650.     }
  651.  
  652.     public boolean handleEvent(Event evt)
  653.     {
  654.     if (evt.id == Event.WINDOW_DESTROY ||
  655.         evt.id == Event.ACTION_EVENT && evt.target == close)
  656.         dispose();
  657.     return super.handleEvent(evt);
  658.     }
  659. }
  660.  
  661. // PropertiesPanel
  662. // Displays all server properties currently stored on the server
  663. class PropertiesPanel extends Panel
  664. {
  665.     JFSclient client;
  666.     DoubleListPanel plist;
  667.     TextField pname, puser, pvalue;
  668.     Button psave, pnew, pdel, pref;
  669.  
  670.     Vector prop;        // properties from server
  671.  
  672.     PropertiesPanel()
  673.     {
  674.     // create user interface
  675.     setLayout(new GridLayout(1,2));
  676.     Panel left = new Panel();
  677.     left.setLayout(new BorderLayout());
  678.     left.add("Center", plist = new DoubleListPanel("Property", "Owner"));
  679.     left.add("South", pref = new Button("Refresh"));
  680.     add(left);
  681.     Panel right = new Panel();
  682.     right.setLayout(new BorderLayout());
  683.     Panel rt = new Panel();
  684.     rt.setLayout(new GridLayout(6,1));
  685.     rt.add(new Label("Property"));
  686.     rt.add(pname = new TextField());
  687.     rt.add(new Label("Owner"));
  688.     rt.add(puser = new TextField());
  689.     rt.add(new Label("Value"));
  690.     rt.add(pvalue = new TextField());
  691.     right.add("North",rt);
  692.     Panel rb = new Panel();
  693.     rb.setLayout(new FlowLayout(FlowLayout.RIGHT));
  694.     rb.add(psave = new Button("Save"));
  695.     rb.add(pnew = new Button("New"));
  696.     rb.add(pdel = new Button("Delete"));
  697.     right.add("South",rb);
  698.     add(right);
  699.     }
  700.  
  701.     // connect
  702.     // Read and display properties
  703.     void connect(JFSclient c)
  704.     {
  705.     client = c;
  706.     pread();
  707.     pfill();
  708.     }
  709.  
  710.     // pread
  711.     // Read all properties from the server
  712.     void pread()
  713.     {
  714.     prop = new Vector();
  715.     Message head = new Message(), r = null;
  716.     head.add("Command","Properties");
  717.     try r = client.devget("/dev/Server", head);
  718.     catch(RequestException e) {
  719.         new ErrorWindow("Failed to read properties from server");
  720.         return;
  721.         }
  722.     BufferInputStream buf = new BufferInputStream(r.getdata());
  723.     try {
  724.         while(true)
  725.             prop.addElement(new ServerProperty(buf.gets()));
  726.         }
  727.     catch(IOException e);
  728.     }
  729.  
  730.     // pfill
  731.     // Display properties in the list
  732.     void pfill()
  733.     {
  734.     plist.clear();
  735.     for(int i=0; i<prop.size(); i++) {
  736.         ServerProperty p = (ServerProperty)prop.elementAt(i);
  737.         plist.addItem(p.name, p.user);
  738.         }
  739.     }
  740.  
  741.     public boolean action(Event evt, Object obj)
  742.     {
  743.     if (evt.target == plist) {
  744.         // Property chosen from list
  745.         int sel = plist.selected();
  746.         ServerProperty p = (ServerProperty)prop.elementAt(sel);
  747.         pname.setText(p.name);
  748.         puser.setText(p.user);
  749.         pvalue.setText(p.value);
  750.         setmod(p.external);
  751.         }
  752.     else if (evt.target == pref) {
  753.         // Refresh properties button clicked
  754.         pread();
  755.         pfill();
  756.         }
  757.     else if (evt.target == pnew) {
  758.         // New button clicked
  759.         pname.setText("");
  760.         puser.setText("");
  761.         pvalue.setText("");
  762.         setmod(true);
  763.         }
  764.     else if (evt.target == psave) {
  765.         // Save property button clicked
  766.         ServerProperty np = new ServerProperty(pname.getText(),
  767.                                puser.getText(),
  768.                                pvalue.getText(),
  769.                                true);
  770.         client.putprop(np);
  771.         pread();
  772.         pfill();
  773.         }
  774.     else if (evt.target == pdel) {
  775.         // Delete property button clicked
  776.         int sel = plist.selected();
  777.         if (sel < 0) return true;
  778.         ServerProperty vic = (ServerProperty)prop.elementAt(sel);
  779.         client.delprop(vic.name, vic.user);
  780.         pread();
  781.         pfill();
  782.         }
  783.     return true;
  784.     }
  785.  
  786.     // setmod
  787.     // Enable or display editing of property details
  788.     void setmod(boolean m)
  789.     {
  790.     pname.setEditable(m);
  791.     puser.setEditable(m);
  792.     pvalue.setEditable(m);
  793.     psave.enable(m);
  794.     }
  795. }
  796.  
  797. // DevicesPanel
  798. // Displays devices files in /dev and their permissions.
  799. class DevicesPanel extends Panel
  800. {
  801.     JFSclient client;
  802.     JFSdirectory devices;
  803.     DoubleListPanel list;
  804.     Button add, del;
  805.  
  806.     DevicesPanel()
  807.     {
  808.     setLayout(new BorderLayout());
  809.     add("Center", list = new DoubleListPanel("Device", "Permissions"));
  810.     Panel top = new Panel();
  811.     top.setLayout(new FlowLayout(FlowLayout.LEFT));
  812.     top.add(add = new Button("Add"));
  813.     top.add(del = new Button("Delete"));
  814.     add("North", top);
  815.     }
  816.  
  817.     // connect
  818.     // Retrieve a list of devices from the server
  819.     void connect(JFSclient c)
  820.     {
  821.     client = c;
  822.     JFSdirectory d = null;
  823.     try devices = client.getdir("/dev");
  824.     catch(RequestException e) {
  825.         new ErrorWindow("Could not read /dev : "+e.getMessage());
  826.         return;
  827.         }
  828.     fill();
  829.     }
  830.  
  831.     // fill
  832.     // Display the important stuff from /dev in the list
  833.     void fill()
  834.     {
  835.     list.clear();
  836.     for(int i=0; i<devices.size(); i++) {
  837.         JFSfile f = devices.find(i);
  838.         String p = "";
  839.         for(int j=0; j<f.users.size(); j++) {
  840.             JFSfileuser u = (JFSfileuser)f.users.elementAt(j);
  841.             p += u.name + " (" + u.rwp + ")  ";
  842.             }
  843.         list.addItem("/dev/"+f.name, p);
  844.         }
  845.     }
  846.  
  847.     public boolean action(Event evt, Object obj)
  848.     {
  849.     if (evt.target == add) {
  850.         // Add device button clicked
  851.         new DeviceEditRequestor(this);
  852.         }
  853.     else if (evt.target == del) {
  854.         // Delete device button clicked
  855.         int sel = list.selected();
  856.         if (sel < 0) return false;
  857.         JFSfile doomed = devices.find(sel);
  858.         try client.delete("/dev/"+doomed.name, 0);
  859.         catch(RequestException e) {
  860.             new ErrorWindow("Failed to delete device : "+
  861.                     e.getMessage());
  862.             return false;
  863.             }
  864.         devices.delete(doomed);
  865.         fill();
  866.         }
  867.     return true;
  868.     }
  869. }
  870.  
  871. // DeviceEditRequestor
  872. // A pop-up window for creating a new device entry
  873. class DeviceEditRequestor extends FixedFrame
  874. {
  875.     DevicesPanel parent;
  876.     TextField name;
  877.     Choice perms;
  878.     Button ok, cancel;
  879.  
  880.     DeviceEditRequestor(DevicesPanel p)
  881.     {
  882.     super(new Dimension(250, -1));
  883.     parent = p;
  884.  
  885.     // create UI
  886.     setLayout(new BorderLayout());
  887.     Panel top = new Panel();
  888.     top.setLayout(new BorderLayout());
  889.     Panel left = new Panel();
  890.     left.setLayout(new GridLayout(2,1));
  891.     left.add(new Label("Name"));
  892.     left.add(new Label("Permissions"));
  893.     top.add("West", left);
  894.     Panel right = new Panel();
  895.     right.setLayout(new GridLayout(2,1));
  896.     right.add(name = new TextField());
  897.     right.add(perms = new Choice());
  898.     perms.addItem("No access");
  899.     perms.addItem("Read only");
  900.     perms.addItem("Write only");
  901.     perms.addItem("Read and write");
  902.     top.add("Center", right);
  903.     add("North", top);
  904.     Panel bot = new Panel();
  905.     bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
  906.     bot.add(ok = new Button("Ok"));
  907.     bot.add(cancel = new Button("Cancel"));
  908.     add("South", bot);
  909.  
  910.     setTitle("New device");
  911.     pack();
  912.     show();
  913.     }
  914.  
  915.     public boolean handleEvent(Event evt)
  916.     {
  917.     if (evt.id == Event.WINDOW_DESTROY ||
  918.         evt.id == Event.ACTION_EVENT && evt.target == cancel)
  919.         dispose();
  920.     else if (evt.id == Event.ACTION_EVENT && evt.target == ok) {
  921.         // add this device
  922.         String nm = name.getText();
  923.  
  924.         // does it already exist?
  925.         if (parent.devices.find(nm) != null) {
  926.             new ErrorWindow("A device with the name "+nm+
  927.                     " already exists");
  928.             return false;
  929.             }
  930.  
  931.         // create file in /dev
  932.         String path = "/dev/"+nm;
  933.         try parent.client.put(path, 0, new byte[0], "jfs/special");
  934.         catch(RequestException e) {
  935.             new ErrorWindow("Could not create device : "+
  936.                     e.getMessage());
  937.             return false;
  938.             }
  939.         int ch =perms.getSelectedIndex();
  940.         if (ch != 0) {
  941.             try parent.client.chmod(path, "all",ch==1 ? "r" :
  942.                                 ch==2 ? "w" : "rw");
  943.             catch(RequestException e) {
  944.                 new ErrorWindow("Could not set permissions : "+
  945.                         e.getMessage());
  946.                 return false;
  947.                 }
  948.             }
  949.  
  950.         // update list
  951.         try parent.devices.add(parent.client.statfile(path));
  952.         catch(RequestException e);
  953.         parent.fill();
  954.         dispose();
  955.         }
  956.     return super.handleEvent(evt);
  957.     }
  958. }
  959.  
  960.