From 24ffbc2095e00cbb984c6e8d75f5d16c4670e35a Mon Sep 17 00:00:00 2001 From: Jonatan Kronqvist Date: Fri, 6 Sep 2013 16:07:33 +0300 Subject: [PATCH] Allow storing and restoring null instances in CurrentInstance #12509 Change-Id: Icf82377b0d47166d59e8be5f2f8b450d654302d7 --- .../src/com/vaadin/util/CurrentInstance.java | 31 ++++++++--- .../com/vaadin/util/TestCurrentInstance.java | 53 ++++++++++++++++++- 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/server/src/com/vaadin/util/CurrentInstance.java b/server/src/com/vaadin/util/CurrentInstance.java index 3320a04366..39c2a60a5c 100644 --- a/server/src/com/vaadin/util/CurrentInstance.java +++ b/server/src/com/vaadin/util/CurrentInstance.java @@ -57,6 +57,8 @@ import com.vaadin.ui.UI; * @since 7.0.0 */ public class CurrentInstance implements Serializable { + private static final Object NULL_OBJECT = new Object(); + private final WeakReference instance; private final boolean inheritable; @@ -137,7 +139,7 @@ public class CurrentInstance implements Serializable { Object instance = entry.getValue().instance.get(); if (instance == null) { iterator.remove(); - getLogger().log(Level.WARNING, + getLogger().log(Level.FINE, "CurrentInstance for {0} has been garbage collected.", entry.getKey()); } @@ -234,6 +236,8 @@ public class CurrentInstance implements Serializable { Object v = ci.instance.get(); if (v == null) { removeStale = true; + } else if (v == NULL_OBJECT) { + set(c, null, ci.inheritable); } else { set(c, v, ci.inheritable); } @@ -265,7 +269,7 @@ public class CurrentInstance implements Serializable { boolean removeStale = false; for (Class c : map.keySet()) { CurrentInstance ci = map.get(c); - if (ci.instance.isEnqueued()) { + if (ci.instance.get() == null) { removeStale = true; } else if (ci.inheritable || !onlyInheritable) { copy.put(c, ci); @@ -295,7 +299,8 @@ public class CurrentInstance implements Serializable { */ public static Map, CurrentInstance> setCurrent(UI ui) { Map, CurrentInstance> old = new HashMap, CurrentInstance>(); - old.put(UI.class, new CurrentInstance(UI.getCurrent(), true)); + old.put(UI.class, + new CurrentInstance(getSameOrNullObject(UI.getCurrent()), true)); UI.setCurrent(ui); old.putAll(setCurrent(ui.getSession())); return old; @@ -316,10 +321,10 @@ public class CurrentInstance implements Serializable { public static Map, CurrentInstance> setCurrent( VaadinSession session) { Map, CurrentInstance> old = new HashMap, CurrentInstance>(); - old.put(VaadinSession.class, - new CurrentInstance(VaadinSession.getCurrent(), true)); - old.put(VaadinService.class, - new CurrentInstance(VaadinService.getCurrent(), true)); + old.put(VaadinSession.class, new CurrentInstance( + getSameOrNullObject(VaadinSession.getCurrent()), true)); + old.put(VaadinService.class, new CurrentInstance( + getSameOrNullObject(VaadinService.getCurrent()), true)); VaadinService service = null; if (session != null) { service = session.getService(); @@ -331,6 +336,18 @@ public class CurrentInstance implements Serializable { return old; } + /** + * Returns {@code object} unless it is null, in which case #NULL_OBJECT is + * returned. + * + * @param object + * The instance to return if non-null. + * @return {@code object} or #NULL_OBJECT if {@code object} is null. + */ + private static Object getSameOrNullObject(Object object) { + return object == null ? NULL_OBJECT : object; + } + private static Logger getLogger() { return Logger.getLogger(CurrentInstance.class.getName()); } diff --git a/server/tests/src/com/vaadin/util/TestCurrentInstance.java b/server/tests/src/com/vaadin/util/TestCurrentInstance.java index da986abe31..1910172aa8 100644 --- a/server/tests/src/com/vaadin/util/TestCurrentInstance.java +++ b/server/tests/src/com/vaadin/util/TestCurrentInstance.java @@ -15,14 +15,21 @@ */ package com.vaadin.util; +import static org.junit.Assert.assertNull; + import java.lang.reflect.Field; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; -import junit.framework.Assert; - +import org.easymock.EasyMock; +import org.junit.Assert; import org.junit.Test; +import com.vaadin.server.VaadinRequest; +import com.vaadin.server.VaadinService; +import com.vaadin.server.VaadinSession; +import com.vaadin.ui.UI; + public class TestCurrentInstance { @Test @@ -142,4 +149,46 @@ public class TestCurrentInstance { public void testInheritedClearedAfterRemove() { } + + private static class UIStoredInCurrentInstance extends UI { + @Override + protected void init(VaadinRequest request) { + } + } + + private static class SessionStoredInCurrentInstance extends VaadinSession { + public SessionStoredInCurrentInstance(VaadinService service) { + super(service); + } + } + + @Test + public void testRestoringNullUIWorks() throws Exception { + // First make sure current instance is empty + CurrentInstance.clearAll(); + + // Then store a new UI in there + Map, CurrentInstance> old = CurrentInstance + .setCurrent(new UIStoredInCurrentInstance()); + + // Restore the old values and assert that the UI is null again + CurrentInstance.restoreInstances(old); + assertNull(CurrentInstance.get(UI.class)); + } + + @Test + public void testRestoringNullSessionWorks() throws Exception { + // First make sure current instance is empty + CurrentInstance.clearAll(); + + // Then store a new session in there + Map, CurrentInstance> old = CurrentInstance + .setCurrent(new SessionStoredInCurrentInstance(EasyMock + .createNiceMock(VaadinService.class))); + + // Restore the old values and assert that the session is null again + CurrentInstance.restoreInstances(old); + assertNull(CurrentInstance.get(VaadinSession.class)); + assertNull(CurrentInstance.get(VaadinService.class)); + } } -- 2.39.5