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 006 package fc.util; 007 008 import java.io.*; 009 import fc.io.*; 010 011 /** 012 Implementations help load and manage properties from various 013 sources including java property files, databases, custom 014 file formats etc. Regardless of where the properties are 015 loaded from, each property consists of a pair of <b>name</b> 016 and <b>value</b> strings. 017 018 @author hursh jain 019 @version 1.0 12/30/2001 020 */ 021 public abstract class PropertyMgr 022 { 023 protected String usage; 024 protected Log log; 025 026 /** 027 Constructs a new PropertyMgr. 028 **/ 029 public PropertyMgr() { 030 this.log = Log.getDefault(); 031 } 032 033 /** 034 Returns the property associated with the specified key or <tt>null</tt> 035 if the property was not found. 036 @param name the property key 037 **/ 038 public abstract String get(String name); 039 040 041 /** 042 Returns 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 **/ 048 public 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 /** 059 Returns the property associated with the specified key as a 060 boolean value. If the property <b>is</b> present, then the 061 corresponding boolean value is <tt>true</tt> if the property 062 value is any of the following (case-insensitive): 063 <blockquote> 064 <code> 065 yes, 1, true 066 </code> 067 <blockquote> 068 else <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 */ 076 public 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 /** 086 Returns the property associated with the specified key as a 087 integer value. If the property is present but cannot be 088 converted into an integer (via a {@link 089 Integer.parseInt(String)} call), the backup value will be 090 returned. 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 */ 098 public 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 /** 114 Returns the value corresponding to the specified key. If the 115 property <b>value</b> is not found, the {@link #handleError} method 116 is called, which by default prints a stack trace and exits 117 the application. 118 <p> 119 If the handleError method is overriden to <b>not</b> exit 120 the application, then this method will return <tt>null</tt> 121 if the specified key is not found. 122 123 @param name the property key 124 **/ 125 public 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 /* 147 Returns the value obtained via {@link getRequired(String)} 148 as as a boolean. The boolean value returned is 149 <code>true</code> if the property value is any of the 150 following (case-insensitive): 151 <blockquote> 152 <code> 153 yes, 1, true 154 </code> 155 <blockquote> 156 else <tt>false</tt> is returned. 157 */ 158 public boolean getRequiredBoolean(String name) 159 { 160 String val = getRequired(name); 161 return toBoolean(val); 162 } 163 164 /* 165 Returns the value obtained via {@link getRequired(String)} as 166 as an integer. If the property cannot be converted into an integer (via a {@link 167 Integer.parseInt(String)} call), the resulting action would 168 be the same as if the required key was not present. 169 */ 170 public 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 /** 200 Sets 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 **/ 206 public abstract String set(String name, String backup); 207 208 /** 209 Saves any properties that were set previously. This method does not 210 need to be called if properties were only read, however if any 211 property was modified or added, it is essential to call this method 212 to save any such changes. 213 **/ 214 public abstract void save() throws IOException; 215 216 /** 217 Specify program usage information to be output when an error occurs. This 218 information should contain a short description of required keys and any 219 other information that the application expects. 220 @param str Usage information 221 **/ 222 public void setUsage(String str) 223 { 224 this.usage = str; 225 } 226 227 /** 228 Default implementation:<br> 229 Handles all error situation - such as when a required property is 230 not found. By default, prints an error message to <tt>System.err</tt> and 231 exits the JVM by calling <tt>System.exit(1)</tt>. 232 This 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 **/ 236 protected 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 246 final 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