blob: 19c5ee882aff434d8dab74216040a3fb86c8f192 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.admin.jmx.internal;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.geode.annotations.Immutable;
import org.apache.geode.internal.ExitCode;
import org.apache.geode.internal.classloader.ClassPathLoader;
/**
* A tool that reads the XML description of MBeans used with the Jakarta Commons Modeler and
* generates an HTML file that documents each MBean.
*
* @since GemFire 3.5
*/
@Deprecated
public class GenerateMBeanHTML extends DefaultHandler {
/** The location of the DTD for the MBean descriptions */
private static final String DTD_LOCATION =
"/org/apache/geode/admin/jmx/internal/doc-files/mbeans-descriptors.dtd";
/** The name of the "mbean-descriptors" element */
private static final String MBEANS_DESCRIPTORS = "mbeans-descriptors";
/** The name of the "mbean" element */
private static final String MBEAN = "mbean";
/** The name of the "name" attribute */
private static final String NAME = "name";
/** The name of the "description" attribute */
private static final String DESCRIPTION = "description";
/** The name of the "type" attribute */
private static final String TYPE = "type";
/** The name of the "attribute" element */
private static final String ATTRIBUTE = "attribute";
/** The name of the "writeable" attribute */
private static final String WRITEABLE = "writeable";
/** The name of the "operation" element */
private static final String OPERATION = "operation";
/** The name of the "returnType" attribute */
private static final String RETURN_TYPE = "returnType";
/** The name of the "paremeter" element */
private static final String PARAMETER = "parameter";
/** The name of the "notification" element */
private static final String NOTIFICATION = "notification";
/** The name of the "field" element */
private static final String FIELD = "field";
/** The name of the "value" attribute */
private static final String VALUE = "value";
////////////////////// Instance Fields ///////////////////////
/** Where the generated HTML data is written */
private final PrintWriter pw;
/** Have we seen attributes for the current MBean? */
private boolean seenAttribute = false;
/** Have we seen operations for the current MBean? */
private boolean seenOperation = false;
/** Have we seen notifications for the current MBean? */
private boolean seenNotifications = false;
/////////////////////// Static Methods ///////////////////////
/**
* Converts data from the given <code>InputStream</code> into HTML that is written to the given
* <code>PrintWriter</code>
*/
private static void convert(InputStream in, PrintWriter out) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(true);
SAXParser parser = factory.newSAXParser();
DefaultHandler handler = new GenerateMBeanHTML(out);
parser.parse(in, handler);
}
//////////////////////// Constructors ////////////////////////
/**
* Creates a new <code>GenerateMBeanHTML</code> that writes to the given <code>PrintWriter</code>.
*/
private GenerateMBeanHTML(PrintWriter pw) {
this.pw = pw;
}
////////////////////// Instance Methods //////////////////////
/**
* Given a public id, attempt to resolve it to a DTD. Returns an <code>InputSoure</code> for the
* DTD.
*/
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
if (publicId == null || systemId == null) {
throw new SAXException(String.format("Public Id: %s System Id: %s",
publicId, systemId));
}
// Figure out the location for the publicId.
String location = DTD_LOCATION;
InputSource result;
{
InputStream stream = ClassPathLoader.getLatest().getResourceAsStream(getClass(), location);
if (stream != null) {
result = new InputSource(stream);
} else {
throw new SAXNotRecognizedException(
String.format("DTD not found: %s", location));
}
}
return result;
}
/**
* Warnings are ignored
*/
@Override
public void warning(SAXParseException ex) throws SAXException {
}
/**
* Rethrow the <code>SAXParseException</code>
*/
@Override
public void error(SAXParseException ex) throws SAXException {
throw ex;
}
/**
* Rethrow the <code>SAXParseException</code>
*/
@Override
public void fatalError(SAXParseException ex) throws SAXException {
throw ex;
}
/**
* Starts the HTML document
*/
private void startMBeansDescriptors() {
pw.println("<HTML>");
pw.println("<HEAD>");
pw.println("<TITLE>GemFire MBeans Interface</TITLE>");
pw.println("</HEAD>");
pw.println("");
pw.println("<h1>GemFire Management Beans</h1>");
pw.println("");
pw.println("<P>This document describes the attributes, operations,");
pw.println("and notifications of the GemFire Administration");
pw.println("Management Beans (MBeans).<p>");
pw.println("");
}
/**
* Ends the HTML document
*/
private void endMBeansDescriptors() {
pw.println("</HTML>");
}
/**
* Generates a heading and a table declaration for an MBean
*/
private void startMBean(Attributes atts) {
String name = atts.getValue(NAME);
/* String description = */ atts.getValue(DESCRIPTION);
pw.println("<h2><b>" + name + "</b> MBean</h2>");
pw.println("<table border=\"0\" cellpadding=\"3\">");
pw.println("<tr valign=\"top\">");
pw.println(" <th align=\"left\">Description:</th>");
pw.println(" <td colspan=\"4\">GemFire distributed system</td>");
pw.println("</tr>");
}
/**
* Ends the MBean table
*/
private void endMBean() {
seenAttribute = false;
seenOperation = false;
seenNotifications = false;
pw.println("</table>");
pw.println("");
pw.println("<P><p>");
pw.println("");
}
/**
* Generates a table row for an MBean attribute
*/
private void startAttribute(Attributes atts) {
if (!seenAttribute) {
// Print header row
pw.println("<tr valign=\"top\">");
pw.println(" <th align=\"left\">Attributes</th>");
pw.println(" <th align=\"left\" colspan=\"2\">Name</th>");
pw.println(" <th align=\"left\">Type</th>");
pw.println(" <th align=\"left\">Description</th>");
pw.println(" <th align=\"left\">Writable</th>");
pw.println("</tr>");
}
seenAttribute = true;
String name = atts.getValue(NAME);
String description = atts.getValue(DESCRIPTION);
String type = atts.getValue(TYPE);
String writeable = atts.getValue(WRITEABLE);
pw.println("<tr valign=\"top\">");
pw.println(" <td></td>");
pw.println(" <td colspan=\"2\">" + name + "</td>");
pw.println(" <td>" + type + "</td>");
pw.println(" <td>" + description + "</td>");
pw.println(" <td>" + writeable + "</td>");
pw.println("</tr>");
}
/**
* Generates a table row for an MBean operation
*/
private void startOperation(Attributes atts) {
if (!seenOperation) {
if (!seenAttribute) {
pw.println("<tr valign=\"top\">");
pw.println(" <th align=\"left\">Operations</th>");
pw.println(" <th align=\"left\" colspan=\"2\">Name</th>");
pw.println(" <th align=\"left\">Type</th>");
pw.println(" <th align=\"left\">Description</th>");
pw.println(" <th align=\"left\"></th>");
pw.println("</tr>");
} else {
String title = "Operations and Parameters";
pw.println("<tr valign=\"top\">");
pw.println(" <th align=\"left\" colspan=\"6\">" + title + "</th>");
pw.println("</tr>");
}
}
seenOperation = true;
String name = atts.getValue(NAME);
String type = atts.getValue(RETURN_TYPE);
String description = atts.getValue(DESCRIPTION);
pw.println("<tr valign=\"top\">");
pw.println(" <td></td>");
pw.println(" <td colspan=\"2\">" + name + "</td>");
pw.println(" <td>" + type + "</td>");
pw.println(" <td colspan=\"2\">" + description + "</td>");
pw.println("</tr>");
}
/**
* Generates a table row for the parameter of an MBean operation
*/
private void startParameter(Attributes atts) {
String name = atts.getValue(NAME);
String description = atts.getValue(DESCRIPTION);
String type = atts.getValue(TYPE);
pw.println("<tr valign=\"top\">");
pw.println(" <td></td>");
pw.println(" <td width=\"10\"></td>");
pw.println(" <td>" + name + "</td>");
pw.println(" <td>" + type + "</td>");
pw.println(" <td colspan=\"2\">" + description + "</td>");
pw.println("</tr>");
}
/**
* Generates a row in a table for an MBean notification
*/
private void startNotification(Attributes atts) {
if (!seenNotifications) {
if (!seenAttribute && !seenOperation) {
pw.println("<tr valign=\"top\">");
pw.println(" <th align=\"left\">Notifications</th>");
pw.println(" <th align=\"left\" colspan=\"2\">Name</th>");
pw.println(" <th align=\"left\">Type</th>");
pw.println(" <th align=\"left\">Description</th>");
pw.println(" <th align=\"left\"></th>");
pw.println("</tr>");
pw.println("</tr>");
} else {
pw.println("<tr valign=\"top\">");
pw.println(" <th align=\"left\" colspan=\"6\">Notifications and Fields</th>");
pw.println("</tr>");
}
}
seenNotifications = true;
String name = atts.getValue(NAME);
String description = atts.getValue(DESCRIPTION);
pw.println("<tr valign=\"top\">");
pw.println(" <td></td>");
pw.println(" <td colspan=\"3\">" + name + "</td>");
pw.println(" <td colspan=\"3\">" + description + "</td>");
pw.println("</tr>");
}
/**
* Generates a table row for a descriptor field
*/
private void startField(Attributes atts) {
String name = atts.getValue(NAME);
String value = atts.getValue(VALUE);
pw.println("<tr valign=\"top\">");
pw.println(" <td></td>");
pw.println(" <td width=\"10\"></td>");
pw.println(" <td colspan=\"2\">" + name + "</td>");
pw.println(" <td colspan=\"2\">" + value + "</td>");
pw.println("</tr>");
}
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
throws SAXException {
if (qName.equals(MBEANS_DESCRIPTORS)) {
startMBeansDescriptors();
} else if (qName.equals(MBEAN)) {
startMBean(atts);
} else if (qName.equals(ATTRIBUTE)) {
startAttribute(atts);
} else if (qName.equals(OPERATION)) {
startOperation(atts);
} else if (qName.equals(PARAMETER)) {
startParameter(atts);
} else if (qName.equals(NOTIFICATION)) {
startNotification(atts);
} else if (qName.equals(FIELD)) {
startField(atts);
}
}
@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
if (qName.equals(MBEANS_DESCRIPTORS)) {
endMBeansDescriptors();
} else if (qName.equals(MBEAN)) {
endMBean();
}
}
////////// Inherited methods that don't do anything //////////
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
}
@Override
public void setDocumentLocator(Locator locator) {}
@Override
public void startDocument() throws SAXException {}
@Override
public void endDocument() throws SAXException {}
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException {}
@Override
public void endPrefixMapping(String prefix) throws SAXException {}
@Override
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {}
@Override
public void processingInstruction(String target, String data) throws SAXException {}
@Override
public void skippedEntity(String name) throws SAXException {}
//////////////////////// Main Program ////////////////////////
@Immutable
private static final PrintStream err = System.err;
/**
* Prints usage information about this program
*/
private static void usage(String s) {
err.println("\n** " + s + "\n");
err.println("usage: java GenerateMBeanHTML xmlFile htmlFile");
err.println();
err.println("Converts an MBeans description XML file into an HTML");
err.println("file suitable for documentation");
err.println();
ExitCode.FATAL.doSystemExit();
}
public static void main(String[] args) throws Exception {
String xmlFileName = null;
String htmlFileName = null;
for (final String arg : args) {
if (xmlFileName == null) {
xmlFileName = arg;
} else if (htmlFileName == null) {
htmlFileName = arg;
} else {
usage("Extraneous command line argument: " + arg);
}
}
if (xmlFileName == null) {
usage("Missing XML file name");
} else if (htmlFileName == null) {
usage("Missing HTML file name");
}
File xmlFile = new File(xmlFileName);
if (!xmlFile.exists()) {
usage("XML file \"" + xmlFile + "\" does not exist");
}
File htmlFile = new File(htmlFileName);
try (FileInputStream fileInputStream = new FileInputStream(xmlFile);
FileWriter fileWriter = new FileWriter(htmlFile);
PrintWriter printWriter = new PrintWriter(fileWriter, true)) {
convert(fileInputStream, printWriter);
}
}
}