summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2013-06-13 22:38:42 +0300
committerLeif Åstrand <leif@vaadin.com>2013-06-13 22:38:42 +0300
commitfaa693e33b24cb34e7811d94d5efe5605117af7f (patch)
treeb0b54d989d5ec83416b77f01c9e63398786dd8a5 /server
parentbe274254b5e6f4dd9386d4a3dd994ec834147e8b (diff)
parent54ffbdb70746743f4754416911f726f8d556b3ed (diff)
downloadvaadin-framework-faa693e33b24cb34e7811d94d5efe5605117af7f.tar.gz
vaadin-framework-faa693e33b24cb34e7811d94d5efe5605117af7f.zip
Merge changes from origin/7.1
da0a112 Merge changes from origin/7.0 6ba8938 Restore legacyPropertyToString value parsing logic (#11970) d5c0ffa Fix NPE when converting null values (#11895) 2aa3096 Avoid string casing problems (#11970) 0f107f3 Update widgetset template (#12053) eb64fda Add support for rem units (#11279) 5f66766 Using StringTokenizer instead of String.split() in AbstractComponent (#8759) 15b217d Handle push disconnections and reconnections more reliably (#11831, #11922) 47addab Adding isIOs and isAndroid to the WebBrowser wrapper around VBrowserDetails (#11168) 0aa5907 Do not write 404 as a response to all action/event requests (#12056) 55ebe13 Detach and attach when adding or removing the caption wrapper (#11708) 7830af2 Fix GridLayout resize after removing caption (#12011) 53e3a25 DebugWindow resize/move improved, fixes #11937 (also implements shift-resize and alt-move, improves bounds-check) f2b2ce9 Updated to Smartsprites 0.2.10 (#12069) 29c9b60 SimpleTree styling changed for #12058 da8382d DebugWindow now remembers open tab/section, InfoSection fixed to support being opened at once, for #12058 4f5bcef Info tab is now tab 1, hierarchy tab 2 a089743 Consistently recover from disconnections in IE (#12073) 59103a9 Always notify parent of enable state changes (#12062) 997e9a9 Fixed test issue apparently caused by three levels of classes 54ffbdb Add missing license header Change-Id: Ifba747964fa0d8265bb468ca555b84dadec9fa0a
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/data/util/converter/ConverterUtil.java59
-rw-r--r--server/src/com/vaadin/server/DefaultDeploymentConfiguration.java26
-rw-r--r--server/src/com/vaadin/server/Sizeable.java4
-rw-r--r--server/src/com/vaadin/server/VaadinPortletResponse.java8
-rw-r--r--server/src/com/vaadin/server/VaadinPortletService.java2
-rw-r--r--server/src/com/vaadin/server/WebBrowser.java20
-rw-r--r--server/src/com/vaadin/server/communication/PortletStateAwareRequestHandler.java54
-rw-r--r--server/src/com/vaadin/server/communication/PushHandler.java30
-rw-r--r--server/src/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java31
-rw-r--r--server/src/com/vaadin/ui/AbstractComponent.java24
-rw-r--r--server/tests/src/com/vaadin/benchmarks/PerformanceTester8759.java52
-rw-r--r--server/tests/src/com/vaadin/server/MockUIContainingServlet.java16
-rw-r--r--server/tests/src/com/vaadin/server/VaadinServletConfigurationTest.java25
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/ComponentSizeParseTest.java61
14 files changed, 328 insertions, 84 deletions
diff --git a/server/src/com/vaadin/data/util/converter/ConverterUtil.java b/server/src/com/vaadin/data/util/converter/ConverterUtil.java
index 3c62a71b73..3457c16755 100644
--- a/server/src/com/vaadin/data/util/converter/ConverterUtil.java
+++ b/server/src/com/vaadin/data/util/converter/ConverterUtil.java
@@ -29,17 +29,17 @@ public class ConverterUtil implements Serializable {
* {@link VaadinSession#getCurrent()}.
*
* @param <PRESENTATIONTYPE>
- * The presentation type
+ * the presentation type
* @param <MODELTYPE>
- * The model type
+ * the model type
* @param presentationType
- * The presentation type
+ * the presentation type
* @param modelType
- * The model type
+ * the model type
* @param session
- * The session to use to find a ConverterFactory or null to use
+ * the session to use to find a ConverterFactory or null to use
* the current session
- * @return A Converter capable of converting between the given types or null
+ * @return a Converter capable of converting between the given types or null
* if no converter was found
*/
public static <PRESENTATIONTYPE, MODELTYPE> Converter<PRESENTATIONTYPE, MODELTYPE> getConverter(
@@ -62,22 +62,23 @@ public class ConverterUtil implements Serializable {
* Convert the given value from the data source type to the UI type.
*
* @param modelValue
- * The model value to convert
+ * the model value to convert
* @param presentationType
- * The type of the presentation value
+ * the type of the presentation value
* @param converter
- * The converter to (try to) use
+ * the converter to use
* @param locale
- * The locale to use for conversion
+ * the locale to use for conversion
* @param <PRESENTATIONTYPE>
- * Presentation type
+ * the presentation type
+ * @param <MODELTYPE>
+ * the model type
*
- * @return The converted value, compatible with the presentation type, or
+ * @return the converted value, compatible with the presentation type, or
* the original value if its type is compatible and no converter is
* set.
* @throws Converter.ConversionException
- * if there is no converter and the type is not compatible with
- * the model type.
+ * if there was a problem converting the value
*/
@SuppressWarnings("unchecked")
public static <PRESENTATIONTYPE, MODELTYPE> PRESENTATIONTYPE convertFromModel(
@@ -86,9 +87,14 @@ public class ConverterUtil implements Serializable {
Converter<PRESENTATIONTYPE, MODELTYPE> converter, Locale locale)
throws Converter.ConversionException {
if (converter != null) {
+ /*
+ * If there is a converter, always use it. It must convert or throw
+ * an exception.
+ */
PRESENTATIONTYPE presentation = converter.convertToPresentation(
modelValue, presentationType, locale);
- if (!presentationType.isInstance(presentation)) {
+ if (presentation != null
+ && !presentationType.isInstance(presentation)) {
throw new Converter.ConversionException(
"Converter returned an object of type "
+ presentation.getClass().getName()
@@ -99,6 +105,8 @@ public class ConverterUtil implements Serializable {
return presentation;
}
if (modelValue == null) {
+ // Null should always be passed through the converter but if there
+ // is no converter we can safely return null
return null;
}
@@ -115,14 +123,26 @@ public class ConverterUtil implements Serializable {
}
/**
- * @param <MODELTYPE>
- * @param <PRESENTATIONTYPE>
+ * Convert the given value from the presentation (UI) type to model (data
+ * source) type.
+ *
* @param presentationValue
+ * the presentation value to convert
* @param modelType
+ * the type of the model
* @param converter
+ * the converter to use
* @param locale
- * @return
+ * the locale to use for conversion
+ * @param <PRESENTATIONTYPE>
+ * the presentation type
+ * @param <MODELTYPE>
+ * the model type
+ *
+ * @return the converted value, compatible with the model type, or the
+ * original value if its type is compatible and no converter is set.
* @throws Converter.ConversionException
+ * if there was a problem converting the value
*/
public static <MODELTYPE, PRESENTATIONTYPE> MODELTYPE convertToModel(
PRESENTATIONTYPE presentationValue, Class<MODELTYPE> modelType,
@@ -135,7 +155,7 @@ public class ConverterUtil implements Serializable {
*/
MODELTYPE model = converter.convertToModel(presentationValue,
modelType, locale);
- if (!modelType.isInstance(model)) {
+ if (model != null && !modelType.isInstance(model)) {
throw new Converter.ConversionException(
"Converter returned an object of type "
+ model.getClass().getName()
@@ -143,7 +163,6 @@ public class ConverterUtil implements Serializable {
}
return model;
-
}
if (presentationValue == null) {
diff --git a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java
index a55c3231f3..993d60133b 100644
--- a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java
+++ b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java
@@ -86,17 +86,25 @@ public class DefaultDeploymentConfiguration implements DeploymentConfiguration {
}
private void checkLegacyPropertyToString() {
+ // Verify that the default value has not changed without also
+ // updating logic here
+ assert DEFAULT_LEGACY_PROPERTY_TO_STRING == LegacyProperyToStringMode.WARNING;
+
String param = getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING,
- DEFAULT_LEGACY_PROPERTY_TO_STRING.name().toLowerCase());
+ Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING, "warning");
- try {
- legacyPropertyToStringMode = LegacyProperyToStringMode
- .valueOf(param.toUpperCase());
- } catch (IllegalArgumentException e) {
- getLogger().log(Level.WARNING,
- Constants.WARNING_UNKNOWN_LEGACY_PROPERTY_TOSTRING_VALUE,
- param);
+ if ("true".equals(param)) {
+ legacyPropertyToStringMode = LegacyProperyToStringMode.ENABLED;
+ } else if ("false".equals(param)) {
+ legacyPropertyToStringMode = LegacyProperyToStringMode.DISABLED;
+ } else {
+ if (!"warning".equals(param)) {
+ getLogger()
+ .log(Level.WARNING,
+ Constants.WARNING_UNKNOWN_LEGACY_PROPERTY_TOSTRING_VALUE,
+ param);
+
+ }
legacyPropertyToStringMode = DEFAULT_LEGACY_PROPERTY_TO_STRING;
}
}
diff --git a/server/src/com/vaadin/server/Sizeable.java b/server/src/com/vaadin/server/Sizeable.java
index 38e998c04b..decace3d10 100644
--- a/server/src/com/vaadin/server/Sizeable.java
+++ b/server/src/com/vaadin/server/Sizeable.java
@@ -101,6 +101,10 @@ public interface Sizeable extends Serializable {
*/
EM("em"),
/**
+ * Unit code representing the font-size of the root font.
+ */
+ REM("rem"),
+ /**
* Unit code representing the x-height of the relevant font.
*/
EX("ex"),
diff --git a/server/src/com/vaadin/server/VaadinPortletResponse.java b/server/src/com/vaadin/server/VaadinPortletResponse.java
index f89cb6ea7a..334b94a5dc 100644
--- a/server/src/com/vaadin/server/VaadinPortletResponse.java
+++ b/server/src/com/vaadin/server/VaadinPortletResponse.java
@@ -65,7 +65,13 @@ public class VaadinPortletResponse implements VaadinResponse {
@Override
public OutputStream getOutputStream() throws IOException {
- return ((MimeResponse) response).getPortletOutputStream();
+ if (response instanceof MimeResponse) {
+ return ((MimeResponse) response).getPortletOutputStream();
+ } else {
+ throw new IOException(
+ "Output stream not available for response of type "
+ + response.getClass().getName());
+ }
}
/**
diff --git a/server/src/com/vaadin/server/VaadinPortletService.java b/server/src/com/vaadin/server/VaadinPortletService.java
index 2eca07dd4a..c7fc5a23bd 100644
--- a/server/src/com/vaadin/server/VaadinPortletService.java
+++ b/server/src/com/vaadin/server/VaadinPortletService.java
@@ -32,6 +32,7 @@ import com.vaadin.server.VaadinPortlet.RequestType;
import com.vaadin.server.communication.PortletBootstrapHandler;
import com.vaadin.server.communication.PortletDummyRequestHandler;
import com.vaadin.server.communication.PortletListenerNotifier;
+import com.vaadin.server.communication.PortletStateAwareRequestHandler;
import com.vaadin.server.communication.PortletUIInitHandler;
import com.vaadin.ui.UI;
@@ -64,6 +65,7 @@ public class VaadinPortletService extends VaadinService {
handlers.add(new PortletListenerNotifier());
handlers.add(0, new PortletDummyRequestHandler());
handlers.add(0, new PortletBootstrapHandler());
+ handlers.add(0, new PortletStateAwareRequestHandler());
return handlers;
}
diff --git a/server/src/com/vaadin/server/WebBrowser.java b/server/src/com/vaadin/server/WebBrowser.java
index 8038bbc207..4d1027f0e4 100644
--- a/server/src/com/vaadin/server/WebBrowser.java
+++ b/server/src/com/vaadin/server/WebBrowser.java
@@ -259,6 +259,26 @@ public class WebBrowser implements Serializable {
}
/**
+ * Tests if the browser is run on Android.
+ *
+ * @return true if run on Android false if the user is not using Android or
+ * if no information on the browser is present
+ */
+ public boolean isAndroid() {
+ return browserDetails.isAndroid();
+ }
+
+ /**
+ * Tests if the browser is run in iOS.
+ *
+ * @return true if run in iOS false if the user is not using iOS or if no
+ * information on the browser is present
+ */
+ public boolean isIOS() {
+ return browserDetails.isIOS();
+ }
+
+ /**
* Returns the browser-reported TimeZone offset in milliseconds from GMT.
* This includes possible daylight saving adjustments, to figure out which
* TimeZone the user actually might be in, see
diff --git a/server/src/com/vaadin/server/communication/PortletStateAwareRequestHandler.java b/server/src/com/vaadin/server/communication/PortletStateAwareRequestHandler.java
new file mode 100644
index 0000000000..162c479fac
--- /dev/null
+++ b/server/src/com/vaadin/server/communication/PortletStateAwareRequestHandler.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.server.communication;
+
+import java.io.IOException;
+
+import javax.portlet.StateAwareResponse;
+
+import com.vaadin.server.RequestHandler;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinResponse;
+import com.vaadin.server.VaadinSession;
+
+/**
+ * Handler which ensures that Action and Event requests are marked as handled
+ * and do not cause a 404 to be sent.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public class PortletStateAwareRequestHandler implements RequestHandler {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.server.RequestHandler#handleRequest(com.vaadin.server.
+ * VaadinSession, com.vaadin.server.VaadinRequest,
+ * com.vaadin.server.VaadinResponse)
+ */
+ @Override
+ public boolean handleRequest(VaadinSession session, VaadinRequest request,
+ VaadinResponse response) throws IOException {
+ if (response instanceof StateAwareResponse) {
+ // StateAwareResponse is fully handled by listeners through
+ // PortletListenerNotifier
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/server/src/com/vaadin/server/communication/PushHandler.java b/server/src/com/vaadin/server/communication/PushHandler.java
index 6b853063a7..1c50f79349 100644
--- a/server/src/com/vaadin/server/communication/PushHandler.java
+++ b/server/src/com/vaadin/server/communication/PushHandler.java
@@ -28,6 +28,7 @@ import org.atmosphere.cpr.AtmosphereRequest;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResource.TRANSPORT;
import org.atmosphere.cpr.AtmosphereResourceEvent;
+import org.atmosphere.cpr.AtmosphereResourceEventListenerAdapter;
import org.json.JSONException;
import com.vaadin.server.LegacyCommunicationManager.InvalidUIDLSecurityKeyException;
@@ -51,7 +52,8 @@ import com.vaadin.ui.UI;
* @author Vaadin Ltd
* @since 7.1
*/
-public class PushHandler implements AtmosphereHandler {
+public class PushHandler extends AtmosphereResourceEventListenerAdapter
+ implements AtmosphereHandler {
/**
* Callback interface used internally to process an event with the
@@ -67,12 +69,15 @@ public class PushHandler implements AtmosphereHandler {
* open by calling resource.suspend(). If there is a pending push, send it
* now.
*/
- private static PushEventCallback establishCallback = new PushEventCallback() {
+ private final PushEventCallback establishCallback = new PushEventCallback() {
@Override
public void run(AtmosphereResource resource, UI ui) throws IOException {
getLogger().log(Level.FINER,
"New push connection with transport {0}",
resource.transport());
+
+ resource.addEventListener(PushHandler.this);
+
resource.getResponse().setContentType("text/plain; charset=UTF-8");
VaadinSession session = ui.getSession();
@@ -122,9 +127,12 @@ public class PushHandler implements AtmosphereHandler {
* the request and send changed UI state via the push channel (we do not
* respond to the request directly.)
*/
- private static PushEventCallback receiveCallback = new PushEventCallback() {
+ private final PushEventCallback receiveCallback = new PushEventCallback() {
@Override
public void run(AtmosphereResource resource, UI ui) throws IOException {
+ getLogger().log(Level.FINER, "Received message from resource {0}",
+ resource.uuid());
+
AtmosphereRequest req = resource.getRequest();
AtmospherePushConnection connection = getConnectionForUI(ui);
@@ -167,7 +175,7 @@ public class PushHandler implements AtmosphereHandler {
/**
* Callback used when a connection is closed by the client.
*/
- PushEventCallback disconnectCallback = new PushEventCallback() {
+ private final PushEventCallback disconnectCallback = new PushEventCallback() {
@Override
public void run(AtmosphereResource resource, UI ui) throws IOException {
PushMode pushMode = ui.getPushConfiguration().getPushMode();
@@ -187,7 +195,7 @@ public class PushHandler implements AtmosphereHandler {
* mode has been set to disabled, just clean up some stuff
* and be done with it
*/
- getLogger().log(Level.FINEST,
+ getLogger().log(Level.FINER,
"Connection closed for resource {0}", id);
} else {
/*
@@ -195,7 +203,7 @@ public class PushHandler implements AtmosphereHandler {
* tab.
*/
getLogger()
- .log(Level.FINE,
+ .log(Level.FINER,
"Connection unexpectedly closed for resource {0} with transport {1}",
new Object[] { id, resource.transport() });
}
@@ -316,7 +324,8 @@ public class PushHandler implements AtmosphereHandler {
String id = resource.uuid();
if (event.isCancelled()) {
- callWithUi(resource, disconnectCallback);
+ // Disconnected for whatever reason, handle in onDisconnect() as
+ // it's more reliable
} else if (event.isResuming()) {
// A connection that was suspended earlier was resumed (committed to
// the client.) Should only happen if the transport is JSONP or
@@ -352,6 +361,13 @@ public class PushHandler implements AtmosphereHandler {
}
@Override
+ public void onDisconnect(AtmosphereResourceEvent event) {
+ // Log event on trace level
+ super.onDisconnect(event);
+ callWithUi(event.getResource(), disconnectCallback);
+ }
+
+ @Override
public void destroy() {
}
diff --git a/server/src/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java b/server/src/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java
index 3a0e59df71..6d0818b2cd 100644
--- a/server/src/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java
+++ b/server/src/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java
@@ -84,25 +84,26 @@ public class WidgetSetBuilder {
widgetsetFile.createNewFile();
PrintStream printStream = new PrintStream(new FileOutputStream(
widgetsetFile));
- printStream.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- + "<!DOCTYPE module PUBLIC \"-//Google Inc.//DTD "
- + "Google Web Toolkit 1.7.0//EN\" \"http://google"
- + "-web-toolkit.googlecode.com/svn/tags/1.7.0/dis"
- + "tro-source/core/src/gwt-module.dtd\">\n");
+ printStream
+ .print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ + "<!DOCTYPE module PUBLIC \"-//Google Inc.//DTD Google Web Toolkit 2.5.1//EN\" \"http://google-web-toolkit.googlecode.com/svn/tags/2.5.1/distro-source/core/src/gwt-module.dtd\">\n");
printStream.print("<module>\n");
printStream
.print(" <!--\n"
- + " Uncomment the following to compile the widgetset for one browser only.\n"
- + " This can reduce the GWT compilation time significantly when debugging.\n"
- + " The line should be commented out before deployment to production\n"
- + " environments.\n\n"
- + " Multiple browsers can be specified for GWT 1.7 as a comma separated\n"
- + " list. The supported user agents at the moment of writing were:\n"
- + " ie6,ie8,gecko,gecko1_8,safari,opera\n\n"
- + " The value gecko1_8 is used for Firefox 3 and later and safari is used for\n"
- + " webkit based browsers including Google Chrome.\n"
+ + " Uncomment the following to compile the widgetset for one browser only.\n\n"
+ + " Multiple browsers can be specified as a comma separated list. The\n"
+ + " supported user agents at the moment of writing were:\n"
+ + " ie8,ie9,gecko1_8,safari,opera\n\n"
+ + " The value gecko1_8 is used for Firefox and safari is used for webkit\n"
+ + " based browsers including Google Chrome.\n"
+ + " -->\n"
+ + " <!-- <set-property name=\"user.agent\" value=\"safari\"/> -->\n\n"
+ + " <!--\n"
+ + " To enable SuperDevMode, uncomment this line.\n\n"
+ + " See https://vaadin.com/wiki/-/wiki/Main/Using%20SuperDevMode for more\n"
+ + " information and instructions.\n"
+ " -->\n"
- + " <!-- <set-property name=\"user.agent\" value=\"gecko1_8\"/> -->\n");
+ + " <!-- <set-configuration-property name=\"devModeRedirectEnabled\" value=\"true\" /> -->\n\n");
printStream.print("\n</module>\n");
printStream.close();
changed = true;
diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java
index 0bf27435fb..262d47af18 100644
--- a/server/src/com/vaadin/ui/AbstractComponent.java
+++ b/server/src/com/vaadin/ui/AbstractComponent.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -81,7 +82,7 @@ public abstract class AbstractComponent extends AbstractClientConnector
private Unit widthUnit = Unit.PIXELS;
private Unit heightUnit = Unit.PIXELS;
private static final Pattern sizePattern = Pattern
- .compile("^(-?\\d+(\\.\\d+)?)(%|px|em|ex|in|cm|mm|pt|pc)?$");
+ .compile("^(-?\\d+(\\.\\d+)?)(%|px|em|rem|ex|in|cm|mm|pt|pc)?$");
private ErrorHandler errorHandler = null;
@@ -176,11 +177,9 @@ public abstract class AbstractComponent extends AbstractClientConnector
}
List<String> styles = getState().styles;
styles.clear();
- String[] styleParts = style.split(" +");
- for (String part : styleParts) {
- if (part.length() > 0) {
- styles.add(part);
- }
+ StringTokenizer tokenizer = new StringTokenizer(style, " ");
+ while (tokenizer.hasMoreTokens()) {
+ styles.add(tokenizer.nextToken());
}
}
@@ -201,8 +200,9 @@ public abstract class AbstractComponent extends AbstractClientConnector
}
if (style.contains(" ")) {
// Split space separated style names and add them one by one.
- for (String realStyle : style.split(" ")) {
- addStyleName(realStyle);
+ StringTokenizer tokenizer = new StringTokenizer(style, " ");
+ while (tokenizer.hasMoreTokens()) {
+ addStyleName(tokenizer.nextToken());
}
return;
}
@@ -219,11 +219,9 @@ public abstract class AbstractComponent extends AbstractClientConnector
@Override
public void removeStyleName(String style) {
if (ComponentStateUtil.hasStyles(getState())) {
- String[] styleParts = style.split(" +");
- for (String part : styleParts) {
- if (part.length() > 0) {
- getState().styles.remove(part);
- }
+ StringTokenizer tokenizer = new StringTokenizer(style, " ");
+ while (tokenizer.hasMoreTokens()) {
+ getState().styles.remove(tokenizer.nextToken());
}
}
}
diff --git a/server/tests/src/com/vaadin/benchmarks/PerformanceTester8759.java b/server/tests/src/com/vaadin/benchmarks/PerformanceTester8759.java
new file mode 100644
index 0000000000..968edd4b24
--- /dev/null
+++ b/server/tests/src/com/vaadin/benchmarks/PerformanceTester8759.java
@@ -0,0 +1,52 @@
+package com.vaadin.benchmarks;
+
+import com.vaadin.ui.Label;
+
+/*
+ * This simple test shows the performance difference between the StringTokenizer implementation and the String.split() implementation in AbstractComponent.
+ * Your results will vary.
+ * The real world use case motivating it was a 10k Row table, which generated labels for 10 columns.
+ * This is 1/10th of what this performance tester demonstrates.
+ *
+ * Please run with -server and -Xloggc:/tmp/gclog.vgc -verbose:gc -XX:+PrintCompilation
+ *
+ * My results Win 7 64, i7 2760QM 2.4Ghz, Java 7 21.
+ *
+ * Proposed Patch with StringTokenizer:
+ * 13 GC activations, 1.009GB allocated memory over time, total time 948ms
+ *
+ * Current String.split implementation:
+ * 31 GC activations, 2.277 GB allocated memory over time, total time 1557ms
+ *
+ */
+public class PerformanceTester8759 {
+
+ public static void main(String[] args) throws InterruptedException {
+ warmup();
+
+ long start = System.currentTimeMillis();
+ runBenchmark(1000000);
+ long end = System.currentTimeMillis();
+ System.out.println("took " + (end - start) + " ms");
+
+ }
+
+ private static void warmup() throws InterruptedException {
+ runBenchmark(10000);
+ System.gc();
+ System.out.println("warmup and gc complete. sleeping 5 seconds.");
+ Thread.sleep(5000l);
+ System.out.println("woke up - go.");
+ }
+
+ private static void runBenchmark(int loops) {
+ Label label = null;
+ for (int i = 0; i < loops; i++) {
+ label = new Label();
+ label.setStyleName("mainStyle");
+ label.addStyleName("foo bar baz");
+ label.addStyleName("vaadin");
+ }
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/server/MockUIContainingServlet.java b/server/tests/src/com/vaadin/server/MockUIContainingServlet.java
new file mode 100644
index 0000000000..d54242e31f
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/MockUIContainingServlet.java
@@ -0,0 +1,16 @@
+package com.vaadin.server;
+
+import com.vaadin.ui.UI;
+
+public class MockUIContainingServlet extends UI {
+
+ public static class ServletInUI extends VaadinServlet {
+ // This servlet should automatically be configured to use the
+ // enclosing UI class
+ }
+
+ @Override
+ protected void init(VaadinRequest request) {
+ // Do nothing
+ }
+}
diff --git a/server/tests/src/com/vaadin/server/VaadinServletConfigurationTest.java b/server/tests/src/com/vaadin/server/VaadinServletConfigurationTest.java
index d347534f5c..3098970e6a 100644
--- a/server/tests/src/com/vaadin/server/VaadinServletConfigurationTest.java
+++ b/server/tests/src/com/vaadin/server/VaadinServletConfigurationTest.java
@@ -31,34 +31,21 @@ import org.junit.Test;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.server.DeploymentConfiguration.LegacyProperyToStringMode;
-import com.vaadin.server.VaadinServletConfigurationTest.MockUI;
-import com.vaadin.server.VaadinServletConfigurationTest.MockUI.ServletInUI;
+import com.vaadin.server.MockUIContainingServlet.ServletInUI;
import com.vaadin.ui.UI;
public class VaadinServletConfigurationTest {
- public static class MockUI extends UI {
-
- public static class ServletInUI extends VaadinServlet {
- // This servlet should automatically be configured to use the
- // enclosing UI class
- }
-
- @Override
- protected void init(VaadinRequest request) {
- // Do nothing
- }
- }
@Test
public void testEnclosingUIClass() throws Exception {
- ServletInUI servlet = new MockUI.ServletInUI();
+ ServletInUI servlet = new MockUIContainingServlet.ServletInUI();
servlet.init(new MockServletConfig());
Class<? extends UI> uiClass = new DefaultUIProvider()
.getUIClass(new UIClassSelectionEvent(new VaadinServletRequest(
EasyMock.createMock(HttpServletRequest.class), servlet
.getService())));
- Assert.assertEquals(MockUI.class, uiClass);
+ Assert.assertEquals(MockUIContainingServlet.class, uiClass);
}
@Test
@@ -79,7 +66,7 @@ public class VaadinServletConfigurationTest {
.getUIClass(new UIClassSelectionEvent(new VaadinServletRequest(
EasyMock.createMock(HttpServletRequest.class), servlet
.getService())));
- Assert.assertEquals(MockUI.class, uiClass);
+ Assert.assertEquals(MockUIContainingServlet.class, uiClass);
}
@Test
@@ -107,11 +94,11 @@ public class VaadinServletConfigurationTest {
.getUIClass(new UIClassSelectionEvent(new VaadinServletRequest(
EasyMock.createMock(HttpServletRequest.class), servlet
.getService())));
- Assert.assertEquals(MockUI.class, uiClass);
+ Assert.assertEquals(MockUIContainingServlet.class, uiClass);
}
}
-@VaadinServletConfiguration(productionMode = true, ui = MockUI.class, closeIdleSessions = true, heartbeatInterval = 1234, resourceCacheTime = 4321)
+@VaadinServletConfiguration(productionMode = true, ui = MockUIContainingServlet.class, closeIdleSessions = true, heartbeatInterval = 1234, resourceCacheTime = 4321)
class TestServlet extends VaadinServlet {
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/ComponentSizeParseTest.java b/server/tests/src/com/vaadin/tests/server/component/ComponentSizeParseTest.java
new file mode 100644
index 0000000000..11c0d10998
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/ComponentSizeParseTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.tests.server.component;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+
+import com.vaadin.server.Sizeable.Unit;
+import com.vaadin.shared.ui.label.LabelState;
+import com.vaadin.ui.Label;
+
+public class ComponentSizeParseTest extends TestCase {
+
+ private final class LabelWithPublicState extends Label {
+ @Override
+ protected LabelState getState() {
+ return super.getState();
+ }
+ }
+
+ public void testAllTheUnit() {
+ testUnit("10.0px", 10, Unit.PIXELS);
+ testUnit("10.0pt", 10, Unit.POINTS);
+ testUnit("10.0pc", 10, Unit.PICAS);
+ testUnit("10.0em", 10, Unit.EM);
+ testUnit("10.0rem", 10, Unit.REM);
+ testUnit("10.0mm", 10, Unit.MM);
+ testUnit("10.0cm", 10, Unit.CM);
+ testUnit("10.0in", 10, Unit.INCH);
+ testUnit("10.0%", 10, Unit.PERCENTAGE);
+ }
+
+ private void testUnit(String string, int amout, Unit unit) {
+ LabelWithPublicState label = new LabelWithPublicState();
+ label.setHeight(string);
+
+ Assert.assertEquals(amout, label.getHeight(), 0);
+ Assert.assertEquals(unit, label.getHeightUnits());
+
+ label = new LabelWithPublicState();
+
+ label.setHeight(10, unit);
+ label.beforeClientResponse(true);
+ Assert.assertEquals(string, label.getState().height);
+ }
+}