1315
|
1 package luan.webserver.handlers;
|
|
2
|
|
3 import java.io.Closeable;
|
|
4 import java.io.IOException;
|
|
5 import java.lang.ref.Reference;
|
|
6 import java.lang.ref.SoftReference;
|
|
7 import java.lang.ref.ReferenceQueue;
|
|
8 import java.util.Map;
|
|
9 import java.util.HashMap;
|
|
10 import org.slf4j.Logger;
|
|
11 import org.slf4j.LoggerFactory;
|
|
12 import luan.webserver.Handler;
|
|
13 import luan.webserver.Request;
|
|
14 import luan.webserver.Response;
|
|
15
|
|
16
|
|
17 public final class DomainHandler implements Handler {
|
|
18 private static final Logger logger = LoggerFactory.getLogger(DomainHandler.class);
|
|
19
|
|
20 public interface Factory {
|
|
21 public Handler newHandler(String domain);
|
|
22 }
|
|
23
|
|
24 private static class Ref {
|
|
25 private final Handler handler;
|
|
26
|
|
27 private Ref(Handler handler) {
|
|
28 this.handler = handler;
|
|
29 }
|
|
30 }
|
|
31
|
|
32 private final ReferenceQueue<Ref> queue = new ReferenceQueue<Ref>();
|
|
33
|
|
34 private class MyReference extends SoftReference<Ref> {
|
|
35 private Handler handler;
|
|
36
|
|
37 private MyReference(Ref r) {
|
|
38 super(r,queue);
|
|
39 this.handler = r.handler;
|
|
40 }
|
|
41 }
|
|
42
|
|
43 private static void close(Handler handler) {
|
|
44 if( handler instanceof Closeable ) {
|
|
45 try {
|
|
46 ((Closeable)handler).close();
|
|
47 } catch(IOException e) {
|
|
48 logger.error(handler.toString(),e);
|
|
49 }
|
|
50 }
|
|
51 }
|
|
52
|
|
53 private void sweep() {
|
|
54 while(true) {
|
|
55 MyReference ref = (MyReference)queue.poll();
|
|
56 if( ref == null )
|
|
57 return;
|
|
58 //logger.info("sweep");
|
|
59 close(ref.handler);
|
|
60 ref.handler = null;
|
|
61 }
|
|
62 }
|
|
63
|
|
64 private final Map<String,MyReference> map = new HashMap<String,MyReference>();
|
|
65
|
|
66 private final Factory factory;
|
|
67
|
|
68 public DomainHandler(Factory factory) {
|
|
69 this.factory = factory;
|
|
70 }
|
|
71
|
|
72 public Response handle(Request request) {
|
|
73 String host = (String)request.headers.get("host");
|
|
74 int i = host.indexOf(':');
|
|
75 String domain = i == -1 ? host : host.substring(0,i);
|
|
76 Handler handler = getHandler(domain);
|
|
77 return handler==null ? null : handler.handle(request);
|
|
78 }
|
|
79
|
|
80 public Handler getHandler(String domain) {
|
|
81 Ref r = getRef(domain);
|
|
82 return r==null ? null : r.handler;
|
|
83 }
|
|
84
|
|
85 public void removeHandler(String domain) {
|
|
86 domain = domain.toLowerCase();
|
|
87 synchronized(map) {
|
|
88 Reference<Ref> ref = map.remove(domain);
|
|
89 Ref r = ref==null ? null : ref.get();
|
|
90 if( r != null ) {
|
|
91 close(r.handler);
|
|
92 }
|
|
93 }
|
|
94 }
|
|
95
|
|
96 private Ref getRef(String domain) {
|
|
97 domain = domain.toLowerCase();
|
|
98 synchronized(map) {
|
|
99 Reference<Ref> ref = map.get(domain);
|
|
100 Ref r = ref==null ? null : ref.get();
|
|
101 if( r == null ) {
|
|
102 //if(ref!=null) logger.info("gc "+domain);
|
|
103 sweep();
|
|
104 Handler handler = factory.newHandler(domain);
|
|
105 if( handler == null )
|
|
106 return null;
|
|
107 r = new Ref(handler);
|
|
108 map.put(domain,new MyReference(r));
|
|
109 }
|
|
110 return r;
|
|
111 }
|
|
112 }
|
|
113
|
|
114 }
|