/*
* Copyright(c) 2005 Center for E-Commerce Infrastructure Development, The
* University of Hong Kong (HKU). All Rights Reserved.
*
* This software is licensed under the Apache License Version 2.0 [1]
*
* [1] http://www.apache.org/licenses/LICENSE-2.0.txt
*/
package hk.hku.cecid.piazza.corvus.core.main.admin.listener;
import hk.hku.cecid.piazza.commons.Sys;
import hk.hku.cecid.piazza.commons.util.PropertySheet;
import hk.hku.cecid.piazza.commons.util.PropertyTree;
import hk.hku.cecid.piazza.commons.util.StringUtilities;
import hk.hku.cecid.piazza.corvus.core.main.admin.AdminMainProcessor;
import hk.hku.cecid.piazza.corvus.core.main.admin.hc.module.SchedulerTask;
import hk.hku.cecid.piazza.corvus.core.main.admin.hc.util.AdminProperties;
import hk.hku.cecid.piazza.corvus.core.main.admin.hc.util.AdminPropertiesException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.xml.transform.Source;
/**
* CorePropertiesPageletAdaptor is a properties pagelet adaptor which provides
* an admin function of the core system properties.
*
* @author Hugo Y. K. Lam
*
*/
public class CorePropertiesPageletAdaptor extends PropertiesPageletAdaptor {
private static final String REQ_PARAM_PROPERTY_HC = "hc:";
protected Source getCenterSource(HttpServletRequest request) {
PropertyTree dom = new PropertyTree();
dom.setProperty("/properties", "");
dom = getPropertiesForDisplayAndUpdate(request, dom);
dom.setProperty("page_type", "coreProps");
dom = addHouseCleaning(request, dom);
return dom.getSource();
}
/**
* Add the housecleaning data to the XSL tranformation.
*
* @param request
* @param dom
* @return PropertyTree
*/
protected PropertyTree addHouseCleaning(HttpServletRequest request,
PropertyTree dom) {
AdminProperties props = new AdminProperties(
(PropertyTree) getHCProperties());
boolean required = false;
dom.setProperty("required", "true");
String action = request.getParameter(REQ_PARAM_ACTION);
if (request.getMethod().equalsIgnoreCase("post")) {
if ("update_hc".equalsIgnoreCase(action)) {
/**
* check if the email is set
*/
if (!(StringUtilities.isEmptyString(request
.getParameter(REQ_PARAM_PROPERTY_HC + "email")))) {
props.setEmail(StringUtilities.trim(request
.getParameter(REQ_PARAM_PROPERTY_HC + "email")));
/**
* check if it is a valid email.
*/
if (!validEmail(request.getParameter(REQ_PARAM_PROPERTY_HC
+ "email"))) {
required = false;
request.setAttribute(ATTR_MESSAGE,
"Invalid email address.");
} else {
/**
* check if the smtp is set.
*/
if (StringUtilities.isEmptyString(request
.getParameter(REQ_PARAM_PROPERTY_HC + "smtp"))) {
request.setAttribute(ATTR_MESSAGE,
"Please specify an SMTP server");
required = false;
dom.setProperty("required", "false");
} else {
required = true;
dom.setProperty("required", "true");
}
}
} else {
required = true;
dom.setProperty("required", "true");
}
if (!StringUtilities.isEmptyString(request
.getParameter(REQ_PARAM_PROPERTY_HC + "smtp"))
&& !isValidDomain(request
.getParameter(REQ_PARAM_PROPERTY_HC + "smtp"))) {
if (required == true) {
required = false;
request.setAttribute(ATTR_MESSAGE,
"Invalid SMTP server.");
}
}
if (request.getParameter(REQ_PARAM_PROPERTY_HC + "on").equals(
"true")) {
Calendar c = GregorianCalendar.getInstance();
try {
c.setTime(new SimpleDateFormat(
SchedulerTask.TIME_FORMAT).parse(props
.getTime()));
props.setNextRun(new SimpleDateFormat(
SchedulerTask.DATE_FORMAT).format(SchedulerTask
.getNextRunDateFromNow(props.getDay(), c
.get(Calendar.HOUR_OF_DAY), c
.get(Calendar.MINUTE), c
.get(Calendar.SECOND))));
} catch (AdminPropertiesException e) {
request.setAttribute(ATTR_MESSAGE,
"Error retrieving property.");
} catch (Exception e) {
request.setAttribute(ATTR_MESSAGE,
"Unable to set next run time: " + e);
}
}
Enumeration names = request.getParameterNames();
while (names.hasMoreElements()) {
String name = names.nextElement().toString();
if (name.startsWith(REQ_PARAM_PROPERTY_HC)) {
props.setElementHC(name.substring(REQ_PARAM_PROPERTY_HC
.length()), request.getParameter(name));
}
}
if (required) {
try {
props.write();
request.setAttribute(ATTR_MESSAGE,
"House Cleaning settings updated successfully");
} catch (Exception e) {
request.setAttribute(ATTR_MESSAGE,
"Unable to update properties: " + e);
}
}
}
}
String[] propArray = { AdminProperties.ON, AdminProperties.EMAIL,
AdminProperties.SMTP, AdminProperties.USERNAME,
AdminProperties.PASSWORD };
try {
for (int index = 0; index < propArray.length; index++) {
dom.setProperty("hc/" + propArray[index], props
.getElementHC(propArray[index]));
}
String[] datesArray = { AdminProperties.LAST_RUN,
AdminProperties.NEXT_RUN };
for (int jndex = 0; jndex < datesArray.length; jndex++) {
if (!props.getElementHC(datesArray[jndex]).equals("")
&& props.getElementHC(datesArray[jndex]) != null) {
dom
.setProperty(
"hc/" + datesArray[jndex],
(new SimpleDateFormat(
SchedulerTask.DATE_FORMAT))
.parse(
props
.getElementHC(datesArray[jndex]))
.toString());
}
}
return dom;
} catch (Exception e) {
request.setAttribute(ATTR_MESSAGE,
"Unable to retrieve properties: " + e);
return dom;
}
}
private PropertySheet getHCProperties() {
try {
AdminMainProcessor.core.properties.load();
} catch (Exception e) {
AdminMainProcessor.core.log.error("Unable to load the properties.");
}
return AdminMainProcessor.core.properties;
}
/**
* Checks if the String s is in a valid email format using regex.
*
* @param s
* @return
*/
private boolean validEmail(String s) {
int pos_at = posOfAt(s);
String username;
String domain;
if (pos_at == 0) {
return false;
} else {
username = s.substring(0, pos_at - 1);
if (!isValidFormat(username, "[\\w\\.\\-]")) {
return false;
} else {
domain = s.substring(pos_at + 1);
if (!isValidFormat(domain, "[a-zA-Z0-9\\.\\-]")) {
return false;
} else {
if (!isValidDomain(domain)) {
return false;
} else {
return true;
}
}
}
}
}
/**
* Checks if the characters in the String s conform to the regex specified.
*
* @param s
* @param regex
* @return
*/
private boolean isValidFormat(String s, String regex) {
char[] array = s.toCharArray();
boolean matches = true;
for (int i = 0; i < array.length; i++) {
if (!Pattern.matches(regex, String.valueOf(array[i]))) {
matches = false;
break;
}
}
return matches;
}
/**
* Checks to see if the String s is a valid domain. A valid domain is
* considered to be where there is at least 1 decimal and the sections
* devided by decimals are alphanumeric or dashes but the dashes can only be
* in the middle. The last segment should be all alphabets.
*
* @param s
* @return
*/
private boolean isValidDomain(String s) {
int dot_count = 0;
char[] array = s.toCharArray();
for (int i = 0; i < array.length; i++) {
if (array[i] == '.') {
dot_count++;
}
}
boolean validString = true;
String[] blocks = s.split("\\.");
if (dot_count != blocks.length - 1) {
return false;
}
for (int j = 0; j < blocks.length; j++) {
char[] temp = blocks[j].toCharArray();
for (int k = 0; k < temp.length; k++) {
if (j == blocks.length - 1) {
if (!String.valueOf(temp[k]).matches("[a-zA-Z]")) {
validString = false;
}
} else {
if (k == 0 || k == temp.length - 1) {
if (!String.valueOf(temp[k]).matches("[a-zA-Z0-9]")) {
validString = false;
} else {
if (!String.valueOf(temp[k]).matches(
"[a-zA-Z0-9\\-]")) {
validString = false;
}
}
}
}
}
}
if (dot_count != 0 && validString) {
return true;
} else {
return false;
}
}
/**
* Return position of the @ symbol or 0 if none or more than 1
* @param address
* @return
*/
private int posOfAt(String s) {
char[] address = s.toCharArray();
int at_count = 0;
int pos = 0;
for (int i = 0; i < address.length; i++) {
if (address[i] == '@') {
at_count++;
pos = i;
}
}
if (at_count == 1) {
return pos;
} else {
return 0;
}
}
/**
* Gets the core system properties.
*
* @return the core system properties.
* @see hk.hku.cecid.piazza.corvus.core.main.admin.listener.PropertiesPageletAdaptor#getProperties()
*/
protected PropertySheet getProperties() {
return Sys.main.properties;
}
}