|
From: <wak...@us...> - 2011-07-03 20:06:48
|
Revision: 1598
http://rails.svn.sourceforge.net/rails/?rev=1598&view=rev
Author: wakko666
Date: 2011-07-03 20:06:38 +0000 (Sun, 03 Jul 2011)
Log Message:
-----------
Refactor GameInfo XML parsing
Modified Paths:
--------------
trunk/18xx/data/GamesList.xml
trunk/18xx/rails/algorithms/RevenueAdapter.java
trunk/18xx/rails/algorithms/RevenueBonusTemplate.java
trunk/18xx/rails/algorithms/RevenueManager.java
trunk/18xx/rails/algorithms/RevenueTrainRun.java
trunk/18xx/rails/game/Bank.java
trunk/18xx/rails/game/BonusToken.java
trunk/18xx/rails/game/Company.java
trunk/18xx/rails/game/CompanyManager.java
trunk/18xx/rails/game/CompanyType.java
trunk/18xx/rails/game/CompanyTypeI.java
trunk/18xx/rails/game/ComponentManager.java
trunk/18xx/rails/game/ConfigurableComponentI.java
trunk/18xx/rails/game/EndOfGameRound.java
trunk/18xx/rails/game/Game.java
trunk/18xx/rails/game/GameManager.java
trunk/18xx/rails/game/MapHex.java
trunk/18xx/rails/game/MapManager.java
trunk/18xx/rails/game/OperatingRound.java
trunk/18xx/rails/game/Phase.java
trunk/18xx/rails/game/PhaseManager.java
trunk/18xx/rails/game/PlayerManager.java
trunk/18xx/rails/game/Portfolio.java
trunk/18xx/rails/game/PrivateCompany.java
trunk/18xx/rails/game/PublicCertificate.java
trunk/18xx/rails/game/PublicCompany.java
trunk/18xx/rails/game/ReportBuffer.java
trunk/18xx/rails/game/Round.java
trunk/18xx/rails/game/ShareSellingRound.java
trunk/18xx/rails/game/StartPacket.java
trunk/18xx/rails/game/StartRound.java
trunk/18xx/rails/game/StartRound_1830.java
trunk/18xx/rails/game/StartRound_1835.java
trunk/18xx/rails/game/StockMarket.java
trunk/18xx/rails/game/StockRound.java
trunk/18xx/rails/game/StockSpaceType.java
trunk/18xx/rails/game/Tile.java
trunk/18xx/rails/game/TileI.java
trunk/18xx/rails/game/TileManager.java
trunk/18xx/rails/game/TrainCertificateType.java
trunk/18xx/rails/game/TrainManager.java
trunk/18xx/rails/game/TrainType.java
trunk/18xx/rails/game/TreasuryShareRound.java
trunk/18xx/rails/game/action/LayBonusToken.java
trunk/18xx/rails/game/correct/CashCorrectionManager.java
trunk/18xx/rails/game/correct/CorrectionManager.java
trunk/18xx/rails/game/correct/CorrectionModeAction.java
trunk/18xx/rails/game/correct/MapCorrectionManager.java
trunk/18xx/rails/game/move/MoveStack.java
trunk/18xx/rails/game/special/ExchangeForShare.java
trunk/18xx/rails/game/special/LocatedBonus.java
trunk/18xx/rails/game/special/SellBonusToken.java
trunk/18xx/rails/game/special/SpecialProperty.java
trunk/18xx/rails/game/special/SpecialRight.java
trunk/18xx/rails/game/special/SpecialTileLay.java
trunk/18xx/rails/game/special/SpecialTokenLay.java
trunk/18xx/rails/game/special/SpecialTrainBuy.java
trunk/18xx/rails/game/specific/_1825/StartRound_1825.java
trunk/18xx/rails/game/specific/_1835/OperatingRound_1835.java
trunk/18xx/rails/game/specific/_1835/PrussianFormationRound.java
trunk/18xx/rails/game/specific/_1835/StockRound_1835.java
trunk/18xx/rails/game/specific/_1851/StartRound_1851.java
trunk/18xx/rails/game/specific/_1856/CGRFormationRound.java
trunk/18xx/rails/game/specific/_1856/OperatingRound_1856.java
trunk/18xx/rails/game/specific/_1856/PublicCompany_CGR.java
trunk/18xx/rails/game/specific/_1856/StockRound_1856.java
trunk/18xx/rails/game/specific/_1880/StartRound_1880.java
trunk/18xx/rails/game/specific/_1880/StockRound_1880.java
trunk/18xx/rails/game/specific/_1889/OperatingRound_1889.java
trunk/18xx/rails/game/specific/_18AL/NameTrains.java
trunk/18xx/rails/game/specific/_18AL/NamedTrainRevenueModifier.java
trunk/18xx/rails/game/specific/_18AL/NamedTrainToken.java
trunk/18xx/rails/game/specific/_18AL/OperatingRound_18AL.java
trunk/18xx/rails/game/specific/_18EU/FinalMinorExchangeRound.java
trunk/18xx/rails/game/specific/_18EU/GameManager_18EU.java
trunk/18xx/rails/game/specific/_18EU/OperatingRound_18EU.java
trunk/18xx/rails/game/specific/_18EU/PullmanRevenueModifier.java
trunk/18xx/rails/game/specific/_18EU/StartRound_18EU.java
trunk/18xx/rails/game/specific/_18EU/StockRound_18EU.java
trunk/18xx/rails/game/specific/_18GA/OperatingRound_18GA.java
trunk/18xx/rails/game/specific/_18Kaas/RuhrRevenueModifier.java
trunk/18xx/rails/test/GameTest.java
trunk/18xx/rails/ui/swing/AbstractReportWindow.java
trunk/18xx/rails/ui/swing/AutoSaveLoadDialog.java
trunk/18xx/rails/ui/swing/ConfigWindow.java
trunk/18xx/rails/ui/swing/GameSetupWindow.java
trunk/18xx/rails/ui/swing/GameStatus.java
trunk/18xx/rails/ui/swing/GameUIManager.java
trunk/18xx/rails/ui/swing/ImageLoader.java
trunk/18xx/rails/ui/swing/ORPanel.java
trunk/18xx/rails/ui/swing/ORUIManager.java
trunk/18xx/rails/ui/swing/ORWindow.java
trunk/18xx/rails/ui/swing/RemainingTilesWindow.java
trunk/18xx/rails/ui/swing/ReportWindow.java
trunk/18xx/rails/ui/swing/ReportWindowDynamic.java
trunk/18xx/rails/ui/swing/Scale.java
trunk/18xx/rails/ui/swing/StartRoundWindow.java
trunk/18xx/rails/ui/swing/StatusWindow.java
trunk/18xx/rails/ui/swing/UpgradesPanel.java
trunk/18xx/rails/ui/swing/WindowSettings.java
trunk/18xx/rails/ui/swing/elements/CheckBoxDialog.java
trunk/18xx/rails/ui/swing/elements/ConfirmationDialog.java
trunk/18xx/rails/ui/swing/elements/MessageDialog.java
trunk/18xx/rails/ui/swing/elements/RadioButtonDialog.java
trunk/18xx/rails/ui/swing/gamespecific/_1835/StatusWindow_1835.java
trunk/18xx/rails/ui/swing/gamespecific/_1856/StatusWindow_1856.java
trunk/18xx/rails/ui/swing/gamespecific/_18AL/NameTrainsDialog.java
trunk/18xx/rails/ui/swing/gamespecific/_18EU/GameStatus_18EU.java
trunk/18xx/rails/ui/swing/gamespecific/_18EU/GameUIManager_18EU.java
trunk/18xx/rails/ui/swing/gamespecific/_18EU/StatusWindow_18EU.java
trunk/18xx/rails/ui/swing/hexmap/HexMap.java
trunk/18xx/rails/ui/swing/hexmap/HexMapImage.java
trunk/18xx/rails/util/ListAndFixSavedFiles.java
trunk/18xx/rails/util/RunGame.java
trunk/18xx/rails/util/Util.java
trunk/18xx/test/TestGame.java
trunk/18xx/test/TestGameBuilder.java
trunk/18xx/tools/ConvertTilesXML.java
trunk/18xx/tools/MakeGameTileSets.java
trunk/18xx/tools/XmlUtils.java
Added Paths:
-----------
trunk/18xx/rails/common/LocalText.java
trunk/18xx/rails/common/MoneyFormatter.java
trunk/18xx/rails/common/ResourceLoader.java
trunk/18xx/rails/common/parser/
trunk/18xx/rails/common/parser/Config.java
trunk/18xx/rails/common/parser/ConfigItem.java
trunk/18xx/rails/common/parser/ConfigurationException.java
trunk/18xx/rails/common/parser/GameInfo.java
trunk/18xx/rails/common/parser/GameInfoParser.java
trunk/18xx/rails/common/parser/GameOption.java
trunk/18xx/rails/common/parser/Tag.java
trunk/18xx/rails/common/parser/XMLParser.java
trunk/18xx/rails/common/parser/XMLTags.java
Removed Paths:
-------------
trunk/18xx/rails/game/ConfigurationException.java
trunk/18xx/rails/game/GameOption.java
trunk/18xx/rails/game/GamesInfo.java
trunk/18xx/rails/util/Config.java
trunk/18xx/rails/util/ConfigItem.java
trunk/18xx/rails/util/Format.java
trunk/18xx/rails/util/LocalText.java
trunk/18xx/rails/util/ResourceLoader.java
trunk/18xx/rails/util/Tag.java
Modified: trunk/18xx/data/GamesList.xml
===================================================================
--- trunk/18xx/data/GamesList.xml 2011-06-30 18:56:00 UTC (rev 1597)
+++ trunk/18xx/data/GamesList.xml 2011-07-03 20:06:38 UTC (rev 1598)
@@ -318,17 +318,33 @@
</Game>
- <Credits>Rails is a computer implementation of a number of railroad board games,
-that are collectively known as the "18xx" railway game system.
-Rails is a Sourceforge project.
-Project founder: Brett Lentz.
-Developers: Erik Vos, Stefan Frey and Brett Lentz.
+ <Credits>Rails is a computer implementation of a number of board games.
+ These games all have a railroad theme. They are collectively known as "18xx"
+ games due to the naming scheme used by many games in the genre.
-The 18xx railway game system was originated by Francis Tresham and Hartland Trefoil Ltd.
+Contributors:
+ Erik Vos
+ Stefan Frey
+ Freek Dijkstra
+ Scott Peterson
+ Adam Badura
+ Phil Davies
+ Bill Rosgen
+ Martin Brumm
+ Chris Shaffer
+ Brett Lentz
All rights reserved by the respective owners of the original games
(see the Game Notes per game for specific acknowledgements).
-No challenge to their status is intended.
+
+No challenge to the original author's or publisher's rights, licensing, or status is intended.
+
Rails is intended as a play aid for owners of each respective boardgame.
+
+The Rails application and source code are distributed under
+version 2 of the GNU Public License (GPL).
+
+A copy of the GPL should have been shipped with the game files and is also available here:
+ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
</Credits>
</GamesList>
Modified: trunk/18xx/rails/algorithms/RevenueAdapter.java
===================================================================
--- trunk/18xx/rails/algorithms/RevenueAdapter.java 2011-06-30 18:56:00 UTC (rev 1597)
+++ trunk/18xx/rails/algorithms/RevenueAdapter.java 2011-07-03 20:06:38 UTC (rev 1598)
@@ -17,6 +17,7 @@
import org.jgrapht.Graphs;
import org.jgrapht.graph.SimpleGraph;
+import rails.common.LocalText;
import rails.game.GameManagerI;
import rails.game.MapHex;
import rails.game.PhaseI;
@@ -24,7 +25,6 @@
import rails.game.TrainI;
import rails.game.TrainType;
import rails.ui.swing.hexmap.HexMap;
-import rails.util.LocalText;
public final class RevenueAdapter implements Runnable {
Modified: trunk/18xx/rails/algorithms/RevenueBonusTemplate.java
===================================================================
--- trunk/18xx/rails/algorithms/RevenueBonusTemplate.java 2011-06-30 18:56:00 UTC (rev 1597)
+++ trunk/18xx/rails/algorithms/RevenueBonusTemplate.java 2011-07-03 20:06:38 UTC (rev 1598)
@@ -5,15 +5,15 @@
import org.apache.log4j.Logger;
+import rails.common.parser.ConfigurationException;
+import rails.common.parser.Tag;
import rails.game.ConfigurableComponentI;
-import rails.game.ConfigurationException;
import rails.game.GameManagerI;
import rails.game.MapHex;
import rails.game.PhaseI;
import rails.game.PhaseManager;
import rails.game.TrainManager;
import rails.game.TrainType;
-import rails.util.Tag;
/**
* defines a template for a revenue bonus at creation time of rails objects
Modified: trunk/18xx/rails/algorithms/RevenueManager.java
===================================================================
--- trunk/18xx/rails/algorithms/RevenueManager.java 2011-06-30 18:56:00 UTC (rev 1597)
+++ trunk/18xx/rails/algorithms/RevenueManager.java 2011-07-03 20:06:38 UTC (rev 1598)
@@ -7,12 +7,12 @@
import org.apache.log4j.Logger;
+import rails.common.LocalText;
+import rails.common.parser.ConfigurationException;
+import rails.common.parser.Tag;
import rails.game.ConfigurableComponentI;
-import rails.game.ConfigurationException;
import rails.game.GameManagerI;
import rails.game.state.ArrayListState;
-import rails.util.LocalText;
-import rails.util.Tag;
/**
* Coordinates and stores all elements related to revenue calulcation,
Modified: trunk/18xx/rails/algorithms/RevenueTrainRun.java
===================================================================
--- trunk/18xx/rails/algorithms/RevenueTrainRun.java 2011-06-30 18:56:00 UTC (rev 1597)
+++ trunk/18xx/rails/algorithms/RevenueTrainRun.java 2011-07-03 20:06:38 UTC (rev 1598)
@@ -12,8 +12,8 @@
import rails.algorithms.NetworkVertex.StationType;
import rails.algorithms.NetworkVertex.VertexType;
+import rails.common.LocalText;
import rails.ui.swing.hexmap.HexMap;
-import rails.util.LocalText;
/**
* Links the results from the revenue calculator to the rails program
Copied: trunk/18xx/rails/common/LocalText.java (from rev 1597, trunk/18xx/rails/util/LocalText.java)
===================================================================
--- trunk/18xx/rails/common/LocalText.java (rev 0)
+++ trunk/18xx/rails/common/LocalText.java 2011-07-03 20:06:38 UTC (rev 1598)
@@ -0,0 +1,153 @@
+/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/util/LocalText.java,v 1.7 2010/03/23 18:45:16 stefanfrey Exp $*/
+package rails.common;
+
+import java.text.MessageFormat;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.apache.log4j.Logger;
+
+import rails.common.parser.Config;
+import rails.util.Util;
+
+public class LocalText extends ResourceBundle {
+
+ private static final String TEST_LOCALE = "te_ST";
+
+ protected static String language = "en";
+
+ protected static String country = "";
+
+ protected static String localeCode = language;
+
+ protected static Locale locale;
+
+ protected static ResourceBundle localisedText;
+
+ protected static Logger log =
+ Logger.getLogger(LocalText.class.getPackage().getName());
+
+ public static String getText(String key) {
+ return getText(key, (Object[]) null);
+ }
+
+ public static String getText(String key, Object parameter) {
+ return getText(key, new Object[] { parameter });
+ }
+
+ public static String getText(String key, Object... parameters) {
+ /* If the text is not found, return the key in brackets */
+ return getTextExecute(key, "<" + key + ">", true, parameters);
+ }
+
+ public static String getTextWithDefault(String key, String defaultText) {
+ return getTextExecute(key, defaultText, false, (Object[]) null);
+ }
+
+ // actual procedure to retrieve the local text
+ private static String getTextExecute(String key, String defaultText, boolean errorOnMissing, Object... parameters) {
+ String result = "";
+
+ if (key == null || key.length() == 0) return "";
+
+ /* Load the texts */
+ if (localisedText == null) {
+ /*
+ * Check what locale has been configured, if any. If not, we use the
+ * default assigned above.
+ */
+ String item;
+ if (Util.hasValue(item = Config.get("language"))) {
+ language = item.toLowerCase();
+ }
+ if (Util.hasValue(item = Config.get("country"))) {
+ country = item.toUpperCase();
+ localeCode = language + "_" + country;
+ }
+ if (Util.hasValue(item = Config.get("locale"))) {
+ localeCode = item;
+ if (localeCode.length() >= 2)
+ language = localeCode.substring(0, 2);
+ if (localeCode.length() >= 5)
+ country = localeCode.substring(3, 5);
+ }
+ log.debug("Language=" + language + ", country=" + country
+ + ", locale=" + localeCode);
+
+ /* Create the locale and get the resource bundle. */
+ locale = new Locale(language, country);
+
+ try {
+ localisedText =
+ ResourceBundle.getBundle("LocalisedText", locale);
+ } catch (MissingResourceException e) {
+ System.err.println("Unable to locate LocalisedText resource: "
+ + e);
+ }
+ }
+
+ /* If the key contains a space, something is wrong, check who did that! */
+ if (key.indexOf(" ") > -1) {
+ try {
+ throw new Exception("Invalid resource key '" + key + "'");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // special treatment for test locale
+ if (localeCode.equals(TEST_LOCALE)) {
+ StringBuffer s = new StringBuffer(key);
+ if (parameters != null)
+ for (Object o:parameters)
+ s.append("," + o.toString());
+ return s.toString();
+ }
+
+ /* Find the text */
+ try {
+ result = localisedText.getString(key);
+ } catch (Exception e) {
+ if (errorOnMissing) {
+ System.out.println("Missing text for key " + key + " in locale "
+ + locale.getDisplayName() + " (" + localeCode
+ + ")");
+ }
+ return defaultText;
+ }
+
+ if (parameters != null) {
+ result = MessageFormat.format(result, parameters);
+ }
+
+ return result;
+
+ }
+
+ public static void setLocale(String localeCode) {
+
+ LocalText.localeCode = localeCode;
+ String[] codes = localeCode.split("_");
+ if (codes.length > 0) language = codes[0];
+ if (codes.length > 1) country = codes[1];
+
+ // reset localised text
+ localisedText = null;
+ }
+
+ public Enumeration<String> getKeys() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Locale getLocale() {
+ return locale;
+ }
+
+ protected Object handleGetObject(String arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
Copied: trunk/18xx/rails/common/MoneyFormatter.java (from rev 1597, trunk/18xx/rails/util/Format.java)
===================================================================
--- trunk/18xx/rails/common/MoneyFormatter.java (rev 0)
+++ trunk/18xx/rails/common/MoneyFormatter.java 2011-07-03 20:06:38 UTC (rev 1598)
@@ -0,0 +1,30 @@
+/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/util/Format.java,v 1.3 2008/06/04 19:00:39 evos Exp $*/
+package rails.common;
+
+import rails.common.parser.Config;
+import rails.util.Util;
+
+public class MoneyFormatter {
+
+ private static final String DEFAULT_MONEY_FORMAT = "$@";
+ private static String moneyFormat = null;
+ static {
+ String configFormat = Config.get("money_format");
+ if (Util.hasValue(configFormat) && configFormat.matches(".*@.*")) {
+ moneyFormat = configFormat;
+ }
+ }
+
+ /* This class is never instantiated */
+ private MoneyFormatter() {}
+
+ public static String money(int amount) {
+ if (moneyFormat == null) moneyFormat = DEFAULT_MONEY_FORMAT;
+ return moneyFormat.replaceFirst("@", String.valueOf(amount));
+ }
+
+ public static void setMoneyFormat(String format) {
+ moneyFormat = format;
+ }
+
+}
Copied: trunk/18xx/rails/common/ResourceLoader.java (from rev 1597, trunk/18xx/rails/util/ResourceLoader.java)
===================================================================
--- trunk/18xx/rails/common/ResourceLoader.java (rev 0)
+++ trunk/18xx/rails/common/ResourceLoader.java 2011-07-03 20:06:38 UTC (rev 1598)
@@ -0,0 +1,581 @@
+/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/util/ResourceLoader.java,v 1.5 2009/01/15 20:53:28 evos Exp $*/
+package rails.common;
+
+import java.awt.Font;
+import java.io.*;
+import java.lang.reflect.Constructor;
+import java.net.Socket;
+import java.util.*;
+
+import javax.swing.text.*;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.HTMLEditorKit;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Class ResourceLoader is an utility class to load a resource from a filename
+ * and a list of directory.
+ *
+ * @version $Id: ResourceLoader.java,v 1.5 2009/01/15 20:53:28 evos Exp $
+ * @author Romain Dolbeau
+ * @author David Ripton
+ */
+
+public final class ResourceLoader {
+
+ /**
+ * Class ColossusClassLoader allows for class loading outside the CLASSPATH,
+ * i.e. from the various variant directories.
+ *
+ * @version $Id: ResourceLoader.java,v 1.5 2009/01/15 20:53:28 evos Exp $
+ * @author Romain Dolbeau
+ */
+ private static class RailsClassLoader extends ClassLoader {
+ List<String> directories = null;
+
+ protected static Logger log =
+ Logger.getLogger(RailsClassLoader.class.getPackage().getName());
+
+ RailsClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ RailsClassLoader() {
+ super();
+ }
+
+ @Override
+ public Class<?> findClass(String className)
+ throws ClassNotFoundException {
+ try {
+ int index = className.lastIndexOf(".");
+ String shortClassName = className.substring(index + 1);
+ if (index == -1) {
+ log.error("Loading of class \"" + className
+ + "\" failed (no dot in class name)");
+ return null;
+ }
+ InputStream classDataIS =
+ getInputStream(shortClassName + ".class", directories);
+ if (classDataIS == null) {
+ log.error("Couldn't find the class file anywhere ! ("
+ + shortClassName + ".class)");
+ throw new FileNotFoundException("missing " + shortClassName
+ + ".class");
+ }
+ byte[] classDataBytes = new byte[classDataIS.available()];
+ classDataIS.read(classDataBytes);
+ return defineClass(className, classDataBytes, 0,
+ classDataBytes.length);
+ } catch (Exception e) {
+ return super.findClass(className);
+ }
+ }
+
+ void setDirectories(List<String> d) {
+ directories = d;
+ }
+ }
+
+ public static final String keyContentType = "ResourceLoaderContentType";
+ public static final String defaultFontName = "Lucida Sans Bold";
+ public static final int defaultFontStyle = Font.PLAIN;
+ public static final int defaultFontSize = 12;
+ public static final Font defaultFont =
+ new Font(defaultFontName, defaultFontStyle, defaultFontSize);
+
+ // File.separator does not work in jar files, except in Unix.
+ // A hardcoded '/' works in Unix, Windows, MacOS X, and jar files.
+ private static final String pathSeparator = "/";
+ private static final ClassLoader baseCL =
+ rails.common.ResourceLoader.class.getClassLoader();
+ private static final RailsClassLoader cl = new RailsClassLoader(baseCL);
+
+ private static final Map<String, Object> fileCache =
+ Collections.synchronizedMap(new HashMap<String, Object>());
+
+ private final static String sep = "~";
+
+ protected static Logger log =
+ Logger.getLogger(ResourceLoader.class.getPackage().getName());
+
+ private static String server = null;
+ private static int serverPort = 0;
+
+ public static void setDataServer(String server, int port) {
+ ResourceLoader.server = server;
+ ResourceLoader.serverPort = port;
+ }
+
+ /**
+ * Give the String to mark directories.
+ *
+ * @return The String to mark directories.
+ */
+ public static String getPathSeparator() {
+ return pathSeparator;
+ }
+
+ /** empty the cache so that all files have to be reloaded */
+ public synchronized static void purgeFileCache() {
+ log.debug("Purging File Cache.");
+ fileCache.clear();
+ }
+
+ /**
+ * Return the first InputStream from file of name filename in the list of
+ * directories, tell the getInputStream not to complain if not found.
+ *
+ * @param filename Name of the file to load.
+ * @param directories List of directories to search (in order).
+ * @return The InputStream, or null if it was not found.
+ */
+ public static InputStream getInputStreamIgnoreFail(String filename,
+ List<String> directories) {
+ return getInputStream(filename, directories, server != null, false,
+ true);
+ }
+
+ /**
+ * Return the first InputStream from file of name filename in the list of
+ * directories.
+ *
+ * @param filename Name of the file to load.
+ * @param directories List of directories to search (in order).
+ * @return The InputStream, or null if it was not found.
+ */
+ public static InputStream getInputStream(String filename, List<String> directories) {
+ return getInputStream(filename, directories, server != null, false,
+ false);
+ }
+
+ /**
+ * Return the first InputStream from file of name filename in the list of
+ * directories.
+ *
+ * @param filename Name of the file to load.
+ * @param directories List of directories to search (in order).
+ * @param remote Ask the server for the stream.
+ * @param cachedOnly Only look in the cache file, do not try to load the
+ * file from permanent storage.
+ * @param ignoreFail (=don't complain) if file not found
+ * @return The InputStream, or null if it was not found.
+ */
+ public static InputStream getInputStream(String filename, List<String> directories,
+ boolean remote, boolean cachedOnly, boolean ignoreFail) {
+ String mapKey = getMapKey(filename, directories);
+ Object cached = fileCache.get(mapKey);
+ byte[] data = null;
+
+ if ((cached == null) && cachedOnly) {
+ if (!ignoreFail) {
+ log.warn("Requested file " + filename
+ + " is requested cached-only but is not is cache.");
+ }
+ return null;
+ }
+
+ if ((cached == null) && ((!remote) || (server == null))) {
+ synchronized (fileCache) {
+ InputStream stream = null;
+ java.util.Iterator<String> it = directories.iterator();
+ while (it.hasNext() && (stream == null)) {
+ Object o = it.next();
+ if (o instanceof String) {
+ String path = (String) o;
+ String fullPath =
+ path + pathSeparator + fixFilename(filename);
+
+ log.debug("Trying to locate InputStream: " + path
+ + pathSeparator + filename);
+ try {
+ File tempFile = new File(fullPath);
+ stream = new FileInputStream(tempFile);
+ } catch (Exception e) {
+ stream = cl.getResourceAsStream(fullPath);
+ }
+ }
+ }
+ if (stream == null) {
+ if (!remote && ignoreFail) {
+ // If someone locally requests it as ignoreFail,
+ // let's assume a remote requester later sees it the
+ // same way.
+ // Right now, the remote-requesting is not able to
+ // submit the "ignore-fail" property...
+ // @TODO: submit that properly?
+ // fileCacheIgnoreFail.put(mapKey, new Boolean(true));
+ }
+ if (!ignoreFail) {
+ log.warn("getInputStream:: "
+ + " Couldn't get InputStream for file "
+ + filename + " in " + directories
+ + (cachedOnly ? " (cached only)" : ""));
+ // @TODO this sounds more serious than just a warning in
+ // the logs
+ // Anyway now at least MarkersLoader does not complain
+ // any more...
+ }
+ } else {
+ data = getBytesFromInputStream(stream);
+ fileCache.put(mapKey, data);
+ }
+ }
+ } else {
+ synchronized (fileCache) {
+ if (cached != null) {
+ data = (byte[]) cached;
+ } else {
+ try {
+ Socket fileSocket = new Socket(server, serverPort);
+ InputStream is = fileSocket.getInputStream();
+
+ if (is == null) {
+ log.warn("getInputStream:: "
+ + " Couldn't get InputStream from socket"
+ + " for file " + filename + " in "
+ + directories
+ + (cachedOnly ? " (cached only)" : ""));
+ // @TODO this sounds more serious than just a
+ // warning in the logs
+ } else {
+ PrintWriter out =
+ new PrintWriter(
+ fileSocket.getOutputStream(), true);
+
+ if (ignoreFail) {
+ // Not in this version yet (05/2007).
+ // New clients could not talk with old server.
+ // Take this into full use somewhat later.
+ // out.print(
+ // Constants.fileServerIgnoreFailSignal + sep);
+ }
+ out.print(filename);
+ java.util.Iterator<String> it = directories.iterator();
+ while (it.hasNext()) {
+ out.print(sep + it.next());
+ }
+ out.println();
+ data = getBytesFromInputStream(is);
+ if (data != null && data.length == 0 && !ignoreFail) {
+ log.warn("Got empty contents for file "
+ + filename + " directories "
+ + directories.toString());
+ }
+ fileSocket.close();
+ fileCache.put(mapKey, data);
+ }
+ } catch (Exception e) {
+ log.error("ResourceLoader::getInputStream() : " + e);
+ }
+ }
+
+ }
+ }
+ return (data == null ? null : getInputStreamFromBytes(data));
+ }
+
+ /**
+ * Return the content of the specified file as an array of byte.
+ *
+ * @param filename Name of the file to load.
+ * @param directories List of directories to search (in order).
+ * @param cachedOnly Only look in the cache file, do not try to load the
+ * file from permanent storage.
+ * @return An array of byte representing the content of the file, or null if
+ * it fails.
+ */
+ public static byte[] getBytesFromFile(String filename, List<String> directories,
+ boolean cachedOnly, boolean ignoreFail) {
+ InputStream is =
+ getInputStream(filename, directories, server != null,
+ cachedOnly, ignoreFail);
+ if (is == null) {
+ // right now only FileServerThread is using this method at all.
+ if (!ignoreFail) {
+ log.warn("getBytesFromFile:: "
+ + " Couldn't get InputStream for file " + filename
+ + " in " + directories
+ + (cachedOnly ? " (cached only)" : ""));
+ }
+ return null;
+ }
+ return getBytesFromInputStream(is);
+ }
+
+ /**
+ * Return the content of the specified InputStream as an array of byte.
+ *
+ * @param InputStream The InputStream to use.
+ * @return An array of byte representing the content of the InputStream, or
+ * null if it fails.
+ */
+ private static byte[] getBytesFromInputStream(InputStream is) {
+ byte[] all = new byte[0];
+
+ try {
+ byte[] data = new byte[1024 * 64];
+ int r = is.read(data);
+ while (r > 0) {
+ byte[] temp = new byte[all.length + r];
+ for (int i = 0; i < all.length; i++) {
+ temp[i] = all[i];
+ }
+ for (int i = 0; i < r; i++) {
+ temp[i + all.length] = data[i];
+ }
+ all = temp;
+ r = is.read(data);
+ }
+ } catch (Exception e) {
+ log.error("Can't Stringify stream " + is + " (" + e + ")");
+ }
+ return all;
+ }
+
+ /**
+ * Return the content of the specified byte array as an InputStream.
+ *
+ * @param data The byte array to convert.
+ * @return An InputStream whose content is the data byte array.
+ */
+ private static InputStream getInputStreamFromBytes(byte[] data) {
+ if (data == null) {
+ log.warn("getInputStreamFromBytes:: "
+ + " Can't create InputStream from null byte array");
+ return null;
+ }
+ return new ByteArrayInputStream(data);
+ }
+
+ /**
+ * Return the first OutputStream from file of name filename in the list of
+ * directories.
+ *
+ * @param filename Name of the file to load.
+ * @param directories List of directories to search (in order).
+ * @return The OutputStream, or null if it was not found.
+ */
+ public static OutputStream getOutputStream(String filename, List<String> directories) {
+ OutputStream stream = null;
+ java.util.Iterator<String> it = directories.iterator();
+ while (it.hasNext() && (stream == null)) {
+ Object o = it.next();
+ if (o instanceof String) {
+ String path = (String) o;
+ String fullPath = path + pathSeparator + fixFilename(filename);
+ try {
+ stream = new FileOutputStream(fullPath);
+ } catch (Exception e) {
+ log.debug("getOutputStream:: "
+ + " Couldn't get OutputStream for file "
+ + filename + " in " + directories + "("
+ + e.getMessage() + ")");
+ }
+ }
+ }
+ return (stream);
+ }
+
+ /**
+ * Return the first Document from file of name filename in the list of
+ * directories. It also add a property of key keyContentType and of type
+ * String describing the content type of the Document. This can currently
+ * load HTML and pure text.
+ *
+ * @param filename Name of the file to load.
+ * @param directories List of directories to search (in order).
+ * @return The Document, or null if it was not found.
+ */
+ public static Document getDocument(String filename, List<String> directories) {
+ InputStream htmlIS =
+ getInputStreamIgnoreFail(filename + ".html", directories);
+ if (htmlIS != null) {
+ try {
+ HTMLEditorKit htedk = new HTMLEditorKit();
+ HTMLDocument htdoc = new HTMLDocument(htedk.getStyleSheet());
+ htdoc.putProperty(keyContentType, "text/html");
+ htedk.read(htmlIS, htdoc, 0);
+ return htdoc;
+ } catch (Exception e) {
+ log.error("html document exists, but cannot be loaded ("
+ + filename + "): " + e);
+ }
+ return null;
+ }
+ InputStream textIS =
+ getInputStreamIgnoreFail(filename + ".txt", directories);
+ if (textIS == null) {
+ textIS = getInputStreamIgnoreFail(filename, directories);
+ }
+ if (textIS != null) {
+ try {
+ // Must be a StyledDocument not a PlainDocument for
+ // JEditorPane.setDocument()
+ StyledDocument txtdoc = new DefaultStyledDocument();
+ char[] buffer = new char[128];
+ InputStreamReader textISR = new InputStreamReader(textIS);
+ int read = 0;
+ int offset = 0;
+ while (read != -1) {
+ read = textISR.read(buffer, 0, 128);
+ if (read != -1) {
+ txtdoc.insertString(offset,
+ new String(buffer, 0, read), null);
+ offset += read;
+ }
+ }
+ txtdoc.putProperty(keyContentType, "text/plain");
+ return txtdoc;
+ } catch (Exception e) {
+ log.error("text document exists, but cannot be loaded ("
+ + filename + "): " + e);
+ }
+ return null;
+ }
+ log.error("No document for basename " + filename + " found "
+ + "(neither .html, .txt nor without extention)!");
+ return null;
+ }
+
+ /**
+ * Return the key to use in the image and file caches.
+ *
+ * @param filename Name of the file.
+ * @param directories List of directories.
+ * @return A String to use as a key when storing/loading in a cache the
+ * specified file from the specified list of directories.
+ */
+ private static String getMapKey(String filename, List<String> directories) {
+ String[] filenames = new String[1];
+ filenames[0] = filename;
+ return getMapKey(filenames, directories);
+ }
+
+ /**
+ * Return the key to use in the image cache.
+ *
+ * @param filenames Array of name of files.
+ * @param directories List of directories.
+ * @return A String to use as a key when storing/loading in a cache the
+ * specified array of name of files from the specified list of directories.
+ */
+ private static String getMapKey(String[] filenames, List<String> directories) {
+ StringBuffer buf = new StringBuffer(filenames[0]);
+ for (int i = 1; i < filenames.length; i++) {
+ buf.append(",");
+ buf.append(filenames[i]);
+ }
+ Iterator<String> it = directories.iterator();
+ while (it.hasNext()) {
+ Object o = it.next();
+ if (o instanceof String) {
+ buf.append(",");
+ buf.append(o);
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Fix a filename by replacing space with underscore.
+ *
+ * @param filename Filename to fix.
+ * @return The fixed filename.
+ */
+ private static String fixFilename(String filename) {
+ return filename.replace(' ', '_');
+ }
+
+ /**
+ * Create an instance of the class whose name is in parameter.
+ *
+ * @param className The name of the class to use.
+ * @param directories List of directories to search (in order).
+ * @return A new object, instance from the given class.
+ */
+ public static Object getNewObject(String className, List<String> directories) {
+ return getNewObject(className, directories, null);
+ }
+
+ /**
+ * Create an instance of the class whose name is in parameter, using
+ * parameters.
+ *
+ * If no parameters are given, the default constructor is used.
+ *
+ * @TODO this is full of catch(Exception) blocks, which all return null.
+ * Esp. returning null seems a rather bad idea, since it will most likely
+ * turn out to be NPEs somewhere later.
+ *
+ * @param className The name of the class to use, must not be null.
+ * @param directories List of directories to search (in order), must not be
+ * null.
+ * @param parameter Array of parameters to pass to the constructor, can be
+ * null.
+ * @return A new object, instance from the given class or null if
+ * instantiation failed.
+ */
+ public static Object getNewObject(String className, List<String> directories,
+ Object[] parameter) {
+ Class<?> theClass = null;
+ cl.setDirectories(directories);
+ try {
+ theClass = cl.loadClass(className);
+ } catch (Exception e) {
+ log.error("Loading of class \"" + className + "\" failed (" + e
+ + ")");
+ return null;
+ }
+ if (parameter != null) {
+ Class<?>[] paramClasses = new Class[parameter.length];
+ for (int i = 0; i < parameter.length; i++) {
+ paramClasses[i] = parameter[i].getClass();
+ }
+ try {
+ Constructor<?> c = theClass.getConstructor(paramClasses);
+ return c.newInstance(parameter);
+ } catch (Exception e) {
+ log.error("Loading or instantiating class' constructor for \""
+ + className + "\" failed (" + e + ")");
+ return null;
+ }
+ } else {
+ try {
+ return theClass.newInstance();
+ } catch (Exception e) {
+ log.error("Instantiating \"" + className + "\" failed (" + e
+ + ")");
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Force adding the given data as belonging to the given filename in the
+ * file cache.
+ *
+ * @param filename Name of the Image file to add.
+ * @param directories List of directories to search (in order).
+ * @param data File content to add.
+ */
+ public static void putIntoFileCache(String filename, List<String> directories,
+ byte[] data) {
+ String mapKey = getMapKey(filename, directories);
+ fileCache.put(mapKey, data);
+ }
+
+ /**
+ * Force adding the given data as belonging to the given key in the file
+ * cache.
+ *
+ * @see #getMapKey(String, List)
+ * @see #getMapKey(String[], List)
+ * @param mapKey Key to use in the cache.
+ * @param data File content to add.
+ */
+ public static void putIntoFileCache(String mapKey, byte[] data) {
+ fileCache.put(mapKey, data);
+ }
+}
Copied: trunk/18xx/rails/common/parser/Config.java (from rev 1597, trunk/18xx/rails/util/Config.java)
===================================================================
--- trunk/18xx/rails/common/parser/Config.java (rev 0)
+++ trunk/18xx/rails/common/parser/Config.java 2011-07-03 20:06:38 UTC (rev 1598)
@@ -0,0 +1,584 @@
+/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/util/Config.java,v 1.13 2010/06/24 21:48:08 stefanfrey Exp $*/
+package rails.common.parser;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+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.Properties;
+
+import org.apache.log4j.Logger;
+
+import rails.game.GameManager;
+import rails.util.Util;
+
+/**
+ * This is a simple utility class with a collection of static functions to load
+ * a property object from a property file, to retrieve a particular value from
+ * the property file etc.
+ *
+ * @author Ramiah Bala,
+ * @author Erik Vos
+ * @author Stefan Frey
+ * @version 2.0
+ */
+public final class Config {
+
+ protected static Logger log;
+
+ /** Commandline options */
+ private static final String CONFIGFILE_CMDLINE = "configfile";
+ private static final String PROFILE_CMDLINE = "profile";
+
+ /** XML setup */
+ private static final String CONFIG_XML_DIR = "data";
+ private static final String CONFIG_XML_FILE = "Properties.xml";
+ private static final String CONFIG_TAG = "Properties";
+ private static final String SECTION_TAG = "Section";
+ private static final String ITEM_TAG = "Property";
+
+ /** Log 4j configuration */
+ private static final String LOG4J_CONFIG_FILE = "log4j.properties";
+
+ /** Rails profile configurations */
+ private static String defaultProfilesFile = "data/profiles/default.profiles";
+ private static Properties defaultProfiles = new Properties();
+ private static String userProfilesFile = "user.profiles";
+ private static Properties userProfiles = new Properties();
+ private static boolean profilesLoaded = false;
+ private static String DEFAULT_PROFILE_SELECTION = "default"; // can be overwritten
+ private static final String TEST_PROFILE_SELECTION = ".test"; // used as default profile for integration tests
+ private static final String STANDARD_PROFILE_SELECTION = "user";
+ private static final String DEFAULTPROFILE_PROPERTY = "default.profile";
+ private static final String PROFILENAME_PROPERTY = "profile.name";
+
+ /** selected profile */
+ private static String selectedProfile;
+ private static boolean legacyConfigFile;
+
+ /** properties storage. */
+ private static Properties defaultProperties = new Properties();
+ private static Properties userProperties = new Properties();
+ private static boolean propertiesLoaded = false;
+
+ /** Map that holds the panel, which contains config items */
+ private static Map<String, List<ConfigItem>> configSections = null;
+
+ /**
+ * Hidden constructor, the class is never instantiated, everything is static
+ */
+ private Config() {}
+
+ /**
+ * Reads the config.xml file that defines all config items
+ */
+ public static void readConfigSetupXML() {
+ List<String> directories = new ArrayList<String>();
+ directories.add(CONFIG_XML_DIR);
+ try {
+ // Find the config tag inside the the config xml file
+ Tag configTag =
+ Tag.findTopTagInFile(CONFIG_XML_FILE, directories, CONFIG_TAG);
+ log.debug("Opened config xml, filename = " + CONFIG_XML_FILE);
+
+ // define sections
+ configSections = new LinkedHashMap<String, List<ConfigItem>>();
+
+ // find sections
+ List<Tag> sectionTags = configTag.getChildren(SECTION_TAG);
+ if (sectionTags != null) {
+ for (Tag sectionTag:sectionTags) {
+ // find name attribute
+ String sectionName = sectionTag.getAttributeAsString("name");
+ if (!Util.hasValue(sectionName)) continue;
+
+ // find items
+ List<Tag> itemTags = sectionTag.getChildren(ITEM_TAG);
+ if (itemTags == null || itemTags.size() == 0) continue;
+ List<ConfigItem> sectionItems = new ArrayList<ConfigItem>();
+ for (Tag itemTag:itemTags) {
+ sectionItems.add(new ConfigItem(itemTag));
+ }
+ configSections.put(sectionName, sectionItems);
+ }
+ }
+
+ } catch (ConfigurationException e) {
+ log.error("Configuration error in setup of " + CONFIG_XML_FILE + ", exception = " + e);
+ }
+ }
+
+ public static Map<String, List<ConfigItem>> getConfigSections() {
+ if (configSections == null) {
+ readConfigSetupXML();
+ }
+ log.debug("Configuration setup = " + configSections);
+ return configSections;
+ }
+
+ public static int getMaxElementsInPanels() {
+ int maxElements = 0;
+ for (List<ConfigItem> panel:configSections.values()) {
+ maxElements = Math.max(maxElements, panel.size());
+ }
+ log.debug("Configuration sections with maximum elements of " + maxElements);
+ return maxElements;
+ }
+
+ /**
+ * updates the profile according to the changes in configitems
+ */
+ public static void updateProfile(boolean applyInitMethods) {
+ for (List<ConfigItem> items:configSections.values()) {
+ for (ConfigItem item:items) {
+ if (!item.hasNewValue()) continue;
+ if (item.getNewValue().equals(defaultProperties.get(item.name))) {
+ userProperties.remove(item.name);
+ continue;
+ }
+ userProperties.setProperty(item.name, item.getNewValue());
+ if (applyInitMethods) item.callInitMethod();
+ log.debug("Changed property name = " + item.name + " to value = " + item.getNewValue());
+ item.setNewValue(null);
+ }
+ }
+ }
+
+ /**
+ * reverts all changes in configitems
+ */
+ public static void revertProfile() {
+ for (List<ConfigItem> items:configSections.values()) {
+ for (ConfigItem item:items) {
+ item.setNewValue(null);
+ }
+ }
+ }
+
+ /**
+ * First tries to return {key}.{gameName}, if undefined returns {key}
+ */
+ public static String getGameSpecific(String key) {
+ return Config.getSpecific(key, GameManager.getInstance().getGameName());
+ }
+
+ /**
+ * First tries to return {key}.{appendix}, if undefined returns {key}
+ */
+ public static String getSpecific(String key, String appendix) {
+ String value = Config.get(key + "." + appendix);
+ if (value == "") {
+ value = Config.get(key);
+ }
+ return value;
+ }
+
+ public static String get(String key) {
+ return get(key, "");
+ }
+
+ public static String get(String key, String defaultValue) {
+ if (defaultProperties.isEmpty() || !propertiesLoaded) {
+ initialLoad();
+ }
+ if (userProperties.containsKey(key)) return userProperties.getProperty(key).trim();
+ if (defaultProperties.containsKey(key)) return defaultProperties.getProperty(key).trim();
+
+ return defaultValue;
+ }
+
+
+ /**
+ * save active Profile
+ */
+ public static boolean saveActiveProfile() {
+ String filepath = userProfiles.getProperty(selectedProfile);
+ if (Util.hasValue(filepath)) {
+ return storePropertyFile(userProperties, filepath);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * change active Profile
+ */
+ public static boolean changeActiveProfile(String profileName) {
+ readConfigSetupXML();
+ loadProfile(profileName);
+ selectedProfile = profileName;
+ return true;
+ }
+
+ /**
+ * create new profile
+ */
+ public static boolean createUserProfile(String profileName, String defaultProfile) {
+ userProperties = new Properties();
+ defaultProperties = new Properties();
+
+ // add to list of user profiles
+ userProfiles.setProperty(profileName, "");
+
+ // define and load default profile
+ String defaultConfigFile = defaultProfiles.getProperty(defaultProfile);
+ userProperties.setProperty(PROFILENAME_PROPERTY, profileName);
+ userProperties.setProperty(DEFAULTPROFILE_PROPERTY, defaultProfile);
+ loadPropertyFile(defaultProperties, defaultConfigFile, true);
+ setSaveDirDefaults();
+
+ selectedProfile = profileName;
+ return true;
+ }
+
+
+ private static Map<String, String> convertProperties(Properties properties, boolean visibleOnly) {
+ Map<String, String> converted = new HashMap<String, String>();
+ for (Object key:properties.keySet()) {
+ if (visibleOnly && ((String)key).substring(0,1).equals(".")) continue;
+ converted.put((String) key, (String) properties.get(key));
+ }
+ return converted;
+ }
+
+ /**
+ * get all default profiles
+ */
+ public static List<String> getDefaultProfiles(boolean visibleOnly) {
+ List<String> profiles = new ArrayList<String>(convertProperties(defaultProfiles, visibleOnly).keySet());
+ Collections.sort(profiles);
+ return profiles;
+ }
+
+ public static String getDefaultProfileSelection() {
+ return DEFAULT_PROFILE_SELECTION;
+ }
+
+ /**
+ * get all user profiles
+ */
+ public static List<String> getUserProfiles() {
+ List<String> profiles = new ArrayList<String>(convertProperties(userProfiles, true).keySet());
+ Collections.sort(profiles);
+ return profiles;
+ }
+
+ /**
+ * get all (visible default + user) profiles
+ */
+ public static List<String> getAllProfiles() {
+ List<String> profiles = getDefaultProfiles(true);
+ profiles.addAll(getUserProfiles());
+ return profiles;
+ }
+
+ /**
+ * checks if profile is default profile
+ */
+ public static boolean isDefaultProfile(String profileName) {
+ return !(defaultProfiles.get(profileName) == null);
+ }
+
+ /**
+ * returns name of (active) default profile
+ */
+ public static String getDefaultProfileName() {
+ return userProperties.getProperty(DEFAULTPROFILE_PROPERTY);
+ }
+
+ /**
+ * returns name of active profile
+ */
+ public static String getActiveProfileName() {
+ return selectedProfile;
+ }
+
+ /**
+ * returns true if legacy configfile is used
+ */
+ public static boolean isLegacyConfigFile() {
+ return legacyConfigFile;
+ }
+
+ /**
+ * sets filename for an active profile (and store list of profiles)
+ * @return false if list of profiles cannot be stored
+ */
+ public static boolean setActiveFilepath(String filepath) {
+ userProfiles.setProperty(selectedProfile, filepath);
+ return storePropertyFile(userProfiles, userProfilesFile);
+ }
+
+ /**
+ * returns filename of active profile, (null if undefined or default profile)
+ */
+ public static String getActiveFilepath() {
+ return userProfiles.getProperty(selectedProfile);
+ }
+
+ /**
+ * @return if user location is defined
+ */
+ public static boolean isFilePathDefined() {
+ return Util.hasValue(userProfiles.getProperty(selectedProfile));
+ }
+
+
+ /**
+ * activates settings used for testing
+ */
+ public static void setConfigTest() {
+ /*
+ * Set the system property that tells log4j to use this file. (Note:
+ * this MUST be done before updating Config)
+ */
+ String log4jSelection = System.getProperty("log4j.configuration");
+ if (!Util.hasValue(log4jSelection)) {
+ log4jSelection = LOG4J_CONFIG_FILE;
+ }
+ System.setProperty("log4j.configuration", log4jSelection);
+ System.out.println("log4j.configuration = " + log4jSelection);
+
+ // delayed setting of logger
+ log = Logger.getLogger(Config.class.getPackage().getName());
+
+ // define settings for testing
+ legacyConfigFile = false;
+ DEFAULT_PROFILE_SELECTION = TEST_PROFILE_SELECTION;
+ selectedProfile = null;
+
+ initialLoad();
+ }
+
+
+ /**
+ * activates configuration settings based on default settings
+ */
+ public static void setConfigSelection() {
+ /*
+ * Set the system property that tells log4j to use this file. (Note:
+ * this MUST be done before updating Config)
+ */
+ String log4jSelection = System.getProperty("log4j.configuration");
+ if (!Util.hasValue(log4jSelection)) {
+ log4jSelection = LOG4J_CONFIG_FILE;
+ }
+ System.setProperty("log4j.configuration", log4jSelection);
+ System.out.println("log4j.configuration = " + log4jSelection);
+
+ // delayed setting of logger
+ log = Logger.getLogger(Config.class.getPackage().getName());
+
+ /*
+ * Check if the profile has been set from the command line
+ * to do this is adding an option to the java command: -Dprofile=<profile-name>
+ */
+ String configSelection = System.getProperty(PROFILE_CMDLINE);
+ System.out.println("Cmdline profile selection = " + configSelection);
+
+ legacyConfigFile = false;
+ if (configSelection == null) {
+ /*
+ * Check if the property file has been set on the command line. The way
+ * to do this is adding an option to the java command: -Dconfigfile=<property-filename>
+ *
+ * This is for legacy reasons only
+ */
+ configSelection = System.getProperty(CONFIGFILE_CMDLINE);
+
+ if (Util.hasValue(configSelection)) {
+ System.out.println("Cmdline configfile selection (legacy!) = " + configSelection);
+ legacyConfigFile = true;
+ }
+ }
+
+ /* if nothing has selected so far, choose standardProfile */
+ if (!Util.hasValue(configSelection)) {
+ configSelection = STANDARD_PROFILE_SELECTION;
+ }
+
+ selectedProfile = configSelection;
+ if (!legacyConfigFile) {
+ System.out.println("Profile selection = " + selectedProfile);
+ }
+
+ initialLoad();
+ }
+
+
+ private static void initialLoad() {
+ if (legacyConfigFile) {
+ if (!propertiesLoaded) {
+ loadPropertyFile(defaultProperties, selectedProfile, false);
+ propertiesLoaded = true;
+ setSaveDirDefaults();
+ }
+ return;
+ }
+
+ if (!profilesLoaded) {
+ loadPropertyFile(defaultProfiles, defaultProfilesFile, true);
+ loadPropertyFile(userProfiles, userProfilesFile, false);
+ profilesLoaded = true;
+ }
+
+ /* Tell the properties loader to read this file. */
+ log.info("Selected profile = " + selectedProfile);
+
+ if (!propertiesLoaded) {
+ loadProfile(selectedProfile);
+ propertiesLoaded = true;
+ }
+ }
+
+
+ /**
+ * loads an external user profile
+ * defined by the filepath
+ */
+ public static boolean loadProfileFromFile(File file) {
+ String filepath = file.getPath();
+ if (loadPropertyFile(userProperties, filepath, false)) {
+ String profile = userProperties.getProperty(PROFILENAME_PROPERTY);
+ if (!Util.hasValue(profile)) {
+ profile = STANDARD_PROFILE_SELECTION;
+ }
+ selectedProfile = profile;
+ setActiveFilepath(filepath); // do not set filepath on import
+ loadDefaultProfile();
+ setSaveDirDefaults();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * imports an external user profile into an existing profile
+ * defined by the filepath
+ */
+ public static boolean importProfileFromFile(File file) {
+ String filepath = file.getPath();
+ Properties importProperties = new Properties();
+ if (loadPropertyFile(importProperties, filepath, false)) {
+ userProperties.putAll(importProperties);
+ setSaveDirDefaults();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * loads a user profile
+ * if not defined or loadable, creates a default user profile
+ */
+ private static void loadProfile(String userProfile) {
+ // reset properties
+ userProperties = new Properties();
+ defaultProperties = new Properties();
+
+ String userConfigFile = null;
+ if (Util.hasValue(userProfile)) {
+ // check if the profile is already defined under userProfiles
+ userConfigFile = userProfiles.getProperty(userProfile);
+ if (Util.hasValue(userConfigFile) && // load user profile
+ loadPropertyFile(userProperties, userConfigFile, fa...
[truncated message content] |