initial commit of xml->html conversion

This commit is contained in:
Chris PeBenito 2005-06-02 20:39:32 +00:00
parent 4196997813
commit 36e54b81f7
14 changed files with 1308 additions and 5 deletions

View File

@ -50,7 +50,6 @@ LOADPOLICY := $(SBINDIR)/load_policy
SETFILES := $(SBINDIR)/setfiles SETFILES := $(SBINDIR)/setfiles
XMLLINT := $(BINDIR)/xmllint XMLLINT := $(BINDIR)/xmllint
XMLDTD := policy.dtd
# enable MLS if requested. # enable MLS if requested.
ifeq ($(MLS),y) 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 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 # default action: build policy locally
@ -280,10 +288,9 @@ relabel: $(FC) $(SETFILES)
# Documentation generation # Documentation generation
# #
xml: policy.xml tmp/policy.xml: $(ALL_INTERFACES) tmp/generated_definitions.conf
policy.xml: $(ALL_INTERFACES) tmp/generated_definitions.conf
@echo "Creating $@" @echo "Creating $@"
@cp $(XMLDTD) tmp
$(QUIET) echo '<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>' > $@ $(QUIET) echo '<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>' > $@
$(QUIET) echo '<!DOCTYPE policy SYSTEM "policy.dtd">' >> $@ $(QUIET) echo '<!DOCTYPE policy SYSTEM "policy.dtd">' >> $@
$(QUIET) echo "<policy>" >> $@ $(QUIET) echo "<policy>" >> $@
@ -295,6 +302,15 @@ policy.xml: $(ALL_INTERFACES) tmp/generated_definitions.conf
$(XMLLINT) --noout --dtdvalid $(XMLDTD) $@ ;\ $(XMLLINT) --noout --dtdvalid $(XMLDTD) $@ ;\
fi 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 # Runtime binary policy patching of users
@ -369,5 +385,7 @@ clean:
rm -f policy.conf rm -f policy.conf
rm -f policy.$(PV) rm -f policy.$(PV)
rm -f $(FC) 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

View File

@ -0,0 +1,2 @@
</body>
</html>

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1,247 @@
/* Copyright (C) 2005 Tresys Technology, LLC
* License: refer to COPYING file for license information.
* Authors: Spencer Shimko <sshimko@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&nbsp;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-&nbsp;<a href=\"" + layerName + "_" + moduleName + HTMLEXT
+ "\">" + moduleName + "</a><br />\n");
}
out.append("\t</div>\n");
} else {
out.append("\t<a href=\"" + layerName +
HTMLEXT + "\">+&nbsp;" + 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-&nbsp;<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:&nbsp;"+ module.Name + "<br />\n");
out.append("\tSummary:&nbsp;" + 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&nbsp;Type</td><td colspan=\"2\">" + iface.Type.toString() + "</td></tr>\n");
out.append("\t<td>Flow&nbsp;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&nbsp;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);
}
}
}

View File

@ -0,0 +1,565 @@
/* Copyright (C) 2005 Tresys Technology, LLC
* License: refer to COPYING file for license information.
* Authors: Spencer Shimko <sshimko@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);
}
}

View File

@ -0,0 +1,37 @@
/* Copyright (C) 2005 Tresys Technology, LLC
* License: refer to COPYING file for license information.
* Authors: Spencer Shimko <sshimko@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>();
}
}

View File

@ -0,0 +1,12 @@
/* Copyright (C) 2005 Tresys Technology, LLC
* License: refer to COPYING file for license information.
* Authors: Spencer Shimko <sshimko@tresys.com>
*
* Interface.java: The reference policy interface types
* Version: @version@
*/
package policy;
public enum InterfaceType {
Read, Write, Both, None;
}

View File

@ -0,0 +1,34 @@
/* Copyright (C) 2005 Tresys Technology, LLC
* License: refer to COPYING file for license information.
* Authors: Spencer Shimko <sshimko@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>();
}
}

View File

@ -0,0 +1,34 @@
/* Copyright (C) 2005 Tresys Technology, LLC
* License: refer to COPYING file for license information.
* Authors: Spencer Shimko <sshimko@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>();
}
}

View File

@ -0,0 +1,28 @@
/* Copyright (C) 2005 Tresys Technology, LLC
* License: refer to COPYING file for license information.
* Authors: Spencer Shimko <sshimko@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);
}
}

View File

@ -0,0 +1,35 @@
/* Copyright (C) 2005 Tresys Technology, LLC
* License: refer to COPYING file for license information.
* Authors: Spencer Shimko <sshimko@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>();
}
}

View File

@ -0,0 +1,114 @@
/* Copyright (C) 2005 Tresys Technology, LLC
* License: refer to COPYING file for license information.
* Authors: Spencer Shimko <sshimko@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);
}
}

View File

@ -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;}