/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.xmlui.aspect.administrative;
import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.cocoon.configuration.Settings;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.commons.lang.StringUtils;
import org.apache.excalibur.store.Store;
import org.apache.excalibur.store.StoreJanitor;
import org.dspace.app.util.Util;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.Body;
import org.dspace.app.xmlui.wing.element.Division;
import org.dspace.app.xmlui.wing.element.Item;
import org.dspace.app.xmlui.wing.element.List;
import org.dspace.app.xmlui.wing.element.PageMeta;
import org.dspace.app.xmlui.wing.element.Row;
import org.dspace.app.xmlui.wing.element.Select;
import org.dspace.app.xmlui.wing.element.Table;
import org.dspace.app.xmlui.wing.element.TextArea;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.harvest.OAIHarvester.HarvestScheduler;
import org.dspace.core.ConfigurationManager;
import org.dspace.eperson.EPerson;
import org.xml.sax.SAXException;
/**
* This page displays important (and some not-so important) systems
* type information about your running dspace.
*
* @author Jay Paz
* @author Scott Phillips
*/
public class ControlPanel extends AbstractDSpaceTransformer implements Serviceable, Disposable {
/** Language Strings */
private static final Message T_DSPACE_HOME = message("xmlui.general.dspace_home");
private static final Message T_title = message("xmlui.administrative.ControlPanel.title");
private static final Message T_trail = message("xmlui.administrative.ControlPanel.trail");
private static final Message T_head = message("xmlui.administrative.ControlPanel.head");
private static final Message T_option_java = message("xmlui.administrative.ControlPanel.option_java");
private static final Message T_option_dspace = message("xmlui.administrative.ControlPanel.option_dspace");
private static final Message T_option_alerts = message("xmlui.administrative.ControlPanel.option_alerts");
private static final Message T_seconds = message("xmlui.administrative.ControlPanel.seconds");
private static final Message T_hours = message("xmlui.administrative.ControlPanel.hours");
private static final Message T_minutes = message("xmlui.administrative.ControlPanel.minutes");
private static final Message T_JAVA_HEAD = message("xmlui.administrative.ControlPanel.java_head");
private static final Message T_JAVA_VERSION = message("xmlui.administrative.ControlPanel.java_version");
private static final Message T_JAVA_VENDOR = message("xmlui.administrative.ControlPanel.java_vendor");
private static final Message T_OS_NAME = message("xmlui.administrative.ControlPanel.os_name");
private static final Message T_OS_ARCH = message("xmlui.administrative.ControlPanel.os_arch");
private static final Message T_OS_VERSION = message("xmlui.administrative.ControlPanel.os_version");
private static final Message T_RUNTIME_HEAD = message("xmlui.administrative.ControlPanel.runtime_head");
private static final Message T_RUNTIME_PROCESSORS = message("xmlui.administrative.ControlPanel.runtime_processors");
private static final Message T_RUNTIME_MAX = message("xmlui.administrative.ControlPanel.runtime_max");
private static final Message T_RUNTIME_TOTAL = message("xmlui.administrative.ControlPanel.runtime_total");
private static final Message T_RUNTIME_USED = message("xmlui.administrative.ControlPanel.runtime_used");
private static final Message T_RUNTIME_FREE = message("xmlui.administrative.ControlPanel.runtime_free");
private static final Message T_COCOON_HEAD = message("xmlui.administrative.ControlPanel.cocoon_head");
private static final Message T_COCOON_VERSION = message("xmlui.administrative.ControlPanel.cocoon_version");
private static final Message T_COCOON_CACHE_DIR = message("xmlui.administrative.ControlPanel.cocoon_cache_dir");
private static final Message T_COCOON_WORK_DIR = message("xmlui.administrative.ControlPanel.cocoon_work_dir");
private static final Message T_COCOON_MAIN_CACHE_SIZE = message("xmlui.administrative.ControlPanel.cocoon_main_cache_size");
private static final Message T_COCOON_PERSISTENT_CACHE_SIZE = message("xmlui.administrative.ControlPanel.cocoon_persistent_cache_size");
private static final Message T_COCOON_TRANS_CACHE_SIZE = message("xmlui.administrative.ControlPanel.cocoon_transient_cache_size");
private static final Message T_COCOON_CACHE_CLEAR = message("xmlui.administrative.ControlPanel.cocoon_cache_clear");
private static final Message T_DSPACE_HEAD = message("xmlui.administrative.ControlPanel.dspace_head");
private static final Message T_DSPACE_DIR = message("xmlui.administrative.ControlPanel.dspace_dir");
private static final Message T_DSPACE_URL = message("xmlui.administrative.ControlPanel.dspace_url");
private static final Message T_DSPACE_HOST_NAME = message("xmlui.administrative.ControlPanel.dspace_hostname");
private static final Message T_DSPACE_NAME = message("xmlui.administrative.ControlPanel.dspace_name");
private static final Message T_DSPACE_VERSION = message("xmlui.administrative.ControlPanel.dspace_version");
private static final Message T_DB_NAME = message("xmlui.administrative.ControlPanel.db_name");
private static final Message T_DB_URL = message("xmlui.administrative.ControlPanel.db_url");
private static final Message T_DB_DRIVER = message("xmlui.administrative.ControlPanel.db_driver");
private static final Message T_DB_MAX_CONN = message("xmlui.administrative.ControlPanel.db_maxconnections");
private static final Message T_DB_MAX_WAIT = message("xmlui.administrative.ControlPanel.db_maxwait");
private static final Message T_DB_MAX_IDLE = message("xmlui.administrative.ControlPanel.db_maxidle");
private static final Message T_MAIL_SERVER = message("xmlui.administrative.ControlPanel.mail_server");
private static final Message T_MAIL_FROM_ADDRESS = message("xmlui.administrative.ControlPanel.mail_from_address");
private static final Message T_FEEDBACK_RECIPIENT = message("xmlui.administrative.ControlPanel.mail_feedback_recipient");
private static final Message T_MAIL_ADMIN = message("xmlui.administrative.ControlPanel.mail_admin");
private static final Message T_alerts_head = message("xmlui.administrative.ControlPanel.alerts_head");
private static final Message T_alerts_warning = message("xmlui.administrative.ControlPanel.alerts_warning");
private static final Message T_alerts_message_label = message("xmlui.administrative.ControlPanel.alerts_message_label");
private static final Message T_alerts_message_default = message("xmlui.administrative.ControlPanel.alerts_message_default");
private static final Message T_alerts_countdown_label = message("xmlui.administrative.ControlPanel.alerts_countdown_label");
private static final Message T_alerts_countdown_none = message("xmlui.administrative.ControlPanel.alerts_countdown_none");
private static final Message T_alerts_countdown_5 = message("xmlui.administrative.ControlPanel.alerts_countdown_5");
private static final Message T_alerts_countdown_15 = message("xmlui.administrative.ControlPanel.alerts_countdown_15");
private static final Message T_alerts_countdown_30 = message("xmlui.administrative.ControlPanel.alerts_countdown_30");
private static final Message T_alerts_countdown_60 = message("xmlui.administrative.ControlPanel.alerts_countdown_60");
private static final Message T_alerts_countdown_keep = message("xmlui.administrative.ControlPanel.alerts_countdown_keep");
private static final Message T_alerts_session_label = message("xmlui.administrative.ControlPanel.alerts_session_label");
private static final Message T_alerts_session_all_sessions = message("xmlui.administrative.ControlPanel.alerts_session_all_sessions");
private static final Message T_alerts_session_current_sessions = message("xmlui.administrative.ControlPanel.alerts_session_current_sessions");
private static final Message T_alerts_session_only_administrative = message("xmlui.administrative.ControlPanel.alerts_session_only_administrative_sessions");
private static final Message T_alerts_session_note = message("xmlui.administrative.ControlPanel.alerts_session_note");
private static final Message T_alerts_submit_activate = message("xmlui.administrative.ControlPanel.alerts_submit_activate");
private static final Message T_alerts_submit_deactivate = message("xmlui.administrative.ControlPanel.alerts_submit_deactivate");
private static final Message T_activity_head = message("xmlui.administrative.ControlPanel.activity_head");
private static final Message T_stop_anonymous = message("xmlui.administrative.ControlPanel.stop_anonymous");
private static final Message T_start_anonymous = message("xmlui.administrative.ControlPanel.start_anonymous");
private static final Message T_stop_bot = message("xmlui.administrative.ControlPanel.stop_bot");
private static final Message T_start_bot = message("xmlui.administrative.ControlPanel.start_bot");
private static final Message T_activity_sort_time = message("xmlui.administrative.ControlPanel.activity_sort_time");
private static final Message T_activity_sort_user = message("xmlui.administrative.ControlPanel.activity_sort_user");
private static final Message T_activity_sort_ip = message("xmlui.administrative.ControlPanel.activity_sort_ip");
private static final Message T_activity_sort_url = message("xmlui.administrative.ControlPanel.activity_sort_url");
private static final Message T_activity_sort_agent = message("xmlui.administrative.ControlPanel.activity_sort_Agent");
private static final Message T_activity_anonymous = message("xmlui.administrative.ControlPanel.activity_anonymous");
private static final Message T_activity_none = message("xmlui.administrative.ControlPanel.activity_none");
private static final Message T_select_panel = message("xmlui.administrative.ControlPanel.select_panel");
private static final Message T_option_harvest = message("xmlui.administrative.ControlPanel.option_harvest");
private static final Message T_harvest_scheduler_head = message("xmlui.administrative.ControlPanel.harvest_scheduler_head");
private static final Message T_harvest_label_status = message("xmlui.administrative.ControlPanel.harvest_label_status");
private static final Message T_harvest_label_actions = message("xmlui.administrative.ControlPanel.harvest_label_actions");
private static final Message T_harvest_submit_start = message("xmlui.administrative.ControlPanel.harvest_submit_start");
private static final Message T_harvest_submit_reset = message("xmlui.administrative.ControlPanel.harvest_submit_reset");
private static final Message T_harvest_submit_resume = message("xmlui.administrative.ControlPanel.harvest_submit_resume");
private static final Message T_harvest_submit_pause = message("xmlui.administrative.ControlPanel.harvest_submit_pause");
private static final Message T_harvest_submit_stop = message("xmlui.administrative.ControlPanel.harvest_submit_stop");
private static final Message T_harvest_label_collections = message("xmlui.administrative.ControlPanel.harvest_label_collections");
private static final Message T_harvest_label_active = message("xmlui.administrative.ControlPanel.harvest_label_active");
private static final Message T_harvest_label_queued = message("xmlui.administrative.ControlPanel.harvest_label_queued");
private static final Message T_harvest_label_oai_errors = message("xmlui.administrative.ControlPanel.harvest_label_oai_errors");
private static final Message T_harvest_label_internal_errors = message("xmlui.administrative.ControlPanel.harvest_label_internal_errors");
private static final Message T_harvest_head_generator_settings = message("xmlui.administrative.ControlPanel.harvest_head_generator_settings");
private static final Message T_harvest_label_oai_url = message("xmlui.administrative.ControlPanel.harvest_label_oai_url");
private static final Message T_harvest_label_oai_source = message("xmlui.administrative.ControlPanel.harvest_label_oai_source");
private static final Message T_harvest_head_harvester_settings = message("xmlui.administrative.ControlPanel.harvest_head_harvester_settings");
/**
* The service manager allows us to access the continuation's
* manager. It is obtained from the Serviceable API
*/
private ServiceManager serviceManager;
/**
* The Cocoon Settings (used to display Cocoon info)
*/
private Settings settings;
/**
* The Cocoon StoreJanitor (used for cache statistics)
*/
private StoreJanitor storeJanitor;
/**
* The Cocoon Default Store (used for cache statistics)
*/
private Store storeDefault;
/**
* The Cocoon Persistent Store (used for cache statistics)
*/
private Store storePersistent;
/**
* The five states that this page can be in.
*/
private enum OPTIONS {java, dspace, alerts, activity, harvest};
/**
* From the <code>org.apache.avalon.framework.service.Serviceable</code> API,
* give us the current <code>ServiceManager</code> instance.
* <P>
* Much of this ServiceManager logic/code has been borrowed from the source
* code of the Cocoon <code>StatusGenerator</code> class:
* http://svn.apache.org/repos/asf/cocoon/tags/cocoon-2.2/cocoon-sitemap-components/cocoon-sitemap-components-1.0.0/src/main/java/org/apache/cocoon/generation/StatusGenerator.java
*/
@Override
public void service(ServiceManager serviceManager) throws ServiceException
{
this.serviceManager = serviceManager;
this.settings = (Settings) this.serviceManager.lookup(Settings.ROLE);
if(this.serviceManager.hasService(StoreJanitor.ROLE))
this.storeJanitor = (StoreJanitor) this.serviceManager.lookup(StoreJanitor.ROLE);
if (this.serviceManager.hasService(Store.ROLE))
this.storeDefault = (Store) this.serviceManager.lookup(Store.ROLE);
if(this.serviceManager.hasService(Store.PERSISTENT_STORE))
this.storePersistent = (Store) this.serviceManager.lookup(Store.PERSISTENT_STORE);
}
@Override
public void addPageMeta(PageMeta pageMeta) throws SAXException,
WingException, UIException, SQLException, IOException,
AuthorizeException
{
pageMeta.addMetadata("title").addContent(T_title);
pageMeta.addTrailLink(contextPath + "/", T_DSPACE_HOME);
pageMeta.addTrailLink(null, T_trail);
}
@Override
public void addBody(Body body) throws SAXException, WingException,
UIException, SQLException, IOException, AuthorizeException
{
if (!AuthorizeManager.isAdmin(context))
{
throw new AuthorizeException("You are not authorized to view this page.");
}
Request request = ObjectModelHelper.getRequest(objectModel);
OPTIONS option = null;
if (request.getParameter("java") != null)
{
option = OPTIONS.java;
}
if (request.getParameter("dspace") != null)
{
option = OPTIONS.dspace;
}
if (request.getParameter("alerts") != null)
{
option = OPTIONS.alerts;
}
if (request.getParameter("activity") != null)
{
option = OPTIONS.activity;
}
if (request.getParameter("harvest") != null)
{
option = OPTIONS.harvest;
}
Division div = body.addInteractiveDivision("control-panel", contextPath+"/admin/panel", Division.METHOD_POST, "primary administrative");
div.setHead(T_head);
// LIST: options
List options = div.addList("options",List.TYPE_SIMPLE,"horizontal");
// our options, selected or not....
if (option == OPTIONS.java)
{
options.addItem().addHighlight("bold").addXref("?java", T_option_java);
}
else
{
options.addItemXref("?java", T_option_java);
}
if (option == OPTIONS.dspace)
{
options.addItem().addHighlight("bold").addXref("?dspace", T_option_dspace);
}
else
{
options.addItemXref("?dspace", T_option_dspace);
}
if (option == OPTIONS.alerts)
{
options.addItem().addHighlight("bold").addXref("?alerts", T_option_alerts);
}
else
{
options.addItemXref("?alerts", T_option_alerts);
}
if (option == OPTIONS.harvest)
{
options.addItem().addHighlight("bold").addXref("?harvest", T_option_harvest);
}
else
{
options.addItemXref("?harvest", T_option_harvest);
}
String userSortTarget = "?activity";
if (request.getParameter("sortBy") != null)
{
userSortTarget += "&sortBy=" + request.getParameter("sortBy");
}
if (option == OPTIONS.activity)
{
options.addItem().addHighlight("bold").addXref(userSortTarget, "Current Activity");
}
else
{
options.addItemXref(userSortTarget, "Current Activity");
}
// The main content:
if (option == OPTIONS.java)
{
addJavaInformation(div);
}
else if (option == OPTIONS.dspace)
{
addDSpaceConfiguration(div);
}
else if (option == OPTIONS.alerts)
{
addAlerts(div);
}
else if (option == OPTIONS.activity)
{
addActivity(div);
}
else if (option == OPTIONS.harvest)
{
addHarvest(div);
}
else
{
div.addPara(T_select_panel);
}
}
/**
* Add specific java information including JRE, OS, and runtime memory statistics.
*/
private void addJavaInformation(Division div) throws WingException
{
// Get memory statistics
int processors = Runtime.getRuntime().availableProcessors();
long maxMemory = Runtime.getRuntime().maxMemory();
long totalMemory = Runtime.getRuntime().totalMemory();
long freeMemory = Runtime.getRuntime().freeMemory();
long usedMemory = totalMemory-freeMemory;
// Convert bytes into MiB
maxMemory = maxMemory / 1024 / 1024;
totalMemory = totalMemory / 1024 / 1024;
usedMemory = usedMemory / 1024 / 1024;
freeMemory = freeMemory / 1024 / 1024;
// LIST: Java
List list = div.addList("javaOs");
list.setHead(T_JAVA_HEAD);
list.addLabel(T_JAVA_VERSION);
list.addItem(System.getProperty("java.version"));
list.addLabel(T_JAVA_VENDOR);
list.addItem(System.getProperty("java.vendor"));
list.addLabel(T_OS_NAME);
list.addItem(System.getProperty("os.name"));
list.addLabel(T_OS_ARCH);
list.addItem(System.getProperty("os.arch"));
list.addLabel(T_OS_VERSION);
list.addItem(System.getProperty("os.version"));
// LIST: memory
List runtime = div.addList("runtime");
runtime.setHead(T_RUNTIME_HEAD);
runtime.addLabel(T_RUNTIME_PROCESSORS);
runtime.addItem(String.valueOf(processors));
runtime.addLabel(T_RUNTIME_MAX);
runtime.addItem(String.valueOf(maxMemory) + " MiB");
runtime.addLabel(T_RUNTIME_TOTAL);
runtime.addItem(String.valueOf(totalMemory) + " MiB");
runtime.addLabel(T_RUNTIME_USED);
runtime.addItem(String.valueOf(usedMemory) + " MiB");
runtime.addLabel(T_RUNTIME_FREE);
runtime.addItem(String.valueOf(freeMemory) + " MiB");
//List: Cocoon Info & Cache
addCocoonInformation(div);
}
/**
* Add specific Cocoon information, especially related to the Cocoon Cache.
* <P>
* For more information about Cocoon Caches/Stores, see:
* http://wiki.apache.org/cocoon/StoreComponents
*/
private void addCocoonInformation(Division div) throws WingException
{
// List: Cocoon Info & Caches
List cocoon = div.addList("cocoon");
cocoon.setHead(T_COCOON_HEAD);
cocoon.addLabel(T_COCOON_VERSION);
cocoon.addItem(org.apache.cocoon.Constants.VERSION);
//attempt to Display some basic info about Cocoon's Settings & Caches
//Get access to basic Cocoon Settings
if(this.settings!=null)
{
//Output Cocoon's Work Directory & Cache Directory
cocoon.addLabel(T_COCOON_WORK_DIR);
cocoon.addItem(this.settings.getWorkDirectory());
cocoon.addLabel(T_COCOON_CACHE_DIR);
cocoon.addItem(this.settings.getCacheDirectory());
}
// Check if we have access to Cocoon's Default Cache
//Cocoon's Main (Default) Store is used to store objects that are serializable
if(this.storeDefault!=null)
{
//Store name is just the className (remove the package info though, just to save space)
String storeName = this.storeDefault.getClass().getName();
storeName = storeName.substring(storeName.lastIndexOf(".")+1);
//display main store's cache info
cocoon.addLabel(T_COCOON_MAIN_CACHE_SIZE.parameterize(storeName + ", 0x" + Integer.toHexString(this.storeDefault.hashCode())));
//display cache size & link to clear Cocoon's main cache
Item defaultSize = cocoon.addItem();
defaultSize.addContent(String.valueOf(this.storeDefault.size()) + " ");
defaultSize.addXref(contextPath + "/admin/panel?java=true&clearcache=true", T_COCOON_CACHE_CLEAR);
}
// Check if we have access to Cocoon's Persistent Cache
//Cocoon's Persistent Store may be used by the Default Cache/Store to delegate persistent storage
//(it's an optional store which may not exist)
if(this.storePersistent!=null)
{
//Store name is just the className (remove the package info though, just to save space)
String storeName = this.storeDefault.getClass().getName();
storeName = storeName.substring(storeName.lastIndexOf(".")+1);
//display persistent store's cache size info
cocoon.addLabel(T_COCOON_PERSISTENT_CACHE_SIZE.parameterize(storeName + ", 0x" + Integer.toHexString(this.storePersistent.hashCode())));
cocoon.addItem(String.valueOf(this.storePersistent.size()));
}
//Check if we have access to Cocoon's StoreJanitor
//The Store Janitor manages all of Cocoon's "transient caches/stores"
// These "transient" stores are used for non-serializable objects or objects whose
// storage doesn't make sense across a server restart.
if(this.storeJanitor!=null)
{
// For each Cache Store in Cocoon's StoreJanitor
Iterator i = this.storeJanitor.iterator();
while(i.hasNext())
{
//get the Cache Store
Store store = (Store) i.next();
//Store name is just the className (remove the package info though, just to save space)
String storeName = store.getClass().getName();
storeName = storeName.substring(storeName.lastIndexOf(".")+1);
//display its size information
cocoon.addLabel(T_COCOON_TRANS_CACHE_SIZE.parameterize(storeName + ", 0x" + Integer.toHexString(store.hashCode())));
cocoon.addItem(String.valueOf(store.size()));
}
}
}
/**
* List important DSpace configuration parameters.
*/
private void addDSpaceConfiguration(Division div) throws WingException
{
// LIST: DSpace
List dspace = div.addList("dspace");
dspace.setHead(T_DSPACE_HEAD);
dspace.addLabel(T_DSPACE_VERSION);
dspace.addItem(Util.getSourceVersion());
dspace.addLabel(T_DSPACE_DIR);
dspace.addItem(ConfigurationManager.getProperty("dspace.dir"));
dspace.addLabel(T_DSPACE_URL);
dspace.addItem(ConfigurationManager.getProperty("dspace.url"));
dspace.addLabel(T_DSPACE_HOST_NAME);
dspace.addItem(ConfigurationManager.getProperty("dspace.hostname"));
dspace.addLabel(T_DSPACE_NAME);
dspace.addItem(ConfigurationManager.getProperty("dspace.name"));
dspace.addLabel(T_DB_NAME);
dspace.addItem(ConfigurationManager.getProperty("db.name"));
dspace.addLabel(T_DB_URL);
dspace.addItem(ConfigurationManager.getProperty("db.url"));
dspace.addLabel(T_DB_DRIVER);
dspace.addItem(ConfigurationManager.getProperty("db.driver"));
dspace.addLabel(T_DB_MAX_CONN);
dspace.addItem(ConfigurationManager.getProperty("db.maxconnections"));
dspace.addLabel(T_DB_MAX_WAIT);
dspace.addItem(ConfigurationManager.getProperty("db.maxwait"));
dspace.addLabel(T_DB_MAX_IDLE);
dspace.addItem(ConfigurationManager.getProperty("db.maxidle"));
dspace.addLabel(T_MAIL_SERVER);
dspace.addItem(ConfigurationManager.getProperty("mail.server"));
dspace.addLabel(T_MAIL_FROM_ADDRESS);
dspace.addItem(ConfigurationManager.getProperty("mail.from.address"));
dspace.addLabel(T_FEEDBACK_RECIPIENT);
dspace.addItem(ConfigurationManager.getProperty("feedback.recipient"));
dspace.addLabel(T_MAIL_ADMIN);
dspace.addItem(ConfigurationManager.getProperty("mail.admin"));
}
/**
* Add a section that allows administrators to activate or deactivate system-wide alerts.
*/
private void addAlerts(Division div) throws WingException
{
// Remember we're in the alerts section
div.addHidden("alerts").setValue("true");
List form = div.addList("system-wide-alerts",List.TYPE_FORM);
form.setHead(T_alerts_head);
form.addItem(T_alerts_warning);
TextArea message = form.addItem().addTextArea("message");
message.setAutofocus("autofocus");
message.setLabel(T_alerts_message_label);
message.setSize(5, 45);
if (SystemwideAlerts.getMessage() == null)
{
message.setValue(T_alerts_message_default);
}
else
{
message.setValue(SystemwideAlerts.getMessage());
}
Select countdown = form.addItem().addSelect("countdown");
countdown.setLabel(T_alerts_countdown_label);
countdown.addOption(0,T_alerts_countdown_none);
countdown.addOption(5,T_alerts_countdown_5);
countdown.addOption(15,T_alerts_countdown_15);
countdown.addOption(30,T_alerts_countdown_30);
countdown.addOption(60,T_alerts_countdown_60);
// Is there a current count down active?
if (SystemwideAlerts.isAlertActive() && SystemwideAlerts.getCountDownToo() - System.currentTimeMillis() > 0)
{
countdown.addOption(true, -1, T_alerts_countdown_keep);
}
else
{
countdown.setOptionSelected(0);
}
Select restrictsessions = form.addItem().addSelect("restrictsessions");
restrictsessions.setLabel(T_alerts_session_label);
restrictsessions.addOption(SystemwideAlerts.STATE_ALL_SESSIONS,T_alerts_session_all_sessions);
restrictsessions.addOption(SystemwideAlerts.STATE_CURRENT_SESSIONS,T_alerts_session_current_sessions);
restrictsessions.addOption(SystemwideAlerts.STATE_ONLY_ADMINISTRATIVE_SESSIONS,T_alerts_session_only_administrative);
restrictsessions.setOptionSelected(SystemwideAlerts.getRestrictSessions());
form.addItem(T_alerts_session_note);
Item actions = form.addItem();
actions.addButton("submit_activate").setValue(T_alerts_submit_activate);
actions.addButton("submit_deactivate").setValue(T_alerts_submit_deactivate);
}
/** The possible sorting parameters */
private static enum EventSort { TIME, URL, SESSION, AGENT, IP };
/**
* Create a list of all activity.
*/
private void addActivity(Division div) throws WingException, SQLException
{
// 0) Update recording settings
Request request = ObjectModelHelper.getRequest(objectModel);
// Toggle anonymous recording
String recordAnonymousString = request.getParameter("recordanonymous");
if (recordAnonymousString != null)
{
if ("ON".equals(recordAnonymousString))
{
CurrentActivityAction.setRecordAnonymousEvents(true);
}
if ("OFF".equals(recordAnonymousString))
{
CurrentActivityAction.setRecordAnonymousEvents(false);
}
}
// Toggle bot recording
String recordBotString = request.getParameter("recordbots");
if (recordBotString != null)
{
if ("ON".equals(recordBotString))
{
CurrentActivityAction.setRecordBotEvents(true);
}
if ("OFF".equals(recordBotString))
{
CurrentActivityAction.setRecordBotEvents(false);
}
}
// 1) Determine how to sort
EventSort sortBy = EventSort.TIME;
String sortByString = request.getParameter("sortBy");
if (EventSort.TIME.toString().equals(sortByString))
{
sortBy = EventSort.TIME;
}
if (EventSort.URL.toString().equals(sortByString))
{
sortBy = EventSort.URL;
}
if (EventSort.SESSION.toString().equals(sortByString))
{
sortBy = EventSort.SESSION;
}
if (EventSort.AGENT.toString().equals(sortByString))
{
sortBy = EventSort.AGENT;
}
if (EventSort.IP.toString().equals(sortByString))
{
sortBy = EventSort.IP;
}
// 2) Sort the events by the requested sorting parameter
java.util.List<CurrentActivityAction.Event> events = CurrentActivityAction.getEvents();
Collections.sort(events, new ActivitySort<CurrentActivityAction.Event>(sortBy));
Collections.reverse(events);
// 3) Toggle controls for anonymous and bot activity
if (CurrentActivityAction.getRecordAnonymousEvents())
{
div.addPara().addXref("?activity&sortBy=" + sortBy + "&recordanonymous=OFF").addContent(T_stop_anonymous);
}
else
{
div.addPara().addXref("?activity&sortBy=" + sortBy + "&recordanonymous=ON").addContent(T_start_anonymous);
}
if (CurrentActivityAction.getRecordBotEvents())
{
div.addPara().addXref("?activity&sortBy=" + sortBy + "&recordbots=OFF").addContent(T_stop_bot);
}
else
{
div.addPara().addXref("?activity&sortBy=" + sortBy + "&recordbots=ON").addContent(T_start_bot);
}
// 4) Display the results Table
// TABLE: activeUsers
Table activeUsers = div.addTable("users",1,1);
activeUsers.setHead(T_activity_head.parameterize(CurrentActivityAction.MAX_EVENTS));
Row row = activeUsers.addRow(Row.ROLE_HEADER);
if (sortBy == EventSort.TIME)
{
row.addCell().addHighlight("bold").addXref("?activity&sortBy=" + EventSort.TIME).addContent(T_activity_sort_time);
}
else
{
row.addCell().addXref("?activity&sortBy=" + EventSort.TIME).addContent(T_activity_sort_time);
}
if (sortBy == EventSort.SESSION)
{
row.addCell().addHighlight("bold").addXref("?activity&sortBy=" + EventSort.SESSION).addContent(T_activity_sort_user);
}
else
{
row.addCell().addXref("?activity&sortBy=" + EventSort.SESSION).addContent(T_activity_sort_user);
}
if (sortBy == EventSort.IP)
{
row.addCell().addHighlight("bold").addXref("?activity&sortBy=" + EventSort.IP).addContent(T_activity_sort_ip);
}
else
{
row.addCell().addXref("?activity&sortBy=" + EventSort.IP).addContent(T_activity_sort_ip);
}
if (sortBy == EventSort.URL)
{
row.addCell().addHighlight("bold").addXref("?activity&sortBy=" + EventSort.URL).addContent(T_activity_sort_url);
}
else
{
row.addCell().addXref("?activity&sortBy=" + EventSort.URL).addContent(T_activity_sort_url);
}
if (sortBy == EventSort.AGENT)
{
row.addCell().addHighlight("bold").addXref("?activity&sortBy=" + EventSort.AGENT).addContent(T_activity_sort_agent);
}
else
{
row.addCell().addXref("?activity&sortBy=" + EventSort.AGENT).addContent(T_activity_sort_agent);
}
// Keep track of how many individual anonymous users there are, each unique anonymous
// user is assigned an index based upon the servlet session id.
HashMap<String,Integer> anonymousHash = new HashMap<String,Integer>();
int anonymousCount = 1;
int shown = 0;
for (CurrentActivityAction.Event event : events)
{
if (event == null)
{
continue;
}
shown++;
Message timeStampMessage = null;
long ago = System.currentTimeMillis() - event.getTimeStamp();
if (ago > 2*60*60*1000)
{
timeStampMessage = T_hours.parameterize((ago / (60 * 60 * 1000)));
}
else if (ago > 60*1000)
{
timeStampMessage = T_minutes.parameterize((ago / (60 * 1000)));
}
else
{
timeStampMessage = T_seconds.parameterize((ago / (1000)));
}
Row eventRow = activeUsers.addRow();
eventRow.addCellContent(timeStampMessage);
int eid = event.getEPersonID();
EPerson eperson = EPerson.find(context, eid);
if (eperson != null)
{
String name = eperson.getFullName();
eventRow.addCellContent(name);
}
else
{
// Is this a new anonymous user?
if (!anonymousHash.containsKey(event.getSessionID()))
{
anonymousHash.put(event.getSessionID(), anonymousCount++);
}
eventRow.addCellContent(T_activity_anonymous.parameterize(anonymousHash.get(event.getSessionID())));
}
eventRow.addCellContent(event.getIP());
eventRow.addCell().addXref(contextPath+"/"+event.getURL()).addContent("/"+event.getURL());
eventRow.addCellContent(event.getDectectedBrowser());
}
if (shown == 0)
{
activeUsers.addRow().addCell(1, 5).addContent(T_activity_none);
}
}
/**
* Comparator to sort activity events by their access times.
*/
public static class ActivitySort<E extends CurrentActivityAction.Event> implements Comparator<E>, Serializable
{
// Sort parameter
private EventSort sortBy;
public ActivitySort(EventSort sortBy)
{
this.sortBy = sortBy;
}
/**
* Compare these two activity events based upon the given sort parameter. In the case of a tie,
* allways fallback to sorting based upon the timestamp.
*/
@Override
public int compare(E a, E b)
{
// Protect against null events while sorting
if (a != null && b == null)
{
return 1; // A > B
}
else if (a == null && b != null)
{
return -1; // B > A
}
else if (a == null && b == null)
{
return 0; // A == B
}
// Sort by the given ordering matrix
if (EventSort.URL == sortBy)
{
String aURL = a.getURL();
String bURL = b.getURL();
int cmp = aURL.compareTo(bURL);
if (cmp != 0)
{
return cmp;
}
}
else if (EventSort.AGENT == sortBy)
{
String aAgent = a.getDectectedBrowser();
String bAgent = b.getDectectedBrowser();
int cmp = aAgent.compareTo(bAgent);
if (cmp != 0)
{
return cmp;
}
}
else if (EventSort.IP == sortBy)
{
String aIP = a.getIP();
String bIP = b.getIP();
int cmp = aIP.compareTo(bIP);
if (cmp != 0)
{
return cmp;
}
}
else if (EventSort.SESSION == sortBy)
{
// Ensure that all sessions with an EPersonID associated are
// ordered to the top. Otherwise fall back to comparing session
// IDs. Unfortunitaly we can not compare eperson names because
// we do not have access to a context object.
if (a.getEPersonID() > 0 && b.getEPersonID() < 0)
{
return 1; // A > B
}
else if (a.getEPersonID() < 0 && b.getEPersonID() > 0)
{
return -1; // B > A
}
String aSession = a.getSessionID();
String bSession = b.getSessionID();
int cmp = aSession.compareTo(bSession);
if (cmp != 0)
{
return cmp;
}
}
// All ways fall back to sorting by time, when events are equal.
if (a.getTimeStamp() > b.getTimeStamp())
{
return 1; // A > B
}
else if (a.getTimeStamp() > b.getTimeStamp())
{
return -1; // B > A
}
return 0; // A == B
}
}
/**
* Add a section that allows management of the OAI harvester.
* @throws SQLException
*/
private void addHarvest(Division div) throws WingException, SQLException
{
// Remember we're in the harvest section
div.addHidden("harvest").setValue("true");
List harvesterControls = div.addList("oai-harvester-controls",List.TYPE_FORM);
harvesterControls.setHead(T_harvest_scheduler_head);
harvesterControls.addLabel(T_harvest_label_status);
Item status = harvesterControls.addItem();
status.addContent(HarvestScheduler.getStatus());
status.addXref(contextPath + "/admin/panel?harvest", "(refresh)");
harvesterControls.addLabel(T_harvest_label_actions);
Item actionsItem = harvesterControls.addItem();
if (HarvestScheduler.hasStatus(HarvestScheduler.HARVESTER_STATUS_STOPPED)) {
actionsItem.addButton("submit_harvest_start").setValue(T_harvest_submit_start);
actionsItem.addButton("submit_harvest_reset").setValue(T_harvest_submit_reset);
}
if (HarvestScheduler.hasStatus(HarvestScheduler.HARVESTER_STATUS_PAUSED))
{
actionsItem.addButton("submit_harvest_resume").setValue(T_harvest_submit_resume);
}
if (HarvestScheduler.hasStatus(HarvestScheduler.HARVESTER_STATUS_RUNNING) ||
HarvestScheduler.hasStatus(HarvestScheduler.HARVESTER_STATUS_SLEEPING))
{
actionsItem.addButton("submit_harvest_pause").setValue(T_harvest_submit_pause);
}
if (!HarvestScheduler.hasStatus(HarvestScheduler.HARVESTER_STATUS_STOPPED))
{
actionsItem.addButton("submit_harvest_stop").setValue(T_harvest_submit_stop);
}
// Can be retrieved via "{context-path}/admin/collection?collectionID={id}"
String baseURL = contextPath + "/admin/collection?collectionID=";
harvesterControls.addLabel(T_harvest_label_collections);
Item allCollectionsItem = harvesterControls.addItem();
java.util.List<Integer> allCollections = HarvestedCollection.findAll(context);
for (Integer oaiCollection : allCollections) {
allCollectionsItem.addXref(baseURL + oaiCollection, oaiCollection.toString());
}
harvesterControls.addLabel(T_harvest_label_active);
Item busyCollectionsItem = harvesterControls.addItem();
java.util.List<Integer> busyCollections = HarvestedCollection.findByStatus(context, HarvestedCollection.STATUS_BUSY);
for (Integer busyCollection : busyCollections) {
busyCollectionsItem.addXref(baseURL + busyCollection, busyCollection.toString());
}
harvesterControls.addLabel(T_harvest_label_queued);
Item queuedCollectionsItem = harvesterControls.addItem();
java.util.List<Integer> queuedCollections = HarvestedCollection.findByStatus(context, HarvestedCollection.STATUS_QUEUED);
for (Integer queuedCollection : queuedCollections) {
queuedCollectionsItem.addXref(baseURL + queuedCollection, queuedCollection.toString());
}
harvesterControls.addLabel(T_harvest_label_oai_errors);
Item oaiErrorsItem = harvesterControls.addItem();
java.util.List<Integer> oaiErrors = HarvestedCollection.findByStatus(context, HarvestedCollection.STATUS_OAI_ERROR);
for (Integer oaiError : oaiErrors) {
oaiErrorsItem.addXref(baseURL + oaiError, oaiError.toString());
}
harvesterControls.addLabel(T_harvest_label_internal_errors);
Item internalErrorsItem = harvesterControls.addItem();
java.util.List<Integer> internalErrors = HarvestedCollection.findByStatus(context, HarvestedCollection.STATUS_UNKNOWN_ERROR);
for (Integer internalError : internalErrors) {
internalErrorsItem.addXref(baseURL + internalError, internalError.toString());
}
// OAI Generator settings
List generatorSettings = div.addList("oai-generator-settings");
generatorSettings.setHead(T_harvest_head_generator_settings);
generatorSettings.addLabel(T_harvest_label_oai_url);
String oaiUrl = ConfigurationManager.getProperty("oai", "dspace.oai.url");
if (!StringUtils.isEmpty(oaiUrl))
{
generatorSettings.addItem(oaiUrl);
}
generatorSettings.addLabel(T_harvest_label_oai_source);
String oaiAuthoritativeSource = ConfigurationManager.getProperty("oai", "ore.authoritative.source");
if (!StringUtils.isEmpty(oaiAuthoritativeSource))
{
generatorSettings.addItem(oaiAuthoritativeSource);
}
else
{
generatorSettings.addItem("oai");
}
// OAI Harvester settings (just iterate over all the values that start with "harvester")
List harvesterSettings = div.addList("oai-harvester-settings");
harvesterSettings.setHead(T_harvest_head_harvester_settings);
String metaString = "harvester.";
Enumeration pe = ConfigurationManager.propertyNames();
while (pe.hasMoreElements())
{
String key = (String)pe.nextElement();
if (key.startsWith(metaString)) {
harvesterSettings.addLabel(key);
harvesterSettings.addItem(ConfigurationManager.getProperty(key) + " ");
}
}
}
/**
* Release all Cocoon resources.
* @see org.apache.avalon.framework.activity.Disposable#dispose()
*/
@Override
public void dispose()
{
if (this.serviceManager != null)
{
this.serviceManager.release(this.storePersistent);
this.serviceManager.release(this.storeJanitor);
this.serviceManager.release(this.storeDefault);
this.serviceManager.release(this.settings);
this.storePersistent = null;
this.storeJanitor = null;
this.storeDefault = null;
this.settings = null;
}
super.dispose();
}
}