Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements properties methods for metacat
4
 *             skins
5
 *  Copyright: 2008 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Michael Daigle
8
 *
9
 *   '$Author: daigle $'
10
 *     '$Date: 2008-07-06 21:25:34 -0700 (Sun, 06 Jul 2008) $'
11
 * '$Revision: 4080 $'
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 */
27

    
28
package edu.ucsb.nceas.metacat.service;
29

    
30
import java.io.IOException;
31
import java.util.HashMap;
32
import java.util.Set;
33
import java.util.Vector;
34

    
35
import javax.servlet.ServletContext;
36
import javax.servlet.http.HttpServletRequest;
37
import javax.xml.transform.TransformerException;
38

    
39
import org.apache.log4j.Logger;
40

    
41
import edu.ucsb.nceas.metacat.util.SkinUtil;
42
import edu.ucsb.nceas.metacat.util.UtilException;
43
import edu.ucsb.nceas.utilities.FileUtil;
44
import edu.ucsb.nceas.utilities.GeneralPropertyException;
45
import edu.ucsb.nceas.utilities.PropertiesMetaData;
46
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
47
import edu.ucsb.nceas.utilities.SortedProperties;
48

    
49
/**
50
 * A suite of utility classes for the skin configuration utility
51
 */
52
public class SkinPropertyService implements ServiceInterface {
53
	
54
	private static SkinPropertyService skinService = null;
55
	
56
	private static String SKIN_DIR = null;
57
	private static String BACKUP_DIR = null;
58
	
59
	private static Vector<String> skinNames = null;
60
	
61
	private static HashMap<String, SortedProperties> skinPropertiesMap = null;	
62
	private static HashMap<String, SortedProperties> skinBackupPropertiesMap = null;
63
	private static HashMap<String, PropertiesMetaData> skinMetaDataMap = null;
64
	
65
	private static Logger logMetacat = Logger.getLogger(SkinPropertyService.class);
66

    
67
	/**
68
	 * private constructor since this is a singleton
69
	 * 
70
	 * @param servletContext the context we will use to get relative paths
71
	 */
72
	private SkinPropertyService(ServletContext servletContext) throws ServiceException {
73
		try {
74
			initialize(servletContext);
75
		} catch (GeneralPropertyException gpe) {
76
			throw new ServiceException(
77
					"Properties problem while initializing PropertyService: "
78
							+ gpe.getMessage());
79
		} catch (IOException ioe) {
80
			throw new ServiceException("I/O Problem while initializing PropertyService: "
81
					+ ioe.getMessage());
82
		}
83
	}
84
	
85
	/**
86
	 * Get the single instance of AuthAdmin.
87
	 * 
88
	 * @param servletContext the context we will use to get relative paths
89
	 * @return the single instance of AuthAdmin
90
	 */
91
	public static SkinPropertyService getInstance(ServletContext servletContext) throws ServiceException {
92
		if (skinService == null) {
93
			skinService = new SkinPropertyService(servletContext);
94
		}
95
		return skinService;
96
	}
97
	
98
	/**
99
	 * Initialize the singleton.
100
	 * 
101
	 * @param servletContext
102
	 *            the context we will use to get relative paths
103
	 */
104
	private void initialize(ServletContext servletContext) throws IOException,
105
			GeneralPropertyException {
106

    
107
		logMetacat.debug("Initializing SkinService");
108

    
109
		SKIN_DIR = "/style/skins";
110
		BACKUP_DIR = PropertyService.getBackupDir();
111

    
112
		skinNames = SkinUtil.getSkinNames();
113

    
114
		skinPropertiesMap = new HashMap<String, SortedProperties>();
115
		skinBackupPropertiesMap = new HashMap<String, SortedProperties>();
116
		skinMetaDataMap = new HashMap<String, PropertiesMetaData>();
117

    
118
		try {
119
			for (String skinName : skinNames) {
120
				String propertyFilePath = servletContext.getRealPath(SKIN_DIR)
121
						+ FileUtil.getFS() + skinName + FileUtil.getFS() + skinName
122
						+ ".properties";
123
				SortedProperties skinProperties = new SortedProperties(propertyFilePath);
124
				skinProperties.load();
125
				skinPropertiesMap.put(skinName, skinProperties);
126

    
127
				String metaDataFilePath = servletContext.getRealPath(SKIN_DIR)
128
						+ FileUtil.getFS() + skinName + FileUtil.getFS() + skinName
129
						+ ".properties.metadata.xml";
130
				PropertiesMetaData skinMetaData = new PropertiesMetaData(metaDataFilePath);
131
				skinMetaDataMap.put(skinName, skinMetaData);
132

    
133
				String backupPropertyFilePath = servletContext.getRealPath(BACKUP_DIR)
134
						+ FileUtil.getFS() + skinName + ".properties.metadata.xml";
135
				SortedProperties skinBackupProperties = new SortedProperties(
136
						backupPropertyFilePath);
137
				skinBackupProperties.load();
138
				skinBackupPropertiesMap.put(skinName, skinBackupProperties);
139
			}
140
		} catch (TransformerException te) {
141
			throw new GeneralPropertyException(te.getMessage());
142
		}
143
	}
144

    
145
	/**
146
	 * Utility method to get a property value from the properties file for
147
	 * a specific skin.
148
	 * 
149
	 * @param skinName the skin for which we want to retrieve the property
150
	 * @param propertyName
151
	 *            the name of the property requested
152
	 * @return the String value for the property
153
	 */
154
	public static String getProperty(String skinName, String propertyName)
155
			throws PropertyNotFoundException {
156
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
157
		if (skinProperties == null) {
158
			throw new PropertyNotFoundException("There is not property map for " + skinName);
159
		}
160
		return skinProperties.getProperty(propertyName);
161
	}
162
	
163
	/**
164
     * Get a set of all property names for a given skin.
165
     * 
166
     * @param skinName the skin for which we want to retrieve the property
167
     * names
168
     * @return Set of property names  
169
     */
170
    public static Vector<String> getPropertyNames(String skinName) throws PropertyNotFoundException {   
171
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
172
		if (skinProperties == null) {
173
			throw new PropertyNotFoundException("There is not property map for " + skinName);
174
		}
175
    	return skinProperties.getPropertyNames();
176
    }
177
    
178

    
179
	/**
180
	 * Get a Set of all property names that start with the groupName prefix.
181
	 * 
182
	 * @param groupName
183
	 *            the prefix of the keys to search for.
184
	 * @return enumeration of property names
185
	 */
186
    public static Vector<String> getPropertyNamesByGroup(String skinName, String groupName) throws PropertyNotFoundException {  
187
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
188
		if (skinProperties == null) {
189
			throw new PropertyNotFoundException("There is not property map for " + skinName);
190
		}
191
    	return skinProperties.getPropertyNamesByGroup(groupName);
192
    }
193
    
194
	/**
195
	 * Get the main backup properties file. These are configurable properties that
196
	 * are stored outside the metacat install directories so the user does not
197
	 * need to re-enter all the configuration information every time they do an
198
	 * upgrade.
199
	 * 
200
	 * @return a SortedProperties object with the backup properties
201
	 */
202
	public static HashMap<String, SortedProperties> getProperties() {
203
		return skinPropertiesMap;
204
	}
205
    
206
	/**
207
	 * Get the main backup properties file. These are configurable properties that
208
	 * are stored outside the metacat install directories so the user does not
209
	 * need to re-enter all the configuration information every time they do an
210
	 * upgrade.
211
	 * 
212
	 * @return a SortedProperties object with the backup properties
213
	 */
214
	public static SortedProperties getProperties(String skinName) {
215
		return skinPropertiesMap.get(skinName);
216
	}
217

    
218
	/**
219
	 * Get the main backup properties file. These are configurable properties that
220
	 * are stored outside the metacat install directories so the user does not
221
	 * need to re-enter all the configuration information every time they do an
222
	 * upgrade.
223
	 * 
224
	 * @return a SortedProperties object with the backup properties
225
	 */
226
	public static HashMap<String, SortedProperties> getBackupProperties() {
227
		return skinBackupPropertiesMap;
228
	}
229
	
230
	/**
231
	 * Get the main backup properties file. These are configurable properties that
232
	 * are stored outside the metacat install directories so the user does not
233
	 * need to re-enter all the configuration information every time they do an
234
	 * upgrade.
235
	 * 
236
	 * @return a SortedProperties object with the backup properties
237
	 */
238
	public static SortedProperties getBackupProperties(String skinName) {
239
		return skinBackupPropertiesMap.get(skinName);
240
	}
241
	
242
	/**
243
	 * Get the main properties metadata. This is retrieved from an xml file that
244
	 * describes the attributes of configurable properties.
245
	 * 
246
	 * @return a PropertiesMetaData object with the main properties metadata
247
	 */
248
	public static HashMap<String, PropertiesMetaData> getMetaData() {
249
		return skinMetaDataMap;
250
	}
251
	
252
	/**
253
	 * Get the main properties metadata. This is retrieved from an xml file that
254
	 * describes the attributes of configurable properties.
255
	 * 
256
	 * @return a PropertiesMetaData object with the main properties metadata
257
	 */
258
	public static PropertiesMetaData getMetaData(String skinName) {
259
		return skinMetaDataMap.get(skinName);
260
	}
261

    
262
	/**
263
	 * Utility method to set a property value both in memory and to the
264
	 * properties file
265
	 * 
266
	 * @param propertyName
267
	 *            the name of the property requested
268
	 * @param newValue
269
	 *            the new value for the property
270
	 */
271
	public static void setProperty(String skinName, String propertyName, String newValue) throws IOException, GeneralPropertyException {
272
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
273
		if (skinProperties == null) {
274
			throw new GeneralPropertyException("There is not property map for " + skinName);
275
		}
276
		skinProperties.setProperty(propertyName, newValue);
277
		skinProperties.store();
278

    
279
	}
280

    
281
	/**
282
	 * Utility method to set a property value in memory. This will NOT cause the
283
	 * property to be written to disk. Use this method to set multiple
284
	 * properties in a row without causing excessive I/O. You must call
285
	 * persistProperties() once you're done setting properties to have them
286
	 * written to disk.
287
	 * 
288
	 * @param propertyName
289
	 *            the name of the property requested
290
	 * @param newValue
291
	 *            the new value for the property
292
	 */
293
	public static void setPropertyNoPersist(String skinName, String propertyName, String newValue) throws GeneralPropertyException {
294
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
295
		if (skinProperties == null) {
296
			throw new GeneralPropertyException("There is not property map for " + skinName);
297
		}
298
		skinProperties.setPropertyNoPersist(propertyName, newValue);
299
	}
300

    
301
	/**
302
	 * Save the properties to a properties file. Note, the 
303
	 * order and comments will be preserved.
304
	 */
305
	public static void persistProperties(String skinName) throws IOException, GeneralPropertyException {
306
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
307
		if (skinProperties == null) {
308
			throw new GeneralPropertyException("There is not property map for " + skinName);
309
		}
310
		skinProperties.store();
311
	}
312

    
313
	/**
314
	 * Save the properties to a properties file. Note, the order and comments
315
	 * will be preserved.
316
	 */
317
	public static void persistAllProperties() throws IOException,
318
			GeneralPropertyException {
319
		for (String skinName : skinNames) {
320
			persistProperties(skinName);
321
		}
322
	}
323
	
324
	/**
325
	 * Writes out backup configurable properties to a file.
326
	 */
327
	public static void persistBackupProperties(String skinName, ServletContext servletContext)
328
			throws GeneralPropertyException {
329
		
330
		String metaDataFilePath = servletContext.getRealPath(SKIN_DIR) + FileUtil.getFS()
331
				+ skinName + FileUtil.getFS() + skinName + ".properties.metadata.xml";
332
		
333
		String backupPropertyFilePath = servletContext.getRealPath(BACKUP_DIR)
334
				+ FileUtil.getFS() + skinName + ".properties.metadata.xml";
335

    
336
		// Use the metadata to extract configurable properties from the 
337
		// overall properties list, and store those properties.
338
		try {
339
			SortedProperties backupProperties = 
340
				new SortedProperties(backupPropertyFilePath);
341
			
342
			// Populate the backup properties for main metacat properties using
343
			// the associated metadata file
344
			PropertiesMetaData mainMetadata = new PropertiesMetaData(metaDataFilePath);
345
			Set<String> mainKeySet = mainMetadata.getKeys();
346
			for (String propertyKey : mainKeySet) {
347
				backupProperties.setProperty(propertyKey, getProperty(skinName, propertyKey));
348
			}
349
			
350
			// store the properties to file
351
			backupProperties.store();
352

    
353
		} catch (TransformerException te) {
354
			throw new GeneralPropertyException("Could not transform backup properties xml: "
355
					+ te.getMessage());
356
		} catch (IOException ioe) {
357
			throw new GeneralPropertyException("Could not backup configurable properties: "
358
					+ ioe.getMessage());
359
		}
360
	}
361

    
362
	/**
363
	 * Gets the backup properties directory
364
	 * 
365
	 * TODO MCD figure out how to expand this.  At least for Windows
366
	 * 
367
	 * @return a string which holds the name of the backup directory. returns
368
	 *         null if directory could not be created.
369
	 */
370
	public static String getBackupDir() {
371
		return "/var/metacat/.metacat";
372
	}
373
	
374
	/**
375
	 * Reports whether properties are fully configured.
376
	 * 
377
	 * @return a boolean that is true if properties are not unconfigured and
378
	 *         false otherwise
379
	 */
380
	public static boolean areSkinsConfigured() throws UtilException {
381
		try {
382
			return !PropertyService.getProperty("configutil.skinsConfigured").equals(
383
					PropertyService.UNCONFIGURED);
384
		} catch (PropertyNotFoundException pnfe) {
385
			throw new UtilException("Could not determine if skins are configured: "
386
					+ pnfe.getMessage());
387
		}
388
	}
389
	
390
	/**
391
	 * Take input from the user in an HTTP request about an property to be changed
392
	 * and update the metacat property file with that new value if it has
393
	 * changed from the value that was originally set.
394
	 * 
395
	 * @param request
396
	 *            that was generated by the user
397
	 * @param response
398
	 *            to send output back to the user
399
	 * @param propertyName
400
	 *            the name of the property to be checked and set
401
	 */
402
	public static void checkAndSetProperty(String skinName, HttpServletRequest request,String propertyName) 
403
			throws GeneralPropertyException {
404
		String value = SkinPropertyService.getProperty(skinName, propertyName);
405
		String newValue = request.getParameter(propertyName);
406
		if (newValue != null && !newValue.equals(value)) {
407
			SkinPropertyService.setPropertyNoPersist(skinName, propertyName, newValue);
408
		}
409
	}
410

    
411
}
(5-5/5)