| 1 | /* This file is part of the project "Hilbert II" - http://www.qedeq.org |
| 2 | * |
| 3 | * Copyright 2000-2014, Michael Meyling <mime@qedeq.org>. |
| 4 | * |
| 5 | * "Hilbert II" is free software; you can redistribute |
| 6 | * it and/or modify it under the terms of the GNU General Public |
| 7 | * License as published by the Free Software Foundation; either |
| 8 | * version 2 of the License, or (at your option) any later version. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | */ |
| 15 | |
| 16 | package org.qedeq.kernel.se.config; |
| 17 | |
| 18 | import java.io.File; |
| 19 | import java.io.FileInputStream; |
| 20 | import java.io.FileOutputStream; |
| 21 | import java.io.IOException; |
| 22 | import java.io.InputStream; |
| 23 | import java.io.OutputStream; |
| 24 | import java.util.ArrayList; |
| 25 | import java.util.Collections; |
| 26 | import java.util.Enumeration; |
| 27 | import java.util.HashMap; |
| 28 | import java.util.Iterator; |
| 29 | import java.util.List; |
| 30 | import java.util.Map; |
| 31 | import java.util.Properties; |
| 32 | |
| 33 | import org.qedeq.base.io.IoUtility; |
| 34 | |
| 35 | |
| 36 | /** |
| 37 | * This class reads entries from property files. This class should not |
| 38 | * be used outside this package. |
| 39 | * |
| 40 | * @author Michael Meyling |
| 41 | */ |
| 42 | final class ConfigAccess { |
| 43 | |
| 44 | /** Config file. */ |
| 45 | private final File configFile; |
| 46 | |
| 47 | /** Collector for properties. */ |
| 48 | private Properties properties = new Properties(); |
| 49 | |
| 50 | /** Config file description. */ |
| 51 | private final String description; |
| 52 | |
| 53 | /** |
| 54 | * Get access for a config file. |
| 55 | * |
| 56 | * @param configFile Config file. |
| 57 | * @param description Config file description |
| 58 | * @throws IOException Config file couldn't be loaded. |
| 59 | */ |
| 60 | public ConfigAccess(final File configFile, final String description) throws IOException { |
| 61 | this.configFile = configFile; |
| 62 | this.description = description; |
| 63 | FileInputStream stream = null; |
| 64 | try { |
| 65 | stream = new FileInputStream(configFile); |
| 66 | load(stream); |
| 67 | } catch (IOException e) { |
| 68 | System.out.println("no config file found, using default values"); |
| 69 | } finally { |
| 70 | IoUtility.close(stream); |
| 71 | } |
| 72 | setString("configFileLocation", configFile.getCanonicalPath()); |
| 73 | } |
| 74 | |
| 75 | /** |
| 76 | * Get config file. |
| 77 | * |
| 78 | * @return Config file. |
| 79 | */ |
| 80 | public final synchronized File getConfigFile() { |
| 81 | return configFile; |
| 82 | } |
| 83 | |
| 84 | /** |
| 85 | * Get description for config file. |
| 86 | * |
| 87 | * @return Config file description. |
| 88 | */ |
| 89 | public final synchronized String getConfigDescription() { |
| 90 | return description; |
| 91 | } |
| 92 | |
| 93 | /** |
| 94 | * Get properties. |
| 95 | * |
| 96 | * @return properties. |
| 97 | */ |
| 98 | private final Properties getProperties() { |
| 99 | return properties; |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * Load properties from stream. The properties are |
| 104 | * added to the previous ones. |
| 105 | * |
| 106 | * @param inStream load from this stream |
| 107 | * @throws IOException loading failed |
| 108 | */ |
| 109 | private final void load(final InputStream inStream) throws IOException { |
| 110 | getProperties().load(inStream); |
| 111 | } |
| 112 | |
| 113 | /** |
| 114 | * Store properties in config file. |
| 115 | * |
| 116 | * @throws IOException Saving failed. |
| 117 | */ |
| 118 | public final synchronized void store() throws IOException { |
| 119 | OutputStream out = null; |
| 120 | try { |
| 121 | final File file = getConfigFile(); |
| 122 | IoUtility.createNecessaryDirectories(file); |
| 123 | out = new FileOutputStream(file); |
| 124 | getProperties().store(out, getConfigDescription()); |
| 125 | } finally { |
| 126 | if (out != null) { |
| 127 | try { |
| 128 | out.close(); |
| 129 | } catch (IOException e) { |
| 130 | throw e; |
| 131 | } catch (Exception e) { |
| 132 | throw new IOException(e.toString()); |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | /** |
| 139 | * Return String property. |
| 140 | * |
| 141 | * @param name Get this property. |
| 142 | * @return String for looked property. <code>null</code>, if property is missing. |
| 143 | */ |
| 144 | public final synchronized String getString(final String name) { |
| 145 | return getProperties().getProperty(name); |
| 146 | } |
| 147 | |
| 148 | /** |
| 149 | * Return String property. |
| 150 | * |
| 151 | * @param name Look for this String property. |
| 152 | * @param defaultValue Return this value if property doesn't exist. |
| 153 | * @return Value of property. Equal to default value if parameter doesn't exist. |
| 154 | */ |
| 155 | public final synchronized String getString(final String name, final String defaultValue) { |
| 156 | final String value = getProperties().getProperty(name); |
| 157 | if (value == null) { |
| 158 | setString(name, defaultValue); |
| 159 | return defaultValue; |
| 160 | } |
| 161 | return value; |
| 162 | } |
| 163 | |
| 164 | /** |
| 165 | * Set String property. |
| 166 | * |
| 167 | * @param name Set this property. |
| 168 | * @param value Set property to this value. |
| 169 | */ |
| 170 | public final synchronized void setString(final String name, final String value) { |
| 171 | getProperties().setProperty(name, value); |
| 172 | } |
| 173 | |
| 174 | /** |
| 175 | * Get list of String properties with certain prefix. |
| 176 | * Example: |
| 177 | * <ul> |
| 178 | * <li>qeq=green</li> |
| 179 | * <li>module2=tiger</li> |
| 180 | * <li>module3=tulip</li> |
| 181 | * <li>modula=green</li> |
| 182 | * <li>module1=bluebird</li> |
| 183 | * </ul> |
| 184 | * If namePrefix == "module" we get: |
| 185 | * <ul> |
| 186 | * <li>module1=bluebird</li> |
| 187 | * <li>module2=tiger</li> |
| 188 | * <li>module3=tulip</li> |
| 189 | * </ul> |
| 190 | * The sequence of resulting properties is sorted by their keys. |
| 191 | * |
| 192 | * @param namePrefix Prefix of seek property name. |
| 193 | * @return List of key sorted string properties (maybe empty). |
| 194 | */ |
| 195 | public final synchronized String[] getStringProperties(final String namePrefix) { |
| 196 | final List list = new ArrayList(); |
| 197 | final Enumeration keys = getProperties().keys(); |
| 198 | final List keyList = Collections.list(keys); |
| 199 | Collections.sort(keyList); |
| 200 | for (int i = 0; i < keyList.size(); i++) { |
| 201 | final String key = (String) keyList.get(i); |
| 202 | if (key.startsWith(namePrefix)) { |
| 203 | list.add(getProperties().get(key)); |
| 204 | } |
| 205 | } |
| 206 | return (String []) list.toArray(new String[list.size()]); |
| 207 | } |
| 208 | |
| 209 | /** |
| 210 | * Get map of String properties with certain prefix. |
| 211 | * |
| 212 | * @param namePrefix Prefix of seek property name. |
| 213 | * @return Map of properties that have String keys that start with <code>namePrefix</code>. |
| 214 | * The prefix is removed of for the resulting map. |
| 215 | */ |
| 216 | public final synchronized Map getProperties(final String namePrefix) { |
| 217 | final Map result = new HashMap(); |
| 218 | Iterator i = getProperties().entrySet().iterator(); |
| 219 | while (i.hasNext()) { |
| 220 | Map.Entry entry = (Map.Entry) i.next(); |
| 221 | final String name = String.valueOf(entry.getKey()); |
| 222 | if (name.startsWith(namePrefix)) { |
| 223 | result.put(name.substring(namePrefix.length()), entry.getValue()); |
| 224 | } |
| 225 | } |
| 226 | return result; |
| 227 | } |
| 228 | |
| 229 | /** |
| 230 | * Set int property. |
| 231 | * |
| 232 | * @param name Set this property. |
| 233 | * @param value Set property to this value. |
| 234 | */ |
| 235 | public final synchronized void setInteger(final String name, final int value) { |
| 236 | setString(name, "" + value); |
| 237 | } |
| 238 | |
| 239 | |
| 240 | /** |
| 241 | * Get int property. |
| 242 | * |
| 243 | * @param name look for this property |
| 244 | * @return property |
| 245 | * @throws IllegalArgumentException Property is no valid int value |
| 246 | * @throws NullPointerException Property doesn't exist |
| 247 | */ |
| 248 | public final synchronized int getInteger(final String name) { |
| 249 | final String intPropAsString = getProperties().getProperty(name); |
| 250 | if (intPropAsString == null) { |
| 251 | throw new NullPointerException("property \"" + name + "\" not found"); |
| 252 | } |
| 253 | try { |
| 254 | return Integer.parseInt(intPropAsString); |
| 255 | } catch (NumberFormatException ex) { |
| 256 | throw new IllegalArgumentException( |
| 257 | "int property " + intPropAsString + " has invalid format"); |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | /** |
| 262 | * Return int property. |
| 263 | * |
| 264 | * @param name Look for this integer property. |
| 265 | * @param defaultValue Return this value if property doesn't exist. |
| 266 | * @return int value of property. Equal to default value if parameter doesn't exist. |
| 267 | * @throws IllegalArgumentException Property is no valid int value. |
| 268 | */ |
| 269 | public final synchronized int getInteger(final String name, final int defaultValue) { |
| 270 | final String intPropAsString = getProperties().getProperty(name); |
| 271 | if (intPropAsString == null || intPropAsString.length() == 0) { |
| 272 | setInteger(name, defaultValue); |
| 273 | return defaultValue; |
| 274 | } |
| 275 | try { |
| 276 | return Integer.parseInt(intPropAsString); |
| 277 | } catch (NumberFormatException ex) { |
| 278 | throw new IllegalArgumentException( |
| 279 | "Integer-Property " + intPropAsString + " has invalid format"); |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | /** |
| 284 | * Remove property. |
| 285 | * |
| 286 | * @param name Property to delete. |
| 287 | */ |
| 288 | public final synchronized void removeProperty(final String name) { |
| 289 | getProperties().remove(name); |
| 290 | } |
| 291 | |
| 292 | /** |
| 293 | * Remove properties with certain prefix. |
| 294 | * |
| 295 | * Example: |
| 296 | * <ul> |
| 297 | * <li>module1=bluebird</li> |
| 298 | * <li>module2=tiger</li> |
| 299 | * <li>module3=tulip</li> |
| 300 | * </ul> |
| 301 | * Calling with value <code>module</code> deletes all. |
| 302 | * |
| 303 | * @param namePrefix Prefix of seeked property name. |
| 304 | */ |
| 305 | public final synchronized void removeProperties(final String namePrefix) { |
| 306 | final Enumeration keys = getProperties().keys(); |
| 307 | while (keys.hasMoreElements()) { |
| 308 | final String key = (String) keys.nextElement(); |
| 309 | if (key.startsWith(namePrefix)) { |
| 310 | getProperties().remove(key); |
| 311 | } |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | } |