~ubuntu-branches/ubuntu/saucy/commons-configuration/saucy

« back to all changes in this revision

Viewing changes to src/java/org/apache/commons/configuration/interpol/ConfigurationInterpolator.java

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg
  • Date: 2013-07-01 16:29:44 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20130701162944-98waq5gogha5gpn1
Tags: 1.9-1
* New upstream release
* debian/control:
  - Updated Standards-Version to 3.9.4 (no changes)
  - Use canonical URLs for the Vcs-* fields
  - Added new build dependencies (libjavacc-maven-plugin-java, junit4)
  - Upgraded the dependency on the Servlet API (2.5 -> 3.0)
  - Removed the dependency on the Activation Framework (glassfish-activation)
  - Replaced the dependency on glassfish-mail with libgnumail-java
  - Removed the unused dependencies:
    liblog4j1.2-java-doc, libmaven-assembly-plugin-java
  - Replaced the dependency on libcommons-jexl-java by libcommons-jexl2-java
* debian/watch: Changed to point the official Apache distribution server
* Removed the obsolete file debian/ant.properties
* Installed the upstream changelog in the binary packages
* Added the report plugins to maven.ignoreRules
* Added the classpath attribute to the jar manifest

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 
 * contributor license agreements.  See the NOTICE file distributed with
4
 
 * this work for additional information regarding copyright ownership.
5
 
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 
 * (the "License"); you may not use this file except in compliance with
7
 
 * the License.  You may obtain a copy of the License at
8
 
 *
9
 
 *     http://www.apache.org/licenses/LICENSE-2.0
10
 
 *
11
 
 * Unless required by applicable law or agreed to in writing, software
12
 
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 
 * See the License for the specific language governing permissions and
15
 
 * limitations under the License.
16
 
 */
17
 
package org.apache.commons.configuration.interpol;
18
 
 
19
 
import java.util.HashMap;
20
 
import java.util.Map;
21
 
import java.util.Set;
22
 
 
23
 
import org.apache.commons.lang.text.StrLookup;
24
 
 
25
 
/**
26
 
 * <p>
27
 
 * A class that handles interpolation (variable substitution) for configuration
28
 
 * objects.
29
 
 * </p>
30
 
 * <p>
31
 
 * Each instance of <code>AbstractConfiguration</code> is associated with an
32
 
 * object of this class. All interpolation tasks are delegated to this object.
33
 
 * </p>
34
 
 * <p>
35
 
 * <code>ConfigurationInterpolator</code> works together with the
36
 
 * <code>StrSubstitutor</code> class from <a
37
 
 * href="http://commons.apache.org/lang">Commons Lang</a>. By extending
38
 
 * <code>StrLookup</code> it is able to provide values for variables that
39
 
 * appear in expressions.
40
 
 * </p>
41
 
 * <p>
42
 
 * The basic idea of this class is that it can maintain a set of primitive
43
 
 * <code>StrLookup</code> objects, each of which is identified by a special
44
 
 * prefix. The variables to be processed have the form
45
 
 * <code>${prefix:name}</code>. <code>ConfigurationInterpolator</code> will
46
 
 * extract the prefix and determine, which primitive lookup object is registered
47
 
 * for it. Then the name of the variable is passed to this object to obtain the
48
 
 * actual value. It is also possible to define a default lookup object, which
49
 
 * will be used for variables that do not have a prefix or that cannot be
50
 
 * resolved by their associated lookup object.
51
 
 * </p>
52
 
 * <p>
53
 
 * When a new instance of this class is created it is initialized with a default
54
 
 * set of primitive lookup objects. This set can be customized using the static
55
 
 * methods <code>registerGlobalLookup()</code> and
56
 
 * <code>deregisterGlobalLookup()</code>. Per default it contains the
57
 
 * following standard lookup objects:
58
 
 * </p>
59
 
 * <p>
60
 
 * <table border="1">
61
 
 * <tr>
62
 
 * <th>Prefix</th>
63
 
 * <th>Lookup object</th>
64
 
 * </tr>
65
 
 * <tr>
66
 
 * <td valign="top">sys</td>
67
 
 * <td>With this prefix a lookup object is associated that is able to resolve
68
 
 * system properties.</td>
69
 
 * </tr>
70
 
 * <tr>
71
 
 * <td valign="top">const</td>
72
 
 * <td>The <code>const</code> prefix indicates that a variable is to be
73
 
 * interpreted as a constant member field of a class (i.e. a field with the
74
 
 * <b>static final</b> modifiers). The name of the variable must be of the form
75
 
 * <code>&lt;full qualified class name&gt;.&lt;field name&gt;</code>, e.g.
76
 
 * <code>org.apache.commons.configuration.interpol.ConfigurationInterpolator.PREFIX_CONSTANTS
77
 
 * </code>.</td>
78
 
 * </tr>
79
 
 * </table>
80
 
 * </p>
81
 
 * <p>
82
 
 * After an instance has been created the current set of lookup objects can be
83
 
 * modified using the <code>registerLookup()</code> and
84
 
 * <code>deregisterLookup()</code> methods. The default lookup object (that is
85
 
 * invoked for variables without a prefix) can be set with the
86
 
 * <code>setDefaultLookup()</code> method. (If a
87
 
 * <code>ConfigurationInterpolator</code> instance is created by a
88
 
 * configuration object, this lookup points to the configuration itself, so that
89
 
 * variables are resolved using the configuration's properties. This ensures
90
 
 * backward compatibility to earlier version of Commons Configuration.)
91
 
 * </p>
92
 
 * <p>
93
 
 * Implementation node: Instances of this class are not thread-safe related to
94
 
 * modifications of their current set of registered lookup objects. It is
95
 
 * intended that each instance is associated with a single
96
 
 * <code>Configuration</code> object and used for its interpolation tasks.
97
 
 * </p>
98
 
 *
99
 
 * @version $Id: ConfigurationInterpolator.java 833923 2009-11-08 20:53:52Z oheger $
100
 
 * @since 1.4
101
 
 * @author <a
102
 
 * href="http://commons.apache.org/configuration/team-list.html">Commons
103
 
 * Configuration team</a>
104
 
 */
105
 
public class ConfigurationInterpolator extends StrLookup
106
 
{
107
 
    /**
108
 
     * Constant for the prefix of the standard lookup object for resolving
109
 
     * system properties.
110
 
     */
111
 
    public static final String PREFIX_SYSPROPERTIES = "sys";
112
 
 
113
 
    /**
114
 
     * Constant for the prefix of the standard lookup object for resolving
115
 
     * constant values.
116
 
     */
117
 
    public static final String PREFIX_CONSTANTS = "const";
118
 
 
119
 
    /**
120
 
     * Constant for the prefix of the standard lookup object for resolving
121
 
     * environment properties.
122
 
     * @since 1.7
123
 
     */
124
 
    public static final String PREFIX_ENVIRONMENT = "env";
125
 
 
126
 
    /** Constant for the prefix separator. */
127
 
    private static final char PREFIX_SEPARATOR = ':';
128
 
 
129
 
    /** A map with the globally registered lookup objects. */
130
 
    private static Map globalLookups;
131
 
 
132
 
    /** A map with the locally registered lookup objects. */
133
 
    private Map localLookups;
134
 
 
135
 
    /** Stores the default lookup object. */
136
 
    private StrLookup defaultLookup;
137
 
 
138
 
    /** Stores a parent interpolator objects if the interpolator is nested hierarchically. */
139
 
    private ConfigurationInterpolator parentInterpolator;
140
 
 
141
 
    /**
142
 
     * Creates a new instance of <code>ConfigurationInterpolator</code>.
143
 
     */
144
 
    public ConfigurationInterpolator()
145
 
    {
146
 
        synchronized (globalLookups)
147
 
        {
148
 
            localLookups = new HashMap(globalLookups);
149
 
        }
150
 
    }
151
 
 
152
 
    /**
153
 
     * Registers the given lookup object for the specified prefix globally. This
154
 
     * means that all instances that are created later will use this lookup
155
 
     * object for this prefix. If for this prefix a lookup object is already
156
 
     * registered, the new lookup object will replace the old one. Note that the
157
 
     * lookup objects registered here will be shared between multiple clients.
158
 
     * So they should be thread-safe.
159
 
     *
160
 
     * @param prefix the variable prefix (must not be <b>null</b>)
161
 
     * @param lookup the lookup object to be used for this prefix (must not be
162
 
     * <b>null</b>)
163
 
     */
164
 
    public static void registerGlobalLookup(String prefix, StrLookup lookup)
165
 
    {
166
 
        if (prefix == null)
167
 
        {
168
 
            throw new IllegalArgumentException(
169
 
                    "Prefix for lookup object must not be null!");
170
 
        }
171
 
        if (lookup == null)
172
 
        {
173
 
            throw new IllegalArgumentException(
174
 
                    "Lookup object must not be null!");
175
 
        }
176
 
        synchronized (globalLookups)
177
 
        {
178
 
            globalLookups.put(prefix, lookup);
179
 
        }
180
 
    }
181
 
 
182
 
    /**
183
 
     * Deregisters the global lookup object for the specified prefix. This means
184
 
     * that this lookup object won't be available for later created instances
185
 
     * any more. For already existing instances this operation does not have any
186
 
     * impact.
187
 
     *
188
 
     * @param prefix the variable prefix
189
 
     * @return a flag whether for this prefix a lookup object had been
190
 
     * registered
191
 
     */
192
 
    public static boolean deregisterGlobalLookup(String prefix)
193
 
    {
194
 
        synchronized (globalLookups)
195
 
        {
196
 
            return globalLookups.remove(prefix) != null;
197
 
        }
198
 
    }
199
 
 
200
 
    /**
201
 
     * Registers the given lookup object for the specified prefix at this
202
 
     * instance. From now on this lookup object will be used for variables that
203
 
     * have the specified prefix.
204
 
     *
205
 
     * @param prefix the variable prefix (must not be <b>null</b>)
206
 
     * @param lookup the lookup object to be used for this prefix (must not be
207
 
     * <b>null</b>)
208
 
     */
209
 
    public void registerLookup(String prefix, StrLookup lookup)
210
 
    {
211
 
        if (prefix == null)
212
 
        {
213
 
            throw new IllegalArgumentException(
214
 
                    "Prefix for lookup object must not be null!");
215
 
        }
216
 
        if (lookup == null)
217
 
        {
218
 
            throw new IllegalArgumentException(
219
 
                    "Lookup object must not be null!");
220
 
        }
221
 
        localLookups.put(prefix, lookup);
222
 
    }
223
 
 
224
 
    /**
225
 
     * Deregisters the lookup object for the specified prefix at this instance.
226
 
     * It will be removed from this instance.
227
 
     *
228
 
     * @param prefix the variable prefix
229
 
     * @return a flag whether for this prefix a lookup object had been
230
 
     * registered
231
 
     */
232
 
    public boolean deregisterLookup(String prefix)
233
 
    {
234
 
        return localLookups.remove(prefix) != null;
235
 
    }
236
 
 
237
 
    /**
238
 
     * Returns a set with the prefixes, for which lookup objects are registered
239
 
     * at this instance. This means that variables with these prefixes can be
240
 
     * processed.
241
 
     *
242
 
     * @return a set with the registered variable prefixes
243
 
     */
244
 
    public Set prefixSet()
245
 
    {
246
 
        return localLookups.keySet();
247
 
    }
248
 
 
249
 
    /**
250
 
     * Returns the default lookup object.
251
 
     *
252
 
     * @return the default lookup object
253
 
     */
254
 
    public StrLookup getDefaultLookup()
255
 
    {
256
 
        return defaultLookup;
257
 
    }
258
 
 
259
 
    /**
260
 
     * Sets the default lookup object. This lookup object will be used for all
261
 
     * variables without a special prefix. If it is set to <b>null</b>, such
262
 
     * variables won't be processed.
263
 
     *
264
 
     * @param defaultLookup the new default lookup object
265
 
     */
266
 
    public void setDefaultLookup(StrLookup defaultLookup)
267
 
    {
268
 
        this.defaultLookup = defaultLookup;
269
 
    }
270
 
 
271
 
    /**
272
 
     * Resolves the specified variable. This implementation will try to extract
273
 
     * a variable prefix from the given variable name (the first colon (':') is
274
 
     * used as prefix separator). It then passes the name of the variable with
275
 
     * the prefix stripped to the lookup object registered for this prefix. If
276
 
     * no prefix can be found or if the associated lookup object cannot resolve
277
 
     * this variable, the default lookup object will be used.
278
 
     *
279
 
     * @param var the name of the variable whose value is to be looked up
280
 
     * @return the value of this variable or <b>null</b> if it cannot be
281
 
     * resolved
282
 
     */
283
 
    public String lookup(String var)
284
 
    {
285
 
        if (var == null)
286
 
        {
287
 
            return null;
288
 
        }
289
 
 
290
 
        int prefixPos = var.indexOf(PREFIX_SEPARATOR);
291
 
        if (prefixPos >= 0)
292
 
        {
293
 
            String prefix = var.substring(0, prefixPos);
294
 
            String name = var.substring(prefixPos + 1);
295
 
            String value = fetchLookupForPrefix(prefix).lookup(name);
296
 
            if (value == null && getParentInterpolator() != null)
297
 
            {
298
 
                value = getParentInterpolator().fetchLookupForPrefix(prefix).lookup(name);
299
 
            }
300
 
            if (value != null)
301
 
            {
302
 
                return value;
303
 
            }
304
 
        }
305
 
        String value = fetchNoPrefixLookup().lookup(var);
306
 
        if (value == null && getParentInterpolator() != null)
307
 
        {
308
 
            value = getParentInterpolator().fetchNoPrefixLookup().lookup(var);
309
 
        }
310
 
        return value;
311
 
    }
312
 
 
313
 
    /**
314
 
     * Returns the lookup object to be used for variables without a prefix. This
315
 
     * implementation will check whether a default lookup object was set. If
316
 
     * this is the case, it will be returned. Otherwise a <b>null</b> lookup
317
 
     * object will be returned (never <code>null</code>).
318
 
     *
319
 
     * @return the lookup object to be used for variables without a prefix
320
 
     */
321
 
    protected StrLookup fetchNoPrefixLookup()
322
 
    {
323
 
        return (getDefaultLookup() != null) ? getDefaultLookup() : StrLookup.noneLookup();
324
 
    }
325
 
 
326
 
    /**
327
 
     * Obtains the lookup object for the specified prefix. This method is called
328
 
     * by the <code>lookup()</code> method. This implementation will check
329
 
     * whether a lookup object is registered for the given prefix. If not, a
330
 
     * <b>null</b> lookup object will be returned (never <code>null</code>).
331
 
     *
332
 
     * @param prefix the prefix
333
 
     * @return the lookup object to be used for this prefix
334
 
     */
335
 
    protected StrLookup fetchLookupForPrefix(String prefix)
336
 
    {
337
 
        StrLookup lookup = (StrLookup) localLookups.get(prefix);
338
 
        if (lookup == null)
339
 
        {
340
 
            lookup = StrLookup.noneLookup();
341
 
        }
342
 
        return lookup;
343
 
    }
344
 
 
345
 
    /**
346
 
     * Registers the local lookup instances for the given interpolator.
347
 
     *
348
 
     * @param interpolator the instance receiving the local lookups
349
 
     * @since upcoming
350
 
     */
351
 
    public void registerLocalLookups(ConfigurationInterpolator interpolator)
352
 
    {
353
 
        interpolator.localLookups.putAll(localLookups);
354
 
    }
355
 
 
356
 
    /**
357
 
     * Sets the parent interpolator. This object is used if the interpolation is nested
358
 
     * hierarchically and the current interpolation object cannot resolve a variable.
359
 
     *
360
 
     * @param parentInterpolator the parent interpolator object or <code>null</code>
361
 
     * @since upcoming
362
 
     */
363
 
    public void setParentInterpolator(ConfigurationInterpolator parentInterpolator)
364
 
    {
365
 
        this.parentInterpolator = parentInterpolator;
366
 
    }
367
 
 
368
 
    /**
369
 
     * Requests the parent interpolator. This object is used if the interpolation is nested
370
 
     * hierarchically and the current interpolation
371
 
     *
372
 
     * @return the parent interpolator or <code>null</code>
373
 
     * @since upcoming
374
 
     */
375
 
    public ConfigurationInterpolator getParentInterpolator()
376
 
    {
377
 
        return this.parentInterpolator;
378
 
    }
379
 
 
380
 
    // static initializer, sets up the map with the standard lookups
381
 
    static
382
 
    {
383
 
        globalLookups = new HashMap();
384
 
        globalLookups.put(PREFIX_SYSPROPERTIES, StrLookup.systemPropertiesLookup());
385
 
        globalLookups.put(PREFIX_CONSTANTS, new ConstantLookup());
386
 
        globalLookups.put(PREFIX_ENVIRONMENT, new EnvironmentLookup());
387
 
    }
388
 
}