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      public final String[] getStringArray(String key) {
110        return getStringArrayBySeparator(key, ",");
111      }
112    
113      public final String[] getStringArrayBySeparator(String key, String separator) {
114        String value = getString(key);
115        if (value != null) {
116          return StringUtils.splitByWholeSeparator(value, separator);
117        }
118        return ArrayUtils.EMPTY_STRING_ARRAY;
119      }
120    
121      public List<String> getKeysStartingWith(String prefix) {
122        List<String> result = Lists.newArrayList();
123        for (String key : properties.keySet()) {
124          if (StringUtils.startsWith(key, prefix)) {
125            result.add(key);
126          }
127        }
128        return result;
129      }
130    
131    
132    
133      public final Settings appendProperty(String key, String value) {
134        String newValue = properties.get(key);
135        if (StringUtils.isEmpty(newValue)) {
136          newValue = value;
137        } else {
138          newValue += "," + value;
139        }
140        properties.put(key, newValue);
141        return this;
142      }
143    
144      public final Settings setProperty(String key, String value) {
145        if (!clearIfNullValue(key, value)) {
146          properties.put(key, value);
147        }
148        return this;
149      }
150    
151      public final Settings setProperty(String key, Boolean value) {
152        if (!clearIfNullValue(key, value)) {
153          properties.put(key, String.valueOf(value));
154        }
155        return this;
156      }
157    
158      public final Settings setProperty(String key, Integer value) {
159        if (!clearIfNullValue(key, value)) {
160          properties.put(key, String.valueOf(value));
161        }
162        return this;
163      }
164    
165      public final Settings setProperty(String key, Long value) {
166        if (!clearIfNullValue(key, value)) {
167          properties.put(key, String.valueOf(value));
168        }
169        return this;
170      }
171    
172      public final Settings setProperty(String key, Double value) {
173        if (!clearIfNullValue(key, value)) {
174          properties.put(key, String.valueOf(value));
175        }
176        return this;
177      }
178    
179      public final Settings setProperty(String key, Date date) {
180        return setProperty(key, date, false);
181      }
182    
183      public final Settings addProperties(Map<String, String> props) {
184        properties.putAll(props);
185        return this;
186      }
187    
188      public final Settings addProperties(Properties props) {
189        for (Map.Entry<Object, Object> entry : props.entrySet()) {
190          properties.put(entry.getKey().toString(), entry.getValue().toString());
191        }
192        return this;
193      }
194    
195      public final Settings addSystemProperties() {
196        return addProperties(System.getProperties());
197      }
198    
199      public final Settings addEnvironmentVariables() {
200        return addProperties(System.getenv());
201      }
202    
203      public final Settings setProperties(Map<String, String> props) {
204        properties = Maps.newHashMap(props);
205        return this;
206      }
207    
208      public final Settings setProperty(String key, Date date, boolean includeTime) {
209        if (!clearIfNullValue(key, date)) {
210          properties.put(key, includeTime ? DateUtils.formatDateTime(date) : DateUtils.formatDate(date));
211        }
212        return this;
213      }
214    
215      public final Settings removeProperty(String key) {
216        properties.remove(key);
217        return this;
218      }
219    
220      public final Settings clear() {
221        properties.clear();
222        return this;
223      }
224    
225      /**
226       * @return unmodifiable properties
227       */
228      public final Map<String, String> getProperties() {
229        return Collections.unmodifiableMap(properties);
230      }
231    
232      public final PropertyDefinitions getDefinitions() {
233        return definitions;
234      }
235    
236      private boolean clearIfNullValue(String key, Object value) {
237        if (value == null) {
238          properties.remove(key);
239          return true;
240        }
241        return false;
242      }
243    
244      /**
245       * Create empty settings. Definition of available properties is loaded from the given annotated class.
246       * This method is usually used by unit tests.
247       */
248      public static Settings createForComponent(Object component) {
249        return new Settings(new PropertyDefinitions(component));
250      }
251    }