Project

General

Profile

1 4080 daigle
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements properties methods for metacat
4
 *  Copyright: 2008 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Michael Daigle
7
 *
8
 *   '$Author$'
9
 *     '$Date$'
10
 * '$Revision$'
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */
26
27 5030 daigle
package edu.ucsb.nceas.metacat.properties;
28 4080 daigle
29 4107 daigle
import java.util.Map;
30 4080 daigle
import java.util.Vector;
31
32
import javax.servlet.ServletContext;
33
import javax.servlet.http.HttpServletRequest;
34
35
import org.apache.log4j.Logger;
36
37 5015 daigle
import edu.ucsb.nceas.metacat.shared.BaseService;
38
import edu.ucsb.nceas.metacat.shared.ServiceException;
39 4080 daigle
import edu.ucsb.nceas.utilities.FileUtil;
40
import edu.ucsb.nceas.utilities.GeneralPropertyException;
41
import edu.ucsb.nceas.utilities.PropertiesMetaData;
42
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
43
import edu.ucsb.nceas.utilities.SortedProperties;
44
45
/**
46
 * A suite of utility classes for the metadata configuration utility
47
 */
48 4442 daigle
public class PropertyService extends BaseService {
49 5030 daigle
50 4080 daigle
	private static PropertyService propertyService = null;
51 5030 daigle
52
	private static PropertiesInterface properties = null;
53
54 4080 daigle
	// system is configured
55 5030 daigle
	public static final String CONFIGURED = PropertiesInterface.CONFIGURED;
56 4080 daigle
	// system has never been configured
57 5030 daigle
	public static final String UNCONFIGURED = PropertiesInterface.UNCONFIGURED;
58
	public static final String BYPASSED = PropertiesInterface.BYPASSED;
59
60
	private static String DEFAULT_CONFIG_FILE_DIR = "WEB-INF";
61
	public static String CONFIG_FILE_DIR = null;
62
	public static String CONFIG_FILE_NAME = null;
63
	public static String CONFIG_FILE_PATH = null;
64 4080 daigle
65 5030 daigle
	public static String TEST_CONFIG_FILE_NAME = null;
66
67
	private static String DEFAULT_PROPERTY_CLASS_NAME = "edu.ucsb.nceas.metacat.properties.ConfigurableProperties";
68
	private static String PROPERTY_CLASS_NAME = null;
69
70
	private static String RECOMMENDED_EXTERNAL_DIR = null;
71
72 4080 daigle
	private static Logger logMetacat = Logger.getLogger(PropertyService.class);
73
74
	/**
75
	 * private constructor since this is a singleton
76
	 *
77 5030 daigle
	 * @param servletContext
78
	 *            the context we will use to get relative paths
79 4080 daigle
	 */
80 5030 daigle
	private PropertyService() throws ServiceException {
81 5015 daigle
		_serviceName = "PropertyService";
82
83 5030 daigle
		initialize();
84 4080 daigle
	}
85 5030 daigle
86 4080 daigle
	/**
87 4429 daigle
	 * Get the single instance of PropertyService.
88 4080 daigle
	 *
89 4429 daigle
	 * @return the single instance of PropertyService
90 4080 daigle
	 */
91 5030 daigle
	public static PropertyService getInstance(ServletContext context)
92
			throws ServiceException {
93 4080 daigle
		if (propertyService == null) {
94 4711 daigle
95 5030 daigle
			String applicationName = (String)context.getAttribute("APPLICATION_NAME");
96
97
			CONFIG_FILE_DIR = context.getInitParameter("configFileDir");
98
			if (CONFIG_FILE_DIR == null) {
99
				String configDir = context.getRealPath(DEFAULT_CONFIG_FILE_DIR);
100
				CONFIG_FILE_DIR = configDir;
101
			}
102
103
			CONFIG_FILE_PATH = CONFIG_FILE_DIR + FileUtil.getFS() + applicationName + ".properties";
104
105
			PROPERTY_CLASS_NAME = context.getInitParameter("propertyClassName");
106
			if (PROPERTY_CLASS_NAME == null) {
107
				PROPERTY_CLASS_NAME = DEFAULT_PROPERTY_CLASS_NAME;
108
			}
109
110 4711 daigle
			propertyService = new PropertyService();
111 4080 daigle
		}
112
		return propertyService;
113
	}
114 5030 daigle
115
	 /**
116
	 * Get the single instance of PropertyService for test purposes. In this
117 4719 daigle
	 * case, we allow the configuration directory to be passed in.
118 5030 daigle
	 *
119 4719 daigle
	 * @param configDir the configuration directory we need to look in
120
	 * @return the single instance of PropertyService
121
	 */
122 5030 daigle
	 public static PropertyService getInstance(String testConfigFileDir)
123
			throws ServiceException {
124 4719 daigle
		if (propertyService == null) {
125 5030 daigle
			CONFIG_FILE_DIR = testConfigFileDir;
126
127
			PROPERTY_CLASS_NAME = DEFAULT_PROPERTY_CLASS_NAME;
128
129 4719 daigle
			propertyService = new PropertyService();
130
		}
131
		return propertyService;
132
	}
133 5030 daigle
134
	 /**
135
		 * Get the single instance of PropertyService for test purposes. In this
136
		 * case, we allow the configuration directory to be passed in.
137
		 *
138
		 * @param configDir the configuration directory we need to look in
139
		 * @return the single instance of PropertyService
140
		 */
141
		 public static PropertyService getInstance() throws ServiceException {
142
			if (propertyService == null) {
143
				throw new ServiceException("PropertyService.getInstance - cannot call " +
144
						"getInstance without parameters until property service has been created " +
145
						"with either servlet context or config file path.");
146
			}
147
			return propertyService;
148
		}
149
150 4442 daigle
	public boolean refreshable() {
151 4711 daigle
		return true;
152 4442 daigle
	}
153 5030 daigle
154 4981 daigle
	public void doRefresh() throws ServiceException {
155 5030 daigle
		// initialize();
156 4442 daigle
	}
157 5030 daigle
158 4981 daigle
	public void stop() throws ServiceException {
159
		return;
160
	}
161 5030 daigle
162 4080 daigle
	/**
163
	 * Initialize the singleton.
164
	 *
165 5030 daigle
	 * @param servletContext
166
	 *            the context we will use to get relative paths
167 4080 daigle
	 */
168 4795 daigle
	private void initialize() throws ServiceException {
169 5030 daigle
170 4080 daigle
		logMetacat.debug("Initializing PropertyService");
171 4711 daigle
172 5030 daigle
		try {
173
			Class<?> classDef = Class.forName(PROPERTY_CLASS_NAME);
174
			properties = (PropertiesInterface) classDef.newInstance();
175
		} catch (InstantiationException ie) {
176
			throw new ServiceException("Could not instantiate property class: "
177
					+ PROPERTY_CLASS_NAME + " " + ie.getMessage());
178
		} catch (IllegalAccessException iae) {
179
			throw new ServiceException("Access error when intantiating property class: "
180
					+ PROPERTY_CLASS_NAME + " " + iae.getMessage());
181
		} catch (ClassNotFoundException cnfe) {
182
			throw new ServiceException("Could not find property class: "
183
					+ PROPERTY_CLASS_NAME + " " + cnfe.getMessage());
184 4719 daigle
		}
185 4080 daigle
	}
186
187
	/**
188
	 * Utility method to get a property value from the properties file
189
	 *
190
	 * @param propertyName
191
	 *            the name of the property requested
192
	 * @return the String value for the property
193
	 */
194
	public static String getProperty(String propertyName)
195
			throws PropertyNotFoundException {
196 5030 daigle
		return properties.getProperty(propertyName);
197 4080 daigle
	}
198 5030 daigle
199 4080 daigle
	/**
200 5030 daigle
	 * Get a set of all property names.
201
	 *
202
	 * @return Set of property names
203
	 */
204
	public static Vector<String> getPropertyNames() {
205
		return properties.getPropertyNames();
206
	}
207 4080 daigle
208
	/**
209
	 * Get a Set of all property names that start with the groupName prefix.
210
	 *
211
	 * @param groupName
212
	 *            the prefix of the keys to search for.
213
	 * @return enumeration of property names
214
	 */
215 5030 daigle
	public static Vector<String> getPropertyNamesByGroup(String groupName) {
216
		return properties.getPropertyNamesByGroup(groupName);
217
	}
218
219 4107 daigle
	/**
220
	 * Get a Map of all properties that start with the groupName prefix.
221
	 *
222
	 * @param groupName
223
	 *            the prefix of the keys to search for.
224
	 * @return Map of property names
225
	 */
226 5030 daigle
	public static Map<String, String> getPropertiesByGroup(String groupName)
227
			throws PropertyNotFoundException {
228
		return properties.getPropertiesByGroup(groupName);
229
	}
230 4080 daigle
231
	/**
232
	 * Utility method to set a property value both in memory and to the
233
	 * properties file
234
	 *
235
	 * @param propertyName
236
	 *            the name of the property requested
237
	 * @param newValue
238
	 *            the new value for the property
239
	 */
240 5030 daigle
	public static void setProperty(String propertyName, String newValue)
241
			throws GeneralPropertyException {
242
		properties.setProperty(propertyName, newValue);
243
		properties.persistProperties();
244 4080 daigle
	}
245 6030 leinfelder
246
	/**
247
	 * Utility method to add a property value both in memory and to the
248
	 * properties file
249
	 *
250
	 * @param propertyName
251
	 *            the name of the property to add
252
	 * @param newValue
253
	 *            the value for the property
254
	 */
255
	public static void addProperty(String propertyName, String value)
256
			throws GeneralPropertyException {
257
		properties.addProperty(propertyName, value);
258
		properties.persistProperties();
259
	}
260 4080 daigle
261
	/**
262
	 * Utility method to set a property value in memory. This will NOT cause the
263
	 * property to be written to disk. Use this method to set multiple
264
	 * properties in a row without causing excessive I/O. You must call
265
	 * persistProperties() once you're done setting properties to have them
266
	 * written to disk.
267
	 *
268
	 * @param propertyName
269
	 *            the name of the property requested
270
	 * @param newValue
271
	 *            the new value for the property
272
	 */
273 5030 daigle
	public static void setPropertyNoPersist(String propertyName, String newValue)
274
			throws GeneralPropertyException {
275
		properties.setPropertyNoPersist(propertyName, newValue);
276 4080 daigle
	}
277
278
	/**
279 5030 daigle
	 * Save the properties to a properties file. Note, the order and comments
280
	 * will be preserved.
281 4080 daigle
	 */
282 4085 daigle
	public static void persistProperties() throws GeneralPropertyException {
283 5030 daigle
		properties.persistProperties();
284 4080 daigle
	}
285 5030 daigle
286 4080 daigle
	/**
287 5030 daigle
	 * Get the main backup properties file. These are configurable properties
288
	 * that are stored outside the metacat install directories so the user does
289
	 * not need to re-enter all the configuration information every time they do
290
	 * an upgrade.
291 4080 daigle
	 *
292
	 * @return a SortedProperties object with the backup properties
293
	 */
294 5030 daigle
	public static SortedProperties getMainBackupProperties() throws GeneralPropertyException {
295
		return properties.getMainBackupProperties();
296 4080 daigle
	}
297 5030 daigle
298 4080 daigle
	/**
299 5030 daigle
	 * Get the auth backup properties file. These are configurable properties
300
	 * that are stored outside the metacat install directories so the user does
301
	 * not need to re-enter all the configuration information every time they do
302
	 * an upgrade.
303 4159 daigle
	 *
304
	 * @return a SortedProperties object with the backup properties
305
	 */
306 5030 daigle
	public static SortedProperties getAuthBackupProperties() throws GeneralPropertyException{
307
		return properties.getAuthBackupProperties();
308 4159 daigle
	}
309 5030 daigle
310 4159 daigle
	/**
311 4080 daigle
	 * Get the main properties metadata. This is retrieved from an xml file that
312
	 * describes the attributes of configurable properties.
313
	 *
314
	 * @return a PropertiesMetaData object with the main properties metadata
315
	 */
316 5030 daigle
	public static PropertiesMetaData getMainMetaData() throws GeneralPropertyException{
317
		return properties.getMainMetaData();
318 4080 daigle
	}
319 5030 daigle
320 4080 daigle
	/**
321 5030 daigle
	 * Get the auth properties metadata. This is retrieved from an xml file that
322
	 * describes the attributes of configurable properties.
323 4159 daigle
	 *
324
	 * @return a PropertiesMetaData object with the organization properties
325
	 *         metadata
326
	 */
327 5030 daigle
	public static PropertiesMetaData getAuthMetaData() throws GeneralPropertyException{
328
		return properties.getAuthMetaData();
329 4159 daigle
	}
330 5030 daigle
331 4159 daigle
	/**
332 4080 daigle
	 * Writes out backup configurable properties to a file.
333
	 */
334 5030 daigle
	public static void persistMainBackupProperties() throws GeneralPropertyException {
335 4080 daigle
336 5030 daigle
		properties.persistMainBackupProperties();
337
	}
338 4766 daigle
339 4080 daigle
	/**
340
	 * Writes out backup configurable properties to a file.
341
	 */
342 4589 daigle
	public static void persistAuthBackupProperties(ServletContext servletContext)
343 4159 daigle
			throws GeneralPropertyException {
344 4080 daigle
345 5030 daigle
		properties.persistAuthBackupProperties(servletContext);
346
	}
347 4159 daigle
348 4080 daigle
	/**
349
	 * Reports whether properties are fully configured.
350
	 *
351
	 * @return a boolean that is true if properties are not unconfigured and
352
	 *         false otherwise
353
	 */
354 5030 daigle
	public static boolean arePropertiesConfigured() throws GeneralPropertyException {
355
		return properties.arePropertiesConfigured();
356 4080 daigle
	}
357 5030 daigle
358 4080 daigle
	/**
359 4711 daigle
	 * Determine if the system is configured to bypass configuration. If so, the
360
	 * system will look for backup configuration files at startup time and use
361
	 * those to configure metacat. The bypass options should only be set by
362
	 * developers. Production code should never bypass confguration.
363
	 *
364
	 * @return true if dev.runConfiguration is set to true in metacat.properties
365
	 *         and we have not already checked for bypass, false otherwise.
366
	 */
367 5030 daigle
	public static boolean doBypass() throws GeneralPropertyException {
368
		return properties.doBypass();
369 4711 daigle
	}
370 5030 daigle
371 4711 daigle
	/**
372 5030 daigle
	 * Reports whether the metacat configuration utility should be run. Returns
373
	 * false if -- dev.runConfiguration=false and -- backup properties file
374
	 * exists Note that dev.runConfiguration should only be set to false when
375 4154 daigle
	 * reinstalling the same version of the application in developement.
376
	 *
377 5030 daigle
	 * @return a boolean that is false if dev.runConfiguration is false and the
378
	 *         backup properties file exists.
379 4154 daigle
	 */
380 5030 daigle
	public static void bypassConfiguration() throws GeneralPropertyException {
381
		properties.bypassConfiguration();
382
	}
383 4154 daigle
384
	/**
385 5030 daigle
	 * Take input from the user in an HTTP request about an property to be
386
	 * changed and update the metacat property file with that new value if it
387
	 * has changed from the value that was originally set.
388 4080 daigle
	 *
389
	 * @param request
390
	 *            that was generated by the user
391
	 * @param response
392
	 *            to send output back to the user
393
	 * @param propertyName
394
	 *            the name of the property to be checked and set
395
	 */
396 5846 leinfelder
	public static boolean checkAndSetProperty(HttpServletRequest request, String propertyName)
397 4080 daigle
			throws GeneralPropertyException {
398 5846 leinfelder
		return properties.checkAndSetProperty(request, propertyName);
399 4080 daigle
	}
400 5030 daigle
401 4795 daigle
	/**
402 5030 daigle
	 * Sets the recommended external directory. This is populated during
403
	 * initialization time using the SystemUtil.discoverExternalDir() method.
404
	 * This directory will be used to suggest external user directories when the
405
	 * user configures metacat for the first time.
406 4795 daigle
	 *
407
	 */
408
	public static void setRecommendedExternalDir(String extBaseDir) {
409 5030 daigle
		RECOMMENDED_EXTERNAL_DIR = extBaseDir;
410 4795 daigle
	}
411 5030 daigle
412 4795 daigle
	/**
413 5030 daigle
	 * Returns the recommended external base directory. This is populated during
414
	 * initialization time using the SystemUtil.discoverExternalBaseDir()
415
	 * method. This directory will be used to suggest external user directories
416
	 * when the user configures metacat for the first time.
417 4795 daigle
	 *
418
	 * @return a String holding the recommended external directory
419
	 */
420
	public static String getRecommendedExternalDir() {
421 5030 daigle
		return RECOMMENDED_EXTERNAL_DIR;
422 4795 daigle
	}
423 4080 daigle
424
}