1
|
/**
|
2
|
* '$RCSfile: Config.java,v $'
|
3
|
*
|
4
|
* '$Author: barseghian $'
|
5
|
* '$Date: 2007/10/11 00:36:37 $'
|
6
|
* '$Revision: 1.22 $'
|
7
|
*
|
8
|
* For Details: http://kepler.ecoinformatics.org
|
9
|
*
|
10
|
* Copyright (c) 2003 The Regents of the University of California.
|
11
|
* All rights reserved.
|
12
|
*
|
13
|
* Permission is hereby granted, without written agreement and without
|
14
|
* license or royalty fees, to use, copy, modify, and distribute this
|
15
|
* software and its documentation for any purpose, provided that the
|
16
|
* above copyright notice and the following two paragraphs appear in
|
17
|
* all copies of this software.
|
18
|
*
|
19
|
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
|
20
|
* FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
21
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
22
|
* IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY
|
23
|
* OF SUCH DAMAGE.
|
24
|
*
|
25
|
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
|
26
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
27
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
|
28
|
* PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY
|
29
|
* OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
|
30
|
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
31
|
*/
|
32
|
|
33
|
package org.ecoinformatics.util;
|
34
|
|
35
|
import java.io.File;
|
36
|
import java.io.FileNotFoundException;
|
37
|
import java.io.InputStream;
|
38
|
import java.util.Collections;
|
39
|
import java.util.Hashtable;
|
40
|
import java.util.List;
|
41
|
import java.util.Map;
|
42
|
import java.util.Vector;
|
43
|
|
44
|
import javax.xml.transform.TransformerException;
|
45
|
|
46
|
import org.apache.commons.logging.Log;
|
47
|
import org.apache.commons.logging.LogFactory;
|
48
|
import org.apache.xpath.XPathAPI;
|
49
|
import org.w3c.dom.Node;
|
50
|
import org.w3c.dom.NodeList;
|
51
|
|
52
|
import edu.ucsb.nceas.configxml.ConfigXML;
|
53
|
import edu.ucsb.nceas.configxml.exception.ElementNotFoundException;
|
54
|
import edu.ucsb.nceas.configxml.exception.IndexTooLargeException;
|
55
|
import java.net.URL;
|
56
|
|
57
|
/**
|
58
|
*
|
59
|
* configuration file routines
|
60
|
*
|
61
|
*/
|
62
|
public class Config
|
63
|
{
|
64
|
//private static final String configfilename = "kepler/config.xml";
|
65
|
private static final String configfilename = "config.xml";
|
66
|
|
67
|
private static final String settingsdir = ".kepler";
|
68
|
|
69
|
// Define useful static strings. At some point in time, these could be moved
|
70
|
// into the config.xml file, environment variable, or something else
|
71
|
// which could move this directory to another location.
|
72
|
|
73
|
// KEPLER_USER_DIR is returned by Config.getUserDirPath().
|
74
|
private static final String KEPLER_USER_DIR = System.getProperty("user.home")
|
75
|
+ File.separator + settingsdir + File.separator;
|
76
|
|
77
|
// KEPLER_CACHE_DIR is returned by Config.getCacheDirPath().
|
78
|
private static final String KEPLER_CACHE_DIR = KEPLER_USER_DIR + "cache" + File.separator;
|
79
|
|
80
|
/**
|
81
|
* The singleton instance.
|
82
|
*/
|
83
|
private static Config configure ;
|
84
|
static {
|
85
|
configure = new Config();
|
86
|
}
|
87
|
|
88
|
private static Log log;
|
89
|
static {
|
90
|
log = LogFactory.getLog("org.ecoinformatics.util.Config");
|
91
|
}
|
92
|
|
93
|
// Instance variables.
|
94
|
|
95
|
/**
|
96
|
* The underlying ConfigXML object.
|
97
|
*/
|
98
|
private ConfigXML config;
|
99
|
|
100
|
/**
|
101
|
* Error indicator. Set to true if ConfigXML has problems.
|
102
|
*/
|
103
|
private boolean error = false;
|
104
|
|
105
|
/**
|
106
|
* Method for get object as a singleton class
|
107
|
* @return Config
|
108
|
*/
|
109
|
public static Config getInstance()
|
110
|
{
|
111
|
return configure;
|
112
|
}
|
113
|
|
114
|
/*
|
115
|
* Constructor for ConfigDatasource.
|
116
|
* @throws FileNotFoundException
|
117
|
* @throws Exception
|
118
|
*/
|
119
|
private Config()
|
120
|
{
|
121
|
try
|
122
|
{
|
123
|
InputStream is = this.getClass().getClassLoader().getResourceAsStream(configfilename);
|
124
|
if (is == null) {
|
125
|
throw new FileNotFoundException("Failed to find \""
|
126
|
+ configfilename + "\" as a resource");
|
127
|
}
|
128
|
URL configFileURL = this.getClass().getClassLoader().getSystemResource(configfilename);
|
129
|
File configFile = new File(configFileURL.toURI());
|
130
|
config = new ConfigXML( is, configFile.getAbsolutePath() );
|
131
|
|
132
|
//config = new ConfigXML(configfilename);
|
133
|
}
|
134
|
catch(FileNotFoundException fnfe)
|
135
|
{
|
136
|
error = true;
|
137
|
throw new RuntimeException("Config file not found at " + configfilename, fnfe );
|
138
|
}
|
139
|
catch(Exception e)
|
140
|
{
|
141
|
error = true;
|
142
|
throw new RuntimeException("Unspecified error creating config object: ", e );
|
143
|
}
|
144
|
}
|
145
|
|
146
|
/**
|
147
|
* Method to get a string value from config.xml base on given element path
|
148
|
* @param path String
|
149
|
* @return String
|
150
|
*/
|
151
|
public static String getValue(String path)
|
152
|
{
|
153
|
Config configInstance = Config.getInstance();
|
154
|
return configInstance.getValueFromPath(path);
|
155
|
}
|
156
|
|
157
|
private String getValueFromPath(String path)
|
158
|
{
|
159
|
String value = null;
|
160
|
if ( error ) {
|
161
|
return value;
|
162
|
}
|
163
|
if ( path == null ) {
|
164
|
return value;
|
165
|
}
|
166
|
try {
|
167
|
Vector valueVector = config.getValuesForPath(path);
|
168
|
value = (String) valueVector.elementAt(0);
|
169
|
}
|
170
|
catch ( ElementNotFoundException e1 ) {
|
171
|
log.debug("Element " + path + " not found");
|
172
|
}
|
173
|
catch ( Exception e2 ) {
|
174
|
log.error("Exception occurred:", e2 );
|
175
|
}
|
176
|
log.debug("The value for path " + path + " in config.xml is " + ((value==null) ? "null" : value) );
|
177
|
return value;
|
178
|
}//getValues
|
179
|
|
180
|
/**
|
181
|
* Method returns an unmodifiable list of values from config.xml base on given path.
|
182
|
* If the argument is null or not found in config.xml, return EMPTY_LIST.
|
183
|
*
|
184
|
* @param path String
|
185
|
* @return Vector
|
186
|
*/
|
187
|
public static List getList(String path)
|
188
|
{
|
189
|
Config configInstance = Config.getInstance();
|
190
|
return configInstance.getListFromPath(path);
|
191
|
}
|
192
|
|
193
|
private List getListFromPath(String path)
|
194
|
{
|
195
|
List value = Collections.EMPTY_LIST;
|
196
|
if ( error ) {
|
197
|
return value;
|
198
|
}
|
199
|
if ( path == null ) {
|
200
|
return value;
|
201
|
}
|
202
|
try {
|
203
|
value = Collections.unmodifiableList(config.getValuesForPath(path));
|
204
|
}
|
205
|
catch ( ElementNotFoundException e1 ) {
|
206
|
log.debug("Element " + path + " not found");
|
207
|
}
|
208
|
catch ( Exception e2 ) {
|
209
|
log.error("Exception occurred:", e2 );
|
210
|
}
|
211
|
|
212
|
return value;
|
213
|
}//getList
|
214
|
|
215
|
/**
|
216
|
* Method to get unmodifiable map for some given pathes in config.xml.
|
217
|
* If the arguments are invalid (either null) or not found, return an empty map.
|
218
|
* Here is the segment of config.xml:
|
219
|
* <parenetElement>
|
220
|
* <keyElement>key1</keyElement>
|
221
|
* <valueElement>value1</valueElement>
|
222
|
* </parentElement>
|
223
|
* <parentElement>
|
224
|
* <keyElement>key2</keyElement>
|
225
|
* <valueElement>value2</valueElement>
|
226
|
* </parentElement>
|
227
|
* The parentPath can be "//parentElement", keyPath should be "./keyElement",
|
228
|
* and valuePath should be "./valuePath".
|
229
|
* @param parentPath String
|
230
|
* @param keyPath String
|
231
|
* @param valuePath String
|
232
|
* @throws ElementNotFoundException
|
233
|
* @throws Exception
|
234
|
* @return Hashtable
|
235
|
*/
|
236
|
public static Map getMap(String parentPath, String keyPath, String valuePath)
|
237
|
{
|
238
|
Config configInstance = Config.getInstance();
|
239
|
return configInstance.getMapFromPath(parentPath, keyPath, valuePath);
|
240
|
}
|
241
|
|
242
|
private Map getMapFromPath(String parentPath, String keyPath, String valuePath)
|
243
|
{
|
244
|
Map map = Collections.EMPTY_MAP;
|
245
|
if ( error ) {
|
246
|
return map;
|
247
|
}
|
248
|
if ( parentPath == null || keyPath == null || valuePath == null ) {
|
249
|
return map;
|
250
|
}
|
251
|
NodeList nl = null;
|
252
|
try {
|
253
|
nl = config.getPathContent(parentPath);
|
254
|
}
|
255
|
catch ( ElementNotFoundException e1 ) {
|
256
|
log.debug("Element " + parentPath + " not found");
|
257
|
return map;
|
258
|
}
|
259
|
catch ( TransformerException e2 ) {
|
260
|
log.error("Transfomer Exception when reading parentPath " + parentPath, e2);
|
261
|
return map;
|
262
|
}
|
263
|
// At this point nl != null because we didn't get an ElementNotFoundException
|
264
|
map = new Hashtable();
|
265
|
try {
|
266
|
for (int i = 0; i < nl.getLength(); i++)
|
267
|
{
|
268
|
Node n = nl.item(i);
|
269
|
Node keyNode = XPathAPI.selectSingleNode(n, keyPath);
|
270
|
Node valueNode = XPathAPI.selectSingleNode(n, valuePath);
|
271
|
if (keyNode == null || valueNode == null)
|
272
|
{
|
273
|
log.debug("keyNode or valueNode not found at iteration " + i);
|
274
|
continue;
|
275
|
}
|
276
|
|
277
|
String keyNodeValue = keyNode.getFirstChild().getNodeValue();
|
278
|
String valueNodeValue = valueNode.getFirstChild().getNodeValue();
|
279
|
if (keyNodeValue == null || valueNodeValue == null)
|
280
|
{
|
281
|
log.debug("keyNodeValue or valueNodeValue is null at iteration " + i);
|
282
|
continue;
|
283
|
}
|
284
|
log.debug("The value of " + keyPath + " " + keyNodeValue + " and " +
|
285
|
" the value of " + valuePath + " " + valueNodeValue +
|
286
|
" are put into mapping");
|
287
|
|
288
|
map.put(keyNodeValue, valueNodeValue);
|
289
|
} //for
|
290
|
}
|
291
|
catch ( TransformerException e ) {
|
292
|
log.error("Transfomer Exception in loop ", e);
|
293
|
}
|
294
|
return Collections.unmodifiableMap(map);
|
295
|
}//getMap
|
296
|
|
297
|
/**
|
298
|
* Get a node list base on the given xpath in config file
|
299
|
* @param path String the xpath
|
300
|
* @return NodeList
|
301
|
*/
|
302
|
public static NodeList getNodeListFromPath(String path)
|
303
|
{
|
304
|
Config configInstance = Config.getInstance();
|
305
|
return configInstance.getNodeListFromXPath(path);
|
306
|
}
|
307
|
|
308
|
/*
|
309
|
* This method will get a node list from config file
|
310
|
*/
|
311
|
private NodeList getNodeListFromXPath(String xpath)
|
312
|
{
|
313
|
NodeList list = null;
|
314
|
if ( error ) {
|
315
|
return list;
|
316
|
}
|
317
|
try
|
318
|
{
|
319
|
list = config.getPathContent(xpath);
|
320
|
}
|
321
|
catch (ElementNotFoundException e)
|
322
|
{
|
323
|
log.debug("Element Not found for " + xpath );
|
324
|
}
|
325
|
catch ( TransformerException e2 ) {
|
326
|
log.error( "Transformer Exception for " + xpath );
|
327
|
}
|
328
|
return list;
|
329
|
}
|
330
|
|
331
|
/**
|
332
|
* Method to get error state
|
333
|
*/
|
334
|
public boolean getErrorState()
|
335
|
{
|
336
|
return error;
|
337
|
}
|
338
|
|
339
|
/**
|
340
|
* Returns the path of the Kepler hidden working directory terminated with File.seperator.
|
341
|
* This directory is current coded to be ${system.home}/.kepler.
|
342
|
*
|
343
|
* @return the path to the .kepler directory.
|
344
|
*/
|
345
|
public static String getUserDirPath()
|
346
|
{
|
347
|
return KEPLER_USER_DIR;
|
348
|
}
|
349
|
|
350
|
/**
|
351
|
* Returns the path to a subdirectory of the working directory.
|
352
|
* The pathname is normalized to use the system style File.separator.
|
353
|
*
|
354
|
*
|
355
|
* @param path a subdirectory of the working directory
|
356
|
* @return normalized pathname of the subdirectory.
|
357
|
*/
|
358
|
public static String getUserDirPath( String path )
|
359
|
{
|
360
|
String pdir = path;
|
361
|
// In the config file we use unix style separators.
|
362
|
// Convert them to windows if on windows.
|
363
|
if ( '/' != File.separatorChar ) {
|
364
|
pdir.replace('/', File.separatorChar );
|
365
|
}
|
366
|
pdir = KEPLER_USER_DIR + path;
|
367
|
if ( pdir.endsWith(File.separator) ) {
|
368
|
return pdir;
|
369
|
}
|
370
|
else {
|
371
|
return pdir + File.separator;
|
372
|
}
|
373
|
}
|
374
|
|
375
|
/**
|
376
|
* Returns the path to the Cache working directory terminated with File.seperator.
|
377
|
* This directory is currently in getUserDirPath() + "cache".
|
378
|
*
|
379
|
* @return the path to the cache directory
|
380
|
*/
|
381
|
public static String getCacheDirPath()
|
382
|
{
|
383
|
return KEPLER_CACHE_DIR;
|
384
|
}
|
385
|
|
386
|
/**
|
387
|
* Method save. - pass through to ConfigXML member
|
388
|
* @throws Exception
|
389
|
*/
|
390
|
public void save() throws Exception
|
391
|
{
|
392
|
config.save();
|
393
|
}
|
394
|
|
395
|
/**
|
396
|
* Method set. - pass through to ConfigXML member
|
397
|
* @param arg1
|
398
|
* @param arg2
|
399
|
* @param arg3
|
400
|
* @throws ElementNotFoundException
|
401
|
*/
|
402
|
public void set(String arg1, int arg2, String arg3) throws ElementNotFoundException
|
403
|
{
|
404
|
config.set(arg1, arg2, arg3);
|
405
|
}
|
406
|
|
407
|
|
408
|
/**
|
409
|
* Method deleteSubFields. - pass through to ConfigXML member
|
410
|
* @param parentName
|
411
|
* @param i
|
412
|
* @throws IndexTooLargeException
|
413
|
*/
|
414
|
public void deleteSubFields(String parentName, int i) throws IndexTooLargeException
|
415
|
{
|
416
|
config.deleteSubFields(parentName, i);
|
417
|
}
|
418
|
|
419
|
/**
|
420
|
* Method addSubFields. - pass through to ConfigXML member
|
421
|
* @param parentName
|
422
|
* @param i
|
423
|
* @param childName
|
424
|
* @param value
|
425
|
* @throws IndexTooLargeException
|
426
|
*/
|
427
|
public void addSubField(String parentName, int i, String childName, String value)
|
428
|
throws IndexTooLargeException
|
429
|
{
|
430
|
config.addSubField(parentName, i, childName, value);
|
431
|
}
|
432
|
|
433
|
}
|
434
|
|