KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > base > util > collections > FlexibleProperties


1 /*
2  * $Id: FlexibleProperties.java 5720 2005-09-13 03:10:59Z jonesde $
3  *
4  * Copyright (c) 2001 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */

24 package org.ofbiz.base.util.collections;
25
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.io.Serializable JavaDoc;
29 import java.net.URL JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.Enumeration JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.Properties JavaDoc;
34 import java.util.Set JavaDoc;
35
36 import org.ofbiz.base.util.Debug;
37
38 /**
39  * Simple Class for flexibly working with properties files
40  *
41  * @author <a HREF="mailto:jonesde@ofbiz.org">David E. Jones</a>
42  * @version $Revision
43  * @since 1.0
44  */

45 public class FlexibleProperties extends Properties JavaDoc implements Serializable JavaDoc {
46
47     public static final String JavaDoc module = FlexibleProperties.class.getName();
48     
49     private static final boolean truncateIfMissingDefault = false;
50     private static final boolean doPropertyExpansionDefault = true;
51
52     private URL JavaDoc url = null;
53     private boolean doPropertyExpansion = doPropertyExpansionDefault;
54     private boolean truncateIfMissing = truncateIfMissingDefault;
55
56     // constructors
57
public FlexibleProperties() {
58         super();
59     }
60
61     public FlexibleProperties(Properties JavaDoc properties) {
62         super(properties);
63     }
64
65     public FlexibleProperties(URL JavaDoc url) {
66         this.url = url;
67         init();
68     }
69
70     public FlexibleProperties(URL JavaDoc url, Properties JavaDoc properties) {
71         super(properties);
72         this.url = url;
73         init();
74     }
75
76     // factories
77
public static FlexibleProperties makeFlexibleProperties(Properties JavaDoc properties) {
78         return new FlexibleProperties(properties);
79     }
80
81     public static FlexibleProperties makeFlexibleProperties(URL JavaDoc url) {
82         return new FlexibleProperties(url);
83     }
84
85     public static FlexibleProperties makeFlexibleProperties(URL JavaDoc url, Properties JavaDoc properties) {
86         return new FlexibleProperties(url, properties);
87     }
88
89     public static FlexibleProperties makeFlexibleProperties(String JavaDoc[] keysAndValues) {
90         // if they gave me an odd number of elements
91
if ((keysAndValues.length % 2) != 0) {
92             throw new IllegalArgumentException JavaDoc("FlexibleProperties(String[] keysAndValues) cannot accept an odd number of elements!");
93         }
94         Properties JavaDoc newProperties = new Properties JavaDoc();
95
96         for (int i = 0; i < keysAndValues.length; i += 2) {
97             newProperties.setProperty(keysAndValues[i], keysAndValues[i + 1]);
98         }
99
100         return new FlexibleProperties(newProperties);
101     }
102
103     private void init() {
104         try {
105             load();
106         } catch (IOException JavaDoc e) {
107             Debug.log(e, module);
108         }
109     }
110
111     public boolean getDoPropertyExpansion() {
112         return doPropertyExpansion;
113     }
114
115     public void setDoPropertyExpansion(boolean doPropertyExpansion) {
116         this.doPropertyExpansion = doPropertyExpansion;
117     }
118
119     public boolean getTruncateIfMissing() {
120         return truncateIfMissing;
121     }
122
123     public void setTruncateIfMissing(boolean truncateIfMissing) {
124         this.truncateIfMissing = truncateIfMissing;
125     }
126
127     public URL JavaDoc getURL() {
128         return url;
129     }
130
131     public void setURL(URL JavaDoc url) {
132         this.url = url;
133         init();
134     }
135
136     public Properties JavaDoc getDefaultProperties() {
137         return this.defaults;
138     }
139
140     public void setDefaultProperties(Properties JavaDoc defaults) {
141         this.defaults = new FlexibleProperties(defaults);
142     }
143
144     protected synchronized void load() throws IOException JavaDoc {
145         if (url == null) return;
146         InputStream JavaDoc in = null;
147
148         try {
149             in = url.openStream();
150         } catch (Exception JavaDoc urlex) {
151             Debug.log(urlex, "[FlexibleProperties.load]: Couldn't find the URL: " + url, module);
152         }
153
154         if (in == null) throw new IOException JavaDoc("Could not open resource URL " + url);
155
156         super.load(in);
157         in.close();
158
159         if (defaults instanceof FlexibleProperties) ((FlexibleProperties) defaults).reload();
160         if (getDoPropertyExpansion()) interpolateProperties();
161     }
162
163     public synchronized void store(String JavaDoc header) throws IOException JavaDoc {
164         super.store(url.openConnection().getOutputStream(), header);
165     }
166
167     public synchronized void reload() throws IOException JavaDoc {
168         Debug.log("Reloading the resource: " + url, module);
169         this.load();
170     }
171
172     // ==== Property interpolation methods ====
173
public void interpolateProperties() {
174         if ((defaults != null) && (defaults instanceof FlexibleProperties)) {
175             ((FlexibleProperties) defaults).interpolateProperties();
176         }
177         interpolateProperties(this, getTruncateIfMissing());
178     }
179
180     public static void interpolateProperties(Properties JavaDoc props) {
181         interpolateProperties(props, truncateIfMissingDefault);
182     }
183
184     public static void interpolateProperties(Properties JavaDoc props, boolean truncateIfMissing) {
185         Enumeration JavaDoc keys = props.keys();
186
187         while (keys.hasMoreElements()) {
188             String JavaDoc key = keys.nextElement().toString();
189             String JavaDoc value = props.getProperty(key);
190
191             key = interpolate(key, props, truncateIfMissing);
192             props.setProperty(key, interpolate(value, props, truncateIfMissing));
193         }
194     }
195
196     public static String JavaDoc interpolate(String JavaDoc value, Properties JavaDoc props) {
197         return interpolate(value, props, truncateIfMissingDefault);
198     }
199
200     public static String JavaDoc interpolate(String JavaDoc value, Properties JavaDoc props, boolean truncateIfMissing) {
201         return interpolate(value, props, truncateIfMissing, null);
202     }
203
204     public static String JavaDoc interpolate(String JavaDoc value, Properties JavaDoc props, boolean truncateIfMissing, ArrayList JavaDoc beenThere) {
205         if (props == null || value == null) return value;
206         if (beenThere == null) {
207             beenThere = new ArrayList JavaDoc();
208             // Debug.log("[FlexibleProperties.interpolate] starting interpolate: value=[" + value + "]");
209
} else {// Debug.log("[FlexibleProperties.interpolate] starting sub-interpolate: beenThere=[" + beenThere + "], value=[" + value + "]");
210
}
211         int start = value.indexOf("${");
212
213         while (start > -1) {
214             int end = value.indexOf("}", (start + 2));
215
216             if (end > start + 2) {
217                 String JavaDoc keyToExpand = value.substring((start + 2), end);
218                 int nestedStart = keyToExpand.indexOf("${");
219
220                 while (nestedStart > -1) {
221                     end = value.indexOf("}", (end + 1));
222                     if (end > -1) {
223                         keyToExpand = value.substring((start + 2), end);
224                         nestedStart = keyToExpand.indexOf("${", (nestedStart + 2));
225                     } else {
226                         Debug.log("[FlexibleProperties.interpolate] Malformed value: [" + value + "] " + "contained unbalanced start \"${\" and end \"}\" characters", module);
227                         return value;
228                     }
229                 }
230                 // if this key needs to be interpolated itself
231
if (keyToExpand.indexOf("${") > -1) {
232                     // Debug.log("[FlexibleProperties.interpolate] recursing on key: keyToExpand=[" + keyToExpand + "]");
233

234                     // save current beenThere and restore after so the later interpolates don't get messed up
235
ArrayList JavaDoc tempBeenThere = new ArrayList JavaDoc(beenThere);
236
237                     beenThere.add(keyToExpand);
238                     keyToExpand = interpolate(keyToExpand, props, truncateIfMissing, beenThere);
239                     beenThere = tempBeenThere;
240                 }
241                 if (beenThere.contains(keyToExpand)) {
242                     beenThere.add(keyToExpand);
243                     Debug.log("[FlexibleProperties.interpolate] Recursion loop detected: Property:[" + beenThere.get(0) + "] " + "included property: [" + keyToExpand + "]", module);
244                     Debug.log("[FlexibleProperties.interpolate] Recursion loop path:" + beenThere, module);
245                     return value;
246                 } else {
247                     String JavaDoc expandValue = null;
248
249                     if (keyToExpand.startsWith("env.")) {
250                         String JavaDoc envValue = System.getProperty(keyToExpand.substring(4));
251
252                         if (envValue == null) {
253                             Debug.log("[FlexibleProperties.interpolate] ERROR: Could not find environment variable named: " + keyToExpand.substring(4), module);
254                         } else {
255                             expandValue = envValue;
256                             // Debug.log("[FlexibleProperties.interpolate] Got expandValue from environment: " + expandValue);
257
}
258                     } else {
259                         expandValue = props.getProperty(keyToExpand);
260                         // Debug.log("[FlexibleProperties.interpolate] Got expandValue from another property: " + expandValue);
261
}
262
263                     if (expandValue != null) {
264                         // Key found - interpolate
265

266                         // if this value needs to be interpolated itself
267
if (expandValue.indexOf("${") > -1) {
268                             // Debug.log("[FlexibleProperties] recursing on value: expandValue=[" + expandValue + "]");
269
// save current beenThere and restore after so the later interpolates don't get messed up
270
ArrayList JavaDoc tempBeenThere = new ArrayList JavaDoc(beenThere);
271
272                             beenThere.add(keyToExpand);
273                             expandValue = interpolate(expandValue, props, truncateIfMissing, beenThere);
274                             beenThere = tempBeenThere;
275                         }
276                         value = value.substring(0, start) + expandValue + value.substring(end + 1);
277                         end = start + expandValue.length();
278
279                     } else {
280                         // Key not found - (expandValue == null)
281
if (truncateIfMissing == true) {
282                             value = value.substring(0, start) + value.substring(end + 1);
283                         }
284                     }
285                 }
286             } else {
287                 Debug.log("[FlexibleProperties.interpolate] Value [" + value + "] starts but does end variable", module);
288                 return value;
289             }
290             start = value.indexOf("${", end);
291         }
292         return value;
293     }
294
295     // ==== Utility/override methods ====
296
public Object JavaDoc clone() {
297         FlexibleProperties c = (FlexibleProperties) super.clone();
298
299         // avoid recursion for some reason someone used themselves as defaults
300
if (defaults != null && !this.equals(defaults)) {
301             c.defaults = (FlexibleProperties) getDefaultProperties().clone();
302         }
303         return c;
304     }
305
306     public String JavaDoc toString() {
307         StringBuffer JavaDoc retVal = new StringBuffer JavaDoc();
308         Set JavaDoc keySet = keySet();
309         Iterator JavaDoc keys = keySet.iterator();
310
311         while (keys.hasNext()) {
312             String JavaDoc key = keys.next().toString();
313             String JavaDoc value = getProperty(key);
314
315             retVal.append(key);
316             retVal.append("=");
317             retVal.append(value);
318             retVal.append("\n");
319         }
320
321         return retVal.toString();
322     }
323 }
324
Popular Tags