org.lockss.servlet.DaemonStatus Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lockss-core Show documentation
Show all versions of lockss-core Show documentation
The Slimmed Down LOCKSS Daemon Core
The newest version!
/*
Copyright (c) 2000-2021 Board of Trustees of Leland Stanford Jr. University,
all rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
STANFORD UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Stanford University shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Stanford University.
*/
package org.lockss.servlet;
import java.io.*;
import java.util.*;
import java.util.regex.*;
import javax.servlet.*;
import org.apache.commons.lang3.StringUtils;
import org.mortbay.html.*;
import org.w3c.dom.Document;
import org.lockss.config.*;
import org.lockss.daemon.status.*;
import org.lockss.plugin.PluginManager;
import org.lockss.util.*;
import org.lockss.util.time.TimeBase;
/**
* DaemonStatus servlet
*/
public class DaemonStatus extends BaseDaemonStatus {
private static final Logger log = Logger.getLogger();
private String sortKey;
private StatusTable statTable;
private int outputFmt;
private java.util.List rules;
private BitSet tableOptions;
protected void resetLocals() {
super.resetLocals();
rules = null;
statTable = null;
rules = null;
}
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
static final Set fixedParams =
SetUtil.set("text", "output", "options", "table", "key", "sort");
/**
* Handle a request
* @throws IOException
*/
public void lockssHandleRequest() throws IOException {
if (!StringUtil.isNullString(req.getParameter("isDaemonReady"))) {
if (pluginMgr.areAusStartedOrStartOnDemand()) {
resp.setStatus(200);
PrintWriter wrtr = resp.getWriter();
resp.setContentType("text/plain");
wrtr.println("true");
} else {
PrintWriter wrtr = resp.getWriter();
resp.setContentType("text/plain");
wrtr.println("false");
resp.sendError(202, "Not ready");
}
return;
}
outputFmt = OUTPUT_HTML; // default output is html
String outputParam = req.getParameter("output");
if (!StringUtil.isNullString(outputParam)) {
if ("html".equalsIgnoreCase(outputParam)) {
outputFmt = OUTPUT_HTML;
} else if ("xml".equalsIgnoreCase(outputParam)) {
outputFmt = OUTPUT_XML;
} else if ("text".equalsIgnoreCase(outputParam)) {
outputFmt = OUTPUT_TEXT;
} else if ("csv".equalsIgnoreCase(outputParam)) {
outputFmt = OUTPUT_CSV;
} else {
log.warning("Unknown output format: " + outputParam);
}
}
String optionsParam = req.getParameter("options");
tableOptions = new BitSet();
tableName = req.getParameter("table");
if (handleForeignRedirect()) {
return;
}
if (isDebugUser()) {
log.debug2("Debug user. Setting OPTION_DEBUG_USER");
tableOptions.set(StatusTable.OPTION_DEBUG_USER);
}
for (Iterator iter = StringUtil.breakAt(optionsParam, ',').iterator();
iter.hasNext(); ) {
String s = (String)iter.next();
if ("norows".equalsIgnoreCase(s)) {
tableOptions.set(StatusTable.OPTION_NO_ROWS);
}
}
tableKey = req.getParameter("key");
if (StringUtil.isNullString(tableName)) {
tableName = statSvc.getDefaultTableName();
}
if (StringUtil.isNullString(tableKey)) {
tableKey = null;
}
sortKey = req.getParameter("sort");
if (StringUtil.isNullString(sortKey)) {
sortKey = null;
}
switch (outputFmt) {
case OUTPUT_HTML:
doHtmlStatusTable();
break;
case OUTPUT_XML:
try {
doXmlStatusTable();
} catch (XmlDomBuilder.XmlDomException xde) {
throw new IOException("Error building XML", xde);
}
break;
case OUTPUT_TEXT:
doTextStatusTable();
break;
case OUTPUT_CSV:
doCsvStatusTable();
break;
}
}
private Page newTablePage() throws IOException {
Page page = newPage();
addJavaScript(page);
if (!pluginMgr.areAusStartedOrStartOnDemand()) {
page.add(ServletUtil.notStartedWarning());
}
// After resp.getWriter() has been called, throwing an exception will
// result in a blank page, so don't call it until the end.
// (HttpResponse.sendError() calls getOutputStream(), and only one of
// getWriter() or getOutputStream() may be called.)
// all pages but index get a select box to choose a different table
if (!isAllTablesTable()) {
Block centeredBlock = new Block(Block.Center);
centeredBlock.add(getSelectTableForm());
page.add(centeredBlock);
page.add(ServletUtil.removeElementWithId("dsSelectBox"));
}
// page.add("");
// page.add(srvLink(SERVLET_DAEMON_STATUS, ".",
// concatParams("text=1", req.getQueryString())));
// page.add("
");
return page;
}
private void doHtmlStatusTable() throws IOException {
Page page = doHtmlStatusTable0();
endPage(page);
}
private void doTextStatusTable() throws IOException {
PrintWriter wrtr = resp.getWriter();
resp.setContentType("text/plain");
// String vPlatform = CurrentConfig.getParam(PARAM_PLATFORM_VERSION);
String vPlatform;
PlatformVersion pVer = ConfigManager.getPlatformVersion();
if (pVer != null) {
vPlatform = ", platform=" + StringUtil.ckvEscape(pVer.displayString());
} else {
vPlatform = "";
}
Date now = new Date();
Date startDate = getLockssDaemon().getStartDate();
wrtr.println("host=" + getLcapIPAddr() +
",time=" + now.getTime() +
",up=" + TimeBase.msSince(startDate.getTime()) +
",version=" + BuildInfo.getBuildInfoString() +
vPlatform);
doTextStatusTable(wrtr);
}
private StatusTable makeTable() throws StatusService.NoSuchTableException {
StatusTable table = new StatusTable(tableName, tableKey);
table.setOptions(tableOptions);
for (Enumeration en = req.getParameterNames(); en.hasMoreElements(); ) {
String name = (String)en.nextElement();
if (!fixedParams.contains(name)) {
table.setProperty(name, req.getParameter(name));
}
}
statSvc.fillInTable(table);
return table;
}
// build and send an XML DOM Document of the StatusTable
private void doXmlStatusTable()
throws IOException, XmlDomBuilder.XmlDomException {
// By default, XmlDomBuilder will produce UTF-8. Must set content type
// *before* calling getWriter()
resp.setContentType("text/xml; charset=UTF-8");
PrintWriter wrtr = resp.getWriter();
try {
StatusTable statTable = makeTable();
XmlStatusTable xmlTable = new XmlStatusTable(statTable);
String over = req.getParameter("outputVersion");
if (over != null) {
try {
int ver = Integer.parseInt(over);
xmlTable.setOutputVersion(ver);
} catch (NumberFormatException e) {
log.warning("Illegal outputVersion: " + over + ": " + e.toString());
}
}
Document xmlTableDoc = xmlTable.getTableDocument();
XmlDomBuilder.serialize(xmlTableDoc, wrtr);
} catch (Exception e) {
XmlDomBuilder xmlBuilder =
new XmlDomBuilder(XmlStatusConstants.NS_PREFIX,
XmlStatusConstants.NS_URI,
"1.0");
Document errorDoc = XmlDomBuilder.createDocument();
org.w3c.dom.Element rootElem = xmlBuilder.createRoot(errorDoc,
XmlStatusConstants.ERROR);
if (e instanceof StatusService.NoSuchTableException) {
XmlDomBuilder.addText(rootElem, "No such table: " + e.toString());
} else {
String emsg = e.toString();
StringBuilder buffer = new StringBuilder("Error getting table: ");
buffer.append(emsg);
buffer.append("\n");
buffer.append(StringUtil.trimStackTrace(emsg,
StringUtil.stackTraceString(e)));
XmlDomBuilder.addText(rootElem, buffer.toString());
}
XmlDomBuilder.serialize(errorDoc, wrtr);
return;
}
}
private java.util.List getRowList(StatusTable statTable) {
java.util.List rowList;
if (sortKey != null) {
try {
rules = makeSortRules(statTable, sortKey);
rowList = statTable.getSortedRows(rules);
} catch (Exception e) {
// There are lots of ways a user-specified sort can fail if the
// table creator isn't careful. Fall back to default if that
// happens.
log.warning("Error sorting table by: " + rules, e);
// XXX should display some sort of error msg
rowList = statTable.getSortedRows();
rules = null; // prevent column titles from indicating
// the sort order that didn't work
}
} else {
rowList = statTable.getSortedRows();
}
return rowList;
}
// Build the table, adding elements to page
private Page doHtmlStatusTable0() throws IOException {
Page page;
try {
statTable = makeTable();
} catch (StatusService.NoSuchTableException e) {
page = newTablePage();
errMsg = "No such table: " + e.getMessage();
layoutErrorBlock(page);
return page;
} catch (Exception e) {
page = newTablePage();
errMsg = "Error getting table: " + e.toString();
layoutErrorBlock(page);
if (isDebugUser()) {
page.add("
");
page.add(StringUtil.trimStackTrace(e.toString(),
StringUtil.stackTraceString(e)));
page.add("
");
}
return page;
}
java.util.List colList = statTable.getColumnDescriptors();
java.util.List rowList = getRowList(statTable);
String title0 = htmlEncode(statTable.getTitle());
String titleFoot = htmlEncode(statTable.getTitleFootnote());
page = newTablePage();
Table table = null;
// convert list of ColumnDescriptors to array of ColumnDescriptors
ColumnDescriptor cds[];
int cols;
if (colList != null) {
cds = (ColumnDescriptor [])colList.toArray(new ColumnDescriptor[0]);
cols = cds.length;
} else {
cds = new ColumnDescriptor[0];
cols = 1;
}
if (true || !rowList.isEmpty()) {
// if table not empty, output column headings
// Make the table. Make a narrow empty column between real columns,
// for spacing. Resulting table will have 2*cols-1 columns
table = new Table(0, "ALIGN=CENTER CELLSPACING=2 CELLPADDING=0");
String title = title0 + addFootnote(titleFoot);
table.newRow();
table.addHeading(title, "ALIGN=CENTER COLSPAN=" + (cols * 2 - 1));
table.newRow();
addSummaryInfo(table, statTable, cols);
if (colList != null) {
// output column headings
for (int ix = 0; ix < cols; ix++) {
ColumnDescriptor cd = cds[ix];
table.newCell("class=\"colhead\" valign=\"bottom\" align=\"" +
((cols == 1) ? "center" : getColAlignment(cd)) + "\"");
table.add(getColumnTitleElement(statTable, cd, rules));
if (ix < (cols - 1)) {
table.newCell("width=8");
table.add(" ");
}
}
}
}
// Create (but do not yet refer to) any footnotes that the table wants
// to be in a specific order
for (String orderedFoot : statTable.getOrderedFootnotes()) {
addFootnote(orderedFoot);
}
if (rowList != null) {
// output rows
for (Iterator rowIter = rowList.iterator(); rowIter.hasNext(); ) {
Map rowMap = (Map)rowIter.next();
if (rowMap.get(StatusTable.ROW_SEPARATOR) != null) {
table.newRow();
table.newCell("align=center colspan=" + (cols * 2 - 1));
table.add("
");
}
table.newRow();
for (int ix = 0; ix < cols; ix++) {
ColumnDescriptor cd = cds[ix];
Object val = rowMap.get(cd.getColumnName());
table.newCell("valign=\"top\" align=\"" + getColAlignment(cd) + "\"");
table.add(getDisplayString(val, cd.getType()));
if (ix < (cols - 1)) {
table.newCell(); // empty column for spacing
}
}
}
}
if (table != null) {
Form frm = new Form(srvURL(myServletDescr()));
// use GET so user can refresh in browser
frm.method("GET");
frm.add(table);
page.add(frm);
page.add("
");
}
return page;
}
/** Prepend table name to servlet-specfici part of page title */
protected String getTitleHeading() {
if (statTable == null) {
return super.getTitleHeading();
} else {
return statTable.getTitle() + " - " + super.getTitleHeading();
}
}
// Build the table, writing text to wrtr
private void doTextStatusTable(PrintWriter wrtr) throws IOException {
StatusTable statTable;
try {
statTable = makeTable();
} catch (StatusService.NoSuchTableException e) {
wrtr.println("No table: " + e.toString());
return;
} catch (Exception e) {
wrtr.println("Error getting table: " + e.toString());
return;
}
wrtr.println();
wrtr.print("table=" + StringUtil.ckvEscape(statTable.getTitle()));
if (tableKey != null) {
wrtr.print(",key=" + StringUtil.ckvEscape(tableKey));
}
java.util.List summary = statTable.getSummaryInfo();
if (summary != null && !summary.isEmpty()) {
for (Iterator iter = summary.iterator(); iter.hasNext(); ) {
StatusTable.SummaryInfo sInfo = (StatusTable.SummaryInfo)iter.next();
wrtr.print(",");
wrtr.print(sInfo.getTitle());
wrtr.print("=");
Object dispVal = getTextDisplayString(sInfo.getValue());
String valStr = dispVal != null ? dispVal.toString() : "(null)";
wrtr.print(StringUtil.ckvEscape(valStr));
}
}
wrtr.println();
java.util.List rowList = getRowList(statTable);
if (rowList != null) {
// output rows
for (Iterator rowIter = rowList.iterator(); rowIter.hasNext(); ) {
Map rowMap = (Map)rowIter.next();
for (Iterator iter = rowMap.keySet().iterator(); iter.hasNext(); ) {
Object o = iter.next();
if (!(o instanceof String)) {
// ignore special markers (eg, StatusTable.ROW_SEPARATOR)
continue;
}
String key = (String)o;
Object val = rowMap.get(key);
Object dispVal = getTextDisplayString(val);
String valStr = dispVal != null ? dispVal.toString() : "(null)";
wrtr.print(key + "=" + StringUtil.ckvEscape(valStr));
if (iter.hasNext()) {
wrtr.print(",");
} else {
wrtr.println();
}
}
}
}
}
// Build the table, writing csv to wrtr
private void doCsvStatusTable() throws IOException {
PrintWriter wrtr = resp.getWriter();
resp.setContentType("text/plain");
StatusTable statTable;
try {
statTable = makeTable();
} catch (StatusService.NoSuchTableException e) {
wrtr.println("No table: " + e.toString());
return;
} catch (Exception e) {
wrtr.println("Error getting table: " + e.toString());
return;
}
java.util.List colList =
statTable.getColumnDescriptors();
java.util.List