From 4c75ea858ab3d1175daaa03744d9693dcc15dd8d Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 23 May 2013 14:43:12 -0700 Subject: [PATCH] Check all regexp patterns in ResourceUtils.getDeviceOverrideValue This change also fixes a regexp error of Galaxy S III. Change-Id: I42a4780bbfd2b083f4e27e61ec513aa875907344 --- .../values/keypress-vibration-durations.xml | 2 +- .../inputmethod/latin/ResourceUtils.java | 81 ++++++++++++----- .../inputmethod/latin/ResourceUtilsTests.java | 86 +++++++++++-------- 3 files changed, 107 insertions(+), 62 deletions(-) diff --git a/java/res/values/keypress-vibration-durations.xml b/java/res/values/keypress-vibration-durations.xml index 9ce5051d2..ad6beadb6 100644 --- a/java/res/values/keypress-vibration-durations.xml +++ b/java/res/values/keypress-vibration-durations.xml @@ -37,7 +37,7 @@ MODEL=(SAMSUNG-)?GT-I(930[05][NT]?|9308):MANUFACTURER=samsung,8 MODEL=(SAMSUNG-)?SGH-(T999[V]?|I747[M]?|N064|N035):MANUFACTURER=samsung,8 MODEL=(SAMSUNG-)?SCH-(J021|R530|I535|I939):MANUFACTURER=samsung,8 - MODEL=(SAMSUNG-)?(SCL21|SC-06D|SC-03E]):MANUFACTURER=samsung,8 + MODEL=(SAMSUNG-)?(SCL21|SC-06D|SC-03E):MANUFACTURER=samsung,8 MODEL=(SAMSUNG-)?(SHV-210[KLS]?|SPH-L710):MANUFACTURER=samsung,8 MODEL=LG-E97[013]|LS970|L-01E:MANUFACTURER=LGE,15 diff --git a/java/src/com/android/inputmethod/latin/ResourceUtils.java b/java/src/com/android/inputmethod/latin/ResourceUtils.java index a9fba5348..0eb8b4f09 100644 --- a/java/src/com/android/inputmethod/latin/ResourceUtils.java +++ b/java/src/com/android/inputmethod/latin/ResourceUtils.java @@ -27,6 +27,7 @@ import com.android.inputmethod.annotations.UsedForTesting; import java.util.ArrayList; import java.util.HashMap; +import java.util.regex.PatternSyntaxException; public final class ResourceUtils { private static final String TAG = ResourceUtils.class.getSimpleName(); @@ -83,22 +84,39 @@ public final class ResourceUtils { return overrideValue; } - final String defaultValue = findDefaultConstant(overrideArray); - // The defaultValue might be an empty string. - if (defaultValue == null) { - Log.w(TAG, "Couldn't find override value nor default value:" - + " resource="+ res.getResourceEntryName(overrideResId) - + " build=" + sBuildKeyValuesDebugString); - } else { - Log.i(TAG, "Found default value:" - + " resource="+ res.getResourceEntryName(overrideResId) - + " build=" + sBuildKeyValuesDebugString - + " default=" + defaultValue); + String defaultValue = null; + try { + defaultValue = findDefaultConstant(overrideArray); + // The defaultValue might be an empty string. + if (defaultValue == null) { + Log.w(TAG, "Couldn't find override value nor default value:" + + " resource="+ res.getResourceEntryName(overrideResId) + + " build=" + sBuildKeyValuesDebugString); + } else { + Log.i(TAG, "Found default value:" + + " resource="+ res.getResourceEntryName(overrideResId) + + " build=" + sBuildKeyValuesDebugString + + " default=" + defaultValue); + } + } catch (final DeviceOverridePatternSyntaxError e) { + Log.w(TAG, "Syntax error, ignored", e); } sDeviceOverrideValueMap.put(key, defaultValue); return defaultValue; } + @SuppressWarnings("serial") + static class DeviceOverridePatternSyntaxError extends Exception { + public DeviceOverridePatternSyntaxError(final String message, final String expression) { + this(message, expression, null); + } + + public DeviceOverridePatternSyntaxError(final String message, final String expression, + final Throwable throwable) { + super(message + ": " + expression, throwable); + } + } + /** * Find the condition that fulfills specified key value pairs from an array of * "condition,constant", and return the corresponding string constant. A condition is @@ -123,10 +141,12 @@ public final class ResourceUtils { if (conditionConstantArray == null || keyValuePairs == null) { return null; } + String foundValue = null; for (final String conditionConstant : conditionConstantArray) { final int posComma = conditionConstant.indexOf(','); if (posComma < 0) { - throw new RuntimeException("Array element has no comma: " + conditionConstant); + Log.w(TAG, "Array element has no comma: " + conditionConstant); + continue; } final String condition = conditionConstant.substring(0, posComma); if (condition.isEmpty()) { @@ -134,44 +154,59 @@ public final class ResourceUtils { // {@link #findConstantForDefault(String[])}. continue; } - if (fulfillsCondition(keyValuePairs, condition)) { - return conditionConstant.substring(posComma + 1); + try { + if (fulfillsCondition(keyValuePairs, condition)) { + // Take first match + if (foundValue == null) { + foundValue = conditionConstant.substring(posComma + 1); + } + // And continue walking through all conditions. + } + } catch (final DeviceOverridePatternSyntaxError e) { + Log.w(TAG, "Syntax error, ignored", e); } } - return null; + return foundValue; } private static boolean fulfillsCondition(final HashMap keyValuePairs, - final String condition) { + final String condition) throws DeviceOverridePatternSyntaxError { final String[] patterns = condition.split(":"); // Check all patterns in a condition are true + boolean matchedAll = true; for (final String pattern : patterns) { final int posEqual = pattern.indexOf('='); if (posEqual < 0) { - throw new RuntimeException("Pattern has no '=': " + condition); + throw new DeviceOverridePatternSyntaxError("Pattern has no '='", condition); } final String key = pattern.substring(0, posEqual); final String value = keyValuePairs.get(key); if (value == null) { - throw new RuntimeException("Found unknown key: " + condition); + throw new DeviceOverridePatternSyntaxError("Unknown key", condition); } final String patternRegexpValue = pattern.substring(posEqual + 1); - if (!value.matches(patternRegexpValue)) { - return false; + try { + if (!value.matches(patternRegexpValue)) { + matchedAll = false; + // And continue walking through all patterns. + } + } catch (final PatternSyntaxException e) { + throw new DeviceOverridePatternSyntaxError("Syntax error", condition, e); } } - return true; + return matchedAll; } @UsedForTesting - static String findDefaultConstant(final String[] conditionConstantArray) { + static String findDefaultConstant(final String[] conditionConstantArray) + throws DeviceOverridePatternSyntaxError { if (conditionConstantArray == null) { return null; } for (final String condition : conditionConstantArray) { final int posComma = condition.indexOf(','); if (posComma < 0) { - throw new RuntimeException("Array element has no comma: " + condition); + throw new DeviceOverridePatternSyntaxError("Array element has no comma", condition); } if (posComma == 0) { // condition is empty. return condition.substring(posComma + 1); diff --git a/tests/src/com/android/inputmethod/latin/ResourceUtilsTests.java b/tests/src/com/android/inputmethod/latin/ResourceUtilsTests.java index ed16846b9..c915522ee 100644 --- a/tests/src/com/android/inputmethod/latin/ResourceUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/ResourceUtilsTests.java @@ -19,25 +19,41 @@ package com.android.inputmethod.latin; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; +import com.android.inputmethod.latin.ResourceUtils.DeviceOverridePatternSyntaxError; + import java.util.HashMap; @SmallTest public class ResourceUtilsTests extends AndroidTestCase { public void testFindDefaultConstant() { final String[] nullArray = null; - assertNull(ResourceUtils.findDefaultConstant(nullArray)); - final String[] emptyArray = {}; - assertNull(ResourceUtils.findDefaultConstant(emptyArray)); - final String[] array = { - "HARDWARE=grouper,0.3", - "HARDWARE=mako,0.4", - ",defaultValue1", - "HARDWARE=manta,0.2", - ",defaultValue2", + "HARDWARE=grouper,0.3", + "HARDWARE=mako,0.4", + ",defaultValue1", + "HARDWARE=manta,0.2", + ",defaultValue2", }; - assertEquals(ResourceUtils.findDefaultConstant(array), "defaultValue1"); + + try { + assertNull(ResourceUtils.findDefaultConstant(nullArray)); + assertNull(ResourceUtils.findDefaultConstant(emptyArray)); + assertEquals(ResourceUtils.findDefaultConstant(array), "defaultValue1"); + } catch (final DeviceOverridePatternSyntaxError e) { + fail(e.getMessage()); + } + + final String[] errorArray = { + "HARDWARE=grouper,0.3", + "no_comma" + }; + try { + final String defaultValue = ResourceUtils.findDefaultConstant(errorArray); + fail("exception should be thrown: defaultValue=" + defaultValue); + } catch (final DeviceOverridePatternSyntaxError e) { + assertEquals("Array element has no comma: no_comma", e.getMessage()); + } } public void testFindConstantForKeyValuePairsSimple() { @@ -67,33 +83,23 @@ public class ResourceUtilsTests extends AndroidTestCase { final HashMap keyValues = CollectionUtils.newHashMap(); keyValues.put(HARDWARE_KEY, "grouper"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.3"); + assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); keyValues.put(HARDWARE_KEY, "mako"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.4"); + assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); keyValues.put(HARDWARE_KEY, "manta"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.2"); + assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + + keyValues.clear(); + keyValues.put("hardware", "grouper"); + assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); - try { - keyValues.clear(); - keyValues.put("hardware", "grouper"); - final String constant = ResourceUtils.findConstantForKeyValuePairs(keyValues, array); - fail("condition without HARDWARE must fail: constant=" + constant); - } catch (final RuntimeException e) { - assertEquals(e.getMessage(), "Found unknown key: HARDWARE=grouper"); - } keyValues.clear(); keyValues.put(HARDWARE_KEY, "MAKO"); assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); keyValues.put(HARDWARE_KEY, "mantaray"); assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); - try { - final String constant = ResourceUtils.findConstantForKeyValuePairs( - emptyKeyValue, array); - fail("emptyCondition shouldn't match: constant=" + constant); - } catch (final RuntimeException e) { - assertEquals(e.getMessage(), "Found unknown key: HARDWARE=grouper"); - } + assertNull(ResourceUtils.findConstantForKeyValuePairs(emptyKeyValue, array)); } public void testFindConstantForKeyValuePairsCombined() { @@ -102,6 +108,8 @@ public class ResourceUtilsTests extends AndroidTestCase { final String MANUFACTURER_KEY = "MANUFACTURER"; final String[] array = { ",defaultValue", + "no_comma", + "error_pattern,0.1", "HARDWARE=grouper:MANUFACTURER=asus,0.3", "HARDWARE=mako:MODEL=Nexus 4,0.4", "HARDWARE=manta:MODEL=Nexus 10:MANUFACTURER=samsung,0.2" @@ -117,25 +125,25 @@ public class ResourceUtilsTests extends AndroidTestCase { keyValues.put(HARDWARE_KEY, "grouper"); keyValues.put(MODEL_KEY, "Nexus 7"); keyValues.put(MANUFACTURER_KEY, "asus"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.3"); + assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray)); keyValues.clear(); keyValues.put(HARDWARE_KEY, "mako"); keyValues.put(MODEL_KEY, "Nexus 4"); keyValues.put(MANUFACTURER_KEY, "LGE"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.4"); + assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray)); keyValues.clear(); keyValues.put(HARDWARE_KEY, "manta"); keyValues.put(MODEL_KEY, "Nexus 10"); keyValues.put(MANUFACTURER_KEY, "samsung"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.2"); + assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray)); keyValues.put(HARDWARE_KEY, "mantaray"); assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray), "0.2"); + assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray)); } public void testFindConstantForKeyValuePairsRegexp() { @@ -144,6 +152,8 @@ public class ResourceUtilsTests extends AndroidTestCase { final String MANUFACTURER_KEY = "MANUFACTURER"; final String[] array = { ",defaultValue", + "no_comma", + "HARDWARE=error_regexp:MANUFACTURER=error[regexp,0.1", "HARDWARE=grouper|tilapia:MANUFACTURER=asus,0.3", "HARDWARE=[mM][aA][kK][oO]:MODEL=Nexus 4,0.4", "HARDWARE=manta.*:MODEL=Nexus 10:MANUFACTURER=samsung,0.2" @@ -153,24 +163,24 @@ public class ResourceUtilsTests extends AndroidTestCase { keyValues.put(HARDWARE_KEY, "grouper"); keyValues.put(MODEL_KEY, "Nexus 7"); keyValues.put(MANUFACTURER_KEY, "asus"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.3"); + assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); keyValues.put(HARDWARE_KEY, "tilapia"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.3"); + assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); keyValues.clear(); keyValues.put(HARDWARE_KEY, "mako"); keyValues.put(MODEL_KEY, "Nexus 4"); keyValues.put(MANUFACTURER_KEY, "LGE"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.4"); + assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); keyValues.put(HARDWARE_KEY, "MAKO"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.4"); + assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); keyValues.clear(); keyValues.put(HARDWARE_KEY, "manta"); keyValues.put(MODEL_KEY, "Nexus 10"); keyValues.put(MANUFACTURER_KEY, "samsung"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.2"); + assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); keyValues.put(HARDWARE_KEY, "mantaray"); - assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.2"); + assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); } }