/* * #%L * gitools-ui-platform * %% * Copyright (C) 2013 Universitat Pompeu Fabra - Biomedical Genomics group * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ package org.gitools.ui.platform.help; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Hashtable; import java.util.NoSuchElementException; import java.util.Properties; /** * The tag ${} is used to introduce substitutable parameters so it * expands properties with ${} described in a property file; it is possible to * have different sections with the same names as:<br> * <p/> * global_name1=z1 <br> * sec_name=v <br> * x1=2 <br> * y1=0 <br> * [section_1] <br> * x1=${x1} <br> * [section2] <br> * x1=zxc <br> * [${sec_name}] <br> * ... <br> * * @author Serguei Eremenko * @version 1.0 * <p/> * http://articles.techrepublic.com.com/5100-10878_11-1049526.html# * @noinspection ALL */ public class PropertiesExpansion extends Properties { /** * Creates an empty property list with no default values. */ public PropertiesExpansion() { super(); } /** * Creates an empty property list with the specified defaults. * * @param def the defaults. */ public PropertiesExpansion(Properties def) { super(def); } /** * Searches for the property with the specified key in this property list * and substitutes any ${} occurrence that may be in the key. * * @param key the property key. * @return the value in this property list with the specified key value or * null if not found. */ public String getProperty(String key) { return replace(super.getProperty(replace(key))); } /** * Searches for the property within the specified section and with the * specified key in this property list and substitutes any ${} occurrence * that may be in the key. * * @param section the property section. * @param key the property key. * @return the value in this property list within the specified section and * with the specified key value or null if not found. */ public String getProperty(String section, String key) { Properties p = (Properties) get(replace(section)); if (p == null) { return null; } return replace(p.getProperty(replace(key))); } /** * @param section the property section. * @param key the property key. * @param def the default value. * @return the value in this property list within the specified section and * with the specified key value or this default value. */ public String getProperty(String section, String key, String def) { String s = getProperty(section, key); if (s == null) { s = def; } return replace(s); } /** * Casts a found property to its integer value * * @param prop the Properties to be searched in * @param key the property key * @param def the default value * @return the found value cast to integer or the default value * @see #getProperty */ public static int getInt(Properties prop, String key, int def) { int out = def; try { out = getInt(prop, key); } catch (RuntimeException e) { } return out; } /** * @see #getProperty */ private static int getInt(Properties prop, String key) { String s = prop.getProperty(key); if (s == null) { throw new NoSuchElementException("No key " + key + " found"); } return Integer.parseInt(s); } public static long getLong(Properties prop, String key, long def) { long out = def; try { out = getLong(prop, key); } catch (RuntimeException e) { } return out; } private static long getLong(Properties prop, String key) { String s = prop.getProperty(key); if (s == null) { throw new NoSuchElementException("No key " + key + " found"); } return Long.parseLong(s); } public static float getFloat(Properties prop, String key, float def) { float out = def; try { out = getFloat(prop, key); } catch (RuntimeException e) { } return out; } private static float getFloat(Properties prop, String key) { String s = prop.getProperty(key); if (s == null) { throw new NoSuchElementException("No key " + key + " found"); } return Float.parseFloat(s); } public static double getDouble(Properties prop, String key, double def) { double out = def; try { out = getDouble(prop, key); } catch (RuntimeException e) { } return out; } private static double getDouble(Properties prop, String key) { String s = prop.getProperty(key); if (s == null) { throw new NoSuchElementException("No key " + key + " found"); } return Double.parseDouble(s); } public static boolean getBoolean(Properties prop, String key, boolean def) { boolean out = def; try { out = getBoolean(prop, key); } catch (RuntimeException e) { } return out; } private static boolean getBoolean(Properties prop, String key) { String s = prop.getProperty(key); if (s == null) { throw new NoSuchElementException("No key " + key + " found"); } return new Boolean(s).booleanValue(); } public int getInt(String key, int def) { int out = def; try { out = getInt(key); } catch (RuntimeException e) { } return out; } int getInt(String key) { String s = getProperty(key); if (s == null) { throw new NoSuchElementException("No key " + key + " found"); } return Integer.parseInt(s); } public long getLong(String key, long def) { long out = def; try { out = getLong(key); } catch (RuntimeException e) { } return out; } long getLong(String key) { String s = getProperty(key); if (s == null) { throw new NoSuchElementException("No key " + key + " found"); } return Long.parseLong(s); } public float getFloat(String key, float def) { float out = def; try { out = getFloat(key); } catch (RuntimeException e) { } return out; } float getFloat(String key) { String s = getProperty(key); if (s == null) { throw new NoSuchElementException("No key " + key + " found"); } return Float.parseFloat(s); } public double getDouble(String key, double def) { double out = def; try { out = getDouble(key); } catch (RuntimeException e) { } return out; } double getDouble(String key) { String s = getProperty(key); if (s == null) { throw new NoSuchElementException("No key " + key + " found"); } return Double.parseDouble(s); } public boolean getBoolean(String key, boolean def) { boolean out = def; try { out = getBoolean(key); } catch (RuntimeException e) { } return out; } boolean getBoolean(String key) { String s = getProperty(key); if (s == null) { throw new NoSuchElementException("No key " + key + " found"); } return new Boolean(s).booleanValue(); } /** * @param key the key to be placed into this property list. * @param value the value corresponding to key. * @return the previous value of the specified key in this property list, * or null if it did not have one. */ public Object setProperty(String key, String value) { return super.setProperty(replace(key), replace(value)); } /** * @param section the section where the key to be placed into this property * list, the section is created if the property list did not have one. * @param key the key to be placed into this property list. * @param value the value corresponding to key. * @return the previous value of the specified key in this property list, * or null if it did not have one. */ public Object setProperty(String section, String key, String value) { Properties p = (Properties) get(replace(section)); if (p == null) { p = new Properties(); put(replace(section), p); } return p.setProperty(key, replace(value)); } /** * @return an enumeration of the sections in this property list. */ public synchronized Enumeration sections() { final int len = keySet().size(); final String[] all = (String[]) keySet().toArray(new String[len]); return new Enumeration() { public boolean hasMoreElements() { next = null; while (i < len) { String key = all[i++]; if (get(key) instanceof Properties) { next = key; break; } else { next = null; } } return next != null; } public Object nextElement() { if (next == null) { throw new NoSuchElementException(); } return next; } private Object next = null; private int i = 0; }; } /** * @param section the section name where to enumerate the keys from. * @return an enumeration of the section keys in this property list or * empty enumeration if there is no such section or the section * does not contain any keys. */ public synchronized Enumeration sectionKeys(String section) { Properties p = (Properties) get(replace(section)); Enumeration en = null; if (p == null) { en = new Enumeration() { public boolean hasMoreElements() { return false; } public Object nextElement() { throw new NoSuchElementException(); } }; } else { en = p.keys(); } return en; } /** * Overrides the Hashtable's put method and its use is strongly discouraged. * * @see java.util.Hashtable#put * @see #setProperty */ public Object put(Object key, Object val) { if (key == null || val == null) { throw new NullPointerException(); } Object o = null; if (key instanceof String && val instanceof String) { String s = (String) key; int i = s.indexOf(startSecSep); if (i == 0) { curSec = replace(s.substring(i + 1, s.indexOf(endSecSep, i + 2))); Properties p = (Properties) get(curSec); if (p == null) { p = new Properties(); o = super.put(curSec, p); } } else { Properties p = (Properties) get(curSec); if (p != null) { o = p.put(key, val); } else { o = super.put(key, val); } } } else { o = super.put(key, val); } return o; } /** * Reads a property list (key and element pairs) from the input stream. * * @param is the input stream. */ public synchronized void load(InputStream is) throws IOException { curSec = ""; super.load(is); curSec = ""; replaceAll(this); } /** * Writes this property list (key and element pairs) in this Properties * table to the output stream in a format suitable for loading into a * Properties table using the load method. * * @param os an output stream. * @param header a description of the property list. */ public synchronized void store(OutputStream os, String header) throws IOException { Properties p = null; for (Enumeration en = keys(); en.hasMoreElements(); ) { String k = (String) en.nextElement(); Object v = get(k); if (v instanceof String) { if (p == null) { p = new Properties(); } p.put(k, v); } } if (p != null) { p.store(os, header); } for (Enumeration en = keys(); en.hasMoreElements(); ) { String k = (String) en.nextElement(); Object v = get(k); if (v instanceof Properties) { byte[] b = (startSecSep + k + endSecSep + "\r\n").getBytes(); os.write(b, 0, b.length); os.flush(); ((Properties) v).store(os, null); } } } /** * @param in the string where substitutable parameters ${} will be replaces * with values contained in the hashtable of keys * @param keys the hashtable of keys * @return the substituted string */ public static String replace(String in, Hashtable keys) { if (in == null) { return null; } if (keys == null) { throw new NullPointerException("Keys source is null"); } StringBuffer out = new StringBuffer(); int index = 0; int i = 0; String key = null; while ((index = in.indexOf(startTag, i)) > -1) { key = in.substring(index + 2, in.indexOf(endTag, index + 3)); out.append(in.substring(i, index)); if (keys.containsKey(key)) { out.append(keys.get(key)); } else { out.append(startTag).append(key).append(endTag); } i = index + 3 + key.length(); } return out.append(in.substring(i)).toString(); } /** * @param in the key which string value to be replaced with values from * this property list */ String replace(String in) { if (in == null) { return null; } StringBuffer out = new StringBuffer(); int index = 0; int i = 0; String key = null; while ((index = in.indexOf(startTag, i)) > -1) { key = in.substring(index + 2, in.indexOf(endTag, index + 3)); out.append(in.substring(i, index)); String val = super.getProperty(key); if (val != null) { // be careful here out.append(replace(val)); } else { out.append(startTag).append(key).append(endTag); } i = index + 3 + key.length(); } return out.append(in.substring(i)).toString(); } /** * Replaces all occurrences of the substitution tag in the given Properties. */ void replaceAll(Properties p) { for (Enumeration en = p.keys(); en.hasMoreElements(); ) { String k = (String) en.nextElement(); Object v = p.get(k); if (v instanceof String) { String nv = replace((String) v); p.put(k, nv); } if (v instanceof Properties) { replaceAll((Properties) v); } } } private static final char startSecSep = '['; private static final char endSecSep = ']'; private static final String startTag = "${"; private static final String endTag = "}"; private String curSec = ""; }