001// Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 002// The Molly framework is freely distributable under the terms of an 003// MIT-style license. For details, see the molly pages web site at: 004// http://www.mollypages.org/. Use, modify, have fun ! 005 006package fc.util; 007 008import java.io.*; 009import fc.io.*; 010 011/** 012Implementations help load and manage properties from various 013sources including java property files, databases, custom 014file formats etc. Regardless of where the properties are 015loaded from, each property consists of a pair of <b>name</b> 016and <b>value</b> strings. 017 018@author hursh jain 019@version 1.0 12/30/2001 020*/ 021public abstract class PropertyMgr 022{ 023protected String usage; 024protected Log log; 025 026/** 027Constructs a new PropertyMgr. 028**/ 029public PropertyMgr() { 030 this.log = Log.getDefault(); 031 } 032 033/** 034Returns the property associated with the specified key or <tt>null</tt> 035if the property was not found. 036@param name the property key 037**/ 038public abstract String get(String name); 039 040 041/** 042Returns the property associated with the specified key. 043@param name the property key 044@param backup value to return if the property for the specified key is not found 045 046@return value of specified key or backup string 047**/ 048public String get(String name, String backup) 049 { 050 String val = get(name); 051 if (val == null) 052 { 053 return backup; 054 } 055 else return val; 056 } 057 058/** 059Returns the property associated with the specified key as a 060boolean value. If the property <b>is</b> present, then the 061corresponding boolean value is <tt>true</tt> if the property 062value is any of the following (case-insensitive): 063<blockquote> 064<code> 065yes, 1, true 066</code> 067<blockquote> 068else <tt>false</tt> is returned. 069 070@param name the property key 071@param backup value to return if the property for the 072 specified property is <b>not</b> present 073 074@return value of specified key or backup string 075*/ 076public boolean getBoolean(String name, boolean backup) 077 { 078 String val = get(name); 079 if (val == null) 080 return backup; 081 else 082 return toBoolean(val); 083 } 084 085/** 086Returns the property associated with the specified key as a 087integer value. If the property is present but cannot be 088converted into an integer (via a {@link 089Integer.parseInt(String)} call), the backup value will be 090returned. 091 092@param name the property key 093@param backup value to return if the property for the 094 specified property is <b>not</b> present 095 096@return value of specified key or backup string 097*/ 098public int getInt(String name, int backup) 099 { 100 String val = get(name); 101 if (val != null) 102 { 103 try { 104 return Integer.parseInt(val); 105 } 106 catch (NumberFormatException e) { 107 log.warn("Cannot convert property '" + name + "', into a number, returning backup value " + backup); 108 } 109 } 110 return backup; 111 } 112 113/** 114Returns the value corresponding to the specified key. If the 115property <b>value</b> is not found, the {@link #handleError} method 116is called, which by default prints a stack trace and exits 117the application. 118<p> 119If the handleError method is overriden to <b>not</b> exit 120the application, then this method will return <tt>null</tt> 121if the specified key is not found. 122 123@param name the property key 124**/ 125public String getRequired(String name) 126 { 127 String val = get(name); 128 if (val == null || val.trim().length() == 0) { 129 try { 130 handleError(name); 131 } 132 catch (Exception e) { 133 /* 134 If the handler throws us an Exception, we pass 135 it along as a Runtime Exception (since this 136 method does not throw a checked exception). Of 137 course, handlers are free to deal with 138 Exceptions in any other way they see fit. 139 */ 140 throw new RuntimeException(e); 141 } 142 } 143 return val; 144 } 145 146/* 147Returns the value obtained via {@link getRequired(String)} 148as as a boolean. The boolean value returned is 149<code>true</code> if the property value is any of the 150following (case-insensitive): 151<blockquote> 152<code> 153yes, 1, true 154</code> 155<blockquote> 156else <tt>false</tt> is returned. 157*/ 158public boolean getRequiredBoolean(String name) 159 { 160 String val = getRequired(name); 161 return toBoolean(val); 162 } 163 164/* 165Returns the value obtained via {@link getRequired(String)} as 166as an integer. If the property cannot be converted into an integer (via a {@link 167Integer.parseInt(String)} call), the resulting action would 168be the same as if the required key was not present. 169*/ 170public int getRequiredInt(String name) 171 { 172 String val = getRequired(name); 173 174 int result = 0; 175 176 try { 177 result = Integer.parseInt(val); 178 } 179 catch (NumberFormatException ne) { 180 log.warn("Cannot convert property '" + name + "', into a number"); 181 try { 182 handleError(name); 183 } 184 catch (Exception e) { 185 /* 186 If the handler throws us an Exception, we pass 187 it along as a Runtime Exception (since this 188 method does not throw a checked exception). Of 189 course, handlers are free to deal with 190 Exceptions in any other way they see fit. 191 */ 192 throw new RuntimeException(e); 193 } 194 } 195 196 return result; 197 } 198 199/** 200Sets the property associated with the specified key. 201@param name the property key 202@param backup the property value 203@return the previous value of the specified key or null if it did not 204 have one. 205**/ 206public abstract String set(String name, String backup); 207 208/** 209Saves any properties that were set previously. This method does not 210need to be called if properties were only read, however if any 211property was modified or added, it is essential to call this method 212to save any such changes. 213**/ 214public abstract void save() throws IOException; 215 216/** 217Specify program usage information to be output when an error occurs. This 218information should contain a short description of required keys and any 219other information that the application expects. 220@param str Usage information 221**/ 222public void setUsage(String str) 223 { 224 this.usage = str; 225 } 226 227/** 228Default implementation:<br> 229Handles all error situation - such as when a required property is 230not found. By default, prints an error message to <tt>System.err</tt> and 231exits the JVM by calling <tt>System.exit(1)</tt>. 232This method can be overriden in subclasses to handle errors differently. 233@param str the error message 234@throws Exception sub classes can throw an Exception, if necessary 235**/ 236protected void handleError(String str) throws PropertyNotFoundException 237 { 238 log.error("Application is missing required Property: " + str); 239 new Exception().printStackTrace(System.err); 240 if (usage != null) { 241 log.error(usage); 242 } 243 System.exit(1); 244 } 245 246final boolean toBoolean(String val) 247 { 248 val = val.trim().toLowerCase().intern(); 249 if ( val == "true" || val == "yes" || val == "1" ) 250 return true; 251 return false; 252 } 253 254} //~class PropertyMgr