Now the clearing behaviour can be parametrized

A when no longer referenced strategy can be used, so
IServletRequestHandler is not keep around in memory more time than
necessary.

FEA: ItEr74S08DeployFramework
This commit is contained in:
Óscar González Fernández 2011-05-26 19:32:26 +02:00
parent 1ec711ce4c
commit 0d49317ada

View file

@ -21,6 +21,7 @@
package org.zkoss.ganttz.servlets;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
@ -29,6 +30,7 @@ import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
@ -51,12 +53,9 @@ public class CallbackServlet extends HttpServlet {
// minute
// minutes
private static final long EXPIRATION_TIME_MILLIS = 1000 * 60 * 2; // two
// minutes
private static Random random = new Random();
private static ConcurrentMap<String, HandlerWithRegisterTime> handlersCallbacks = new ConcurrentHashMap<String, HandlerWithRegisterTime>();
private static ConcurrentMap<String, IHandler> handlersCallbacks = new ConcurrentHashMap<String, IHandler>();
private static Timer cleaningTimer = new Timer(true);
@ -66,32 +65,105 @@ public class CallbackServlet extends HttpServlet {
IOException;
}
private static class HandlerWithRegisterTime {
private final IServletRequestHandler handler;
private final long creationTime;
public enum DisposalMode {
WHEN_NO_LONGER_REFERENCED {
@Override
public IHandler create(IServletRequestHandler handler) {
return new WeakReferencedHandler(handler);
}
},
AFTER_TEN_MINUTES {
@Override
public IHandler create(IServletRequestHandler handler) {
return new BasedOnExpirationTimeHandler(handler,
tenMinutesInMillis);
}
};
public HandlerWithRegisterTime(IServletRequestHandler handler) {
private static final long tenMinutesInMillis = TimeUnit.MILLISECONDS
.convert(10, TimeUnit.MINUTES);
public abstract IHandler create(
IServletRequestHandler handler);
}
private interface IHandler {
abstract boolean hasExpired();
abstract IServletRequestHandler getHandler();
}
private static class BasedOnExpirationTimeHandler implements IHandler {
private IServletRequestHandler handler;
private final long creationTime;
private final long expirationTimeMilliseconds;
public BasedOnExpirationTimeHandler(IServletRequestHandler handler,
long expirationTimeMilliseconds) {
Validate.notNull(handler);
this.handler = handler;
this.creationTime = System.currentTimeMillis();
this.expirationTimeMilliseconds = expirationTimeMilliseconds;
}
boolean hasExpired() {
return System.currentTimeMillis() - creationTime > EXPIRATION_TIME_MILLIS;
@Override
public IServletRequestHandler getHandler() {
return handler;
}
@Override
public boolean hasExpired() {
return System.currentTimeMillis() - creationTime > expirationTimeMilliseconds;
}
}
private static class WeakReferencedHandler implements IHandler {
private final WeakReference<IServletRequestHandler> handler;
WeakReferencedHandler(IServletRequestHandler handler) {
this.handler = new WeakReference<IServletRequestHandler>(handler);
}
@Override
public boolean hasExpired() {
return handler.get() == null;
}
@Override
public IServletRequestHandler getHandler() {
return handler.get();
}
}
public static String registerAndCreateURLFor(HttpServletRequest request,
IServletRequestHandler handler) {
return registerAndCreateURLFor(request, handler, true);
return registerAndCreateURLFor(request, handler,
DisposalMode.AFTER_TEN_MINUTES);
}
public static String registerAndCreateURLFor(HttpServletRequest request,
IServletRequestHandler handler, DisposalMode disposalMode) {
return registerAndCreateURLFor(request, handler, true, disposalMode);
}
public static String registerAndCreateURLFor(HttpServletRequest request,
IServletRequestHandler handler, boolean withContextPath) {
return registerAndCreateURLFor(request, handler, withContextPath,
DisposalMode.AFTER_TEN_MINUTES);
}
public static String registerAndCreateURLFor(HttpServletRequest request,
IServletRequestHandler handler, boolean withContextPath,
DisposalMode disposalMode) {
Validate.notNull(disposalMode);
// theoretically could be an infinite loop, could be improved.
String generatedKey = "";
HandlerWithRegisterTime toBeRegistered = new HandlerWithRegisterTime(
handler);
IHandler toBeRegistered = disposalMode.create(handler);
do {
generatedKey = generateKey();
} while (handlersCallbacks.putIfAbsent(generatedKey, toBeRegistered) != null);
@ -127,10 +199,10 @@ public class CallbackServlet extends HttpServlet {
}
private static List<String> findExpired() {
ArrayList<Entry<String, HandlerWithRegisterTime>> handlersList = new ArrayList<Entry<String, HandlerWithRegisterTime>>(
ArrayList<Entry<String, IHandler>> handlersList = new ArrayList<Entry<String, IHandler>>(
handlersCallbacks.entrySet());
List<String> expired = new ArrayList<String>();
for (Entry<String, HandlerWithRegisterTime> entry : handlersList) {
for (Entry<String, IHandler> entry : handlersList) {
if (entry.getValue().hasExpired()) {
expired.add(entry.getKey());
}
@ -171,8 +243,8 @@ public class CallbackServlet extends HttpServlet {
}
private IServletRequestHandler handlerFor(String callbackId) {
HandlerWithRegisterTime h = handlersCallbacks.get(callbackId);
return h != null ? h.handler : null;
IHandler h = handlersCallbacks.get(callbackId);
return h != null ? h.getHandler() : null;
}
}