[selinux-policy: 253/3172] initial commit of xml->html conversion
Daniel J Walsh
dwalsh at fedoraproject.org
Thu Oct 7 19:26:47 UTC 2010
commit 36e54b81f790075495420b76844d4231cfb089e9
Author: Chris PeBenito <cpebenito at tresys.com>
Date: Thu Jun 2 20:39:32 2005 +0000
initial commit of xml->html conversion
refpolicy/Makefile | 28 +-
refpolicy/doc/doctools/footer.html | 2 +
refpolicy/doc/doctools/header.html | 8 +
refpolicy/doc/doctools/policy.dtd | 17 +
refpolicy/doc/doctools/src/Converter.java | 247 +++++++++
refpolicy/doc/doctools/src/Docgen.java | 565 ++++++++++++++++++++
refpolicy/doc/doctools/src/policy/Interface.java | 37 ++
.../doc/doctools/src/policy/InterfaceType.java | 12 +
refpolicy/doc/doctools/src/policy/Layer.java | 34 ++
refpolicy/doc/doctools/src/policy/Module.java | 34 ++
refpolicy/doc/doctools/src/policy/Parameter.java | 28 +
refpolicy/doc/doctools/src/policy/Policy.java | 35 ++
.../doc/doctools/src/policy/PolicyElement.java | 114 ++++
refpolicy/doc/doctools/style.css | 152 ++++++
14 files changed, 1308 insertions(+), 5 deletions(-)
---
diff --git a/refpolicy/Makefile b/refpolicy/Makefile
index 631a2e3..2c7ba7e 100644
--- a/refpolicy/Makefile
+++ b/refpolicy/Makefile
@@ -50,7 +50,6 @@ LOADPOLICY := $(SBINDIR)/load_policy
SETFILES := $(SBINDIR)/setfiles
XMLLINT := $(BINDIR)/xmllint
-XMLDTD := policy.dtd
# enable MLS if requested.
ifeq ($(MLS),y)
@@ -108,6 +107,15 @@ ALL_FC_FILES := $(foreach dir,$(ALL_LAYERS),$(wildcard $(dir)/*.fc))
POLICY_SECTIONS := tmp/pre_te_files.conf tmp/generated_definitions.conf tmp/all_interfaces.conf tmp/all_attrs_types.conf tmp/only_te_rules.conf tmp/all_post.conf
+DOCTOOLS = doctools
+XMLDTD = $(DOCTOOLS)/policy.dtd
+HTMLHEAD = $(DOCTOOLS)/header.html
+HTMLFOOT = $(DOCTOOLS)/footer.html
+HTMLCSS = $(DOCTOOLS)/style.css
+HTMLOUT = $(DOCTOOLS)/html
+JAVASRC = $(wildcard $(DOCTOOLS)/src/*.java) $(wildcard $(DOCTOOLS)/src/policy/*.java)
+JAVABYTE = $(patsubst %.java,%.class,$(JAVASRC))
+
########################################
#
# default action: build policy locally
@@ -280,10 +288,9 @@ relabel: $(FC) $(SETFILES)
# Documentation generation
#
-xml: policy.xml
-
-policy.xml: $(ALL_INTERFACES) tmp/generated_definitions.conf
+tmp/policy.xml: $(ALL_INTERFACES) tmp/generated_definitions.conf
@echo "Creating $@"
+ @cp $(XMLDTD) tmp
$(QUIET) echo '<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>' > $@
$(QUIET) echo '<!DOCTYPE policy SYSTEM "policy.dtd">' >> $@
$(QUIET) echo "<policy>" >> $@
@@ -295,6 +302,15 @@ policy.xml: $(ALL_INTERFACES) tmp/generated_definitions.conf
$(XMLLINT) --noout --dtdvalid $(XMLDTD) $@ ;\
fi
+$(JAVABYTE) doctool: $(JAVASRC)
+ javac $(JAVASRC)
+
+html: tmp/policy.xml $(JAVABYTE) $(HTMLHEAD) $(HTMLFOOT)
+ @mkdir -p $(DOCTOOLS)/html
+ $(QUIET) java -cp $(DOCTOOLS)/src/ Docgen -xf tmp/policy.xml \
+ -hf $(HTMLHEAD) -ff $(HTMLFOOT) -od $(HTMLOUT)
+ $(QUIET) cp $(HTMLCSS) $(HTMLOUT)
+
########################################
#
# Runtime binary policy patching of users
@@ -369,5 +385,7 @@ clean:
rm -f policy.conf
rm -f policy.$(PV)
rm -f $(FC)
+ rm -fR $(HTMLOUT)
+ find $(DOCTOOLS)/src -iname "*.class" | xargs rm -f
-.PHONY: default policy install reload enableaudit checklabels restorelabels relabel xml clean
+.PHONY: default policy install reload enableaudit checklabels restorelabels relabel html clean
diff --git a/refpolicy/doc/doctools/footer.html b/refpolicy/doc/doctools/footer.html
new file mode 100644
index 0000000..308b1d0
--- /dev/null
+++ b/refpolicy/doc/doctools/footer.html
@@ -0,0 +1,2 @@
+</body>
+</html>
diff --git a/refpolicy/doc/doctools/header.html b/refpolicy/doc/doctools/header.html
new file mode 100644
index 0000000..daf0904
--- /dev/null
+++ b/refpolicy/doc/doctools/header.html
@@ -0,0 +1,8 @@
+
+<html>
+<head>
+<title>Security Enhanced Linux Reference Policy</title>
+<style type="text/css" media="all">@import "style.css";</style>
+</head>
+<body>
+<div id="Header">Security Enhanced Linux Reference Policy</div>
diff --git a/refpolicy/doc/doctools/policy.dtd b/refpolicy/doc/doctools/policy.dtd
new file mode 100644
index 0000000..6d21a1b
--- /dev/null
+++ b/refpolicy/doc/doctools/policy.dtd
@@ -0,0 +1,17 @@
+<!ELEMENT policy (module+)>
+<!ELEMENT module (summary,interface+)>
+<!ATTLIST module
+ name CDATA #REQUIRED
+ layer CDATA #REQUIRED>
+<!ELEMENT summary (#PCDATA)>
+<!ELEMENT interface (description,parameter+,infoflow)>
+<!ATTLIST interface name CDATA #REQUIRED>
+<!ELEMENT description (#PCDATA)>
+<!ELEMENT parameter (#PCDATA)>
+<!ATTLIST parameter
+ name CDATA #REQUIRED
+ optional (true|false) "false">
+<!ELEMENT infoflow EMPTY>
+<!ATTLIST infoflow
+ type CDATA #REQUIRED
+ weight CDATA #IMPLIED>
diff --git a/refpolicy/doc/doctools/src/Converter.java b/refpolicy/doc/doctools/src/Converter.java
new file mode 100644
index 0000000..91378fd
--- /dev/null
+++ b/refpolicy/doc/doctools/src/Converter.java
@@ -0,0 +1,247 @@
+/* Copyright (C) 2005 Tresys Technology, LLC
+ * License: refer to COPYING file for license information.
+ * Authors: Spencer Shimko <sshimko at tresys.com>
+ *
+ * Converter.java: The reference policy documentation converter
+ * Version: @version@
+ */
+import policy.*;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import java.util.Map;
+
+/**
+ * The reference policy documentation generator and xml analyzer class.
+ * It pulls in XML describing reference policy, transmogrifies it,
+ * and spits it back out in some other arbitrary format.
+ */
+public class Converter{
+ private Policy policy;
+ private static final String HTMLEXT = ".html";
+ private static final String indexContent =
+ "<div id=\"Content\"><h2>Welcome to the reference policy API!</h2><p/>" +
+ "Please choose from the navigation options to the left.</div>";
+
+ private StringBuffer headerOutput = new StringBuffer();
+ private StringBuffer footerOutput = new StringBuffer();
+ private File outDir;
+
+ public Converter(Policy pol, File headerFile, File footerFile) throws IOException{
+ policy = pol;
+
+ /*
+ * Setup header and footer.
+ */
+ FileReader headIn = new FileReader(headerFile);
+
+ BufferedReader br = new BufferedReader(headIn);
+ String line = null; //not declared within while loop
+ while (( line = br.readLine()) != null){
+ headerOutput.append(line);
+ headerOutput.append(System.getProperty("line.separator"));
+ }
+
+ FileReader footerIn = new FileReader(footerFile);
+
+ br = new BufferedReader(footerIn);
+ line = null; //not declared within while loop
+ while (( line = br.readLine()) != null){
+ footerOutput.append(line);
+ footerOutput.append(System.getProperty("line.separator"));
+ }
+ }
+
+ public void Convert(File _outDir) throws IOException{
+ outDir = _outDir;
+
+ // write the index document
+ FileWrite("index" + HTMLEXT, headerOutput.toString()
+ + Menu().toString() + indexContent + footerOutput.toString());
+
+ // walk the policy and write pages for each module
+ for(Map.Entry<String,Layer> lay:policy.Children.entrySet()){
+ Layer layer = lay.getValue();
+ // the base output contains the menu and layer content header
+ StringBuffer baseOutput = new StringBuffer();
+ // the layer output will be filled with modules and summarys for content
+ StringBuffer layerOutput = new StringBuffer();
+
+ // create the navigation menu
+ baseOutput.append(Menu(layer.Name));
+
+ baseOutput.append("<div id=\"Content\">\n");
+ baseOutput.append("\t<h1>Layer: " + layer.Name + "</h1><p/>\n");
+
+ layerOutput.append("<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\" width=\"75%\">\n");
+ layerOutput.append("<tr><th class=\"title\">Module Name</th>" +
+ "<th class=\"title\">Summary</th></tr>");
+
+ for(Map.Entry<String,Module> mod:layer.Children.entrySet()){
+ // module output will be filled with in-depth module info.
+ StringBuffer moduleOutput = new StringBuffer();
+ Module module = mod.getValue();
+
+ // get the content for the module's document
+ moduleOutput.append(moduleContent(mod.getValue()).toString() + "</div>");
+
+ // get the summary and name for the layer's document
+
+ layerOutput.append("<tr><td><a href=\"" + layer.Name + "_" + module.Name + HTMLEXT
+ + "\">" + module.Name + "</a></td>" +
+ "\n<td>" + module.PCDATA + "</td></tr>\n");
+
+ // write module document
+ FileWrite(layer.Name + "_" + module.Name + HTMLEXT,
+ headerOutput.toString() + "\n" + baseOutput.toString() + moduleOutput.toString() + footerOutput.toString());
+ }
+ // write layer document
+ FileWrite(layer.Name + HTMLEXT,
+ headerOutput.toString() + "\n" + baseOutput.toString()
+ + layerOutput.toString() + "</div>" + footerOutput.toString());
+
+ }
+ }
+
+ private StringBuffer Menu(String key){
+ StringBuffer out = new StringBuffer();
+ out.append("<div id=\"Menu\">\n");
+ for(Map.Entry<String,Layer> layer:policy.Children.entrySet()){
+ String layerName = layer.getKey();
+
+
+ // show the modules for the current key
+ if (layerName.equals(key)){
+ out.append("\t<a href=\"" + layerName
+ + HTMLEXT + "\">" + layerName + "</a><br />\n");
+ out.append("\t<div id=\"subitem\">\n");
+ for(Map.Entry<String,Module> module:layer.getValue().Children.entrySet()){
+ String moduleName = module.getKey();
+ out.append("\t\t- <a href=\"" + layerName + "_" + moduleName + HTMLEXT
+ + "\">" + moduleName + "</a><br />\n");
+ }
+ out.append("\t</div>\n");
+ } else {
+ out.append("\t<a href=\"" + layerName +
+ HTMLEXT + "\">+ " + layerName + "</a><br />\n");
+ }
+ }
+ out.append("</div>");
+ return out;
+ }
+
+ private StringBuffer Menu(){
+ StringBuffer out = new StringBuffer();
+ out.append("<div id=\"Menu\">\n");
+ for(Map.Entry<String,Layer> layer:policy.Children.entrySet()){
+ String layerName = layer.getKey();
+
+
+ out.append("\t<a href=\"" + layerName + HTMLEXT + "\">" + layerName + "</a><br />\n");
+ out.append("\t<div id=\"subitem\">\n");
+ for(Map.Entry<String,Module> module:layer.getValue().Children.entrySet()){
+ String moduleName = module.getKey();
+ out.append("\t\t- <a href=\"" + layerName + "_" + moduleName + HTMLEXT
+ + "\">" + moduleName + "</a><br />\n");
+ }
+ out.append("\t</div>\n");
+ }
+ out.append("</div>");
+ return out;
+ }
+
+ private StringBuffer moduleContent(Module module){
+ StringBuffer out = new StringBuffer();
+
+ out.append("\t<h2>Module: "+ module.Name + "<br />\n");
+ out.append("\tSummary: " + module.PCDATA + "</h2>\n");
+ for (Map.Entry<String,Interface> inter:module.Children.entrySet()){
+ Interface iface = inter.getValue();
+ // main table header
+ out.append("<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\" width=\"75%\">\n");
+ out.append("<tr><th class=\"title\" colspan=\"3\">Interface</th></tr>\n");
+
+ // only show weight when type isnt none
+ if (iface.Type != InterfaceType.None){
+ out.append("<tr><td>Name</td><td colspan=\"2\">" + iface.Name + "</td></tr>\n" +
+ "<tr><td>Flow Type</td><td colspan=\"2\">" + iface.Type.toString() + "</td></tr>\n");
+ out.append("\t<td>Flow Weight</td><td colspan=\"2\">" + iface.Weight + "</td></tr>\n");
+ } else {
+ out.append("<tr><td>Name</td><td colspan=\"2\">" + iface.Name + "</td></tr>\n");
+ out.append("<tr><td>Flow Type</td><td colspan=\"2\">" + iface.Type.toString() + "</td></tr>\n");
+
+ }
+ out.append("<tr><td>Description</td><td colspan=\"2\">" + iface.PCDATA + "</td></tr>\n");
+
+ out.append("<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\" width=\"75%\">\n"
+ + "<tr><th class=\"title\">Parameter</th><th class=\"title\">Description</th>"
+ + "<th class=\"title\">Optional</th></tr>");
+ for (Map.Entry<String,Parameter> param:iface.Children.entrySet()){
+ Parameter parameter = param.getValue();
+ out.append("\t<tr><td> " + parameter.Name + "</td>\n");
+ out.append("\t<td>" + parameter.PCDATA + "</td>\n");
+ String opt = parameter.GetAttribute("optional");
+ if (opt != null && opt.equalsIgnoreCase("true")){
+ out.append("\t<td><center>Yes</center></td></tr>\n");
+ } else {
+ out.append("\t<td><center>No</center></td></tr>\n");
+ }
+ }
+ out.append("\n</table></table><br/><br/>\n");
+ }
+ return out;
+ }
+
+ /**
+ * Write to sub directory.
+ * @param path
+ * @param outFilename
+ * @param content
+ * @return
+ */
+ private void FileWrite (String path, String outFilename, String content){
+ try {
+ // create parent if necessary
+ File outParent = new File(outDir, path );
+ File outFile = new File(outParent, outFilename );
+ if (outParent.exists() && !outParent.isDirectory()){
+ throw new IOException("Output directory not really a directory");
+ } else if (!outParent.exists()){
+ outParent.mkdirs();
+ }
+ PrintStream stream = new PrintStream(new FileOutputStream(outFile));
+ stream.println(content);
+ stream.flush();
+ stream.close();
+ } catch (Exception e){
+ System.err.println (e.getMessage());
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Write to output directory directly.
+ *
+ * @param path
+ * @param outFilename
+ * @param content
+ * @return
+ */
+ private void FileWrite (String outFilename, String content){
+ try {
+ File out = new File(outDir, outFilename );
+ PrintStream stream = new PrintStream(new FileOutputStream(out));
+ stream.println(content);
+ stream.flush();
+ stream.close();
+ } catch (Exception e){
+ System.err.println (e.getMessage());
+ System.exit(1);
+ }
+ }
+}
\ No newline at end of file
diff --git a/refpolicy/doc/doctools/src/Docgen.java b/refpolicy/doc/doctools/src/Docgen.java
new file mode 100644
index 0000000..12e38bf
--- /dev/null
+++ b/refpolicy/doc/doctools/src/Docgen.java
@@ -0,0 +1,565 @@
+/* Copyright (C) 2005 Tresys Technology, LLC
+ * License: refer to COPYING file for license information.
+ * Authors: Spencer Shimko <sshimko at tresys.com>
+ *
+ * Docgen.java: The reference policy xml analyzer and documentation generator
+ */
+import policy.*;
+
+import java.io.*;
+import java.util.*;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Schema;
+
+import javax.xml.XMLConstants;
+
+import org.xml.sax.*;
+import org.w3c.dom.*;
+
+/**
+ * The reference policy documentation generator and xml analyzer class.
+ * It pulls in XML describing reference policy, transmogrifies it,
+ * and spits it back out in some other arbitrary format.
+ */
+public class Docgen{
+ // store the PIs here
+ private static Vector procInstr = new Vector();
+ private static boolean verbose = false;
+ // the policy structure built after xml is parsed
+ private Policy policy = null;
+ // the xml document
+ private Document dom = null;
+
+ // the files/directories passed in from the command line
+ private static File xmlFile;
+ private static File headerFile;
+ private static File footerFile;
+ private static File outputDir;
+
+ private static void printUsage(){
+ System.out.println("Reference Policy Documentation Compiler usage:");
+ System.out.println("\tjava -cp ./src Docgen [-h] [-v] -xf xmlFileIn -hf headerFile -ff footerFile -od outDirectory");
+ System.out.println("-h display this message and exit");
+ System.out.println("-xf XML file to parse");
+ System.out.println("-hf header file for HTML output");
+ System.out.println("-ff footer file for HTML output");
+ System.out.println("-od output directory");
+ System.exit(1);
+ }
+
+ /**
+ * Docgen constructor
+ *
+ * @param output Filename to setup for output
+ */
+ public Docgen(String output)
+ throws FileNotFoundException {
+ }
+
+ /**
+ * The main() driver for the policy documentation generator.
+ * @param argv Arguments, takes 1 filename parameter
+ */
+ public static void main(String argv[]) {
+ if (argv.length == 0){
+ printUsage();
+ System.exit(1);
+ }
+ // hacked up version of getopt()
+ for (int x=0; x < argv.length; x++){
+ if (argv[x].equals("-xf")){
+ x++;
+ if (x<argv.length){
+ xmlFile = new File(argv[x]);
+ if (!xmlFile.isFile()){
+ printUsage();
+ System.err.println("XML file is not really a file!");
+ System.exit(1);
+ }
+ } else {
+ printUsage();
+ System.exit(1);
+ }
+ } else if (argv[x].equals("-hf")){
+ x++;
+ if (x<argv.length){
+ headerFile = new File(argv[x]);
+ if (!headerFile.isFile()){
+ printUsage();
+ System.err.println("Header file is not really a file!");
+ System.exit(1);
+ }
+ } else {
+ printUsage();
+ System.exit(1);
+ }
+ } else if (argv[x].equals("-ff")){
+ x++;
+ if (x<argv.length){
+ footerFile = new File(argv[x]);
+ if (!footerFile.isFile()){
+ printUsage();
+ System.err.println("Footer file is not really a file!");
+ System.exit(1);
+ }
+ } else {
+ printUsage();
+ System.exit(1);
+ }
+ } else if (argv[x].equals("-od")){
+ x++;
+ if (x<argv.length){
+ outputDir = new File(argv[x]);
+ if (!outputDir.isDirectory()){
+ printUsage();
+ System.err.println("Output directory is not really a directory!");
+ System.exit(1);
+ }
+ } else {
+ printUsage();
+ System.exit(1);
+ }
+ } else if (argv[x].equals("-h")){
+ printUsage();
+ System.exit(1);
+ } else if (argv[x].equals("-v")){
+ verbose = true;
+ } else {
+ printUsage();
+ System.out.println("Error unknown argument: " + argv[x]);
+ System.exit(1);
+ }
+ }
+
+ try {
+ // create document factory
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ Schema schema = schemaFactory.newSchema();
+
+ factory.setValidating(true);
+ factory.setNamespaceAware(true);
+
+ // in order for this setting to hold factory must be validating
+ factory.setIgnoringElementContentWhitespace(true);
+
+ // get builder from factory
+ DocumentBuilder builder = factory.newDocumentBuilder();
+
+ // create an anonymous error handler for parsing errors
+ builder.setErrorHandler(
+ new org.xml.sax.ErrorHandler() {
+ // fatal errors
+ public void fatalError(SAXParseException exception)
+ throws SAXException {
+ throw exception;
+ }
+
+ // parse exceptions will be fatal
+ public void error(SAXParseException parseErr)
+ throws SAXParseException
+ {
+ // Error generated by the parser
+ System.err.println("\nPARSE ERROR: line " + parseErr.getLineNumber()
+ + ", URI " + parseErr.getSystemId());
+ System.err.println("PARSE ERROR: " + parseErr.getMessage() );
+
+ // check the wrapped exception
+ Exception x = parseErr;
+ if (parseErr.getException() != null)
+ x = parseErr.getException();
+ x.printStackTrace(); }
+
+ // dump warnings too
+ public void warning(SAXParseException err)
+ throws SAXParseException
+ {
+ System.err.println("\nPARSE WARNING: line " + err.getLineNumber()
+ + ", URI " + err.getSystemId());
+ System.err.println("PARSE WARNING: " + err.getMessage());
+ }
+ }
+ );
+
+ Docgen redoc = new Docgen(argv[1]);
+
+ redoc.dom = builder.parse(xmlFile);
+
+ // do our own transformations
+ redoc.processDocumentNode();
+
+ // build our own converter then convert
+ Converter converter = new Converter(redoc.policy, headerFile, footerFile);
+ converter.Convert(outputDir);
+ // TODO: figure out which of these is taken care of by the anonymous error handler above
+ } catch (SAXException saxErr) {
+ // sax error
+ Exception x = saxErr;
+ if (saxErr.getException() != null)
+ x = saxErr.getException();
+ x.printStackTrace();
+ } catch (ParserConfigurationException parseConfigErr) {
+ // Sometimes we can't build the parser with the specified options
+ parseConfigErr.printStackTrace();
+ } catch (IOException ioe) {
+ // I/O error
+ ioe.printStackTrace();
+ } catch (Exception err) {
+ err.printStackTrace();
+ }
+
+
+ } // main
+
+ public static void Debug(String msg){
+ if (verbose)
+ System.out.println(msg);
+ }
+
+ void processDocumentNode() throws SAXException{
+ Element docNode = dom.getDocumentElement();
+
+ if (docNode != null && docNode.getNodeName().equals("policy")){
+ policy = new Policy("policy");
+
+ NodeList children = docNode.getChildNodes();
+ int len = children.getLength();
+
+ for (int index = 0; index < len; index++){
+ processNode(children.item(index), policy);
+ }
+ } else {
+ System.err.println("Failed to find document/policy node!");
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Process children of the policy node (aka modules).
+ *
+ * @param node A child node of the policy.
+ * @param parent The parent PolicyElement.
+ */
+ void processNode(Node node, Policy parent) throws SAXException{
+ Layer layer = null;
+ Module module = null;
+
+ // save us from null pointer de-referencing
+ if (node == null){
+ System.err.println(
+ "Nothing to do, node is null");
+ return;
+ }
+
+ // snag the name
+ String nodeName = node.getNodeName();
+
+ // validity check and pull layer attribute
+ if (node.getNodeType() == Node.ELEMENT_NODE && nodeName.equals("module")){
+ // display the name which might be generic
+ Docgen.Debug("Encountered node: " + nodeName);
+ NamedNodeMap attrList = node.getAttributes();
+
+ // the required attributes
+ int attrLen = 0;
+ if(attrList != null){
+ attrLen = attrList.getLength();
+ } else{
+ fatalNodeError("Missing attributes in module. \""
+ + "\". \"layer\" and \"name\" are required attributes.");
+ }
+
+ Node moduleNode = attrList.getNamedItem("name");
+ Node layerNode = attrList.getNamedItem("layer");
+
+ if (moduleNode == null || layerNode == null)
+ fatalNodeError("Missing attributes in module element. \"layer\" and \"name\" are required attributes.");
+
+ String moduleName = moduleNode.getNodeValue();
+ String layerName = layerNode.getNodeValue();
+
+ // check to see if this is a new layer or a pre-existing layer
+ layer = parent.Children.get(layerName);
+ if (layer == null){
+ Docgen.Debug("Adding new layer: " + layerName);
+ layer = new Layer(layerName, parent);
+ } else {
+ Docgen.Debug("Lookup succeeded for: " + layerName);
+ }
+
+ if (layer.Children.containsKey(moduleName)){
+ Docgen.Debug("Reusing previously defined module: " + moduleName);
+ module = layer.Children.get(moduleName);
+ } else {
+ Docgen.Debug("Creating module: " + moduleName);
+ module = new Module(moduleName, layer);
+ }
+
+ // take care of the attributes
+ for(int i = 0; i < attrLen; i++){
+ Node attrNode = attrList.item(i);
+ String attrName = attrNode.getNodeName();
+ String attrValue = attrNode.getNodeValue();
+ if (!attrName.equals("layer") && !attrName.equals("name")){
+ Docgen.Debug("\tAdding attribute: " + attrNode.getNodeName()
+ + "=" + attrValue);
+ module.AddAttribute(attrName,attrValue);
+ }
+ }
+ } else if (!isEmptyTextNode(node)){
+ fatalNodeError("Unexpected child \"" + nodeName
+ +"\" node of parent \"" + parent.Name + "\".");
+ }
+
+ // recurse over children if both module and layer defined
+ if (module != null && layer != null){
+ // the containsKey check verified no duplicate module
+ layer.Children.put(module.Name, module);
+ parent.Children.put(layer.Name, layer);
+
+ NodeList children = node.getChildNodes();
+ if (children != null){
+ int len = children.getLength();
+ for (int index = 0; index < len; index++){
+ processNode(children.item(index), module);
+ }
+ }
+ }
+ }
+
+ /**
+ * Process children of the module node (aka interfaces).
+ *
+ * @param node A child node of the policy.
+ * @param parent The parent PolicyElement.
+ */
+ void processNode(Node node, Module parent) throws SAXException{
+ Interface iface = null;
+
+ // save us from null pointer de-referencing
+ if (node == null){
+ System.err.println(
+ "Nothing to do, node is null");
+ return;
+ }
+
+ // snag the name
+ String nodeName = node.getNodeName();
+
+ // if summary node
+ if (node.getNodeType() == Node.ELEMENT_NODE && nodeName.equals("summary")){
+ // unfortunately we still need to snag the PCDATA child node for the actual text
+ Docgen.Debug("Encountered node: " + nodeName);
+ NodeList children = node.getChildNodes();
+ if (children != null && children.getLength() == 1){
+ if (children.item(0).getNodeType() == Node.TEXT_NODE){
+ parent.PCDATA = children.item(0).getNodeValue();
+ return;
+ }
+ }
+ fatalNodeError("Unexpected child \"" + nodeName
+ +"\" node of parent \"" + parent.Name + "\".");
+ // if interface node
+ } else if (node.getNodeType() == Node.ELEMENT_NODE && nodeName.equals("interface")){
+ NamedNodeMap attrList = node.getAttributes();
+ // the required attributes
+ int attrLen = 0;
+ if(attrList != null){
+ attrLen = attrList.getLength();
+ } else{
+ fatalNodeError("Missing attribute in interface. "
+ + "\"name\" is a required attribute.");
+ }
+
+ Node nameNode = attrList.getNamedItem("name");
+
+ if (nameNode == null )
+ fatalNodeError("Missing attribute in interface. "
+ + "\"name\" is a required attribute.");
+
+
+ String iName = nameNode.getNodeValue();
+
+ Docgen.Debug("Creating interface: " + iName);
+ iface = new Interface(iName, parent);
+
+ // take care of the attributes
+ for(int i = 0; i < attrLen; i++){
+ Node attrNode = attrList.item(i);
+ String attrName = attrNode.getNodeName();
+ String attrValue = attrNode.getNodeValue();
+ if (!attrName.equals("name")){
+ Docgen.Debug("\tAdding attribute: " + attrNode.getNodeName()
+ + "=" + attrValue);
+ iface.AddAttribute(attrName,attrValue);
+ }
+ }
+ } else if (!isEmptyTextNode(node)){
+ fatalNodeError("Unexpected child \"" + nodeName
+ +"\" node of parent \"" + parent.Name + "\".");
+ }
+
+ // recurse over children if both module and layer defined
+ if (iface != null && parent != null){
+ // FIXME: containsKey() check for duplicate
+ parent.Children.put(iface.Name, iface);
+
+ NodeList children = node.getChildNodes();
+ if (children != null){
+ int len = children.getLength();
+ for (int index = 0; index < len; index++){
+ processNode(children.item(index), iface);
+ }
+ }
+ }
+ }
+
+ /**
+ * Process children of the interface node (aka parameters, desc., infoflow).
+ *
+ * @param node A child node of the policy.
+ * @param parent The parent PolicyElement.
+ */
+ void processNode(Node node, Interface parent) throws SAXException{
+ Parameter param = null;
+
+ // save us from null pointer de-referencing
+ if (node == null){
+ System.err.println(
+ "Nothing to do, node is null");
+ return;
+ }
+
+ // snag the name
+ String nodeName = node.getNodeName();
+
+ // if description node
+ if (node.getNodeType() == Node.ELEMENT_NODE && nodeName.equals("description")){
+ // unfortunately we still need to snag the PCDATA child node for the actual text
+ NodeList children = node.getChildNodes();
+ if (children != null && children.getLength() == 1){
+ if (children.item(0).getNodeType() == Node.TEXT_NODE){
+ parent.PCDATA = children.item(0).getNodeValue();
+ return;
+ }
+ }
+ fatalNodeError("Unexpected child \"" + nodeName
+ +"\" node of parent \"" + parent.Name + "\".");
+ // if infoflow node
+ } else if (node.getNodeType() == Node.ELEMENT_NODE && nodeName.equals("infoflow")){
+ NamedNodeMap attrList = node.getAttributes();
+ // the required attributes
+ int attrLen = 0;
+ if(attrList != null){
+ attrLen = attrList.getLength();
+ } else{
+ fatalNodeError("Missing attribute in infoflow."
+ + " \"type\" and \"weight\" are required attributes.");
+ }
+
+ Node typeNode = attrList.getNamedItem("type");
+ Node weightNode = attrList.getNamedItem("weight");
+
+ String type = typeNode.getNodeValue();
+ if (typeNode == null ||
+ (!type.equals("none") && weightNode == null))
+ fatalNodeError("Missing attribute in infoflow."
+ + " \"type\" and \"weight\" are required attributes (unless type is none).");
+
+ if (type.equals("read")){
+ parent.Type = InterfaceType.Read;
+ parent.Weight = Integer.parseInt(weightNode.getNodeValue());
+ }else if (type.equals("write")){
+ parent.Type = InterfaceType.Write;
+ parent.Weight = Integer.parseInt(weightNode.getNodeValue());
+ }else if (type.equals("both")){
+ parent.Type = InterfaceType.Both;
+ parent.Weight = Integer.parseInt(weightNode.getNodeValue());
+ }else if (type.equals("none")){
+ parent.Type = InterfaceType.None;
+ parent.Weight = -1;
+ } else {
+ System.err.println("Infoflow type must be read, write, both, or none!");
+ }
+
+ } else if (node.getNodeType() == Node.ELEMENT_NODE && nodeName.equals("parameter")){
+ NamedNodeMap attrList = node.getAttributes();
+ // the required attributes
+ int attrLen = 0;
+ if(attrList != null){
+ attrLen = attrList.getLength();
+ } else{
+ fatalNodeError("Missing attribute in parameter \""
+ + "\". \"name\" is a required attribute.");
+ }
+
+ Node nameNode = attrList.getNamedItem("name");
+
+ if (nameNode == null )
+ fatalNodeError("Missing attribute in parameter \""
+ + "\". \"name\" is a required attribute.");
+
+ String paramName = nameNode.getNodeValue();
+
+ Docgen.Debug("Creating parameter: " + paramName);
+ param = new Parameter(paramName, parent);
+
+ // unfortunately we still need to snag the PCDATA child node for the actual text
+ NodeList children = node.getChildNodes();
+ if (children != null && children.getLength() == 1){
+ if (children.item(0).getNodeType() == Node.TEXT_NODE){
+ param.PCDATA = children.item(0).getNodeValue();
+ }
+ } else {
+ fatalNodeError("Unexpected child \""
+ +"\" node of parameter.");
+ }
+
+ // take care of the attributes
+ for(int i = 0; i < attrLen; i++){
+ Node attrNode = attrList.item(i);
+ String attrName = attrNode.getNodeName();
+ String attrValue = attrNode.getNodeValue();
+ if (!attrName.equals("name")){
+ Docgen.Debug("\tAdding attribute: " + attrNode.getNodeName()
+ + "=" + attrValue);
+ param.AddAttribute(attrName,attrValue);
+ }
+ }
+ } else if (!isEmptyTextNode(node)){
+ fatalNodeError("Unexpected child \"" + nodeName
+ +"\" node of parent \"" + parent.Name + "\".");
+ }
+
+ // recurse over children if both parent and param defined
+ if (param != null && parent != null){
+ // the containsKey check verified no duplicate module
+ // FIXME: containsKey() check for duplicate
+ parent.Children.put(param.Name, param);
+ }
+ }
+
+ public boolean isEmptyTextNode(Node node){
+ /*
+ * FIXME: remove once properly validating
+ * Since we aren't validating yet we needed our
+ * own pointless whitespace remover.
+ */
+
+ if (node.getNodeType() == Node.TEXT_NODE &&
+ node.getNodeValue().trim().length() == 0)
+ return true;
+ return false;
+ }
+
+ public void fatalNodeError(String msg)
+ throws SAXException {
+ // FIXME: figure out how to throw SAXParseException w/ location
+ throw new SAXException(msg);
+ }
+}
diff --git a/refpolicy/doc/doctools/src/policy/Interface.java b/refpolicy/doc/doctools/src/policy/Interface.java
new file mode 100644
index 0000000..6014adf
--- /dev/null
+++ b/refpolicy/doc/doctools/src/policy/Interface.java
@@ -0,0 +1,37 @@
+/* Copyright (C) 2005 Tresys Technology, LLC
+ * License: refer to COPYING file for license information.
+ * Authors: Spencer Shimko <sshimko at tresys.com>
+ *
+ * Interface.java: The reference policy interfaces
+ * Version: @version@
+ */
+package policy;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Each reference policy interface is represented by this class.
+ *
+ * @see Layer
+ * @see Module
+ * @see Parameter
+ */
+public class Interface extends PolicyElement {
+ /** the children of this element */
+ public final Map<String,Parameter> Children;
+
+ public InterfaceType Type;
+ public int Weight;
+
+ /**
+ * Default constructor assigns name to module.
+ *
+ * @param _name The name of the module.
+ * @param _Parent The reference to the parent element.
+ */
+ public Interface(String _name, Module _Parent){
+ super(_name, _Parent);
+ Children = new TreeMap<String,Parameter>();
+ }
+}
\ No newline at end of file
diff --git a/refpolicy/doc/doctools/src/policy/InterfaceType.java b/refpolicy/doc/doctools/src/policy/InterfaceType.java
new file mode 100644
index 0000000..0a102c5
--- /dev/null
+++ b/refpolicy/doc/doctools/src/policy/InterfaceType.java
@@ -0,0 +1,12 @@
+/* Copyright (C) 2005 Tresys Technology, LLC
+ * License: refer to COPYING file for license information.
+ * Authors: Spencer Shimko <sshimko at tresys.com>
+ *
+ * Interface.java: The reference policy interface types
+ * Version: @version@
+ */
+package policy;
+
+public enum InterfaceType {
+ Read, Write, Both, None;
+}
\ No newline at end of file
diff --git a/refpolicy/doc/doctools/src/policy/Layer.java b/refpolicy/doc/doctools/src/policy/Layer.java
new file mode 100644
index 0000000..b232a38
--- /dev/null
+++ b/refpolicy/doc/doctools/src/policy/Layer.java
@@ -0,0 +1,34 @@
+/* Copyright (C) 2005 Tresys Technology, LLC
+ * License: refer to COPYING file for license information.
+ * Authors: Spencer Shimko <sshimko at tresys.com>
+ *
+ * Layer.java: The reference policy layers
+ * Version: @version@
+ */
+package policy;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Each reference policy layer is represented by this class.
+ *
+ * @see Module
+ * @see Interface
+ * @see Parameter
+ */
+public class Layer extends PolicyElement {
+ /** the children of this element */
+ public final Map<String,Module> Children;
+
+ /**
+ * Default constructor assigns name to layer.
+ *
+ * @param _name The name of the layer.
+ * @param _Parent The reference to the parent element.
+ */
+ public Layer(String _name, Policy _Parent){
+ super(_name, _Parent);
+ Children = new TreeMap<String, Module>();
+ }
+}
\ No newline at end of file
diff --git a/refpolicy/doc/doctools/src/policy/Module.java b/refpolicy/doc/doctools/src/policy/Module.java
new file mode 100644
index 0000000..3bb0c22
--- /dev/null
+++ b/refpolicy/doc/doctools/src/policy/Module.java
@@ -0,0 +1,34 @@
+/* Copyright (C) 2005 Tresys Technology, LLC
+ * License: refer to COPYING file for license information.
+ * Authors: Spencer Shimko <sshimko at tresys.com>
+ *
+ * Module.java: The reference policy module
+ * Version: @version@
+ */
+package policy;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Each reference policy layer is represented by this class.
+ *
+ * @see Layer
+ * @see Interface
+ * @see Parameter
+ */
+public class Module extends PolicyElement {
+ /** the children of this element */
+ public final Map<String,Interface> Children;
+
+ /**
+ * Default constructor assigns name to module.
+ *
+ * @param _name The name of the module.
+ * @param _Parent The reference to the parent element.
+ */
+ public Module(String _name, Layer _Parent){
+ super(_name, _Parent);
+ Children = new TreeMap<String,Interface>();
+ }
+}
\ No newline at end of file
diff --git a/refpolicy/doc/doctools/src/policy/Parameter.java b/refpolicy/doc/doctools/src/policy/Parameter.java
new file mode 100644
index 0000000..0f0ee45
--- /dev/null
+++ b/refpolicy/doc/doctools/src/policy/Parameter.java
@@ -0,0 +1,28 @@
+/* Copyright (C) 2005 Tresys Technology, LLC
+ * License: refer to COPYING file for license information.
+ * Authors: Spencer Shimko <sshimko at tresys.com>
+ *
+ * Parameter.java: The reference policy interface parameters
+ * Version: @version@
+ */
+package policy;
+
+/**
+ * Each reference policy layer is represented by this class.
+ *
+ * @see Layer
+ * @see Module
+ * @see Interface
+ */
+public class Parameter extends PolicyElement{
+
+ /**
+ * Default constructor assigns name to parameter.
+ *
+ * @param _name The name of the parameter.
+ * @param _Parent The reference to the parent element.
+ */
+ public Parameter(String _name, Interface _Parent){
+ super(_name, _Parent);
+ }
+}
\ No newline at end of file
diff --git a/refpolicy/doc/doctools/src/policy/Policy.java b/refpolicy/doc/doctools/src/policy/Policy.java
new file mode 100644
index 0000000..e17ff1f
--- /dev/null
+++ b/refpolicy/doc/doctools/src/policy/Policy.java
@@ -0,0 +1,35 @@
+/* Copyright (C) 2005 Tresys Technology, LLC
+ * License: refer to COPYING file for license information.
+ * Authors: Spencer Shimko <sshimko at tresys.com>
+ *
+ * Policy.java: The reference policy api
+ * Version: @version@
+ */
+package policy;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Each reference policy layer is represented by this class.
+ *
+ * @see Module
+ * @see Interface
+ * @see Parameter
+ */
+public class Policy extends PolicyElement {
+ /** the children of this element */
+ public final Map<String,Layer> Children;
+
+ /**
+ * Default constructor assigns name to layer.
+ *
+ * @param _name The name of the layer.
+ * @param _Parent The reference to the parent element.
+ */
+ public Policy(String _name){
+ // the policy is the root element so parent==null
+ super(_name, null);
+ Children = new TreeMap<String,Layer>();
+ }
+}
\ No newline at end of file
diff --git a/refpolicy/doc/doctools/src/policy/PolicyElement.java b/refpolicy/doc/doctools/src/policy/PolicyElement.java
new file mode 100644
index 0000000..f5fc913
--- /dev/null
+++ b/refpolicy/doc/doctools/src/policy/PolicyElement.java
@@ -0,0 +1,114 @@
+/* Copyright (C) 2005 Tresys Technology, LLC
+ * License: refer to COPYING file for license information.
+ * Authors: Spencer Shimko <sshimko at tresys.com>
+ *
+ * PolicyElement.java: The reference policy base class
+ * Version: @version@
+ */
+package policy;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Reference policy elements have certain similarties which
+ * should be inherited from a base class. This includes a name
+ * attribute that will be used for hashing, sorting, and converting
+ * to a string.
+ *
+ * @see Layer
+ * @see Module
+ * @see Interface
+ * @see Parameter
+ */
+public abstract class PolicyElement {
+ /** the string identifying the element */
+ public final String Name;
+ /** the parent component */
+ public final PolicyElement Parent;
+
+ /** the attributes of this element */
+ private final Map<String,String> attributes;
+
+ public String PCDATA;
+
+ /**
+ * Default constructor assigns name.
+ *
+ * @param _name The name of the element.
+ * @param _Parent The reference to the parent element.
+ */
+ public PolicyElement(String _name, PolicyElement _Parent){
+ Name = _name;
+ Parent = _Parent;
+ attributes = new TreeMap<String,String>();
+ }
+
+ /**
+ * Add attribute to policy element.
+ *
+ * @param aName String to identify attribute
+ * @param aString Value of attribute identified by string aName
+ * @return <code>true</code> when attribute added to element,
+ * <code>false</code> when attribute already defined for element
+ */
+ public boolean AddAttribute(String aName, String aString){
+ if (attributes.containsKey(aName)){
+ return false;
+ }
+ attributes.put(aName,aString);
+ return true;
+ }
+
+ /**
+ * Get attribute from policy element.
+ *
+ * @param aName String to identify attribute
+ * @return String value associated with named attribute
+ * or <code>null</code> if no attribute defined
+ * for aName.
+ */
+ public String GetAttribute(String aName){
+ return attributes.get(aName);
+ }
+
+ /**
+ * Overridden equals method
+ *
+ * @param obj Object for comparison
+ */
+ @Override public boolean equals(Object obj){
+ return obj.toString().equals(this.Name);
+ }
+
+ /**
+ * Return a hashcode for the element. Currently implemented as a
+ * call to the String hashCode() method.
+ *
+ * @return integer hashCode of this instance assuring two objects that
+ * are == will return same hashcode.
+ */
+ @Override public int hashCode() {
+ return this.toString().hashCode();
+ }
+
+ /**
+ * Overridden toString() method.
+ *
+ * @return String representation of instance (it's name).
+ */
+ @Override public String toString(){
+ return Name;
+ }
+
+ /**
+ * Since Component might be used as a key in some type of sort Compare
+ * is implemented.
+ *
+ * @return 0 if this==that, <0 if this<that, >0 if this>that
+ * @see String.compareTo
+ */
+ public int compareTo(Layer that){
+ return Name.compareTo(that.Name);
+ }
+}
\ No newline at end of file
diff --git a/refpolicy/doc/doctools/style.css b/refpolicy/doc/doctools/style.css
new file mode 100644
index 0000000..3805bf8
--- /dev/null
+++ b/refpolicy/doc/doctools/style.css
@@ -0,0 +1,152 @@
+body {
+ margin:0px;
+ padding:0px;
+ font-family:verdana, arial, helvetica, sans-serif;
+ color:#333;
+ background-color:white;
+ }
+h1 {
+ margin:0px 0px 15px 0px;
+ padding:0px;
+ font-size:28px;
+ line-height:28px;
+ font-weight:900;
+ color:#ccc;
+ }
+h2 {
+ font-size:100%;
+ }
+h3 {
+ font-size:75%;
+ }
+h4 {
+ font-size:67%;
+ }
+li {
+ font:11px/20px verdana, arial, helvetica, sans-serif;
+ margin:0px 0px 0px 0px;
+ padding:0px;
+ }
+p {
+ /* normal */
+ font:11px/20px verdana, arial, helvetica, sans-serif;
+ margin:0px 0px 16px 0px;
+ padding:0px;
+ }
+
+tt {
+ /* inline code */
+ font-family: monospace;
+ }
+
+table {
+ background-color:#eee;
+ border:1px dashed #999;
+ /*background-color: white;*/
+ color: black;
+ text-align: left;
+ font:11px/20px verdana, arial, helvetica, sans-serif;
+ margin-left: 10%;
+ margin-right: 10%;
+}
+
+th {
+ background-color: #ccccff;
+ text-align: center;
+}
+
+td.header {
+ font-weight: bold;
+}
+
+#Content>p {margin:0px;}
+#Content>p+p {text-indent:30px;}
+a {
+ color:#09c;
+ font-size:11px;
+ text-decoration:none;
+ font-weight:600;
+ font-family:verdana, arial, helvetica, sans-serif;
+ }
+a:link {color:#09c;}
+a:visited {color:#07a;}
+a:hover {background-color:#eee;}
+
+#Codeblock {
+ margin:5px 50px 5px 50px;
+ padding:5px 0px 5px 15px;
+ border-style:solid;
+ border-color:black;
+ border-width:1px 1px 1px 1px;
+ background-color:#f8f8f8;
+ font-size:11px;
+ font-weight:600;
+ text-decoration:none;
+ font-family:courier;
+}
+pre {
+ font-size:11px;
+ font-weight:600;
+ text-decoration:none;
+ font-family:courier;
+}
+pre.codeblock {
+ /* code block (bordered, slight gray background) */
+ border-style:solid;
+ border-color:black;
+ border-width:1px 1px 1px 1px;
+ background-color:#f8f8f8;
+ margin-left: 10%;
+ margin-right: 10%;
+}
+dl {
+ /* definition text block */
+ font:11px/20px verdana, arial, helvetica, sans-serif;
+ margin:0px 0px 16px 0px;
+ padding:0px;
+ }
+dt {
+ /* definition term */
+ font-weight: bold;
+ }
+
+#Header {
+ margin:50px 0px 10px 0px;
+ padding:17px 0px 0px 20px;
+ /* For IE5/Win's benefit height = [correct height] + [top padding] + [top and bottom border widths] */
+ height:33px; /* 14px + 17px + 2px = 33px */
+ border-style:solid;
+ border-color:black;
+ border-width:1px 0px; /* top and bottom borders: 1px; left and right borders: 0px */
+ line-height:11px;
+ font-size:110%;
+ background-color:#eee;
+ voice-family: "\"}\"";
+ voice-family:inherit;
+ height:14px; /* the correct height */
+ }
+body>#Header {height:14px;}
+#Content {
+ margin:0px 50px 50px 200px;
+ padding:10px;
+ }
+
+#Menu {
+ position:absolute;
+ top:100px;
+ left:20px;
+ width:162px;
+ padding:10px;
+ background-color:#eee;
+ border:1px dashed #999;
+ line-height:17px;
+ text-align:left;
+ voice-family: "\"}\"";
+ voice-family:inherit;
+ width:160px;
+ }
+#Menu subitem {
+ font-size: 5px;
+}
+
+body>#Menu {width:160px;}
More information about the scm-commits
mailing list