View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe 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   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package org.mycore.common.config;
20  
21  import java.io.IOException;
22  import java.io.OutputStream;
23  import java.io.Writer;
24  import java.nio.charset.Charset;
25  import java.util.Collections;
26  import java.util.Enumeration;
27  import java.util.Map;
28  import java.util.Properties;
29  import java.util.Set;
30  import java.util.TreeSet;
31  
32  import org.apache.logging.log4j.LogManager;
33  
34  /**
35   * Like {@link Properties} but with in-place replacement of properties that want to append a value.
36   * 
37   * Properties for System.getProperties() have always precedence for Properties defined here.
38   * 
39   * <pre>
40   * key=value1
41   * key=%key%,value2
42   * </pre>
43   * 
44   * will be resolved to
45   * 
46   * <pre>
47   * key=value1,value2
48   * </pre>
49   * 
50   * @author Thomas Scheffler (yagee)
51   * @since 2013.12
52   */
53  public class MCRProperties extends Properties {
54  
55      private static final long serialVersionUID = 8801587133852810123L;
56  
57      @Override
58      public synchronized Object put(Object key, Object value) {
59          return putString((String) key, (String) value);
60      }
61  
62      private Object putString(String key, String value) {
63          String systemProperty = System.getProperties().getProperty(key);
64          if (systemProperty != null && !systemProperty.equals(value)) {
65              LogManager.getLogger(getClass()).error("Cannot overwrite system property: {}={}", key, value);
66              return systemProperty;
67          }
68          String oldValue = (String) super.get(key);
69          String newValue = oldValue == null ? value : value.replaceAll('%' + key + '%', oldValue);
70          if (!newValue.equals(value) && newValue.startsWith(",")) {
71              //replacement took place, but starts with 'empty' value
72              newValue = newValue.substring(1);
73          }
74          return super.put(key, newValue);
75      }
76  
77      @Override
78      public synchronized Object get(Object key) {
79          String systemProperty = System.getProperties().getProperty((String) key);
80          return systemProperty != null ? systemProperty : super.get(key);
81      }
82  
83      Map<String, String> getAsMap() {
84          @SuppressWarnings("rawtypes")
85          Map compileFix = this;
86          @SuppressWarnings("unchecked")
87          Map<String, String> returns = compileFix;
88          return returns;
89      }
90  
91      /**
92       * Creates a new <code>MCRProperties</code> instance with the values
93       * of the given properties.
94       */
95      public static MCRProperties copy(Properties properties) {
96          MCRProperties p = new MCRProperties();
97          for (Map.Entry<Object, Object> entry : properties.entrySet()) {
98              p.put(entry.getKey(), entry.getValue());
99          }
100         return p;
101     }
102 
103     @Override
104     public void store(OutputStream out, String comments) throws IOException {
105         toSortedProperties().store(out, comments);
106     }
107 
108     @Override
109     public void store(Writer writer, String comments) throws IOException {
110         toSortedProperties().store(writer, comments);
111     }
112 
113     @Override
114     public void storeToXML(OutputStream os, String comment, Charset charset) throws IOException {
115         toSortedProperties().storeToXML(os, comment, charset);
116     }
117 
118     private Properties toSortedProperties() {
119         Properties sortedProps = new Properties() {
120             @Override
121             public Set<Map.Entry<Object, Object>> entrySet() {
122                 Set<Map.Entry<Object, Object>> sortedSet = new TreeSet<>(
123                     (o1, o2) -> o1.getKey().toString().compareTo(o2.getKey().toString()));
124                 sortedSet.addAll(super.entrySet());
125                 return sortedSet;
126             }
127 
128             @Override
129             public Set<Object> keySet() {
130                 return new TreeSet<Object>(super.keySet());
131             }
132 
133             @Override
134             public synchronized Enumeration<Object> keys() {
135                 return Collections.enumeration(new TreeSet<Object>(super.keySet()));
136             }
137 
138         };
139         sortedProps.putAll(this);
140         return sortedProps;
141     }
142 }