aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2015-01-28 17:08:15 +0200
committerArtur Signell <artur@vaadin.com>2015-01-29 10:13:00 +0200
commita66eeb58e8c1144c8d01cc37f727638139db711d (patch)
tree423a1973d4e7ed38152f18a206ea9c9b2d04c377
parenta681bf8f13163b67f55ec2d334f44f976d3eb161 (diff)
downloadvaadin-framework-a66eeb58e8c1144c8d01cc37f727638139db711d.tar.gz
vaadin-framework-a66eeb58e8c1144c8d01cc37f727638139db711d.zip
Do not loop infinitely when encountering an invalid tag name (#16522)
Also do not write to sysout Change-Id: Idae318a851323cd27b3363d12e8080101e996d9c
-rw-r--r--server/src/com/vaadin/ui/declarative/DesignContext.java30
-rw-r--r--server/tests/src/com/vaadin/tests/design/InvalidTagNames.java103
-rw-r--r--shared/src/com/vaadin/shared/util/SharedUtil.java4
3 files changed, 117 insertions, 20 deletions
diff --git a/server/src/com/vaadin/ui/declarative/DesignContext.java b/server/src/com/vaadin/ui/declarative/DesignContext.java
index fd83339b76..b298c95320 100644
--- a/server/src/com/vaadin/ui/declarative/DesignContext.java
+++ b/server/src/com/vaadin/ui/declarative/DesignContext.java
@@ -20,7 +20,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import org.jsoup.nodes.Attributes;
@@ -29,6 +28,7 @@ import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import com.vaadin.annotations.DesignRoot;
+import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.Component;
import com.vaadin.ui.HasComponents;
@@ -509,7 +509,7 @@ public class DesignContext implements Serializable {
// Otherwise, get the full class name using the prefix to package
// mapping. Example: "v-vertical-layout" ->
// "com.vaadin.ui.VerticalLayout"
- String[] parts = tagName.split("-");
+ String[] parts = tagName.split("-", 2);
if (parts.length < 2) {
throw new DesignException("The tagname '" + tagName
+ "' is invalid: missing prefix.");
@@ -519,24 +519,16 @@ public class DesignContext implements Serializable {
if (packageName == null) {
throw new DesignException("Unknown tag: " + tagName);
}
- int firstCharacterIndex = prefixName.length() + 1; // +1 is for '-'
- tagName = tagName.substring(firstCharacterIndex,
- firstCharacterIndex + 1).toUpperCase(Locale.ENGLISH)
- + tagName.substring(firstCharacterIndex + 1);
- int i;
- while ((i = tagName.indexOf("-")) != -1) {
- int length = tagName.length();
- if (i != length - 1) {
- tagName = tagName.substring(0, i)
- + tagName.substring(i + 1, i + 2).toUpperCase(
- Locale.ENGLISH) + tagName.substring(i + 2);
-
- } else {
- // Ends with "-"
- System.out.println("A tag name should not end with '-'.");
- }
+ String[] classNameParts = parts[1].split("-");
+ String className = "";
+ for (String classNamePart : classNameParts) {
+ // Split will ignore trailing and multiple dashes but that should be
+ // ok
+ // <v-button--> will be resolved to <v-button>
+ // <v--button> will be resolved to <v-button>
+ className += SharedUtil.capitalize(classNamePart);
}
- return packageName + "." + tagName;
+ return packageName + "." + className;
}
@SuppressWarnings("unchecked")
diff --git a/server/tests/src/com/vaadin/tests/design/InvalidTagNames.java b/server/tests/src/com/vaadin/tests/design/InvalidTagNames.java
new file mode 100644
index 0000000000..0b6ccf8cb1
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/design/InvalidTagNames.java
@@ -0,0 +1,103 @@
+/*
+ * 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.design;
+
+import java.io.ByteArrayInputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.declarative.Design;
+import com.vaadin.ui.declarative.DesignException;
+
+public class InvalidTagNames {
+
+ @Test(expected = DesignException.class)
+ public void tagWithoutDash() {
+ readDesign("<vbutton>foo</vbutton>");
+ }
+
+ @Test
+ public void emptyTag() {
+ // JSoup parses empty tags into text nodes
+ Component c = readDesign("<>foo</>");
+ Assert.assertNull(c);
+ }
+
+ @Test(expected = DesignException.class)
+ public void onlyPrefix() {
+ readDesign("<v->foo</v->");
+ }
+
+ @Test
+ public void onlyClass() {
+ // JSoup will refuse to parse tags starting with - and convert them into
+ // text nodes instead
+ Component c = readDesign("<-v>foo</-v>");
+ Assert.assertNull(c);
+ }
+
+ @Test(expected = DesignException.class)
+ public void unknownClass() {
+ readDesign("<v-unknownbutton>foo</v-unknownbutton>");
+ }
+
+ @Test(expected = DesignException.class)
+ public void unknownTag() {
+ readDesign("<x-button></x-button>");
+ }
+
+ // @Test(expected = DesignException.class)
+ // This is a side effect of not actively checking for invalid input. Will be
+ // parsed currently as <v-button> (this should not be considered API)
+ public void tagEndsInDash() {
+ Component c = readDesign("<v-button-></v-button->");
+ Assert.assertTrue(c.getClass() == Button.class);
+ }
+
+ // @Test(expected = DesignException.class)
+ // This is a side effect of not actively checking for invalid input. Will be
+ // parsed currently as <v-button> (this should not be considered API)
+ public void tagEndsInTwoDashes() {
+ Component c = readDesign("<v-button--></v-button-->");
+ Assert.assertTrue(c.getClass() == Button.class);
+ }
+
+ // @Test(expected = DesignException.class)
+ // This is a side effect of not actively checking for invalid input. Will be
+ // parsed currently as <v-button> (this should not be considered API)
+ public void tagWithTwoDashes() {
+ Component c = readDesign("<v--button></v--button>");
+ Assert.assertTrue(c.getClass() == Button.class);
+ }
+
+ @Test(expected = DesignException.class)
+ public void specialCharacters() {
+ readDesign("<v-button-&!#></v-button-&!#>");
+ }
+
+ private Component readDesign(String string) {
+ try {
+ return Design.read(new ByteArrayInputStream(string
+ .getBytes("UTF-8")));
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/shared/src/com/vaadin/shared/util/SharedUtil.java b/shared/src/com/vaadin/shared/util/SharedUtil.java
index 206041235a..bc5d87b9f5 100644
--- a/shared/src/com/vaadin/shared/util/SharedUtil.java
+++ b/shared/src/com/vaadin/shared/util/SharedUtil.java
@@ -16,6 +16,7 @@
package com.vaadin.shared.util;
import java.io.Serializable;
+import java.util.Locale;
/**
* Misc internal utility methods used by both the server and the client package.
@@ -168,7 +169,8 @@ public class SharedUtil implements Serializable {
return string.toUpperCase();
}
- return string.substring(0, 1).toUpperCase() + string.substring(1);
+ return string.substring(0, 1).toUpperCase(Locale.ENGLISH)
+ + string.substring(1);
}
/**