001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.core; 020 021import java.io.BufferedInputStream; 022import java.io.FileInputStream; 023import java.io.IOException; 024import java.io.Serializable; 025import java.util.*; 026import java.util.stream.IntStream; 027 028/** 029 * A {@link Configuration} implementation backed by a {@link java.util.Properties} object. 030 * @author apr@cs.com.uy 031 * @version $Id$ 032 * @since jPOS 1.1 033 */ 034public class SimpleConfiguration implements Configuration, Serializable { 035 /** Backing property store used by this configuration instance. */ 036 private Properties props; 037 038 /** Default constructor. */ 039 public SimpleConfiguration () { 040 props = new Properties(); 041 } 042 /** 043 * Wraps the supplied {@link Properties} as a configuration. 044 * 045 * @param props backing properties (used by reference) 046 */ 047 public SimpleConfiguration (Properties props) { 048 this.props = props; 049 } 050 /** 051 * Loads a configuration from a Java {@code .properties} file. 052 * 053 * @param filename path to the properties file 054 * @throws IOException if the file cannot be read 055 */ 056 public SimpleConfiguration (String filename) 057 throws IOException 058 { 059 props = new Properties(); 060 load (filename); 061 } 062 063 /** 064 * Returns the value of the configuration property named {@code name}, or the default value {@code def}. 065 * 066 * If the property value has the format <code>${xxx}</code> then its value is taken from a system property 067 * if it exists, or an environment variable. System property takes priority over environment variable. 068 * 069 * If the format is <code>$sys{...}</code> we read only a system property. 070 * if the format is <code>$env{...}</code> only an environment variable is used. 071 * 072 * @param name The configuration property key name. 073 * @param def The default value. 074 * @return The value stored under {@code name}, 075 * or {@code def} if there's no configuration property under the given {@code name}. 076 */ 077 public String get (String name, String def) { 078 Object obj = props.get (name); 079 if (obj instanceof String[]) { 080 String[] arr= (String[]) obj; 081 obj = arr.length > 0 ? arr[0] : null; 082 } else if (obj instanceof List) { 083 List l = (List) obj; 084 obj = l.size() > 0 ? l.get(0) : null; 085 } 086 return (obj instanceof String) ? Environment.get((String) obj, def) : def; 087 } 088 public String[] getAll (String name) { 089 String[] ret; 090 Object obj = props.get (name); 091 if (obj instanceof String[]) { 092 ret = (String[]) obj; 093 } else if (obj instanceof String) { 094 ret = new String[1]; 095 ret[0] = (String) obj; 096 } else 097 ret = new String[0]; 098 099 Environment env = Environment.getEnvironment(); 100 IntStream.range(0, ret.length).forEachOrdered(i -> ret[i] = env.getProperty(ret[i])); 101 return Arrays.stream(ret).filter(Objects::nonNull).toArray(String[]::new); 102 } 103 public int[] getInts (String name) { 104 String[] ss = getAll (name); 105 int[] ii = new int[ss.length]; 106 for (int i=0; i<ss.length; i++) 107 ii[i] = Integer.parseInt(ss[i].trim()); 108 return ii; 109 } 110 public long[] getLongs (String name) { 111 String[] ss = getAll (name); 112 long[] ll = new long[ss.length]; 113 for (int i=0; i<ss.length; i++) 114 ll[i] = Long.parseLong(ss[i].trim()); 115 return ll; 116 } 117 public double[] getDoubles (String name) { 118 String[] ss = getAll (name); 119 double[] dd = new double[ss.length]; 120 for (int i=0; i<ss.length; i++) 121 dd[i] = Double.valueOf(ss[i].trim()); 122 return dd; 123 } 124 public boolean[] getBooleans (String name) { 125 String[] ss = getAll (name); 126 boolean[] bb = new boolean[ss.length]; 127 for (int i=0; i<ss.length; i++) 128 bb[i] = ss[i].equalsIgnoreCase("true") || ss[i].equalsIgnoreCase("yes"); 129 return bb; 130 } 131 public String get (String name) { 132 return get(name, ""); 133 } 134 public int getInt (String name) { 135 return Integer.parseInt(get(name, "0").trim()); 136 } 137 public int getInt (String name, int def) { 138 return Integer.parseInt(get(name, Integer.toString(def)).trim()); 139 } 140 public long getLong (String name) { 141 return Long.parseLong(get(name, "0").trim()); 142 } 143 public long getLong (String name, long def) { 144 return Long.parseLong(get(name, Long.toString(def)).trim()); 145 } 146 public double getDouble(String name) { 147 return Double.valueOf(get(name, "0.00").trim()); 148 } 149 public double getDouble(String name, double def) { 150 return Double.valueOf(get(name, Double.toString(def)).trim()); 151 } 152 public boolean getBoolean (String name) { 153 String v = get (name, "false").trim(); 154 return v.equalsIgnoreCase("true") || v.equalsIgnoreCase("yes"); 155 } 156 public boolean getBoolean (String name, boolean def) { 157 String v = get (name); 158 return v.length() == 0 ? def : 159 v.equalsIgnoreCase("true") || v.equalsIgnoreCase("yes"); 160 } 161 /** 162 * Loads a Java {@code .properties} file into this configuration. 163 * 164 * @param filename path to the properties file 165 * @throws IOException if the file cannot be read 166 */ 167 public void load(String filename) 168 throws IOException 169 { 170 FileInputStream fis = new FileInputStream(filename); 171 props.load(new BufferedInputStream(fis)); 172 fis.close(); 173 } 174 public synchronized void put (String name, Object value) { 175 props.put (name, value); 176 } 177 @Override 178 public Set<String> keySet() { 179 return props.stringPropertyNames(); 180 } 181 182 @Override 183 public boolean equals(Object o) { 184 if (this == o) return true; 185 if (o == null || getClass() != o.getClass()) return false; 186 SimpleConfiguration that = (SimpleConfiguration) o; 187 return Objects.equals(props, that.props); 188 } 189 190 @Override 191 public int hashCode() { 192 return Objects.hash(props); 193 } 194 195 @Override 196 public String toString() { 197 return "SimpleConfiguration{" + 198 "props=" + props + 199 '}'; 200 } 201 202 private static final long serialVersionUID = -6361797037366246968L; 203}