Project

General

Profile

« Previous | Next » 

Revision 5030

Added by daigle over 14 years ago

Change location of PropertyService to properties directory

View differences:

src/edu/ucsb/nceas/metacat/service/PropertyService.java
1
/**
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
package edu.ucsb.nceas.metacat.service;
28

  
29
import java.io.IOException;
30
import java.util.Map;
31
import java.util.Set;
32
import java.util.Vector;
33

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

  
38
import org.apache.log4j.Logger;
39

  
40
import edu.ucsb.nceas.metacat.shared.BaseService;
41
import edu.ucsb.nceas.metacat.shared.MetacatUtilException;
42
import edu.ucsb.nceas.metacat.shared.ServiceException;
43
import edu.ucsb.nceas.metacat.util.SystemUtil;
44
import edu.ucsb.nceas.utilities.FileUtil;
45
import edu.ucsb.nceas.utilities.GeneralPropertyException;
46
import edu.ucsb.nceas.utilities.MetaDataProperty;
47
import edu.ucsb.nceas.utilities.PropertiesMetaData;
48
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
49
import edu.ucsb.nceas.utilities.SortedProperties;
50

  
51
/**
52
 * A suite of utility classes for the metadata configuration utility
53
 */
54
public class PropertyService extends BaseService {
55
	
56
	private static PropertyService propertyService = null;
57
	
58
	// system is configured
59
	public static final String CONFIGURED = "true"; 
60
	// system has never been configured
61
	public static final String UNCONFIGURED = "false"; 
62
	public static final String BYPASSED = "bypassed";
63
	
64
	private static String MAIN_CONFIG_NAME = "";
65
	private static final String AUTH_CONFIG_NAME = "auth.properties";
66
	
67
	private static boolean bypassAlreadyChecked = false;
68
	
69
	private static String recommendedExternalDir = null;
70
	
71
	private static String mainPropertiesFilePath = null;
72
	private static SortedProperties mainProperties = null;
73
	
74
	private static String mainBackupPropertiesFilePath = null;
75
	private static SortedProperties mainBackupProperties = null;
76
	
77
	private static String propertiesMetaDataFilePath = null;
78
	private static PropertiesMetaData mainMetaData = null;
79
	
80
	private static String authBackupPropertiesFilePath = null;
81
	private static SortedProperties authBackupProperties = null;
82
	
83
	private static String authMetaDataFilePath = null;
84
	private static PropertiesMetaData authMetaData = null;
85
	
86
	private static boolean testInstance = false;
87
	private static String testConfigDir = null;
88
	
89
	private static Logger logMetacat = Logger.getLogger(PropertyService.class);
90

  
91
	/**
92
	 * private constructor since this is a singleton
93
	 * 
94
	 * @param servletContext the context we will use to get relative paths
95
	 */
96
	private PropertyService() throws ServiceException {		
97
		_serviceName = "PropertyService";
98
		
99
		MAIN_CONFIG_NAME = ServiceService.CONFIG_FILE_NAME;
100
		
101
		initialize();		
102
	}
103
	
104
	/**
105
	 * Get the single instance of PropertyService.
106
	 * 
107
	 * @return the single instance of PropertyService
108
	 */
109
	public static PropertyService getInstance() throws ServiceException {
110
		if (propertyService == null) {
111
			
112
			propertyService = new PropertyService();
113
		}
114
		return propertyService;
115
	}
116
	
117
	/**
118
	 * Get the single instance of PropertyService for test purposes.  In this
119
	 * case, we allow the configuration directory to be passed in.
120
	 * 
121
	 * @param configDir the configuration directory we need to look in
122
	 * @return the single instance of PropertyService
123
	 */
124
	public static PropertyService getTestInstance(String configDir) throws ServiceException {
125
		if (propertyService == null) {
126
			
127
			testInstance = true;
128
			testConfigDir = configDir;
129
			
130
			propertyService = new PropertyService();
131
		}
132
		return propertyService;
133
	}
134
	
135
	public boolean refreshable() {
136
		return true;
137
	}
138
	
139
	public void doRefresh() throws ServiceException {
140
		initialize();
141
	}
142
	
143
	public void stop() throws ServiceException {
144
		return;
145
	}
146
	
147
	/**
148
	 * Initialize the singleton.
149
	 * 
150
	 * @param servletContext the context we will use to get relative paths
151
	 */
152
	private void initialize() throws ServiceException {
153
		
154
		logMetacat.debug("Initializing PropertyService");
155
		
156
		String configDir;
157
		if (testInstance) {
158
			configDir = testConfigDir;
159
		} else {
160
			configDir = ServiceService.getRealConfigDir();
161
		}
162
		
163
		try {
164
			// mainProperties will hold the primary configuration values for
165
			// metacat.
166
			mainPropertiesFilePath = configDir + FileUtil.getFS() + MAIN_CONFIG_NAME;
167
			mainProperties = new SortedProperties(mainPropertiesFilePath);
168
			mainProperties.load();
169

  
170
			// mainMetaData holds configuration information about main
171
			// properties. This is primarily used to display input fields on 
172
			// the configuration page. The information is retrieved from an 
173
			// xml metadata file
174
			propertiesMetaDataFilePath = 
175
				configDir + FileUtil.getFS() + MAIN_CONFIG_NAME + ".metadata.xml";
176
			mainMetaData = new PropertiesMetaData(propertiesMetaDataFilePath);
177

  
178
			// authMetaData holds configuration information about organization
179
			// level
180
			// properties. This is primarily used to display input fields on
181
			// the auth configuration page. The information is retrieved
182
			// from an xml metadata file dedicated just to auth properties.
183
			authMetaDataFilePath = 
184
				configDir + FileUtil.getFS() + AUTH_CONFIG_NAME + ".metadata.xml";
185
			authMetaData = new PropertiesMetaData(authMetaDataFilePath);
186

  
187
			String recommendedExternalDir = SystemUtil.discoverExternalDir();
188
			setRecommendedExternalDir(recommendedExternalDir);
189
			
190
			String backupPath = getProperty("application.backupDir");
191
			if (backupPath == null || backupPath.equals("")) {
192
				backupPath = SystemUtil.getStoredBackupDir();
193
			}
194
			if (backupPath == null || backupPath.equals("") && recommendedExternalDir != null) {
195
				backupPath = 
196
					recommendedExternalDir + FileUtil.getFS() + "." + ServiceService.getRealApplicationContext();
197
			}
198

  
199
			// if backupPath is still null, no reason to initialize the
200
			// backup properties. The system will need to prompt the user for 
201
			// the backup properties and reinitialize PropertyService.
202
			if (backupPath != null && !backupPath.equals("")) {		
203
				setProperty("application.backupDir", backupPath);
204
				SystemUtil.writeStoredBackupFile(backupPath);
205

  
206
				// The mainBackupProperties hold properties that were backed up
207
				// the last time the application was configured. On disk, the 
208
				// file will look like a smaller version of metacat.properties. 
209
				// It is stored in the data storage directory outside the 
210
				// application directories.
211
				mainBackupPropertiesFilePath =
212
					backupPath + FileUtil.getFS() + MAIN_CONFIG_NAME + ".backup";
213
				mainBackupProperties = new SortedProperties(mainBackupPropertiesFilePath);
214
				mainBackupProperties.load();
215

  
216
				// The authBackupProperties hold properties that were backed up
217
				// the last time the auth was configured. On disk, the file 
218
				// will look like a smaller version of metacat.properties. It 
219
				// is stored in the data storage directory outside the 
220
				// application directories.
221
				authBackupPropertiesFilePath = 
222
					backupPath + FileUtil.getFS() + AUTH_CONFIG_NAME + ".backup";
223
				authBackupProperties = new SortedProperties(authBackupPropertiesFilePath);
224
				authBackupProperties.load();
225
			}
226
		} catch (TransformerException te) {
227
			throw new ServiceException("Transform problem while loading properties: "
228
					+ te.getMessage());
229
		} catch (IOException ioe) {
230
			throw new ServiceException("I/O problem while loading properties: "
231
					+ ioe.getMessage());
232
		} catch (GeneralPropertyException gpe) {
233
			throw new ServiceException("General properties problem while loading properties: "
234
					+ gpe.getMessage());
235
		} catch (MetacatUtilException ue) {
236
			throw new ServiceException("Utilities problem while loading properties: "
237
					+ ue.getMessage());
238
		} 
239
	}
240

  
241
	/**
242
	 * Utility method to get a property value from the properties file
243
	 * 
244
	 * @param propertyName
245
	 *            the name of the property requested
246
	 * @return the String value for the property
247
	 */
248
	public static String getProperty(String propertyName)
249
			throws PropertyNotFoundException {
250
		return mainProperties.getProperty(propertyName);
251
	}
252
	
253
	/**
254
     * Get a set of all property names.
255
     * 
256
     * @return Set of property names  
257
     */
258
    public static Vector<String> getPropertyNames() {   	
259
    	return mainProperties.getPropertyNames();
260
    }
261
    
262

  
263
	/**
264
	 * Get a Set of all property names that start with the groupName prefix.
265
	 * 
266
	 * @param groupName
267
	 *            the prefix of the keys to search for.
268
	 * @return enumeration of property names
269
	 */
270
    public static Vector<String> getPropertyNamesByGroup(String groupName) {   	
271
    	return mainProperties.getPropertyNamesByGroup(groupName);
272
    }
273
    
274
	/**
275
	 * Get a Map of all properties that start with the groupName prefix.
276
	 * 
277
	 * @param groupName
278
	 *            the prefix of the keys to search for.
279
	 * @return Map of property names
280
	 */
281
    public static Map<String, String> getPropertiesByGroup(String groupName) throws PropertyNotFoundException {   	
282
    	return mainProperties.getPropertiesByGroup(groupName);
283
    }
284

  
285
	/**
286
	 * Utility method to set a property value both in memory and to the
287
	 * properties file
288
	 * 
289
	 * @param propertyName
290
	 *            the name of the property requested
291
	 * @param newValue
292
	 *            the new value for the property
293
	 */
294
	public static void setProperty(String propertyName, String newValue) throws GeneralPropertyException {
295
			mainProperties.setProperty(propertyName, newValue);
296
			mainProperties.store();
297
	}
298

  
299
	/**
300
	 * Utility method to set a property value in memory. This will NOT cause the
301
	 * property to be written to disk. Use this method to set multiple
302
	 * properties in a row without causing excessive I/O. You must call
303
	 * persistProperties() once you're done setting properties to have them
304
	 * written to disk.
305
	 * 
306
	 * @param propertyName
307
	 *            the name of the property requested
308
	 * @param newValue
309
	 *            the new value for the property
310
	 */
311
	public static void setPropertyNoPersist(String propertyName, String newValue) throws GeneralPropertyException {
312
		mainProperties.setPropertyNoPersist(propertyName, newValue);
313
	}
314

  
315
	/**
316
	 * Save the properties to a properties file. Note, the 
317
	 * order and comments will be preserved.
318
	 */
319
	public static void persistProperties() throws GeneralPropertyException {
320
		mainProperties.store();
321
	}
322
	
323
	/**
324
	 * Get the main backup properties file. These are configurable properties that
325
	 * are stored outside the metacat install directories so the user does not
326
	 * need to re-enter all the configuration information every time they do an
327
	 * upgrade.
328
	 * 
329
	 * @return a SortedProperties object with the backup properties
330
	 */
331
	public static SortedProperties getMainBackupProperties() {
332
		return mainBackupProperties;
333
	}
334
	
335
	/**
336
	 * Get the auth backup properties file. These are configurable 
337
	 * properties that are stored outside the metacat install directories so 
338
	 * the user does not need to re-enter all the configuration information 
339
	 * every time they do an upgrade.
340
	 * 
341
	 * @return a SortedProperties object with the backup properties
342
	 */
343
	public static SortedProperties getAuthBackupProperties() {
344
		return authBackupProperties;
345
	}
346
	
347
	/**
348
	 * Get the main properties metadata. This is retrieved from an xml file that
349
	 * describes the attributes of configurable properties.
350
	 * 
351
	 * @return a PropertiesMetaData object with the main properties metadata
352
	 */
353
	public static PropertiesMetaData getMainMetaData() {
354
		return mainMetaData;
355
	}
356
	
357
	/**
358
	 * Get the auth properties metadata. This is retrieved from an xml
359
	 * file that describes the attributes of configurable properties.
360
	 * 
361
	 * @return a PropertiesMetaData object with the organization properties
362
	 *         metadata
363
	 */
364
	public static PropertiesMetaData getAuthMetaData() {
365
		return authMetaData;
366
	}
367
	
368
	/**
369
	 * Writes out backup configurable properties to a file.
370
	 */
371
	public static void persistMainBackupProperties()
372
			throws GeneralPropertyException {
373

  
374
		// Use the metadata to extract configurable properties from the 
375
		// overall properties list, and store those properties.
376
		try {
377
			SortedProperties backupProperties = new SortedProperties(mainBackupPropertiesFilePath);
378
			
379
			// Populate the backup properties for main metacat properties using
380
			// the associated metadata file
381
			PropertiesMetaData mainMetadata = new PropertiesMetaData(propertiesMetaDataFilePath);
382

  
383
			Map<String, MetaDataProperty> mainKeyMap = mainMetadata.getProperties();
384
			Set<String> mainKeySet = mainKeyMap.keySet();
385
			for (String propertyKey : mainKeySet) {
386
				// don't backup passwords
387
				MetaDataProperty metaData = mainKeyMap.get(propertyKey);
388
				if (!metaData.getFieldType().equals(MetaDataProperty.PASSWORD_TYPE)) {
389
					backupProperties.addProperty(propertyKey, getProperty(propertyKey));
390
				}
391
			}
392
			
393
			// store the properties to file
394
			backupProperties.store();
395
			mainBackupProperties = 
396
				new SortedProperties(mainBackupPropertiesFilePath);
397
			mainBackupProperties.load();
398

  
399
		} catch (TransformerException te) {
400
			throw new GeneralPropertyException("Could not transform backup properties xml: "
401
					+ te.getMessage());
402
		} catch (IOException ioe) {
403
			throw new GeneralPropertyException("Could not backup configurable properties: "
404
					+ ioe.getMessage());
405
		}
406
	}
407
	
408
	/**
409
	 * Writes out backup configurable properties to a file.
410
	 */
411
	public static void persistAuthBackupProperties(ServletContext servletContext)
412
			throws GeneralPropertyException {
413

  
414
		// Use the metadata to extract configurable properties from the 
415
		// overall properties list, and store those properties.
416
		try {
417
			SortedProperties backupProperties = 
418
				new SortedProperties(authBackupPropertiesFilePath);
419
			
420
			// Populate the backup properties for auth properties using
421
			// the associated metadata file
422
			PropertiesMetaData authMetadata = new PropertiesMetaData(authMetaDataFilePath);
423
			
424
			Map<String, MetaDataProperty> authKeyMap = authMetadata.getProperties();
425
			Set<String> authKeySet = authKeyMap.keySet();
426
			for (String propertyKey : authKeySet) {
427
				// don't backup passwords
428
				MetaDataProperty metaData = authKeyMap.get(propertyKey);
429
				if (!metaData.getFieldType().equals(MetaDataProperty.PASSWORD_TYPE)) {
430
					backupProperties.addProperty(propertyKey, getProperty(propertyKey));
431
				}
432
			}
433
			
434
			// store the properties to file
435
			backupProperties.store();
436
			authBackupProperties = 
437
				new SortedProperties(authBackupPropertiesFilePath);
438
			authBackupProperties.load();
439

  
440
		} catch (TransformerException te) {
441
			throw new GeneralPropertyException("Could not transform backup properties xml: "
442
					+ te.getMessage());
443
		} catch (IOException ioe) {
444
			throw new GeneralPropertyException("Could not backup configurable properties: "
445
					+ ioe.getMessage());
446
		} 
447
	}
448
	
449
	/**
450
	 * Reports whether properties are fully configured.
451
	 * 
452
	 * @return a boolean that is true if properties are not unconfigured and
453
	 *         false otherwise
454
	 */
455
	public static boolean arePropertiesConfigured() throws MetacatUtilException {		
456
		try {
457
			String propertiesConfigured = PropertyService.getProperty("configutil.propertiesConfigured");
458
			if (propertiesConfigured != null && !propertiesConfigured.equals(UNCONFIGURED)) {
459
				return true;
460
			}			
461
			return false;
462
		} catch (PropertyNotFoundException pnfe) {
463
			throw new MetacatUtilException("Could not determine if properties are configured: "
464
					+ pnfe.getMessage());
465
		}
466
	}
467
	
468
	/**
469
	 * Determine if the system is configured to bypass configuration. If so, the
470
	 * system will look for backup configuration files at startup time and use
471
	 * those to configure metacat. The bypass options should only be set by
472
	 * developers. Production code should never bypass confguration.
473
	 * 
474
	 * @return true if dev.runConfiguration is set to true in metacat.properties
475
	 *         and we have not already checked for bypass, false otherwise.
476
	 */
477
	public static boolean doBypass() throws PropertyNotFoundException {
478
		// We only want to go through the check once to see if we want to
479
		// bypass the configuration.  We don't want to run through all of
480
		// this every time  we hit metacat. 
481
		if (bypassAlreadyChecked) {
482
			logMetacat.debug("bypassConfiguration not performing full bypass check.  Bypass set to false");
483
			return false;
484
		}
485
		
486
		// check how dev.runConfiguration is set in metacat.properties
487
		String strRunConfiguration = PropertyService.getProperty("dev.runConfiguration");
488
		boolean runConfiguration = Boolean.parseBoolean(strRunConfiguration);
489
		logMetacat.debug("bypassConfiguration: dev.runConfiguration property set to: " + strRunConfiguration);
490
		
491
		// if the dev.runConfiguration is true, return false here.
492
		if (runConfiguration) {
493
			bypassAlreadyChecked = true;
494
			return false;
495
		} 
496
		
497
		return true;
498
	}
499
	
500
	/**
501
	 * Reports whether the metacat configuration utility should be run.  
502
	 * Returns false if  
503
	 *   -- dev.runConfiguration=false and
504
	 *   -- backup properties file exists
505
	 * Note that dev.runConfiguration should only be set to false when
506
	 * reinstalling the same version of the application in developement.
507
	 * 
508
	 * @return a boolean that is false if dev.runConfiguration is false and 
509
	 * the backup properties file exists.  
510
	 */
511
	public static void bypassConfiguration() throws ServiceException {
512
		try {
513
			boolean doBypass = doBypass();
514

  
515
			if (!doBypass) {
516
				throw new ServiceException(
517
						"Attempting to do bypass when system is not configured for it.");
518
			}			
519

  
520
			// The system is bypassing the configuration utility. We need to
521
			// get the backup properties and replace existing properties with
522
			// backup values.  We do this for main and org properties.		
523
			logMetacat.debug("bypassConfiguration: setting main backup properties.");
524
			SortedProperties mainBackupProperties = getMainBackupProperties();
525
			Vector<String> backupPropertyNames = 
526
				mainBackupProperties.getPropertyNames();
527
			for (String backupPropertyName : backupPropertyNames) {
528
				String value = mainBackupProperties.getProperty(backupPropertyName);
529
				setPropertyNoPersist(backupPropertyName, value);
530
			}
531

  
532
			logMetacat.debug("bypassConfiguration: setting auth backup properties.");
533
			SortedProperties authBackupProperties = getAuthBackupProperties();
534
			Vector<String> authBackupPropertyNames = 
535
				authBackupProperties.getPropertyNames();
536
			for (String authBackupPropertyName : authBackupPropertyNames) {
537
				String value = authBackupProperties.getProperty(authBackupPropertyName);
538
				setPropertyNoPersist(authBackupPropertyName, value);
539
			}
540

  
541
			logMetacat.debug("bypassConfiguration: setting configutil sections to true.");
542
			setPropertyNoPersist("configutil.propertiesConfigured", "true");
543
			setPropertyNoPersist("configutil.authConfigured", "true");
544
			setPropertyNoPersist("configutil.skinsConfigured", "true");
545
			setPropertyNoPersist("configutil.databaseConfigured", "true");
546
			setPropertyNoPersist("configutil.geoserverConfigured", "bypassed");
547
				
548
			persistProperties();
549

  
550
		} catch (PropertyNotFoundException pnfe) {
551
			logMetacat.error("bypassConfiguration: Could not find property: " + pnfe.getMessage());
552
		} catch (GeneralPropertyException gpe) {
553
			logMetacat.error("bypassConfiguration: General property error: " + gpe.getMessage());
554
		}
555

  
556
		bypassAlreadyChecked = true;
557
	}
558
	
559
	/**
560
	 * Take input from the user in an HTTP request about an property to be changed
561
	 * and update the metacat property file with that new value if it has
562
	 * changed from the value that was originally set.
563
	 * 
564
	 * @param request
565
	 *            that was generated by the user
566
	 * @param response
567
	 *            to send output back to the user
568
	 * @param propertyName
569
	 *            the name of the property to be checked and set
570
	 */
571
	public static void checkAndSetProperty(HttpServletRequest request, String propertyName) 
572
			throws GeneralPropertyException {
573
		String value = PropertyService.getProperty(propertyName);
574
		String newValue = request.getParameter(propertyName);
575
		if (newValue != null && !newValue.trim().equals(value)) {
576
			PropertyService.setPropertyNoPersist(propertyName, newValue.trim());
577
		}
578
	}
579
	
580
	/**
581
	 * Sets the recommended external directory.  This is populated during initialization 
582
	 * time using the SystemUtil.discoverExternalDir() method.  This directory will be used to
583
	 * suggest external user directories when the user configures metacat for the first time.
584
	 * 
585
	 */
586
	public static void setRecommendedExternalDir(String extBaseDir) {
587
		recommendedExternalDir = extBaseDir;
588
	}
589
	
590
	/**
591
	 * Returns the recommended external base directory.  This is populated during initialization 
592
	 * time using the SystemUtil.discoverExternalBaseDir() method.  This directory will be used to
593
	 * suggest external user directories when the user configures metacat for the first time.
594
	 * 
595
	 * @return a String holding the recommended external directory
596
	 */
597
	public static String getRecommendedExternalDir() {
598
		return recommendedExternalDir;
599
	}
600

  
601
}
602 0

  
src/edu/ucsb/nceas/metacat/service/SkinPropertyService.java
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$'
10
 *     '$Date$'
11
 * '$Revision$'
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.Map;
33
import java.util.Set;
34
import java.util.Vector;
35

  
36

  
37
import javax.servlet.http.HttpServletRequest;
38
import javax.xml.transform.TransformerException;
39

  
40
import org.apache.log4j.Logger;
41

  
42
import edu.ucsb.nceas.metacat.shared.BaseService;
43
import edu.ucsb.nceas.metacat.shared.MetacatUtilException;
44
import edu.ucsb.nceas.metacat.shared.ServiceException;
45
import edu.ucsb.nceas.metacat.util.SkinUtil;
46
import edu.ucsb.nceas.utilities.FileUtil;
47
import edu.ucsb.nceas.utilities.GeneralPropertyException;
48
import edu.ucsb.nceas.utilities.MetaDataProperty;
49
import edu.ucsb.nceas.utilities.PropertiesMetaData;
50
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
51
import edu.ucsb.nceas.utilities.SortedProperties;
52

  
53
/**
54
 * A suite of utility classes for the skin configuration utility
55
 */
56
public class SkinPropertyService extends BaseService {
57

  
58
	private static SkinPropertyService skinService = null;
59

  
60
	private static boolean bypassAlreadyChecked = false;
61

  
62
	private static String BACKUP_DIR = null;
63

  
64
	private static Vector<String> skinNames = null;
65

  
66
	private static HashMap<String, SortedProperties> skinPropertiesMap = null;
67
	private static HashMap<String, SortedProperties> skinBackupPropertiesMap = null;
68
	private static HashMap<String, PropertiesMetaData> skinMetaDataMap = null;
69

  
70
	private static Logger logMetacat = Logger.getLogger(SkinPropertyService.class);
71

  
72
	/**
73
	 * private constructor since this is a singleton
74
	 * 
75
	 * @param servletContext
76
	 *            the context we will use to get relative paths
77
	 */
78
	private SkinPropertyService() throws ServiceException {
79
		try {
80
			_serviceName = "SkinPropertyService";
81
			
82
			initialize();
83
		} catch (GeneralPropertyException gpe) {
84
			throw new ServiceException(
85
					"Properties problem while initializing SkinPropertyService: "
86
							+ gpe.getMessage());
87
		} catch (IOException ioe) {
88
			throw new ServiceException("I/O Problem while initializing SkinPropertyService: "
89
					+ ioe.getMessage());
90
		}
91
	}
92

  
93
	/**
94
	 * Get the single instance of SkinPropertyService.
95
	 * 
96
	 * @param servletContext
97
	 *            the context we will use to get relative paths
98
	 * @return the single instance of SkinPropertyService
99
	 */
100
	public static SkinPropertyService getInstance() throws ServiceException {
101
		if (skinService == null) {
102
			skinService = new SkinPropertyService();
103
		}
104
		return skinService;
105
	}
106

  
107
	public boolean refreshable() {
108
		return true;
109
	}
110

  
111
	public void doRefresh() throws ServiceException {
112
		try {
113
			initialize();
114
		} catch (IOException ioe) {
115
			throw new ServiceException("Could not refresh SkinPropertyService due to"
116
					+ " I/O error: " + ioe.getMessage());
117
		} catch (GeneralPropertyException gpe) {
118
			throw new ServiceException("Could not refresh SkinPropertyService due to"
119
					+ " property error: " + gpe.getMessage());
120
		}
121
	}
122
	
123
	public void stop() throws ServiceException {
124
		return;
125
	}
126

  
127
	/**
128
	 * Initialize the singleton.
129
	 * 
130
	 * @param servletContext
131
	 *            the context we will use to get relative paths
132
	 */
133
	private void initialize() throws IOException, GeneralPropertyException,
134
			ServiceException {
135

  
136
		logMetacat.debug("Initializing SkinService");
137

  
138
		BACKUP_DIR = PropertyService.getProperty("application.backupDir");
139

  
140
		skinNames = SkinUtil.getSkinNames();
141

  
142
		skinPropertiesMap = new HashMap<String, SortedProperties>();
143
		skinBackupPropertiesMap = new HashMap<String, SortedProperties>();
144
		skinMetaDataMap = new HashMap<String, PropertiesMetaData>();
145

  
146
		try {
147
			for (String skinName : skinNames) {
148
				String propertyFilePath = ServiceService.getRealSkinDir()
149
						+ FileUtil.getFS() + skinName + FileUtil.getFS() + skinName
150
						+ ".properties";
151

  
152
				if (FileUtil.getFileStatus(propertyFilePath) < FileUtil.EXISTS_READ_WRITABLE) {
153
					logMetacat.error("Skin property file: " + propertyFilePath
154
							+ " does not exist read/writable. This skin will not be available.");
155
					continue;
156
				}
157

  
158
				SortedProperties skinProperties = new SortedProperties(propertyFilePath);
159
				skinProperties.load();
160
				skinPropertiesMap.put(skinName, skinProperties);
161

  
162
				String metaDataFilePath = ServiceService.getRealSkinDir()
163
						+ FileUtil.getFS() + skinName + FileUtil.getFS() + skinName
164
						+ ".properties.metadata.xml";
165
				if (FileUtil.getFileStatus(metaDataFilePath) > FileUtil.DOES_NOT_EXIST) {
166
					PropertiesMetaData skinMetaData = new PropertiesMetaData(metaDataFilePath);
167
					skinMetaDataMap.put(skinName, skinMetaData);
168
				} else {
169
					skinPropertiesMap.remove(skinName);
170
					logMetacat.error("Could not find skin property metadata file for skin: " 
171
							+ skinName + " at: " + metaDataFilePath  
172
							+ ". This skin will not be available.");
173
					continue;
174
				}
175

  
176
				String backupPropertyFilePath = BACKUP_DIR + FileUtil.getFS() + skinName
177
						+ ".properties.backup";
178
				if (FileUtil.getFileStatus(backupPropertyFilePath) > FileUtil.DOES_NOT_EXIST) {
179
					SortedProperties skinBackupProperties = new SortedProperties(
180
							backupPropertyFilePath);
181
					skinBackupProperties.load();
182
					skinBackupPropertiesMap.put(skinName, skinBackupProperties);
183
				} else {
184
					logMetacat.warn("Could not find backup properties for skin: "
185
							+ skinName + " at: " + backupPropertyFilePath);
186
				}
187
			}
188
		} catch (TransformerException te) {
189
			throw new GeneralPropertyException(te.getMessage());
190
		}
191
	}
192

  
193
	/**
194
	 * Utility method to get a property value from the properties file for a
195
	 * specific skin.
196
	 * 
197
	 * @param skinName
198
	 *            the skin for which we want to retrieve the property
199
	 * @param propertyName
200
	 *            the name of the property requested
201
	 * @return the String value for the property
202
	 */
203
	public static String getProperty(String skinName, String propertyName)
204
			throws PropertyNotFoundException {
205
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
206
		if (skinProperties == null) {
207
			throw new PropertyNotFoundException("There is not property map for "
208
					+ skinName);
209
		}
210
		return skinProperties.getProperty(propertyName);
211
	}
212

  
213
	/**
214
	 * Get a set of all property names for a given skin.
215
	 * 
216
	 * @param skinName
217
	 *            the skin for which we want to retrieve the property names
218
	 * @return Set of property names
219
	 */
220
	public static Vector<String> getPropertyNames(String skinName)
221
			throws PropertyNotFoundException {
222
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
223
		if (skinProperties == null) {
224
			throw new PropertyNotFoundException("There is not property map for "
225
					+ skinName);
226
		}
227
		return skinProperties.getPropertyNames();
228
	}
229

  
230
	/**
231
	 * Get a Set of all property names that start with the groupName prefix.
232
	 * 
233
	 * @param groupName
234
	 *            the prefix of the keys to search for.
235
	 * @return Vector of property names
236
	 */
237
	public static Vector<String> getPropertyNamesByGroup(String skinName, String groupName)
238
			throws PropertyNotFoundException {
239
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
240
		if (skinProperties == null) {
241
			throw new PropertyNotFoundException("There is not property map for "
242
					+ skinName);
243
		}
244
		return skinProperties.getPropertyNamesByGroup(groupName);
245
	}
246

  
247
	/**
248
	 * Get the main backup properties file. These are configurable properties
249
	 * that are stored outside the metacat install directories so the user does
250
	 * not need to re-enter all the configuration information every time they do
251
	 * an upgrade.
252
	 * 
253
	 * @return a SortedProperties object with the backup properties
254
	 */
255
	public static HashMap<String, SortedProperties> getProperties() {
256
		return skinPropertiesMap;
257
	}
258

  
259
	/**
260
	 * Get the main backup properties file. These are configurable properties
261
	 * that are stored outside the metacat install directories so the user does
262
	 * not need to re-enter all the configuration information every time they do
263
	 * an upgrade.
264
	 * 
265
	 * @return a SortedProperties object with the backup properties
266
	 */
267
	public static SortedProperties getProperties(String skinName) {
268
		return skinPropertiesMap.get(skinName);
269
	}
270

  
271
	/**
272
	 * Get the main backup properties file. These are configurable properties
273
	 * that are stored outside the metacat install directories so the user does
274
	 * not need to re-enter all the configuration information every time they do
275
	 * an upgrade.
276
	 * 
277
	 * @return a SortedProperties object with the backup properties
278
	 */
279
	public static HashMap<String, SortedProperties> getBackupProperties() {
280
		return skinBackupPropertiesMap;
281
	}
282

  
283
	/**
284
	 * Get the main backup properties file. These are configurable properties
285
	 * that are stored outside the metacat install directories so the user does
286
	 * not need to re-enter all the configuration information every time they do
287
	 * an upgrade.
288
	 * 
289
	 * @return a SortedProperties object with the backup properties
290
	 */
291
	public static SortedProperties getBackupProperties(String skinName) {
292
		return skinBackupPropertiesMap.get(skinName);
293
	}
294

  
295
	/**
296
	 * Get the main properties metadata. This is retrieved from an xml file that
297
	 * describes the attributes of configurable properties.
298
	 * 
299
	 * @return a PropertiesMetaData object with the main properties metadata
300
	 */
301
	public static HashMap<String, PropertiesMetaData> getMetaData() {
302
		return skinMetaDataMap;
303
	}
304

  
305
	/**
306
	 * Get the main properties metadata. This is retrieved from an xml file that
307
	 * describes the attributes of configurable properties.
308
	 * 
309
	 * @return a PropertiesMetaData object with the main properties metadata
310
	 */
311
	public static PropertiesMetaData getMetaData(String skinName) {
312
		return skinMetaDataMap.get(skinName);
313
	}
314

  
315
	/**
316
	 * Utility method to set a property value both in memory and to the
317
	 * properties file
318
	 * 
319
	 * @param propertyName
320
	 *            the name of the property requested
321
	 * @param newValue
322
	 *            the new value for the property
323
	 */
324
	public static void setProperty(String skinName, String propertyName, String newValue)
325
			throws IOException, GeneralPropertyException {
326
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
327
		if (skinProperties == null) {
328
			throw new GeneralPropertyException("There is not property map for "
329
					+ skinName);
330
		}
331
		skinProperties.setProperty(propertyName, newValue);
332
		skinProperties.store();
333

  
334
	}
335

  
336
	/**
337
	 * Utility method to set a property value in memory. This will NOT cause the
338
	 * property to be written to disk. Use this method to set multiple
339
	 * properties in a row without causing excessive I/O. You must call
340
	 * persistProperties() once you're done setting properties to have them
341
	 * written to disk.
342
	 * 
343
	 * @param propertyName
344
	 *            the name of the property requested
345
	 * @param newValue
346
	 *            the new value for the property
347
	 */
348
	public static void setPropertyNoPersist(String skinName, String propertyName,
349
			String newValue) throws GeneralPropertyException {
350
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
351
		if (skinProperties == null) {
352
			throw new GeneralPropertyException("There is not property map for "
353
					+ skinName);
354
		}
355
		skinProperties.setPropertyNoPersist(propertyName, newValue);
356
	}
357

  
358
	/**
359
	 * Save the properties to a properties file. Note, the order and comments
360
	 * will be preserved.
361
	 */
362
	public static void persistProperties(String skinName) throws IOException,
363
			GeneralPropertyException {
364
		SortedProperties skinProperties = skinPropertiesMap.get(skinName);
365
		if (skinProperties == null) {
366
			throw new GeneralPropertyException("There is not property map for "
367
					+ skinName);
368
		}
369
		skinProperties.store();
370
	}
371

  
372
	/**
373
	 * Save the properties to a properties file. Note, the order and comments
374
	 * will be preserved.
375
	 */
376
	public static void persistAllProperties() throws IOException,
377
			GeneralPropertyException {
378
		for (String skinName : skinNames) {
379
			persistProperties(skinName);
380
		}
381
	}
382

  
383
	/**
384
	 * Writes out backup configurable properties to a file.
385
	 */
386
	public static void persistBackupProperties(String skinName)
387
			throws GeneralPropertyException {
388
		try {
389
			String metaDataFilePath = ServiceService.getRealSkinDir() + FileUtil.getFS()
390
					+ skinName + FileUtil.getFS() + skinName + ".properties.metadata.xml";
391

  
392
			String backupPropertyFilePath = BACKUP_DIR + FileUtil.getFS() + skinName
393
					+ ".properties.backup";
394

  
395
			// Use the metadata to extract configurable properties from the
396
			// overall properties list, and store those properties.
397
			SortedProperties backupProperties = new SortedProperties(
398
					backupPropertyFilePath);
399

  
400
			// Populate the backup properties for main metacat properties using
401
			// the associated metadata file
402
			PropertiesMetaData skinMetadata = new PropertiesMetaData(metaDataFilePath);
403
			
404
			Map<String, MetaDataProperty> skinKeyMap = skinMetadata.getProperties();
405
			Set<String> skinKeySet = skinKeyMap.keySet();
406
			for (String propertyKey : skinKeySet) {
407
				// don't backup passwords
408
				MetaDataProperty metaData = skinKeyMap.get(propertyKey);
409
				if (!metaData.getFieldType().equals(MetaDataProperty.PASSWORD_TYPE)) {
410
					backupProperties.addProperty(propertyKey, getProperty(skinName, propertyKey));
411
				}
412
			}			
413

  
414
			// store the properties to file
415
			backupProperties.store();
416

  
417
		} catch (TransformerException te) {
418
			throw new GeneralPropertyException(
419
					"Could not transform backup properties xml: " + te.getMessage());
420
		} catch (IOException ioe) {
421
			throw new GeneralPropertyException(
422
					"Could not backup configurable properties: " + ioe.getMessage());
423
		} catch (ServiceException se) {
424
			throw new GeneralPropertyException("Could not get skins property file: "
425
					+ se.getMessage());
426
		}
427
	}
428

  
429
	/**
430
	 * Reports whether properties are fully configured.
431
	 * 
432
	 * @return a boolean that is true if properties are not unconfigured and
433
	 *         false otherwise
434
	 */
435
	public static boolean areSkinsConfigured() throws MetacatUtilException {
436
		try {
437
			return !PropertyService.getProperty("configutil.skinsConfigured").equals(
438
					PropertyService.UNCONFIGURED);
439
		} catch (PropertyNotFoundException pnfe) {
440
			throw new MetacatUtilException("Could not determine if skins are configured: "
441
					+ pnfe.getMessage());
442
		}
443
	}
444

  
445
	/**
446
	 * Take input from the user in an HTTP request about an property to be
447
	 * changed and update the metacat property file with that new value if it
448
	 * has changed from the value that was originally set.
449
	 * 
450
	 * @param request
451
	 *            that was generated by the user
452
	 * @param response
453
	 *            to send output back to the user
454
	 * @param propertyName
455
	 *            the name of the property to be checked and set
456
	 */
457
	public static void checkAndSetProperty(HttpServletRequest request, String skinName,
458
			String propertyName) throws GeneralPropertyException {
459
		String newValue = request.getParameter(skinName + "." + propertyName);
460
		checkAndSetProperty(newValue, skinName, propertyName);
461
	}
462

  
463
	/**
464
	 * Check user input against existing value and update the metacat property
465
	 * file with that new value if it has changed from the value that was
466
	 * originally set.
467
	 * 
468
	 * @param newValue
469
	 *            the value that was returned by the form
470
	 * @param skinname
471
	 *            the skin that we are checking
472
	 * @param propertyName
473
	 *            the name of the property to be checked and set
474
	 */
475
	public static void checkAndSetProperty(String newValue, String skinName,
476
			String propertyName) throws GeneralPropertyException {
477
		String oldValue = SkinPropertyService.getProperty(skinName, propertyName);
478
		if (newValue != null && !newValue.equals(oldValue)) {
479
			SkinPropertyService.setPropertyNoPersist(skinName, propertyName, newValue);
480
		}
481
	}
482

  
483
	/**
484
	 * Reports whether the metacat configuration utility should be run. Returns
485
	 * false if -- dev.runConfiguration=false and -- backup properties file
486
	 * exists Note that dev.runConfiguration should only be set to false when
487
	 * reinstalling the same version of the application in developement.
488
	 * 
489
	 * @return a boolean that is false if dev.runConfiguration is false and the
490
	 *         backup properties file exists.
491
	 */
492
	public static boolean bypassConfiguration() {
493
		boolean bypass = false;
494

  
495
		// We only want to go through the check once to see if we want to
496
		// bypass the configuration. We don't want to run through all of
497
		// this every time we hit metacat.
498
		if (bypassAlreadyChecked) {
499
			return bypass;
500
		}
501

  
502
		try {
503
			// check how dev.runConfiguration is set in metacat.properties
504
			String strRunConfiguration = PropertyService
505
					.getProperty("dev.runConfiguration");
506
			bypass = !(Boolean.parseBoolean(strRunConfiguration));
507

  
508
			// if the deb.runConfiguration is true, return false here.
509
			if (!bypass) {
510
				bypassAlreadyChecked = true;
511
				return false;
512
			}
513

  
514
			// the system is bypassing the configuration utility. We need to
515
			// get the backup properties and replace existing properties with
516
			// backup values. We do this for main and org properties.
517
			for (String skinName : skinNames) {
518
				SortedProperties backupProperties = getBackupProperties(skinName);
519
				Vector<String> backupPropertyNames = backupProperties.getPropertyNames();
520
				for (String backupPropertyName : backupPropertyNames) {
521
					String value = backupProperties.getProperty(backupPropertyName);
522
					backupProperties.setPropertyNoPersist(backupPropertyName, value);
523
				}
524
				backupProperties.store();
525
			}
526
		} catch (PropertyNotFoundException pnfe) {
527
			logMetacat.error("Could not find property: " + pnfe.getMessage());
528
		} catch (GeneralPropertyException gpe) {
529
			logMetacat.error("General property error: " + gpe.getMessage());
530
		}
531

  
532
		bypassAlreadyChecked = true;
533
		return bypass;
534
	}
535

  
536
}
537 0

  
src/edu/ucsb/nceas/metacat/workflow/WorkflowSchedulerServlet.java
1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements a metadata catalog as a java Servlet
4
 *  Copyright: 2006 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones, Dan Higgins, Jivka Bojilova, Chad Berkley, Matthew Perry
7
 *
8
 *   '$Author: daigle $'
9
 *     '$Date: 2009-08-07 10:35:18 -0700 (Fri, 07 Aug 2009) $'
10
 * '$Revision: 5018 $'
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
package edu.ucsb.nceas.metacat.workflow;
28

  
29
import java.io.IOException;
30
import java.io.PrintWriter;
31
import java.sql.SQLException;
32
import java.util.Enumeration;
33
import java.util.Hashtable;
34
import java.util.Timer;
35

  
36
import javax.servlet.ServletConfig;
37
import javax.servlet.ServletContext;
38
import javax.servlet.ServletException;
39
import javax.servlet.http.HttpServlet;
40
import javax.servlet.http.HttpServletRequest;
41
import javax.servlet.http.HttpServletResponse;
42
import javax.servlet.http.HttpSession;
43

  
44
import org.apache.log4j.Logger;
45
import org.apache.log4j.PropertyConfigurator;
46

  
47
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
48
import edu.ucsb.nceas.metacat.scheduler.SchedulerService;
49
import edu.ucsb.nceas.metacat.service.PropertyService;
50
import edu.ucsb.nceas.metacat.service.ServiceService;
51
import edu.ucsb.nceas.metacat.service.SessionService;
52
import edu.ucsb.nceas.metacat.shared.BaseException;
53
import edu.ucsb.nceas.metacat.shared.ServiceException;
54
import edu.ucsb.nceas.metacat.util.ErrorSendingErrorException;
55
import edu.ucsb.nceas.metacat.util.RequestUtil;
56
import edu.ucsb.nceas.metacat.util.ResponseUtil;
57
import edu.ucsb.nceas.metacat.util.SessionData;
58
import edu.ucsb.nceas.metacat.workflow.WorkflowScheduler;
59

  
60
/**
61
 * A workflow scheduling server implemented as a Java Servlet
62
 *
63
 * Valid actions are:
64
 * 
65
 * action=scheduleWorkflow -- Schedule a workflow to be run.  Scheduling a workflow 
66
 *                            registers it with the scheduling engine and creates a row
67
 *                            in the scheduled_job table.  Note that this may be 
68
 *                            extracted into a separate servlet.
69
 *     delay -- The amount of time from now before the workflow should be run.  The 
70
 *              delay can be expressed in number of seconds, minutes, hours and days, 
71
 *              for instance 30s, 2h, etc.
72
 *     starttime -- The time that the workflow should first run.  If both are provided
73
 *                  this takes precedence over delay.  The time should be expressed as: 
74
 *                  MM/dd/yyyy HH:mm:ss with the timezone assumed to be that of the OS.
75
 *     endtime -- The time when the workflow should end. The time should be expressed as: 
76
 *                  MM/dd/yyyy HH:mm:ss with the timezone assumed to be that of the OS.
77
 *     intervalvalue -- The numeric value of the interval between runs
78
 *     intervalunit -- The unit of the interval between runs.  Can be s, m, h, d for 
79
 *                     seconds, minutes, hours and days respectively
80
 *     workflowid -- The lsid of the workflow that we want to schedule.  This workflow
81
 *                   must already exist in the database.
82
 *     karid -- The karid for the workflow that we want to schedule.
83
 *     workflowname -- The name of the workflow.
84
 *     forwardto -- If provided, forward to this page when processing is done.
85
 *     qformat -- If provided, render results using the stylesheets associated with
86
 *                this skin.  Default is xml.
87
 * action=unscheduleWorkflow -- Unschedule a workflow.  Unscheduling a workflow 
88
 *                            removes it from the scheduling engine and changes the 
89
 *                            status in the scheduled_job table to " unscheduled.  Note 
90
 *                            that this may be extracted into a separate servlet.
91
 *     workflowjobid -- The job ID for the workflow run that we want to unschedule.  This
92
 *                      is held in the database as scheduled_job.name
93
 *     forwardto -- If provided, forward to this page when processing is done.
94
 *     qformat -- If provided, render results using the stylesheets associated with
95
 *                this skin.  Default is xml.
96
 * action=rescheduleWorkflow -- Unschedule a workflow.  Rescheduling a workflow 
97
 *                            registers it with the scheduling engine and changes the 
98
 *                            status in the scheduled_job table to " scheduled.  Note 
99
 *                            that this may be extracted into a separate servlet.
100
 *     workflowjobid -- The job ID for the workflow run that we want to reschedule.  This
101
 *                      is held in the database as scheduled_job.name
102
 *     forwardto -- If provided, forward to this page when processing is done.
103
 *     qformat -- If provided, render results using the stylesheets associated with
104
 *                this skin.  Default is xml.
105
 * action=deleteScheduledWorkflow -- Delete a workflow.  Deleting a workflow 
106
 *                            removes it from the scheduling engine and changes the 
107
 *                            status in the scheduled_job table to " deleted.  Note 
108
 *                            that this may be extracted into a separate servlet.
109
 *     workflowjobid -- The job ID for the workflow run that we want to delete.  This
110
 *                      is held in the database as scheduled_job.name
111
 *     forwardto -- If provided, forward to this page when processing is done.
112
 *     qformat -- If provided, render results using the stylesheets associated with
113
 *                this skin.  Default is xml.
114
 *     
115
 */
116
public class WorkflowSchedulerServlet extends HttpServlet {
117

  
118
	/**
119
	 * 
120
	 */
121
	private static final long serialVersionUID = 1L;
122

  
123
	private Timer timer = null;
124
    
125
    // Constants -- these should be final in a servlet
126
    private static String LOG_CONFIG_NAME = null;
127
    
128
    /**
129
     * Initialize the servlet by creating appropriate database connections
130
     */
131
    public void init(ServletConfig config) throws ServletException {
132
    	Logger logMetacat = Logger.getLogger(WorkflowSchedulerServlet.class);
133
    	try {
134
    		
135
            super.init(config);
136
            
137
            ServletContext context = config.getServletContext();
138
            
139
            ServiceService serviceService = ServiceService.getInstance(context);
140
            logMetacat.debug("ServiceService singleton created " + serviceService);
141
            
142
            // Initialize the properties file
143
            String dirPath = ServiceService.getRealConfigDir();
144
            
145
            LOG_CONFIG_NAME = dirPath + "/log4j.properties";
146
            PropertyConfigurator.configureAndWatch(LOG_CONFIG_NAME);
147
            
148
            // Register preliminary services
149
            ServiceService.registerService("PropertyService", PropertyService.getInstance());
150
            ServiceService.registerService("SessionService", SessionService.getInstance()); 
151
            ServiceService.registerService("SchedulerService", SchedulerService.getInstance());
152
            
153
    	} catch (ServiceException se) {
154
        	String errorMessage = 
155
        		"Service problem while intializing WorkflowScheduler Servlet: " + se.getMessage();
156
            logMetacat.error(errorMessage);
157
            throw new ServletException(errorMessage);
158
        }
159
    }
160
    
161
    /**
162
	 * Close all db connections from the pool
163
	 */
164
    public void destroy() {
165
    	Logger logMetacat = Logger.getLogger(WorkflowSchedulerServlet.class);
166
    	
167
    	ServiceService.stopAllServices();
168
    	
169
        // Close all db connection
170
        logMetacat.warn("Destroying WorkflowSchedulerServlet");
171
        timer.cancel();
172
//        IndexingQueue.getInstance().setMetacatRunning(false);
173
        DBConnectionPool.release();
174
    }
175
    
176
    /** Handle "GET" method requests from HTTP clients */
177
    public void doGet(HttpServletRequest request, HttpServletResponse response)
178
    throws ServletException, IOException {
179
        
180
        // Process the data and send back the response
181
        handleGetOrPost(request, response);
182
    }
183
    
184
    /** Handle "POST" method requests from HTTP clients */
185
    public void doPost(HttpServletRequest request, HttpServletResponse response)
186
    throws ServletException, IOException {
187
        
188
        // Process the data and send back the response
189
        handleGetOrPost(request, response);
190
    }
191
    
192
    /**
193
	 * Control servlet response depending on the action parameter specified
194
	 */
195
	private void handleGetOrPost(HttpServletRequest request, HttpServletResponse response)
196
			throws ServletException, IOException {
197
		Logger logMetacat = Logger.getLogger(WorkflowSchedulerServlet.class);
198

  
199
		// Update the last update time for this user if they are not new
200
		HttpSession httpSession = request.getSession(false);
201
		if (httpSession != null) {
202
			SessionService.touchSession(httpSession.getId());
203
		}
204

  
205
		/*
206
		 * logMetacat.debug("Connection pool size: "
207
		 * +connPool.getSizeOfDBConnectionPool(),10); logMetacat.debug("Free
208
		 * DBConnection number: "
209
		 */
210
		// If all DBConnection in the pool are free and DBConnection pool
211
		// size is greater than initial value, shrink the connection pool
212
		// size to initial value
213
		DBConnectionPool.shrinkDBConnectionPoolSize();
214

  
215
		// Debug message to print out the method which have a busy DBConnection
216
		try {
217
			DBConnectionPool pool = DBConnectionPool.getInstance();
218
			pool.printMethodNameHavingBusyDBConnection();
219
		} catch (SQLException e) {
220
			logMetacat.error("Error in WorkflowSchedulerServlet.handleGetOrPost: "
221
					+ e.getMessage());
222
			e.printStackTrace();
223
		}
224

  
225
		try {
226

  
227
			String name = null;
228
			String[] value = null;
229
			Hashtable<String, String[]> params = new Hashtable<String, String[]>();
230

  
231
			Enumeration<String> paramlist = (Enumeration<String>) request
232
					.getParameterNames();
233
			while (paramlist.hasMoreElements()) {
234

  
235
				name = paramlist.nextElement();
236
				value = request.getParameterValues(name);
237

  
238
				params.put(name, value);
239
			}
240

  
241
			// handle param is emptpy
242
			if (params.isEmpty() || params == null) {
243
				return;
244
			}
245

  
246
			// if the user clicked on the input images, decode which image
247
			// was clicked then set the action.
248
			if (params.get("action") == null) {
249
				PrintWriter out = response.getWriter();
250
				response.setContentType("text/xml");
251
				out.println("<?xml version=\"1.0\"?>");
252
				out.println("<error>");
253
				out.println("Action not specified");
254
				out.println("</error>");
255
				out.close();
256
				return;
257
			}
258

  
259
			String action = (params.get("action"))[0];
260
			logMetacat.info("Action is: " + action);
261

  
262
			// This block handles session management for the servlet
263
			// by looking up the current session information for all actions
264
			// other than "login" and "logout"
265
			String userName = null;
266
			String[] groupNames = null;
267
			name = null;
268

  
269
			// handle login action
270
			if (action.equals("login")) {
271
				// PrintWriter out = response.getWriter();
272
				// handleLoginAction(out, params, request, response);
273
				// out.close();
274

  
275
				// handle logout action
276
			} else if (action.equals("logout")) {
277
				// PrintWriter out = response.getWriter();
278
				// handleLogoutAction(out, params, request, response);
279
				// out.close();
280

  
281
				// handle shrink DBConnection request
282
			} else if (action.equals("shrink")) {
283
				PrintWriter out = response.getWriter();
284
				boolean success = false;
285
				// If all DBConnection in the pool are free and DBConnection
286
				// pool
287
				// size is greater than initial value, shrink the connection
288
				// pool
289
				// size to initial value
290
				success = DBConnectionPool.shrinkConnectionPoolSize();
291
				if (success) {
292
					// if successfully shrink the pool size to initial value
293
					out.println("DBConnection Pool shrunk successfully.");
294
				}// if
295
				else {
296
					out.println("DBConnection pool not shrunk successfully.");
297
				}
298
				// close out put
299
				out.close();
300

  
301
				// aware of session expiration on every request
302
			} else {
303
				SessionData sessionData = RequestUtil.getSessionData(request);
304

  
305
				userName = sessionData.getUserName();
306
				// password = sessionData.getPassword();
307
				groupNames = sessionData.getGroupNames();
308
				// sessionId = sessionData.getId();
309

  
310
				logMetacat.info("The user is : " + userName);
311
			}
312

  
313
			if (action.equals("refreshServices")) {
314
				// TODO MCD this interface is for testing. It should go through
315
				// a
316
				// ServiceService class and only work for an admin user. Move to
317
				// the
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff