/* * Copyright(c) 2005 Center for E-Commerce Infrastructure Development, The * University of Hong Kong (HKU). All Rights Reserved. * * This software is licensed under the Apache License Version 2.0 [1] * * [1] http://www.apache.org/licenses/LICENSE-2.0.txt */ package hk.hku.cecid.piazza.corvus.admin.listener; import hk.hku.cecid.piazza.commons.Sys; import hk.hku.cecid.piazza.commons.pagelet.PageletStore; import hk.hku.cecid.piazza.commons.pagelet.TemplateElement; import hk.hku.cecid.piazza.commons.pagelet.xslt.BorderLayoutPageletAdaptor; import hk.hku.cecid.piazza.commons.util.DataFormatter; import hk.hku.cecid.piazza.commons.util.PropertyTree; import hk.hku.cecid.piazza.corvus.admin.menu.MenuComponent; import hk.hku.cecid.piazza.corvus.core.Kernel; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.TreeSet; import javax.servlet.http.HttpServletRequest; import javax.xml.transform.Source; /** * AdminPageletAdaptor is an HTTP-XSLT pagelet adaptor. It generally serves as a * main framework for the admin pages. Pages generated by this pagelet are in * border layout format corresponding to the pre-defined template. * <p> * Subclasses are expected to override the getCenterSource() method and provide * implementation for the generation of the transformation source which * contributes to the center region of the page being rendered. * * @author Hugo Y. K. Lam * */ public class AdminPageletAdaptor extends BorderLayoutPageletAdaptor { /** * The pagelet store of this pagelet. */ public final static PageletStore store = new PageletStore(); /** * The modules of this pagelet. */ public final static Set modules = Collections.synchronizedSortedSet(new TreeSet()); /** * The prefix of the attriute name used in this pagelet. */ protected final static String ATTR_PREFIX = AdminPageletAdaptor.class.getName() + "."; /** * The attribute name of the message attribute. */ protected final static String ATTR_MESSAGE = ATTR_PREFIX + "message"; /** * Indicator of menu type Module. */ private final static String MENU_TYPE_MODULE = "module"; /** * Indicator of menu type Tab. */ private final static String MENU_TYPE_TAB = "tab"; /** * @see hk.hku.cecid.piazza.commons.pagelet.PageletStore */ protected PageletStore getPageletStore() { return store; } /** * Gets the module ID that this pagelet represents. This method will look * up the listener parameter 'module'. * * @param request the servlet request. * @return the module ID. */ protected String getModuleId(HttpServletRequest request) { return getParameters().getProperty("module"); } /** * Gets the tab ID that this pagelet represents. This method will look * up the listener parameter 'tab'. * * @param request the servlet request. * @return the tab ID. */ protected String getTabId(HttpServletRequest request) { return getParameters().getProperty("tab"); } /** * Gets the transformation source of the menu tabs. * * @see hk.hku.cecid.piazza.commons.pagelet.xslt.BorderLayoutPageletAdaptor#getNorthSource(javax.servlet.http.HttpServletRequest) */ protected Source getNorthSource(HttpServletRequest request) { return getMenuComponentSource(request, MENU_TYPE_TAB); } /** * Gets the transformation source of the menu modules. * * @see hk.hku.cecid.piazza.commons.pagelet.xslt.BorderLayoutPageletAdaptor#getWestSource(javax.servlet.http.HttpServletRequest) */ protected Source getWestSource(HttpServletRequest request) { return getMenuComponentSource(request, MENU_TYPE_MODULE); } /** * Gets the transformation source of the specified menu type. * * @param request the servlet request. * @param type the menu type. * @return the transformation source of the specified menu type. */ private Source getMenuComponentSource(HttpServletRequest request, String type) { Source componentSource = (Source)request.getAttribute(ATTR_PREFIX + type); if (componentSource == null) { Collection tabs = generateMenuComponentSource(request, modules, getModuleId(request), -1, MENU_TYPE_MODULE); generateMenuComponentSource(request, tabs, getTabId(request), 12, MENU_TYPE_TAB); componentSource = (Source)request.getAttribute(ATTR_PREFIX + type); } return componentSource; } /** * Generates the transformation source of the specified menu type by the * given menu components. The generated source will be stored as a request * attribute having an attribute name [ATTR_PREFIX][MENU_TYPE]. * * @param request the servlet request. * @param components the menu components. * @param selectedId the ID of the selected component. * @param maxComponentWidth the maximum width of each component's caption. * @param type the menu type. * @return the sub-menu components of the selected menu or an empty collection. * * @see #ATTR_PREFIX */ private Collection generateMenuComponentSource(HttpServletRequest request, Collection components, String selectedId, int maxComponentWidth, String type) { boolean isAlreadySelected = false; String basePath = "/"+type+"s"; PropertyTree dom = new PropertyTree(); dom.setProperty(basePath, ""); List subcomponents = null; Iterator allComponents = components.iterator(); for (int i=1; allComponents.hasNext(); i++) { MenuComponent component = (MenuComponent)allComponents.next(); boolean componentSelected = !isAlreadySelected && selectedId != null && selectedId.equals(component.getId()); isAlreadySelected = isAlreadySelected || componentSelected; if (component.isVisible()) { String componentName = component.getName(); if (maxComponentWidth >= 3) { if (componentName.length()>maxComponentWidth) { componentName = componentName.substring(0, maxComponentWidth-3) + "..."; } } String componentPath = basePath + "/"+ type; dom.setProperty(componentPath+"["+i+"]/name", componentName); dom.setProperty(componentPath+"["+i+"]/description", component.getDescription()); dom.setProperty(componentPath+"["+i+"]/link", request.getContextPath() + component.getLink()); if (componentSelected) { dom.setProperty(componentPath+"["+i+"]/selected", ""); } } else { i--; } if (componentSelected) { subcomponents = component.getChildren(); } } request.setAttribute(ATTR_PREFIX + type, dom.getSource()); return (subcomponents == null? Collections.EMPTY_LIST:subcomponents); } /** * Gets the transformation source of the message area. The source will be * generated according to the message attribute. * * @param request the servlet request. * @return the transformation source of the message area. * * @see #ATTR_MESSAGE * @see hk.hku.cecid.piazza.commons.pagelet.xslt.BorderLayoutPageletAdaptor#getSouthSource(javax.servlet.http.HttpServletRequest) */ protected Source getSouthSource(HttpServletRequest request) { Object message = request.getAttribute(ATTR_MESSAGE); PropertyTree dom = new PropertyTree(); dom.setProperty("/message", ""); if (message!=null) { dom.setProperty("description", message.toString()); } return dom.getSource(); } /** * Gets the transformation source of the main body. This method by default * generates a transformation source of the system status. Sub-classes * should override this method and provide its own implementation. * * @param request the servlet request. * @return the transformation source of the system status. * @see hk.hku.cecid.piazza.commons.pagelet.xslt.BorderLayoutPageletAdaptor#getCenterSource(javax.servlet.http.HttpServletRequest) */ protected Source getCenterSource(HttpServletRequest request) { String action = request.getParameter(REQ_PARAM_ACTION); if ("gc".equalsIgnoreCase(action)) { System.gc(); request.setAttribute(ATTR_MESSAGE, "Garbage collection initiated"); } else if ("final".equalsIgnoreCase(action)) { System.runFinalization(); request.setAttribute(ATTR_MESSAGE, "Finalization initiated"); } PropertyTree dom = new PropertyTree(); dom.setProperty("/home", ""); Date startupTime = Kernel.getInstance().getStartupTime(); Date currentTime = new Date(System.currentTimeMillis()); long elapsedTime = currentTime.getTime() - startupTime.getTime(); long days = elapsedTime/86400000; long hours= (elapsedTime%86400000)/3600000; long mins = ((elapsedTime%86400000)%3600000)/60000; long secs = (((elapsedTime%86400000)%3600000)%60000)/1000; String upTime = days + " days " + hours + " hours " + mins + " mins " + secs + " secs"; dom.setProperty("system/name", Sys.main.getName()); dom.setProperty("system/version", Sys.main.getVersion()); dom.setProperty("system/buildID", Sys.main.getBuildID()); dom.setProperty("system/startup-time", startupTime.toString()); dom.setProperty("system/current-time", currentTime.toString()); dom.setProperty("system/up-time", upTime); dom.setProperty("system/processors", String.valueOf(Runtime.getRuntime().availableProcessors())); long maxMemory = Runtime.getRuntime().maxMemory()/1048576; long totalMemory = Runtime.getRuntime().totalMemory()/1048576; long freeMemory = Runtime.getRuntime().freeMemory()/1048576; long usedMemory = totalMemory - freeMemory; String memoryUsage = DataFormatter.getInstance().formatDecimal( (((double)usedMemory) / maxMemory) * 100); dom.setProperty("memory/max", maxMemory + " MB"); dom.setProperty("memory/total", totalMemory + " MB"); dom.setProperty("memory/used", usedMemory + " MB"); dom.setProperty("memory/free", freeMemory + " MB"); dom.setProperty("memory/usage", memoryUsage + "%"); return dom.getSource(); } /** * Gets transformation source which represents the error generated by any of * the pagelets composing the page being generated by this pagelet. * * @see hk.hku.cecid.piazza.commons.pagelet.xslt.HttpXsltPageletAdaptor#getErrorSource(TemplateElement,Throwable,HttpServletRequest) */ protected Source getErrorSource(TemplateElement element, Throwable e, HttpServletRequest request) { PropertyTree dom = new PropertyTree(); dom.setProperty("/error", ""); dom.setProperty("plugin", getModuleId(request)); dom.setProperty("home_directory", Sys.main.properties.getProperty("/corvus/home")); dom.setProperty("time", new Date().toString()); return dom.getSource(); } }