summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2014-07-22 12:59:14 +0300
committerLeif Åstrand <leif@vaadin.com>2014-07-22 12:59:32 +0300
commit86e1c718578f8c81323b47e3efed03178d123c03 (patch)
tree9eaf3779ce79b67963c9fcb3a43c7fd6c39f25fd
parentaca2902c9cafcb02db19a0cdd42b1488786c0f56 (diff)
parent6ae7843e46ee906adfc99bde71ded5f296caea74 (diff)
downloadvaadin-framework-86e1c718578f8c81323b47e3efed03178d123c03.tar.gz
vaadin-framework-86e1c718578f8c81323b47e3efed03178d123c03.zip
Merge branch 'master' into grid
Change-Id: I6878b3c64eb5c98174537f4e5864e2ff2cb1863f
-rw-r--r--WebContent/VAADIN/themes/base/common/common.scss6
-rw-r--r--WebContent/VAADIN/themes/chameleon/components/notification/notification.scss1
-rw-r--r--WebContent/VAADIN/themes/chameleon/components/tabsheet/tabsheet.scss1
-rw-r--r--WebContent/WEB-INF/web.xml4
-rw-r--r--buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java10
-rw-r--r--client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java12
-rw-r--r--client/src/com/vaadin/client/ApplicationConnection.java198
-rw-r--r--client/src/com/vaadin/client/Util.java17
-rw-r--r--client/src/com/vaadin/client/communication/AtmospherePushConnection.java26
-rw-r--r--client/src/com/vaadin/client/ui/VContextMenu.java2
-rw-r--r--client/src/com/vaadin/client/ui/VFilterSelect.java8
-rw-r--r--client/src/com/vaadin/client/ui/VOverlay.java6
-rw-r--r--client/src/com/vaadin/client/ui/VScrollTable.java24
-rw-r--r--client/src/com/vaadin/client/ui/VTextField.java57
-rw-r--r--client/src/com/vaadin/client/ui/table/TableConnector.java11
-rw-r--r--push/build.xml2
-rw-r--r--push/ivy.xml2
-rw-r--r--server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java4
-rw-r--r--server/src/com/vaadin/data/util/ContainerOrderedWrapper.java1
-rw-r--r--server/src/com/vaadin/server/AbstractJavaScriptExtension.java2
-rw-r--r--server/src/com/vaadin/server/Constants.java2
-rw-r--r--server/src/com/vaadin/server/JsonCodec.java23
-rw-r--r--server/src/com/vaadin/server/VaadinService.java278
-rw-r--r--server/src/com/vaadin/server/VaadinServlet.java134
-rw-r--r--server/src/com/vaadin/server/VaadinSession.java215
-rw-r--r--server/src/com/vaadin/server/communication/LegacyUidlWriter.java13
-rw-r--r--server/src/com/vaadin/server/communication/PushHandler.java20
-rw-r--r--server/src/com/vaadin/server/communication/PushRequestHandler.java15
-rw-r--r--server/src/com/vaadin/server/communication/ServerRpcHandler.java42
-rw-r--r--server/src/com/vaadin/ui/AbstractJavaScriptComponent.java2
-rw-r--r--server/src/com/vaadin/ui/AbstractSelect.java4
-rw-r--r--server/src/com/vaadin/ui/ComboBox.java2
-rw-r--r--server/src/com/vaadin/ui/ConnectorTracker.java91
-rw-r--r--server/src/com/vaadin/ui/Upload.java160
-rw-r--r--server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java1
-rw-r--r--server/src/com/vaadin/util/CurrentInstance.java94
-rw-r--r--server/tests/src/com/vaadin/data/util/ContainerSizeAssertTest.java59
-rw-r--r--server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java248
-rw-r--r--shared/src/com/vaadin/shared/ApplicationConstants.java20
-rw-r--r--uitest/eclipse-run-selected-test.properties15
-rw-r--r--uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java135
-rw-r--r--uitest/src/com/vaadin/launcher/CustomDeploymentConfiguration.java36
-rw-r--r--uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConf.java55
-rw-r--r--uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConfTest.java41
-rw-r--r--uitest/src/com/vaadin/tests/components/button/ButtonTooltips.html37
-rw-r--r--uitest/src/com/vaadin/tests/components/table/MemoryLeakTable.java85
-rw-r--r--uitest/src/com/vaadin/tests/components/table/MemoryLeakTableTest.java95
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableTooManyColumns.java65
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableTooManyColumnsTest.java46
-rw-r--r--uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpace.java75
-rw-r--r--uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpaceTest.java47
-rw-r--r--uitest/src/com/vaadin/tests/components/upload/TestFileUploadTest.java2
-rw-r--r--uitest/src/com/vaadin/tests/serialization/SerializerTest.java8
-rw-r--r--uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java31
-rw-r--r--uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java19
-rw-r--r--uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java63
-rw-r--r--uitest/src/com/vaadin/tests/tb3/TB3Runner.java16
-rw-r--r--uitest/src/com/vaadin/tests/tooltip/ButtonTooltips.java16
-rw-r--r--uitest/src/com/vaadin/tests/tooltip/ButtonTooltipsTest.java12
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml5
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java81
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java13
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/csrf/CsrfButtonConnector.java82
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/csrf/CsrfButton.java30
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUI.java60
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUITest.java116
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabled.java35
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabledTest.java43
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabled.java25
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabledTest.java43
70 files changed, 2517 insertions, 732 deletions
diff --git a/WebContent/VAADIN/themes/base/common/common.scss b/WebContent/VAADIN/themes/base/common/common.scss
index 0a493e0356..77248c0c96 100644
--- a/WebContent/VAADIN/themes/base/common/common.scss
+++ b/WebContent/VAADIN/themes/base/common/common.scss
@@ -146,6 +146,12 @@ body &.v-app .v-app-loading {
border: 0;
margin: 0;
}
+
+.v-contextmenu .gwt-MenuBar {
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
.v-contextmenu .gwt-MenuItem div {
cursor: pointer;
vertical-align: middle;
diff --git a/WebContent/VAADIN/themes/chameleon/components/notification/notification.scss b/WebContent/VAADIN/themes/chameleon/components/notification/notification.scss
index fbf78d40c4..783e4bcc1f 100644
--- a/WebContent/VAADIN/themes/chameleon/components/notification/notification.scss
+++ b/WebContent/VAADIN/themes/chameleon/components/notification/notification.scss
@@ -8,6 +8,7 @@ div.#{$primaryStyleName} {
-webkit-box-shadow: 0 2px 5px rgba(0,0,0,.7);
-moz-box-shadow: 0 2px 5px rgba(0,0,0,.7);
box-shadow: 0 2px 5px rgba(0,0,0,.7);
+ background:rgba(255,255,255,.90) url(../img/grad-light-top.png) repeat-x;
}
.#{$primaryStyleName} p {
diff --git a/WebContent/VAADIN/themes/chameleon/components/tabsheet/tabsheet.scss b/WebContent/VAADIN/themes/chameleon/components/tabsheet/tabsheet.scss
index dfa1c51c3a..d7f968fe43 100644
--- a/WebContent/VAADIN/themes/chameleon/components/tabsheet/tabsheet.scss
+++ b/WebContent/VAADIN/themes/chameleon/components/tabsheet/tabsheet.scss
@@ -89,6 +89,7 @@
.#{$primaryStyleName}-scrollerNext-disabled,
.#{$primaryStyleName}-scrollerPrev-disabled:active,
.#{$primaryStyleName}-scrollerNext-disabled:active {
+ padding-top: 12px;
border: 1px solid #b3b3b3;
border-width: 0;
background: transparent url(../../img/tab-arrows.png) no-repeat 6px 50%;
diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml
index fb2ddbd998..9ca5be2bdf 100644
--- a/WebContent/WEB-INF/web.xml
+++ b/WebContent/WEB-INF/web.xml
@@ -118,11 +118,11 @@
<param-name>pushmode</param-name>
<param-value>automatic</param-value>
</init-param>
- <async-supported>true</async-supported>
<init-param>
<param-name>org.atmosphere.cpr.scanClassPath</param-name>
<param-value>false</param-value>
</init-param>
+ <async-supported>true</async-supported>
</servlet>
<!-- For testing GAE - the deployment script changes this to use GAEVaadinServlet -->
@@ -133,11 +133,11 @@
<param-name>UI</param-name>
<param-value>com.vaadin.tests.integration.ServletIntegrationUI</param-value>
</init-param>
- <async-supported>true</async-supported>
<init-param>
<param-name>org.atmosphere.cpr.scanClassPath</param-name>
<param-value>false</param-value>
</init-param>
+ <async-supported>true</async-supported>
</servlet>
<servlet-mapping>
diff --git a/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java b/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java
index 028880b2e1..dc2a676ab8 100644
--- a/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java
+++ b/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -58,6 +58,10 @@ public class FetchReleaseNotesTickets {
List<String> tickets = IOUtils.readLines(urlStream);
for (String ticket : tickets) {
+ // Omit BOM
+ if (!ticket.isEmpty() && ticket.charAt(0) == 65279) {
+ ticket = ticket.substring(1);
+ }
String[] fields = ticket.split("\t");
if ("id".equals(fields[0])) {
// This is the header
diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java
index 6c242dfd74..a31dafe05c 100644
--- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java
+++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java
@@ -45,25 +45,17 @@ public class FieldProperty extends Property {
@Override
public void writeSetterBody(TreeLogger logger, SourceWriter w,
String beanVariable, String valueVariable) {
- // Don't try to unbox Longs in javascript, as it's not supported.
- // (#13692)
- boolean shouldUnbox = !"long".equals(field.getType()
- .getSimpleSourceName());
w.println("%s.@%s::%s = %s;", beanVariable, getBeanType()
- .getQualifiedSourceName(), getName(),
- shouldUnbox ? unboxValue(valueVariable) : valueVariable);
+ .getQualifiedSourceName(), getName(), unboxValue(valueVariable));
}
@Override
public void writeGetterBody(TreeLogger logger, SourceWriter w,
String beanVariable) {
- // Longs are not unboxed, as it's not supported. (#13692)
- boolean shouldBox = !"long".equals(field.getType()
- .getSimpleSourceName());
String value = String.format("%s.@%s::%s", beanVariable, getBeanType()
.getQualifiedSourceName(), getName());
w.print("return ");
- w.print(shouldBox ? boxValue(value) : value);
+ w.print(boxValue(value));
w.println(";");
}
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java
index 6bbca98042..6abcdac487 100644
--- a/client/src/com/vaadin/client/ApplicationConnection.java
+++ b/client/src/com/vaadin/client/ApplicationConnection.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -111,14 +111,14 @@ import com.vaadin.shared.ui.ui.UIState.PushConfigurationState;
* This is the client side communication "engine", managing client-server
* communication with its server side counterpart
* com.vaadin.server.VaadinService.
- *
+ *
* Client-side connectors receive updates from the corresponding server-side
* connector (typically component) as state updates or RPC calls. The connector
* has the possibility to communicate back with its server side counter part
* through RPC calls.
- *
+ *
* TODO document better
- *
+ *
* Entry point classes (widgetsets) define <code>onModuleLoad()</code>.
*/
public class ApplicationConnection implements HasHandlers {
@@ -150,12 +150,12 @@ public class ApplicationConnection implements HasHandlers {
* A string that, if found in a non-JSON response to a UIDL request, will
* cause the browser to refresh the page. If followed by a colon, optional
* whitespace, and a URI, causes the browser to synchronously load the URI.
- *
+ *
* <p>
* This allows, for instance, a servlet filter to redirect the application
* to a custom login page when the session expires. For example:
* </p>
- *
+ *
* <pre>
* if (sessionExpired) {
* response.setHeader(&quot;Content-Type&quot;, &quot;text/html&quot;);
@@ -168,7 +168,7 @@ public class ApplicationConnection implements HasHandlers {
public static final String UIDL_REFRESH_TOKEN = "Vaadin-Refresh";
// will hold the CSRF token once received
- private String csrfToken = "init";
+ private String csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE;
private final HashMap<String, String> resourcesMap = new HashMap<String, String>();
@@ -346,7 +346,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Event triggered when a XHR request has finished with the status code of
* the response.
- *
+ *
* Useful for handlers observing network failures like online/off-line
* monitors.
*/
@@ -402,12 +402,12 @@ public class ApplicationConnection implements HasHandlers {
/**
* Event triggered when a application is stopped by calling
* {@link ApplicationConnection#setApplicationRunning(false)}.
- *
+ *
* To listen for the event add a {@link ApplicationStoppedHandler} by
* invoking
* {@link ApplicationConnection#addHandler(ApplicationConnection.ApplicationStoppedEvent.Type, ApplicationStoppedHandler)}
* to the {@link ApplicationConnection}
- *
+ *
* @since 7.1.8
* @author Vaadin Ltd
*/
@@ -434,7 +434,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Called when a communication error has occurred. Returning
* <code>true</code> from this method suppresses error handling.
- *
+ *
* @param details
* A string describing the error.
* @param statusCode
@@ -449,7 +449,7 @@ public class ApplicationConnection implements HasHandlers {
* A listener for listening to application stopped events. The listener can
* be added to a {@link ApplicationConnection} by invoking
* {@link ApplicationConnection#addHandler(ApplicationStoppedEvent.Type, ApplicationStoppedHandler)}
- *
+ *
* @since 7.1.8
* @author Vaadin Ltd
*/
@@ -459,7 +459,7 @@ public class ApplicationConnection implements HasHandlers {
* Triggered when the {@link ApplicationConnection} marks a previously
* running application as stopped by invoking
* {@link ApplicationConnection#setApplicationRunning(false)}
- *
+ *
* @param event
* the event triggered by the {@link ApplicationConnection}
*/
@@ -570,7 +570,7 @@ public class ApplicationConnection implements HasHandlers {
* called once this application has started (first response received) or
* failed to start. This ensures that the applications are started in order,
* to avoid session-id problems.
- *
+ *
*/
public void start() {
String jsonText = configuration.getUIDL();
@@ -671,7 +671,7 @@ public class ApplicationConnection implements HasHandlers {
* <li><code>vaadin.postRequestHooks</code> is a map of functions which gets
* called after each XHR made by vaadin application. Note, that it is
* attaching js functions responsibility to create the variable like this:
- *
+ *
* <code><pre>
* if(!vaadin.postRequestHooks) {vaadin.postRequestHooks = new Object();}
* postRequestHooks.myHook = function(appId) {
@@ -682,7 +682,7 @@ public class ApplicationConnection implements HasHandlers {
* </pre></code> First parameter passed to these functions is the identifier
* of Vaadin application that made the request.
* </ul>
- *
+ *
* TODO make this multi-app aware
*/
private native void initializeClientHooks()
@@ -713,7 +713,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Runs possibly registered client side post request hooks. This is expected
* to be run after each uidl request made by Vaadin application.
- *
+ *
* @param appId
*/
private static native void runPostRequestHooks(String appId)
@@ -733,7 +733,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* If on Liferay and logged in, ask the client side session management
* JavaScript to extend the session duration.
- *
+ *
* Otherwise, Liferay client side JavaScript will explicitly expire the
* session even though the server side considers the session to be active.
* See ticket #8305 for more information.
@@ -752,7 +752,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Indicates whether or not there are currently active UIDL requests. Used
* internally to sequence requests properly, seldom needed in Widgets.
- *
+ *
* @return true if there are active requests
*/
public boolean hasActiveRequest() {
@@ -772,7 +772,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Requests an analyze of layouts, to find inconsistencies. Exclusively used
* for debugging during development.
- *
+ *
* @deprecated as of 7.1. Replaced by {@link UIConnector#analyzeLayouts()}
*/
@Deprecated
@@ -784,7 +784,7 @@ public class ApplicationConnection implements HasHandlers {
* Sends a request to the server to print details to console that will help
* the developer to locate the corresponding server-side connector in the
* source code.
- *
+ *
* @param serverConnector
* @deprecated as of 7.1. Replaced by
* {@link UIConnector#showServerDebugInfo(ServerConnector)}
@@ -796,7 +796,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Makes an UIDL request to the server.
- *
+ *
* @param reqInvocations
* Data containing RPC invocations and all related information.
* @param extraParams
@@ -810,8 +810,10 @@ public class ApplicationConnection implements HasHandlers {
startRequest();
JSONObject payload = new JSONObject();
- payload.put(ApplicationConstants.CSRF_TOKEN, new JSONString(
- getCsrfToken()));
+ if (!getCsrfToken().equals(ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE)) {
+ payload.put(ApplicationConstants.CSRF_TOKEN, new JSONString(
+ getCsrfToken()));
+ }
payload.put(ApplicationConstants.RPC_INVOCATIONS, reqInvocations);
payload.put(ApplicationConstants.SERVER_SYNC_ID, new JSONNumber(
lastSeenServerSyncId));
@@ -833,7 +835,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Sends an asynchronous or synchronous UIDL request to the server using the
* given URI.
- *
+ *
* @param uri
* The URI to use for the request. May includes GET parameters
* @param payload
@@ -971,7 +973,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Handles received UIDL JSON text, parsing it, and passing it on to the
* appropriate handlers, while logging timing information.
- *
+ *
* @param jsonText
* @param statusCode
*/
@@ -999,7 +1001,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Sends an asynchronous UIDL request to the server using the given URI.
- *
+ *
* @param uri
* The URI to use for the request. May includes GET parameters
* @param payload
@@ -1134,7 +1136,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Checks whether or not the CSS is loaded. By default checks the size of
* the loading indicator element.
- *
+ *
* @return
*/
protected boolean isCSSLoaded() {
@@ -1144,12 +1146,12 @@ public class ApplicationConnection implements HasHandlers {
/**
* Shows the communication error notification.
- *
+ *
* @param details
* Optional details for debugging.
* @param statusCode
* The status code returned for the request
- *
+ *
*/
protected void showCommunicationError(String details, int statusCode) {
VConsole.error("Communication error: " + details);
@@ -1158,7 +1160,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Shows the authentication error notification.
- *
+ *
* @param details
* Optional details for debugging.
*/
@@ -1169,7 +1171,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Shows the session expiration notification.
- *
+ *
* @param details
* Optional details for debugging.
*/
@@ -1180,7 +1182,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Shows an error notification.
- *
+ *
* @param details
* Optional details for debugging.
* @param message
@@ -1193,7 +1195,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Shows the error notification.
- *
+ *
* @param details
* Optional details for debugging.
*/
@@ -1281,7 +1283,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* This method is called after applying uidl change set to application.
- *
+ *
* It will clean current and queued variable change sets. And send next
* change set if it exists.
*/
@@ -1300,7 +1302,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Cleans given queue of variable changes of such changes that came from
* components that do not exist anymore.
- *
+ *
* @param variableBurst
*/
private void cleanVariableBurst(
@@ -1325,7 +1327,7 @@ public class ApplicationConnection implements HasHandlers {
* <p>
* Used by the native "client.isActive" function.
* </p>
- *
+ *
* @return true if deferred commands are (potentially) being executed, false
* otherwise
*/
@@ -1340,7 +1342,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Returns the loading indicator used by this ApplicationConnection
- *
+ *
* @return The loading indicator for this ApplicationConnection
*/
public VLoadingIndicator getLoadingIndicator() {
@@ -1349,7 +1351,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Determines whether or not the loading indicator is showing.
- *
+ *
* @return true if the loading indicator is visible
* @deprecated As of 7.1. Use {@link #getLoadingIndicator()} and
* {@link VLoadingIndicator#isVisible()}.isVisible() instead.
@@ -1383,7 +1385,7 @@ public class ApplicationConnection implements HasHandlers {
* server is received.
* <p>
* The initial id when no request has yet been processed is -1.
- *
+ *
* @return and id identifying the response
*/
public int getLastResponseId() {
@@ -1806,13 +1808,13 @@ public class ApplicationConnection implements HasHandlers {
/**
* Sends the state change events created while updating the state
* information.
- *
+ *
* This must be called after hierarchy change listeners have been
* called. At least caption updates for the parent are strange if
* fired from state change listeners and thus calls the parent
* BEFORE the parent is aware of the child (through a
* ConnectorHierarchyChangedEvent)
- *
+ *
* @param pendingStateChangeEvents
* The events to send
*/
@@ -2127,7 +2129,7 @@ public class ApplicationConnection implements HasHandlers {
* Updates the connector hierarchy and returns a list of events that
* should be fired after update of the hierarchy and the state is
* done.
- *
+ *
* @param json
* The JSON containing the hierarchy information
* @return A collection of events that should be fired when update
@@ -2524,9 +2526,9 @@ public class ApplicationConnection implements HasHandlers {
/**
* Adds an explicit RPC method invocation to the send queue.
- *
+ *
* @since 7.0
- *
+ *
* @param invocation
* RPC method invocation
* @param delayed
@@ -2566,7 +2568,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Removes any pending invocation of the given method from the queue
- *
+ *
* @param invocation
* The invocation to remove
*/
@@ -2584,12 +2586,12 @@ public class ApplicationConnection implements HasHandlers {
/**
* This method sends currently queued variable changes to server. It is
* called when immediate variable update must happen.
- *
+ *
* To ensure correct order for variable changes (due servers multithreading
* or network), we always wait for active request to be handler before
* sending a new one. If there is an active request, we will put varible
* "burst" to queue that will be purged after current request is handled.
- *
+ *
*/
public void sendPendingVariableChanges() {
if (!deferedSendPending) {
@@ -2630,11 +2632,11 @@ public class ApplicationConnection implements HasHandlers {
/**
* Build the variable burst and send it to server.
- *
+ *
* When sync is forced, we also force sending of all pending variable-bursts
* at the same time. This is ok as we can assume that DOM will never be
* updated after this.
- *
+ *
* @param pendingInvocations
* List of RPC method invocations to send
*/
@@ -2721,7 +2723,7 @@ public class ApplicationConnection implements HasHandlers {
* is true, the update is sent as soon as possible. If immediate is false,
* the update will be sent along with the next immediate update.
* </p>
- *
+ *
* @param paintableId
* the id of the paintable that owns the variable
* @param variableName
@@ -2743,7 +2745,7 @@ public class ApplicationConnection implements HasHandlers {
* is true, the update is sent as soon as possible. If immediate is false,
* the update will be sent along with the next immediate update.
* </p>
- *
+ *
* @param paintableId
* the id of the paintable that owns the variable
* @param variableName
@@ -2766,7 +2768,7 @@ public class ApplicationConnection implements HasHandlers {
* is true, the update is sent as soon as possible. If immediate is false,
* the update will be sent along with the next immediate update.
* </p>
- *
+ *
* @param paintableId
* the id of the paintable that owns the variable
* @param variableName
@@ -2789,7 +2791,7 @@ public class ApplicationConnection implements HasHandlers {
* is true, the update is sent as soon as possible. If immediate is false,
* the update will be sent along with the next immediate update.
* </p>
- *
+ *
* @param paintableId
* the id of the paintable that owns the variable
* @param variableName
@@ -2812,7 +2814,7 @@ public class ApplicationConnection implements HasHandlers {
* is true, the update is sent as soon as possible. If immediate is false,
* the update will be sent along with the next immediate update.
* </p>
- *
+ *
* @param paintableId
* the id of the paintable that owns the variable
* @param variableName
@@ -2835,7 +2837,7 @@ public class ApplicationConnection implements HasHandlers {
* is true, the update is sent as soon as possible. If immediate is false,
* the update will be sent along with the next immediate update.
* </p>
- *
+ *
* @param paintableId
* the id of the paintable that owns the variable
* @param variableName
@@ -2858,7 +2860,7 @@ public class ApplicationConnection implements HasHandlers {
* is true, the update is sent as soon as possible. If immediate is false,
* the update will be sent along with the next immediate update.
* </p>
- *
+ *
* @param paintableId
* the id of the paintable that owns the variable
* @param variableName
@@ -2881,7 +2883,7 @@ public class ApplicationConnection implements HasHandlers {
* is true, the update is sent as soon as possible. If immediate is false,
* the update will be sent along with the next immediate update.
* </p>
- *
+ *
* @param paintableId
* the id of the paintable that owns the variable
* @param variableName
@@ -2898,13 +2900,13 @@ public class ApplicationConnection implements HasHandlers {
/**
* Sends a new value for the given paintables given variable to the server.
- *
+ *
* The update is actually queued to be sent at a suitable time. If immediate
* is true, the update is sent as soon as possible. If immediate is false,
* the update will be sent along with the next immediate update.
- *
+ *
* A null array is sent as an empty array.
- *
+ *
* @param paintableId
* the id of the paintable that owns the variable
* @param variableName
@@ -2921,14 +2923,14 @@ public class ApplicationConnection implements HasHandlers {
/**
* Sends a new value for the given paintables given variable to the server.
- *
+ *
* The update is actually queued to be sent at a suitable time. If immediate
* is true, the update is sent as soon as possible. If immediate is false,
* the update will be sent along with the next immediate update. </p>
- *
+ *
* A null array is sent as an empty array.
- *
- *
+ *
+ *
* @param paintableId
* the id of the paintable that owns the variable
* @param variableName
@@ -2945,7 +2947,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Does absolutely nothing. Replaced by {@link LayoutManager}.
- *
+ *
* @param container
* @deprecated As of 7.0, serves no purpose
*/
@@ -2967,7 +2969,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Returns false
- *
+ *
* @param paintable
* @return false, always
* @deprecated As of 7.0, serves no purpose
@@ -2979,7 +2981,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Returns false
- *
+ *
* @param paintable
* @return false, always
* @deprecated As of 7.0, serves no purpose
@@ -3000,16 +3002,16 @@ public class ApplicationConnection implements HasHandlers {
/**
* Get either an existing ComponentConnector or create a new
* ComponentConnector with the given type and id.
- *
+ *
* If a ComponentConnector with the given id already exists, returns it.
* Otherwise creates and registers a new ComponentConnector of the given
* type.
- *
+ *
* @param connectorId
* Id of the paintable
* @param connectorType
* Type of the connector, as passed from the server side
- *
+ *
* @return Either an existing ComponentConnector or a new ComponentConnector
* of the given type
*/
@@ -3022,15 +3024,15 @@ public class ApplicationConnection implements HasHandlers {
/**
* Creates a new ServerConnector with the given type and id.
- *
+ *
* Creates and registers a new ServerConnector of the given type. Should
* never be called with the connector id of an existing connector.
- *
+ *
* @param connectorId
* Id of the new connector
* @param connectorType
* Type of the connector, as passed from the server side
- *
+ *
* @return A new ServerConnector of the given type
*/
private ServerConnector createAndRegisterConnector(String connectorId,
@@ -3050,7 +3052,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Gets a recource that has been pre-loaded via UIDL, such as custom
* layouts.
- *
+ *
* @param name
* identifier of the resource to get
* @return the resource
@@ -3061,7 +3063,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Singleton method to get instance of app's context menu.
- *
+ *
* @return VContextMenu object
*/
public VContextMenu getContextMenu() {
@@ -3076,7 +3078,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Gets an {@link Icon} instance corresponding to a URI.
- *
+ *
* @since 7.2
* @param uri
* @return Icon object
@@ -3098,7 +3100,7 @@ public class ApplicationConnection implements HasHandlers {
* Translates custom protocols in UIDL URI's to be recognizable by browser.
* All uri's from UIDL should be routed via this method before giving them
* to browser due URI's in UIDL may contain custom protocols like theme://.
- *
+ *
* @param uidlUri
* Vaadin URI from uidl
* @return translated URI ready for browser
@@ -3170,7 +3172,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Gets the URI for the current theme. Can be used to reference theme
* resources.
- *
+ *
* @return URI to the current theme
*/
public String getThemeUri() {
@@ -3180,7 +3182,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Listens for Notification hide event, and redirects. Used for system
* messages, such as session expired.
- *
+ *
*/
private class NotificationRedirect implements VNotification.EventListener {
String url;
@@ -3209,7 +3211,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Gets the token (aka double submit cookie) that the server uses to protect
* against Cross Site Request Forgery attacks.
- *
+ *
* @return the CSRF token string
*/
public String getCsrfToken() {
@@ -3219,7 +3221,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Use to notify that the given component's caption has changed; layouts may
* have to be recalculated.
- *
+ *
* @param component
* the Paintable whose caption has changed
* @deprecated As of 7.0.2, has not had any effect for a long time
@@ -3231,7 +3233,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Gets the main view
- *
+ *
* @return the main view
*/
public UIConnector getUIConnector() {
@@ -3240,7 +3242,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Gets the {@link ApplicationConfiguration} for the current application.
- *
+ *
* @see ApplicationConfiguration
* @return the configuration for this application
*/
@@ -3253,7 +3255,7 @@ public class ApplicationConnection implements HasHandlers {
* list of events which has server side listeners is updated automatically
* before the component is updated so the value is correct if called from
* updatedFromUIDL.
- *
+ *
* @param paintable
* The connector to register event listeners for
* @param eventIdentifier
@@ -3273,7 +3275,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Adds the get parameters to the uri and returns the new uri that contains
* the parameters.
- *
+ *
* @param uri
* The uri to which the parameters should be added.
* @param extraParams
@@ -3326,7 +3328,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Get VTooltip instance related to application connection
- *
+ *
* @return VTooltip instance
*/
public VTooltip getVTooltip() {
@@ -3338,7 +3340,7 @@ public class ApplicationConnection implements HasHandlers {
* this method is now handled by the state change event handler in
* AbstractComponentConnector. The only function this method has is to
* return true if the UIDL is a "cached" update.
- *
+ *
* @param component
* @param uidl
* @param manageCaption
@@ -3389,7 +3391,7 @@ public class ApplicationConnection implements HasHandlers {
* Schedules a heartbeat request to occur after the configured heartbeat
* interval elapses if the interval is a positive number. Otherwise, does
* nothing.
- *
+ *
* @deprecated as of 7.2, use {@link Heartbeat#schedule()} instead
*/
@Deprecated
@@ -3403,7 +3405,7 @@ public class ApplicationConnection implements HasHandlers {
* Heartbeat requests are used to inform the server that the client-side is
* still alive. If the client page is closed or the connection lost, the
* server will eventually close the inactive UI.
- *
+ *
* @deprecated as of 7.2, use {@link Heartbeat#send()} instead
*/
@Deprecated
@@ -3427,7 +3429,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* This method can be used to postpone rendering of a response for a short
* period of time (e.g. to avoid the rendering process during animation).
- *
+ *
* @param lock
*/
public void suspendReponseHandling(Object lock) {
@@ -3436,7 +3438,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Resumes the rendering process once all locks have been removed.
- *
+ *
* @param lock
*/
public void resumeResponseHandling(Object lock) {
@@ -3481,7 +3483,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Sets the delegate that is called whenever a communication error occurrs.
- *
+ *
* @param delegate
* the delegate.
*/
@@ -3524,7 +3526,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Gets the active connector for focused element in browser.
- *
+ *
* @return Connector for focused element or null.
*/
private ComponentConnector getActiveConnector() {
@@ -3538,7 +3540,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Sets the status for the push connection.
- *
+ *
* @param enabled
* <code>true</code> to enable the push connection;
* <code>false</code> to disable the push connection.
@@ -3588,7 +3590,7 @@ public class ApplicationConnection implements HasHandlers {
/**
* Returns a human readable string representation of the method used to
* communicate with the server.
- *
+ *
* @since 7.1
* @return A string representation of the current transport type
*/
diff --git a/client/src/com/vaadin/client/Util.java b/client/src/com/vaadin/client/Util.java
index 507a5c2c2d..f175bbe714 100644
--- a/client/src/com/vaadin/client/Util.java
+++ b/client/src/com/vaadin/client/Util.java
@@ -925,12 +925,27 @@ public class Util {
* Performs a hack to trigger a re-layout in the IE8. This is usually
* necessary in cases where IE8 "forgets" to update child elements when they
* resize.
- *
+ *
* @param e
* The element to perform the hack on
*/
public static final void forceIE8Redraw(Element e) {
if (BrowserInfo.get().isIE8()) {
+ forceIERedraw(e);
+ }
+ }
+
+ /**
+ * Performs a hack to trigger a re-layout in the IE browser. This is usually
+ * necessary in cases where IE "forgets" to update child elements when they
+ * resize.
+ *
+ * @since
+ * @param e
+ * The element to perform the hack on
+ */
+ public static void forceIERedraw(Element e) {
+ if (BrowserInfo.get().isIE()) {
setStyleTemporarily(e, "zoom", "1");
}
}
diff --git a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java
index 48e17cde05..5073e0ce5d 100644
--- a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java
+++ b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -37,7 +37,7 @@ import com.vaadin.shared.ui.ui.UIState.PushConfigurationState;
/**
* The default {@link PushConnection} implementation that uses Atmosphere for
* handling the communication channel.
- *
+ *
* @author Vaadin Ltd
* @since 7.1
*/
@@ -171,8 +171,12 @@ public class AtmospherePushConnection implements PushConnection {
+ ApplicationConstants.PUSH_PATH + '/');
String extraParams = UIConstants.UI_ID_PARAMETER + "="
+ connection.getConfiguration().getUIId();
- extraParams += "&" + ApplicationConstants.CSRF_TOKEN_PARAMETER + "="
- + connection.getCsrfToken();
+
+ if (!connection.getCsrfToken().equals(
+ ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE)) {
+ extraParams += "&" + ApplicationConstants.CSRF_TOKEN_PARAMETER
+ + "=" + connection.getCsrfToken();
+ }
// uri is needed to identify the right connection when closing
uri = ApplicationConnection.addGetParameters(baseUrl, extraParams);
@@ -239,9 +243,9 @@ public class AtmospherePushConnection implements PushConnection {
/**
* Called whenever a server push connection is established (or
* re-established).
- *
+ *
* @param response
- *
+ *
* @since 7.2
*/
protected void onConnect(AtmosphereResponse response) {
@@ -330,7 +334,7 @@ public class AtmospherePushConnection implements PushConnection {
/**
* Called if the push connection fails. Atmosphere will automatically retry
* the connection until successful.
- *
+ *
*/
protected void onError(AtmosphereResponse response) {
state = State.DISCONNECTED;
@@ -448,7 +452,7 @@ public class AtmospherePushConnection implements PushConnection {
contentType: 'application/json; charset=UTF-8',
reconnectInterval: 5000,
timeout: -1,
- maxReconnectOnClose: 10000000,
+ maxReconnectOnClose: 10000000,
trackMessageLength: true,
enableProtocol: true,
messageDelimiter: String.fromCharCode(@com.vaadin.shared.communication.PushConstants::MESSAGE_DELIMITER)
@@ -501,7 +505,7 @@ public class AtmospherePushConnection implements PushConnection {
private static native boolean isAtmosphereLoaded()
/*-{
- return $wnd.jQueryVaadin != undefined;
+ return $wnd.jQueryVaadin != undefined;
}-*/;
private void runWhenAtmosphereLoaded(final Command command) {
diff --git a/client/src/com/vaadin/client/ui/VContextMenu.java b/client/src/com/vaadin/client/ui/VContextMenu.java
index 038ee27dad..1b0181fb7d 100644
--- a/client/src/com/vaadin/client/ui/VContextMenu.java
+++ b/client/src/com/vaadin/client/ui/VContextMenu.java
@@ -161,6 +161,8 @@ public class VContextMenu extends VOverlay implements SubPartAware {
top = top - offsetHeight;
if (top < 0) {
top = 0;
+
+ setHeight(Window.getClientHeight() + "px");
}
}
setPopupPosition(left, top);
diff --git a/client/src/com/vaadin/client/ui/VFilterSelect.java b/client/src/com/vaadin/client/ui/VFilterSelect.java
index 004072d04a..7f67c39500 100644
--- a/client/src/com/vaadin/client/ui/VFilterSelect.java
+++ b/client/src/com/vaadin/client/ui/VFilterSelect.java
@@ -332,6 +332,14 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
.clearWidth();
setPopupPositionAndShow(popup);
+ // Fix for #14173
+ // IE9 and IE10 have a bug, when resize an a element with
+ // box-shadow.
+ // IE9 and IE10 need explicit update to remove extra
+ // box-shadows
+ if (BrowserInfo.get().isIE9() || BrowserInfo.get().isIE10()) {
+ forceReflow();
+ }
}
});
}
diff --git a/client/src/com/vaadin/client/ui/VOverlay.java b/client/src/com/vaadin/client/ui/VOverlay.java
index f9aa2ef2f8..d2c3ee2dae 100644
--- a/client/src/com/vaadin/client/ui/VOverlay.java
+++ b/client/src/com/vaadin/client/ui/VOverlay.java
@@ -656,6 +656,12 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
}
}
}
+ // Fix for #14173
+ // IE9 and IE10 have a bug, when resize an a element with box-shadow.
+ // IE9 and IE10 need explicit update to remove extra box-shadows
+ if (BrowserInfo.get().isIE9() || BrowserInfo.get().isIE10()) {
+ Util.forceIERedraw(getElement());
+ }
}
/**
diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java
index ef8be5aadc..d88f7426ef 100644
--- a/client/src/com/vaadin/client/ui/VScrollTable.java
+++ b/client/src/com/vaadin/client/ui/VScrollTable.java
@@ -588,6 +588,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
private boolean hadScrollBars = false;
+ private HandlerRegistration addCloseHandler;
+
public VScrollTable() {
setMultiSelectMode(MULTISELECT_MODE_DEFAULT);
@@ -669,13 +671,14 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
this.client = client;
// Add a handler to clear saved context menu details when the menu
// closes. See #8526.
- client.getContextMenu().addCloseHandler(new CloseHandler<PopupPanel>() {
+ addCloseHandler = client.getContextMenu().addCloseHandler(
+ new CloseHandler<PopupPanel>() {
- @Override
- public void onClose(CloseEvent<PopupPanel> event) {
- contextMenu = null;
- }
- });
+ @Override
+ public void onClose(CloseEvent<PopupPanel> event) {
+ contextMenu = null;
+ }
+ });
}
private void handleBodyContextMenu(ContextMenuEvent event) {
@@ -7929,4 +7932,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
// Nothing found.
return null;
}
+
+ /**
+ * @since
+ */
+ public void onUnregister() {
+ if (addCloseHandler != null) {
+ addCloseHandler.removeHandler();
+ }
+ }
}
diff --git a/client/src/com/vaadin/client/ui/VTextField.java b/client/src/com/vaadin/client/ui/VTextField.java
index c517f8fec0..1968c7e0a6 100644
--- a/client/src/com/vaadin/client/ui/VTextField.java
+++ b/client/src/com/vaadin/client/ui/VTextField.java
@@ -16,6 +16,8 @@
package com.vaadin.client.ui;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
@@ -254,6 +256,48 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler,
el.oncut = null;
}-*/;
+ private void onDrop() {
+ if (focusedTextField == this) {
+ return;
+ }
+ updateText(false);
+ }
+
+ private void updateText(boolean blurred) {
+ String text = getText();
+ setPrompting(inputPrompt != null && (text == null || text.isEmpty()));
+ if (prompting) {
+ setText(isReadOnly() ? "" : inputPrompt);
+ if (blurred) {
+ addStyleDependentName(CLASSNAME_PROMPT);
+ }
+ }
+
+ valueChange(blurred);
+ }
+
+ private void scheduleOnDropEvent() {
+ Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+ @Override
+ public void execute() {
+ onDrop();
+ }
+ });
+ }
+
+ private native void attachDropEventListener(Element el)
+ /*-{
+ var me = this;
+ el.ondrop = $entry(function() {
+ me.@com.vaadin.client.ui.VTextField::scheduleOnDropEvent()();
+ });
+ }-*/;
+
+ private native void detachDropEventListener(Element el)
+ /*-{
+ el.ondrop = null;
+ }-*/;
+
@Override
protected void onDetach() {
super.onDetach();
@@ -263,6 +307,7 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler,
}
if (BrowserInfo.get().isFirefox()) {
removeOnInputListener(getElement());
+ detachDropEventListener(getElement());
}
}
@@ -276,6 +321,9 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler,
// Workaround for FF setting input prompt as the value if esc is
// pressed while the field is focused and empty (#8051).
addOnInputListener(getElement());
+ // Workaround for FF updating component's internal value after
+ // having drag-and-dropped text from another element (#14056)
+ attachDropEventListener(getElement());
}
}
@@ -418,14 +466,7 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler,
}
removeStyleDependentName(CLASSNAME_FOCUS);
focusedTextField = null;
- String text = getText();
- setPrompting(inputPrompt != null && (text == null || "".equals(text)));
- if (prompting) {
- setText(isReadOnly() ? "" : inputPrompt);
- addStyleDependentName(CLASSNAME_PROMPT);
- }
-
- valueChange(true);
+ updateText(true);
}
private void setPrompting(boolean prompting) {
diff --git a/client/src/com/vaadin/client/ui/table/TableConnector.java b/client/src/com/vaadin/client/ui/table/TableConnector.java
index bea49e5f27..017d1d1024 100644
--- a/client/src/com/vaadin/client/ui/table/TableConnector.java
+++ b/client/src/com/vaadin/client/ui/table/TableConnector.java
@@ -55,6 +55,17 @@ public class TableConnector extends AbstractHasComponentsConnector implements
/*
* (non-Javadoc)
*
+ * @see com.vaadin.client.ui.AbstractComponentConnector#onUnregister()
+ */
+ @Override
+ public void onUnregister() {
+ super.onUnregister();
+ getWidget().onUnregister();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
* @see com.vaadin.client.Paintable#updateFromUIDL(com.vaadin.client.UIDL,
* com.vaadin.client.ApplicationConnection)
*/
diff --git a/push/build.xml b/push/build.xml
index dfc8d03156..dee5820efb 100644
--- a/push/build.xml
+++ b/push/build.xml
@@ -16,7 +16,7 @@
<property name="vaadinPush.debug.js" location="${result.dir}/js/VAADIN/vaadinPush.debug.js" />
<!-- Keep the version number in sync with ivy.xml, server/src/com/vaadin/server/Constants.java -->
- <property name="atmosphere.runtime.version" value="2.1.2.vaadin2" />
+ <property name="atmosphere.runtime.version" value="2.1.2.vaadin3" />
<property name="jquery.js" location="lib/jquery/jquery-1.11.0.js" />
<path id="classpath.compile.custom" />
diff --git a/push/ivy.xml b/push/ivy.xml
index 1b98969fca..d3b4944353 100644
--- a/push/ivy.xml
+++ b/push/ivy.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ivy-module [
<!-- Keep the version number in sync with build.xml -->
- <!ENTITY atmosphere.runtime.version "2.1.2.vaadin2">
+ <!ENTITY atmosphere.runtime.version "2.1.2.vaadin3">
<!ENTITY atmosphere.js.version "2.1.5.vaadin4">
]>
diff --git a/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java b/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java
index eafd3573bc..0bfec33957 100644
--- a/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java
+++ b/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java
@@ -701,7 +701,9 @@ public class ContainerHierarchicalWrapper implements Container.Hierarchical,
*/
@Override
public int size() {
- return container.size();
+ int size = container.size();
+ assert size >= 0;
+ return size;
}
/*
diff --git a/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java b/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java
index 483753da88..4bb4e4c1b2 100644
--- a/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java
+++ b/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java
@@ -494,6 +494,7 @@ public class ContainerOrderedWrapper implements Container.Ordered,
@Override
public int size() {
int newSize = container.size();
+ assert newSize >= 0;
if (lastKnownSize != -1 && newSize != lastKnownSize
&& !(container instanceof Container.ItemSetChangeNotifier)) {
// Update the internal cache when the size of the container changes
diff --git a/server/src/com/vaadin/server/AbstractJavaScriptExtension.java b/server/src/com/vaadin/server/AbstractJavaScriptExtension.java
index acf6a870c6..410eea3c01 100644
--- a/server/src/com/vaadin/server/AbstractJavaScriptExtension.java
+++ b/server/src/com/vaadin/server/AbstractJavaScriptExtension.java
@@ -103,6 +103,8 @@ import com.vaadin.ui.JavaScriptFunction;
* <li>The primitive Java boolean and the boxed Boolean are represented by
* JavaScript booleans.</li>
* <li>Java Strings are represented by JavaScript strings.</li>
+ * <li>Java Dates are represented by JavaScript numbers containing the timestamp
+ * </li>
* <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li>
* <li>Map<String, ?> in Java is represented by JavaScript object with fields
* corresponding to the map keys.</li>
diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java
index 34c9b5b767..08b5b70f50 100644
--- a/server/src/com/vaadin/server/Constants.java
+++ b/server/src/com/vaadin/server/Constants.java
@@ -67,7 +67,7 @@ public interface Constants {
// Keep the version number in sync with push/build.xml and other locations
// listed in that file
- static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.1.2.vaadin2";
+ static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.1.2.vaadin3";
static final String INVALID_ATMOSPHERE_VERSION_WARNING = "\n"
+ "=================================================================\n"
diff --git a/server/src/com/vaadin/server/JsonCodec.java b/server/src/com/vaadin/server/JsonCodec.java
index 93074abcdb..34b05f73bf 100644
--- a/server/src/com/vaadin/server/JsonCodec.java
+++ b/server/src/com/vaadin/server/JsonCodec.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -56,7 +56,7 @@ import com.vaadin.ui.ConnectorTracker;
/**
* Decoder for converting RPC parameters and other values from JSON in transfer
* between the client and the server and vice versa.
- *
+ *
* @since 7.0
*/
public class JsonCodec implements Serializable {
@@ -119,9 +119,9 @@ public class JsonCodec implements Serializable {
public static Collection<FieldProperty> find(Class<?> type)
throws IntrospectionException {
- Collection<FieldProperty> properties = new ArrayList<FieldProperty>();
-
Field[] fields = type.getFields();
+ Collection<FieldProperty> properties = new ArrayList<FieldProperty>(
+ fields.length);
for (Field field : fields) {
if (!Modifier.isStatic(field.getModifiers())) {
properties.add(new FieldProperty(field));
@@ -341,7 +341,7 @@ public class JsonCodec implements Serializable {
* using the declared type. Otherwise only internal types are allowed in
* collections.
* </p>
- *
+ *
* @param targetType
* The type that should be returned by this method
* @param valueAndType
@@ -471,13 +471,13 @@ public class JsonCodec implements Serializable {
private static Map<Object, Object> decodeObjectMap(Type keyType,
Type valueType, JSONArray jsonMap, ConnectorTracker connectorTracker)
throws JSONException {
- Map<Object, Object> map = new HashMap<Object, Object>();
JSONArray keys = jsonMap.getJSONArray(0);
JSONArray values = jsonMap.getJSONArray(1);
assert (keys.length() == values.length());
+ Map<Object, Object> map = new HashMap<Object, Object>(keys.length() * 2);
for (int i = 0; i < keys.length(); i++) {
Object key = decodeInternalOrCustomType(keyType, keys.get(i),
connectorTracker);
@@ -580,8 +580,9 @@ public class JsonCodec implements Serializable {
private static List<Object> decodeList(Type targetType,
boolean restrictToInternalTypes, JSONArray jsonArray,
ConnectorTracker connectorTracker) throws JSONException {
- List<Object> list = new ArrayList<Object>();
- for (int i = 0; i < jsonArray.length(); ++i) {
+ int arrayLength = jsonArray.length();
+ List<Object> list = new ArrayList<Object>(arrayLength);
+ for (int i = 0; i < arrayLength; ++i) {
// each entry always has two elements: type and value
Object encodedValue = jsonArray.get(i);
Object decodedChild = decodeParametrizedType(targetType,
@@ -754,7 +755,7 @@ public class JsonCodec implements Serializable {
/**
* Compares the value with the reference. If they match, returns true.
- *
+ *
* @param fieldValue
* @param referenceValue
* @return
diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java
index e8cdcd7055..8d44ff74ed 100644
--- a/server/src/com/vaadin/server/VaadinService.java
+++ b/server/src/com/vaadin/server/VaadinService.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -34,6 +34,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
@@ -69,9 +70,9 @@ import com.vaadin.util.ReflectTools;
/**
* Provide deployment specific settings that are required outside terminal
* specific code.
- *
+ *
* @author Vaadin Ltd.
- *
+ *
* @since 7.0
*/
public abstract class VaadinService implements Serializable {
@@ -144,7 +145,7 @@ public abstract class VaadinService implements Serializable {
/**
* Creates a new vaadin service based on a deployment configuration
- *
+ *
* @param deploymentConfiguration
* the deployment configuration for the service
*/
@@ -172,7 +173,7 @@ public abstract class VaadinService implements Serializable {
/**
* Initializes this service. The service should be initialized before it is
* used.
- *
+ *
* @since 7.1
* @throws ServiceException
* if a problem occurs when creating the service
@@ -191,7 +192,7 @@ public abstract class VaadinService implements Serializable {
* called first. This enables overriding this method and using add on the
* returned list to add a custom request handler which overrides any
* predefined handler.
- *
+ *
* @return The list of request handlers used by this service.
* @throws ServiceException
* if a problem occurs when creating the request handlers
@@ -214,13 +215,13 @@ public abstract class VaadinService implements Serializable {
* Return the URL from where static files, e.g. the widgetset and the theme,
* are served. In a standard configuration the VAADIN folder inside the
* returned folder is what is used for widgetsets and themes.
- *
+ *
* The returned folder is usually the same as the context path and
* independent of e.g. the servlet mapping.
- *
+ *
* @param request
* the request for which the location should be determined
- *
+ *
* @return The location of static resources (should contain the VAADIN
* directory). Never ends with a slash (/).
*/
@@ -229,7 +230,7 @@ public abstract class VaadinService implements Serializable {
/**
* Gets the widgetset that is configured for this deployment, e.g. from a
* parameter in web.xml.
- *
+ *
* @param request
* the request for which a widgetset is required
* @return the name of the widgetset
@@ -239,7 +240,7 @@ public abstract class VaadinService implements Serializable {
/**
* Gets the theme that is configured for this deployment, e.g. from a portal
* parameter or just some sensible default value.
- *
+ *
* @param request
* the request for which a theme is required
* @return the name of the theme
@@ -251,7 +252,7 @@ public abstract class VaadinService implements Serializable {
* whether it will be included into some other context. A standalone UI may
* do things that might interfere with other parts of a page, e.g. changing
* the page title and requesting focus upon loading.
- *
+ *
* @param request
* the request for which the UI is loaded
* @return a boolean indicating whether the UI should be standalone
@@ -262,9 +263,9 @@ public abstract class VaadinService implements Serializable {
* Gets the class loader to use for loading classes loaded by name, e.g.
* custom UI classes. This is by default the class loader that was used to
* load the Servlet or Portlet class to which this service belongs.
- *
+ *
* @return the class loader to use, or <code>null</code>
- *
+ *
* @see #setClassLoader(ClassLoader)
*/
public ClassLoader getClassLoader() {
@@ -277,10 +278,10 @@ public abstract class VaadinService implements Serializable {
* any existing class loader hierarchy, e.g. by ensuring that a class loader
* set for this service delegates to the previously set class loader if the
* class is not found.
- *
+ *
* @param classLoader
* the new class loader to set, not <code>null</code>.
- *
+ *
* @see #getClassLoader()
*/
public void setClassLoader(ClassLoader classLoader) {
@@ -296,11 +297,11 @@ public abstract class VaadinService implements Serializable {
* not known. The MIME type is determined by the configuration of the
* container, and may be specified in a deployment descriptor. Common MIME
* types are "text/html" and "image/gif".
- *
+ *
* @param resourceName
* a String specifying the name of a file
* @return a String specifying the file's MIME type
- *
+ *
* @see ServletContext#getMimeType(String)
* @see PortletContext#getMimeType(String)
*/
@@ -308,7 +309,7 @@ public abstract class VaadinService implements Serializable {
/**
* Gets the deployment configuration.
- *
+ *
* @return the deployment configuration
*/
public DeploymentConfiguration getDeploymentConfiguration() {
@@ -318,9 +319,9 @@ public abstract class VaadinService implements Serializable {
/**
* Sets the system messages provider to use for getting system messages to
* display to users of this service.
- *
+ *
* @see #getSystemMessagesProvider()
- *
+ *
* @param systemMessagesProvider
* the system messages provider; <code>null</code> is not
* allowed.
@@ -340,11 +341,11 @@ public abstract class VaadinService implements Serializable {
* By default, the {@link DefaultSystemMessagesProvider} which always
* provides the built-in default {@link SystemMessages} is used.
* </p>
- *
+ *
* @see #setSystemMessagesProvider(SystemMessagesProvider)
* @see SystemMessagesProvider
* @see SystemMessages
- *
+ *
* @return the system messages provider; not <code>null</code>
*/
public SystemMessagesProvider getSystemMessagesProvider() {
@@ -356,7 +357,7 @@ public abstract class VaadinService implements Serializable {
* also be implemented to use information from current instances of various
* objects, which means that this method might return different values for
* the same locale under different circumstances.
- *
+ *
* @param locale
* the desired locale for the system messages
* @param request
@@ -373,13 +374,13 @@ public abstract class VaadinService implements Serializable {
/**
* Returns the context base directory.
- *
+ *
* Typically an application is deployed in a such way that is has an
* application directory. For web applications this directory is the root
* directory of the web applications. In some cases applications might not
* have an application directory (for example web applications running
* inside a war).
- *
+ *
* @return The application base directory or null if the application has no
* base directory.
*/
@@ -393,10 +394,10 @@ public abstract class VaadinService implements Serializable {
* the listener is not necessarily notified immediately when the session is
* created but only when the first request for that session is handled by
* this service.
- *
+ *
* @see #removeSessionInitListener(SessionInitListener)
* @see SessionInitListener
- *
+ *
* @param listener
* the Vaadin service session initialization listener
*/
@@ -408,9 +409,9 @@ public abstract class VaadinService implements Serializable {
/**
* Removes a Vaadin service session initialization listener from this
* service.
- *
+ *
* @see #addSessionInitListener(SessionInitListener)
- *
+ *
* @param listener
* the Vaadin service session initialization listener to remove.
*/
@@ -425,9 +426,9 @@ public abstract class VaadinService implements Serializable {
* <p>
* The session being destroyed is locked and its UIs have been removed when
* the listeners are called.
- *
+ *
* @see #addSessionInitListener(SessionInitListener)
- *
+ *
* @param listener
* the vaadin service session destroy listener
*/
@@ -439,7 +440,7 @@ public abstract class VaadinService implements Serializable {
/**
* Handles destruction of the given session. Internally ensures proper
* locking is done.
- *
+ *
* @param vaadinSession
* The session to destroy
*/
@@ -485,9 +486,9 @@ public abstract class VaadinService implements Serializable {
/**
* Removes a Vaadin service session destroy listener from this service.
- *
+ *
* @see #addSessionDestroyListener(SessionDestroyListener)
- *
+ *
* @param listener
* the vaadin service session destroy listener
*/
@@ -502,12 +503,12 @@ public abstract class VaadinService implements Serializable {
* Handles locking of the session internally to avoid creation of duplicate
* sessions by two threads simultaneously.
* </p>
- *
+ *
* @param request
* the request to get a vaadin service session for.
- *
+ *
* @see VaadinSession
- *
+ *
* @return the vaadin service session for the request, or <code>null</code>
* if no session is found and this is a request for which a new
* session shouldn't be created.
@@ -529,7 +530,7 @@ public abstract class VaadinService implements Serializable {
* Associates the given lock with this service and the given wrapped
* session. This method should not be called more than once when the lock is
* initialized for the session.
- *
+ *
* @see #getSessionLock(WrappedSession)
* @param wrappedSession
* The wrapped session the lock is associated with
@@ -550,7 +551,7 @@ public abstract class VaadinService implements Serializable {
/**
* Returns the name used to store the lock in the HTTP session.
- *
+ *
* @return The attribute name for the lock
*/
private String getLockAttributeName() {
@@ -564,7 +565,7 @@ public abstract class VaadinService implements Serializable {
* This method uses the wrapped session instead of VaadinSession to be able
* to lock even before the VaadinSession has been initialized.
* </p>
- *
+ *
* @param wrappedSession
* The wrapped session
* @return A lock instance used for locking access to the wrapped session
@@ -588,10 +589,10 @@ public abstract class VaadinService implements Serializable {
/**
* Locks the given session for this service instance. Typically you want to
* call {@link VaadinSession#lock()} instead of this method.
- *
+ *
* @param wrappedSession
* The session to lock
- *
+ *
* @throws IllegalStateException
* if the session is invalidated before it can be locked
*/
@@ -631,7 +632,7 @@ public abstract class VaadinService implements Serializable {
* Releases the lock for the given session for this service instance.
* Typically you want to call {@link VaadinSession#unlock()} instead of this
* method.
- *
+ *
* @param wrappedSession
* The session to unlock
*/
@@ -666,7 +667,7 @@ public abstract class VaadinService implements Serializable {
* Finds or creates a Vaadin session. Assumes necessary synchronization has
* been done by the caller to ensure this is not called simultaneously by
* several threads.
- *
+ *
* @param request
* @param requestCanCreateSession
* @return
@@ -733,8 +734,8 @@ public abstract class VaadinService implements Serializable {
/**
* Creates and registers a new VaadinSession for this service. Assumes
* proper locking has been taken care of by the caller.
- *
- *
+ *
+ *
* @param request
* The request which triggered session creation.
* @return A new VaadinSession instance
@@ -771,11 +772,11 @@ public abstract class VaadinService implements Serializable {
* service.
* <p>
* This is only used to support legacy cases.
- *
+ *
* @param request
* @return
* @throws MalformedURLException
- *
+ *
* @deprecated As of 7.0. Only used to support {@link LegacyApplication}.
*/
@Deprecated
@@ -786,12 +787,12 @@ public abstract class VaadinService implements Serializable {
/**
* Creates a new Vaadin session for this service and request
- *
+ *
* @param request
* The request for which to create a VaadinSession
* @return A new VaadinSession
* @throws ServiceException
- *
+ *
*/
protected VaadinSession createVaadinSession(VaadinRequest request)
throws ServiceException {
@@ -839,7 +840,7 @@ public abstract class VaadinService implements Serializable {
/**
* Retrieves the wrapped session for the request.
- *
+ *
* @param request
* The request for which to retrieve a session
* @param requestCanCreateSession
@@ -862,7 +863,7 @@ public abstract class VaadinService implements Serializable {
/**
* Checks whether it's valid to create a new service session as a result of
* the given request.
- *
+ *
* @param request
* the request
* @return <code>true</code> if it's valid to create a new service session
@@ -877,10 +878,10 @@ public abstract class VaadinService implements Serializable {
* {@link InheritableThreadLocal}). In other cases, (e.g. from background
* threads started in some other way), the current service is not
* automatically defined.
- *
+ *
* @return the current Vaadin service instance if available, otherwise
* <code>null</code>
- *
+ *
* @see #setCurrentInstances(VaadinRequest, VaadinResponse)
*/
public static VaadinService getCurrent() {
@@ -898,14 +899,14 @@ public abstract class VaadinService implements Serializable {
* instances outside the normal request handling, e.g. when initiating
* custom background threads.
* </p>
- *
+ *
* @param request
* the Vaadin request to set as the current request, or
* <code>null</code> if no request should be set.
* @param response
* the Vaadin response to set as the current response, or
* <code>null</code> if no response should be set.
- *
+ *
* @see #getCurrent()
* @see #getCurrentRequest()
* @see #getCurrentResponse()
@@ -919,7 +920,7 @@ public abstract class VaadinService implements Serializable {
/**
* Sets the given Vaadin service as the current service.
- *
+ *
* @param service
*/
public static void setCurrent(VaadinService service) {
@@ -931,10 +932,10 @@ public abstract class VaadinService implements Serializable {
* automatically defined when the request is started. The current request
* can not be used in e.g. background threads because of the way server
* implementations reuse request instances.
- *
+ *
* @return the current Vaadin request instance if available, otherwise
* <code>null</code>
- *
+ *
* @see #setCurrentInstances(VaadinRequest, VaadinResponse)
*/
public static VaadinRequest getCurrentRequest() {
@@ -946,10 +947,10 @@ public abstract class VaadinService implements Serializable {
* automatically defined when the request is started. The current response
* can not be used in e.g. background threads because of the way server
* implementations reuse response instances.
- *
+ *
* @return the current Vaadin response instance if available, otherwise
* <code>null</code>
- *
+ *
* @see #setCurrentInstances(VaadinRequest, VaadinResponse)
*/
public static VaadinResponse getCurrentResponse() {
@@ -961,7 +962,7 @@ public abstract class VaadinService implements Serializable {
* different services of the same type but the same for corresponding
* instances running in different JVMs in a cluster. This is typically based
* on e.g. the configured servlet's or portlet's name.
- *
+ *
* @return the unique name of this service instance.
*/
public abstract String getServiceName();
@@ -972,11 +973,11 @@ public abstract class VaadinService implements Serializable {
* related to any particular UI or have the UI information encoded in a
* non-standard way. The returned UI is also set as the current UI (
* {@link UI#setCurrent(UI)}).
- *
+ *
* @param request
* the request for which a UI is desired
* @return the UI belonging to the request or null if no UI is found
- *
+ *
*/
public UI findUI(VaadinRequest request) {
// getForSession asserts that the lock is held
@@ -1002,12 +1003,12 @@ public abstract class VaadinService implements Serializable {
* typically checks the @{@link PreserveOnRefresh} annotation but UI
* providers and ultimately VaadinService implementations may choose to
* override the defaults.
- *
+ *
* @param provider
* the UI provider responsible for the UI
* @param event
* the UI create event with details about the UI
- *
+ *
* @return <code>true</code> if the UI should be preserved on refresh;
* <code>false</code> if a new UI instance should be initialized on
* refreshed.
@@ -1024,7 +1025,7 @@ public abstract class VaadinService implements Serializable {
* Please note that this method makes certain assumptions about how data is
* stored in the underlying session and may thus not be compatible with some
* environments.
- *
+ *
* @param request
* The Vaadin request for which the session should be
* reinitialized
@@ -1034,8 +1035,10 @@ public abstract class VaadinService implements Serializable {
// Stores all attributes (security key, reference to this context
// instance) so they can be added to the new session
- HashMap<String, Object> attrs = new HashMap<String, Object>();
- for (String name : oldSession.getAttributeNames()) {
+ Set<String> attributeNames = oldSession.getAttributeNames();
+ HashMap<String, Object> attrs = new HashMap<String, Object>(
+ attributeNames.size() * 2);
+ for (String name : attributeNames) {
Object value = oldSession.getAttribute(name);
if (value instanceof VaadinSession) {
// set flag to avoid cleanup
@@ -1076,9 +1079,9 @@ public abstract class VaadinService implements Serializable {
/**
* TODO PUSH Document
- *
+ *
* TODO Pass UI or VaadinSession?
- *
+ *
* @param uI
* @param themeName
* @param resource
@@ -1090,14 +1093,14 @@ public abstract class VaadinService implements Serializable {
/**
* Creates and returns a unique ID for the DIV where the UI is to be
* rendered.
- *
+ *
* @param session
* The service session to which the bootstrapped UI will belong.
* @param request
* The request for which a div id is needed
* @param uiClass
* The class of the UI that will be bootstrapped
- *
+ *
* @return the id to use in the DOM
*/
public abstract String getMainDivId(VaadinSession session,
@@ -1115,9 +1118,9 @@ public abstract class VaadinService implements Serializable {
* To avoid causing out of sync errors, you should typically redirect to
* some other page using {@link Page#setLocation(String)} to make the
* browser unload the invalidated UI.
- *
+ *
* @see SystemMessages#getSessionExpiredCaption()
- *
+ *
* @param session
* the session to close
*/
@@ -1129,7 +1132,7 @@ public abstract class VaadinService implements Serializable {
* Called at the end of a request, after sending the response. Closes
* inactive UIs in the given session, removes closed UIs from the session,
* and closes the session if it is itself inactive.
- *
+ *
* @param session
*/
void cleanupSession(VaadinSession session) {
@@ -1164,29 +1167,29 @@ public abstract class VaadinService implements Serializable {
/**
* Removes those UIs from the given session for which {@link UI#isClosing()
* isClosing} yields true.
- *
+ *
* @param session
*/
private void removeClosedUIs(final VaadinSession session) {
ArrayList<UI> uis = new ArrayList<UI>(session.getUIs());
for (final UI ui : uis) {
- ui.accessSynchronously(new Runnable() {
- @Override
- public void run() {
- if (ui.isClosing()) {
+ if (ui.isClosing()) {
+ ui.accessSynchronously(new Runnable() {
+ @Override
+ public void run() {
getLogger().log(Level.FINER, "Removing closed UI {0}",
ui.getUIId());
session.removeUI(ui);
}
- }
- });
+ });
+ }
}
}
/**
* Closes those UIs in the given session for which {@link #isUIActive}
* yields false.
- *
+ *
* @since 7.0.0
*/
private void closeInactiveUIs(VaadinSession session) {
@@ -1212,11 +1215,11 @@ public abstract class VaadinService implements Serializable {
* session. This is a lower bound; it might take longer to close an inactive
* UI. Returns a negative number if heartbeat is disabled and timeout never
* occurs.
- *
+ *
* @see DeploymentConfiguration#getHeartbeatInterval()
- *
+ *
* @since 7.0.0
- *
+ *
* @return The heartbeat timeout in seconds or a negative number if timeout
* never occurs.
*/
@@ -1235,12 +1238,12 @@ public abstract class VaadinService implements Serializable {
* requests suffice to keep the session alive, but it will still eventually
* expire in the regular manner if there are no requests at all (see
* {@link WrappedSession#getMaxInactiveInterval()}).
- *
+ *
* @see DeploymentConfiguration#isCloseIdleSessions()
* @see #getHeartbeatTimeout()
- *
+ *
* @since 7.0.0
- *
+ *
* @return The UIDL request timeout in seconds, or a negative number if
* timeout never occurs.
*/
@@ -1257,12 +1260,12 @@ public abstract class VaadinService implements Serializable {
* A UI is active if and only if its {@link UI#isClosing() isClosing}
* returns false and {@link #getHeartbeatTimeout() getHeartbeatTimeout} is
* negative or has not yet expired.
- *
+ *
* @since 7.0.0
- *
+ *
* @param ui
* The UI whose status to check
- *
+ *
* @return true if the UI is active, false if it could be removed.
*/
private boolean isUIActive(UI ui) {
@@ -1282,10 +1285,10 @@ public abstract class VaadinService implements Serializable {
* A session is active if and only if its {@link #isClosing} returns false
* and {@link #getUidlRequestTimeout(VaadinSession) getUidlRequestTimeout}
* is negative or has not yet expired.
- *
+ *
* @param session
* The session whose status to check
- *
+ *
* @return true if the session is active, false if it could be closed.
*/
private boolean isSessionActive(VaadinSession session) {
@@ -1305,7 +1308,7 @@ public abstract class VaadinService implements Serializable {
/**
* Called before the framework starts handling a request
- *
+ *
* @param request
* The request
* @param response
@@ -1323,7 +1326,7 @@ public abstract class VaadinService implements Serializable {
/**
* Called after the framework has handled a request and the response has
* been written.
- *
+ *
* @param request
* The request object
* @param response
@@ -1335,23 +1338,16 @@ public abstract class VaadinService implements Serializable {
public void requestEnd(VaadinRequest request, VaadinResponse response,
VaadinSession session) {
if (session != null) {
- final VaadinSession finalSession = session;
-
- session.accessSynchronously(new Runnable() {
- @Override
- public void run() {
- cleanupSession(finalSession);
- }
- });
-
- final long duration = (System.nanoTime() - (Long) request
- .getAttribute(REQUEST_START_TIME_ATTRIBUTE)) / 1000000;
- session.accessSynchronously(new Runnable() {
- @Override
- public void run() {
- finalSession.setLastRequestDuration(duration);
- }
- });
+ assert VaadinSession.getCurrent() == session;
+ session.lock();
+ try {
+ cleanupSession(session);
+ final long duration = (System.nanoTime() - (Long) request
+ .getAttribute(REQUEST_START_TIME_ATTRIBUTE)) / 1000000;
+ session.setLastRequestDuration(duration);
+ } finally {
+ session.unlock();
+ }
}
CurrentInstance.clearAll();
}
@@ -1360,11 +1356,11 @@ public abstract class VaadinService implements Serializable {
* Returns the request handlers that are registered with this service. The
* iteration order of the returned collection is the same as the order in
* which the request handlers will be invoked when a request is handled.
- *
+ *
* @return a collection of request handlers in the order they are invoked
- *
+ *
* @see #createRequestHandlers()
- *
+ *
* @since 7.1
*/
public Iterable<RequestHandler> getRequestHandlers() {
@@ -1381,7 +1377,7 @@ public abstract class VaadinService implements Serializable {
* request handler handles session expiration a default expiration message
* will be written.
* </p>
- *
+ *
* @param request
* The incoming request
* @param response
@@ -1473,7 +1469,7 @@ public abstract class VaadinService implements Serializable {
/**
* Writes the given string as a response using the given content type.
- *
+ *
* @param response
* The response reference
* @param contentType
@@ -1498,7 +1494,7 @@ public abstract class VaadinService implements Serializable {
/**
* Called when the session has expired and the request handling is therefore
* aborted.
- *
+ *
* @param request
* The request
* @param response
@@ -1553,7 +1549,7 @@ public abstract class VaadinService implements Serializable {
/**
* Creates a JSON message which, when sent to client as-is, will cause a
* critical error to be shown with the given details.
- *
+ *
* @param caption
* The caption of the error or null to omit
* @param message
@@ -1616,10 +1612,10 @@ public abstract class VaadinService implements Serializable {
/**
* Enables push if push support is available and push has not yet been
* enabled.
- *
+ *
* If push support is not available, a warning explaining the situation will
* be logged at least the first time this method is invoked.
- *
+ *
* @return <code>true</code> if push can be used; <code>false</code> if push
* is not available.
*/
@@ -1638,7 +1634,7 @@ public abstract class VaadinService implements Serializable {
* internally used by {@link VaadinSession#accessSynchronously(Runnable)}
* and {@link UI#accessSynchronously(Runnable)} to help avoid causing
* deadlocks.
- *
+ *
* @since 7.1
* @param session
* the session that is being locked
@@ -1657,7 +1653,7 @@ public abstract class VaadinService implements Serializable {
* provided one for which the current thread holds a lock. This method might
* not detect all cases where some other session is locked, but it should
* cover the most typical situations.
- *
+ *
* @since 7.2
* @param session
* the session that is expected to be locked
@@ -1681,11 +1677,11 @@ public abstract class VaadinService implements Serializable {
* to allow a certain type of testing. For these cases, the check can be
* disabled by setting the init parameter
* <code>disable-xsrf-protection</code> to <code>true</code>.
- *
+ *
* @see DeploymentConfiguration#isXsrfProtectionEnabled()
- *
+ *
* @since 7.1
- *
+ *
* @param session
* the vaadin session for which the check should be done
* @param requestToken
@@ -1712,15 +1708,15 @@ public abstract class VaadinService implements Serializable {
* Implementation for {@link VaadinSession#access(Runnable)}. This method is
* implemented here instead of in {@link VaadinSession} to enable overriding
* the implementation without using a custom subclass of VaadinSession.
- *
+ *
* @since 7.1
* @see VaadinSession#access(Runnable)
- *
+ *
* @param session
* the vaadin session to access
* @param runnable
* the runnable to run with the session locked
- *
+ *
* @return a future that can be used to check for task completion and to
* cancel the task
*/
@@ -1739,7 +1735,7 @@ public abstract class VaadinService implements Serializable {
* thread, the queue will be purged when the session is unlocked. If the
* lock is not held by any thread, it is acquired and the queue is purged
* right away.
- *
+ *
* @since 7.1.2
* @param session
* the session for which the access queue should be purged
@@ -1775,7 +1771,7 @@ public abstract class VaadinService implements Serializable {
* <p>
* This method is automatically run by the framework at appropriate
* situations and is not intended to be used by application developers.
- *
+ *
* @param session
* the vaadin session to purge the queue for
* @since 7.1
@@ -1817,11 +1813,11 @@ public abstract class VaadinService implements Serializable {
/**
* Adds a service destroy listener that gets notified when this service is
* destroyed.
- *
+ *
* @since 7.2
* @param listener
* the service destroy listener to add
- *
+ *
* @see #destroy()
* @see #removeServiceDestroyListener(ServiceDestroyListener)
* @see ServiceDestroyListener
@@ -1834,7 +1830,7 @@ public abstract class VaadinService implements Serializable {
/**
* Removes a service destroy listener that was previously added with
* {@link #addServiceDestroyListener(ServiceDestroyListener)}.
- *
+ *
* @since 7.2
* @param listener
* the service destroy listener to remove
@@ -1848,11 +1844,11 @@ public abstract class VaadinService implements Serializable {
* Called when the servlet, portlet or similar for this service is being
* destroyed. After this method has been called, no more requests will be
* handled by this service.
- *
+ *
* @see #addServiceDestroyListener(ServiceDestroyListener)
* @see Servlet#destroy()
* @see Portlet#destroy()
- *
+ *
* @since 7.2
*/
public void destroy() {
diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java
index 12e7c28cd8..09b8a22a46 100644
--- a/server/src/com/vaadin/server/VaadinServlet.java
+++ b/server/src/com/vaadin/server/VaadinServlet.java
@@ -16,12 +16,14 @@
package com.vaadin.server;
import java.io.BufferedWriter;
+import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
+import java.io.Serializable;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
@@ -29,7 +31,10 @@ import java.net.URLConnection;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -51,6 +56,59 @@ import com.vaadin.util.CurrentInstance;
@SuppressWarnings("serial")
public class VaadinServlet extends HttpServlet implements Constants {
+ private static class ScssCacheEntry implements Serializable {
+
+ private final String css;
+ private final List<String> sourceUris;
+ private final long timestamp;
+
+ public ScssCacheEntry(String css, List<String> sourceUris) {
+ this.css = css;
+ this.sourceUris = sourceUris;
+
+ timestamp = getLastModified();
+ }
+
+ public String getCss() {
+ return css;
+ }
+
+ private long getLastModified() {
+ long newest = 0;
+ for (String uri : sourceUris) {
+ File file = new File(uri);
+ if (!file.exists()) {
+ return -1;
+ } else {
+ newest = Math.max(newest, file.lastModified());
+ }
+ }
+
+ return newest;
+ }
+
+ public boolean isStillValid() {
+ if (timestamp == -1) {
+ /*
+ * Don't ever bother checking anything if files used during the
+ * compilation were gone before the cache entry was created.
+ */
+ return false;
+ } else if (timestamp != getLastModified()) {
+ /*
+ * Would in theory still be valid if the last modification is
+ * before the recorded timestamp, but that would still mean that
+ * something has changed since we last checked, so let's
+ * invalidate in that case as well to be on the safe side.
+ */
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ }
+
private VaadinServletService servletService;
/**
@@ -535,10 +593,18 @@ public class VaadinServlet extends HttpServlet implements Constants {
* Mutex for preventing to scss compilations to take place simultaneously.
* This is a workaround needed as the scss compiler currently is not thread
* safe (#10292).
+ * <p>
+ * In addition, this is also used to protect the cached compilation results.
*/
private static final Object SCSS_MUTEX = new Object();
/**
+ * Global cache of scss compilation results. This map is protected from
+ * concurrent access by {@link #SCSS_MUTEX}.
+ */
+ private static final Map<String, ScssCacheEntry> scssCache = new HashMap<String, ScssCacheEntry>();
+
+ /**
* Returns the default theme. Must never return null.
*
* @return
@@ -824,46 +890,62 @@ public class VaadinServlet extends HttpServlet implements Constants {
}
synchronized (SCSS_MUTEX) {
- String realFilename = sc.getRealPath(scssFilename);
- ScssStylesheet scss = ScssStylesheet.get(realFilename);
- if (scss == null) {
- // Not a file in the file system (WebContent directory). Use the
- // identifier directly (VAADIN/themes/.../styles.css) so
- // ScssStylesheet will try using the class loader.
- if (scssFilename.startsWith("/")) {
- scssFilename = scssFilename.substring(1);
- }
+ ScssCacheEntry cacheEntry = scssCache.get(scssFilename);
- scss = ScssStylesheet.get(scssFilename);
+ if (cacheEntry == null || !cacheEntry.isStillValid()) {
+ cacheEntry = compileScssOnTheFly(filename, scssFilename, sc);
+ scssCache.put(scssFilename, cacheEntry);
}
- if (scss == null) {
- getLogger()
- .log(Level.WARNING,
- "Scss file {0} exists but ScssStylesheet was not able to find it",
- scssFilename);
- return false;
- }
- try {
- getLogger().log(Level.FINE, "Compiling {0} for request to {1}",
- new Object[] { realFilename, filename });
- scss.compile();
- } catch (Exception e) {
- getLogger().log(Level.WARNING, "Scss compilation failed", e);
+ if (cacheEntry == null) {
+ // compilation did not produce any result, but logged a message
return false;
}
// This is for development mode only so instruct the browser to
- // never
- // cache it
+ // never cache it
response.setHeader("Cache-Control", "no-cache");
final String mimetype = getService().getMimeType(filename);
- writeResponse(response, mimetype, scss.printState());
+ writeResponse(response, mimetype, cacheEntry.getCss());
return true;
}
}
+ private ScssCacheEntry compileScssOnTheFly(String filename,
+ String scssFilename, ServletContext sc) throws IOException {
+ String realFilename = sc.getRealPath(scssFilename);
+ ScssStylesheet scss = ScssStylesheet.get(realFilename);
+ if (scss == null) {
+ // Not a file in the file system (WebContent directory). Use the
+ // identifier directly (VAADIN/themes/.../styles.css) so
+ // ScssStylesheet will try using the class loader.
+ if (scssFilename.startsWith("/")) {
+ scssFilename = scssFilename.substring(1);
+ }
+
+ scss = ScssStylesheet.get(scssFilename);
+ }
+
+ if (scss == null) {
+ getLogger()
+ .log(Level.WARNING,
+ "Scss file {0} exists but ScssStylesheet was not able to find it",
+ scssFilename);
+ return null;
+ }
+ try {
+ getLogger().log(Level.FINE, "Compiling {0} for request to {1}",
+ new Object[] { realFilename, filename });
+ scss.compile();
+ } catch (Exception e) {
+ getLogger().log(Level.WARNING, "Scss compilation failed", e);
+ return null;
+ }
+
+ return new ScssCacheEntry(scss.printState(), scss.getSourceUris());
+ }
+
/**
* Check whether a URL obtained from a classloader refers to a valid static
* resource in the directory VAADIN.
diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java
index bbabd881f8..2ab8c52dad 100644
--- a/server/src/com/vaadin/server/VaadinSession.java
+++ b/server/src/com/vaadin/server/VaadinSession.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -65,7 +65,7 @@ import com.vaadin.util.ReflectTools;
* Everything inside a {@link VaadinSession} should be serializable to ensure
* compatibility with schemes using serialization for persisting the session
* data.
- *
+ *
* @author Vaadin Ltd
* @since 7.0.0
*/
@@ -77,7 +77,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* {@link VaadinSession#access(Runnable)}. This class is used internally by
* the framework and is not intended to be directly used by application
* developers.
- *
+ *
* @since 7.1
* @author Vaadin Ltd
*/
@@ -93,10 +93,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Creates an instance for the given runnable
- *
+ *
* @param session
* the session to which the task belongs
- *
+ *
* @param runnable
* the runnable to run when this task is purged from the
* queue
@@ -114,7 +114,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* deadlocks unless implemented very carefully. get(long, TimeUnit)
* does not have the same detection since a sensible timeout should
* avoid completely locking up the application.
- *
+ *
* Even though no deadlock could occur after the runnable has been
* run, the check is always done as the deterministic behavior makes
* it easier to detect potential problems.
@@ -126,9 +126,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Gets the current instance values that should be used when running
* this task.
- *
+ *
* @see CurrentInstance#restoreInstances(Map)
- *
+ *
* @return a map of current instances.
*/
public Map<Class<?>, CurrentInstance> getCurrentInstances() {
@@ -137,7 +137,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Handles exceptions thrown during the execution of this task.
- *
+ *
* @since 7.1.8
* @param exception
* the thrown exception.
@@ -168,7 +168,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* The lifecycle state of a VaadinSession.
- *
+ *
* @since 7.2
*/
public enum State {
@@ -273,7 +273,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Creates a new VaadinSession tied to a VaadinService.
- *
+ *
* @param service
* the Vaadin service for the new session
*/
@@ -327,9 +327,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Get the web browser associated with this session.
- *
+ *
* @return the web browser object
- *
+ *
* @deprecated As of 7.0, use {@link Page#getWebBrowser()} instead.
*/
@Deprecated
@@ -350,7 +350,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Sets the time spent servicing the last request in the session and updates
* the total time spent servicing requests in this session.
- *
+ *
* @param time
* The time spent in the last request, in milliseconds.
*/
@@ -371,11 +371,11 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Sets the time when the last UIDL request was serviced in this session.
- *
+ *
* @param timestamp
* The time when the last request was handled, in milliseconds
* since the epoch.
- *
+ *
*/
public void setLastRequestTimestamp(long timestamp) {
assert hasLock();
@@ -384,7 +384,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Returns the time when the last request was serviced in this session.
- *
+ *
* @return The time when the last request was handled, in milliseconds since
* the epoch.
*/
@@ -396,7 +396,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Gets the underlying session to which this service session is currently
* associated.
- *
+ *
* @return the wrapped session for this context
*/
public WrappedSession getSession() {
@@ -410,7 +410,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* @return
- *
+ *
* @deprecated As of 7.0. Will likely change or be removed in a future
* version
*/
@@ -430,7 +430,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Loads the VaadinSession for the given service and WrappedSession from the
* HTTP session.
- *
+ *
* @param service
* The service the VaadinSession is associated with
* @param underlyingSession
@@ -460,7 +460,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Retrieves all {@link VaadinSession}s which are stored in the given HTTP
* session
- *
+ *
* @since 7.2
* @param httpSession
* the HTTP session
@@ -485,7 +485,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Removes this VaadinSession from the HTTP session.
- *
+ *
* @param service
* The service this session is associated with
* @deprecated As of 7.0. Should be moved to a separate session storage
@@ -500,7 +500,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Retrieves the name of the attribute used for storing a VaadinSession for
* the given service.
- *
+ *
* @param service
* The service associated with the sessio
* @return The attribute name used for storing the session
@@ -511,7 +511,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Stores this VaadinSession in the HTTP session.
- *
+ *
* @param service
* The service this session is associated with
* @param session
@@ -564,7 +564,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Gets the configuration for this session
- *
+ *
* @return the deployment configuration
*/
public DeploymentConfiguration getConfiguration() {
@@ -574,10 +574,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Gets the default locale for this session.
- *
+ *
* By default this is the preferred locale of the user using the session. In
* most cases it is read from the browser defaults.
- *
+ *
* @return the locale of this session.
*/
public Locale getLocale() {
@@ -590,13 +590,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Sets the default locale for this session.
- *
+ *
* By default this is the preferred locale of the user using the
* application. In most cases it is read from the browser defaults.
- *
+ *
* @param locale
* the Locale object.
- *
+ *
*/
public void setLocale(Locale locale) {
assert hasLock();
@@ -605,7 +605,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Gets the session's error handler.
- *
+ *
* @return the current error handler
*/
public ErrorHandler getErrorHandler() {
@@ -615,7 +615,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Sets the session error handler.
- *
+ *
* @param errorHandler
*/
public void setErrorHandler(ErrorHandler errorHandler) {
@@ -626,9 +626,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Gets the {@link ConverterFactory} used to locate a suitable
* {@link Converter} for fields in the session.
- *
+ *
* See {@link #setConverterFactory(ConverterFactory)} for more details
- *
+ *
* @return The converter factory used in the session
*/
public ConverterFactory getConverterFactory() {
@@ -653,7 +653,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* </p>
* <p>
* The converter factory must never be set to null.
- *
+ *
* @param converterFactory
* The converter factory used in the session
*/
@@ -670,12 +670,12 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* Handlers are called in reverse order of addition, so the most recently
* added handler will be called first.
* </p>
- *
+ *
* @param handler
* the request handler to add
- *
+ *
* @see #removeRequestHandler(RequestHandler)
- *
+ *
* @since 7.0
*/
public void addRequestHandler(RequestHandler handler) {
@@ -685,10 +685,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Removes a request handler from the session.
- *
+ *
* @param handler
* the request handler to remove
- *
+ *
* @since 7.0
*/
public void removeRequestHandler(RequestHandler handler) {
@@ -700,13 +700,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* Gets the request handlers that are registered to the session. The
* iteration order of the returned collection is the same as the order in
* which the request handlers will be invoked when a request is handled.
- *
+ *
* @return a collection of request handlers, with the iteration order
* according to the order they would be invoked
- *
+ *
* @see #addRequestHandler(RequestHandler)
* @see #removeRequestHandler(RequestHandler)
- *
+ *
* @since 7.0
*/
public Collection<RequestHandler> getRequestHandlers() {
@@ -721,12 +721,12 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* {@link InheritableThreadLocal}). In other cases, (e.g. from background
* threads started in some other way), the current session is not
* automatically defined.
- *
+ *
* @return the current session instance if available, otherwise
* <code>null</code>
- *
+ *
* @see #setCurrent(VaadinSession)
- *
+ *
* @since 7.0
*/
public static VaadinSession getCurrent() {
@@ -742,12 +742,12 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* session outside the normal request handling and treads started from
* request handling threads, e.g. when initiating custom background threads.
* </p>
- *
+ *
* @param session
- *
+ *
* @see #getCurrent()
* @see ThreadLocal
- *
+ *
* @since 7.0
*/
public static void setCurrent(VaadinSession session) {
@@ -758,9 +758,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* Gets all the UIs of this session. This includes UIs that have been
* requested but not yet initialized. UIs that receive no heartbeat requests
* from the client are eventually removed from the session.
- *
+ *
* @return a collection of UIs belonging to this application
- *
+ *
* @since 7.0
*/
public Collection<UI> getUIs() {
@@ -775,11 +775,11 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Generate an id for the given Connector. Connectors must not call this
* method more than once, the first time they need an id.
- *
+ *
* @param connector
* A connector that has not yet been assigned an id.
* @return A new id for the connector
- *
+ *
* @deprecated As of 7.0. Will likely change or be removed in a future
* version
*/
@@ -794,7 +794,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* <p>
* This is meant for framework internal use.
* </p>
- *
+ *
* @param uiId
* The UI id
* @return The UI with the given id or null if not found
@@ -806,7 +806,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Checks if the current thread has exclusive access to this VaadinSession
- *
+ *
* @return true if the thread has exclusive access, false otherwise
*/
public boolean hasLock() {
@@ -817,7 +817,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Checks if the current thread has exclusive access to the given
* WrappedSession.
- *
+ *
* @return true if this thread has exclusive access, false otherwise
*/
private static boolean hasLock(VaadinService service, WrappedSession session) {
@@ -830,10 +830,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* be generated. This can be used to modify the contents of the HTML that
* loads the Vaadin application in the browser and the HTTP headers that are
* included in the response serving the HTML.
- *
+ *
* @see BootstrapListener#modifyBootstrapFragment(BootstrapFragmentResponse)
* @see BootstrapListener#modifyBootstrapPage(BootstrapPageResponse)
- *
+ *
* @param listener
* the bootstrap listener to add
*/
@@ -847,9 +847,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Remove a bootstrap listener that was previously added.
- *
+ *
* @see #addBootstrapListener(BootstrapListener)
- *
+ *
* @param listener
* the bootstrap listener to remove
*/
@@ -865,11 +865,11 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* Fires a bootstrap event to all registered listeners. There are currently
* two supported events, both inheriting from {@link BootstrapResponse}:
* {@link BootstrapFragmentResponse} and {@link BootstrapPageResponse}.
- *
+ *
* @param response
* the bootstrap response event for which listeners should be
* fired
- *
+ *
* @deprecated As of 7.0. Will likely change or be removed in a future
* version
*/
@@ -882,12 +882,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Called by the framework to remove an UI instance from the session because
* it has been closed.
- *
+ *
* @param ui
* the UI to remove
*/
public void removeUI(UI ui) {
assert hasLock();
+ assert UI.getCurrent() == ui;
Integer id = Integer.valueOf(ui.getUIId());
ui.setSession(null);
uIs.remove(id);
@@ -902,7 +903,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* connector resources that are not served by any single connector because
* e.g. because they are served with strong caching or because of legacy
* reasons.
- *
+ *
* @param createOnDemand
* <code>true</code> if a resource handler should be initialized
* if there is no handler associated with this application.
@@ -911,7 +912,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* @return this session's global resource handler, or <code>null</code> if
* there is no handler and the createOnDemand parameter is
* <code>false</code>.
- *
+ *
* @since 7.0.0
*/
public GlobalResourceHandler getGlobalResourceHandler(boolean createOnDemand) {
@@ -933,10 +934,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* instance is not guaranteed to support any other features of the
* <code>Lock</code> interface than {@link Lock#lock()} and
* {@link Lock#unlock()}.
- *
+ *
* @return the <code>Lock</code> that is used for synchronization, never
* <code>null</code>
- *
+ *
* @see #lock()
* @see Lock
*/
@@ -951,7 +952,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* is done correctly is to wrap your code using {@link UI#access(Runnable)}
* (or {@link VaadinSession#access(Runnable)} if you are only touching the
* session and not any UI), e.g.:
- *
+ *
* <pre>
* myUI.access(new Runnable() {
* &#064;Override
@@ -962,10 +963,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* }
* });
* </pre>
- *
+ *
* If you for whatever reason want to do locking manually, you should do it
* like:
- *
+ *
* <pre>
* session.lock();
* try {
@@ -974,12 +975,12 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* session.unlock();
* }
* </pre>
- *
+ *
* This method will block until the lock can be retrieved.
* <p>
* {@link #getLockInstance()} can be used if more control over the locking
* is required.
- *
+ *
* @see #unlock()
* @see #getLockInstance()
* @see #hasLock()
@@ -995,7 +996,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* For UIs in this session that have its push mode set to
* {@link PushMode#AUTOMATIC automatic}, pending changes will be pushed to
* their respective clients.
- *
+ *
* @see #lock()
* @see UI#push()
*/
@@ -1045,9 +1046,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* data with the current user so that it can be retrieved at a later point
* from some other part of the application. Setting the value to
* <code>null</code> clears the stored value.
- *
+ *
* @see #getAttribute(String)
- *
+ *
* @param name
* the name to associate the value with, can not be
* <code>null</code>
@@ -1077,10 +1078,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* value. The outcome of calling this method is thus the same as if calling<br />
* <br />
* <code>setAttribute(type.getName(), value);</code>
- *
+ *
* @see #getAttribute(Class)
* @see #setAttribute(String, Object)
- *
+ *
* @param type
* the type that the stored value represents, can not be null
* @param value
@@ -1104,9 +1105,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* Gets a stored attribute value. If a value has been stored for the
* session, that value is returned. If no value is stored for the name,
* <code>null</code> is returned.
- *
+ *
* @see #setAttribute(String, Object)
- *
+ *
* @param name
* the name of the value to get, can not be <code>null</code>.
* @return the value, or <code>null</code> if no value has been stored or if
@@ -1129,10 +1130,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* value. The outcome of calling this method is thus the same as if calling<br />
* <br />
* <code>getAttribute(type.getName());</code>
- *
+ *
* @see #setAttribute(Class, Object)
* @see #getAttribute(String)
- *
+ *
* @param type
* the type of the value to get, can not be <code>null</code>.
* @return the value, or <code>null</code> if no value has been stored or if
@@ -1153,7 +1154,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Creates a new unique id for a UI.
- *
+ *
* @return a unique UI id
*/
public int getNextUIid() {
@@ -1163,7 +1164,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Adds an initialized UI to this session.
- *
+ *
* @param ui
* the initialized UI to add.
*/
@@ -1197,7 +1198,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Adds a UI provider to this session.
- *
+ *
* @param uiProvider
* the UI provider that should be added
*/
@@ -1208,7 +1209,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Removes a UI provider association from this session.
- *
+ *
* @param uiProvider
* the UI provider that should be removed
*/
@@ -1219,7 +1220,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Gets the UI providers configured for this session.
- *
+ *
* @return an unmodifiable list of UI providers
*/
public List<UIProvider> getUIProviders() {
@@ -1243,9 +1244,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* To avoid causing out of sync errors, you should typically redirect to
* some other page using {@link Page#setLocation(String)} to make the
* browser unload the invalidated UI.
- *
+ *
* @see SystemMessages#getSessionExpiredCaption()
- *
+ *
*/
public void close() {
assert hasLock();
@@ -1255,13 +1256,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Returns whether this session is marked to be closed. Note that this
* method also returns true if the session is actually already closed.
- *
+ *
* @see #close()
- *
+ *
* @deprecated As of 7.2, use
* <code>{@link #getState() getState() != State.OPEN}</code>
* instead.
- *
+ *
* @return true if this session is marked to be closed, false otherwise
*/
@Deprecated
@@ -1272,7 +1273,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Returns the lifecycle state of this session.
- *
+ *
* @since 7.2
* @return the current state
*/
@@ -1284,7 +1285,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Sets the lifecycle state of this session. The allowed transitions are
* OPEN to CLOSING and CLOSING to CLOSED.
- *
+ *
* @since 7.2
* @param state
* the new state
@@ -1323,15 +1324,15 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* later point in time.</li>
* </ul>
* </p>
- *
+ *
* @param runnable
* the runnable which accesses the session
- *
+ *
* @throws IllegalStateException
* if the current thread holds the lock for another session
- *
+ *
* @since 7.1
- *
+ *
* @see #lock()
* @see #getCurrent()
* @see #access(Runnable)
@@ -1385,14 +1386,14 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* an exception if it is detected that the current thread holds the lock for
* some other session.
* </p>
- *
+ *
* @see #lock()
* @see #getCurrent()
* @see #accessSynchronously(Runnable)
* @see UI#access(Runnable)
- *
+ *
* @since 7.1
- *
+ *
* @param runnable
* the runnable which accesses the session
* @return a future that can be used to check for task completion and to
@@ -1406,9 +1407,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* Gets the queue of tasks submitted using {@link #access(Runnable)}. It is
* safe to call this method and access the returned queue without holding
* the {@link #lock() session lock}.
- *
+ *
* @since 7.1
- *
+ *
* @return the queue of pending access tasks
*/
public Queue<FutureAccess> getPendingAccessQueue() {
@@ -1418,7 +1419,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Gets the CSRF token (aka double submit cookie) that is used to protect
* against Cross Site Request Forgery attacks.
- *
+ *
* @since 7.1
* @return the csrf token string
*/
@@ -1439,13 +1440,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
/**
* Finds the UI with the corresponding embed id.
- *
+ *
* @since 7.2
* @param embedId
* the embed id
* @return the UI with the corresponding embed id, or <code>null</code> if
* no UI is found
- *
+ *
* @see UI#getEmbedId()
*/
public UI getUIByEmbedId(String embedId) {
diff --git a/server/src/com/vaadin/server/communication/LegacyUidlWriter.java b/server/src/com/vaadin/server/communication/LegacyUidlWriter.java
index 43ea1aca67..3f70a25c5b 100644
--- a/server/src/com/vaadin/server/communication/LegacyUidlWriter.java
+++ b/server/src/com/vaadin/server/communication/LegacyUidlWriter.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -35,7 +35,7 @@ import com.vaadin.ui.UI;
/**
* Serializes legacy UIDL changes to JSON.
- *
+ *
* @author Vaadin Ltd
* @since 7.1
*/
@@ -44,7 +44,7 @@ public class LegacyUidlWriter implements Serializable {
/**
* Writes a JSON array containing the changes of all dirty
* {@link LegacyComponent}s in the given UI.
- *
+ *
* @param ui
* The {@link UI} whose legacy changes to write
* @param writer
@@ -60,7 +60,8 @@ public class LegacyUidlWriter implements Serializable {
Collection<ClientConnector> dirtyVisibleConnectors = ui
.getConnectorTracker().getDirtyVisibleConnectors();
- List<Component> legacyComponents = new ArrayList<Component>();
+ List<Component> legacyComponents = new ArrayList<Component>(
+ dirtyVisibleConnectors.size());
for (ClientConnector connector : dirtyVisibleConnectors) {
// All Components that want to use paintContent must implement
// LegacyComponent
diff --git a/server/src/com/vaadin/server/communication/PushHandler.java b/server/src/com/vaadin/server/communication/PushHandler.java
index 983ada3279..5a7ae5b3e8 100644
--- a/server/src/com/vaadin/server/communication/PushHandler.java
+++ b/server/src/com/vaadin/server/communication/PushHandler.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -48,7 +48,7 @@ import com.vaadin.ui.UI;
/**
* Establishes bidirectional ("push") communication channels
- *
+ *
* @author Vaadin Ltd
* @since 7.1
*/
@@ -194,7 +194,7 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter {
/**
* Find the UI for the atmosphere resource, lock it and invoke the callback.
- *
+ *
* @param resource
* the atmosphere resource for the current request
* @param callback
@@ -211,6 +211,8 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter {
try {
try {
session = service.findVaadinSession(vaadinRequest);
+ assert VaadinSession.getCurrent() == session;
+
} catch (ServiceException e) {
getLogger().log(Level.SEVERE,
"Could not get session. This should never happen", e);
@@ -231,9 +233,9 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter {
UI ui = null;
session.lock();
try {
- VaadinSession.setCurrent(session);
- // Sets UI.currentInstance
ui = service.findUI(vaadinRequest);
+ assert UI.getCurrent() == ui;
+
if (ui == null) {
sendNotificationAndDisconnect(resource,
UidlRequestHandler.getUINotFoundErrorJSON(service,
@@ -417,10 +419,10 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter {
* two push connections which try to use the same UI. Using the
* AtmosphereResource directly guarantees the message goes to the correct
* recipient.
- *
+ *
* @param resource
* The atmosphere resource to send refresh to
- *
+ *
*/
private static void sendRefreshAndDisconnect(AtmosphereResource resource)
throws IOException {
diff --git a/server/src/com/vaadin/server/communication/PushRequestHandler.java b/server/src/com/vaadin/server/communication/PushRequestHandler.java
index db14e73c1a..308f94686f 100644
--- a/server/src/com/vaadin/server/communication/PushRequestHandler.java
+++ b/server/src/com/vaadin/server/communication/PushRequestHandler.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -47,7 +47,7 @@ import com.vaadin.shared.communication.PushConstants;
* Handles requests to open a push (bidirectional) communication channel between
* the client and the server. After the initial request, communication through
* the push channel is managed by {@link PushHandler}.
- *
+ *
* @author Vaadin Ltd
* @since 7.1
*/
@@ -66,7 +66,8 @@ public class PushRequestHandler implements RequestHandler,
public PushRequestHandler(VaadinServletService service)
throws ServiceException {
- final ServletConfig config = service.getServlet().getServletConfig();
+ final ServletConfig vaadinServletConfig = service.getServlet()
+ .getServletConfig();
atmosphere = new AtmosphereFramework() {
@Override
@@ -77,7 +78,7 @@ public class PushRequestHandler implements RequestHandler,
@Override
public AtmosphereFramework addInitParameter(String name,
String value) {
- if (config.getInitParameter(name) == null) {
+ if (vaadinServletConfig.getInitParameter(name) == null) {
super.addInitParameter(name, value);
}
return this;
@@ -117,7 +118,7 @@ public class PushRequestHandler implements RequestHandler,
"org.atmosphere.cpr.showSupportMessage", "false");
try {
- atmosphere.init(config);
+ atmosphere.init(vaadinServletConfig);
// Ensure the client-side knows how to split the message stream
// into individual messages when using certain transports
diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
index 36bfc8bcc6..9107a4e049 100644
--- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java
+++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -55,7 +55,7 @@ import com.vaadin.ui.UI;
/**
* Handles a client-to-server message containing serialized {@link ServerRpc
* server RPC} invocations.
- *
+ *
* @author Vaadin Ltd
* @since 7.1
*/
@@ -64,7 +64,7 @@ public class ServerRpcHandler implements Serializable {
/**
* A data transfer object representing an RPC request sent by the client
* side.
- *
+ *
* @since 7.2
* @author Vaadin Ltd
*/
@@ -78,7 +78,13 @@ public class ServerRpcHandler implements Serializable {
public RpcRequest(String jsonString, VaadinRequest request)
throws JSONException {
json = new JSONObject(jsonString);
- csrfToken = json.getString(ApplicationConstants.CSRF_TOKEN);
+
+ String csrfToken = json.optString(ApplicationConstants.CSRF_TOKEN);
+ if (csrfToken.equals("")) {
+ csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE;
+ }
+ this.csrfToken = csrfToken;
+
if (request.getService().getDeploymentConfiguration()
.isSyncIdCheckEnabled()) {
syncId = json.getInt(ApplicationConstants.SERVER_SYNC_ID);
@@ -91,7 +97,7 @@ public class ServerRpcHandler implements Serializable {
/**
* Gets the CSRF security token (double submit cookie) for this request.
- *
+ *
* @return the CSRF security token for this current change request
*/
public String getCsrfToken() {
@@ -100,7 +106,7 @@ public class ServerRpcHandler implements Serializable {
/**
* Gets the data to recreate the RPC as requested by the client side.
- *
+ *
* @return the data describing which RPC should be made, and all their
* data
*/
@@ -110,7 +116,7 @@ public class ServerRpcHandler implements Serializable {
/**
* Gets the sync id last seen by the client.
- *
+ *
* @return the last sync id given by the server, according to the
* client's request
*/
@@ -124,9 +130,9 @@ public class ServerRpcHandler implements Serializable {
* <p>
* <em>Note:</em> This is a shared reference - any modifications made
* will be shared.
- *
+ *
* @return the raw JSON object that was received from the client
- *
+ *
*/
public JSONObject getRawJson() {
return json;
@@ -138,7 +144,7 @@ public class ServerRpcHandler implements Serializable {
/**
* Reads JSON containing zero or more serialized RPC calls (including legacy
* variable changes) and executes the calls.
- *
+ *
* @param ui
* The {@link UI} receiving the calls. Cannot be null.
* @param reader
@@ -188,7 +194,7 @@ public class ServerRpcHandler implements Serializable {
* changeVariables() is only called once for them. This preserves the Vaadin
* 6 semantics for components and add-ons that do not use Vaadin 7 RPC
* directly.
- *
+ *
* @param uI
* the UI receiving the invocations data
* @param lastSyncIdSeenByClient
@@ -318,7 +324,7 @@ public class ServerRpcHandler implements Serializable {
/**
* Parse JSON from the client into a list of MethodInvocation instances.
- *
+ *
* @param connectorTracker
* The ConnectorTracker used to lookup connectors
* @param invocationsJson
@@ -333,11 +339,13 @@ public class ServerRpcHandler implements Serializable {
private List<MethodInvocation> parseInvocations(
ConnectorTracker connectorTracker, JSONArray invocationsJson,
int lastSyncIdSeenByClient) throws JSONException {
- ArrayList<MethodInvocation> invocations = new ArrayList<MethodInvocation>();
+ int invocationCount = invocationsJson.length();
+ ArrayList<MethodInvocation> invocations = new ArrayList<MethodInvocation>(
+ invocationCount);
MethodInvocation previousInvocation = null;
// parse JSON to MethodInvocations
- for (int i = 0; i < invocationsJson.length(); ++i) {
+ for (int i = 0; i < invocationCount; ++i) {
JSONArray invocationJson = invocationsJson.getJSONArray(i);
@@ -500,7 +508,7 @@ public class ServerRpcHandler implements Serializable {
/**
* Generates an error message when the client is trying to to something
* ('what') with a connector which is disabled or invisible.
- *
+ *
* @since 7.1.8
* @param connector
* the connector which is disabled (or invisible)
diff --git a/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java b/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java
index d6e232035b..f3cbf47b62 100644
--- a/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java
+++ b/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java
@@ -116,6 +116,8 @@ import com.vaadin.shared.ui.JavaScriptComponentState;
* <li>The primitive Java boolean and the boxed Boolean are represented by
* JavaScript booleans.</li>
* <li>Java Strings are represented by JavaScript strings.</li>
+ * <li>Java Dates are represented by JavaScript numbers containing the timestamp
+ * </li>
* <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li>
* <li>Map<String, ?> in Java is represented by JavaScript object with fields
* corresponding to the map keys.</li>
diff --git a/server/src/com/vaadin/ui/AbstractSelect.java b/server/src/com/vaadin/ui/AbstractSelect.java
index b8db329906..b083db3183 100644
--- a/server/src/com/vaadin/ui/AbstractSelect.java
+++ b/server/src/com/vaadin/ui/AbstractSelect.java
@@ -759,7 +759,9 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
*/
@Override
public int size() {
- return items.size();
+ int size = items.size();
+ assert size >= 0;
+ return size;
}
/**
diff --git a/server/src/com/vaadin/ui/ComboBox.java b/server/src/com/vaadin/ui/ComboBox.java
index 048726dc84..5367505c56 100644
--- a/server/src/com/vaadin/ui/ComboBox.java
+++ b/server/src/com/vaadin/ui/ComboBox.java
@@ -354,6 +354,7 @@ public class ComboBox extends AbstractSelect implements
if (pageLength == 0) {
// no paging: return all items
filteredSize = container.size();
+ assert filteredSize >= 0;
return new ArrayList<Object>(container.getItemIds());
}
@@ -391,6 +392,7 @@ public class ComboBox extends AbstractSelect implements
}
filteredSize = container.size();
+ assert filteredSize >= 0;
currentPage = adjustCurrentPage(currentPage, needNullSelectOption,
indexToEnsureInView, filteredSize);
int first = getFirstItemIndexOnCurrentPage(needNullSelectOption,
diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java
index b5a0227d99..9b8729f779 100644
--- a/server/src/com/vaadin/ui/ConnectorTracker.java
+++ b/server/src/com/vaadin/ui/ConnectorTracker.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -55,10 +55,10 @@ import com.vaadin.server.StreamVariable;
* operation new information needs to be sent to its
* {@link com.vaadin.client.ServerConnector}.
* </p>
- *
+ *
* @author Vaadin Ltd
* @since 7.0.0
- *
+ *
*/
public class ConnectorTracker implements Serializable {
@@ -87,7 +87,7 @@ public class ConnectorTracker implements Serializable {
/**
* Map to track on which syncId each connector was removed.
- *
+ *
* @see #getCurrentSyncId()
* @see #cleanConcurrentlyRemovedConnectorIds(long)
*/
@@ -95,9 +95,9 @@ public class ConnectorTracker implements Serializable {
/**
* Gets a logger for this class
- *
+ *
* @return A logger instance for logging within this class
- *
+ *
*/
public static Logger getLogger() {
return Logger.getLogger(ConnectorTracker.class.getName());
@@ -107,7 +107,7 @@ public class ConnectorTracker implements Serializable {
* Creates a new ConnectorTracker for the given uI. A tracker is always
* attached to a uI and the uI cannot be changed during the lifetime of a
* {@link ConnectorTracker}.
- *
+ *
* @param uI
* The uI to attach to. Cannot be null.
*/
@@ -121,7 +121,7 @@ public class ConnectorTracker implements Serializable {
* The lookup method {@link #getConnector(String)} only returns registered
* connectors.
* </p>
- *
+ *
* @param connector
* The connector to register.
*/
@@ -157,12 +157,12 @@ public class ConnectorTracker implements Serializable {
/**
* Unregister the given connector.
- *
+ *
* <p>
* The lookup method {@link #getConnector(String)} only returns registered
* connectors.
* </p>
- *
+ *
* @param connector
* The connector to unregister
*/
@@ -213,7 +213,7 @@ public class ConnectorTracker implements Serializable {
* Checks whether the given connector has already been initialized in the
* browser. The given connector should be registered with this connector
* tracker.
- *
+ *
* @param connector
* the client connector to check
* @return <code>true</code> if the initial state has previously been sent
@@ -228,9 +228,9 @@ public class ConnectorTracker implements Serializable {
/**
* Marks the given connector as initialized, meaning that the client-side
* state has been initialized for the connector.
- *
+ *
* @see #isClientSideInitialized(ClientConnector)
- *
+ *
* @param connector
* the connector that should be marked as initialized
*/
@@ -242,7 +242,7 @@ public class ConnectorTracker implements Serializable {
* Marks all currently registered connectors as uninitialized. This should
* be done when the client-side has been reset but the server-side state is
* retained.
- *
+ *
* @see #isClientSideInitialized(ClientConnector)
*/
public void markAllClientSidesUninitialized() {
@@ -252,7 +252,7 @@ public class ConnectorTracker implements Serializable {
/**
* Gets a connector by its id.
- *
+ *
* @param connectorId
* The connector id to look for
* @return The connector with the given id or null if no connector has the
@@ -400,10 +400,10 @@ public class ConnectorTracker implements Serializable {
/**
* Mark the connector as dirty. This should not be done while the response
* is being written.
- *
+ *
* @see #getDirtyConnectors()
* @see #isWritingResponse()
- *
+ *
* @param connector
* The connector that should be marked clean.
*/
@@ -425,7 +425,7 @@ public class ConnectorTracker implements Serializable {
/**
* Mark the connector as clean.
- *
+ *
* @param connector
* The connector that should be marked clean.
*/
@@ -443,7 +443,7 @@ public class ConnectorTracker implements Serializable {
/**
* Returns {@link #getConnectorString(ClientConnector)} for the connector
* and its parent (if it has a parent).
- *
+ *
* @param connector
* The connector
* @return A string describing the connector and its parent
@@ -460,7 +460,7 @@ public class ConnectorTracker implements Serializable {
/**
* Returns a string with the connector name and id. Useful mostly for
* debugging and logging.
- *
+ *
* @param connector
* The connector
* @return A string that describes the connector
@@ -500,7 +500,7 @@ public class ConnectorTracker implements Serializable {
/**
* Marks all visible connectors dirty, starting from the given connector and
* going downwards in the hierarchy.
- *
+ *
* @param c
* The component to start iterating downwards from
*/
@@ -521,7 +521,7 @@ public class ConnectorTracker implements Serializable {
* The state and pending RPC calls for dirty connectors are sent to the
* client in the following request.
* </p>
- *
+ *
* @return A collection of all dirty connectors for this uI. This list may
* contain invisible connectors.
*/
@@ -531,7 +531,7 @@ public class ConnectorTracker implements Serializable {
/**
* Checks if there a dirty connectors.
- *
+ *
* @return true if there are dirty connectors, false otherwise
*/
public boolean hasDirtyConnectors() {
@@ -541,17 +541,19 @@ public class ConnectorTracker implements Serializable {
/**
* Returns a collection of those {@link #getDirtyConnectors() dirty
* connectors} that are actually visible to the client.
- *
+ *
* @return A list of dirty and visible connectors.
*/
public ArrayList<ClientConnector> getDirtyVisibleConnectors() {
- ArrayList<ClientConnector> dirtyConnectors = new ArrayList<ClientConnector>();
- for (ClientConnector c : getDirtyConnectors()) {
+ Collection<ClientConnector> dirtyConnectors = getDirtyConnectors();
+ ArrayList<ClientConnector> dirtyVisibleConnectors = new ArrayList<ClientConnector>(
+ dirtyConnectors.size());
+ for (ClientConnector c : dirtyConnectors) {
if (LegacyCommunicationManager.isConnectorVisibleToClient(c)) {
- dirtyConnectors.add(c);
+ dirtyVisibleConnectors.add(c);
}
}
- return dirtyConnectors;
+ return dirtyVisibleConnectors;
}
public JSONObject getDiffState(ClientConnector connector) {
@@ -571,10 +573,10 @@ public class ConnectorTracker implements Serializable {
/**
* Checks whether the response is currently being written. Connectors can
* not be marked as dirty when a response is being written.
- *
+ *
* @see #setWritingResponse(boolean)
* @see #markDirty(ClientConnector)
- *
+ *
* @return <code>true</code> if the response is currently being written,
* <code>false</code> if outside the response writing phase.
*/
@@ -590,14 +592,14 @@ public class ConnectorTracker implements Serializable {
* {@link #getCurrentSyncId()}), if {@link #isWritingResponse()} returns
* <code>false</code> and <code>writingResponse</code> is set to
* <code>true</code>.
- *
+ *
* @param writingResponse
* the new response status.
- *
+ *
* @see #markDirty(ClientConnector)
* @see #isWritingResponse()
* @see #getCurrentSyncId()
- *
+ *
* @throws IllegalArgumentException
* if the new response status is the same as the previous value.
* This is done to help detecting problems caused by missed
@@ -625,7 +627,7 @@ public class ConnectorTracker implements Serializable {
// Convert JSONObjects in diff state to String representation as
// JSONObject is not serializable
HashMap<ClientConnector, String> stringDiffStates = new HashMap<ClientConnector, String>(
- diffStates.size());
+ diffStates.size() * 2);
for (ClientConnector key : diffStates.keySet()) {
stringDiffStates.put(key, diffStates.get(key).toString());
}
@@ -643,7 +645,8 @@ public class ConnectorTracker implements Serializable {
@SuppressWarnings("unchecked")
HashMap<ClientConnector, String> stringDiffStates = (HashMap<ClientConnector, String>) in
.readObject();
- diffStates = new HashMap<ClientConnector, JSONObject>();
+ diffStates = new HashMap<ClientConnector, JSONObject>(
+ stringDiffStates.size() * 2);
for (ClientConnector key : stringDiffStates.keySet()) {
try {
diffStates.put(key, new JSONObject(stringDiffStates.get(key)));
@@ -657,7 +660,7 @@ public class ConnectorTracker implements Serializable {
/**
* Checks if the indicated connector has a StreamVariable of the given name
* and returns the variable if one is found.
- *
+ *
* @param connectorId
* @param variableName
* @return variable if a matching one exists, otherwise null
@@ -678,7 +681,7 @@ public class ConnectorTracker implements Serializable {
/**
* Adds a StreamVariable of the given name to the indicated connector.
- *
+ *
* @param connectorId
* @param variableName
* @param variable
@@ -734,7 +737,7 @@ public class ConnectorTracker implements Serializable {
/**
* Removes any StreamVariable of the given name from the indicated
* connector.
- *
+ *
* @param connectorId
* @param variableName
*/
@@ -752,7 +755,7 @@ public class ConnectorTracker implements Serializable {
/**
* Returns the security key associated with the given StreamVariable.
- *
+ *
* @param variable
* @return matching security key if one exists, null otherwise
*/
@@ -767,7 +770,7 @@ public class ConnectorTracker implements Serializable {
* Check whether a connector was present on the client when the it was
* creating this request, but was removed server-side before the request
* arrived.
- *
+ *
* @since 7.2
* @param connectorId
* The connector id to check for whether it was removed
@@ -827,7 +830,7 @@ public class ConnectorTracker implements Serializable {
* <p>
* The sync id value <code>-1</code> is ignored to facilitate testing with
* pre-recorded requests.
- *
+ *
* @see #setWritingResponse(boolean)
* @see #connectorWasPresentAsRequestWasSent(String, long)
* @since 7.2
@@ -853,7 +856,7 @@ public class ConnectorTracker implements Serializable {
* <p>
* The sync id value <code>-1</code> is ignored to facilitate testing with
* pre-recorded requests.
- *
+ *
* @see #connectorWasPresentAsRequestWasSent(String, long)
* @since 7.2
* @param lastSyncIdSeenByClient
diff --git a/server/src/com/vaadin/ui/Upload.java b/server/src/com/vaadin/ui/Upload.java
index 869c32751a..4c248d68ae 100644
--- a/server/src/com/vaadin/ui/Upload.java
+++ b/server/src/com/vaadin/ui/Upload.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -35,16 +35,16 @@ import com.vaadin.util.ReflectTools;
/**
* Component for uploading files from client to server.
- *
+ *
* <p>
* The visible component consists of a file name input box and a browse button
* and an upload submit button to start uploading.
- *
+ *
* <p>
* The Upload component needs a java.io.OutputStream to write the uploaded data.
* You need to implement the Upload.Receiver interface and return the output
* stream in the receiveUpload() method.
- *
+ *
* <p>
* You can get an event regarding starting (StartedEvent), progress
* (ProgressEvent), and finishing (FinishedEvent) of upload by implementing
@@ -52,22 +52,22 @@ import com.vaadin.util.ReflectTools;
* FinishedListener is called for both failed and succeeded uploads. If you wish
* to separate between these two cases, you can use SucceededListener
* (SucceededEvenet) and FailedListener (FailedEvent).
- *
+ *
* <p>
* The upload component does not itself show upload progress, but you can use
* the ProgressIndicator for providing progress feedback by implementing
* ProgressListener and updating the indicator in updateProgress().
- *
+ *
* <p>
* Setting upload component immediate initiates the upload as soon as a file is
* selected, instead of the common pattern of file selection field and upload
* button.
- *
+ *
* <p>
* Note! Because of browser dependent implementations of <input type="file">
* element, setting size for Upload component is not supported. For some
* browsers setting size may work to some extend.
- *
+ *
* @author Vaadin Ltd.
* @since 3.0
*/
@@ -112,7 +112,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Creates a new instance of Upload.
- *
+ *
* The receiver must be set before performing an upload.
*/
public Upload() {
@@ -132,7 +132,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Invoked when the value of a variable has changed.
- *
+ *
* @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object,
* java.util.Map)
*/
@@ -150,7 +150,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Paints the content of this component.
- *
+ *
* @param target
* Target to paint the content on.
* @throws PaintException
@@ -189,7 +189,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Interface that must be implemented by the upload receivers to provide the
* Upload component an output stream to write the uploaded data.
- *
+ *
* @author Vaadin Ltd.
* @since 3.0
*/
@@ -197,7 +197,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Invoked when a new upload arrives.
- *
+ *
* @param filename
* the desired filename of the upload, usually as specified
* by the client.
@@ -242,7 +242,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
* of whether the reception was successful or failed. If you wish to
* distinguish between the two cases, use either SucceededEvent or
* FailedEvent, which are both subclasses of the FinishedEvent.
- *
+ *
* @author Vaadin Ltd.
* @since 3.0
*/
@@ -264,7 +264,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
private final String filename;
/**
- *
+ *
* @param source
* the source of the file.
* @param filename
@@ -284,7 +284,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Uploads where the event occurred.
- *
+ *
* @return the Source of the event.
*/
public Upload getUpload() {
@@ -293,7 +293,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Gets the file name.
- *
+ *
* @return the filename.
*/
public String getFilename() {
@@ -302,7 +302,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Gets the MIME Type of the file.
- *
+ *
* @return the MIME type.
*/
public String getMIMEType() {
@@ -311,7 +311,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Gets the length of the file.
- *
+ *
* @return the length.
*/
public long getLength() {
@@ -323,7 +323,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Upload.FailedEvent event is sent when the upload is received, but the
* reception is interrupted for some reason.
- *
+ *
* @author Vaadin Ltd.
* @since 3.0
*/
@@ -332,7 +332,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
private Exception reason = null;
/**
- *
+ *
* @param source
* @param filename
* @param MIMEType
@@ -346,7 +346,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
}
/**
- *
+ *
* @param source
* @param filename
* @param MIMEType
@@ -360,7 +360,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Gets the exception that caused the failure.
- *
+ *
* @return the exception that caused the failure, null if n/a
*/
public Exception getReason() {
@@ -375,7 +375,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
public static class NoOutputStreamEvent extends FailedEvent {
/**
- *
+ *
* @param source
* @param filename
* @param MIMEType
@@ -393,7 +393,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
public static class NoInputStreamEvent extends FailedEvent {
/**
- *
+ *
* @param source
* @param filename
* @param MIMEType
@@ -409,14 +409,14 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Upload.SucceededEvent event is sent when the upload is received
* successfully.
- *
+ *
* @author Vaadin Ltd.
* @since 3.0
*/
public static class SucceededEvent extends FinishedEvent {
/**
- *
+ *
* @param source
* @param filename
* @param MIMEType
@@ -431,7 +431,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Upload.StartedEvent event is sent when the upload is started to received.
- *
+ *
* @author Vaadin Ltd.
* @since 5.0
*/
@@ -445,7 +445,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
private final long length;
/**
- *
+ *
* @param source
* @param filename
* @param MIMEType
@@ -461,7 +461,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Uploads where the event occurred.
- *
+ *
* @return the Source of the event.
*/
public Upload getUpload() {
@@ -470,7 +470,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Gets the file name.
- *
+ *
* @return the filename.
*/
public String getFilename() {
@@ -479,7 +479,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Gets the MIME Type of the file.
- *
+ *
* @return the MIME type.
*/
public String getMIMEType() {
@@ -498,7 +498,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Upload.ChangeEvent event is sent when the value (filename) of the upload
* changes.
- *
+ *
* @since 7.2
*/
public static class ChangeEvent extends Component.Event {
@@ -512,7 +512,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Uploads where the event occurred.
- *
+ *
* @return the Source of the event.
*/
@Override
@@ -522,7 +522,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Gets the file name.
- *
+ *
* @return the filename.
*/
public String getFilename() {
@@ -533,7 +533,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Receives the events when the upload starts.
- *
+ *
* @author Vaadin Ltd.
* @since 5.0
*/
@@ -541,7 +541,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Upload has started.
- *
+ *
* @param event
* the Upload started event.
*/
@@ -550,7 +550,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Receives the events when the uploads are ready.
- *
+ *
* @author Vaadin Ltd.
* @since 3.0
*/
@@ -558,7 +558,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Upload has finished.
- *
+ *
* @param event
* the Upload finished event.
*/
@@ -567,7 +567,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Receives events when the uploads are finished, but unsuccessful.
- *
+ *
* @author Vaadin Ltd.
* @since 3.0
*/
@@ -575,7 +575,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Upload has finished unsuccessfully.
- *
+ *
* @param event
* the Upload failed event.
*/
@@ -584,7 +584,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Receives events when the uploads are successfully finished.
- *
+ *
* @author Vaadin Ltd.
* @since 3.0
*/
@@ -592,7 +592,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Upload successfull..
- *
+ *
* @param event
* the Upload successfull event.
*/
@@ -601,7 +601,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Listener for {@link ChangeEvent}
- *
+ *
* @since 7.2
*/
public interface ChangeListener extends Serializable {
@@ -611,7 +611,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* A file has been selected but upload has not yet started.
- *
+ *
* @param event
* the change event
*/
@@ -620,7 +620,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Adds the upload started event listener.
- *
+ *
* @param listener
* the Listener to be added.
*/
@@ -639,7 +639,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Removes the upload started event listener.
- *
+ *
* @param listener
* the Listener to be removed.
*/
@@ -658,7 +658,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Adds the upload received event listener.
- *
+ *
* @param listener
* the Listener to be added.
*/
@@ -677,7 +677,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Removes the upload received event listener.
- *
+ *
* @param listener
* the Listener to be removed.
*/
@@ -696,7 +696,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Adds the upload interrupted event listener.
- *
+ *
* @param listener
* the Listener to be added.
*/
@@ -715,7 +715,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Removes the upload interrupted event listener.
- *
+ *
* @param listener
* the Listener to be removed.
*/
@@ -734,7 +734,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Adds the upload success event listener.
- *
+ *
* @param listener
* the Listener to be added.
*/
@@ -753,7 +753,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Removes the upload success event listener.
- *
+ *
* @param listener
* the Listener to be removed.
*/
@@ -771,10 +771,10 @@ public class Upload extends AbstractComponent implements Component.Focusable,
}
/**
- * Adds the upload success event listener.
- *
+ * Adds the upload progress event listener.
+ *
* @param listener
- * the Listener to be added.
+ * the progress listener to be added
*/
public void addProgressListener(ProgressListener listener) {
if (progressListeners == null) {
@@ -793,10 +793,10 @@ public class Upload extends AbstractComponent implements Component.Focusable,
}
/**
- * Removes the upload success event listener.
- *
+ * Removes the upload progress event listener.
+ *
* @param listener
- * the Listener to be removed.
+ * the progress listener to be removed
*/
public void removeProgressListener(ProgressListener listener) {
if (progressListeners != null) {
@@ -806,7 +806,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Adds a filename change event listener
- *
+ *
* @param listener
* the Listener to add
*/
@@ -817,7 +817,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Removes a filename change event listener
- *
+ *
* @param listener
* the listener to be removed
*/
@@ -836,7 +836,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Emit upload received event.
- *
+ *
* @param filename
* @param MIMEType
* @param length
@@ -848,7 +848,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Emits the upload failed event.
- *
+ *
* @param filename
* @param MIMEType
* @param length
@@ -877,11 +877,11 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Emits the upload success event.
- *
+ *
* @param filename
* @param MIMEType
* @param length
- *
+ *
*/
protected void fireUploadSuccess(String filename, String MIMEType,
long length) {
@@ -890,12 +890,12 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Emits the progress event.
- *
+ *
* @param totalBytes
* bytes received so far
* @param contentLength
* actual size of the file being uploaded, if known
- *
+ *
*/
protected void fireUpdateProgress(long totalBytes, long contentLength) {
// this is implemented differently than other listeners to maintain
@@ -911,7 +911,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Returns the current receiver.
- *
+ *
* @return the StreamVariable.
*/
public Receiver getReceiver() {
@@ -920,7 +920,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Sets the receiver.
- *
+ *
* @param receiver
* the receiver to set.
*/
@@ -938,7 +938,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Gets the Tabulator index of this Focusable component.
- *
+ *
* @see com.vaadin.ui.Component.Focusable#getTabIndex()
*/
@Override
@@ -948,7 +948,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Sets the Tabulator index of this Focusable component.
- *
+ *
* @see com.vaadin.ui.Component.Focusable#setTabIndex(int)
*/
@Override
@@ -959,7 +959,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Go into upload state. This is to prevent double uploading on same
* component.
- *
+ *
* Warning: this is an internal method used by the framework and should not
* be used by user of the Upload component. Using it results in the Upload
* component going in wrong state and not working. It is currently public
@@ -986,7 +986,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Go into state where new uploading can begin.
- *
+ *
* Warning: this is an internal method used by the framework and should not
* be used by user of the Upload component.
*/
@@ -1003,7 +1003,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Gets read bytes of the file currently being uploaded.
- *
+ *
* @return bytes
*/
public long getBytesRead() {
@@ -1013,7 +1013,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
/**
* Returns size of file currently being uploaded. Value sane only during
* upload.
- *
+ *
* @return size in bytes
*/
public long getUploadSize() {
@@ -1026,7 +1026,7 @@ public class Upload extends AbstractComponent implements Component.Focusable,
public interface ProgressListener extends Serializable {
/**
* Updates progress to listener
- *
+ *
* @param readBytes
* bytes transferred
* @param contentLength
@@ -1055,12 +1055,12 @@ public class Upload extends AbstractComponent implements Component.Focusable,
* {@link #setImmediate(boolean)}, the file choose (html input with type
* "file") is hidden and only the button with this text is shown.
* <p>
- *
+ *
* <p>
* <strong>Note</strong> the string given is set as is to the button. HTML
* formatting is not stripped. Be sure to properly validate your value
* according to your needs.
- *
+ *
* @param buttonCaption
* text for upload components button.
*/
diff --git a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java
index 7c19395df2..a8804caedb 100644
--- a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java
+++ b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java
@@ -262,6 +262,7 @@ public class ContainerEventProvider implements CalendarEditableEventProvider,
private int[] getFirstAndLastEventIndex(Date start, Date end) {
int startIndex = 0;
int size = container.size();
+ assert size >= 0;
int endIndex = size - 1;
if (start != null) {
diff --git a/server/src/com/vaadin/util/CurrentInstance.java b/server/src/com/vaadin/util/CurrentInstance.java
index 00d2e7346d..6f2c0a2eca 100644
--- a/server/src/com/vaadin/util/CurrentInstance.java
+++ b/server/src/com/vaadin/util/CurrentInstance.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -52,12 +52,14 @@ import com.vaadin.ui.UI;
* <p>
* Non-inheritable: {@link VaadinRequest}, {@link VaadinResponse}.
* </p>
- *
+ *
* @author Vaadin Ltd
* @since 7.0.0
*/
public class CurrentInstance implements Serializable {
private static final Object NULL_OBJECT = new Object();
+ private static final CurrentInstance CURRENT_INSTANCE_NULL = new CurrentInstance(
+ NULL_OBJECT, true);
private final WeakReference<Object> instance;
private final boolean inheritable;
@@ -90,7 +92,7 @@ public class CurrentInstance implements Serializable {
/**
* Gets the current instance of a specific type if available.
- *
+ *
* @param type
* the class to get an instance of
* @return the current instance or the provided type, or <code>null</code>
@@ -110,7 +112,7 @@ public class CurrentInstance implements Serializable {
* ThreadLocal should only outlive the referenced object on
* threads that are not doing anything related to Vaadin, which
* should thus never invoke CurrentInstance.get().
- *
+ *
* At this point, there might also be other values that have
* been collected, so we'll scan the entire map and remove stale
* CurrentInstance objects. Using a ReferenceQueue could make
@@ -148,10 +150,10 @@ public class CurrentInstance implements Serializable {
/**
* Sets the current instance of the given type.
- *
+ *
* @see #setInheritable(Class, Object)
* @see ThreadLocal
- *
+ *
* @param type
* the class that should be used when getting the current
* instance back
@@ -167,10 +169,10 @@ public class CurrentInstance implements Serializable {
* instance that is inheritable will be available for child threads and in
* code run by {@link VaadinSession#access(Runnable)} and
* {@link UI#access(Runnable)}.
- *
+ *
* @see #set(Class, Object)
* @see InheritableThreadLocal
- *
+ *
* @param type
* the class that should be used when getting the current
* instance back
@@ -181,17 +183,18 @@ public class CurrentInstance implements Serializable {
set(type, instance, true);
}
- private static <T> void set(Class<T> type, T instance, boolean inheritable) {
+ private static <T> CurrentInstance set(Class<T> type, T instance,
+ boolean inheritable) {
Map<Class<?>, CurrentInstance> map = instances.get();
+ CurrentInstance previousInstance = null;
if (instance == null) {
// remove the instance
- if (map == null) {
- return;
- }
- map.remove(type);
- if (map.isEmpty()) {
- instances.remove();
- map = null;
+ if (map != null) {
+ previousInstance = map.remove(type);
+ if (map.isEmpty()) {
+ instances.remove();
+ map = null;
+ }
}
} else {
assert type.isInstance(instance) : "Invald instance type";
@@ -200,8 +203,8 @@ public class CurrentInstance implements Serializable {
instances.set(map);
}
- CurrentInstance previousInstance = map.put(type,
- new CurrentInstance(instance, inheritable));
+ previousInstance = map.put(type, new CurrentInstance(instance,
+ inheritable));
if (previousInstance != null) {
assert previousInstance.inheritable == inheritable : "Inheritable status mismatch for "
+ type
@@ -211,6 +214,10 @@ public class CurrentInstance implements Serializable {
+ inheritable + ")";
}
}
+ if (previousInstance == null) {
+ previousInstance = CURRENT_INSTANCE_NULL;
+ }
+ return previousInstance;
}
/**
@@ -223,9 +230,9 @@ public class CurrentInstance implements Serializable {
/**
* Restores the given instances to the given values. Note that this should
* only be used internally to restore Vaadin classes.
- *
+ *
* @since 7.1
- *
+ *
* @param old
* A Class -> CurrentInstance map to set as current instances
*/
@@ -243,7 +250,7 @@ public class CurrentInstance implements Serializable {
* CurrentInstance. Without this a reference to an already
* collected instance may be left in the CurrentInstance when it
* really should be restored to null.
- *
+ *
* One example case that this fixes:
* VaadinService.runPendingAccessTasks() clears all current
* instances and then sets everything but the UI. This makes
@@ -267,9 +274,9 @@ public class CurrentInstance implements Serializable {
/**
* Gets the currently set instances so that they can later be restored using
* {@link #restoreInstances(Map)}.
- *
+ *
* @since 7.1
- *
+ *
* @param onlyInheritable
* <code>true</code> if only the inheritable instances should be
* included; <code>false</code> to get all instances.
@@ -305,20 +312,17 @@ public class CurrentInstance implements Serializable {
* Sets current instances for the UI and all related classes. The previously
* defined values can be restored by passing the returned map to
* {@link #restoreInstances(Map)}.
- *
+ *
* @since 7.1
- *
+ *
* @param ui
* The UI
* @return A map containing the old values of the instances that this method
* updated.
*/
public static Map<Class<?>, CurrentInstance> setCurrent(UI ui) {
- Map<Class<?>, CurrentInstance> old = new HashMap<Class<?>, CurrentInstance>();
- old.put(UI.class,
- new CurrentInstance(getSameOrNullObject(UI.getCurrent()), true));
- UI.setCurrent(ui);
- old.putAll(setCurrent(ui.getSession()));
+ Map<Class<?>, CurrentInstance> old = setCurrent(ui.getSession());
+ old.put(UI.class, set(UI.class, ui, true));
return old;
}
@@ -326,9 +330,9 @@ public class CurrentInstance implements Serializable {
* Sets current instances for the {@link VaadinSession} and all related
* classes. The previously defined values can be restored by passing the
* returned map to {@link #restoreInstances(Map)}.
- *
+ *
* @since 7.1
- *
+ *
* @param session
* The VaadinSession
* @return A map containing the old values of the instances this method
@@ -337,33 +341,15 @@ public class CurrentInstance implements Serializable {
public static Map<Class<?>, CurrentInstance> setCurrent(
VaadinSession session) {
Map<Class<?>, CurrentInstance> old = new HashMap<Class<?>, CurrentInstance>();
- old.put(VaadinSession.class, new CurrentInstance(
- getSameOrNullObject(VaadinSession.getCurrent()), true));
- old.put(VaadinService.class, new CurrentInstance(
- getSameOrNullObject(VaadinService.getCurrent()), true));
+ old.put(VaadinSession.class, set(VaadinSession.class, session, true));
VaadinService service = null;
if (session != null) {
service = session.getService();
}
-
- VaadinSession.setCurrent(session);
- VaadinService.setCurrent(service);
-
+ old.put(VaadinService.class, set(VaadinService.class, service, true));
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/data/util/ContainerSizeAssertTest.java b/server/tests/src/com/vaadin/data/util/ContainerSizeAssertTest.java
new file mode 100644
index 0000000000..04fd8d3cd1
--- /dev/null
+++ b/server/tests/src/com/vaadin/data/util/ContainerSizeAssertTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2014 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.data.util;
+
+import org.junit.Test;
+
+import com.vaadin.data.Container;
+import com.vaadin.ui.Table;
+
+public class ContainerSizeAssertTest {
+
+ @Test(expected = AssertionError.class)
+ public void testNegativeSizeAssert() {
+ Table table = createAttachedTable();
+
+ table.setContainerDataSource(createNegativeSizeContainer());
+ }
+
+ @Test
+ public void testZeroSizeNoAssert() {
+ Table table = createAttachedTable();
+
+ table.setContainerDataSource(new IndexedContainer());
+ }
+
+ private Container createNegativeSizeContainer() {
+ return new IndexedContainer() {
+ @Override
+ public int size() {
+ return -1;
+ }
+ };
+ }
+
+ private Table createAttachedTable() {
+ return new Table() {
+ private boolean initialized = true;
+
+ @Override
+ public boolean isAttached() {
+ // This returns false until the super constructor has finished
+ return initialized;
+ }
+ };
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java b/server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java
new file mode 100644
index 0000000000..30f1c85fef
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2000-2014 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.tests.server;
+
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.easymock.EasyMock;
+import org.json.JSONException;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.server.ServiceException;
+import com.vaadin.server.VaadinService;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.server.VaadinServletRequest;
+import com.vaadin.server.VaadinServletService;
+import com.vaadin.server.VaadinSession;
+import com.vaadin.server.communication.ServerRpcHandler.RpcRequest;
+import com.vaadin.shared.ApplicationConstants;
+import com.vaadin.tests.util.AlwaysLockedVaadinSession;
+import com.vaadin.tests.util.MockDeploymentConfiguration;
+
+/**
+ * Test the actual csrf token validation by the server.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class CsrfTokenMissingTestServer {
+
+ // Dummy fields just to run the test.
+ private VaadinServlet mockServlet;
+
+ // The mock deployment configuration.
+ private MockDeploymentConfiguration mockDeploymentConfiguration;
+
+ private VaadinServletService mockService;
+
+ // The mock UI session.
+ private VaadinSession mockSession;
+
+ // The mock vaadin request.
+ private VaadinServletRequest vaadinRequest;
+
+ /**
+ * Initialize the mock servlet and other stuff for our tests.
+ */
+ @Before
+ public void initMockStuff() throws ServiceException {
+ mockServlet = new VaadinServlet();
+ mockDeploymentConfiguration = new MockDeploymentConfiguration();
+
+ mockService = new VaadinServletService(mockServlet,
+ mockDeploymentConfiguration);
+
+ mockSession = new AlwaysLockedVaadinSession(mockService);
+
+ vaadinRequest = new VaadinServletRequest(
+ EasyMock.createMock(HttpServletRequest.class), mockService);
+
+ }
+
+ private enum TokenType {
+ MISSING, INVALID, VALID
+ }
+
+ private TokenType tokenType;
+
+ private String invalidToken;
+
+ public String getInvalidToken() {
+ if (invalidToken == null) {
+ // Just making sure this will never be in the same format as a valid
+ // token.
+ invalidToken = UUID.randomUUID().toString().substring(1);
+ }
+ return invalidToken;
+ }
+
+ private String getValidToken() {
+ return mockSession.getCsrfToken();
+ }
+
+ /*
+ * Gets the payload with the default token.
+ */
+ private String getPayload() {
+ switch (tokenType) {
+ case MISSING:
+ return getPayload(null);
+
+ case INVALID:
+ return getPayload(getInvalidToken());
+
+ case VALID:
+ return getPayload(getValidToken());
+ }
+
+ return null;
+ }
+
+ /*
+ * Gets the payload with the specified token.
+ */
+ private String getPayload(String token) {
+ return "{"
+ + (token != null ? "\"csrfToken\":" + "\"" + token + "\", "
+ : "")
+ + "\"rpc\":[[\"0\",\"com.vaadin.shared.ui.ui.UIServerRpc\",\"resize\",[\"449\",\"1155\",\"1155\",\"449\"]],[\"4\",\"com.vaadin.shared.ui.button.ButtonServerRpc\",\"click\",[{\"clientY\":\"53\", \"clientX\":\"79\", \"shiftKey\":false, \"button\":\"LEFT\", \"ctrlKey\":false, \"type\":\"1\", \"metaKey\":false, \"altKey\":false, \"relativeY\":\"17\", \"relativeX\":\"61\"}]]], \"syncId\":1}";
+ }
+
+ /*
+ * Init the test parameters.
+ */
+ private void initTest(boolean enableSecurity, TokenType tokenType) {
+ mockDeploymentConfiguration.setXsrfProtectionEnabled(enableSecurity);
+ this.tokenType = tokenType;
+ }
+
+ /*
+ * Create the requets.
+ */
+ private RpcRequest createRequest() {
+ try {
+ return new RpcRequest(getPayload(), vaadinRequest);
+ } catch (JSONException e) {
+ LOGGER.log(Level.SEVERE, "", e);
+
+ Assert.assertTrue(false);
+ return null;
+ }
+ }
+
+ /*
+ * Gets whether the token from the request is the default one.
+ */
+ private boolean isDefaultToken(RpcRequest rpcRequest) {
+ return ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE.equals(rpcRequest
+ .getCsrfToken());
+ }
+
+ /*
+ * Gets whether the token from the request is the invalid one.
+ */
+ private boolean isInvalidToken(RpcRequest rpcRequest) {
+ return getInvalidToken().equals(rpcRequest.getCsrfToken());
+ }
+
+ /*
+ * Gets whether the token from the request is the valid one.
+ */
+ private boolean isValidToken(RpcRequest rpcRequest) {
+ return getValidToken().equals(rpcRequest.getCsrfToken());
+ }
+
+ /*
+ * Gets whether the token from the request is valid.
+ */
+ private boolean isRequestValid(RpcRequest rpcRequest) {
+ return VaadinService.isCsrfTokenValid(mockSession,
+ rpcRequest.getCsrfToken());
+ }
+
+ private static Logger LOGGER = Logger
+ .getLogger(CsrfTokenMissingTestServer.class.getName());
+ static {
+ LOGGER.setLevel(Level.ALL);
+ }
+
+ @Test
+ public void securityOnAndNoToken() {
+ initTest(true, TokenType.MISSING);
+
+ RpcRequest rpcRequest = createRequest();
+
+ Assert.assertTrue(isDefaultToken(rpcRequest));
+ Assert.assertFalse(isRequestValid(rpcRequest));
+ }
+
+ @Test
+ public void securityOffAndNoToken() {
+ initTest(false, TokenType.MISSING);
+
+ RpcRequest rpcRequest = createRequest();
+
+ Assert.assertTrue(isDefaultToken(rpcRequest));
+ Assert.assertTrue(isRequestValid(rpcRequest));
+ }
+
+ @Test
+ public void securityOnAndInvalidToken() {
+ initTest(true, TokenType.INVALID);
+
+ RpcRequest rpcRequest = createRequest();
+
+ Assert.assertTrue(isInvalidToken(rpcRequest));
+ Assert.assertFalse(isRequestValid(rpcRequest));
+ }
+
+ @Test
+ public void securityOffAndInvalidToken() {
+ initTest(false, TokenType.INVALID);
+
+ RpcRequest rpcRequest = createRequest();
+
+ Assert.assertTrue(isInvalidToken(rpcRequest));
+ Assert.assertTrue(isRequestValid(rpcRequest));
+ }
+
+ @Test
+ public void securityOnAndValidToken() {
+ initTest(true, TokenType.VALID);
+
+ RpcRequest rpcRequest = createRequest();
+
+ Assert.assertTrue(isValidToken(rpcRequest));
+ Assert.assertTrue(isRequestValid(rpcRequest));
+ }
+
+ @Test
+ public void securityOffAndValidToken() {
+ initTest(false, TokenType.VALID);
+
+ RpcRequest rpcRequest = createRequest();
+
+ Assert.assertTrue(isValidToken(rpcRequest));
+ Assert.assertTrue(isRequestValid(rpcRequest));
+ }
+
+}
diff --git a/shared/src/com/vaadin/shared/ApplicationConstants.java b/shared/src/com/vaadin/shared/ApplicationConstants.java
index da4ac7450d..15eefe3b21 100644
--- a/shared/src/com/vaadin/shared/ApplicationConstants.java
+++ b/shared/src/com/vaadin/shared/ApplicationConstants.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -86,7 +86,7 @@ public class ApplicationConstants implements Serializable {
/**
* The name of the debug version of the javascript containing push support.
* The file is located in the VAADIN directory.
- *
+ *
* @since 7.1.6
*/
public static final String VAADIN_PUSH_DEBUG_JS = "vaadinPush.debug.js";
@@ -98,14 +98,14 @@ public class ApplicationConstants implements Serializable {
/**
* The name of the parameter used to transmit RPC invocations
- *
+ *
* @since 7.2
*/
public static final String RPC_INVOCATIONS = "rpc";
/**
* The name of the parameter used to transmit the CSRF token
- *
+ *
* @since 7.2
*/
public static final String CSRF_TOKEN = "csrfToken";
@@ -114,9 +114,15 @@ public class ApplicationConstants implements Serializable {
* The name of the parameter used to transmit the sync id. The value can be
* set to -1 e.g. when testing with pre-recorded requests to make the
* framework ignore the sync id.
- *
+ *
* @see com.vaadin.ui.ConnectorTracker#getCurrentSyncId()
* @since 7.2
*/
public static final String SERVER_SYNC_ID = "syncId";
+
+ /**
+ * Default value to use in case the security protection is disabled.
+ */
+ public static final String CSRF_TOKEN_DEFAULT_VALUE = "init";
+
}
diff --git a/uitest/eclipse-run-selected-test.properties b/uitest/eclipse-run-selected-test.properties
index cbd1ab1cef..70010fd1da 100644
--- a/uitest/eclipse-run-selected-test.properties
+++ b/uitest/eclipse-run-selected-test.properties
@@ -1,4 +1,11 @@
;
+; This is an example property file showing how to control how TestBench is used
+; in the Vaadin Framework project. You should not modify this file since it's
+; under version control. Instead, create a copy of it inside the /work/ folder
+; in the project and make your customizations to that file.
+;
+
+;
; For both TestBench 2 and 3
;
@@ -8,6 +15,14 @@ com.vaadin.testbench.screenshot.directory=<enter the full path to the screenshot
;
+; For only TestBench 3
+;
+
+; Simulates @RunLocally with the given value on all test classes without a @RunLocally annotation.
+; com.vaadin.testbench.runLocally=firefox
+
+
+;
; For only TestBench 2
;
diff --git a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java
index a89ec4e587..1f72495596 100644
--- a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java
+++ b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java
@@ -17,12 +17,17 @@ package com.vaadin.launcher;
import java.io.File;
import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -30,7 +35,11 @@ import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import com.vaadin.launcher.CustomDeploymentConfiguration.Conf;
+import com.vaadin.server.DefaultDeploymentConfiguration;
+import com.vaadin.server.DeploymentConfiguration;
import com.vaadin.server.LegacyApplication;
import com.vaadin.server.LegacyVaadinServlet;
import com.vaadin.server.ServiceException;
@@ -43,6 +52,7 @@ import com.vaadin.server.VaadinServletRequest;
import com.vaadin.server.VaadinSession;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.UI;
+import com.vaadin.util.CurrentInstance;
@SuppressWarnings("serial")
public class ApplicationRunnerServlet extends LegacyVaadinServlet {
@@ -287,4 +297,129 @@ public class ApplicationRunnerServlet extends LegacyVaadinServlet {
return Logger.getLogger(ApplicationRunnerServlet.class.getName());
}
+ @Override
+ protected DeploymentConfiguration createDeploymentConfiguration(
+ Properties initParameters) {
+ // Get the original configuration from the super class
+ final DeploymentConfiguration originalConfiguration = super
+ .createDeploymentConfiguration(initParameters);
+
+ // And then create a proxy instance that delegates to the original
+ // configuration or a customized version
+ return (DeploymentConfiguration) Proxy.newProxyInstance(
+ DeploymentConfiguration.class.getClassLoader(),
+ new Class[] { DeploymentConfiguration.class },
+ new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method,
+ Object[] args) throws Throwable {
+ if (method.getDeclaringClass() == DeploymentConfiguration.class) {
+ // Find the configuration instance to delegate to
+ DeploymentConfiguration configuration = findDeploymentConfiguration(originalConfiguration);
+
+ return method.invoke(configuration, args);
+ } else {
+ return method.invoke(proxy, args);
+ }
+ }
+ });
+ }
+
+ private DeploymentConfiguration findDeploymentConfiguration(
+ DeploymentConfiguration originalConfiguration) throws Exception {
+ // First level of cache
+ DeploymentConfiguration configuration = CurrentInstance
+ .get(DeploymentConfiguration.class);
+
+ if (configuration == null) {
+ // Not in cache, try to find a VaadinSession to get it from
+ VaadinSession session = VaadinSession.getCurrent();
+
+ if (session == null) {
+ /*
+ * There's no current session, request or response when serving
+ * static resources, but there's still the current request
+ * maintained by AppliationRunnerServlet, and there's most
+ * likely also a HttpSession containing a VaadinSession for that
+ * request.
+ */
+
+ HttpServletRequest currentRequest = request.get();
+ if (currentRequest != null) {
+ HttpSession httpSession = currentRequest.getSession(false);
+ if (httpSession != null) {
+ Map<Class<?>, CurrentInstance> oldCurrent = CurrentInstance
+ .setCurrent((VaadinSession) null);
+ try {
+ session = getService().findVaadinSession(
+ new VaadinServletRequest(currentRequest,
+ getService()));
+ } finally {
+ /*
+ * Clear some state set by findVaadinSession to
+ * avoid accidentally depending on it when coding on
+ * e.g. static request handling.
+ */
+ CurrentInstance.restoreInstances(oldCurrent);
+ currentRequest.removeAttribute(VaadinSession.class
+ .getName());
+ }
+ }
+ }
+ }
+
+ if (session != null) {
+ String name = ApplicationRunnerServlet.class.getName()
+ + ".deploymentConfiguration";
+ try {
+ session.lock();
+ configuration = (DeploymentConfiguration) session
+ .getAttribute(name);
+
+ if (configuration == null) {
+ Class<?> classToRun;
+ try {
+ classToRun = getClassToRun();
+ } catch (ClassNotFoundException e) {
+ /*
+ * This happens e.g. if the UI class defined in the
+ * URL is not found or if this servlet just serves
+ * static resources while there's some other servlet
+ * that serves the UI (e.g. when using /run-push/).
+ */
+ return originalConfiguration;
+ }
+
+ CustomDeploymentConfiguration customDeploymentConfiguration = classToRun
+ .getAnnotation(CustomDeploymentConfiguration.class);
+ if (customDeploymentConfiguration != null) {
+ Properties initParameters = new Properties(
+ originalConfiguration.getInitParameters());
+
+ for (Conf entry : customDeploymentConfiguration
+ .value()) {
+ initParameters.put(entry.name(), entry.value());
+ }
+
+ configuration = new DefaultDeploymentConfiguration(
+ getClass(), initParameters);
+ } else {
+ configuration = originalConfiguration;
+ }
+
+ session.setAttribute(name, configuration);
+ }
+ } finally {
+ session.unlock();
+ }
+
+ CurrentInstance.set(DeploymentConfiguration.class,
+ configuration);
+
+ } else {
+ configuration = originalConfiguration;
+ }
+ }
+ return configuration;
+ }
}
diff --git a/uitest/src/com/vaadin/launcher/CustomDeploymentConfiguration.java b/uitest/src/com/vaadin/launcher/CustomDeploymentConfiguration.java
new file mode 100644
index 0000000000..da903c13e0
--- /dev/null
+++ b/uitest/src/com/vaadin/launcher/CustomDeploymentConfiguration.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2014 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.launcher;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(value = ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CustomDeploymentConfiguration {
+
+ @Target(value = ElementType.TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface Conf {
+ public String name();
+
+ public String value();
+ }
+
+ public CustomDeploymentConfiguration.Conf[] value();
+}
diff --git a/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConf.java b/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConf.java
new file mode 100644
index 0000000000..8ae7715a77
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConf.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2014 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.tests.applicationservlet;
+
+import com.vaadin.launcher.ApplicationRunnerServlet;
+import com.vaadin.launcher.CustomDeploymentConfiguration;
+import com.vaadin.launcher.CustomDeploymentConfiguration.Conf;
+import com.vaadin.server.DeploymentConfiguration;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Label;
+
+@CustomDeploymentConfiguration({
+ @Conf(name = "customParam", value = "customValue"),
+ @Conf(name = "resourceCacheTime", value = "3599") })
+public class CustomDeploymentConf extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ DeploymentConfiguration deploymentConfiguration = getSession()
+ .getService().getDeploymentConfiguration();
+ addComponent(new Label("Resource cache time: "
+ + deploymentConfiguration.getResourceCacheTime()));
+ addComponent(new Label("Custom config param: "
+ + deploymentConfiguration.getApplicationOrSystemProperty(
+ "customParam", null)));
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Demonstrates the @"
+ + CustomDeploymentConfiguration.class.getSimpleName()
+ + " feature that allows customizing the effective deployment configuration for test UIs run through "
+ + ApplicationRunnerServlet.class.getSimpleName() + ".";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(14215);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConfTest.java b/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConfTest.java
new file mode 100644
index 0000000000..e74eea6c55
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConfTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2014 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.tests.applicationservlet;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.testbench.elements.VerticalLayoutElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class CustomDeploymentConfTest extends MultiBrowserTest {
+ @Test
+ public void testCustomDeploymentConf() {
+ openTestURL();
+
+ LabelElement cacheTimeLabel = $$(VerticalLayoutElement.class)
+ .$$(VerticalLayoutElement.class).$$(LabelElement.class).first();
+
+ LabelElement customParamLabel = $$(VerticalLayoutElement.class)
+ .$$(VerticalLayoutElement.class).$$(LabelElement.class).get(1);
+
+ Assert.assertEquals("Resource cache time: 3599",
+ cacheTimeLabel.getText());
+ Assert.assertEquals("Custom config param: customValue",
+ customParamLabel.getText());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/button/ButtonTooltips.html b/uitest/src/com/vaadin/tests/components/button/ButtonTooltips.html
deleted file mode 100644
index 13fdf52c76..0000000000
--- a/uitest/src/com/vaadin/tests/components/button/ButtonTooltips.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head profile="http://selenium-ide.openqa.org/profiles/test-case">
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-<link rel="selenium.base" href="http://192.168.2.168:8888/" />
-<title>New Test</title>
-</head>
-<body>
-<table cellpadding="1" cellspacing="1" border="1">
-<thead>
-<tr><td rowspan="1" colspan="3">New Test</td></tr>
-</thead><tbody>
-<tr>
- <td>open</td>
- <td>/run/com.vaadin.tests.components.button.ButtonTooltips?restartApplication</td>
- <td></td>
-</tr>
-<tr>
- <td>showTooltip</td>
- <td>vaadin=runcomvaadintestscomponentsbuttonButtonTooltips::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
- <td>0,0</td>
-</tr>
-<tr>
- <td>showTooltip</td>
- <td>vaadin=runcomvaadintestscomponentsbuttonButtonTooltips::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td>
- <td>0,0</td>
-</tr>
-<tr>
- <td>screenCapture</td>
- <td></td>
- <td></td>
-</tr>
-
-</tbody></table>
-</body>
-</html>
diff --git a/uitest/src/com/vaadin/tests/components/table/MemoryLeakTable.java b/uitest/src/com/vaadin/tests/components/table/MemoryLeakTable.java
new file mode 100644
index 0000000000..1b76be3b72
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/MemoryLeakTable.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2014 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.tests.components.table;
+
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Table;
+
+/**
+ * Test UI Class for testing memory leak in table (#14159).
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class MemoryLeakTable extends AbstractTestUI {
+ Button btnAdd = new Button("Add rows");
+ Button btnRemove = new Button("Remove rows");
+ Button btnTenTimes = new Button("Do ten times");
+ Table tbl = new Table();
+ static final int COLS = 15;
+ static final int ROWS = 2000;
+
+ private void addRows() {
+ IndexedContainer idx = new IndexedContainer();
+ for (int i = 0; i < COLS; i++) {
+ idx.addContainerProperty("name " + i, String.class, "value");
+ }
+ for (int i = 0; i < ROWS; i++) {
+ idx.addItem("item" + i);
+ }
+ tbl.setContainerDataSource(idx);
+ addComponent(tbl);
+ }
+
+ private void removeRows() {
+ tbl.removeAllItems();
+ removeComponent(tbl);
+ }
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ btnAdd.addClickListener(new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ addRows();
+ }
+ });
+ btnRemove.addClickListener(new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ removeRows();
+ }
+ });
+ addComponent(btnAdd);
+ addComponent(btnRemove);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Generates table for memory leaking test";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14159;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/MemoryLeakTableTest.java b/uitest/src/com/vaadin/tests/components/table/MemoryLeakTableTest.java
new file mode 100644
index 0000000000..b4b8d93fbe
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/MemoryLeakTableTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2000-2014 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.tests.components.table;
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.TableElement;
+import com.vaadin.tests.tb3.AbstractTB3Test.RunLocally;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+import com.vaadin.tests.tb3.MultiBrowserTest.Browser;
+
+/**
+ * Test case creating and deleting table component in a loop, testing memory
+ * lead in Table component. This test should not be used in auto testing.
+ *
+ * To test memory consuption. Run test in debug mode. Take memory snapshot in
+ * Profiler in browser before and after the loop. Compare memory consuption.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@RunLocally(Browser.CHROME)
+public class MemoryLeakTableTest extends MultiBrowserTest {
+
+ /**
+ *
+ */
+ private static final int ITERATIONS = 200;
+
+ // To run locally in chrome download ChromeDriver for TB3
+ // Set path to the chrome driver. In
+ // ./work/eclipse-run-selected-test.properties add line
+ // chrome.driver.path=path_to_driver
+
+ // Test is marked as ignore to exclude it from auto testing
+ @Test
+ @Ignore
+ public void memoryTest() throws IOException {
+ // Set breakoint and look memory consuption in Profiler
+ // Mozilla Firefox doesn't provide memory usage profiler, use chrome.
+
+ openTestURL();
+
+ ButtonElement btnAdd = $(ButtonElement.class).get(0);
+
+ for (int i = 0; i < ITERATIONS; i++) {
+ btnAdd.click();
+ ButtonElement btnDel = $(ButtonElement.class).get(1);
+ TableElement tbl = $(TableElement.class).get(0);
+ Random rand = new Random();
+ int scrollValue = rand.nextInt(1500);
+ scrollTable(tbl, scrollValue);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ btnDel.click();
+ }
+ // Set breakoint and look memory consuption in Profiler
+ btnAdd = $(ButtonElement.class).get(0);
+ }
+
+ // Scrolls table element
+ // Method scroll in TalbeElement class has a bug
+ //
+ private void scrollTable(TableElement tbl, int value) {
+ WebElement actualElement = tbl.findElement(By
+ .className("v-table-body-wrapper"));
+ JavascriptExecutor js = tbl.getCommandExecutor();
+ js.executeScript("arguments[0].scrollTop = " + value, actualElement);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/TableTooManyColumns.java b/uitest/src/com/vaadin/tests/components/table/TableTooManyColumns.java
new file mode 100644
index 0000000000..2d27636420
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/TableTooManyColumns.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2014 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.tests.components.table;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Table.ColumnGenerator;
+
+public class TableTooManyColumns extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Table table = new Table();
+
+ table.setColumnCollapsingAllowed(true);
+
+ for (int i = 0; i < 91; i++) {
+ table.addGeneratedColumn("COLUMN " + i, new ColumnGenerator() {
+
+ @Override
+ public Object generateCell(Table source, Object itemId,
+ Object columnId) {
+ return columnId;
+ }
+ });
+ }
+
+ addComponent(table);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription()
+ */
+ @Override
+ protected String getTestDescription() {
+ return "Table column drop down becomes too large to fit the screen.";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber()
+ */
+ @Override
+ protected Integer getTicketNumber() {
+ return 14156;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/TableTooManyColumnsTest.java b/uitest/src/com/vaadin/tests/components/table/TableTooManyColumnsTest.java
new file mode 100644
index 0000000000..2244365e00
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/TableTooManyColumnsTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2014 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.tests.components.table;
+
+import java.io.IOException;
+
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.commands.TestBenchElementCommands;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class TableTooManyColumnsTest extends MultiBrowserTest {
+
+ @Test
+ public void testDropdownTable() throws IOException {
+ openTestURL();
+
+ WebElement element = findElement(By
+ .className("v-table-column-selector"));
+
+ element.click();
+
+ WebElement menu = findElement(By.className("gwt-MenuBar-vertical"));
+
+ TestBenchElementCommands scrollable = testBenchElement(menu);
+ scrollable.scroll(3000);
+
+ compareScreen(getScreenshotBaseName());
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpace.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpace.java
new file mode 100644
index 0000000000..0105498f27
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpace.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2014 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.tests.components.tabsheet;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Panel;
+import com.vaadin.ui.TabSheet;
+
+/**
+ * Test to see if tabsheet navigation buttons render correctly in Chameleon
+ *
+ * @author Vaadin Ltd
+ */
+@Theme("chameleon")
+public class TabsheetNotEnoughHorizontalSpace extends AbstractTestUI {
+
+ private TabSheet tabsheet = new TabSheet();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.tests.components.AbstractTestUI#setup(com.vaadin.server.
+ * VaadinRequest)
+ */
+ @Override
+ protected void setup(VaadinRequest request) {
+ generateTabs();
+ tabsheet.setSizeFull();
+ addComponent(tabsheet);
+
+ }
+
+ private void generateTabs() {
+ tabsheet.removeAllComponents();
+ for (int i = 0; i < 100; ++i) {
+ tabsheet.addTab(new Panel(), "Tab" + i);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription()
+ */
+ @Override
+ protected String getTestDescription() {
+ return "Scroll-buttons should render correctly on all browsers";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber()
+ */
+ @Override
+ protected Integer getTicketNumber() {
+ return 12154;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpaceTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpaceTest.java
new file mode 100644
index 0000000000..990f545697
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpaceTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2014 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.tests.components.tabsheet;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.By;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * Tests that tabsheet's scroll button are rendered correctly in Chameleon
+ * theme.
+ *
+ * Ticket #12154
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class TabsheetNotEnoughHorizontalSpaceTest extends MultiBrowserTest {
+
+ @Test
+ public void testThatTabScrollButtonsAreRenderedCorrectly()
+ throws IOException {
+ openTestURL();
+
+ driver.findElement(By.className("v-tabsheet-scrollerPrev-disabled"));
+ driver.findElement(By.className("v-tabsheet-scrollerNext"));
+
+ compareScreen(getScreenshotBaseName());
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/upload/TestFileUploadTest.java b/uitest/src/com/vaadin/tests/components/upload/TestFileUploadTest.java
index 1887427a72..ae966a5b07 100644
--- a/uitest/src/com/vaadin/tests/components/upload/TestFileUploadTest.java
+++ b/uitest/src/com/vaadin/tests/components/upload/TestFileUploadTest.java
@@ -109,7 +109,7 @@ public class TestFileUploadTest extends MultiBrowserTest {
}
private void setLocalFileDetector(WebElement element) throws Exception {
- if (getClass().isAnnotationPresent(RunLocally.class)) {
+ if (getRunLocallyBrowser() != null) {
return;
}
diff --git a/uitest/src/com/vaadin/tests/serialization/SerializerTest.java b/uitest/src/com/vaadin/tests/serialization/SerializerTest.java
index 1c18fb1912..333964e9bf 100644
--- a/uitest/src/com/vaadin/tests/serialization/SerializerTest.java
+++ b/uitest/src/com/vaadin/tests/serialization/SerializerTest.java
@@ -93,13 +93,13 @@ public class SerializerTest extends AbstractTestUI {
rpc.sendInt(Integer.MAX_VALUE, Integer.valueOf(0), new int[] { 5, 7 });
state.intValue = Integer.MAX_VALUE;
- state.intObjectValue = Integer.valueOf(0);
+ state.intObjectValue = Integer.valueOf(42);
state.intArray = new int[] { 5, 7 };
rpc.sendLong(577431841358l, Long.valueOf(0), new long[] {
-57841235865l, 57 });
- state.longValue = 577431841358l;
- state.longObjectValue = Long.valueOf(0);
+ state.longValue = 577431841359l;
+ state.longObjectValue = Long.valueOf(577431841360l);
state.longArray = new long[] { -57841235865l, 57 };
rpc.sendFloat(3.14159f, Float.valueOf(Math.nextUp(1)), new float[] {
@@ -111,7 +111,7 @@ public class SerializerTest extends AbstractTestUI {
rpc.sendDouble(Math.PI, Double.valueOf(-Math.E), new double[] {
Double.MAX_VALUE, Double.MIN_VALUE });
state.doubleValue = Math.PI;
- state.doubleValue = Double.valueOf(-Math.E);
+ state.doubleObjectValue = Double.valueOf(-Math.E);
state.doubleArray = new double[] { Double.MAX_VALUE, Double.MIN_VALUE };
rpc.sendString("This is a tesing string ‡");
diff --git a/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java b/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java
index 5ca1e9ce6a..47bb212347 100644
--- a/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java
+++ b/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java
@@ -77,5 +77,36 @@ public class SerializerTestTest extends MultiBrowserTest {
"sendBoolean: false, false, [false, false, true, false, true, true]",
getLogRow(logRow++));
Assert.assertEquals("sendBeanSubclass: 43", getLogRow(logRow++));
+ Assert.assertEquals(
+ "state.doubleArray: [1.7976931348623157e+308, 5e-324]",
+ getLogRow(logRow++));
+ Assert.assertEquals("state.doubleObjectValue: -2.718281828459045",
+ getLogRow(logRow++));
+ Assert.assertEquals("state.doubleValue: 3.141592653589793",
+ getLogRow(logRow++));
+ Assert.assertEquals("state.floatArray: [57, 0, -12]",
+ getLogRow(logRow++));
+ Assert.assertEquals("state.floatObjectValue: 1.0000001",
+ getLogRow(logRow++));
+ Assert.assertEquals("state.floatValue: 3.14159", getLogRow(logRow++));
+ Assert.assertEquals("state.longArray: [-57841235865, 57]",
+ getLogRow(logRow++));
+ Assert.assertEquals("state.longObjectValue: 577431841360",
+ getLogRow(logRow++));
+ Assert.assertEquals("state.longValue: 577431841359",
+ getLogRow(logRow++));
+ Assert.assertEquals("state.intArray: [5, 7]", getLogRow(logRow++));
+ Assert.assertEquals("state.intObjectValue: 42", getLogRow(logRow++));
+ Assert.assertEquals("state.intValue: 2147483647", getLogRow(logRow++));
+ Assert.assertEquals("state.charArray: aBcD", getLogRow(logRow++));
+ Assert.assertEquals("state.charObjectValue: å", getLogRow(logRow++));
+ Assert.assertEquals("state.charValue: ∫", getLogRow(logRow++));
+ Assert.assertEquals("state.byteArray: [3, 1, 2]", getLogRow(logRow++));
+ Assert.assertEquals("state.byteObjectValue: -12", getLogRow(logRow++));
+ Assert.assertEquals("state.byteValue: 5", getLogRow(logRow++));
+ Assert.assertEquals(
+ "state.booleanArray: [true, true, false, true, false, false]",
+ getLogRow(logRow++));
+
}
}
diff --git a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
index fa704d7b0b..8dd10216d2 100644
--- a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
+++ b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
@@ -120,9 +120,13 @@ public abstract class AbstractTB3Test extends TestBenchTestCase {
protected void setupDriver() throws Exception {
DesiredCapabilities capabilities;
- RunLocally runLocally = getClass().getAnnotation(RunLocally.class);
- if (runLocally != null) {
- capabilities = runLocally.value().getDesiredCapabilities();
+ Browser runLocallyBrowser = getRunLocallyBrowser();
+ if (runLocallyBrowser != null) {
+ if (System.getenv().containsKey("TEAMCITY_VERSION")) {
+ throw new RuntimeException(
+ "@RunLocally is not supported for tests run on the build server");
+ }
+ capabilities = runLocallyBrowser.getDesiredCapabilities();
setupLocalDriver(capabilities);
} else {
capabilities = getDesiredCapabilities();
@@ -152,6 +156,15 @@ public abstract class AbstractTB3Test extends TestBenchTestCase {
}
+ protected Browser getRunLocallyBrowser() {
+ RunLocally runLocally = getClass().getAnnotation(RunLocally.class);
+ if (runLocally != null) {
+ return runLocally.value();
+ } else {
+ return null;
+ }
+ }
+
protected WebElement getTooltipElement() {
return getDriver().findElement(com.vaadin.testbench.By.className("v-tooltip-text"));
}
diff --git a/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java b/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java
index 305caf1cb5..15ca97f701 100644
--- a/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java
+++ b/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
+import java.util.Arrays;
import java.util.Enumeration;
import java.util.Properties;
@@ -34,6 +35,7 @@ import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.safari.SafariDriver;
import com.vaadin.testbench.TestBench;
+import com.vaadin.tests.tb3.MultiBrowserTest.Browser;
/**
* Provides values for parameters which depend on where the test is run.
@@ -43,14 +45,16 @@ import com.vaadin.testbench.TestBench;
* @author Vaadin Ltd
*/
public abstract class PrivateTB3Configuration extends ScreenshotTB3Test {
+ private static final String RUN_LOCALLY_PROPERTY = "com.vaadin.testbench.runLocally";
private static final String HOSTNAME_PROPERTY = "com.vaadin.testbench.deployment.hostname";
private static final String PORT_PROPERTY = "com.vaadin.testbench.deployment.port";
private static final Properties properties = new Properties();
+ private static final File propertiesFile = new File("work",
+ "eclipse-run-selected-test.properties");
static {
- File file = new File("work", "eclipse-run-selected-test.properties");
- if (file.exists()) {
+ if (propertiesFile.exists()) {
try {
- properties.load(new FileInputStream(file));
+ properties.load(new FileInputStream(propertiesFile));
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -66,6 +70,16 @@ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test {
return property;
}
+ private static String getSource(String propertyName) {
+ if (properties.containsKey(propertyName)) {
+ return propertiesFile.getAbsolutePath();
+ } else if (System.getProperty(propertyName) != null) {
+ return "System.getProperty()";
+ } else {
+ return null;
+ }
+ }
+
@Override
protected String getScreenshotDirectory() {
String screenshotDirectory = getProperty("com.vaadin.testbench.screenshot.directory");
@@ -83,7 +97,7 @@ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test {
@Override
protected String getDeploymentHostname() {
- if (getClass().getAnnotation(RunLocally.class) != null) {
+ if (getRunLocallyBrowser() != null) {
return "localhost";
}
return getConfiguredDeploymentHostname();
@@ -180,8 +194,21 @@ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test {
driver = new FirefoxDriver();
}
} else if (BrowserUtil.isChrome(desiredCapabilities)) {
- System.setProperty("webdriver.chrome.driver",
- getProperty("chrome.driver.path"));
+ String propertyName = "chrome.driver.path";
+ String chromeDriverPath = getProperty(propertyName);
+ if (chromeDriverPath == null) {
+ throw new RuntimeException(
+ "You need to install ChromeDriver to use @"
+ + RunLocally.class.getSimpleName()
+ + " with Chrome."
+ + "\nFirst install it from https://code.google.com/p/selenium/wiki/ChromeDriver."
+ + "\nThen update "
+ + propertiesFile.getAbsolutePath()
+ + " to define a property named "
+ + propertyName
+ + " containing the path of your local ChromeDriver installation.");
+ }
+ System.setProperty("webdriver.chrome.driver", chromeDriverPath);
driver = new ChromeDriver();
} else if (BrowserUtil.isSafari(desiredCapabilities)) {
driver = new SafariDriver();
@@ -196,4 +223,28 @@ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test {
setDriver(TestBench.createDriver(driver));
setDesiredCapabilities(desiredCapabilities);
}
+
+ @Override
+ protected Browser getRunLocallyBrowser() {
+ Browser runLocallyBrowser = super.getRunLocallyBrowser();
+ if (runLocallyBrowser != null) {
+ // Always use annotation value if present
+ return runLocallyBrowser;
+ }
+
+ String runLocallyValue = getProperty(RUN_LOCALLY_PROPERTY);
+ if (runLocallyValue == null || runLocallyValue.trim().isEmpty()) {
+ return null;
+ }
+
+ String browserName = runLocallyValue.trim().toUpperCase();
+ try {
+ return Browser.valueOf(browserName);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException("Invalid " + RUN_LOCALLY_PROPERTY
+ + " property from " + getSource(RUN_LOCALLY_PROPERTY)
+ + ": " + runLocallyValue + ". Expected one of "
+ + Arrays.toString(Browser.values()));
+ }
+ }
}
diff --git a/uitest/src/com/vaadin/tests/tb3/TB3Runner.java b/uitest/src/com/vaadin/tests/tb3/TB3Runner.java
index 4d29e479e2..5b5a6dcf39 100644
--- a/uitest/src/com/vaadin/tests/tb3/TB3Runner.java
+++ b/uitest/src/com/vaadin/tests/tb3/TB3Runner.java
@@ -37,7 +37,7 @@ import org.openqa.selenium.remote.DesiredCapabilities;
import com.vaadin.tests.annotations.TestCategory;
import com.vaadin.tests.tb3.AbstractTB3Test.BrowserUtil;
-import com.vaadin.tests.tb3.AbstractTB3Test.RunLocally;
+import com.vaadin.tests.tb3.MultiBrowserTest.Browser;
/**
* This runner is loosely based on FactoryTestRunner by Ted Young
@@ -185,17 +185,17 @@ public class TB3Runner extends BlockJUnit4ClassRunner {
/*
* Returns a list of desired browser capabilities according to browsers
* defined in the test class, filtered by possible filter parameters. Use
- * {@code @RunLocally} annotation to override all capabilities.
+ * {@code @RunLocally} annotation or com.vaadin.testbench.runLocally
+ * property to override all capabilities.
*/
private Collection<DesiredCapabilities> getDesiredCapabilities(
AbstractTB3Test testClassInstance) {
Collection<DesiredCapabilities> desiredCapabilites = getFilteredCapabilities(testClassInstance);
- if (isRunLocally(testClassInstance)) {
+ Browser runLocallyBrowser = testClassInstance.getRunLocallyBrowser();
+ if (runLocallyBrowser != null) {
desiredCapabilites = new ArrayList<DesiredCapabilities>();
- desiredCapabilites.add(testClassInstance.getClass()
- .getAnnotation(RunLocally.class).value()
- .getDesiredCapabilities());
+ desiredCapabilites.add(runLocallyBrowser.getDesiredCapabilities());
}
return desiredCapabilites;
@@ -237,10 +237,6 @@ public class TB3Runner extends BlockJUnit4ClassRunner {
return filteredCapabilities;
}
- private boolean isRunLocally(AbstractTB3Test testClassInstance) {
- return testClassInstance.getClass().getAnnotation(RunLocally.class) != null;
- }
-
private AbstractTB3Test getTestClassInstance()
throws InstantiationException, IllegalAccessException,
InvocationTargetException {
diff --git a/uitest/src/com/vaadin/tests/tooltip/ButtonTooltips.java b/uitest/src/com/vaadin/tests/tooltip/ButtonTooltips.java
index d212a13058..c341aa689b 100644
--- a/uitest/src/com/vaadin/tests/tooltip/ButtonTooltips.java
+++ b/uitest/src/com/vaadin/tests/tooltip/ButtonTooltips.java
@@ -1,14 +1,18 @@
package com.vaadin.tests.tooltip;
-import com.vaadin.tests.components.TestBase;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.VerticalLayout;
-public class ButtonTooltips extends TestBase {
+public class ButtonTooltips extends AbstractTestUI {
+
+ public static final String shortDescription = "Another";
+ public static final String longDescription = "long descidescidescpription";
@Override
- protected String getDescription() {
+ protected String getTestDescription() {
return "Button tooltip's size gets messed up if moving from one tooltip to another before a timer expires.";
}
@@ -18,12 +22,12 @@ public class ButtonTooltips extends TestBase {
}
@Override
- protected void setup() {
+ protected void setup(VaadinRequest request) {
VerticalLayout vl = new VerticalLayout();
Button button = new Button("One");
- button.setDescription("long descidescidescpription");
+ button.setDescription(longDescription);
Button button2 = new Button("Two");
- button2.setDescription("Another");
+ button2.setDescription(shortDescription);
vl.addComponent(button);
vl.addComponent(button2);
vl.setComponentAlignment(button, Alignment.TOP_RIGHT);
diff --git a/uitest/src/com/vaadin/tests/tooltip/ButtonTooltipsTest.java b/uitest/src/com/vaadin/tests/tooltip/ButtonTooltipsTest.java
index d64dd900a7..08436b1332 100644
--- a/uitest/src/com/vaadin/tests/tooltip/ButtonTooltipsTest.java
+++ b/uitest/src/com/vaadin/tests/tooltip/ButtonTooltipsTest.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 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
@@ -26,7 +26,7 @@ import com.vaadin.tests.tb3.TooltipTest;
/**
* Tests that tooltip sizes do not change when moving between adjacent elements
- *
+ *
* @author Vaadin Ltd
*/
public class ButtonTooltipsTest extends TooltipTest {
@@ -38,12 +38,12 @@ public class ButtonTooltipsTest extends TooltipTest {
WebElement buttonOne = $(ButtonElement.class).caption("One").first();
WebElement buttonTwo = $(ButtonElement.class).caption("Two").first();
- checkTooltip(buttonOne, "long descidescidescpription");
+ checkTooltip(buttonOne, ButtonTooltips.longDescription);
int originalWidth = getTooltipElement().getSize().getWidth();
int originalHeight = getTooltipElement().getSize().getHeight();
clearTooltip();
- checkTooltip(buttonTwo, "Another");
+ checkTooltip(buttonTwo, ButtonTooltips.shortDescription);
moveMouseTo(buttonOne, 5, 5);
sleep(100);
assertThat(getTooltipElement().getSize().getWidth(), is(originalWidth));
diff --git a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml
index ac93efd7d4..d23903f9db 100644
--- a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml
+++ b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml
@@ -15,4 +15,9 @@
<when-type-is class="com.vaadin.client.communication.PushConnection" />
</replace-with>
+ <replace-with
+ class="com.vaadin.tests.widgetset.client.MockApplicationConnection">
+ <when-type-is class="com.vaadin.client.ApplicationConnection" />
+ </replace-with>
+
</module>
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java b/uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java
new file mode 100644
index 0000000000..4ee5b71387
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.client;
+
+import java.util.Date;
+import java.util.logging.Logger;
+
+import com.google.gwt.json.client.JSONObject;
+import com.google.gwt.json.client.JSONValue;
+import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.ValueMap;
+import com.vaadin.shared.ApplicationConstants;
+import com.vaadin.tests.widgetset.server.csrf.ui.CsrfTokenDisabled;
+
+/**
+ * Mock ApplicationConnection for several issues where we need to hack it.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class MockApplicationConnection extends ApplicationConnection {
+
+ private static final Logger LOGGER = Logger
+ .getLogger(MockApplicationConnection.class.getName());
+
+ // The last token received from the server.
+ private String lastCsrfTokenReceiver;
+
+ // The last token sent to the server.
+ private String lastCsrfTokenSent;
+
+ /**
+ * Provide the last token received from the server. <br/>
+ * We added this to test the change done on CSRF token.
+ *
+ * @see CsrfTokenDisabled
+ */
+ public String getLastCsrfTokenReceiver() {
+ return lastCsrfTokenReceiver;
+ }
+
+ /**
+ * Provide the last token sent to the server. <br/>
+ * We added this to test the change done on CSRF token.
+ *
+ * @see CsrfTokenDisabled
+ */
+ public String getLastCsrfTokenSent() {
+ return lastCsrfTokenSent;
+ }
+
+ @Override
+ protected void handleUIDLMessage(Date start, String jsonText, ValueMap json) {
+ lastCsrfTokenReceiver = json
+ .getString(ApplicationConstants.UIDL_SECURITY_TOKEN_ID);
+
+ super.handleUIDLMessage(start, jsonText, json);
+ }
+
+ @Override
+ protected void doUidlRequest(String uri, JSONObject payload) {
+ JSONValue jsonValue = payload.get(ApplicationConstants.CSRF_TOKEN);
+ lastCsrfTokenSent = jsonValue != null ? jsonValue.toString() : null;
+
+ super.doUidlRequest(uri, payload);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java
index 0ef4b664ac..7758cdc2ac 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java
@@ -284,11 +284,12 @@ public class SerializerTestConnector extends AbstractExtensionConnector {
public void onStateChanged(StateChangeEvent stateChangeEvent) {
rpc.log("state.booleanValue: " + getState().booleanValue);
rpc.log("state.booleanObjectValue: " + getState().booleanObjectValue);
- rpc.log("state.booleanArray: " + getState().booleanArray);
+ rpc.log("state.booleanArray: "
+ + Arrays.toString(getState().booleanArray));
rpc.log("state.byteValue: " + getState().byteValue);
rpc.log("state.byteObjectValue: " + getState().byteObjectValue);
- rpc.log("state.byteArray: " + getState().byteArray);
+ rpc.log("state.byteArray: " + Arrays.toString(getState().byteArray));
rpc.log("state.charValue: " + getState().charValue);
rpc.log("state.charObjectValue: " + getState().charObjectValue);
@@ -296,19 +297,19 @@ public class SerializerTestConnector extends AbstractExtensionConnector {
rpc.log("state.intValue: " + getState().intValue);
rpc.log("state.intObjectValue: " + getState().intObjectValue);
- rpc.log("state.intArray: " + getState().intArray);
+ rpc.log("state.intArray: " + Arrays.toString(getState().intArray));
rpc.log("state.longValue: " + getState().longValue);
rpc.log("state.longObjectValue: " + getState().longObjectValue);
- rpc.log("state.longArray: " + getState().longArray);
+ rpc.log("state.longArray: " + Arrays.toString(getState().longArray));
rpc.log("state.floatValue: " + getState().floatValue);
rpc.log("state.floatObjectValue: " + getState().floatObjectValue);
- rpc.log("state.floatArray: " + getState().floatArray);
+ rpc.log("state.floatArray: " + Arrays.toString(getState().floatArray));
rpc.log("state.doubleValue: " + getState().doubleValue);
rpc.log("state.doubleObjectValue: " + getState().doubleObjectValue);
- rpc.log("state.doubleArray: " + getState().doubleArray);
+ rpc.log("state.doubleArray: " + Arrays.toString(getState().doubleArray));
/*
* TODO public double doubleValue; public Double DoubleValue; public
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/csrf/CsrfButtonConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/csrf/CsrfButtonConnector.java
new file mode 100644
index 0000000000..cf24ed6921
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/csrf/CsrfButtonConnector.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.client.csrf;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.google.gwt.core.shared.GWT;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.vaadin.client.ui.AbstractComponentConnector;
+import com.vaadin.client.ui.VButton;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.tests.widgetset.client.MockApplicationConnection;
+import com.vaadin.tests.widgetset.server.csrf.CsrfButton;
+
+/**
+ * Dummy connector to test our CSRF bug. See #14111.
+ *
+ * @author Vaadin Ltd
+ */
+@SuppressWarnings("serial")
+@Connect(CsrfButton.class)
+public class CsrfButtonConnector extends AbstractComponentConnector {
+
+ static Logger logger = Logger
+ .getLogger(CsrfButtonConnector.class.getName());
+ static {
+ logger.setLevel(Level.ALL);
+ }
+
+ @Override
+ public VButton getWidget() {
+ return (VButton) super.getWidget();
+ }
+
+ @Override
+ protected VButton createWidget() {
+ return GWT.create(VButton.class);
+ }
+
+ public final static String ID = "CsrfButton";
+
+ @Override
+ public void init() {
+ super.init();
+
+ getWidget().getElement().setId(ID);
+ getWidget().setText(csrfTokenInfo());
+ getWidget().addClickHandler(new ClickHandler() {
+
+ @Override
+ public void onClick(ClickEvent event) {
+ getWidget().setText(csrfTokenInfo());
+ }
+ });
+ }
+
+ private String csrfTokenInfo() {
+ return getMockConnection().getCsrfToken() + ", "
+ + getMockConnection().getLastCsrfTokenReceiver() + ", "
+ + getMockConnection().getLastCsrfTokenSent();
+ }
+
+ private MockApplicationConnection getMockConnection() {
+ return (MockApplicationConnection) getConnection();
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/CsrfButton.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/CsrfButton.java
new file mode 100644
index 0000000000..567127927d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/CsrfButton.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.server.csrf;
+
+import com.vaadin.ui.AbstractComponent;
+
+/**
+ * Dummy client connector to link with the client functionality if the
+ * CsrfToken.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@SuppressWarnings("serial")
+public class CsrfButton extends AbstractComponent {
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUI.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUI.java
new file mode 100644
index 0000000000..f8f1754385
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUI.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.server.csrf.ui;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.server.csrf.CsrfButton;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Label;
+
+/**
+ * Abstract UI to test the CSRF token issue as reported in (#14111)
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@SuppressWarnings("serial")
+@Widgetset(TestingWidgetSet.NAME)
+public abstract class AbstractCsrfTokenUI extends AbstractTestUI {
+
+ public static final String PRESS_ID = "PressMe";
+
+ @Override
+ protected void setup(VaadinRequest request) {
+
+ addComponent(new Label("The button's text is the client token:"));
+ addComponent(new CsrfButton());
+ addComponent(new Label("This one is from the server"));
+ addComponent(new Label(getSession().getCsrfToken()));
+ Button pressMe = new Button("Click me to send a request");
+ pressMe.setId(PRESS_ID);
+ addComponent(pressMe);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Remove csrfToken from the request if security protection is disabled.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14111;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUITest.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUITest.java
new file mode 100644
index 0000000000..614eaa063e
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUITest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.server.csrf.ui;
+
+import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.support.ui.ExpectedCondition;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+import com.vaadin.tests.widgetset.client.csrf.CsrfButtonConnector;
+
+public abstract class AbstractCsrfTokenUITest extends MultiBrowserTest {
+
+ static final Logger LOGGER = Logger.getLogger(AbstractCsrfTokenUITest.class
+ .getName());
+
+ @Test
+ public void testTokens() {
+ openTestURL();
+
+ final By debugButton = By.id(CsrfButtonConnector.ID);
+
+ final String debugMessage1 = getDriver().findElement(debugButton)
+ .getText();
+
+ getDriver().findElement(By.id(CsrfTokenDisabled.PRESS_ID)).click();
+
+ waitUntil(new ExpectedCondition<Boolean>() {
+
+ @Override
+ public Boolean apply(WebDriver input) {
+ getDriver().findElement(debugButton).click();
+ String debugMessage2 = input.findElement(debugButton).getText();
+
+ LOGGER.log(Level.INFO, "1: " + debugMessage1);
+ LOGGER.log(Level.INFO, "2: " + debugMessage2);
+
+ if (!debugMessage1.equals(debugMessage2)) {
+
+ compareMessage(split(debugMessage1), split(debugMessage2));
+
+ LOGGER.log(Level.INFO, "DONE");
+
+ return true;
+
+ } else {
+ return false;
+ }
+ }
+ });
+ }
+
+ private TokenGroup split(String debugMessage) {
+ StringTokenizer tokenizer = new StringTokenizer(debugMessage, ", \"");
+
+ return new TokenGroup(tokenizer.nextToken(), tokenizer.nextToken(),
+ tokenizer.nextToken());
+ }
+
+ /*
+ * Just implement this.
+ */
+ protected abstract boolean compareMessage(TokenGroup tokenGroup1,
+ TokenGroup tokenGroup2);
+
+ boolean isNullOrUndefined(String value) {
+ return isNull(value) || isUndefined(value);
+ }
+
+ boolean isUndefined(String value) {
+ return value.equals("undefined");
+ }
+
+ boolean isNull(String value) {
+ return value.equals("null");
+ }
+
+ /*
+ * Wrapps all tokens from the client app.
+ */
+ static class TokenGroup {
+
+ public final String clientToken;
+
+ public final String tokenReceivedFromServer;
+
+ public final String tokenSentToServer;
+
+ public TokenGroup(String clientToken, String tokenReceivedFromServer,
+ String tokenSentToServer) {
+ this.clientToken = clientToken;
+ this.tokenReceivedFromServer = tokenReceivedFromServer;
+ this.tokenSentToServer = tokenSentToServer;
+ }
+
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabled.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabled.java
new file mode 100644
index 0000000000..6283285b40
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabled.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.server.csrf.ui;
+
+import com.vaadin.launcher.CustomDeploymentConfiguration;
+import com.vaadin.launcher.CustomDeploymentConfiguration.Conf;
+
+/**
+ * When the disable-xsrf-protection is true csrfToken is not present anymore
+ * with the requests.<br/>
+ * This is useful mostly when the client is not Vaadin and so it will not push
+ * the parameter anyway. So now the server knows how to deal the issue if the
+ * csrfToken is not present.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@SuppressWarnings("serial")
+@CustomDeploymentConfiguration({ @Conf(name = "disable-xsrf-protection", value = "true") })
+public class CsrfTokenDisabled extends AbstractCsrfTokenUI {
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabledTest.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabledTest.java
new file mode 100644
index 0000000000..504425fead
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabledTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.server.csrf.ui;
+
+import com.vaadin.shared.ApplicationConstants;
+
+/**
+ * Test the CSRF Token issue.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class CsrfTokenDisabledTest extends AbstractCsrfTokenUITest {
+
+ @Override
+ protected boolean compareMessage(TokenGroup tokenGroup1,
+ TokenGroup tokenGroup2) {
+
+ return tokenGroup1.clientToken
+ .equals(ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE)
+ && isUndefined(tokenGroup1.tokenReceivedFromServer)
+ && isUndefined(tokenGroup1.tokenSentToServer)
+ && tokenGroup2.clientToken
+ .equals(ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE)
+ && isUndefined(tokenGroup2.tokenReceivedFromServer)
+ // This is it actually, no token sent to the server.
+ && isNull(tokenGroup2.tokenSentToServer);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabled.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabled.java
new file mode 100644
index 0000000000..cd02c6da77
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabled.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.server.csrf.ui;
+
+import com.vaadin.launcher.CustomDeploymentConfiguration;
+import com.vaadin.launcher.CustomDeploymentConfiguration.Conf;
+
+@SuppressWarnings("serial")
+@CustomDeploymentConfiguration({ @Conf(name = "disable-xsrf-protection", value = "false") })
+public class CsrfTokenEnabled extends AbstractCsrfTokenUI {
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabledTest.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabledTest.java
new file mode 100644
index 0000000000..1d51f1c372
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabledTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.server.csrf.ui;
+
+/**
+ * Test the CSRF Token issue.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class CsrfTokenEnabledTest extends AbstractCsrfTokenUITest {
+
+ @Override
+ protected boolean compareMessage(TokenGroup tokenGroup1,
+ TokenGroup tokenGroup2) {
+
+ return tokenGroup1.clientToken.equals(tokenGroup2.clientToken)
+ // Valid token received and set on the client
+ && tokenGroup1.clientToken
+ .equals(tokenGroup1.tokenReceivedFromServer)
+ // No token sent yet to the server.
+ && isUndefined(tokenGroup1.tokenSentToServer)
+ // Token is sent to the server.
+ && tokenGroup2.clientToken
+ .equals(tokenGroup2.tokenSentToServer)
+ // And no more token received from the server.
+ && isUndefined(tokenGroup2.tokenReceivedFromServer);
+ }
+
+}