Commit | Line | Data |
---|---|---|
7131093c FT |
1 | package dolda.dolcon; |
2 | ||
3 | import java.util.*; | |
4 | import dolda.dolcon.protocol.*; | |
5 | ||
7ff32e0f FT |
6 | public 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 | } |