Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Sievers2015-04-23 04:16:02 -0400
committerJan Sievers2015-04-23 04:16:02 -0400
commit3283fdca602b1aee0c24c504d84147d74c27c7f1 (patch)
tree8512e8f53af8a2873863f8a766a9b7e98a82d36b
parentbfc69954d480b444ef4a93fe4ff68bbf99612caf (diff)
downloadorg.eclipse.tycho-3283fdca602b1aee0c24c504d84147d74c27c7f1.tar.gz
org.eclipse.tycho-3283fdca602b1aee0c24c504d84147d74c27c7f1.tar.xz
org.eclipse.tycho-3283fdca602b1aee0c24c504d84147d74c27c7f1.zip
464980 stable iteration order for build.properties keys
Make sure build.properties keys which are kept in maps have a defined and stable iteration order. Before, iteration order was undefined (depending on JDKs hash table implementation details). Now keys are added in sorted order and LinkedHashMaps are used to make sure iteration order is the same as insertion order. Bug: 464980 Change-Id: I1024bd03da2d5439f1d3a1d4a4599cd49901be73 Signed-off-by: Jan Sievers <jan.sievers@sap.com>
-rw-r--r--tycho-bundles/org.eclipse.tycho.core.shared.tests/src/test/java/org/eclipse/tycho/core/shared/BuildPropertiesImplTest.java84
-rw-r--r--tycho-bundles/org.eclipse.tycho.core.shared/src/main/java/org/eclipse/tycho/core/shared/BuildPropertiesImpl.java48
2 files changed, 98 insertions, 34 deletions
diff --git a/tycho-bundles/org.eclipse.tycho.core.shared.tests/src/test/java/org/eclipse/tycho/core/shared/BuildPropertiesImplTest.java b/tycho-bundles/org.eclipse.tycho.core.shared.tests/src/test/java/org/eclipse/tycho/core/shared/BuildPropertiesImplTest.java
index d95cdecaa..d059400b3 100644
--- a/tycho-bundles/org.eclipse.tycho.core.shared.tests/src/test/java/org/eclipse/tycho/core/shared/BuildPropertiesImplTest.java
+++ b/tycho-bundles/org.eclipse.tycho.core.shared.tests/src/test/java/org/eclipse/tycho/core/shared/BuildPropertiesImplTest.java
@@ -18,28 +18,64 @@ import static org.junit.Assert.assertNotNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
+import java.util.Set;
import org.junit.Test;
public class BuildPropertiesImplTest {
- @Test
- public void testSupportedKeys() throws IOException {
- FileInputStream in = null;
- Properties properties = new Properties();
- try {
- in = new FileInputStream(new File("resources/testbuild.properties"));
- properties.load(in);
- } finally {
- if (in != null) {
- in.close();
+ /**
+ * Simulate Properties with different key/entry iteration order in different JDKs.
+ */
+ private static class SortedProperties extends Properties {
+
+ private boolean reverse;
+
+ public SortedProperties(boolean reverseSortOrder) {
+ super();
+ this.reverse = reverseSortOrder;
+ }
+
+ @Override
+ public Set keySet() {
+ List sortedList = new ArrayList(super.keySet());
+ Collections.sort(sortedList);
+ if (reverse) {
+ Collections.reverse(sortedList);
}
+ return new LinkedHashSet(sortedList);
}
- BuildPropertiesImpl buildProperties = new BuildPropertiesImpl(properties);
+
+ @Override
+ public Set<Map.Entry<Object, Object>> entrySet() {
+ List<Map.Entry<Object, Object>> sortedList = new ArrayList(super.entrySet());
+ Collections.sort(sortedList, new Comparator<Map.Entry<Object, Object>>() {
+
+ @Override
+ public int compare(java.util.Map.Entry<Object, Object> o1, java.util.Map.Entry<Object, Object> o2) {
+ return ((String) o2.getKey()).compareTo((String) o1.getKey());
+ }
+ });
+ if (reverse) {
+ Collections.reverse(sortedList);
+ }
+ return new LinkedHashSet(sortedList);
+ }
+ }
+
+ @Test
+ public void testSupportedKeys() throws IOException {
+ BuildPropertiesImpl buildProperties = new BuildPropertiesImpl(readProperties(new File(
+ "resources/testbuild.properties")));
assertEquals("1.3", buildProperties.getJavacSource());
assertEquals("1.1", buildProperties.getJavacTarget());
assertEquals("JavaSE-1.6", buildProperties.getJreCompilationProfile());
@@ -65,8 +101,34 @@ public class BuildPropertiesImplTest {
}
@Test
+ public void testKeyOrderIsStable() throws Exception {
+ Properties sortedProperties = new SortedProperties(false);
+ sortedProperties.setProperty("source.a.jar", "source-a1/,source-a2/");
+ sortedProperties.setProperty("source.b.jar", "source-b1/,source-b2/");
+ sortedProperties.setProperty("source.c.jar", "source-c1/,source-c2/");
+
+ Properties reverseSortedProperties = new SortedProperties(true);
+ reverseSortedProperties.putAll(sortedProperties);
+
+ BuildPropertiesImpl buildProperties1 = new BuildPropertiesImpl(sortedProperties);
+ BuildPropertiesImpl buildProperties2 = new BuildPropertiesImpl(reverseSortedProperties);
+ List<String> sourceFolderKeys1 = new ArrayList<String>(buildProperties1.getJarToSourceFolderMap().keySet());
+ List<String> sourceFolderKeys2 = new ArrayList<String>(buildProperties2.getJarToSourceFolderMap().keySet());
+ assertEquals("keyset iteration order must be stable.", sourceFolderKeys1, sourceFolderKeys2);
+ }
+
+ @Test
public void testNoBuildPropertiesFileFound() throws Exception {
BuildPropertiesImpl buildProperties = new BuildPropertiesImpl(new Properties());
assertNotNull(buildProperties);
}
+
+ private static Properties readProperties(File propsFile) throws IOException {
+ Properties properties = new Properties();
+ try (InputStream is = new FileInputStream(propsFile)) {
+ properties.load(is);
+ }
+ return properties;
+ }
+
}
diff --git a/tycho-bundles/org.eclipse.tycho.core.shared/src/main/java/org/eclipse/tycho/core/shared/BuildPropertiesImpl.java b/tycho-bundles/org.eclipse.tycho.core.shared/src/main/java/org/eclipse/tycho/core/shared/BuildPropertiesImpl.java
index 566da9a86..8dbac230a 100644
--- a/tycho-bundles/org.eclipse.tycho.core.shared/src/main/java/org/eclipse/tycho/core/shared/BuildPropertiesImpl.java
+++ b/tycho-bundles/org.eclipse.tycho.core.shared/src/main/java/org/eclipse/tycho/core/shared/BuildPropertiesImpl.java
@@ -14,9 +14,9 @@ package org.eclipse.tycho.core.shared;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Properties;
public class BuildPropertiesImpl implements BuildProperties {
@@ -57,33 +57,35 @@ public class BuildPropertiesImpl implements BuildProperties {
jarsExtraClasspath = splitAndTrimCommaSeparated(properties.getProperty("jars.extra.classpath"));
jarsCompileOrder = splitAndTrimCommaSeparated(properties.getProperty("jars.compile.order"));
- HashMap<String, List<String>> jarTosourceFolderTmp = new HashMap<String, List<String>>();
- HashMap<String, List<String>> jarToExtraClasspathTmp = new HashMap<String, List<String>>();
- HashMap<String, String> jarToJavacDefaultEncodingTmp = new HashMap<String, String>();
- HashMap<String, String> jarToOutputFolderMapTmp = new HashMap<String, String>();
- HashMap<String, String> jarToManifestMapTmp = new HashMap<String, String>();
- HashMap<String, String> rootEntriesTmp = new HashMap<String, String>();
-
- for (Entry<Object, Object> entry : properties.entrySet()) {
- String key = ((String) entry.getKey()).trim();
- String value = ((String) entry.getValue()).trim();
- if (key.startsWith("source.")) {
- String jarName = key.substring("source.".length());
+ HashMap<String, List<String>> jarTosourceFolderTmp = new LinkedHashMap<String, List<String>>();
+ HashMap<String, List<String>> jarToExtraClasspathTmp = new LinkedHashMap<String, List<String>>();
+ HashMap<String, String> jarToJavacDefaultEncodingTmp = new LinkedHashMap<String, String>();
+ HashMap<String, String> jarToOutputFolderMapTmp = new LinkedHashMap<String, String>();
+ HashMap<String, String> jarToManifestMapTmp = new LinkedHashMap<String, String>();
+ HashMap<String, String> rootEntriesTmp = new LinkedHashMap<String, String>();
+
+ List<String> sortedKeys = new ArrayList(properties.keySet());
+ Collections.sort(sortedKeys);
+ for (String key : sortedKeys) {
+ String trimmedKey = key.trim();
+ String value = properties.getProperty(key);
+ if (trimmedKey.startsWith("source.")) {
+ String jarName = trimmedKey.substring("source.".length());
jarTosourceFolderTmp.put(jarName, splitAndTrimCommaSeparated(value));
- } else if (key.startsWith("extra.")) {
- String jarName = key.substring("extra.".length());
+ } else if (trimmedKey.startsWith("extra.")) {
+ String jarName = trimmedKey.substring("extra.".length());
jarToExtraClasspathTmp.put(jarName, splitAndTrimCommaSeparated(value));
- } else if (key.startsWith("javacDefaultEncoding.")) {
- String jarName = key.substring("javacDefaultEncoding.".length());
+ } else if (trimmedKey.startsWith("javacDefaultEncoding.")) {
+ String jarName = trimmedKey.substring("javacDefaultEncoding.".length());
jarToJavacDefaultEncodingTmp.put(jarName, value);
- } else if (key.startsWith("output.")) {
- String jarName = key.substring("output.".length());
+ } else if (trimmedKey.startsWith("output.")) {
+ String jarName = trimmedKey.substring("output.".length());
jarToOutputFolderMapTmp.put(jarName, value);
- } else if (key.startsWith("manifest.")) {
- String jarName = key.substring("manifest.".length());
+ } else if (trimmedKey.startsWith("manifest.")) {
+ String jarName = trimmedKey.substring("manifest.".length());
jarToManifestMapTmp.put(jarName, value);
- } else if (key.startsWith("root.") || key.equals("root")) {
- rootEntriesTmp.put(key, value);
+ } else if (trimmedKey.startsWith("root.") || trimmedKey.equals("root")) {
+ rootEntriesTmp.put(trimmedKey, value);
}
}
jarToSourceFolderMap = unmodifiableMap(jarTosourceFolderTmp);

Back to the top