diff options
author | Leif Åstrand <leif@vaadin.com> | 2013-07-23 16:12:49 +0300 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2013-07-23 16:12:49 +0300 |
commit | a53d4876f2e1b0edf34444e118c79b881f5549f9 (patch) | |
tree | 8e253448a1dd7fdbb37acc7d7ee4340d6497536f /server/src | |
parent | 62c63a6a6dcf97c5a8f7b02e0115fdab096226db (diff) | |
download | vaadin-framework-a53d4876f2e1b0edf34444e118c79b881f5549f9.tar.gz vaadin-framework-a53d4876f2e1b0edf34444e118c79b881f5549f9.zip |
Verify the connector hierarchy if assertions are enabled (#12271)
Change-Id: I87632abe9d86927b7ba4254724fedfdb04513205
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/com/vaadin/ui/ConnectorTracker.java | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java index c2aeebcd44..0f8ec60104 100644 --- a/server/src/com/vaadin/ui/ConnectorTracker.java +++ b/server/src/com/vaadin/ui/ConnectorTracker.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -271,6 +272,12 @@ public class ConnectorTracker implements Serializable { } unregisteredConnectors.clear(); + // Do this expensive check only with assertions enabled + assert isHierarchyComplete() : "The connector hierarchy is corrupted. " + + "Check for missing calls to super.setParent(), super.attach() and super.detach() " + + "and that all custom component containers call child.setParent(this) when a child is added and child.setParent(null) when the child is no longer used. " + + "See previous log messages for details."; + // remove detached components from paintableIdMap so they // can be GC'ed Iterator<String> iterator = connectorIdToConnector.keySet().iterator(); @@ -313,6 +320,49 @@ public class ConnectorTracker implements Serializable { cleanStreamVariables(); } + private boolean isHierarchyComplete() { + boolean noErrors = true; + + Set<ClientConnector> danglingConnectors = new HashSet<ClientConnector>( + connectorIdToConnector.values()); + + LinkedList<ClientConnector> stack = new LinkedList<ClientConnector>(); + stack.add(uI); + while (!stack.isEmpty()) { + ClientConnector connector = stack.pop(); + danglingConnectors.remove(connector); + + Iterable<ClientConnector> children = AbstractClientConnector + .getAllChildrenIterable(connector); + for (ClientConnector child : children) { + stack.add(child); + + if (child.getParent() != connector) { + noErrors = false; + getLogger() + .log(Level.WARNING, + "{0} claims that {1} is its child, but the child claims {2} is its parent.", + new Object[] { + getConnectorString(connector), + getConnectorString(child), + getConnectorString(child + .getParent()) }); + } + } + } + + for (ClientConnector dangling : danglingConnectors) { + noErrors = false; + getLogger() + .log(Level.WARNING, + "{0} claims that {1} is its parent, but the parent does not acknowledge the parenthood.", + new Object[] { getConnectorString(dangling), + getConnectorString(dangling.getParent()) }); + } + + return noErrors; + } + /** * Finds the uI that the connector is attached to. * |