diff src/luan/lib/webserver/handlers/DomainHandler.java @ 1347:643cf1c37723

move webserver to lib and bug fixes
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 25 Feb 2019 13:02:33 -0700
parents src/luan/webserver/handlers/DomainHandler.java@8b61c8c4e07a
children 221eedb0f54e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/lib/webserver/handlers/DomainHandler.java	Mon Feb 25 13:02:33 2019 -0700
@@ -0,0 +1,116 @@
+package luan.lib.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 luan.lib.logging.Logger;
+import luan.lib.logging.LoggerFactory;
+import luan.lib.webserver.Handler;
+import luan.lib.webserver.Request;
+import luan.lib.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");
+		if( host == null )
+			return null;
+		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;
+		}
+	}
+
+}