diff options
Diffstat (limited to 'server')
8 files changed, 66 insertions, 88 deletions
diff --git a/server/src/com/vaadin/data/RpcDataProviderExtension.java b/server/src/com/vaadin/data/RpcDataProviderExtension.java index 71b597ff1d..55947c98d1 100644 --- a/server/src/com/vaadin/data/RpcDataProviderExtension.java +++ b/server/src/com/vaadin/data/RpcDataProviderExtension.java @@ -947,6 +947,14 @@ public class RpcDataProviderExtension extends AbstractExtension { listener.removeListener(); } + // Wipe clean all details. + HashSet<Object> detailItemIds = new HashSet<Object>( + detailComponentManager.visibleDetailsComponents + .keySet()); + for (Object itemId : detailItemIds) { + detailComponentManager.destroyDetails(itemId); + } + listeners.clear(); activeRowHandler.activeRange = Range.withLength(0, 0); @@ -1387,4 +1395,14 @@ public class RpcDataProviderExtension extends AbstractExtension { public DetailComponentManager getDetailComponentManager() { return detailComponentManager; } + + @Override + public void detach() { + for (Object itemId : ImmutableSet + .copyOf(detailComponentManager.visibleDetails)) { + detailComponentManager.destroyDetails(itemId); + } + + super.detach(); + } } diff --git a/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java b/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java index 495bed74f8..b86fec5558 100644 --- a/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java +++ b/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java @@ -155,9 +155,7 @@ public class StringToCollectionConverter implements previous = index + delimiter.length(); index = value.indexOf(delimiter, previous); } - if (result.size() > 0) { - collectToken(value.substring(previous), result, converter, locale); - } + collectToken(value.substring(previous), result, converter, locale); return result; } diff --git a/server/src/com/vaadin/server/AbstractClientConnector.java b/server/src/com/vaadin/server/AbstractClientConnector.java index 0655b482ed..b6bcebd167 100644 --- a/server/src/com/vaadin/server/AbstractClientConnector.java +++ b/server/src/com/vaadin/server/AbstractClientConnector.java @@ -30,6 +30,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; import com.vaadin.event.EventRouter; @@ -91,6 +92,8 @@ public abstract class AbstractClientConnector implements ClientConnector, private ErrorHandler errorHandler = null; + private static final ConcurrentHashMap<Class<? extends AbstractClientConnector>, Class<? extends SharedState>> stateTypeCache = new ConcurrentHashMap<Class<? extends AbstractClientConnector>, Class<? extends SharedState>>(); + @Override public void addAttachListener(AttachListener listener) { addListener(AttachEvent.ATTACH_EVENT_IDENTIFIER, AttachEvent.class, @@ -296,7 +299,12 @@ public abstract class AbstractClientConnector implements ClientConnector, // Lazy load because finding type can be expensive because of the // exceptions flying around if (stateType == null) { - stateType = findStateType(); + // Cache because we don't need to do this once per instance + stateType = stateTypeCache.get(this.getClass()); + if (stateType == null) { + stateType = findStateType(); + stateTypeCache.put(this.getClass(), stateType); + } } return stateType; diff --git a/server/src/com/vaadin/server/CustomizedSystemMessages.java b/server/src/com/vaadin/server/CustomizedSystemMessages.java index f7049e3688..9aef4f5cf3 100644 --- a/server/src/com/vaadin/server/CustomizedSystemMessages.java +++ b/server/src/com/vaadin/server/CustomizedSystemMessages.java @@ -240,50 +240,6 @@ public class CustomizedSystemMessages extends SystemMessages implements } /** - * Sets the URL to go to when the client is out-of-sync. - * - * @param outOfSyncURL - * the URL to go to, or null to reload current - */ - public void setOutOfSyncURL(String outOfSyncURL) { - this.outOfSyncURL = outOfSyncURL; - } - - /** - * Enables or disables the notification. If disabled, the set URL (or - * current) is loaded directly. - * - * @param outOfSyncNotificationEnabled - * true = enabled, false = disabled - */ - public void setOutOfSyncNotificationEnabled( - boolean outOfSyncNotificationEnabled) { - this.outOfSyncNotificationEnabled = outOfSyncNotificationEnabled; - } - - /** - * Sets the caption of the notification. Set to null for no caption. If both - * caption and message is null, the notification is disabled; - * - * @param outOfSyncCaption - * the caption - */ - public void setOutOfSyncCaption(String outOfSyncCaption) { - this.outOfSyncCaption = outOfSyncCaption; - } - - /** - * Sets the message of the notification. Set to null for no message. If both - * caption and message is null, the notification is disabled; - * - * @param outOfSyncMessage - * the message - */ - public void setOutOfSyncMessage(String outOfSyncMessage) { - this.outOfSyncMessage = outOfSyncMessage; - } - - /** * Sets the URL to redirect to when the browser has cookies disabled. * * @param cookiesDisabledURL diff --git a/server/src/com/vaadin/server/SystemMessages.java b/server/src/com/vaadin/server/SystemMessages.java index 51cc7d497d..3bcf0a90fa 100644 --- a/server/src/com/vaadin/server/SystemMessages.java +++ b/server/src/com/vaadin/server/SystemMessages.java @@ -43,12 +43,6 @@ import java.io.Serializable; * <li><b>internalErrorCaption</b> = "Internal error"</li> * <li><b>internalErrorMessage</b> = "Please notify the administrator.<br/> * Take note of any unsaved data, and <u>click here</u> to continue."</li> - * <li><b>outOfSyncURL</b> = null</li> - * <li><b>outOfSyncNotificationEnabled</b> = true</li> - * <li><b>outOfSyncCaption</b> = "Out of sync"</li> - * <li><b>outOfSyncMessage</b> = "Something has caused us to be out of sync with - * the server.<br/> - * Take note of any unsaved data, and <u>click here</u> to re-sync."</li> * <li><b>cookiesDisabledURL</b> = null</li> * <li><b>cookiesDisabledNotificationEnabled</b> = true</li> * <li><b>cookiesDisabledCaption</b> = "Cookies disabled"</li> @@ -80,11 +74,6 @@ public class SystemMessages implements Serializable { protected String internalErrorCaption = "Internal error"; protected String internalErrorMessage = "Please notify the administrator.<br/>Take note of any unsaved data, and <u>click here</u> or press ESC to continue."; - protected String outOfSyncURL = null; - protected boolean outOfSyncNotificationEnabled = true; - protected String outOfSyncCaption = "Out of sync"; - protected String outOfSyncMessage = "Something has caused us to be out of sync with the server.<br/>Take note of any unsaved data, and <u>click here</u> or press ESC to re-sync."; - protected String cookiesDisabledURL = null; protected boolean cookiesDisabledNotificationEnabled = true; protected String cookiesDisabledCaption = "Cookies disabled"; diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java index 95a80b7be0..eba248fb00 100644 --- a/server/src/com/vaadin/ui/ConnectorTracker.java +++ b/server/src/com/vaadin/ui/ConnectorTracker.java @@ -24,6 +24,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; +import java.util.NavigableMap; import java.util.Set; import java.util.TreeMap; import java.util.UUID; @@ -591,8 +592,8 @@ public class ConnectorTracker implements Serializable { * <p> * This method has a side-effect of incrementing the sync id by one (see * {@link #getCurrentSyncId()}), if {@link #isWritingResponse()} returns - * <code>false</code> and <code>writingResponse</code> is set to - * <code>true</code>. + * <code>true</code> and <code>writingResponse</code> is set to + * <code>false</code>. * * @param writingResponse * the new response status. @@ -616,7 +617,9 @@ public class ConnectorTracker implements Serializable { * the right hand side of the && is unnecessary here because of the * if-clause above, but rigorous coding is always rigorous coding. */ - if (writingResponse && !this.writingResponse) { + if (!writingResponse && this.writingResponse) { + // Bump sync id when done writing - the client is not expected to + // know about anything happening after this moment. currentSyncId++; } this.writingResponse = writingResponse; @@ -784,34 +787,25 @@ public class ConnectorTracker implements Serializable { */ public boolean connectorWasPresentAsRequestWasSent(String connectorId, long lastSyncIdSeenByClient) { - assert getConnector(connectorId) == null : "Connector " + connectorId + " is still attached"; - boolean clientRequestIsTooOld = lastSyncIdSeenByClient < currentSyncId - && lastSyncIdSeenByClient != -1; - if (clientRequestIsTooOld) { - /* - * The headMap call is present here because we're only interested in - * connectors removed "in the past" (i.e. the server has removed - * them before the client ever knew about that), since those are the - * ones that we choose to handle as a special case. - */ - /*- - * Server Client - * [#1 add table] ---------. - * \ - * [push: #2 remove table]-. `--> [adding table, storing #1] - * \ .- [table from request #1 needs more data] - * \/ - * /`-> [removing table, storing #2] - * [#1 < #2 - ignoring] <---ยด - */ - for (Set<String> unregisteredConnectors : syncIdToUnregisteredConnectorIds - .headMap(currentSyncId).values()) { - if (unregisteredConnectors.contains(connectorId)) { - return true; - } + if (lastSyncIdSeenByClient == -1) { + // Ignore potential problems + return true; + } + + /* + * Use non-inclusive tail map to find all connectors that were removed + * after the reported sync id was sent to the client. + */ + NavigableMap<Integer, Set<String>> unregisteredAfter = syncIdToUnregisteredConnectorIds + .tailMap(Integer.valueOf((int) lastSyncIdSeenByClient), false); + for (Set<String> unregisteredIds : unregisteredAfter.values()) { + if (unregisteredIds.contains(connectorId)) { + // Removed with a higher sync id, so it was most likely present + // when this sync id was sent. + return true; } } @@ -877,7 +871,7 @@ public class ConnectorTracker implements Serializable { * conflicts. In any case, it's better to clean up too little than too * much, especially as the data will hardly grow into the kilobytes. */ - syncIdToUnregisteredConnectorIds.headMap(lastSyncIdSeenByClient) + syncIdToUnregisteredConnectorIds.headMap(lastSyncIdSeenByClient, true) .clear(); } } diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java index af89064411..251ec0f678 100644 --- a/server/src/com/vaadin/ui/Grid.java +++ b/server/src/com/vaadin/ui/Grid.java @@ -6084,10 +6084,15 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, editorActive = false; editorFieldGroup.discard(); editorFieldGroup.setItemDataSource(null); + if (datasource instanceof ItemSetChangeNotifier) { ((ItemSetChangeNotifier) datasource) .removeItemSetChangeListener(editorClosingItemSetListener); } + + // Mark Grid as dirty so the client side gets to know that the editors + // are no longer attached + markAsDirty(); } void resetEditor() { diff --git a/server/tests/src/com/vaadin/tests/data/converter/StringToCollectionConverterTest.java b/server/tests/src/com/vaadin/tests/data/converter/StringToCollectionConverterTest.java index 977985c6cb..bcd0dc15bd 100644 --- a/server/tests/src/com/vaadin/tests/data/converter/StringToCollectionConverterTest.java +++ b/server/tests/src/com/vaadin/tests/data/converter/StringToCollectionConverterTest.java @@ -141,6 +141,16 @@ public class StringToCollectionConverterTest { Assert.assertEquals("Z,Y", presentation); } + @Test + public void convertToModel_singleItem() { + StringToCollectionConverter converter = new StringToCollectionConverter(); + Collection<?> model = converter.convertToModel("a", List.class, null); + Iterator<?> iterator = model.iterator(); + Assert.assertEquals("Incorrect fist token", "a", iterator.next()); + Assert.assertFalse("More than one item detected after conversation", + iterator.hasNext()); + } + public enum TestEnum { X, Y, Z; } |