aboutsummaryrefslogtreecommitdiffstats
path: root/server/src
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2013-09-03 10:07:22 +0300
committerLeif Åstrand <leif@vaadin.com>2013-09-03 10:07:22 +0300
commitce110b8b060d7c215f69a7e03c24ca80d88da037 (patch)
treeb4209253abf876db9d2233abdba945ae96ae28a8 /server/src
parent261a3ba76a523d7e8d6b717f6f9d67eaef8c901f (diff)
parent11cdf93fedc9e693468d25092afba8172ce8ebf0 (diff)
downloadvaadin-framework-ce110b8b060d7c215f69a7e03c24ca80d88da037.tar.gz
vaadin-framework-ce110b8b060d7c215f69a7e03c24ca80d88da037.zip
Merge changes from origin/7.1
d8b0b50 Always unlock the same session instance that was locked (#12481) e6af0f0 Avoid leaking memory from inherited ThreadLocales. Fixes #12401 f7ee8fb Updated _trackMessageSize based on latest upstream version (#12468) a24d391 Table ignores Container updates while painting (#12258) 7068d78 The colon in the calendar event caption is now also hideable. Fixes #12460 61dd8f7 Corrected typo in version variable (#12440) 476e0b8 Changed 'feature release' text to maintenance release (#12486) faa2569 Updated browser versions 831747a Fix regression where empty RTA returns <br> (#12490) cb8df75 Add deprecation message to unused constant 4c5bb0e Sets the locale in the test case. #12460 11cdf93 Excludes WeakValueMap from the serializable test #12401 Change-Id: Id7eeba06d14518c254ceb01e38e2441967932755
Diffstat (limited to 'server/src')
-rw-r--r--server/src/com/vaadin/server/AbstractClientConnector.java5
-rw-r--r--server/src/com/vaadin/server/Constants.java5
-rw-r--r--server/src/com/vaadin/server/FileDownloader.java6
-rw-r--r--server/src/com/vaadin/ui/AbstractMedia.java6
-rw-r--r--server/src/com/vaadin/ui/Table.java19
-rw-r--r--server/src/com/vaadin/util/CurrentInstance.java2
-rw-r--r--server/src/com/vaadin/util/WeakValueMap.java230
7 files changed, 266 insertions, 7 deletions
diff --git a/server/src/com/vaadin/server/AbstractClientConnector.java b/server/src/com/vaadin/server/AbstractClientConnector.java
index 91a9e41522..a73ca3d985 100644
--- a/server/src/com/vaadin/server/AbstractClientConnector.java
+++ b/server/src/com/vaadin/server/AbstractClientConnector.java
@@ -625,7 +625,8 @@ public abstract class AbstractClientConnector implements ClientConnector,
String[] parts = path.split("/", 2);
String key = parts[0];
- getSession().lock();
+ VaadinSession session = getSession();
+ session.lock();
try {
ConnectorResource resource = (ConnectorResource) getResource(key);
if (resource == null) {
@@ -633,7 +634,7 @@ public abstract class AbstractClientConnector implements ClientConnector,
}
stream = resource.getStream();
} finally {
- getSession().unlock();
+ session.unlock();
}
stream.writeResponse(request, response);
return true;
diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java
index ab91ee021c..8c379abe06 100644
--- a/server/src/com/vaadin/server/Constants.java
+++ b/server/src/com/vaadin/server/Constants.java
@@ -146,6 +146,11 @@ public interface Constants {
// Widget set parameter name
static final String PARAMETER_WIDGETSET = "widgetset";
+ /**
+ * @deprecated As of 7.1, this message is no longer used and might be
+ * removed from the code.
+ */
+ @Deprecated
static final String ERROR_NO_UI_FOUND = "No UIProvider returned a UI for the request.";
static final String DEFAULT_THEME_NAME = "reindeer";
diff --git a/server/src/com/vaadin/server/FileDownloader.java b/server/src/com/vaadin/server/FileDownloader.java
index 9b49ad8edd..bd7d9caafd 100644
--- a/server/src/com/vaadin/server/FileDownloader.java
+++ b/server/src/com/vaadin/server/FileDownloader.java
@@ -129,7 +129,9 @@ public class FileDownloader extends AbstractExtension {
// Ignore if it isn't for us
return false;
}
- getSession().lock();
+ VaadinSession session = getSession();
+
+ session.lock();
DownloadStream stream;
try {
@@ -151,7 +153,7 @@ public class FileDownloader extends AbstractExtension {
stream.setContentType("application/octet-stream;charset=UTF-8");
}
} finally {
- getSession().unlock();
+ session.unlock();
}
stream.writeResponse(request, response);
return true;
diff --git a/server/src/com/vaadin/ui/AbstractMedia.java b/server/src/com/vaadin/ui/AbstractMedia.java
index 97947b568d..d7d593c29e 100644
--- a/server/src/com/vaadin/ui/AbstractMedia.java
+++ b/server/src/com/vaadin/ui/AbstractMedia.java
@@ -30,6 +30,7 @@ import com.vaadin.server.Resource;
import com.vaadin.server.ResourceReference;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinResponse;
+import com.vaadin.server.VaadinSession;
import com.vaadin.shared.communication.URLReference;
import com.vaadin.shared.ui.AbstractMediaState;
import com.vaadin.shared.ui.MediaControl;
@@ -90,7 +91,8 @@ public abstract class AbstractMedia extends AbstractComponent {
DownloadStream stream;
- getSession().lock();
+ VaadinSession session = getSession();
+ session.lock();
try {
List<URLReference> sources = getState().sources;
@@ -108,7 +110,7 @@ public abstract class AbstractMedia extends AbstractComponent {
.getResource(reference);
stream = resource.getStream();
} finally {
- getSession().unlock();
+ session.unlock();
}
stream.writeResponse(request, response);
diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java
index 3507e6b0a5..bd2b7828de 100644
--- a/server/src/com/vaadin/ui/Table.java
+++ b/server/src/com/vaadin/ui/Table.java
@@ -564,6 +564,8 @@ public class Table extends AbstractSelect implements Action.Container,
private List<Throwable> exceptionsDuringCachePopulation = new ArrayList<Throwable>();
+ private boolean isBeingPainted;
+
/* Table constructors */
/**
@@ -3166,6 +3168,15 @@ public class Table extends AbstractSelect implements Action.Container,
@Override
public void paintContent(PaintTarget target) throws PaintException {
+ isBeingPainted = true;
+ try {
+ doPaintContent(target);
+ } finally {
+ isBeingPainted = false;
+ }
+ }
+
+ private void doPaintContent(PaintTarget target) throws PaintException {
/*
* Body actions - Actions which has the target null and can be invoked
* by right clicking on the table body.
@@ -4394,6 +4405,10 @@ public class Table extends AbstractSelect implements Action.Container,
@Override
public void containerItemSetChange(Container.ItemSetChangeEvent event) {
+ if (isBeingPainted) {
+ return;
+ }
+
super.containerItemSetChange(event);
// super method clears the key map, must inform client about this to
@@ -4416,6 +4431,10 @@ public class Table extends AbstractSelect implements Action.Container,
@Override
public void containerPropertySetChange(
Container.PropertySetChangeEvent event) {
+ if (isBeingPainted) {
+ return;
+ }
+
disableContentRefreshing();
super.containerPropertySetChange(event);
diff --git a/server/src/com/vaadin/util/CurrentInstance.java b/server/src/com/vaadin/util/CurrentInstance.java
index b97bab3d8a..a1c543117d 100644
--- a/server/src/com/vaadin/util/CurrentInstance.java
+++ b/server/src/com/vaadin/util/CurrentInstance.java
@@ -60,7 +60,7 @@ public class CurrentInstance implements Serializable {
return null;
}
- Map<Class<?>, CurrentInstance> value = new HashMap<Class<?>, CurrentInstance>();
+ Map<Class<?>, CurrentInstance> value = new WeakValueMap<Class<?>, CurrentInstance>();
// Copy all inheritable values to child map
for (Entry<Class<?>, CurrentInstance> e : parentValue.entrySet()) {
diff --git a/server/src/com/vaadin/util/WeakValueMap.java b/server/src/com/vaadin/util/WeakValueMap.java
new file mode 100644
index 0000000000..1134594cba
--- /dev/null
+++ b/server/src/com/vaadin/util/WeakValueMap.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.util;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A Map holding weak references to its values. It is internally backed by a
+ * normal HashMap and all values are stored as WeakReferences. Garbage collected
+ * entries are removed when touched.
+ * <p>
+ * <em>Note</em> this class is not serializable.
+ *
+ * @author Vaadin Ltd
+ * @since 7.1.4
+ */
+public class WeakValueMap<K, V> implements Map<K, V> {
+
+ /**
+ * This class holds a weak reference to the value and a strong reference to
+ * the key for efficient removal of stale values.
+ */
+ private static class WeakValueReference<K, V> extends WeakReference<V> {
+ private final K key;
+
+ WeakValueReference(K key, V value, ReferenceQueue<V> refQueue) {
+ super(value, refQueue);
+ this.key = key;
+ }
+
+ K getKey() {
+ return key;
+ }
+ }
+
+ private final HashMap<K, WeakValueReference<K, V>> backingMap;
+ private final ReferenceQueue<V> refQueue;
+
+ /**
+ * Constructs a new WeakValueMap, where all values are stored as weak
+ * references.
+ */
+ public WeakValueMap() {
+ backingMap = new HashMap<K, WeakValueReference<K, V>>();
+ refQueue = new ReferenceQueue<V>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public V put(K key, V value) {
+ if (key == null) {
+ throw new NullPointerException("key cannot be null");
+ }
+ if (value == null) {
+ throw new NullPointerException("value cannot be null");
+ }
+ removeStaleEntries();
+ backingMap.put(key, new WeakValueReference<K, V>(key, value, refQueue));
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public V remove(Object o) {
+ removeStaleEntries();
+ WeakReference<V> value = backingMap.remove(o);
+ return value == null ? null : value.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void putAll(Map<? extends K, ? extends V> map) {
+ if (map != null) {
+ for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void clear() {
+ backingMap.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<K> keySet() {
+ removeStaleEntries();
+ return backingMap.keySet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public V get(Object o) {
+ removeStaleEntries();
+ WeakReference<V> weakValue = backingMap.get(o);
+ if (weakValue != null) {
+ return weakValue.get();
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int size() {
+ removeStaleEntries();
+ return backingMap.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isEmpty() {
+ removeStaleEntries();
+ return backingMap.isEmpty();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean containsKey(Object o) {
+ removeStaleEntries();
+ return backingMap.containsKey(o);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean containsValue(Object o) {
+ removeStaleEntries();
+ for (V value : values()) {
+ if (o.equals(value)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Collection<V> values() {
+ removeStaleEntries();
+ Collection<V> values = new HashSet<V>();
+ for (WeakReference<V> weakValue : backingMap.values()) {
+ V value = weakValue.get();
+ if (value != null) {
+ // null values have been GC'd, which may happen long before
+ // anything is enqueued in the ReferenceQueue.
+ values.add(value);
+ }
+ }
+ return values;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<Entry<K, V>> entrySet() {
+ removeStaleEntries();
+ Set<Entry<K, V>> entrySet = new HashSet<Entry<K, V>>();
+ for (Entry<K, WeakValueReference<K, V>> entry : backingMap.entrySet()) {
+ V value = entry.getValue().get();
+ if (value != null) {
+ // null values have been GC'd, which may happen long before
+ // anything is enqueued in the ReferenceQueue.
+ entrySet.add(new AbstractMap.SimpleEntry<K, V>(entry.getKey(),
+ value));
+ }
+ }
+ return entrySet;
+ }
+
+ /**
+ * Cleans up stale entries by polling the ReferenceQueue.
+ * <p>
+ * Depending on the GC implementation and strategy, the ReferenceQueue is
+ * not necessarily notified immediately when a reference is garbage
+ * collected, but it will eventually be.
+ */
+ private void removeStaleEntries() {
+ Reference<? extends V> ref;
+ while ((ref = refQueue.poll()) != null) {
+ Object key = ((WeakValueReference<?, ?>) ref).getKey();
+ backingMap.remove(key);
+ }
+ }
+}