--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/classes/hirondelle/web4j/readconfig/Config.java Wed Dec 04 17:00:31 2013 +0100
@@ -0,0 +1,597 @@
+package hirondelle.web4j.readconfig;
+
+import hirondelle.web4j.database.ConnectionSource;
+import hirondelle.web4j.database.TxIsolationLevel;
+import hirondelle.web4j.util.Util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.TimeZone;
+import java.util.regex.Pattern;
+
+/**
+ (UNPUBLISHED) Access the config values needed by the framework.
+
+ <P>Assumptions:
+ <ul>
+ <li><tt>init</tt> is called only once, upon startup, when the system is in single-threaded mode
+ <li>there is no re-init or reload mechanism
+ <li>after <tt>init</tt> is called, the data will never change, and this class is safe to be used
+ in a multi-threaded environment
+ <li>all data returned by the getXXX methods is immutable, or a defensive copy is passed
+ </ul>
+
+ <P>The typical user of this class is simple:
+<pre>Config config = new Config();
+ String blah = config.getBlah;
+</pre>
+ The caller usually has no need to store the data in their own static private field.
+
+ <P>The hard-coding in this class is desirable and necessary. Note that it makes no
+ sense to add config items at runtime, since no code will be able to talk to it.
+
+ <P>Default values are defined internally by this class. Callers performing tests
+ may use default values, or they may override any number of default values by calling <tt>init</tt>.
+ There is no method to revert to the original defaults.
+
+ <P>
+ When an app as a whole is reloaded, it's a full reload, with new classes/classloaders.
+ When the Deployment Descriptor (DD) is touched, often the app reloads partially, with the same classes/classloaders,
+ but a new Servlet object. (This depends on the Container.)
+ Thus, static blocks are not re-executed in that case.
+
+ <P>This means that classes should not copy/store data from Config in a static block, since that static block
+ will not see partial reloads (tweaks to the DD). This is a bit tricky.
+ As well, any 'first-use-initialization' logic in class X cannot talk to the config, since it will not be executed on a partial reload.
+
+ <P>If all the parsing/caching is done by this class, then callers don't have to worry about partial reloads, and whether or
+ not they are out of date. In addition, if the syntax is the same, then the parsing is centralized here.
+*/
+public final class Config {
+
+ /** Value - {@value} - special value for some settings, denoting an absent value. */
+ public static final String NONE = "NONE";
+
+ /* NOTE: Most of this code was generated by a one-off script. */
+
+ /**
+ Must be called once and only once, upon startup, when the system is in
+ single-threaded mode. Throws an exception if a problem with the syntax is detected.
+
+ <P>Note than this takes a generic map, not <tt>ServletContext</tt>. That's important,
+ since it allows this Config to be used in any context, not just a servlet container.
+ <P>The key is case-sensitive.
+ */
+ public static void init(Map<String, String> aKeyValuePairs){
+ initAllItems(aKeyValuePairs);
+ }
+
+ /**
+ Confirm that database settings in <tt>web.xml</tt> are known to {@link ConnectionSource}.
+ Order dependency: this method is called after <tt>init</tt>, since it needs to know the database names,
+ which in turn requires a call to BuildImpl.init.
+ */
+ public static void checkDbNamesInSettings(Set<String> aValidDbNames){
+ Set<String> namesInSettings = new LinkedHashSet<String>();
+
+ namesInSettings.addAll(fHasAutoGeneratedKeys.getDbNames());
+ namesInSettings.addAll(fSqlFetcherDefaultTxIsolationLevel.getDbNames());
+ namesInSettings.addAll(fSqlEditorDefaultTxIsolationLevel.getDbNames());
+ namesInSettings.addAll(fErrorCodeForDuplicateKey.getDbNames());
+ namesInSettings.addAll(fErrorCodeForForeignKey.getDbNames());
+ namesInSettings.addAll(fMaxRows.getDbNames());
+ namesInSettings.addAll(fFetchSize.getDbNames());
+ namesInSettings.addAll(fIsSQLPrecompilationAttempted.getDbNames());
+ namesInSettings.addAll(fDateTimeFormatForPassingParamsToDb.getDbNames());
+
+ Set<String> unknownNames = new LinkedHashSet<String>();
+ for(String name: namesInSettings){
+ if(Util.textHasContent(name) && ! aValidDbNames.contains(name)){
+ unknownNames.add(name);
+ }
+ }
+
+ if(! unknownNames.isEmpty() ) {
+ throw new IllegalArgumentException("Web.xml contains settings that refer to databases that are not known to your implementation of ConnectionSource.getDatabaseNames(). Please check spelling and case for : " + Util.logOnePerLine(unknownNames));
+ }
+ }
+
+ /** Intended for logging and trouble tickets. */
+ public Map<String, String> getRawMap(){
+ return Collections.unmodifiableMap(fMap);
+ }
+
+ public Boolean isTesting(){
+ return fIsTesting;
+ }
+
+ /** Value is present, and is not 'NONE'. */
+ public boolean isEnabled(String aValue){
+ return Util.textHasContent(aValue) && ! NONE.equalsIgnoreCase(aValue);
+ }
+
+ public String getWebmaster(){
+ return fWebmaster;
+ }
+
+ public String getImplicitMappingRemoveBasePackage(){
+ return fImplicitMappingRemoveBasePackage;
+ }
+
+ public String getMailServerConfig(){
+ return fMailServerConfig;
+ }
+
+ public String getMailServerCredentials(){
+ return fMailServerCredentials;
+ }
+
+ public String getLoggingDirectory (){
+ return fLoggingDirectory;
+ }
+
+ public List<String> getLoggingLevels(){
+ return fLoggingLevels;
+ }
+
+ public List<String> getTroubleTicketMailingList(){
+ return Collections.unmodifiableList(fTroubleTicketMailingList);
+ }
+
+ public Long getMinimumIntervalBetweenTroubleTickets(){
+ return fMinimumIntervalBetweenTroubleTickets;
+ }
+
+ /** Returns the value in nanos, not seconds. */
+ public Long getPoorPerformanceThreshold(){
+ long NANOSECONDS_PER_SECOND = 1000 *1000 * 1000;
+ return fPoorPerformanceThreshold * NANOSECONDS_PER_SECOND;
+ }
+
+ public Long getMaxHttpRequestSize(){
+ return fMaxHttpRequestSize;
+ }
+
+ public Long getMaxFileUploadRequestSize(){
+ return fMaxFileUploadRequestSize;
+ }
+
+ public Long getMaxRequestParamValueSize(){
+ return fMaxRequestParamValueSize;
+ }
+
+ public Boolean getSpamDetectionInFirewall(){
+ return fSpamDetectionInFirewall;
+ }
+
+ public Boolean getFullyValidateFileUploads(){
+ return fFullyValidateFileUploads;
+ }
+
+ public Boolean getAllowStringAsBuildingBlock(){
+ return fAllowStringAsBuildingBlock;
+ }
+
+ public Map<String, List<String>> getUntrustedProxyForUserId(){
+ return fUntrustedProxyForUserId;
+ }
+
+ public String getCharacterEncoding(){
+ return fCharacterEncoding;
+ }
+
+ public Locale getDefaultLocale(){
+ return fDefaultLocale;
+ }
+
+ public TimeZone getDefaultUserTimeZone(){
+ return TimeZone.getTimeZone(fDefaultUserTimeZone.getID()); //mutable class
+ }
+
+ public Boolean hasTimeZoneHint(){
+ return fTimeZoneHint != null;
+ }
+
+ public Calendar getTimeZoneHint(){
+ Calendar result = null;
+ if( hasTimeZoneHint() ) {
+ result = Calendar.getInstance(fTimeZoneHint);
+ }
+ return result;
+ }
+
+ //this could be deleted ? - no callers
+ public String getDecimalSeparator(){
+ return fDecimalSeparator;
+ }
+
+ public Pattern getDecimalInputPattern(){
+ return fDecimalInputPattern; //derived from decimal separator
+ }
+
+ public String getBigDecimalDisplayFormat(){
+ return fBigDecimalDisplayFormat;
+ }
+
+ public String getBooleanTrueDisplayFormat(){
+ return fBooleanTrueDisplayFormat;
+ }
+
+ public String getBooleanFalseDisplayFormat(){
+ return fBooleanFalseDisplayFormat;
+ }
+
+ public String getEmptyOrNullDisplayFormat(){
+ return fEmptyOrNullDisplayFormat;
+ }
+
+ public String getIntegerDisplayFormat(){
+ return fIntegerDisplayFormat;
+ }
+
+ public String getIgnorableParamValue(){
+ return fIgnorableParamValue;
+ }
+
+ public Boolean getIsSQLPrecompilationAttempted(String aDbName){
+ return asBoolean(fIsSQLPrecompilationAttempted.getValue(aDbName));
+ }
+
+ public Integer getMaxRows(String aDbName){
+ return asInteger(fMaxRows.getValue(aDbName));
+ }
+
+ public Integer getFetchSize(String aDbName){
+ return asInteger(fFetchSize.getValue(aDbName));
+ }
+
+ public Boolean getHasAutoGeneratedKeys(String aDbName){
+ return asBoolean(fHasAutoGeneratedKeys.getValue(aDbName));
+ }
+
+ public List<Integer> getErrorCodesForDuplicateKey(String aDbName){
+ return asIntegerList(fErrorCodeForDuplicateKey.getValue(aDbName));
+ }
+
+ public List<Integer> getErrorCodesForForeignKey(String aDbName){
+ return asIntegerList(fErrorCodeForForeignKey.getValue(aDbName));
+ }
+
+ public TxIsolationLevel getSqlFetcherDefaultTxIsolationLevel(String aDbName){
+ return TxIsolationLevel.valueOf(fSqlFetcherDefaultTxIsolationLevel.getValue(aDbName));
+ }
+
+ public TxIsolationLevel getSqlEditorDefaultTxIsolationLevel(String aDbName){
+ return TxIsolationLevel.valueOf(fSqlEditorDefaultTxIsolationLevel.getValue(aDbName));
+ }
+
+ public String getDateFormat(String aDbName){
+ return asDateTimeFormat(fDateTimeFormatForPassingParamsToDb.getValue(aDbName), 0);
+ }
+
+ public String getTimeFormat(String aDbName){
+ return asDateTimeFormat(fDateTimeFormatForPassingParamsToDb.getValue(aDbName), 1);
+ }
+
+ public String getDateTimeFormat(String aDbName){
+ return asDateTimeFormat(fDateTimeFormatForPassingParamsToDb.getValue(aDbName), 2);
+ }
+
+ // PRIVATE
+
+ private static List<String> fErrors = new ArrayList<String>();
+
+ private static void initAllItems(Map<String, String> aKeyValuePairs) {
+ fMap = aKeyValuePairs;
+
+ fWebmaster = initThisStringNoDefault("Webmaster", aKeyValuePairs);
+ fImplicitMappingRemoveBasePackage = initThisStringNoDefault("ImplicitMappingRemoveBasePackage", aKeyValuePairs);
+
+ if (hasValue("MailServerConfig", aKeyValuePairs)) {
+ fMailServerConfig = initThisString("MailServerConfig", aKeyValuePairs);
+ }
+ if (hasValue("MailServerCredentials", aKeyValuePairs)) {
+ fMailServerCredentials = initThisString("MailServerCredentials", aKeyValuePairs);
+ }
+ if (hasValue("LoggingDirectory", aKeyValuePairs)) {
+ fLoggingDirectory = initThisString("LoggingDirectory", aKeyValuePairs);
+ }
+ if (hasValue("LoggingLevels", aKeyValuePairs)) {
+ fLoggingLevels = initThisStringList("LoggingLevels", aKeyValuePairs);
+ }
+ if (hasValueNotNone("TroubleTicketMailingList", aKeyValuePairs)) {
+ fTroubleTicketMailingList = initThisStringList("TroubleTicketMailingList", aKeyValuePairs);
+ }
+ if (hasValue("MinimumIntervalBetweenTroubleTickets", aKeyValuePairs)) {
+ fMinimumIntervalBetweenTroubleTickets = initThisLong("MinimumIntervalBetweenTroubleTickets", aKeyValuePairs);
+ }
+ if (hasValue("PoorPerformanceThreshold", aKeyValuePairs)) {
+ fPoorPerformanceThreshold = initThisLong("PoorPerformanceThreshold", aKeyValuePairs);
+ }
+ if (hasValue("MaxHttpRequestSize", aKeyValuePairs)) {
+ fMaxHttpRequestSize = initThisLong("MaxHttpRequestSize", aKeyValuePairs);
+ checkTooLow(fMaxHttpRequestSize, 1000L, "MaxHttpRequestSize");
+ }
+ if (hasValue("MaxFileUploadRequestSize", aKeyValuePairs)) {
+ fMaxFileUploadRequestSize = initThisLong("MaxFileUploadRequestSize", aKeyValuePairs);
+ checkTooLow(fMaxFileUploadRequestSize, 1000L, "MaxFileUploadRequestSize");
+ }
+ if (hasValue("MaxRequestParamValueSize", aKeyValuePairs)) {
+ fMaxRequestParamValueSize = initThisLong("MaxRequestParamValueSize", aKeyValuePairs);
+ checkTooLow(fMaxRequestParamValueSize, 1000L, "MaxRequestParamValueSize");
+ }
+ if (hasValue("SpamDetectionInFirewall", aKeyValuePairs)) {
+ fSpamDetectionInFirewall = initThisBoolean("SpamDetectionInFirewall", aKeyValuePairs);
+ }
+ if (hasValue("FullyValidateFileUploads", aKeyValuePairs)) {
+ fFullyValidateFileUploads = initThisBoolean("FullyValidateFileUploads", aKeyValuePairs);
+ }
+ if (hasValue("AllowStringAsBuildingBlock", aKeyValuePairs)) {
+ fAllowStringAsBuildingBlock = initThisBoolean("AllowStringAsBuildingBlock", aKeyValuePairs);
+ }
+ if (hasValue("UntrustedProxyForUserId", aKeyValuePairs)) {
+ ParseUntrustedProxy untrusted = new ParseUntrustedProxy();
+ fUntrustedProxyForUserId = untrusted.parse(aKeyValuePairs.get("UntrustedProxyForUserId"));
+ }
+ if (hasValue("CharacterEncoding", aKeyValuePairs)) {
+ fCharacterEncoding = initThisString("CharacterEncoding", aKeyValuePairs);
+ }
+ if (hasValue("DefaultLocale", aKeyValuePairs)) {
+ fDefaultLocale = initThisLocale("DefaultLocale", aKeyValuePairs);
+ }
+ if (hasValue("DefaultUserTimeZone", aKeyValuePairs)) {
+ fDefaultUserTimeZone = initThisTimeZone("DefaultUserTimeZone", aKeyValuePairs);
+ }
+ if (hasValueNotNone("TimeZoneHint", aKeyValuePairs)) {
+ fTimeZoneHint = initThisTimeZone("TimeZoneHint", aKeyValuePairs);
+ }
+ if (hasValue("DecimalSeparator", aKeyValuePairs)) {
+ fDecimalSeparator = initThisString("DecimalSeparator", aKeyValuePairs);
+ fDecimalInputPattern = fDecimalParser.getDecimalFormatPattern(fDecimalSeparator);
+ }
+ if (hasValue("BigDecimalDisplayFormat", aKeyValuePairs)) {
+ fBigDecimalDisplayFormat = initThisString("BigDecimalDisplayFormat", aKeyValuePairs);
+ }
+ if (hasValue("BooleanTrueDisplayFormat", aKeyValuePairs)) {
+ fBooleanTrueDisplayFormat = initThisString("BooleanTrueDisplayFormat", aKeyValuePairs);
+ }
+ if (hasValue("BooleanFalseDisplayFormat", aKeyValuePairs)) {
+ fBooleanFalseDisplayFormat = initThisString("BooleanFalseDisplayFormat", aKeyValuePairs);
+ }
+ if (hasValue("EmptyOrNullDisplayFormat", aKeyValuePairs)) {
+ fEmptyOrNullDisplayFormat = initThisString("EmptyOrNullDisplayFormat", aKeyValuePairs);
+ }
+ if (hasValue("IntegerDisplayFormat", aKeyValuePairs)) {
+ fIntegerDisplayFormat = initThisString("IntegerDisplayFormat", aKeyValuePairs);
+ }
+ if (hasValue("IgnorableParamValue", aKeyValuePairs)) {
+ fIgnorableParamValue = initThisString("IgnorableParamValue", aKeyValuePairs);
+ }
+ if (hasValue("IsSQLPrecompilationAttempted", aKeyValuePairs)) {
+ fIsSQLPrecompilationAttempted = initThisDbConfig("IsSQLPrecompilationAttempted", aKeyValuePairs);
+ }
+ if (hasValue("MaxRows", aKeyValuePairs)) {
+ fMaxRows = initThisDbConfig("MaxRows", aKeyValuePairs);
+ }
+ if (hasValue("FetchSize", aKeyValuePairs)) {
+ fFetchSize = initThisDbConfig("FetchSize", aKeyValuePairs);
+ }
+ if (hasValue("HasAutoGeneratedKeys", aKeyValuePairs)) {
+ fHasAutoGeneratedKeys = initThisDbConfig("HasAutoGeneratedKeys", aKeyValuePairs);
+ }
+ if (hasValue("ErrorCodeForDuplicateKey", aKeyValuePairs)) {
+ fErrorCodeForDuplicateKey = initThisDbConfig("ErrorCodeForDuplicateKey", aKeyValuePairs);
+ }
+ if (hasValue("ErrorCodeForForeignKey", aKeyValuePairs)) {
+ fErrorCodeForForeignKey = initThisDbConfig("ErrorCodeForForeignKey", aKeyValuePairs);
+ }
+ if (hasValue("SqlFetcherDefaultTxIsolationLevel", aKeyValuePairs)) {
+ fSqlFetcherDefaultTxIsolationLevel = initThisDbConfig("SqlFetcherDefaultTxIsolationLevel", aKeyValuePairs);
+ }
+ if (hasValue("SqlEditorDefaultTxIsolationLevel", aKeyValuePairs)) {
+ fSqlEditorDefaultTxIsolationLevel = initThisDbConfig("SqlEditorDefaultTxIsolationLevel", aKeyValuePairs);
+ }
+ if (hasValue("DateTimeFormatForPassingParamsToDb", aKeyValuePairs)) {
+ fDateTimeFormatForPassingParamsToDb = initThisDbConfig("DateTimeFormatForPassingParamsToDb", aKeyValuePairs);
+ }
+ if (hasValue("IsTesting", aKeyValuePairs)) {
+ fIsTesting = initThisBoolean("IsTesting", aKeyValuePairs);
+ }
+
+ if (! fErrors.isEmpty()){
+ throw new RuntimeException("Errors in config data: " + fErrors);
+ }
+ }
+
+ private static boolean hasValue(String aName, Map<String, String> aKeyValuePairs){
+ return Util.textHasContent(aKeyValuePairs.get(aName));
+ }
+
+ private static boolean hasValueNotNone(String aName, Map<String, String> aKeyValuePairs){
+ String value = aKeyValuePairs.get(aName);
+ return Util.textHasContent(value) && (! NONE.equalsIgnoreCase(value));
+ }
+
+ private static String initThisString(String aName, Map<String, String> aKeyValuePairs){
+ return aKeyValuePairs.get(aName);
+ }
+
+ private static Long initThisLong(String aName, Map<String, String> aKeyValuePairs){
+ return asLong(aKeyValuePairs.get(aName));
+ }
+
+ private static TimeZone initThisTimeZone(String aName, Map<String, String> aKeyValuePairs){
+ return asTimeZone(aKeyValuePairs.get(aName));
+ }
+
+ private static List<String> initThisStringList(String aName, Map<String, String> aKeyValuePairs){
+ return asStringListWithNone(aKeyValuePairs.get(aName));
+ }
+
+ private static String initThisStringNoDefault(final String aName, final Map<String, String> aKeyValuePairs){
+ String result = aKeyValuePairs.get(aName);
+ if (! Util.textHasContent(result)){
+ fErrors.add(aName + " has no value set.");
+ }
+ return result;
+ }
+
+ private static Boolean initThisBoolean(String aName, Map<String, String> aKeyValuePairs){
+ String value = aKeyValuePairs.get(aName);
+ return Util.parseBoolean(value);
+ }
+
+ private static DbConfigParser initThisDbConfig(String aName, Map<String, String> aKeyValuePairs){
+ return new DbConfigParser(aKeyValuePairs.get(aName));
+ }
+
+ private static Locale initThisLocale(String aName, Map<String, String> aKeyValuePairs){
+ return asLocale(aKeyValuePairs.get(aName));
+ }
+
+ /* These declares define the default value of each item, if any. */
+
+ //used for iteration over raw values (logging)
+ private static Map<String, String> fMap;
+
+ private static String fWebmaster = ""; //no default
+ private static String fImplicitMappingRemoveBasePackage = ""; //no default
+
+ private static String fMailServerConfig = "NONE";
+ private static String fMailServerCredentials = "NONE";
+ private static String fLoggingDirectory = "NONE";
+ private static List<String> fLoggingLevels = Arrays.asList("hirondelle.web4j.level=CONFIG");
+ private static List<String> fTroubleTicketMailingList = Collections.emptyList();
+ private static Long fMinimumIntervalBetweenTroubleTickets = Long.valueOf(30);
+ private static Long fPoorPerformanceThreshold = 20L;
+ private static Long fMaxHttpRequestSize = 51200L;
+ private static Long fMaxFileUploadRequestSize = 51200L;
+ private static Long fMaxRequestParamValueSize = 51200L;
+ private static Boolean fSpamDetectionInFirewall = Boolean.FALSE;
+ private static Boolean fFullyValidateFileUploads = Boolean.FALSE;
+ private static Boolean fAllowStringAsBuildingBlock = Boolean.FALSE;
+ private static Map<String, List<String>> fUntrustedProxyForUserId = new LinkedHashMap<String, List<String>>();
+ private static String fCharacterEncoding = "UTF-8";
+ private static Locale fDefaultLocale = Util.buildLocale("en");
+ private static TimeZone fDefaultUserTimeZone = TimeZone.getTimeZone("GMT");
+ private static TimeZone fTimeZoneHint; //default is null in this case
+
+ // these 3 are related to each other
+ private static String fDecimalSeparator = "PERIOD";
+ private static ParseDecimalFormat fDecimalParser = new ParseDecimalFormat();
+ private static Pattern fDecimalInputPattern = fDecimalParser.getDecimalFormatPattern(fDecimalSeparator);// the default, as usual
+
+ private static String fBigDecimalDisplayFormat = "#,##0.00";
+ private static String fBooleanTrueDisplayFormat = "<![CDATA[ <input type='checkbox' name='true' value='true' checked readonly notab> ]]>";
+ private static String fBooleanFalseDisplayFormat = "<![CDATA[ <input type='checkbox' name='false' value='false' checked readonly notab>]]>";
+ private static String fEmptyOrNullDisplayFormat = "-";
+ private static String fIntegerDisplayFormat = "#,###";
+ private static String fIgnorableParamValue = "";
+
+ //database items
+ private static DbConfigParser fIsSQLPrecompilationAttempted = new DbConfigParser("TRUE");
+ private static DbConfigParser fMaxRows = new DbConfigParser("300");
+ private static DbConfigParser fFetchSize = new DbConfigParser("25");
+ private static DbConfigParser fHasAutoGeneratedKeys = new DbConfigParser("FALSE");
+ private static DbConfigParser fErrorCodeForDuplicateKey = new DbConfigParser("1");
+ private static DbConfigParser fErrorCodeForForeignKey = new DbConfigParser("2291");
+ private static DbConfigParser fSqlFetcherDefaultTxIsolationLevel = new DbConfigParser("DATABASE_DEFAULT");
+ private static DbConfigParser fSqlEditorDefaultTxIsolationLevel = new DbConfigParser("DATABASE_DEFAULT");
+ private static DbConfigParser fDateTimeFormatForPassingParamsToDb = new DbConfigParser("YYYY-MM-DD^hh:mm:ss^YYYY-MM-DD hh:mm:ss");
+
+ private static Boolean fIsTesting = Boolean.FALSE;
+
+ /* Simple conversion methods. */
+
+ private static Long asLong(String aValue){
+ return Long.valueOf(aValue);
+ }
+
+ private static Integer asInteger(String aValue){
+ return Integer.valueOf(aValue);
+ }
+
+ private static TimeZone asTimeZone(String aValue){
+ TimeZone result = null;
+ try{
+ result = Util.buildTimeZone(aValue);
+ }
+ catch(Throwable ex){
+ fErrors.add(ex.getMessage());
+ }
+ return result;
+ }
+
+ private static Locale asLocale(String aValue){
+ return Util.buildLocale(aValue);
+ }
+
+ /**
+ Separated by a comma.
+ Special value 'NONE' denotes an empty list.
+ */
+ private static List<String> asStringListWithNone(String aValue){
+ List<String> result = new ArrayList<String>();
+ if (! "NONE".equalsIgnoreCase(aValue)){
+ result.addAll(asStringList(aValue));
+ }
+ return result;
+ }
+
+ /** Separated by a comma. */
+ private static List<String> asStringList(String aValue){
+ List<String> result = new ArrayList<String>();
+ StringTokenizer parser = new StringTokenizer(aValue, ",");
+ while (parser.hasMoreElements()){
+ String item = (String)parser.nextElement();
+ result.add(item);
+ }
+ return result;
+ }
+
+
+ /** Separated by a comma. */
+ private static List<Integer> asIntegerList(String aValue){
+ List<Integer> result = new ArrayList<Integer>();
+ String DELIMITER = ",";
+ StringTokenizer parser = new StringTokenizer(aValue, DELIMITER);
+ while ( parser.hasMoreTokens() ) {
+ String errorCode = parser.nextToken();
+ result.add(new Integer(errorCode.trim()));
+ }
+ return result;
+ }
+
+ private static Boolean asBoolean(String aValue){
+ return Util.parseBoolean(aValue);
+ }
+
+ private static String asDateTimeFormat(String aDbSetting, int aPart){
+ String[] formats = aDbSetting.split("\\^");
+ if(formats.length != 3) {
+ fErrors.add(
+ "DateTimeFormatForPassingParamsToDb setting in web.xml does not have a valid value: " + Util.quote(aDbSetting) +
+ ". Does not have 3 entries, separated by a '^' character."
+ );
+ }
+ return formats[aPart];
+ }
+
+ private static void checkTooLow(Long aValue, Long aMin, String aName) {
+ if (aValue < aMin){
+ fErrors.add(
+ "Configured value of " + aValue + " in web.xml for " + aName +
+ " is less than " + aMin + ". Please see web.xml for more information."
+ );
+ }
+ }
+}