Mercurial Hosting > luan
diff src/luan/webserver/handlers/DomainHandler.java @ 1315:5763597ca5c0
add DomainHandler
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 30 Jan 2019 01:21:49 -0700 |
parents | |
children | 02fe660e7748 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/webserver/handlers/DomainHandler.java Wed Jan 30 01:21:49 2019 -0700 @@ -0,0 +1,114 @@ +package luan.webserver.handlers; + +import java.io.Closeable; +import java.io.IOException; +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.lang.ref.ReferenceQueue; +import java.util.Map; +import java.util.HashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import luan.webserver.Handler; +import luan.webserver.Request; +import luan.webserver.Response; + + +public final class DomainHandler implements Handler { + private static final Logger logger = LoggerFactory.getLogger(DomainHandler.class); + + public interface Factory { + public Handler newHandler(String domain); + } + + private static class Ref { + private final Handler handler; + + private Ref(Handler handler) { + this.handler = handler; + } + } + + private final ReferenceQueue<Ref> queue = new ReferenceQueue<Ref>(); + + private class MyReference extends SoftReference<Ref> { + private Handler handler; + + private MyReference(Ref r) { + super(r,queue); + this.handler = r.handler; + } + } + + private static void close(Handler handler) { + if( handler instanceof Closeable ) { + try { + ((Closeable)handler).close(); + } catch(IOException e) { + logger.error(handler.toString(),e); + } + } + } + + private void sweep() { + while(true) { + MyReference ref = (MyReference)queue.poll(); + if( ref == null ) + return; + //logger.info("sweep"); + close(ref.handler); + ref.handler = null; + } + } + + private final Map<String,MyReference> map = new HashMap<String,MyReference>(); + + private final Factory factory; + + public DomainHandler(Factory factory) { + this.factory = factory; + } + + public Response handle(Request request) { + String host = (String)request.headers.get("host"); + int i = host.indexOf(':'); + String domain = i == -1 ? host : host.substring(0,i); + Handler handler = getHandler(domain); + return handler==null ? null : handler.handle(request); + } + + public Handler getHandler(String domain) { + Ref r = getRef(domain); + return r==null ? null : r.handler; + } + + public void removeHandler(String domain) { + domain = domain.toLowerCase(); + synchronized(map) { + Reference<Ref> ref = map.remove(domain); + Ref r = ref==null ? null : ref.get(); + if( r != null ) { + close(r.handler); + } + } + } + + private Ref getRef(String domain) { + domain = domain.toLowerCase(); + synchronized(map) { + Reference<Ref> ref = map.get(domain); + Ref r = ref==null ? null : ref.get(); + if( r == null ) { + //if(ref!=null) logger.info("gc "+domain); + sweep(); + Handler handler = factory.newHandler(domain); + if( handler == null ) + return null; + r = new Ref(handler); + map.put(domain,new MyReference(r)); + } + return r; + } + } + +}