001: /*
002: * ControlPanel.java
003: *
004: * Version: $Revision: 1.3 $
005: *
006: * Date: $Date: 2006/07/13 23:20:54 $
007: *
008: * Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
009: * Institute of Technology. All rights reserved.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions are
013: * met:
014: *
015: * - Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * - Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in the
020: * documentation and/or other materials provided with the distribution.
021: *
022: * - Neither the name of the Hewlett-Packard Company nor the name of the
023: * Massachusetts Institute of Technology nor the names of their
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
030: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
032: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
033: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
034: * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
036: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
037: * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
038: * DAMAGE.
039: */
040: package org.dspace.app.xmlui.aspect.administrative;
041:
042: import java.io.IOException;
043: import java.sql.SQLException;
044: import java.util.ArrayList;
045: import java.util.Collections;
046: import java.util.Comparator;
047:
048: import org.apache.avalon.framework.service.ServiceException;
049: import org.apache.avalon.framework.service.ServiceManager;
050: import org.apache.avalon.framework.service.Serviceable;
051: import org.apache.cocoon.components.flow.ContinuationsManager;
052: import org.apache.cocoon.components.flow.WebContinuation;
053: import org.apache.cocoon.components.flow.WebContinuationDataBean;
054: import org.apache.cocoon.environment.ObjectModelHelper;
055: import org.apache.cocoon.environment.Request;
056: import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
057: import org.dspace.app.xmlui.utils.UIException;
058: import org.dspace.app.xmlui.wing.Message;
059: import org.dspace.app.xmlui.wing.WingException;
060: import org.dspace.app.xmlui.wing.element.Body;
061: import org.dspace.app.xmlui.wing.element.Division;
062: import org.dspace.app.xmlui.wing.element.Item;
063: import org.dspace.app.xmlui.wing.element.List;
064: import org.dspace.app.xmlui.wing.element.PageMeta;
065: import org.dspace.app.xmlui.wing.element.Row;
066: import org.dspace.app.xmlui.wing.element.Select;
067: import org.dspace.app.xmlui.wing.element.Table;
068: import org.dspace.app.xmlui.wing.element.TextArea;
069: import org.dspace.authorize.AuthorizeException;
070: import org.dspace.authorize.AuthorizeManager;
071: import org.dspace.core.ConfigurationManager;
072: import org.xml.sax.SAXException;
073:
074: /**
075: * This page displays important (and some not-so important) systems
076: * type information about your running dspace.
077: *
078: * @author Jay Paz
079: * @author Scott Phillips
080: */
081: public class ControlPanel extends AbstractDSpaceTransformer implements
082: Serviceable {
083:
084: /** Language Strings */
085: private static final Message T_DSPACE_HOME = message("xmlui.general.dspace_home");
086: private static final Message T_title = message("xmlui.administrative.ControlPanel.title");
087: private static final Message T_trail = message("xmlui.administrative.ControlPanel.trail");
088: private static final Message T_head = message("xmlui.administrative.ControlPanel.head");
089: private static final Message T_option_java = message("xmlui.administrative.ControlPanel.option_java");
090: private static final Message T_option_dspace = message("xmlui.administrative.ControlPanel.option_dspace");
091: private static final Message T_option_knots = message("xmlui.administrative.ControlPanel.option_knots");
092: private static final Message T_option_alerts = message("xmlui.administrative.ControlPanel.option_alerts");
093: private static final Message T_JAVA_HEAD = message("xmlui.administrative.ControlPanel.java_head");
094: private static final Message T_JAVA_VERSION = message("xmlui.administrative.ControlPanel.java_version");
095: private static final Message T_JAVA_VENDOR = message("xmlui.administrative.ControlPanel.java_vendor");
096: private static final Message T_OS_NAME = message("xmlui.administrative.ControlPanel.os_name");
097: private static final Message T_OS_ARCH = message("xmlui.administrative.ControlPanel.os_arch");
098: private static final Message T_OS_VERSION = message("xmlui.administrative.ControlPanel.os_version");
099: private static final Message T_RUNTIME_HEAD = message("xmlui.administrative.ControlPanel.runtime_head");
100: private static final Message T_RUNTIME_PROCESSORS = message("xmlui.administrative.ControlPanel.runtime_processors");
101: private static final Message T_RUNTIME_MAX = message("xmlui.administrative.ControlPanel.runtime_max");
102: private static final Message T_RUNTIME_TOTAL = message("xmlui.administrative.ControlPanel.runtime_total");
103: private static final Message T_RUNTIME_USED = message("xmlui.administrative.ControlPanel.runtime_used");
104: private static final Message T_RUNTIME_FREE = message("xmlui.administrative.ControlPanel.runtime_free");
105: private static final Message T_DSPACE_HEAD = message("xmlui.administrative.ControlPanel.dspace_head");
106: private static final Message T_DSPACE_DIR = message("xmlui.administrative.ControlPanel.dspace_dir");
107: private static final Message T_DSPACE_URL = message("xmlui.administrative.ControlPanel.dspace_url");
108: private static final Message T_DSPACE_HOST_NAME = message("xmlui.administrative.ControlPanel.dspace_hostname");
109: private static final Message T_DSPACE_NAME = message("xmlui.administrative.ControlPanel.dspace_name");
110: private static final Message T_DB_NAME = message("xmlui.administrative.ControlPanel.db_name");
111: private static final Message T_DB_URL = message("xmlui.administrative.ControlPanel.db_url");
112: private static final Message T_DB_DRIVER = message("xmlui.administrative.ControlPanel.db_driver");
113: private static final Message T_DB_MAX_CONN = message("xmlui.administrative.ControlPanel.db_maxconnections");
114: private static final Message T_DB_MAX_WAIT = message("xmlui.administrative.ControlPanel.db_maxwait");
115: private static final Message T_DB_MAX_IDLE = message("xmlui.administrative.ControlPanel.db_maxidle");
116: private static final Message T_MAIL_SERVER = message("xmlui.administrative.ControlPanel.mail_server");
117: private static final Message T_MAIL_FROM_ADDRESS = message("xmlui.administrative.ControlPanel.mail_from_address");
118: private static final Message T_FEEDBACK_RECIPIENT = message("xmlui.administrative.ControlPanel.mail_feedback_recipient");
119: private static final Message T_MAIL_ADMIN = message("xmlui.administrative.ControlPanel.mail_admin");
120: private static final Message T_knots_head = message("xmlui.administrative.ControlPanel.knots_head");
121: private static final Message T_knots_column1 = message("xmlui.administrative.ControlPanel.knots_column1");
122: private static final Message T_knots_column2 = message("xmlui.administrative.ControlPanel.knots_column2");
123: private static final Message T_knots_column3 = message("xmlui.administrative.ControlPanel.knots_column3");
124: private static final Message T_knots_hours = message("xmlui.administrative.ControlPanel.knots_hours");
125: private static final Message T_knots_minutes = message("xmlui.administrative.ControlPanel.knots_minutes");
126: private static final Message T_knots_expired = message("xmlui.administrative.ControlPanel.knots_expired");
127: private static final Message T_knots_active = message("xmlui.administrative.ControlPanel.knots_active");
128: private static final Message T_knots_none = message("xmlui.administrative.ControlPanel.knots_none");
129: private static final Message T_alerts_head = message("xmlui.administrative.ControlPanel.alerts_head");
130: private static final Message T_alerts_warning = message("xmlui.administrative.ControlPanel.alerts_warning");
131: private static final Message T_alerts_message_label = message("xmlui.administrative.ControlPanel.alerts_message_label");
132: private static final Message T_alerts_message_default = message("xmlui.administrative.ControlPanel.alerts_message_default");
133: private static final Message T_alerts_countdown_label = message("xmlui.administrative.ControlPanel.alerts_countdown_label");
134: private static final Message T_alerts_countdown_none = message("xmlui.administrative.ControlPanel.alerts_countdown_none");
135: private static final Message T_alerts_countdown_5 = message("xmlui.administrative.ControlPanel.alerts_countdown_5");
136: private static final Message T_alerts_countdown_15 = message("xmlui.administrative.ControlPanel.alerts_countdown_15");
137: private static final Message T_alerts_countdown_30 = message("xmlui.administrative.ControlPanel.alerts_countdown_30");
138: private static final Message T_alerts_countdown_60 = message("xmlui.administrative.ControlPanel.alerts_countdown_60");
139: private static final Message T_alerts_countdown_keep = message("xmlui.administrative.ControlPanel.alerts_countdown_keep");
140: private static final Message T_alerts_submit_activate = message("xmlui.administrative.ControlPanel.alerts_submit_activate");
141: private static final Message T_alerts_submit_deactivate = message("xmlui.administrative.ControlPanel.alerts_submit_deactivate");
142: private static final Message T_select_panel = message("xmlui.administrative.ControlPanel.select_panel");
143: /**
144: * The service manager allows us to access the continuation's
145: * manager, it is obtained from the servicable API
146: */
147: private ServiceManager serviceManager;
148:
149: /**
150: * The four states that this page can be in.
151: */
152: private enum OPTIONS {
153: java, dspace, knots, alerts
154: };
155:
156: /**
157: * From the servicable api, give us a service manager.
158: */
159: public void service(ServiceManager serviceManager)
160: throws ServiceException {
161: this .serviceManager = serviceManager;
162: }
163:
164: public void addPageMeta(PageMeta pageMeta) throws SAXException,
165: WingException, UIException, SQLException, IOException,
166: AuthorizeException {
167: pageMeta.addMetadata("title").addContent(T_title);
168:
169: pageMeta.addTrailLink(contextPath + "/", T_DSPACE_HOME);
170: pageMeta.addTrailLink(contextPath + "/admin/panel", T_trail);
171: }
172:
173: public void addBody(Body body) throws SAXException, WingException,
174: UIException, SQLException, IOException, AuthorizeException {
175:
176: if (!AuthorizeManager.isAdmin(context))
177: throw new AuthorizeException(
178: "You are not authorized to view this page.");
179:
180: Request request = ObjectModelHelper.getRequest(objectModel);
181: OPTIONS option = null;
182: if (request.getParameter("java") != null)
183: option = OPTIONS.java;
184: if (request.getParameter("dspace") != null)
185: option = OPTIONS.dspace;
186: if (request.getParameter("knots") != null)
187: option = OPTIONS.knots;
188: if (request.getParameter("alerts") != null)
189: option = OPTIONS.alerts;
190:
191: Division div = body.addInteractiveDivision("control-panel",
192: contextPath + "/admin/panel", Division.METHOD_POST,
193: "primary administrative");
194: div.setHead(T_head);
195:
196: // LIST: options
197: List options = div.addList("options", List.TYPE_SIMPLE,
198: "horizontal");
199:
200: // our options, selected or not....
201: if (option == OPTIONS.java)
202: options.addItem().addHighlight("bold").addXref("?java",
203: T_option_java);
204: else
205: options.addItemXref("?java", T_option_java);
206:
207: if (option == OPTIONS.dspace)
208: options.addItem().addHighlight("bold").addXref("?dspace",
209: T_option_dspace);
210: else
211: options.addItemXref("?dspace", T_option_dspace);
212:
213: if (option == OPTIONS.knots)
214: options.addItem().addHighlight("bold").addXref("?knots",
215: T_option_knots);
216: else
217: options.addItemXref("?knots", T_option_knots);
218:
219: if (option == OPTIONS.alerts)
220: options.addItem().addHighlight("bold").addXref("?alerts",
221: T_option_alerts);
222: else
223: options.addItemXref("?alerts", T_option_alerts);
224:
225: // The main content:
226: if (option == OPTIONS.java)
227: addJavaInformation(div);
228: else if (option == OPTIONS.dspace)
229: addDSpaceConfiguration(div);
230: else if (option == OPTIONS.knots)
231: addWebContinuations(div);
232: else if (option == OPTIONS.alerts)
233: addAlerts(div);
234: else {
235: div.addPara(T_select_panel);
236: }
237:
238: }
239:
240: /**
241: * Add specific java information including JRE, OS, and runtime memory statistics.
242: */
243: private void addJavaInformation(Division div) throws WingException {
244: // Get memory statistics
245: int processors = Runtime.getRuntime().availableProcessors();
246: long maxMemory = Runtime.getRuntime().maxMemory();
247: long totalMemory = Runtime.getRuntime().totalMemory();
248: long freeMemory = Runtime.getRuntime().freeMemory();
249: long usedMemory = totalMemory - freeMemory;
250:
251: // Convert bytes into MiB
252: maxMemory = maxMemory / 1024 / 1024;
253: totalMemory = totalMemory / 1024 / 1024;
254: usedMemory = usedMemory / 1024 / 1024;
255: freeMemory = freeMemory / 1024 / 1024;
256:
257: // LIST: Java
258: List list = div.addList("javaOs");
259: list.setHead(T_JAVA_HEAD);
260: list.addLabel(T_JAVA_VERSION);
261: list.addItem(System.getProperty("java.version"));
262: list.addLabel(T_JAVA_VENDOR);
263: list.addItem(System.getProperty("java.vendor"));
264: list.addLabel(T_OS_NAME);
265: list.addItem(System.getProperty("os.name"));
266: list.addLabel(T_OS_ARCH);
267: list.addItem(System.getProperty("os.arch"));
268: list.addLabel(T_OS_VERSION);
269: list.addItem(System.getProperty("os.version"));
270:
271: // LIST: memory
272: List runtime = div.addList("runtime");
273: runtime.setHead(T_RUNTIME_HEAD);
274: runtime.addLabel(T_RUNTIME_PROCESSORS);
275: runtime.addItem(String.valueOf(processors));
276: runtime.addLabel(T_RUNTIME_MAX);
277: runtime.addItem(String.valueOf(maxMemory) + " MiB");
278: runtime.addLabel(T_RUNTIME_TOTAL);
279: runtime.addItem(String.valueOf(totalMemory) + " MiB");
280: runtime.addLabel(T_RUNTIME_USED);
281: runtime.addItem(String.valueOf(usedMemory) + " MiB");
282: runtime.addLabel(T_RUNTIME_FREE);
283: runtime.addItem(String.valueOf(freeMemory) + " MiB");
284: }
285:
286: /**
287: * List important DSpace configuration parameters.
288: */
289: private void addDSpaceConfiguration(Division div)
290: throws WingException {
291: // LIST: DSpace
292: List dspace = div.addList("dspace");
293: dspace.setHead(T_DSPACE_HEAD);
294:
295: dspace.addLabel(T_DSPACE_DIR);
296: dspace.addItem(ConfigurationManager.getProperty("dspace.dir"));
297:
298: dspace.addLabel(T_DSPACE_URL);
299: dspace.addItem(ConfigurationManager.getProperty("dspace.url"));
300:
301: dspace.addLabel(T_DSPACE_HOST_NAME);
302: dspace.addItem(ConfigurationManager
303: .getProperty("dspace.hostname"));
304:
305: dspace.addLabel(T_DSPACE_NAME);
306: dspace.addItem(ConfigurationManager.getProperty("dspace.name"));
307:
308: dspace.addLabel(T_DB_NAME);
309: dspace.addItem(ConfigurationManager.getProperty("db.name"));
310:
311: dspace.addLabel(T_DB_URL);
312: dspace.addItem(ConfigurationManager.getProperty("db.url"));
313:
314: dspace.addLabel(T_DB_DRIVER);
315: dspace.addItem(ConfigurationManager.getProperty("db.driver"));
316:
317: dspace.addLabel(T_DB_MAX_CONN);
318: dspace.addItem(ConfigurationManager
319: .getProperty("db.maxconnections"));
320:
321: dspace.addLabel(T_DB_MAX_WAIT);
322: dspace.addItem(ConfigurationManager.getProperty("db.maxwait"));
323:
324: dspace.addLabel(T_DB_MAX_IDLE);
325: dspace.addItem(ConfigurationManager.getProperty("db.maxidle"));
326:
327: dspace.addLabel(T_MAIL_SERVER);
328: dspace.addItem(ConfigurationManager.getProperty("mail.server"));
329:
330: dspace.addLabel(T_MAIL_FROM_ADDRESS);
331: dspace.addItem(ConfigurationManager
332: .getProperty("mail.from.address"));
333:
334: dspace.addLabel(T_FEEDBACK_RECIPIENT);
335: dspace.addItem(ConfigurationManager
336: .getProperty("feedback.recipient"));
337:
338: dspace.addLabel(T_MAIL_ADMIN);
339: dspace.addItem(ConfigurationManager.getProperty("mail.admin"));
340: }
341:
342: /**
343: * Add a list of all active web continuations.
344: */
345: private void addWebContinuations(Division div) throws WingException {
346: // Get all the web continuations and sort them.
347: ArrayList<WebContinuation> knots = new ArrayList<WebContinuation>();
348: try {
349: // Get a list of all continuations
350: ContinuationsManager continuationManager = (ContinuationsManager) serviceManager
351: .lookup(ContinuationsManager.ROLE);
352: @SuppressWarnings("unchecked")
353: // the cast is correct
354: java.util.List<WebContinuationDataBean> knotBeans = continuationManager
355: .getWebContinuationsDataBeanList();
356: for (WebContinuationDataBean flow : knotBeans) {
357: WebContinuation knot = continuationManager
358: .lookupWebContinuation(flow.getId(), flow
359: .getInterpreterId());
360:
361: if (knot != null)
362: knots.add(knot);
363: }
364:
365: // Sort them based upon access time
366: Collections
367: .sort(
368: knots,
369: new WebContinuationByAccessTimeComparator<WebContinuation>());
370:
371: // Reverse it so that the shortest times are at the top.
372: Collections.reverse(knots);
373: } catch (ServiceException se) {
374: throw new UIException(
375: "Unable to query continuation states.", se);
376: }
377:
378: // LIST: Flows
379: Table activeFlows = div.addTable("knots", 1, 1);
380: activeFlows.setHead(T_knots_head);
381:
382: Row row = activeFlows.addRow(Row.ROLE_HEADER);
383: row.addCellContent(T_knots_column1);
384: row.addCellContent(T_knots_column2);
385: row.addCellContent(T_knots_column3);
386:
387: for (WebContinuation knot : knots) {
388: String interpreter = knot.getInterpreterId();
389: if (interpreter != null && interpreter.length() > 45)
390: interpreter = "..."
391: + interpreter
392: .substring(interpreter.length() - 43);
393:
394: Message lastAccessMessage = null;
395: long lastAccess = System.currentTimeMillis()
396: - knot.getLastAccessTime();
397: if (lastAccess > 2 * 60 * 60 * 1000)
398: lastAccessMessage = T_knots_hours
399: .parameterize((lastAccess / (60 * 60 * 1000)));
400: else
401: lastAccessMessage = T_knots_minutes
402: .parameterize((lastAccess / (60 * 1000)));
403:
404: row = activeFlows.addRow();
405: row.addCellContent(interpreter);
406: row.addCellContent(lastAccessMessage);
407: row.addCellContent(knot.hasExpired() ? T_knots_expired
408: : T_knots_active);
409: }
410:
411: if (knots.size() == 0) {
412: activeFlows.addRow().addCell(1, 3).addContent(T_knots_none);
413: }
414: }
415:
416: /**
417: * Comparator to sort webcontinuations by their access times.
418: */
419: public static class WebContinuationByAccessTimeComparator<WC extends WebContinuation>
420: implements Comparator<WC> {
421: public int compare(WC a, WC b) {
422: if (a.getLastAccessTime() > b.getLastAccessTime())
423: return 1; // A > B
424: else if (a.getLastAccessTime() > b.getLastAccessTime())
425: return -1; // B < A
426: return 0; // A == B
427: }
428:
429: }
430:
431: /**
432: * Add a section that allows administrators to activate or deactivate system-wide alerts.
433: */
434: private void addAlerts(Division div) throws WingException {
435: // Remember we're in teh alerts section
436: div.addHidden("alerts").setValue("true");
437:
438: List form = div.addList("system-wide-alerts", List.TYPE_FORM);
439: form.setHead(T_alerts_head);
440:
441: form.addItem(T_alerts_warning);
442:
443: TextArea message = form.addItem().addTextArea("message");
444: message.setLabel(T_alerts_message_label);
445: message.setSize(5, 45);
446: if (SystemwideAlerts.getMessage() == null)
447: message.setValue(T_alerts_message_default);
448: else
449: message.setValue(SystemwideAlerts.getMessage());
450:
451: Select countdown = form.addItem().addSelect("countdown");
452: countdown.setLabel(T_alerts_countdown_label);
453:
454: countdown.addOption(0, T_alerts_countdown_none);
455: countdown.addOption(5, T_alerts_countdown_5);
456: countdown.addOption(15, T_alerts_countdown_15);
457: countdown.addOption(30, T_alerts_countdown_30);
458: countdown.addOption(60, T_alerts_countdown_60);
459:
460: // Is there a current count down active?
461: if (SystemwideAlerts.isAlertActive()
462: && SystemwideAlerts.getCountDownToo()
463: - System.currentTimeMillis() > 0)
464: countdown.addOption(true, -1, T_alerts_countdown_keep);
465: else
466: countdown.setOptionSelected(0);
467:
468: Item actions = form.addItem();
469: actions.addButton("submit_activate").setValue(
470: T_alerts_submit_activate);
471: actions.addButton("submit_deactivate").setValue(
472: T_alerts_submit_deactivate);
473:
474: }
475:
476: }
|