Replaced ContextResponder with a more generic Destroyable interface.
[jsvc.git] / src / dolda / jsvc / util / PerSession.java
1 package dolda.jsvc.util;
2
3 import dolda.jsvc.*;
4 import java.lang.reflect.*;
5
6 public class PerSession implements Responder {
7     private final Class<?> rcl;
8     private final Class<?> dcl;
9     
10     public PerSession(Class<?> rcl, Class<?> dcl) {
11         this.rcl = rcl;
12         this.dcl = dcl;
13     }
14     
15     public PerSession(Class<?> rcl) {
16         this(rcl, null);
17     }
18     
19     private Object makedata(Session sess) {
20         try {
21             try {
22                 return(dcl.getConstructor(Session.class).newInstance(sess));
23             } catch(NoSuchMethodException e) {
24             }
25             try {
26                 return(dcl.getConstructor().newInstance());
27             } catch(NoSuchMethodException e) {
28             }
29         } catch(InstantiationException e) {
30             throw(new RuntimeException(e));
31         } catch(IllegalAccessException e) {
32             throw(new RuntimeException(e));
33         } catch(InvocationTargetException e) {
34             throw(new RuntimeException(e));
35         }
36         throw(new RuntimeException("Found no way to create an instance of " + dcl.getName()));
37     }
38
39     private Object getdata(Session sess) {
40         Object d = sess.get(dcl, null);
41         if(d == null) {
42             d = makedata(sess);
43             sess.put(dcl, d);
44         }
45         return(d);
46     }
47
48     private Responder create(Session sess) {
49         try {
50             if(dcl != null) {
51                 try {
52                     return((Responder)rcl.getMethod("responder", dcl).invoke(null, getdata(sess)));
53                 } catch(NoSuchMethodException e) {
54                 }
55             }
56             try {
57                 return((Responder)rcl.getMethod("responder", Session.class).invoke(null, sess));
58             } catch(NoSuchMethodException e) {
59             }
60             try {
61                 return((Responder)rcl.getMethod("responder").invoke(null));
62             } catch(NoSuchMethodException e) {
63             }
64             if(dcl != null) {
65                 try {
66                     return((Responder)rcl.getConstructor(dcl).newInstance(getdata(sess)));
67                 } catch(NoSuchMethodException e) {
68                 }
69             }
70             try {
71                 return((Responder)rcl.getConstructor(Session.class).newInstance(sess));
72             } catch(NoSuchMethodException e) {
73             }
74             try {
75                 return((Responder)rcl.getConstructor().newInstance());
76             } catch(NoSuchMethodException e) {
77             }
78         } catch(InstantiationException e) {
79             throw(new RuntimeException(e));
80         } catch(IllegalAccessException e) {
81             throw(new RuntimeException(e));
82         } catch(InvocationTargetException e) {
83             throw(new RuntimeException(e));
84         }
85         throw(new RuntimeException("Found no way to create a responder from the class " + rcl.getName()));
86     }
87
88     public void respond(Request req) {
89         Session sess = Session.get(req);
90         Responder resp;
91         synchronized(this) {
92             resp = (Responder)sess.get(rcl, null);
93             if(resp == null) {
94                 resp = create(sess);
95                 sess.put(rcl, resp);
96                 if(resp instanceof Destroyable) {
97                     final Destroyable cr = (Destroyable)resp;
98                     sess.listen(new Session.Listener() {
99                             public void destroy(Session sess) {
100                                 cr.destroy();
101                             }
102                         });
103                 }
104             }
105         }
106         resp.respond(req);
107     }
108 }