Added support for conditionally including resources based on os.arch as well as
os.name. If no architecture is specified, all architectures match, which preserves the existing behavior. Restructured things along the way to be more amenable to unit testing, and added some unit tests.
This commit is contained in:
@@ -23,17 +23,16 @@
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
package com.threerings.getdown.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import com.samskivert.io.StreamUtil;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import static com.threerings.getdown.Log.log;
|
||||
@@ -48,81 +47,30 @@ public class ConfigUtil
|
||||
* Parses a configuration file containing key/value pairs. The file must be in the UTF-8
|
||||
* encoding.
|
||||
*
|
||||
* @param checkPlatform if true, platform qualifiers will be used to filter out pairs that do
|
||||
* not match the current platform; if false, all pairs will be returned.
|
||||
*
|
||||
* @return a list of <code>String[]</code> instances containing the key/value pairs in the
|
||||
* order they were parsed from the file.
|
||||
*/
|
||||
public static List<String[]> parsePairs (File config, boolean checkPlatform)
|
||||
throws IOException
|
||||
{
|
||||
ArrayList<String[]> pairs = new ArrayList<String[]>();
|
||||
String osname = System.getProperty("os.name");
|
||||
osname = (osname == null) ? "" : osname.toLowerCase();
|
||||
// annoyingly FileReader does not allow encoding to be specified (uses platform default)
|
||||
return parsePairs(
|
||||
new InputStreamReader(new FileInputStream(config), "UTF-8"), checkPlatform);
|
||||
}
|
||||
|
||||
// parse our configuration file
|
||||
FileInputStream fin = null;
|
||||
try {
|
||||
fin = new FileInputStream(config);
|
||||
BufferedReader bin = new BufferedReader(new InputStreamReader(fin, "UTF-8"));
|
||||
String line = null;
|
||||
while ((line = bin.readLine()) != null) {
|
||||
// nix comments
|
||||
int cidx = line.indexOf("#");
|
||||
if (cidx != -1) {
|
||||
line = line.substring(0, cidx);
|
||||
}
|
||||
|
||||
// trim whitespace and skip blank lines
|
||||
line = line.trim();
|
||||
if (StringUtil.isBlank(line)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse our key/value pair
|
||||
String[] pair = new String[2];
|
||||
int eidx = line.indexOf("=");
|
||||
if (eidx != -1) {
|
||||
pair[0] = line.substring(0, eidx).trim();
|
||||
pair[1] = line.substring(eidx+1).trim();
|
||||
} else {
|
||||
pair[0] = line;
|
||||
pair[1] = "";
|
||||
}
|
||||
|
||||
// allow a value to have a [Linux]
|
||||
if (pair[1].startsWith("[")) {
|
||||
cidx = pair[1].indexOf("]");
|
||||
if (cidx == -1) {
|
||||
log.warning("Bogus platform specifier [key=" + pair[0] +
|
||||
", value=" + pair[1] + "].");
|
||||
} else {
|
||||
String platform = pair[1].substring(1, cidx);
|
||||
platform = platform.trim().toLowerCase();
|
||||
pair[1] = pair[1].substring(cidx+1).trim();
|
||||
if (checkPlatform) {
|
||||
if (platform.startsWith("!")) {
|
||||
platform = platform.substring(1);
|
||||
if (osname.indexOf(platform) != -1) {
|
||||
log.info("Skipping [platform=!" + platform +
|
||||
", key=" + pair[0] + ", value=" + pair[1] + "].");
|
||||
continue;
|
||||
}
|
||||
} else if (osname.indexOf(platform) == -1) {
|
||||
log.info("Skipping [platform=" + platform +
|
||||
", key=" + pair[0] + ", value=" + pair[1] + "].");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pairs.add(pair);
|
||||
}
|
||||
|
||||
} finally {
|
||||
StreamUtil.close(fin);
|
||||
}
|
||||
|
||||
return pairs;
|
||||
/**
|
||||
* See {@link #parsePairs(File,boolean}.
|
||||
*/
|
||||
public static List<String[]> parsePairs (Reader config, boolean checkPlatform)
|
||||
throws IOException
|
||||
{
|
||||
return parsePairs(
|
||||
config,
|
||||
checkPlatform ? StringUtil.deNull(System.getProperty("os.name")).toLowerCase() : null,
|
||||
checkPlatform ? StringUtil.deNull(System.getProperty("os.arch")).toLowerCase() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,4 +119,90 @@ public class ConfigUtil
|
||||
return (String[])value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function for {@link #parsePairs(Reader,boolean}.
|
||||
*/
|
||||
protected static List<String[]> parsePairs (Reader config, String osname, String osarch)
|
||||
throws IOException
|
||||
{
|
||||
List<String[]> pairs = new ArrayList<String[]>();
|
||||
for (String line : FileUtil.readLines(config)) {
|
||||
// nix comments
|
||||
int cidx = line.indexOf("#");
|
||||
if (cidx != -1) {
|
||||
line = line.substring(0, cidx);
|
||||
}
|
||||
|
||||
// trim whitespace and skip blank lines
|
||||
line = line.trim();
|
||||
if (StringUtil.isBlank(line)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse our key/value pair
|
||||
String[] pair = new String[2];
|
||||
int eidx = line.indexOf("=");
|
||||
if (eidx != -1) {
|
||||
pair[0] = line.substring(0, eidx).trim();
|
||||
pair[1] = line.substring(eidx+1).trim();
|
||||
} else {
|
||||
pair[0] = line;
|
||||
pair[1] = "";
|
||||
}
|
||||
|
||||
// if the pair has an os qualifier, we need to process it
|
||||
if (pair[1].startsWith("[")) {
|
||||
int qidx = pair[1].indexOf("]");
|
||||
if (qidx == -1) {
|
||||
log.warning("Bogus platform specifier", "key", pair[0], "value", pair[1]);
|
||||
continue; // omit the pair entirely
|
||||
}
|
||||
// if we're checking qualifiers and the os doesn't match this qualifier, skip it
|
||||
String quals = pair[1].substring(1, qidx);
|
||||
if (osname != null && !checkQualifiers(quals, osname, osarch)) {
|
||||
log.info("Skipping", "quals", quals, "osname", osname, "osarch", osarch,
|
||||
"key", pair[0], "value", pair[1]);
|
||||
continue;
|
||||
}
|
||||
// otherwise filter out the qualifier text
|
||||
pair[1] = pair[1].substring(qidx+1).trim();
|
||||
}
|
||||
|
||||
pairs.add(pair);
|
||||
}
|
||||
|
||||
return pairs;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function for {@link #parsePairs(Reader,String,String)}. Qualifiers have the
|
||||
* following form:
|
||||
* <pre>
|
||||
* id = os[-arch]
|
||||
* ids = id | id,ids
|
||||
* quals = !id | ids
|
||||
* </pre>
|
||||
* Examples: [linux-amd64,linux-x86_64], [windows], [mac os x], [!windows].
|
||||
*/
|
||||
protected static boolean checkQualifiers (String quals, String osname, String osarch)
|
||||
{
|
||||
for (String qual : quals.split(",")) {
|
||||
String[] bits = qual.trim().toLowerCase().split("-");
|
||||
String os = bits[0], arch = (bits.length > 1) ? bits[1] : "";
|
||||
if (os.startsWith("!")) {
|
||||
// if we have a negative match, we can immediately return false
|
||||
if (osname.indexOf(os.substring(1)) != -1 && osarch.indexOf(arch) != -1) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// if we have a positive match, we can immediately return true
|
||||
if (osname.indexOf(os) != -1 && osarch.indexOf(arch) != -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// we had no positive matches, so return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,15 @@
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
package com.threerings.getdown.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.samskivert.io.StreamUtil;
|
||||
|
||||
@@ -92,4 +97,21 @@ public class FileUtil
|
||||
StreamUtil.close(fout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of the supplied input stream into a list of lines. Closes the reader on
|
||||
* successful or failed completion.
|
||||
*/
|
||||
public static List<String> readLines (Reader in)
|
||||
throws IOException
|
||||
{
|
||||
List<String> lines = new ArrayList<String>();
|
||||
try {
|
||||
BufferedReader bin = new BufferedReader(in);
|
||||
for (String line = null; (line = bin.readLine()) != null; lines.add(line)) {}
|
||||
} finally {
|
||||
StreamUtil.close(in);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Getdown - application installer, patcher and launcher
|
||||
// Copyright (C) 2004-2010 Three Rings Design, Inc.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
// provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
// conditions and the following disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.threerings.getdown.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
|
||||
import com.samskivert.util.RandomUtil;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import org.junit.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests {@link ConfigUtil}.
|
||||
*/
|
||||
public class ConfigUtilTest
|
||||
{
|
||||
public static class Pair {
|
||||
public final String key;
|
||||
public final String value;
|
||||
public Pair (String key, String value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static final Pair[] SIMPLE_PAIRS = {
|
||||
new Pair("one", "two"),
|
||||
new Pair("three", "four"),
|
||||
new Pair("five", "six"),
|
||||
new Pair("seven", "eight"),
|
||||
new Pair("nine", "ten"),
|
||||
};
|
||||
|
||||
@Test public void testSimplePairs () throws IOException
|
||||
{
|
||||
List<String[]> pairs = ConfigUtil.parsePairs(toReader(SIMPLE_PAIRS), true);
|
||||
for (int ii = 0; ii < SIMPLE_PAIRS.length; ii++) {
|
||||
assertEquals(SIMPLE_PAIRS[ii].key, pairs.get(ii)[0]);
|
||||
assertEquals(SIMPLE_PAIRS[ii].value, pairs.get(ii)[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test public void testQualifiedPairs () throws IOException
|
||||
{
|
||||
Pair linux = new Pair("one", "[linux] two");
|
||||
Pair mac = new Pair("three", "[mac os x] four");
|
||||
Pair linuxAndMac = new Pair("five", "[linux, mac os x] six");
|
||||
Pair linux64 = new Pair("seven", "[linux-x86_64] eight");
|
||||
Pair linux64s = new Pair("nine", "[linux-x86_64, linux-amd64] ten");
|
||||
Pair mac64 = new Pair("eleven", "[mac os x-x86_64] twelve");
|
||||
Pair win64 = new Pair("thirteen", "[windows-x86_64] fourteen");
|
||||
Pair[] pairs = { linux, mac, linuxAndMac, linux64, linux64s, mac64, win64 };
|
||||
|
||||
List<String[]> parsed = ConfigUtil.parsePairs(toReader(pairs), "linux", "i386");
|
||||
assertTrue(exists(parsed, linux.key));
|
||||
assertTrue(!exists(parsed, mac.key));
|
||||
assertTrue(exists(parsed, linuxAndMac.key));
|
||||
assertTrue(!exists(parsed, linux64.key));
|
||||
assertTrue(!exists(parsed, linux64s.key));
|
||||
assertTrue(!exists(parsed, mac64.key));
|
||||
assertTrue(!exists(parsed, win64.key));
|
||||
|
||||
parsed = ConfigUtil.parsePairs(toReader(pairs), "linux", "x86_64");
|
||||
assertTrue(exists(parsed, linux.key));
|
||||
assertTrue(!exists(parsed, mac.key));
|
||||
assertTrue(exists(parsed, linuxAndMac.key));
|
||||
assertTrue(exists(parsed, linux64.key));
|
||||
assertTrue(exists(parsed, linux64s.key));
|
||||
assertTrue(!exists(parsed, mac64.key));
|
||||
assertTrue(!exists(parsed, win64.key));
|
||||
|
||||
parsed = ConfigUtil.parsePairs(toReader(pairs), "linux", "amd64");
|
||||
assertTrue(exists(parsed, linux.key));
|
||||
assertTrue(!exists(parsed, mac.key));
|
||||
assertTrue(exists(parsed, linuxAndMac.key));
|
||||
assertTrue(!exists(parsed, linux64.key));
|
||||
assertTrue(exists(parsed, linux64s.key));
|
||||
assertTrue(!exists(parsed, mac64.key));
|
||||
assertTrue(!exists(parsed, win64.key));
|
||||
|
||||
parsed = ConfigUtil.parsePairs(toReader(pairs), "mac os x", "x86_64");
|
||||
assertTrue(!exists(parsed, linux.key));
|
||||
assertTrue(exists(parsed, mac.key));
|
||||
assertTrue(exists(parsed, linuxAndMac.key));
|
||||
assertTrue(!exists(parsed, linux64.key));
|
||||
assertTrue(!exists(parsed, linux64s.key));
|
||||
assertTrue(exists(parsed, mac64.key));
|
||||
assertTrue(!exists(parsed, win64.key));
|
||||
|
||||
parsed = ConfigUtil.parsePairs(toReader(pairs), "windows", "i386");
|
||||
assertTrue(!exists(parsed, linux.key));
|
||||
assertTrue(!exists(parsed, mac.key));
|
||||
assertTrue(!exists(parsed, linuxAndMac.key));
|
||||
assertTrue(!exists(parsed, linux64.key));
|
||||
assertTrue(!exists(parsed, linux64s.key));
|
||||
assertTrue(!exists(parsed, mac64.key));
|
||||
assertTrue(!exists(parsed, win64.key));
|
||||
|
||||
parsed = ConfigUtil.parsePairs(toReader(pairs), "windows", "x86_64");
|
||||
assertTrue(!exists(parsed, linux.key));
|
||||
assertTrue(!exists(parsed, mac.key));
|
||||
assertTrue(!exists(parsed, linuxAndMac.key));
|
||||
assertTrue(!exists(parsed, linux64.key));
|
||||
assertTrue(!exists(parsed, linux64s.key));
|
||||
assertTrue(!exists(parsed, mac64.key));
|
||||
assertTrue(exists(parsed, win64.key));
|
||||
|
||||
parsed = ConfigUtil.parsePairs(toReader(pairs), "windows", "amd64");
|
||||
assertTrue(!exists(parsed, linux.key));
|
||||
assertTrue(!exists(parsed, mac.key));
|
||||
assertTrue(!exists(parsed, linuxAndMac.key));
|
||||
assertTrue(!exists(parsed, linux64.key));
|
||||
assertTrue(!exists(parsed, linux64s.key));
|
||||
assertTrue(!exists(parsed, mac64.key));
|
||||
assertTrue(!exists(parsed, win64.key));
|
||||
}
|
||||
|
||||
protected static boolean exists (List<String[]> pairs, String key)
|
||||
{
|
||||
for (String[] pair : pairs) {
|
||||
if (pair[0].equals(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static StringReader toReader (Pair[] pairs)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (Pair pair : pairs) {
|
||||
// throw some whitespace in to ensure it's trimmed
|
||||
builder.append(whitespace()).append(pair.key).
|
||||
append(whitespace()).append("=").
|
||||
append(whitespace()).append(pair.value).
|
||||
append(whitespace()).append("\n");
|
||||
}
|
||||
return new StringReader(builder.toString());
|
||||
}
|
||||
|
||||
protected static String whitespace ()
|
||||
{
|
||||
return RandomUtil.getBoolean() ? " " : "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Getdown - application installer, patcher and launcher
|
||||
// Copyright (C) 2004-2010 Three Rings Design, Inc.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
// provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
// conditions and the following disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.threerings.getdown.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests {@link FileUtil}.
|
||||
*/
|
||||
public class FileUtilTest
|
||||
{
|
||||
@Test public void testReadLines () throws IOException
|
||||
{
|
||||
String data = "This is a test\nof a file with\na few lines\n";
|
||||
List<String> lines = FileUtil.readLines(new StringReader(data));
|
||||
String[] linesBySplit = data.split("\n");
|
||||
assertEquals(linesBySplit.length, lines.size());
|
||||
for (int ii = 0; ii < lines.size(); ii++) {
|
||||
assertEquals(linesBySplit[ii], lines.get(ii));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user