Project

General

Profile

1 4080 daigle
/**
2
 *  '$RCSfile$'
3
 *    Purpose:  A Class that implements skins configuration methods
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.admin;
28
29
import java.io.IOException;
30
import java.util.HashMap;
31 4321 daigle
import java.util.Set;
32 4080 daigle
import java.util.Vector;
33
34
import javax.servlet.ServletException;
35
import javax.servlet.http.HttpServletRequest;
36
import javax.servlet.http.HttpServletResponse;
37
38
import org.apache.log4j.Logger;
39
40
import edu.ucsb.nceas.metacat.service.PropertyService;
41
import edu.ucsb.nceas.metacat.service.SkinPropertyService;
42
import edu.ucsb.nceas.metacat.util.RequestUtil;
43
import edu.ucsb.nceas.metacat.util.SkinUtil;
44 4106 daigle
import edu.ucsb.nceas.utilities.FileUtil;
45 4321 daigle
import edu.ucsb.nceas.utilities.MetaDataProperty;
46 4080 daigle
import edu.ucsb.nceas.utilities.PropertiesMetaData;
47
import edu.ucsb.nceas.utilities.GeneralPropertyException;
48 4106 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
49 4080 daigle
import edu.ucsb.nceas.utilities.SortedProperties;
50
51
/**
52
 * Control the display of the skins configuration page and the processing
53
 * of the configuration values.
54
 */
55 5027 daigle
public class SkinsAdmin extends MetacatAdmin {
56 4080 daigle
57
	private static SkinsAdmin skinsAdmin = null;
58
	private static Logger logMetacat = Logger.getLogger(SkinsAdmin.class);
59
60
	/**
61
	 * private constructor since this is a singleton
62
	 */
63
	private SkinsAdmin() {}
64
65
	/**
66
	 * Get the single instance of the MetaCatConfig.
67
	 *
68
	 * @return the single instance of MetaCatConfig
69
	 */
70
	public static SkinsAdmin getInstance() {
71
		if (skinsAdmin == null) {
72
			skinsAdmin = new SkinsAdmin();
73
		}
74
		return skinsAdmin;
75
	}
76
77
	/**
78
	 * Handle configuration of the application the first time that Metacat
79
	 * starts or when it is explicitly called in the url. Collect necessary
80
	 * configuration information from the administrator.
81
	 *
82
	 * @param request
83
	 *            the http request information
84
	 * @param response
85
	 *            the http response to be sent back to the client
86
	 */
87
	public void configureSkins(HttpServletRequest request, HttpServletResponse response)
88
			throws AdminException {
89
90
		String processForm = request.getParameter("processForm");
91
		String formErrors = (String) request.getAttribute("formErrors");
92
93
		if (processForm == null || !processForm.equals("true") || formErrors != null) {
94
			// The servlet configuration parameters have not been set, or there
95
			// were form errors on the last attempt to configure, so redirect to
96
			// the web form for configuring metacat
97
			try {
98
				Vector<String> skinNames = SkinUtil.getSkinNames();
99
				String defaultStyle =
100
					PropertyService.getProperty("application.default-style");
101
102
				request.setAttribute("defaultStyle", defaultStyle);
103
104
				// add skin metadata to the request.  The configuration form
105
				// will use this data to determine what the configuration
106
				// fields should look like.
107
				HashMap<String, PropertiesMetaData> propertyMetaData =
108
					SkinPropertyService.getMetaData();
109
				request.setAttribute("metadataMap", propertyMetaData);
110
111
				// get a deep copy of properties so we can override with
112
				// backup values without changing originals
113
				HashMap<String, SortedProperties> originalPropertyMap =
114
					SkinPropertyService.getProperties();
115
				HashMap<String, HashMap<String, String>> localPropertyMap =
116
					new HashMap<String, HashMap<String, String>>();
117
				HashMap<String, SortedProperties> backupPropertiesMap =
118
					SkinPropertyService.getBackupProperties();
119 4762 daigle
120
				// Just in case a skin is not configured correctly, we will want to remove
121
				// it from the skins list
122
				Vector<String> removeSkins = new Vector<String>();
123 4080 daigle
124
				for (String skinName : skinNames) {
125
					// first, get a deep copy of this skin's properties
126
127
					SortedProperties skinProperties = originalPropertyMap.get(skinName);
128
					if (skinProperties == null) {
129 4762 daigle
						logMetacat.error("Could not find properties for skin: " + skinName);
130
						removeSkins.add(skinName);
131
						continue;
132 4080 daigle
					}
133
134
					HashMap<String, String> originalSkinProperties =
135
						skinProperties.getProperties();
136
					HashMap<String, String> localSkinProperties =
137
						new HashMap<String, String>(originalSkinProperties);
138
139
					// now get the backup properties for this skin.  Overwrite the
140
					// properties with backup properties.  This allows previously
141
					// set properties to be preserved in an application upgrade.
142
					SortedProperties backupProperties = backupPropertiesMap.get(skinName);
143 4632 daigle
					if (backupProperties == null) {
144
						logMetacat.warn("Could not find backup properties for skin: "
145
								+ skinName);
146
					} else {
147
						for (String propertyName : backupProperties.getPropertyNames()) {
148
							localSkinProperties.put(propertyName,
149
									backupProperties.getProperty(propertyName));
150
						}
151 4080 daigle
					}
152
153
					localPropertyMap.put(skinName, localSkinProperties);
154 4762 daigle
				}
155
156
				// If there are any skins for which we could not get properties, remove them from
157
				// the skins list we will send to the configuration page.
158
				for (String skinName : removeSkins) {
159
					skinNames.remove(skinName);
160
				}
161
162
				request.setAttribute("skinNameList", skinNames);
163 4080 daigle
				request.setAttribute("skinProperties", localPropertyMap);
164
165
				// Forward the request to the JSP page
166
				RequestUtil.forwardRequest(request, response,
167 5027 daigle
						"/admin/skins-configuration.jsp", null);
168 4080 daigle
169
			} catch (GeneralPropertyException pnfe) {
170
				throw new AdminException("Problem getting property while initializing "
171
						+ "skins properties page: " + pnfe.getMessage());
172
			} catch (IOException ioe) {
173
				throw new AdminException("IO problem while initializing "
174
						+ "skins properties page:" + ioe.getMessage());
175
			} catch (ServletException se) {
176
				throw new AdminException("problem forwarding request while "
177
						+ "initializing skins properties page: " + se.getMessage());
178
			}
179
180
		} else {
181
			// The configuration form is being submitted and needs to be
182
			// processed.
183
			Vector<String> processingSuccess = new Vector<String>();
184
			Vector<String> processingErrors = new Vector<String>();
185
			Vector<String> validationErrors = new Vector<String>();
186
187
			try {
188 4608 daigle
				//Default style is global.
189
				String defaultStyle = request.getParameter("application.default-style");
190
				PropertyService.setProperty("application.default-style", defaultStyle);
191
192 4106 daigle
				// For each skin property, check if it is changed and save it
193
				Vector<String> skinNames = SkinUtil.getSkinNames();
194
				for (String skinName : skinNames) {
195 4321 daigle
					PropertiesMetaData skinMetaData =
196
						SkinPropertyService.getMetaData(skinName);
197 4762 daigle
198
					if (skinMetaData == null) {
199
						logMetacat.error("Could not find metadata for skin: " + skinName);
200
						continue;
201
					}
202
203 4321 daigle
					Set<String> metaDataKeySet = skinMetaData.getKeys();
204
					for (String metaDataKey : metaDataKeySet) {
205
						MetaDataProperty metaDataProperty =
206
							skinMetaData.getProperties().get(metaDataKey);
207
						String fieldType = metaDataProperty.getFieldType();
208
						String newValue = request.getParameter(skinName + "." + metaDataKey);
209 4766 daigle
						if (fieldType != null && fieldType.equals(MetaDataProperty.CHECKBOX_TYPE)) {
210 4321 daigle
							if (newValue != null && newValue.equals("on")) {
211
								SkinPropertyService.checkAndSetProperty("true", skinName, metaDataKey);
212
							} else {
213
								SkinPropertyService.checkAndSetProperty("false", skinName, metaDataKey);
214
							}
215
						} else {
216
							SkinPropertyService.checkAndSetProperty(request, skinName, metaDataKey);
217
						}
218 4106 daigle
					}
219
220
					// we need to write the options from memory to the
221
					// properties file
222
					SkinPropertyService.persistProperties(skinName);
223
224
					// Validate that the options provided are legitimate. Note
225
					// that we've allowed them to persist their entries. As of
226
					// this point there is no other easy way to go back to the
227
					// configure form and preserve their entries.
228
					validationErrors.addAll(validateOptions(request, skinName));
229
230 4707 daigle
//					// Try to create backup directories if necessary.
231
//					String backupDir = PropertyService.getBackupDir();
232
//					try {
233
//						FileUtil.createDirectory(backupDir);
234
//					} catch (IOException ioe) {
235
//						String errorString = "Could not create directory: " + backupDir +
236
//							" : " + ioe.getMessage();
237
//						logMetacat.error(errorString);
238
//						validationErrors.add(errorString);
239
//					}
240 4106 daigle
241
					// write the backup properties to a location outside the
242
					// application directories so they will be available after
243
					// the next upgrade
244 4707 daigle
					SkinPropertyService.persistBackupProperties(skinName);
245 4106 daigle
				}
246
247
				// Now that the options have been set, change the
248
				// 'skinsConfigured'
249
				// option to 'true' so that normal metacat requests will go
250
				// through
251 4080 daigle
				PropertyService.setProperty("configutil.skinsConfigured",
252
						PropertyService.CONFIGURED);
253 4084 daigle
			} catch (GeneralPropertyException gpe) {
254
				String errorMessage = "problem setting property while processing skins "
255
						+ "properties page: " + gpe.getMessage();
256 4080 daigle
				logMetacat.error(errorMessage);
257
				processingErrors.add(errorMessage);
258 4106 daigle
			} catch (IOException ioe) {
259
				String errorMessage = "IO problem while processing skins "
260
						+ "properties page: " + ioe.getMessage();
261
				logMetacat.error(errorMessage);
262
				processingErrors.add(errorMessage);
263 4080 daigle
			}
264
			try {
265
				if (validationErrors.size() > 0 || processingErrors.size() > 0) {
266
					RequestUtil.clearRequestMessages(request);
267
					RequestUtil.setRequestFormErrors(request, validationErrors);
268
					RequestUtil.setRequestErrors(request, processingErrors);
269 5027 daigle
					RequestUtil.forwardRequest(request, response, "/admin", null);
270 4080 daigle
				} else {
271
					// Now that the options have been set, change the
272
					// 'skinsConfigured' option to 'true'
273
					PropertyService.setProperty("configutil.skinsConfigured",
274
							PropertyService.CONFIGURED);
275
276
					// Reload the main metacat configuration page
277
					processingSuccess.add("Skins successfully configured");
278
					RequestUtil.clearRequestMessages(request);
279
					RequestUtil.setRequestSuccess(request, processingSuccess);
280
					RequestUtil.forwardRequest(request, response,
281 5027 daigle
							"/admin?configureType=configure&processForm=false", null);
282 4080 daigle
				}
283
			} catch (ServletException se) {
284
				throw new AdminException("problem forwarding request while "
285
						+ "processing skins properties page: " + se.getMessage());
286
			} catch (IOException ioe) {
287
				throw new AdminException("IO problem while processing skins "
288
						+ "properties page: " + ioe.getMessage());
289 4084 daigle
			} catch (GeneralPropertyException gpe) {
290
				String errorMessage = "problem setting property while processing skins "
291
						+ "properties page: " + gpe.getMessage();
292
				logMetacat.error(errorMessage);
293
				processingErrors.add(errorMessage);
294 4080 daigle
			}
295
		}
296
	}
297
298 4106 daigle
	protected Vector<String> validateOptions(HttpServletRequest request) {
299
		Vector<String> errorVector = new Vector<String>();
300
		Vector<String> skinNames = null;
301
		try {
302
			skinNames = SkinUtil.getSkinNames();
303
		} catch (PropertyNotFoundException pnfe) {
304
			errorVector.add("Could not find skin names: " + pnfe.getMessage());
305
		}
306
307
		for (String skinName : skinNames) {
308
			errorVector.addAll(validateOptions(request, skinName));
309
		}
310
311
		return errorVector;
312
	}
313
314 4080 daigle
	/**
315
	 * Validate the most important configuration options submitted by the user.
316
	 *
317
	 * @return a vector holding error message for any fields that fail
318
	 *         validation.
319
	 */
320 4106 daigle
	protected Vector<String> validateOptions(HttpServletRequest request, String skinName) {
321 4080 daigle
		Vector<String> errorVector = new Vector<String>();
322
323
		//TODO MCD validate options.
324
325
		return errorVector;
326
	}
327
}