001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2011 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.api.config;
021
022 import com.google.common.collect.Lists;
023 import com.google.common.collect.Maps;
024 import org.apache.commons.lang.ArrayUtils;
025 import org.apache.commons.lang.StringUtils;
026 import org.sonar.api.BatchComponent;
027 import org.sonar.api.ServerComponent;
028 import org.sonar.api.utils.DateUtils;
029
030 import java.util.*;
031
032 /**
033 * Project Settings on batch side, Global Settings on server side.
034 * <p/>
035 * Replace the deprecated component org.apache.commons.configuration.Configuration
036 *
037 * @since 2.12
038 */
039 public class Settings implements BatchComponent, ServerComponent {
040
041 protected Map<String, String> properties = Maps.newHashMap();
042 protected PropertyDefinitions definitions;
043
044 public Settings() {
045 this(new PropertyDefinitions());
046 }
047
048 public Settings(PropertyDefinitions definitions) {
049 this.definitions = definitions;
050 }
051
052 public final String getDefaultValue(String key) {
053 return definitions.getDefaultValue(key);
054 }
055
056 public final boolean hasKey(String key) {
057 return properties.containsKey(key);
058 }
059
060 public final boolean hasDefaultValue(String key) {
061 return StringUtils.isNotEmpty(getDefaultValue(key));
062 }
063
064 public final String getString(String key) {
065 String value = properties.get(key);
066 if (value == null) {
067 value = getDefaultValue(key);
068 }
069 return value;
070 }
071
072 public final boolean getBoolean(String key) {
073 String value = getString(key);
074 return StringUtils.isNotEmpty(value) && Boolean.parseBoolean(value);
075 }
076
077 public final int getInt(String key) {
078 String value = getString(key);
079 if (StringUtils.isNotEmpty(value)) {
080 return Integer.parseInt(value);
081 }
082 return 0;
083 }
084
085 public final long getLong(String key) {
086 String value = getString(key);
087 if (StringUtils.isNotEmpty(value)) {
088 return Long.parseLong(value);
089 }
090 return 0L;
091 }
092
093 public final Date getDate(String key) {
094 String value = getString(key);
095 if (StringUtils.isNotEmpty(value)) {
096 return DateUtils.parseDate(value);
097 }
098 return null;
099 }
100
101 public final Date getDateTime(String key) {
102 String value = getString(key);
103 if (StringUtils.isNotEmpty(value)) {
104 return DateUtils.parseDateTime(value);
105 }
106 return null;
107 }
108
109 /**
110 * Value is splitted by comma and trimmed.
111 * <p/>
112 * Examples :
113 * <ul>
114 * <li>"one,two,three " -> ["one", "two", "three"]</li>
115 * <li>" one, two, three " -> ["one", "two", "three"]</li>
116 * <li>"one, , three" -> ["one", "", "three"]</li>
117 * </ul>
118 */
119 public final String[] getStringArray(String key) {
120 return getStringArrayBySeparator(key, ",");
121 }
122
123 /**
124 * Value is splitted and trimmed.
125 */
126 public final String[] getStringArrayBySeparator(String key, String separator) {
127 String value = getString(key);
128 if (value != null) {
129 String[] strings = StringUtils.splitByWholeSeparator(value, separator);
130 String[] result = new String[strings.length];
131 for (int index = 0; index < strings.length; index++) {
132 result[index] = StringUtils.trim(strings[index]);
133 }
134 return result;
135 }
136 return ArrayUtils.EMPTY_STRING_ARRAY;
137 }
138
139 public List<String> getKeysStartingWith(String prefix) {
140 List<String> result = Lists.newArrayList();
141 for (String key : properties.keySet()) {
142 if (StringUtils.startsWith(key, prefix)) {
143 result.add(key);
144 }
145 }
146 return result;
147 }
148
149 public final Settings appendProperty(String key, String value) {
150 String newValue = properties.get(key);
151 if (StringUtils.isEmpty(newValue)) {
152 newValue = value;
153 } else {
154 newValue += "," + value;
155 }
156 properties.put(key, newValue);
157 return this;
158 }
159
160 public final Settings setProperty(String key, String value) {
161 if (!clearIfNullValue(key, value)) {
162 properties.put(key, value);
163 }
164 return this;
165 }
166
167 public final Settings setProperty(String key, Boolean value) {
168 if (!clearIfNullValue(key, value)) {
169 properties.put(key, String.valueOf(value));
170 }
171 return this;
172 }
173
174 public final Settings setProperty(String key, Integer value) {
175 if (!clearIfNullValue(key, value)) {
176 properties.put(key, String.valueOf(value));
177 }
178 return this;
179 }
180
181 public final Settings setProperty(String key, Long value) {
182 if (!clearIfNullValue(key, value)) {
183 properties.put(key, String.valueOf(value));
184 }
185 return this;
186 }
187
188 public final Settings setProperty(String key, Double value) {
189 if (!clearIfNullValue(key, value)) {
190 properties.put(key, String.valueOf(value));
191 }
192 return this;
193 }
194
195 public final Settings setProperty(String key, Date date) {
196 return setProperty(key, date, false);
197 }
198
199 public final Settings addProperties(Map<String, String> props) {
200 properties.putAll(props);
201 return this;
202 }
203
204 public final Settings addProperties(Properties props) {
205 for (Map.Entry<Object, Object> entry : props.entrySet()) {
206 properties.put(entry.getKey().toString(), entry.getValue().toString());
207 }
208 return this;
209 }
210
211 public final Settings addSystemProperties() {
212 return addProperties(System.getProperties());
213 }
214
215 public final Settings addEnvironmentVariables() {
216 return addProperties(System.getenv());
217 }
218
219 public final Settings setProperties(Map<String, String> props) {
220 properties = Maps.newHashMap(props);
221 return this;
222 }
223
224 public final Settings setProperty(String key, Date date, boolean includeTime) {
225 if (!clearIfNullValue(key, date)) {
226 properties.put(key, includeTime ? DateUtils.formatDateTime(date) : DateUtils.formatDate(date));
227 }
228 return this;
229 }
230
231 public final Settings removeProperty(String key) {
232 properties.remove(key);
233 return this;
234 }
235
236 public final Settings clear() {
237 properties.clear();
238 return this;
239 }
240
241 /**
242 * @return unmodifiable properties
243 */
244 public final Map<String, String> getProperties() {
245 return Collections.unmodifiableMap(properties);
246 }
247
248 public final PropertyDefinitions getDefinitions() {
249 return definitions;
250 }
251
252 private boolean clearIfNullValue(String key, Object value) {
253 if (value == null) {
254 properties.remove(key);
255 return true;
256 }
257 return false;
258 }
259
260 /**
261 * Create empty settings. Definition of available properties is loaded from the given annotated class.
262 * This method is usually used by unit tests.
263 */
264 public static Settings createForComponent(Object component) {
265 return new Settings(new PropertyDefinitions(component));
266 }
267 }