]> andersk Git - moira.git/commitdiff
Make Moira Java Object thread safe (provide mutex locking of a sorts)
authorjis <jis>
Sun, 21 Oct 2001 18:43:58 +0000 (18:43 +0000)
committerjis <jis>
Sun, 21 Oct 2001 18:43:58 +0000 (18:43 +0000)
webmoira/Makefile.in
webmoira/mit/moira/Kticket.java
webmoira/mit/moira/Moira.java [moved from webmoira/mit/moira/MoiraConnect.java with 50% similarity]
webmoira/mit/moira/MoiraServlet.java

index e19f0791a09d61531989dbffa51e387c282b218a..0a19e683fdcb86c87d94bba1480930258808067a 100644 (file)
@@ -24,7 +24,7 @@ prefix=@prefix@
 exec_prefix=@exec_prefix@
 bindir=@bindir@
 
-CLASSES= mit/moira/AuthenticationError.class mit/moira/Coder.class mit/moira/Delmember.class mit/moira/Kticket.class mit/moira/ListInfo.class mit/moira/Member.class mit/moira/MoiraConnect.class mit/moira/MoiraConnectInternal.class mit/moira/MoiraException.class mit/moira/MoiraServlet.class
+CLASSES= mit/moira/AuthenticationError.class mit/moira/Coder.class mit/moira/Delmember.class mit/moira/Kticket.class mit/moira/ListInfo.class mit/moira/Member.class mit/moira/Moira.class mit/moira/MoiraConnectInternal.class mit/moira/MoiraException.class mit/moira/MoiraServlet.class
 OBJ=     moirai.o
 SOBJ=    mit/moira/libmoirajava.so
 SOBJG=   mit/moira/libmoirajava_g.so
index 28c6f445a5ce8ae3427bfd37e12877206b6498e2..cc7d35ffe956cd6b5455648b528756750abc7c44 100644 (file)
@@ -4,7 +4,6 @@ import java.util.Date;
 import java.io.IOException;
 
 public class Kticket implements Runnable {
-    Object LOCK;
     String name;
     String instance;
     String realm;
@@ -12,11 +11,10 @@ public class Kticket implements Runnable {
     Runtime r;
     Date renewTime;
 
-    Kticket(String name, String instance, String realm, Object lock) {
+    Kticket(String name, String instance, String realm) {
        this.name = name;
        this.instance = instance;
        this.realm = realm;
-       this.LOCK = lock;
        r = Runtime.getRuntime();
        renewTime = new Date();
     }
@@ -38,27 +36,30 @@ public class Kticket implements Runnable {
     }
 
     public void renew() {
-       synchronized(LOCK) {
-           try {
-               Process p = r.exec("/usr/athena/bin/kinit -k -t /mit/jis/javahacking/moira/KEY " + name + "/" + instance + "@" + realm);
-               p.waitFor();
-           } catch (IOException e) {
-               e.printStackTrace();
-           } catch (InterruptedException i) {
-           }
+       Moira m = null;
+       try {
+           m = Moira.getInstance("MOIRA.MIT.EDU"); // Host doesn't matter, we won't be making a connection!
+                               // We are getting a Moira instance so that no
+                               // other thread will have one and we can safely
+                               // modify the ticket file
+           Process p = r.exec("/usr/athena/bin/kinit -k -t /mit/jis/javahacking/moira/KEY " + name + "/" + instance + "@" + realm);
+           p.waitFor();
+       } catch (IOException e) {
+           e.printStackTrace();
+       } catch (InterruptedException i) {
+       } finally {
+           m.done();           // Release Moira object
        }
     }
 
     public void destroy() {
        dostop = true;
-       synchronized(LOCK) {
-           try {
-               Process p = r.exec("/usr/athena/bin/kdestroy");
-               p.waitFor();
-           } catch (IOException e) {
-               e.printStackTrace();
-           } catch (InterruptedException i) {
-           }
+       try {
+           Process p = r.exec("/usr/athena/bin/kdestroy");
+           p.waitFor();
+       } catch (IOException e) {
+           e.printStackTrace();
+       } catch (InterruptedException i) {
        }
     }
 }
similarity index 50%
rename from webmoira/mit/moira/MoiraConnect.java
rename to webmoira/mit/moira/Moira.java
index d34d18565012bee37b9840a8bc823284a95a321e..f3b65397e1f4ec67e0b04a97f2af487de59af22f 100644 (file)
@@ -1,27 +1,61 @@
 package mit.moira;
 
-public class MoiraConnect {
+public class Moira {
     boolean connected = false;
     boolean isauth = false;
-    Object LOCK;
-
     String server = "";
-    MoiraConnect() {
+    boolean isValid = true;
+
+    protected static Object LOCK = new Object();
+    protected static boolean isAvailable = true;
+
+    public static Moira getInstance(String server) {
+       synchronized (LOCK) {
+           while (!isAvailable) {
+               try {
+                   LOCK.wait();
+               } catch (InterruptedException ie) {
+               }
+           }
+           isAvailable = false;
+           return new Moira(server);
+       }
+    }
+               
+    protected static void returnInstance() {
+       synchronized(LOCK) {
+           isAvailable = true;
+           LOCK.notify();
+       }
     }
 
-    public MoiraConnect(String server, Object lock) {
+    public synchronized void done() {
+       if (!isValid) return;   // Don't make noise...
+       try {
+           disconnect();
+       } catch (MoiraException m) {
+       }
+       isValid = false;
+       returnInstance();
+    }
+
+    protected Moira() {
+    }
+
+    protected Moira(String server) {
        this.server = server;
-       this.LOCK = lock;
     }
 
-    public void connect() throws MoiraException {
+    public synchronized void connect() throws MoiraException {
+       if (!isValid) throw new MoiraException("Attempt to use stale Moira Object");
        if (!connected) {
            MoiraConnectInternal.connect(server);
            connected = true;
        }
     }
            
-    public void auth() throws MoiraException {
+    public synchronized void auth() throws MoiraException {
+       if (!isValid) throw new MoiraException("Attempt to use stale Moira Object");
        if (!isauth) {
            synchronized(LOCK) {
                MoiraConnectInternal.auth();
@@ -30,11 +64,13 @@ public class MoiraConnect {
        }
     }
 
-    public void proxy(String user) throws MoiraException {
+    public synchronized void proxy(String user) throws MoiraException {
+       if (!isValid) throw new MoiraException("Attempt to use stale Moira Object");
        MoiraConnectInternal.proxy(user);
     }
            
-    public void disconnect() {
+    public synchronized void disconnect() throws MoiraException {
+       if (!isValid) throw new MoiraException("Attempt to use stale Moira Object");
        if (connected) {
            MoiraConnectInternal.disconnect();
            connected = false;
@@ -42,7 +78,8 @@ public class MoiraConnect {
        }
     }
 
-    public ListInfo get_list_info(String list) throws MoiraException {
+    public synchronized ListInfo get_list_info(String list) throws MoiraException {
+       if (!isValid) throw new MoiraException("Attempt to use stale Moira Object");
        if (!connected) throw new MoiraException("Not Connected");
        String [] args = new String[1];
        args[0] = list;
@@ -54,7 +91,8 @@ public class MoiraConnect {
        return (new ListInfo(entry[0], entry[1], entry[2], entry[3], entry[4], entry[5], entry[6], entry[7], entry[8], entry[9], entry[10], entry[11], entry[12]));
     }
 
-    void update_list_info(String list, ListInfo info) throws MoiraException {
+    public synchronized void update_list_info(String list, ListInfo info) throws MoiraException {
+       if (!isValid) throw new MoiraException("Attempt to use stale Moira Object");
        if (!connected) throw new MoiraException("Not Connected");
        String [] args = new String[11];
        args[0] = list;
@@ -72,7 +110,8 @@ public class MoiraConnect {
        return;
     }
 
-    void delete_member_from_list(String list, String type, String member) throws MoiraException {
+    public synchronized void delete_member_from_list(String list, String type, String member) throws MoiraException {
+       if (!isValid) throw new MoiraException("Attempt to use stale Moira Object");
        if (!connected) throw new MoiraException("Not Connected");
        String [] args = new String[3];
        args[0] = list;
@@ -82,7 +121,8 @@ public class MoiraConnect {
        return;
     }
 
-    void add_member_to_list(String list, String type, String member) throws MoiraException {
+    public synchronized void add_member_to_list(String list, String type, String member) throws MoiraException {
+       if (!isValid) throw new MoiraException("Attempt to use stale Moira Object");
        if (!connected) throw new MoiraException("Not Connected");
        String [] args = new String[3];
        args[0] = list;
@@ -92,7 +132,19 @@ public class MoiraConnect {
        return;
     }
 
-    public Member [] get_members_of_list(String list) throws MoiraException {
+    public synchronized String [] get_user_by_login(String user) throws MoiraException {
+       if (!isValid) throw new MoiraException("Attempt to use stale Moira Object");
+       if (!connected) throw new MoiraException("Not Connected");
+       String [] args = new String[1];
+       args[0] = user;
+       Object [] retinternal = MoiraConnectInternal.mr_query("get_user_by_login", args);
+       if (retinternal == null) return (null);
+       String [] entry = (String []) retinternal[0];
+       return(entry);
+    }
+
+    public synchronized Member [] get_members_of_list(String list) throws MoiraException {
+       if (!isValid) throw new MoiraException("Attempt to use stale Moira Object");
        if (!connected) throw new MoiraException("Not Connected");
        String [] args = new String[1];
        args[0] = list;
@@ -105,6 +157,12 @@ public class MoiraConnect {
        }
        return (retval);
     }
+
+    public void finalize() {
+       if (isValid) System.err.println("Moira object finalized while valid!");
+       else System.err.println("Moira object finalized (normally)");
+    }
+
 }
 
 class MoiraConnectInternal {
index eeebbe3adbf72a9a7119d580670f703a46fd9673..93ad8ee6e1424240b3b3780f470eb2f289d8baea 100644 (file)
@@ -13,9 +13,7 @@ import java.util.ResourceBundle;
 
 public class MoiraServlet extends HttpServlet {
     static final String MOIRA_SERVER = "moira.mit.edu";
-    Object LOCK = new Object();        // Used to synchronize Moira authentication
-                               // with the ticket fetching thread
-    Kticket kt = new Kticket("jis5", "foobar", "ATHENA.MIT.EDU", LOCK);
+    Kticket kt = new Kticket("jis5", "foobar", "ATHENA.MIT.EDU");
     boolean ktinit = false;
     private static final int MAXDISPLAY = 10;
     Hashtable FileParts = new Hashtable();
@@ -270,12 +268,12 @@ public class MoiraServlet extends HttpServlet {
        if (offset < 0) showall = true;
 
        if (members == null) {
-           MoiraConnect mc = null;
+           Moira mc = null;
            try {
                mc = connect();
                mc.proxy(kname);
                members = mc.get_members_of_list(arg);
-               mc.disconnect();
+               mc.done();      // Done will disconnect
                mc = null;
                if (members != null)
                    session.putValue("members", members);
@@ -297,7 +295,7 @@ public class MoiraServlet extends HttpServlet {
                    e.printStackTrace();
                }
            } finally {
-               if (mc != null) mc.disconnect();
+               if (mc != null) mc.done();
            }
        }
 
@@ -316,7 +314,7 @@ public class MoiraServlet extends HttpServlet {
        }
        for (int i = offset; i < len; i++) {
            msg += "<tr><td>" + members[i].getMemberType() + "</td>";
-           msg += "<td>" + members[i].getMemberId() + "</td></tr>\r\n";
+           msg += "<td>" + quote(members[i].getMemberId()) + "</td></tr>\r\n";
        }
        msg += "</table></td><td>&nbsp;</td></tr><tr>\r\n";
        if ((offset > 0) && !showall) {
@@ -401,7 +399,7 @@ public class MoiraServlet extends HttpServlet {
 
        HttpSession session = request.getSession(true);
 
-       MoiraConnect mc = null;
+       Moira mc = null;
        ListInfo li = null;
        try {
            mc = connect();
@@ -418,11 +416,7 @@ public class MoiraServlet extends HttpServlet {
            msg += "!>\r\n";
            return (msg);
        } finally {
-           try {
-               if (mc != null) mc.disconnect();
-               mc = null;
-           } catch (Exception e) {
-           }
+           if (mc != null) mc.done();
        }
 
        String list_description = "";
@@ -451,7 +445,7 @@ public class MoiraServlet extends HttpServlet {
 
        HttpSession session = request.getSession(true);
 
-       MoiraConnect mc = null;
+       Moira mc = null;
        boolean found = false;
        boolean sublists = false;
        Member [] members = null;
@@ -471,8 +465,6 @@ public class MoiraServlet extends HttpServlet {
                    }
                }
            }
-           mc.disconnect();
-           mc = null;
        } catch (MoiraException m) {
            try {
                msg = "<P><b>\r\n";
@@ -490,7 +482,7 @@ public class MoiraServlet extends HttpServlet {
                e.printStackTrace();
            }
        } finally {
-           if (mc != null) mc.disconnect();
+           if (mc != null) mc.done();
        }
        msg = "You are " + (found ? "" : "not ") + "a member of the list <b>" + arg + "</b>.<br>\r\n";
        if (!found && sublists)
@@ -523,7 +515,7 @@ public class MoiraServlet extends HttpServlet {
        if (listname == null) {
            return("<p>Could not find list name (shouldn't happen).</p>");
        }
-       MoiraConnect mc = null;
+       Moira mc = null;
        try {
            mc = connect();
            mc.proxy(kname);
@@ -543,10 +535,7 @@ public class MoiraServlet extends HttpServlet {
            msg += "!>\r\n";
            return (msg);
        } finally {
-           try {
-               if (mc != null) mc.disconnect();
-           } catch (Exception e) {
-           }
+           if (mc != null) mc.done();
        }
        if (add) msg = "You have been added to the <b>" + listname + "</b> list.";
        else msg = "You have been removed from the <b>" + listname + "</b> list.";
@@ -566,7 +555,7 @@ public class MoiraServlet extends HttpServlet {
 
        HttpSession session = request.getSession(true);
 
-       MoiraConnect mc = null;
+       Moira mc = null;
        try {
            mc = connect();
            mc.proxy(kname);
@@ -578,7 +567,7 @@ public class MoiraServlet extends HttpServlet {
            for (int i = 0; i < members.length; i++) {
                del[i] = new Delmember(members[i]);
            }
-           mc.disconnect();
+           mc.done();
            mc = null;
            session.putValue("list", arg);
            session.removeValue("members"); // In case left over from previous call
@@ -599,7 +588,7 @@ public class MoiraServlet extends HttpServlet {
                e.printStackTrace();
            }
        } finally {
-           if (mc != null) mc.disconnect();
+           if (mc != null) mc.done();
        }
        return (do_remdisplay(qv, request, response, del, 0));
     }
@@ -627,7 +616,7 @@ public class MoiraServlet extends HttpServlet {
            msg += "<tr><td><input type=checkbox name=selected value=\" " + i + "\"";
            if (del[i].marked) msg += " checked";
            msg += "></td><td>" + del[i].member.getMemberType() + "</td>";
-           msg += "<td>" + del[i].member.getMemberId() + "</td></tr>\r\n";
+           msg += "<td>" + quote(del[i].member.getMemberId()) + "</td></tr>\r\n";
        }
        msg += "</table></td>\r\n";
        msg += "<td><input type=hidden name=operation value=delmembers></td></tr>\r\n";
@@ -728,7 +717,7 @@ public class MoiraServlet extends HttpServlet {
        for (int i = 0; i < del.length; i++) {
            if (del[i].marked) {
                msg += "<tr><td>" + del[i].member.getMemberType() + "</td>";
-               msg += "<td>" + del[i].member.getMemberId() + "</td></tr>\r\n";
+               msg += "<td>" + quote(del[i].member.getMemberId()) + "</td></tr>\r\n";
            }
        }
        msg += "</table>\r\n";
@@ -760,7 +749,7 @@ public class MoiraServlet extends HttpServlet {
        Vector problems = new Vector();
        Vector success = new Vector();
 
-       MoiraConnect mc = null;
+       Moira mc = null;
        try {
            mc = connect();
            mc.proxy(kname);
@@ -771,7 +760,7 @@ public class MoiraServlet extends HttpServlet {
                        success.addElement(del[i].member);
                    }
                } catch (MoiraException m) {
-                   problems.addElement("<tr><td>" + del[i].member.getMemberId() + "</td><td>" + m.getMessage() + "</td></tr>\r\n");
+                   problems.addElement("<tr><td>" + quote(del[i].member.getMemberId()) + "</td><td>" + m.getMessage() + "</td></tr>\r\n");
                }
            }
        } catch (MoiraException m) {
@@ -785,10 +774,7 @@ public class MoiraServlet extends HttpServlet {
            msg += "!>\r\n";
            return (msg);
        } finally {
-           try {
-               if (mc != null) mc.disconnect();
-           } catch (Exception e) {
-           }
+           if (mc != null) mc.done();
        }
 
        msg = "";
@@ -796,7 +782,7 @@ public class MoiraServlet extends HttpServlet {
            msg += "<h2>Deleted the following:</h2>\r\n";
            msg += "<table border=1 cellpadding=2>\r\n";
            for (int i = 0; i < success.size(); i++) {
-               msg += "<tr><td>" + ((Member)success.elementAt(i)).getMemberId() + "</td></tr>\r\n";
+               msg += "<tr><td>" + quote(((Member)success.elementAt(i)).getMemberId()) + "</td></tr>\r\n";
            }
            msg += "</table>\r\n";
        }
@@ -825,7 +811,7 @@ public class MoiraServlet extends HttpServlet {
        HttpSession session = request.getSession(true);
 
        String msg = "";
-       MoiraConnect mc = null;
+       Moira mc = null;
        ListInfo li = null;
        try {
            mc = connect();
@@ -842,10 +828,7 @@ public class MoiraServlet extends HttpServlet {
            msg += "!>\r\n";
            return (msg);
        } finally {
-           try {
-               if (mc != null) mc.disconnect();
-           } catch (Exception e) {
-           }
+           if (mc != null) mc.done();
        }
        if (li == null) {
            return("Did not find list info.");
@@ -875,7 +858,7 @@ public class MoiraServlet extends HttpServlet {
        HttpSession session = request.getSession(true);
 
        String msg = "";
-       MoiraConnect mc = null;
+       Moira mc = null;
        ListInfo li = null;
        try {
            mc = connect();
@@ -892,10 +875,7 @@ public class MoiraServlet extends HttpServlet {
            msg += "!>\r\n";
            return (msg);
        } finally {
-           try {
-               if (mc != null) mc.disconnect();
-           } catch (Exception e) {
-           }
+           if (mc != null) mc.done();
        }
        if (li == null) {
            return("Did not find list info.");
@@ -968,13 +948,11 @@ public class MoiraServlet extends HttpServlet {
        if (tmp != null)
            li.ace_name = tmp;
 
-       MoiraConnect mc = null;
+       Moira mc = null;
        try {
            mc = connect();
            mc.proxy(kname);
            mc.update_list_info(li.name, li);
-           mc.disconnect();
-           mc = null;
        } catch (MoiraException e) {
            String msg;
            if (e.getMessage().startsWith("No such list")) {
@@ -994,10 +972,7 @@ public class MoiraServlet extends HttpServlet {
            msg += "!>\r\n";
            return (msg);
        } finally {
-           try {
-               if (mc != null) mc.disconnect();
-           } catch (Exception e) {
-           }
+           if (mc != null) mc.done();
        }
        String msg = "<b>Update of " + li.name + " succeeded</b><p>\r\n";
        qv.put("list", li.name);
@@ -1023,7 +998,7 @@ public class MoiraServlet extends HttpServlet {
        if (member == null || type == null || member.equals("")) {
            return("<p>No names selected to be added!</p>");
        }
-       MoiraConnect mc = null;
+       Moira mc = null;
        StreamTokenizer tk = null;
        msg += "<table border=1 cellpadding=2>\r\n";
        boolean addheader = false;
@@ -1033,6 +1008,8 @@ public class MoiraServlet extends HttpServlet {
            mc = connect();
            mc.proxy(kname);
            tk = new StreamTokenizer(new StringReader(member));
+           mc.done();
+           mc = null;
            tk.wordChars('@', '@');
            tk.wordChars('0', '9');
            tk.wordChars('_', '_');
@@ -1077,10 +1054,7 @@ public class MoiraServlet extends HttpServlet {
        } catch (IOException e) {
            e.printStackTrace(); // Shouldn't happen
        } finally {
-           try {
-               if (mc != null) mc.disconnect();
-           } catch (Exception e) {
-           }
+           if (mc != null) mc.done();
        }
        if (problems.size() != 0) {
            msg += "<p>There were difficulties adding the following users:<br>\r\n";
@@ -1294,39 +1268,51 @@ public class MoiraServlet extends HttpServlet {
      * @return A Moira Connection Object
      * @exception MoiraException on any error
      */
-    protected MoiraConnect connect() throws MoiraException {
-       MoiraConnect retval = null;
+    protected Moira connect() throws MoiraException {
+       Moira retval = null;
+       boolean error = true;
        int count = 0;
-       while (count++ < 10) {  // Got to stop at some point!
-           retval = new MoiraConnect(MOIRA_SERVER, LOCK);
-           retval.connect();
-           try {
-               retval.auth();
-               return (retval); // No exception, return. yeah!
-           } catch (MoiraException m) {
-               if ((m.getCode() != KE_RD_AP_BADD) || (count > 8)) {
-                   if (retval != null) {
-                       try {
-                           retval.disconnect();
-                       } catch (Exception e) {
-                       }
+       try {
+           while (count++ < 10) {      // Got to stop at some point!
+               retval = Moira.getInstance(MOIRA_SERVER);           
+               retval.connect();
+               try {
+                   retval.auth();
+                   error = false;
+                   return (retval); // No exception, return. yeah!
+               } catch (MoiraException m) {
+                   if ((m.getCode() != KE_RD_AP_BADD) || (count > 8)) {
+                       throw m;        // Re-throw if not the error we expect or we are looping
                    }
-                   throw m;    // Re-throw if not the error we expect or we are looping
                }
-           }
-           if (retval != null) {
-               try {
-                   retval.disconnect();
-               } catch (Exception e) {
+               if (retval != null) {
+                   retval.done();
+                   retval = null;
                }
-               retval = null;
+               System.err.println("MoiraServlet: Forced Renewal...");
+               kt.renew();             // Renew tickets
            }
-           System.err.println("MoiraServlet: Forced Renewal...");
-           kt.renew();         // Renew tickets
+           // Fell through, count exceeded
+           throw new MoiraException("Cannot authenticate successfully to Moira");
+       } finally {
+           if (error && (retval != null)) retval.done();
        }
-       return (null);
     }
 
+    public static String quote(String value) {
+        if (value.indexOf('<') == -1 &&
+           value.indexOf('>') == -1) return (value); // Nothing to quote
+       StringBuffer buf = new StringBuffer(value.length() + 10);
+       for (int i = 0; i < value.length(); i++) {
+           char c = value.charAt(i);
+           if (c != '<' && c != '>') buf.append(c);
+           else {
+               if (c == '<') buf.append("&lt;");
+               if (c == '>') buf.append("&gt;");
+           }
+       }
+       return (new String(buf));
+    }
 }
 
 class Delmember {
This page took 0.121012 seconds and 5 git commands to generate.