Java: Hopefully working HubListeners.
[doldaconnect.git] / lib / java / dolda / dolcon / Session.java
CommitLineData
7131093c
FT
1package dolda.dolcon;
2
3import java.util.*;
4import dolda.dolcon.protocol.*;
5
7ff32e0f
FT
6public class Session {
7 Connection conn;
e90ca845 8 private String state;
e90ca845 9 private boolean listening = false;
7ff32e0f
FT
10 private Dispatcher dispatcher;
11 HubManager hm = null;
7131093c
FT
12
13 public Session(String aspec, String username, List<Authenticator> auth) throws AuthException, ProtocolException, InterruptedException {
e90ca845 14 state = "connecting";
7131093c
FT
15 conn = new Connection(aspec);
16 conn.expectVersion(2);
17 try {
18 conn.syncConnect();
19 } catch(ConnectException e) {
20 throw(new ProtocolException(e));
21 }
e90ca845 22 state = "auth";
7131093c 23 authenticate(username, auth);
e90ca845 24 state = "";
7ff32e0f
FT
25 dispatcher = new Dispatcher();
26 dispatcher.start();
7131093c
FT
27 }
28
29 public Session(String aspec, String username, Authenticator... auth) throws AuthException, ProtocolException, InterruptedException {
30 this(aspec, username, Arrays.asList(auth));
31 }
32
33 private void authenticate(String username, List<Authenticator> auth) throws AuthException, ProtocolException, InterruptedException {
34 Response resp;
35
36 try {
37 resp = ResponseException.check(conn.ecmd("lsauth"), 200);
38 List<String> mechs = new LinkedList<String>();
39 for(List<String> mech : resp.lines)
40 mechs.add(mech.get(0).intern());
41 String use = null;
42 Authenticator au = null;
43 for(Authenticator a : auth) {
7131093c
FT
44 use = a.handles(mechs);
45 if(use != null) {
46 au = a;
47 break;
48 }
49 }
50 if(use == null)
51 throw(new NoMechException());
52 resp = conn.ecmd("login", use, username);
53 while(true) {
54 if(resp.code == 200) {
55 return;
56 } else if((resp.code / 100) == 3) {
57 resp = conn.ecmd(au.step(resp));
58 } else if((resp.code / 100) == 5) {
59 throw(new AuthException(resp.token(0, 0)));
60 } else {
61 throw(new ResponseException(resp, 0));
62 }
63 }
64 } catch(ClosedException e) {
65 throw(new ProtocolException(e));
66 }
67 }
92719bd6 68
7ff32e0f
FT
69 private HubManager gethm() {
70 if(hm == null) {
71 hm = new HubManager(this);
e90ca845 72 }
7ff32e0f 73 return(hm);
e90ca845
FT
74 }
75
7ff32e0f
FT
76 public synchronized void addHubListener(HubListener hl, boolean addexisting) {
77 gethm().addls(hl, addexisting);
e90ca845
FT
78 }
79
7ff32e0f
FT
80 public synchronized void removeHubListener(HubListener hl) {
81 gethm().rmls(hl);
e90ca845 82 }
7ff32e0f
FT
83
84 public synchronized Collection<Hub> getHubs() throws InterruptedException {
85 return(gethm().gethubs());
e90ca845
FT
86 }
87
92719bd6
FT
88 public void close() {
89 conn.close();
e90ca845
FT
90 state = "closed";
91 }
92
93 protected void finalize() {
94 if(state != "closed")
95 close();
7ff32e0f
FT
96 dispatcher.interrupt();
97 }
98
99 void dispatch(Runnable ev) {
100 dispatcher.dispatch(ev);
101 }
102
103 private static class Dispatcher extends Thread {
104 private Queue<Runnable> q = new LinkedList<Runnable>();
105
106 private Dispatcher() {
107 setDaemon(true);
108 }
109
110 public void dispatch(Runnable ev) {
111 synchronized(q) {
112 q.offer(ev);
113 q.notifyAll();
114 }
115 }
116
117 public void run() {
118 while(true) {
119 try {
120 Runnable r;
121 synchronized(q) {
122 while((r = q.poll()) == null)
123 q.wait();
124 }
125 r.run();
126 } catch(Throwable t) {
127 t.printStackTrace();
128 }
129 }
130 }
92719bd6 131 }
7131093c 132}