001: /*
002: * Copyright (c) 2001 - 2005 ivata limited.
003: * All rights reserved.
004: * -----------------------------------------------------------------------------
005: * ivata groupware may be redistributed under the GNU General Public
006: * License as published by the Free Software Foundation;
007: * version 2 of the License.
008: *
009: * These programs are free software; you can redistribute them and/or
010: * modify them under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; version 2 of the License.
012: *
013: * These programs are distributed in the hope that they will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: *
017: * See the GNU General Public License in the file LICENSE.txt for more
018: * details.
019: *
020: * If you would like a copy of the GNU General Public License write to
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place - Suite 330
024: * Boston, MA 02111-1307, USA.
025: *
026: *
027: * To arrange commercial support and licensing, contact ivata at
028: * http://www.ivata.com/contact.jsp
029: * -----------------------------------------------------------------------------
030: * $Log: SettingAction.java,v $
031: * Revision 1.4 2005/10/11 18:57:17 colinmacleod
032: * Fixed some checkstyle and javadoc issues.
033: *
034: * Revision 1.3 2005/10/03 10:21:15 colinmacleod
035: * Fixed some style and javadoc issues.
036: *
037: * Revision 1.2 2005/10/02 14:08:59 colinmacleod
038: * Added/improved log4j logging.
039: *
040: * Revision 1.1 2005/09/29 13:06:05 colinmacleod
041: * First version of setting subproject.
042: * Existing classes restructured, new setting user interface created.
043: * Flexible XML UI configuration makes it easy to reuse the same web pages in
044: * other projects.
045: * Web files work as stand-alone webapp for testing.
046: *
047: * Revision 1.18 2003/03/26 16:52:52 peter
048: * when there was no user setting before and only the system one was changed,
049: * new user setting not created
050: *
051: * Revision 1.17 2003/03/04 14:19:35 colin
052: * added emailDefaultFormat
053: *
054: * Revision 1.16 2003/03/03 16:57:08 colin
055: * converted localization to automatic paths
056: * added labels
057: * added mandatory fieldName attribute
058: *
059: * Revision 1.15 2003/02/25 17:00:07 peter
060: * added parent refreshing on close
061: *
062: * Revision 1.14 2003/02/24 18:56:15 colin
063: * added to admin
064: *
065: * Revision 1.13 2003/02/19 18:20:46 peter
066: * fixed validation and input format doubling
067: *
068: * Revision 1.10 2003/02/13 17:24:18 peter
069: * added new tabs: controls, notification
070: *
071: * Revision 1.9 2003/02/12 17:25:34 peter
072: * added library and notification tab
073: *
074: * Revision 1.8 2003/02/12 14:12:50 peter
075: * rights do work
076: *
077: * Revision 1.5 2003/02/05 18:15:07 peter
078: * works on validation, and changed to Map backed form
079: */
080: package com.ivata.groupware.admin.setting.struts;
081:
082: import java.io.InputStream;
083: import java.util.Arrays;
084: import java.util.Iterator;
085: import java.util.List;
086: import java.util.Locale;
087: import java.util.Vector;
088:
089: import javax.servlet.ServletContext;
090: import javax.servlet.http.HttpServletRequest;
091: import javax.servlet.http.HttpServletResponse;
092: import javax.servlet.http.HttpSession;
093:
094: import org.apache.log4j.Logger;
095: import org.apache.struts.Globals;
096: import org.apache.struts.action.ActionForm;
097: import org.apache.struts.action.ActionMapping;
098: import org.apache.struts.util.LabelValueBean;
099: import org.dom4j.Document;
100: import org.dom4j.DocumentException;
101: import org.dom4j.Element;
102: import org.dom4j.io.SAXReader;
103: import org.sourceforge.clientsession.ClientSession;
104: import org.xml.sax.InputSource;
105:
106: import com.ivata.groupware.admin.security.server.SecuritySession;
107: import com.ivata.groupware.admin.security.user.UserDO;
108: import com.ivata.groupware.admin.setting.SettingConstants;
109: import com.ivata.groupware.admin.setting.Settings;
110: import com.ivata.mask.MaskFactory;
111: import com.ivata.mask.util.StringHandling;
112: import com.ivata.mask.util.SystemException;
113: import com.ivata.mask.web.struts.MaskAction;
114: import com.ivata.mask.web.struts.MaskAuthenticator;
115: import com.ivata.mask.web.struts.util.MaskMessageResources;
116:
117: /**
118: * <p><code>Action</code> invoked whenever the user setting page is submitted.
119: * </p>
120: *
121: * <p>
122: * This action lets users modify their personal preferences, or those which
123: * affect the system as a whole (if they have sufficient user rights.
124: * </p>
125: *
126: * <p>
127: * There is a file called <code>ivataSettings.xml</code> which defines which
128: * system settings will be available to users and administrators, and stores
129: * how the settings are displayed. This file is normally located in the
130: * <code>WEB-INF</code> directory of the webapp.
131: * </p>
132: *
133: * @since ivata groupware 1.0 (2003-01-27)
134: * @author Peter Illes
135: * @author Colin MacLeod
136: * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
137: * @version $Revision: 1.4 $
138: */
139: public class SettingAction extends MaskAction {
140: /**
141: * Logger for this class.
142: */
143: private static final Logger logger = Logger
144: .getLogger(SettingAction.class);
145:
146: /**
147: * <p>
148: * Specifies the path to the settings config file, relative to the webapp
149: * root.
150: * </p>
151: */
152: public static final String SETTINGS_FILE_NAME = "/WEB-INF/ivataSettings.xml";
153: /**
154: * Date patterns which are simplified by <code>simplifyDateFormat</code>.
155: */
156: private static final String[] SIMPLIFY_PATTERNS = new String[] {
157: "MM", "dd", "hh", "KK", "HH", "kk", "mm", "ss" };
158:
159: /**
160: * <copyDoc>Refer to {@link SettingAction#SettingAction}.</copyDoc>
161: */
162: private Settings settings;
163:
164: /**
165: * Constructor. Normally called from <code>PicoContainer</code>.
166: *
167: * @param settingsParam Used to retrieve and set system settings.
168: * @param maskFactoryParam {@inheritDoc}
169: * @param authenticatorParam {@inheritDoc}
170: */
171: public SettingAction(final Settings settingsParam,
172: final MaskFactory maskFactoryParam,
173: final MaskAuthenticator authenticatorParam) {
174: super (maskFactoryParam, authenticatorParam);
175: this .settings = settingsParam;
176: }
177:
178: /**
179: * {@inheritDoc}
180: *
181: * @param mappingParam {@inheritDoc}
182: * @param formParam {@inheritDoc}
183: * @param requestParam {@inheritDoc}
184: * @param responseParam {@inheritDoc}
185: * @param sessionParam {@inheritDoc}
186: * @param clientSession {@inheritDoc}
187: * @throws SystemException {@inheritDoc}
188: */
189: public void clear(final ActionMapping mappingParam,
190: final ActionForm formParam,
191: final HttpServletRequest requestParam,
192: final HttpServletResponse responseParam,
193: final HttpSession sessionParam,
194: final ClientSession clientSession) throws SystemException {
195: if (logger.isDebugEnabled()) {
196: logger.debug("clear(ActionMapping mappingParam = "
197: + mappingParam + ", ActionForm formParam = "
198: + formParam
199: + ", HttpServletRequest requestParam = "
200: + requestParam
201: + ", HttpServletResponse responseParam = "
202: + responseParam + ", HttpSession sessionParam = "
203: + sessionParam + ", ClientSession clientSession = "
204: + clientSession + ") - start");
205: }
206:
207: HttpSession session = requestParam.getSession();
208: session.removeAttribute("settingTabActiveTab");
209: session.removeAttribute("settingForm");
210:
211: if (logger.isDebugEnabled()) {
212: logger.debug("clear - end");
213: }
214: }
215:
216: /**
217: * {@inheritDoc}
218: *
219: * @param mappingParam {@inheritDoc}
220: * @param formParam {@inheritDoc}
221: * @param requestParam {@inheritDoc}
222: * @param responseParam {@inheritDoc}
223: * @param sessionParam {@inheritDoc}
224: * @param clientSession {@inheritDoc}
225: * @return "noSettings" if there are no settings the user can
226: * change, otherwise <code>null</code>.
227: * @throws SystemException If the settings cannot be read.
228: */
229: public String execute(final ActionMapping mappingParam,
230: final ActionForm formParam,
231: final HttpServletRequest requestParam,
232: final HttpServletResponse responseParam,
233: final HttpSession sessionParam,
234: final ClientSession clientSession) throws SystemException {
235: if (logger.isDebugEnabled()) {
236: logger.debug("execute(ActionMapping mappingParam = "
237: + mappingParam + ", ActionForm formParam = "
238: + formParam
239: + ", HttpServletRequest requestParam = "
240: + requestParam
241: + ", HttpServletResponse responseParam = "
242: + responseParam + ", HttpSession sessionParam = "
243: + sessionParam + ", ClientSession clientSession = "
244: + clientSession + ") - start");
245: }
246:
247: HttpSession session = requestParam.getSession();
248: SettingForm settingForm = (SettingForm) formParam;
249:
250: SecuritySession securitySession = (SecuritySession) session
251: .getAttribute("securitySession");
252: assert (securitySession != null);
253: UserDO user = securitySession.getUser();
254: assert (user != null);
255:
256: String activeTabKey = StringHandling.getNotNull(settingForm
257: .getSettingTabActiveTabKey(), "");
258:
259: List tabKeys = settingForm.getTabKeys();
260: assert (tabKeys != null);
261:
262: // these two Lists will contain setting names for individual tabs
263:
264: Locale locale = (Locale) session
265: .getAttribute(Globals.LOCALE_KEY);
266: assert (locale != null);
267:
268: // very important, the administrator rights:
269: settingForm.setAdministrator(user.isAdministrator());
270:
271: // the jsp will start in user mode
272: if (StringHandling.isNullOrEmpty(settingForm.getSettingArea())) {
273: settingForm.setSettingArea("user");
274: }
275:
276: // if this is the first time, read in the configuration
277: if (settingForm.getUserSettingTabs().isEmpty()) {
278: readConfiguration(securitySession, settingForm, locale);
279: }
280:
281: // when there's no tab with settings to show, go to page with
282: // this info and a close button
283: if (tabKeys.isEmpty()) {
284: clear(mappingParam, formParam, requestParam, responseParam,
285: sessionParam, clientSession);
286:
287: if (logger.isDebugEnabled()) {
288: logger
289: .debug("execute - end - return value = noSettings");
290: }
291: return "noSettings";
292: }
293:
294: // default the included page from the tab key name
295: if (StringHandling.isNullOrEmpty(activeTabKey)) {
296: activeTabKey = (String) tabKeys.get(0);
297: settingForm.setSettingTabActiveTabKey(activeTabKey);
298: settingForm.setSettingTabActiveTab(new Integer(0));
299: }
300:
301: if (logger.isDebugEnabled()) {
302: logger.debug("execute - end - return value = " + null);
303: }
304: return null;
305: }
306:
307: /**
308: * {@inheritDoc}
309: *
310: * @param mappingParam {@inheritDoc}
311: * @param formParam {@inheritDoc}
312: * @param requestParam {@inheritDoc}
313: * @param responseParam {@inheritDoc}
314: * @param sessionParam {@inheritDoc}
315: * @param clientSession {@inheritDoc}
316: * @param defaultForwardParam {@inheritDoc}
317: * @return Always returns <code>null</code>.
318: * @throws SystemException If there is an error writing the settings.
319: */
320: public String onConfirm(final ActionMapping mappingParam,
321: final ActionForm formParam,
322: final HttpServletRequest requestParam,
323: final HttpServletResponse responseParam,
324: final HttpSession sessionParam,
325: final ClientSession clientSession,
326: final String defaultForwardParam) throws SystemException {
327: if (logger.isDebugEnabled()) {
328: logger.debug("onConfirm(ActionMapping mappingParam = "
329: + mappingParam + ", ActionForm formParam = "
330: + formParam
331: + ", HttpServletRequest requestParam = "
332: + requestParam
333: + ", HttpServletResponse responseParam = "
334: + responseParam + ", HttpSession sessionParam = "
335: + sessionParam + ", ClientSession clientSession = "
336: + clientSession + ", String defaultForwardParam = "
337: + defaultForwardParam + ") - start");
338: }
339:
340: SettingForm settingForm = (SettingForm) formParam;
341:
342: // store the settings, also manage revert-to-system cases
343: saveSettings((SecuritySession) sessionParam
344: .getAttribute("securitySession"), settingForm);
345:
346: requestParam.setAttribute("refreshOpener", "1");
347:
348: if (logger.isDebugEnabled()) {
349: logger.debug("onConfirm - end - return value = " + null);
350: }
351: return null;
352: }
353:
354: /**
355: * Read the configuration in from the XML file, and populate the form with
356: * the settings.
357: *
358: * @param securitySessionParam
359: * Current security session - used for authentication/
360: * @param settingForm
361: * Valid form currently being processed.
362: * @param locale
363: * Used to process message resources for labels.
364: * @throws SystemException If the configuration cannot be read.
365: */
366: private void readConfiguration(
367: final SecuritySession securitySessionParam,
368: final SettingForm settingForm, final Locale locale)
369: throws SystemException {
370: if (logger.isInfoEnabled()) {
371: logger.info("Reading setting configuration.");
372: }
373: ServletContext context = servlet.getServletContext();
374: InputStream inputStream = context
375: .getResourceAsStream(SETTINGS_FILE_NAME);
376: SAXReader reader = new SAXReader();
377: Document document;
378: try {
379: InputSource inputSource = new InputSource();
380: inputSource.setByteStream(inputStream);
381: document = reader.read(inputSource);
382: } catch (DocumentException e) {
383: logger
384: .error(
385: "readConfiguration(SecuritySession, SettingForm, Locale)",
386: e);
387: throw new SystemException(e);
388: }
389: readDocument(securitySessionParam, settingForm, locale,
390: document);
391: if (logger.isInfoEnabled()) {
392: logger.info("Finished setting configuration.");
393: }
394: }
395:
396: /**
397: * Read in a <em>dom4j</em> document containing user setting display
398: * preferences.
399: *
400: * @param securitySessionParam Used to authenticate the current user
401: * when retrieving settings values.
402: * @param settingForm Current setting form we are processing.
403: * @param locale Defines user's localization locale.
404: * @param document The <em>dom4j</em> document containing settings display
405: * preferences.
406: * @throws SystemException If the settings options cannot be read and
407: * parsed.
408: */
409: private void readDocument(
410: final SecuritySession securitySessionParam,
411: final SettingForm settingForm, final Locale locale,
412: final Document document) throws SystemException {
413: if (logger.isDebugEnabled()) {
414: logger
415: .debug("readDocument(SecuritySession securitySessionParam = "
416: + securitySessionParam
417: + ", SettingForm settingForm = "
418: + settingForm
419: + ", Locale locale = "
420: + locale
421: + ", Document document = "
422: + document + ") - start");
423: }
424:
425: // first clear all the lists from the form - we store:
426: // - the keys for the tab titles
427: List tabKeys = settingForm.getTabKeys();
428: assert (tabKeys != null);
429: tabKeys.clear();
430: // - a list of lists of user setting names
431: List userSettingTabs = settingForm.getUserSettingTabs();
432: assert (userSettingTabs != null);
433: userSettingTabs.clear();
434: // - a list of lists of system setting names
435: List systemSettingTabs = settingForm.getSystemSettingTabs();
436: assert (userSettingTabs != null);
437: userSettingTabs.clear();
438: // - a list of lists of all (user + system) setting names
439: List settingTabs = settingForm.getSettingTabs();
440: assert (settingTabs != null);
441: settingTabs.clear();
442:
443: // now go thro' the tabs in turn and start populating this stuff
444: List tabs = document.selectNodes("//settings/tab");
445: Iterator tabIterator = tabs.iterator();
446: String defaultBundle = document.getRootElement()
447: .attributeValue("defaultBundle");
448: if ("none".equals(defaultBundle)) {
449: defaultBundle = null;
450: }
451: while (tabIterator.hasNext()) {
452: Element tab = (Element) tabIterator.next();
453: String tabKey = tab.attributeValue("key");
454: if (tabKey == null) {
455: throw new SystemException(
456: "You must specify a 'key' attribute for each tab.");
457: }
458: tabKeys.add(tabKey);
459:
460: String[] systemUserName = new String[] { "user", "system" };
461: List[] systemUserTabList = new List[] { userSettingTabs,
462: systemSettingTabs };
463: // this list of lists is of both system and user names
464: List allNames = new Vector();
465: settingTabs.add(allNames);
466:
467: // under each tab is either user/system or both
468: for (int i = 0; i < systemUserName.length; i++) {
469: Element systemUser = tab.element(systemUserName[i]);
470: // these elements don't _have_ to be there; this means we just
471: // added an empty list (to keep both lists in sync)
472: if (systemUser == null) {
473: continue;
474: }
475: List names = readSystemOrUserSettings(
476: securitySessionParam, settingForm, locale,
477: systemUser, defaultBundle);
478: // this list of lists contains only system or user setting names
479: // (not both)
480: systemUserTabList[i].add(names);
481: allNames.addAll(names);
482: }
483: }
484:
485: if (logger.isDebugEnabled()) {
486: logger.debug("readDocument() - end");
487: }
488: }
489:
490: /**
491: * If a setting should be displayed as a choice field (HTML
492: * <code>select</code> tag), then it may contain a number of
493: * <code>option</code> tags defining the user choices. This method parses
494: * in one of those options.
495: *
496: * @param locale
497: * <copyDoc>Refer to {@link #getDocument}.</copyDoc>
498: * @param option The <em>dom4j</em> element containing a
499: * <code>option</code> tag to be processed.
500: * @param defaultBundle
501: * <copyDoc>Refer to {@link #getDocument}.</copyDoc>
502: * @return <code>LabelValueBean</code> containing the values from the
503: * <code>option</code> tag.
504: * @throws SystemException If the element cannot be parsed.
505: */
506: private LabelValueBean readOption(final Locale locale,
507: final Element option, final String defaultBundle)
508: throws SystemException {
509: if (logger.isDebugEnabled()) {
510: logger.debug("readOption(Locale locale = " + locale
511: + ", Element option = " + option
512: + ", String defaultBundle = " + defaultBundle
513: + ") - start");
514: }
515:
516: String bundle = option.attributeValue("bundle");
517: MaskMessageResources maskMessageResources = new MaskMessageResources(
518: locale, bundle, "");
519: if ("none".equals(bundle)) {
520: bundle = null;
521: } else if (bundle == null) {
522: bundle = defaultBundle;
523: }
524: String labelKey = option.attributeValue("labelKey");
525: String value = option.attributeValue("value");
526:
527: String label;
528: if (labelKey == null) {
529: label = value;
530: } else {
531: label = maskMessageResources.getMessage(labelKey,
532: (List) null);
533: }
534: LabelValueBean returnLabelValueBean = new LabelValueBean(label,
535: value);
536: if (logger.isDebugEnabled()) {
537: logger.debug("readOption() - end - return value = "
538: + returnLabelValueBean);
539: }
540: return returnLabelValueBean;
541: }
542:
543: /**
544: * Within the <code>system</code> or <code>user</code> in the settings
545: * display file (see {@link #readSystemOrUserSettings}), are lots of
546: * <code>setting</code> tags. This method parses one of those.
547: *
548: * @param securitySessionParam
549: * <copyDoc>Refer to {@link #getDocument}.</copyDoc>
550: * @param settingForm
551: * <copyDoc>Refer to {@link #getDocument}.</copyDoc>
552: * @param locale
553: * <copyDoc>Refer to {@link #getDocument}.</copyDoc>
554: * @param names <code>List</code> of all setting names. The name of this
555: * setting will be appended to the list.
556: * @param setting The <em>dom4j</em> element containing a
557: * <code>setting</code> tag to be processed.
558: * @param defaultBundle
559: * <copyDoc>Refer to {@link #getDocument}.</copyDoc>
560: * @throws SystemException If the element cannot be parsed.
561: */
562: private void readSetting(
563: final SecuritySession securitySessionParam,
564: final SettingForm settingForm, final Locale locale,
565: final List names, final Element setting,
566: final String defaultBundle) throws SystemException {
567: if (logger.isDebugEnabled()) {
568: logger
569: .debug("readSetting(SecuritySession securitySessionParam = "
570: + securitySessionParam
571: + ", SettingForm settingForm = "
572: + settingForm
573: + ", Locale locale = "
574: + locale
575: + ", List names = "
576: + names
577: + ", Element setting = "
578: + setting
579: + ", String defaultBundle = "
580: + defaultBundle + ") - start");
581: }
582:
583: String name = setting.attributeValue("name");
584: String type = setting.attributeValue("type");
585: List options = null;
586:
587: // labels appear as a label tag - not a setting tag
588: if (FieldInfo.TYPE_LABEL.equals(setting.getName())) {
589: type = FieldInfo.TYPE_LABEL;
590: name = setting.attributeValue("key");
591: String bundle = setting.attributeValue("bundle");
592: if ("none".equals(bundle)) {
593: bundle = null;
594: } else if (bundle == null) {
595: bundle = defaultBundle;
596: }
597: MaskMessageResources maskMessageResources = new MaskMessageResources(
598: locale, bundle, "");
599: if (StringHandling.isNullOrEmpty(name)) {
600: throw new SystemException("You must specify a key "
601: + "attribute for each label.");
602: }
603: // get the label and use it to set the field
604: String label = maskMessageResources.getMessage(name,
605: (List) null);
606: if (StringHandling.isNullOrEmpty(label)) {
607: throw new SystemException("No label found with "
608: + "key '" + name + "' in bundle '" + bundle
609: + "'");
610: }
611: names.add(name);
612: settingForm.setUserSetting(name, label);
613: settingForm.setSystemSetting(name, label);
614: settingForm.setSettingType(name,
615: SettingConstants.DATA_TYPE_STRING);
616: settingForm.setSettingOverride(name, true);
617: }
618: if (StringHandling.isNullOrEmpty(name)) {
619: throw new SystemException("You must specify a name "
620: + "attribute for each setting.");
621: }
622: // only date formats and selects have options
623: if (FieldInfo.TYPE_DATE_FORMAT.equals(type)
624: || FieldInfo.TYPE_SELECT.equals(type)) {
625: options = new Vector();
626: Iterator optionIterator = setting.elementIterator("option");
627: // here's where we go 'round the options
628: while (optionIterator.hasNext()) {
629: Element option = (Element) optionIterator.next();
630: options.add(readOption(locale, option, defaultBundle));
631: }
632: if (options.isEmpty()) {
633: logger.warn("No options found for setting '" + name
634: + "', type '" + type + "'.");
635: }
636: }
637:
638: FieldInfo fieldInfo;
639: if (type == null) {
640: fieldInfo = new FieldInfo();
641: } else {
642: fieldInfo = new FieldInfo(type, options);
643: }
644: settingForm.setFieldInfo(name, fieldInfo);
645:
646: // first check if this setting is enabled right now
647: // - labels aren't really settings, so this doesn't apply
648: if (!FieldInfo.TYPE_LABEL.equals(type)
649: && settings
650: .isSettingEnabled(securitySessionParam, name)) {
651: names.add(name);
652: settingForm.setUserSetting(name, settings.getSetting(
653: securitySessionParam, name, securitySessionParam
654: .getUser()));
655: settingForm.setSystemSetting(name, settings.getSetting(
656: securitySessionParam, name, null));
657: settingForm.setSettingType(name, settings.getSettingType(
658: securitySessionParam, name));
659: settingForm.setSettingOverride(name, true);
660: } else if (logger.isInfoEnabled()) {
661: logger.info("Setting '" + name
662: + "' is disabled for this system.");
663: }
664:
665: if (logger.isDebugEnabled()) {
666: logger.debug("readSetting() - end");
667: }
668: }
669:
670: /**
671: * <p>
672: * Each settings prefrences document is ordered as <code>tab</code> tags
673: * contained within a <code>settings</code> root document tag.
674: * </p>
675: * <p>
676: * Inside the <code>tab</code> can be a <code>system</code> and
677: * <code>user</code> tag, grouping together the system or user preferences
678: * respectively. This method parses one of those tags.
679: * </p>
680: *
681: * @param securitySessionParam
682: * <copyDoc>Refer to {@link #getDocument}.</copyDoc>
683: * @param settingForm
684: * <copyDoc>Refer to {@link #getDocument}.</copyDoc>
685: * @param locale
686: * <copyDoc>Refer to {@link #getDocument}.</copyDoc>
687: * @param systemUser The <em>dom4j</em> element containing either a
688: * <code>system</code> or <code>user</code> tag to be processed.
689: * @param defaultBundle
690: * <copyDoc>Refer to {@link #getDocument}.</copyDoc>
691: * @return <code>List</code> containing string names of the settings
692: * retrieved.
693: * @throws SystemException If the element cannot be parsed.
694: */
695: private List readSystemOrUserSettings(
696: final SecuritySession securitySessionParam,
697: final SettingForm settingForm, final Locale locale,
698: final Element systemUser, final String defaultBundle)
699: throws SystemException {
700: if (logger.isDebugEnabled()) {
701: logger.debug("readSystemOrUserSettings("
702: + "SecuritySession securitySessionParam = "
703: + securitySessionParam
704: + ", SettingForm settingForm = " + settingForm
705: + ", Locale locale = " + locale
706: + ", Element systemUser = " + systemUser
707: + ", String defaultBundle = " + defaultBundle
708: + ") - start");
709: }
710:
711: List names = new Vector();
712: Iterator settingIterator = systemUser.elementIterator();
713: // now we're at the settings level
714: while (settingIterator.hasNext()) {
715: Element setting = (Element) settingIterator.next();
716: readSetting(securitySessionParam, settingForm, locale,
717: names, setting, defaultBundle);
718: }
719:
720: if (logger.isDebugEnabled()) {
721: logger
722: .debug("readSystemOrUserSettings() - end - return value = "
723: + names);
724: }
725: return names;
726: }
727:
728: /**
729: * <p>This method handles saves all settings in
730: * <code>settingForm</code>. It removes the user
731: * settings when the values of the system and user settings are the
732: * same.</p>
733: *
734: * @param securitySession Used to authenticate when saving the setting
735: * values.
736: * @param form the <code>SettingForm</code> with the request parameter
737: * values.
738: * @throws SystemException If any setting cannot be saved/set.
739: */
740: private void saveSettings(final SecuritySession securitySession,
741: final SettingForm form) throws SystemException {
742: if (logger.isDebugEnabled()) {
743: logger
744: .debug("saveSettings(SecuritySession securitySession = "
745: + securitySession
746: + ", SettingForm form = "
747: + form + ") - start");
748: }
749:
750: UserDO user = securitySession.getUser();
751: boolean administrator = form.isAdministrator();
752:
753: for (Iterator i = form.getSettingName().iterator(); i.hasNext();) {
754: String name = (String) i.next();
755: Object userValue = form.getUserSetting(name);
756: Object systemValue = form.getSystemSetting(name);
757:
758: Object oldSystemValue = settings.getSetting(
759: securitySession, name, null);
760:
761: // when the user can change system settings and override status
762: // for settings
763: if (administrator) {
764: settings.amendSetting(securitySession, name,
765: systemValue, null);
766: // these two settings have to be treated in a special way,
767: // as they have their simpliefied couples (without 'Display')
768: // to allow less strict user input
769: if (name.equals("i18nDateInputDisplay")
770: || name.equals("i18nTimeInputDisplay")) {
771: settings.amendSetting(securitySession, name
772: .substring(0, name.indexOf("Display")),
773: simplifyInputFormat((String) systemValue),
774: null);
775: }
776: // override checkbox for this setting
777: /*TODO
778: if (form.getSettingOverride(name)) {
779: rights.addAmendRightForSetting(name);
780: } else {
781: rights.removeAmendRightForSetting(name);
782: }*/
783: }
784:
785: // when the user value copies the system one (old or new), remove it
786: if (userValue.equals(systemValue)
787: || userValue.equals(oldSystemValue)) {
788: settings
789: .amendSetting(securitySession, name, null, user);
790: // these two settings have to be treated in a special way,
791: // as they have their simpliefied couples (without 'Display')
792: // to allow less strict user input, remove them also
793: if (name.equals("i18nDateInputDisplay")
794: || name.equals("i18nTimeInputDisplay")) {
795: settings.amendSetting(securitySession, name
796: .substring(0, name.indexOf("Display")),
797: null, user);
798: }
799: // set the user setting as a copy of the new system one to
800: // the form, as this could be an apply only
801: form.setUserSetting(name, systemValue);
802:
803: // otherwise save the new value of the user setting
804: } else {
805: settings.amendSetting(securitySession, name, userValue,
806: user);
807: // these two settings have to be treated in a special way,
808: // as they have their simpliefied couples (without 'Display')
809: // to allow less strict user input
810: if (name.equals("i18nDateInputDisplay")
811: || name.equals("i18nTimeInputDisplay")) {
812: settings.amendSetting(securitySession, name
813: .substring(0, name.indexOf("Display")),
814: simplifyInputFormat((String) userValue),
815: user);
816: }
817:
818: }
819: }
820:
821: if (logger.isDebugEnabled()) {
822: logger
823: .debug("saveSettings(SecuritySession, SettingForm) - end");
824: }
825: }
826:
827: /**
828: * <p>The method takes a date / time input format and converts it to a
829: * less strict one.</p>
830: *
831: * @param inputFormat the <code>String</code> with the date/time
832: * format pattern
833: * @return a less strict form of the provided format
834: */
835: private String simplifyInputFormat(final String inputFormat) {
836: if (logger.isDebugEnabled()) {
837: logger.debug("simplifyInputFormat(String inputFormat = "
838: + inputFormat + ") - start");
839: }
840:
841: String returnFormat = inputFormat;
842: Iterator i = Arrays.asList(SIMPLIFY_PATTERNS).iterator();
843: while (i.hasNext()) {
844: String currentPattern = (String) i.next();
845:
846: // find the pattern
847: int patternPosition = returnFormat.indexOf(currentPattern);
848:
849: if (patternPosition != -1) {
850: int longPatternPosition = returnFormat.indexOf(
851: currentPattern, patternPosition + 1);
852: if (!("MM".equals(currentPattern) && longPatternPosition == (patternPosition + 1))) {
853: // replace the double pattern with a single char of it
854: returnFormat = returnFormat.substring(0,
855: patternPosition)
856: + currentPattern.substring(1)
857: + returnFormat
858: .substring(patternPosition + 2);
859:
860: }
861: }
862: }
863:
864: if (logger.isDebugEnabled()) {
865: logger
866: .debug("simplifyInputFormat(String) - end - return value = "
867: + returnFormat);
868: }
869: return returnFormat;
870: }
871: }
|