aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-09-20 17:49:42 -0700
committerGerrit Code Review <noreply-gerritcodereview@google.com>2012-09-20 17:49:43 -0700
commita5217f041c1d9596ca2d39b880edb4c266a9edc7 (patch)
tree2f5d84b06a344339eaa76b0ba56fc9614ddc5d1a
parent69e16b2fbea467122cea308ac5ad74f27ca94d95 (diff)
parent454f0e05d3e202320b0cd7bc176360458e88658e (diff)
downloadsdk-a5217f041c1d9596ca2d39b880edb4c266a9edc7.zip
sdk-a5217f041c1d9596ca2d39b880edb4c266a9edc7.tar.gz
sdk-a5217f041c1d9596ca2d39b880edb4c266a9edc7.tar.bz2
Merge "37497: Templates should escape string literals in resource files"
-rw-r--r--common/src/com/android/utils/XmlUtils.java21
-rw-r--r--common/tests/src/com/android/utils/XmlUtilsTest.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlAttributeMethod.java40
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlStringMethod.java43
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlTextMethod.java40
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmExtractLettersMethod.java45
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlAttributeMethodTest.java50
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlStringMethodTest.java66
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlTextMethodTest.java46
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmExtractLettersMethodTest.java46
-rw-r--r--templates/activities/BlankActivity/root/res/values/strings.xml.ftl2
-rw-r--r--templates/activities/FullscreenActivity/root/res/values/strings.xml.ftl2
-rw-r--r--templates/activities/LoginActivity/root/res/values/strings.xml.ftl2
-rw-r--r--templates/activities/MasterDetailFlow/globals.xml.ftl8
-rw-r--r--templates/activities/MasterDetailFlow/recipe.xml.ftl2
-rw-r--r--templates/activities/MasterDetailFlow/root/res/values-large/refs.xml.ftl2
-rw-r--r--templates/activities/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl2
-rw-r--r--templates/activities/MasterDetailFlow/root/res/values/strings.xml.ftl4
-rw-r--r--templates/activities/SettingsActivity/root/res/values/strings.xml.ftl2
-rw-r--r--templates/docs/index.html52
-rw-r--r--templates/projects/NewAndroidApplication/root/res/values/strings.xml.ftl2
22 files changed, 471 insertions, 15 deletions
diff --git a/common/src/com/android/utils/XmlUtils.java b/common/src/com/android/utils/XmlUtils.java
index 73e1d11..94b7405 100644
--- a/common/src/com/android/utils/XmlUtils.java
+++ b/common/src/com/android/utils/XmlUtils.java
@@ -182,6 +182,27 @@ public class XmlUtils {
}
/**
+ * Converts the given attribute value to an XML-text-safe value, meaning that
+ * less than and ampersand characters are escaped.
+ *
+ * @param textValue the text value to be escaped
+ * @return the escaped value
+ */
+ @NonNull
+ public static String toXmlTextValue(@NonNull String textValue) {
+ for (int i = 0, n = textValue.length(); i < n; i++) {
+ char c = textValue.charAt(i);
+ if (c == '<' || c == '&') {
+ StringBuilder sb = new StringBuilder(2 * textValue.length());
+ appendXmlTextValue(sb, textValue);
+ return sb.toString();
+ }
+ }
+
+ return textValue;
+ }
+
+ /**
* Appends text to the given {@link StringBuilder} and escapes it as required for a
* DOM attribute node.
*
diff --git a/common/tests/src/com/android/utils/XmlUtilsTest.java b/common/tests/src/com/android/utils/XmlUtilsTest.java
index 6c28451..ea33346 100644
--- a/common/tests/src/com/android/utils/XmlUtilsTest.java
+++ b/common/tests/src/com/android/utils/XmlUtilsTest.java
@@ -16,7 +16,6 @@
package com.android.utils;
import com.android.SdkConstants;
-import com.android.utils.XmlUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
@@ -79,6 +78,10 @@ public class XmlUtilsTest extends TestCase {
assertEquals("&lt;&quot;&apos;>&amp;", sb.toString());
}
+ public void testToXmlTextValue() throws Exception {
+ assertEquals("&lt;\"'>&amp;", XmlUtils.toXmlTextValue("<\"'>&"));
+ }
+
public void testAppendXmlTextValue() throws Exception {
StringBuilder sb = new StringBuilder();
XmlUtils.appendXmlTextValue(sb, "<\"'>&");
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlAttributeMethod.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlAttributeMethod.java
new file mode 100644
index 0000000..21f33b8
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlAttributeMethod.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.android.ide.eclipse.adt.internal.wizards.templates;
+
+import com.android.utils.XmlUtils;
+
+import freemarker.template.SimpleScalar;
+import freemarker.template.TemplateMethodModel;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+
+import java.util.List;
+
+/**
+ * Method invoked by FreeMarker to escape a string such that it can be used
+ * as an XML attribute (escaping ', ", & and <).
+ */
+public class FmEscapeXmlAttributeMethod implements TemplateMethodModel {
+ @Override
+ public TemplateModel exec(List args) throws TemplateModelException {
+ if (args.size() != 1) {
+ throw new TemplateModelException("Wrong arguments");
+ }
+ String string = args.get(0).toString();
+ return new SimpleScalar(XmlUtils.toXmlAttributeValue(string));
+ }
+} \ No newline at end of file
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlStringMethod.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlStringMethod.java
new file mode 100644
index 0000000..7e5866e
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlStringMethod.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.android.ide.eclipse.adt.internal.wizards.templates;
+
+import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringRefactoring;
+
+import freemarker.template.SimpleScalar;
+import freemarker.template.TemplateMethodModel;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+
+import java.util.List;
+
+/**
+ * Method invoked by FreeMarker to escape a string such that it can be placed
+ * as text in a string resource file.
+ * This is similar to {@link FmEscapeXmlTextMethod}, but in addition to escaping
+ * &lt; and &amp; it also escapes characters such as quotes necessary for Android
+ *{@code <string>} elements.
+ */
+public class FmEscapeXmlStringMethod implements TemplateMethodModel {
+ @Override
+ public TemplateModel exec(List args) throws TemplateModelException {
+ if (args.size() != 1) {
+ throw new TemplateModelException("Wrong arguments");
+ }
+ String string = args.get(0).toString();
+ return new SimpleScalar(ExtractStringRefactoring.escapeString(string));
+ }
+} \ No newline at end of file
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlTextMethod.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlTextMethod.java
new file mode 100644
index 0000000..55a4bc8
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlTextMethod.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.android.ide.eclipse.adt.internal.wizards.templates;
+
+import com.android.utils.XmlUtils;
+
+import freemarker.template.SimpleScalar;
+import freemarker.template.TemplateMethodModel;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+
+import java.util.List;
+
+/**
+ * Method invoked by FreeMarker to escape a string such that it can be used
+ * as XML text (escaping < and &, but not ' and " etc).
+ */
+public class FmEscapeXmlTextMethod implements TemplateMethodModel {
+ @Override
+ public TemplateModel exec(List args) throws TemplateModelException {
+ if (args.size() != 1) {
+ throw new TemplateModelException("Wrong arguments");
+ }
+ String string = args.get(0).toString();
+ return new SimpleScalar(XmlUtils.toXmlTextValue(string));
+ }
+} \ No newline at end of file
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmExtractLettersMethod.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmExtractLettersMethod.java
new file mode 100644
index 0000000..09fa81c
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmExtractLettersMethod.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.android.ide.eclipse.adt.internal.wizards.templates;
+
+import freemarker.template.SimpleScalar;
+import freemarker.template.TemplateMethodModel;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+
+import java.util.List;
+
+/**
+ * Method invoked by FreeMarker to extract letters from a string; this will remove
+ * any whitespace, punctuation and digits.
+ */
+public class FmExtractLettersMethod implements TemplateMethodModel {
+ @Override
+ public TemplateModel exec(List args) throws TemplateModelException {
+ if (args.size() != 1) {
+ throw new TemplateModelException("Wrong arguments");
+ }
+ String string = args.get(0).toString();
+ StringBuilder sb = new StringBuilder(string.length());
+ for (int i = 0, n = string.length(); i < n; i++) {
+ char c = string.charAt(i);
+ if (Character.isLetter(c)) {
+ sb.append(c);
+ }
+ }
+ return new SimpleScalar(sb.toString());
+ }
+} \ No newline at end of file
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
index cb45522..f2c64ae 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
@@ -315,6 +315,10 @@ class TemplateHandler {
paramMap.put("activityToLayout", new FmActivityToLayoutMethod()); //$NON-NLS-1$
paramMap.put("layoutToActivity", new FmLayoutToActivityMethod()); //$NON-NLS-1$
paramMap.put("classToResource", new FmClassNameToResourceMethod()); //$NON-NLS-1$
+ paramMap.put("escapeXmlAttribute", new FmEscapeXmlStringMethod()); //$NON-NLS-1$
+ paramMap.put("escapeXmlText", new FmEscapeXmlStringMethod()); //$NON-NLS-1$
+ paramMap.put("escapeXmlString", new FmEscapeXmlStringMethod()); //$NON-NLS-1$
+ paramMap.put("extractLetters", new FmExtractLettersMethod()); //$NON-NLS-1$
// This should be handled better: perhaps declared "required packages" as part of the
// inputs? (It would be better if we could conditionally disable template based
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlAttributeMethodTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlAttributeMethodTest.java
new file mode 100644
index 0000000..eb1e949
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlAttributeMethodTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.android.ide.eclipse.adt.internal.wizards.templates;
+
+import freemarker.template.SimpleScalar;
+import freemarker.template.TemplateModelException;
+
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class FmEscapeXmlAttributeMethodTest extends TestCase {
+ @SuppressWarnings("rawtypes")
+ private void check(String s, String expected) throws TemplateModelException {
+ FmEscapeXmlAttributeMethod method = new FmEscapeXmlAttributeMethod();
+ List list = Collections.singletonList(new SimpleScalar(s));
+ assertEquals(expected, ((SimpleScalar) method.exec(list)).getAsString());
+ }
+
+ public void test1() throws Exception {
+ check("", "");
+ }
+
+ public void test2() throws Exception {
+ check("foo", "foo");
+ }
+
+ public void test3() throws Exception {
+ check("<\"'>&", "&lt;&quot;&apos;>&amp;");
+ }
+
+ public void test4() throws Exception {
+ check("foo>bar", "foo>bar");
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlStringMethodTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlStringMethodTest.java
new file mode 100644
index 0000000..1a4289a
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlStringMethodTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.android.ide.eclipse.adt.internal.wizards.templates;
+
+import freemarker.template.SimpleScalar;
+import freemarker.template.TemplateModelException;
+
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class FmEscapeXmlStringMethodTest extends TestCase {
+ @SuppressWarnings("rawtypes")
+ private void check(String s, String expected) throws TemplateModelException {
+ FmEscapeXmlStringMethod method = new FmEscapeXmlStringMethod();
+ List list = Collections.singletonList(new SimpleScalar(s));
+ assertEquals(expected, ((SimpleScalar) method.exec(list)).getAsString());
+ }
+
+ public void test1() throws Exception {
+ check("", "");
+ }
+
+ public void test2() throws Exception {
+ check("foo", "foo");
+ }
+
+ public void test3() throws Exception {
+ check(" Foo Bar ", "\" Foo Bar \"");
+ }
+
+ public void test4() throws Exception {
+ check("@foo", "\\@foo");
+ }
+
+ public void test5() throws Exception {
+ check("Hello\nWorld", "Hello\\nWorld");
+ }
+
+ public void test6() throws Exception {
+ check("A & B", "A &amp; B");
+ }
+
+ public void test7() throws Exception {
+ check("Foo's Bar", "Foo\\'s Bar");
+ }
+
+ public void test8() throws Exception {
+ check("'\"\\", "\\'\\\"\\\\");
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlTextMethodTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlTextMethodTest.java
new file mode 100644
index 0000000..c08b834
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmEscapeXmlTextMethodTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.android.ide.eclipse.adt.internal.wizards.templates;
+
+import freemarker.template.SimpleScalar;
+import freemarker.template.TemplateModelException;
+
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class FmEscapeXmlTextMethodTest extends TestCase {
+ @SuppressWarnings("rawtypes")
+ private void check(String s, String expected) throws TemplateModelException {
+ FmEscapeXmlTextMethod method = new FmEscapeXmlTextMethod();
+ List list = Collections.singletonList(new SimpleScalar(s));
+ assertEquals(expected, ((SimpleScalar) method.exec(list)).getAsString());
+ }
+
+ public void test1() throws Exception {
+ check("", "");
+ }
+
+ public void test2() throws Exception {
+ check("foo", "foo");
+ }
+
+ public void test3() throws Exception {
+ check("<\"'>&", "&lt;\"'>&amp;");
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmExtractLettersMethodTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmExtractLettersMethodTest.java
new file mode 100644
index 0000000..b1d3cee
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/wizards/templates/FmExtractLettersMethodTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.android.ide.eclipse.adt.internal.wizards.templates;
+
+import freemarker.template.SimpleScalar;
+import freemarker.template.TemplateModelException;
+
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class FmExtractLettersMethodTest extends TestCase {
+ @SuppressWarnings("rawtypes")
+ private void check(String s, String expected) throws TemplateModelException {
+ FmExtractLettersMethod method = new FmExtractLettersMethod();
+ List list = Collections.singletonList(new SimpleScalar(s));
+ assertEquals(expected, ((SimpleScalar) method.exec(list)).getAsString());
+ }
+
+ public void test1() throws Exception {
+ check("", "");
+ }
+
+ public void test2() throws Exception {
+ check("foo", "foo");
+ }
+
+ public void test3() throws Exception {
+ check("<\"'>&foo ", "foo");
+ }
+}
diff --git a/templates/activities/BlankActivity/root/res/values/strings.xml.ftl b/templates/activities/BlankActivity/root/res/values/strings.xml.ftl
index 6c636d6..4ba950a 100644
--- a/templates/activities/BlankActivity/root/res/values/strings.xml.ftl
+++ b/templates/activities/BlankActivity/root/res/values/strings.xml.ftl
@@ -1,6 +1,6 @@
<resources>
<#if !isNewProject>
- <string name="title_${activityToLayout(activityClass)}">${activityTitle}</string>
+ <string name="title_${activityToLayout(activityClass)}">${escapeXmlString(activityTitle)}</string>
</#if>
<string name="menu_settings">Settings</string>
diff --git a/templates/activities/FullscreenActivity/root/res/values/strings.xml.ftl b/templates/activities/FullscreenActivity/root/res/values/strings.xml.ftl
index 53ff7df..5a43acf 100644
--- a/templates/activities/FullscreenActivity/root/res/values/strings.xml.ftl
+++ b/templates/activities/FullscreenActivity/root/res/values/strings.xml.ftl
@@ -1,7 +1,7 @@
<resources>
<#if !isNewProject>
- <string name="title_${simpleName}">${activityTitle}</string>
+ <string name="title_${simpleName}">${escapeXmlString(activityTitle)}</string>
</#if>
<string name="dummy_button1">Button 1</string>
<string name="dummy_button2">Button 2</string>
diff --git a/templates/activities/LoginActivity/root/res/values/strings.xml.ftl b/templates/activities/LoginActivity/root/res/values/strings.xml.ftl
index c2ad046..18bf85f 100644
--- a/templates/activities/LoginActivity/root/res/values/strings.xml.ftl
+++ b/templates/activities/LoginActivity/root/res/values/strings.xml.ftl
@@ -1,6 +1,6 @@
<resources>
<#if !isNewProject>
- <string name="title_${simpleName}">${activityTitle}</string>
+ <string name="title_${simpleName}">${escapeXmlString(activityTitle)}</string>
</#if>
<!-- Strings related to login -->
diff --git a/templates/activities/MasterDetailFlow/globals.xml.ftl b/templates/activities/MasterDetailFlow/globals.xml.ftl
index 519c081..952e278 100644
--- a/templates/activities/MasterDetailFlow/globals.xml.ftl
+++ b/templates/activities/MasterDetailFlow/globals.xml.ftl
@@ -1,8 +1,8 @@
<?xml version="1.0"?>
<globals>
<global id="srcOut" value="src/${slashedPackageName(packageName)}" />
- <global id="CollectionName" value="${objectKind}List" />
- <global id="collection_name" value="${objectKind?lower_case}_list" />
- <global id="DetailName" value="${objectKind}Detail" />
- <global id="detail_name" value="${objectKind?lower_case}_detail" />
+ <global id="CollectionName" value="${extractLetters(objectKind)}List" />
+ <global id="collection_name" value="${extractLetters(objectKind?lower_case)}_list" />
+ <global id="DetailName" value="${extractLetters(objectKind)}Detail" />
+ <global id="detail_name" value="${extractLetters(objectKind?lower_case)}_detail" />
</globals>
diff --git a/templates/activities/MasterDetailFlow/recipe.xml.ftl b/templates/activities/MasterDetailFlow/recipe.xml.ftl
index 2c1f057..8b09c84 100644
--- a/templates/activities/MasterDetailFlow/recipe.xml.ftl
+++ b/templates/activities/MasterDetailFlow/recipe.xml.ftl
@@ -11,7 +11,7 @@
<instantiate from="res/layout/activity_content_list.xml.ftl"
to="res/layout/activity_${collection_name}.xml" />
<instantiate from="res/layout/activity_content_twopane.xml.ftl"
- to="res/layout/activity_${objectKind?lower_case}_twopane.xml" />
+ to="res/layout/activity_${extractLetters(objectKind?lower_case)}_twopane.xml" />
<instantiate from="res/layout/fragment_content_detail.xml.ftl"
to="res/layout/fragment_${detail_name}.xml" />
diff --git a/templates/activities/MasterDetailFlow/root/res/values-large/refs.xml.ftl b/templates/activities/MasterDetailFlow/root/res/values-large/refs.xml.ftl
index 3008e2e..97215c3 100644
--- a/templates/activities/MasterDetailFlow/root/res/values-large/refs.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/res/values-large/refs.xml.ftl
@@ -6,5 +6,5 @@
For more on layout aliases, see:
http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters
-->
- <item type="layout" name="activity_${collection_name}">@layout/activity_${objectKind?lower_case}_twopane</item>
+ <item type="layout" name="activity_${collection_name}">@layout/activity_${extractLetters(objectKind?lower_case)}_twopane</item>
</resources>
diff --git a/templates/activities/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl b/templates/activities/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl
index c698e6e..d592404 100644
--- a/templates/activities/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl
@@ -7,5 +7,5 @@
For more on layout aliases, see:
http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters
-->
- <item type="layout" name="activity_${collection_name}">@layout/activity_${objectKind?lower_case}_twopane</item>
+ <item type="layout" name="activity_${collection_name}">@layout/activity_${extractLetters(objectKind?lower_case)}_twopane</item>
</resources>
diff --git a/templates/activities/MasterDetailFlow/root/res/values/strings.xml.ftl b/templates/activities/MasterDetailFlow/root/res/values/strings.xml.ftl
index 8c555ae..ea882bc 100644
--- a/templates/activities/MasterDetailFlow/root/res/values/strings.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/res/values/strings.xml.ftl
@@ -1,6 +1,6 @@
<resources>
<#if !isNewProject>
- <string name="title_${collection_name}">${objectKindPlural}</string>
+ <string name="title_${collection_name}">${escapeXmlString(objectKindPlural)}</string>
</#if>
- <string name="title_${detail_name}">${objectKind} Detail</string>
+ <string name="title_${detail_name}">${escapeXmlString(objectKind)} Detail</string>
</resources>
diff --git a/templates/activities/SettingsActivity/root/res/values/strings.xml.ftl b/templates/activities/SettingsActivity/root/res/values/strings.xml.ftl
index bf881a3..8dc52ac 100644
--- a/templates/activities/SettingsActivity/root/res/values/strings.xml.ftl
+++ b/templates/activities/SettingsActivity/root/res/values/strings.xml.ftl
@@ -1,6 +1,6 @@
<resources>
<#if !isNewProject>
- <string name="title_${simpleName}">${activityTitle}</string>
+ <string name="title_${simpleName}">${escapeXmlString(activityTitle)}</string>
</#if>
<!-- Strings related to Settings -->
diff --git a/templates/docs/index.html b/templates/docs/index.html
index 0916157..f8e89eb 100644
--- a/templates/docs/index.html
+++ b/templates/docs/index.html
@@ -471,6 +471,58 @@
<h4>See also</h4>
<p><a href="#toc_underscoretocamelcase"><code>underscoreToCamelCase</code></a></p>
+<h3 data-toctitle="escapeXmlAttribute">string <em>escapeXmlAttribute</em>(string)</h3>
+
+<p>This function escapes a string, such as <code>Android's</code> such that it can be used as an XML attribute value: <code>Android&amp;apos;s</code>. In particular, it will escape ', ", &lt; and &amp;.</p>
+
+<h4>Arguments</h4>
+<dl>
+ <dt><code>str</code></dt>
+ <dd>The string to be escaped.</dd>
+</dl>
+
+<h4>See also</h4>
+<p><a href="#toc_escapexmltext"><code>escapeXmlText</code></a></p>
+<p><a href="#toc_escapexmlstring"><code>escapeXmlString</code></a></p>
+
+<h3 data-toctitle="escapeXmlText">string <em>escapeXmlText</em>(string)</h3>
+
+<p>This function escapes a string, such as <code>A &amp; B's</code> such that it can be used as XML text. This means it will escape &lt; and &gt;, but unlike <a href="#toc_escapexmlattribute"><code>escapeXmlAttribute</code></a> it will <b>not</b> escape ' and ". In the preceeding example, it will escape the string to <code>A &amp;amp; B\s</code>. Note that if you plan to use the XML text as the value for a &lt;string&gt; resource value, you should consider using <a href="#toc_escapexmlstring"><code>escapeXmlString</code></a> instead, since it performs additional escapes necessary for string resources.</p>
+
+<h4>Arguments</h4>
+<dl>
+ <dt><code>str</code></dt>
+ <dd>The string to escape to proper XML text.</dd>
+</dl>
+
+<h4>See also</h4>
+<p><a href="#toc_escapexmlattribute"><code>escapeXmlAttribute</code></a></p>
+<p><a href="#toc_escapexmlstring"><code>escapeXmlString</code></a></p>
+
+<h3 data-toctitle="escapeXmlString">string <em>escapeXmlString</em>(string)</h3>
+
+<p>This function escapes a string, such as <code>A &amp; B's</code> such that it is suitable to be inserted in a string resource file as XML text, such as <code>A &amp;amp; B\s</code>. In addition to escaping XML characters like &lt; and &amp;, it also performs additional Android specific escapes, such as escaping apostrophes with a backslash, and so on.</p>
+
+<h4>Arguments</h4>
+<dl>
+ <dt><code>str</code></dt>
+ <dd>The string, e.g. <code>Activity's Title</code> to escape to a proper resource XML value.</dd>
+</dl>
+
+<h4>See also</h4>
+<p><a href="#toc_escapexmlattribute"><code>escapeXmlAttribute</code></a></p>
+<p><a href="#toc_escapexmltext"><code>escapeXmlText</code></a></p>
+
+<h3 data-toctitle="extractLetters">string <em>extractLetters</em>(string)</h3>
+
+<p>This function extracts all the letters from a string, effectively removing any punctuation and whitespace characters.</p>
+
+<h4>Arguments</h4>
+<dl>
+ <dt><code>str</code></dt>
+ <dd>The string to extract letters from</dd>
+</dl>
+
<h3 data-toctitle="classToResource">string <em>classToResource</em>(string)</h3>
<p>This function converts an Android class name, such as <code>FooActivity</code> or <code>FooFragment</code>, to a corresponding resource-friendly identifier string, such as <code>foo</code>, stripping the 'Activity' or 'Fragment' suffix. Currently stripped suffixes are listed below.</p>
diff --git a/templates/projects/NewAndroidApplication/root/res/values/strings.xml.ftl b/templates/projects/NewAndroidApplication/root/res/values/strings.xml.ftl
index 557e5c2..ee03444 100644
--- a/templates/projects/NewAndroidApplication/root/res/values/strings.xml.ftl
+++ b/templates/projects/NewAndroidApplication/root/res/values/strings.xml.ftl
@@ -1,3 +1,3 @@
<resources>
- <string name="app_name">${appTitle}</string>
+ <string name="app_name">${escapeXmlString(appTitle)}</string>
</resources>