/** * 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(); } }