File:
[Public] /
java /
classes /
org /
w3c /
rdf /
examples /
SiRPACServlet.java
Revision
1.10:
download - view:
text,
annotated -
select for diffs
Tue Oct 17 20:34:46 2000 UTC (23 years, 8 months ago) by
barstow
Branches:
MAIN
CVS tags:
HEAD
barstow: Added support for the POST to include a parameter named
"STREAM". If this parameter is set to "off", then the SiRPAC
parser will be invoked with streaming turned off. The stream
mode is on by default but must be turned off to process the
aboutEach[Prefix] attributes.
/**
* SiRPACServlet - Simple RDF Parser & Compiler Servlet wrapper
*
* Copyright © World Wide Web Consortium, (Massachusetts Institute of
* Technology, Institut National de Recherche en Informatique et en
* Automatique, Keio University).
*
* All Rights Reserved.
*
* Please see the full Copyright clause at
* <http://www.w3.org/Consortium/Legal/copyright-software.html>
*
* This servlet is a wrapper for the SiRPAC RDF parser. The servlet
* expects the following variables through the POST method:
*
* 1. "RDF" - the RDF/XML document
* 2. "BAGS" - if "on", each Description should have its own Bag;
* the default is not to do this.
* 3. "STREAM" if "off", the stream mode is turned off so that aboutEach
* and aboutEachPrefix are supported.
*
* @author Art Barstow <barstow@w3.org>
*
* The graphics package is AT&T's GraphVis tool.
*/
package org.w3c.rdf.examples;
import java.io.*;
import java.util.StringTokenizer;
import java.util.Enumeration;
import javax.servlet.*;
import javax.servlet.http.*;
import org.xml.sax.InputSource;
import org.xml.sax.Parser;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.*;
import org.w3c.rdf.model.*;
import org.w3c.rdf.syntax.*;
import org.w3c.rdf.syntax.RDFConsumer;
import org.w3c.rdf.util.xml.DumpConsumer;
import org.w3c.rdf.util.xml.ErrorStore;
import org.w3c.rdf.implementation.model.StatementImpl;
import org.w3c.rdf.implementation.model.NodeFactoryImpl;
import org.w3c.rdf.implementation.syntax.sirpac.*;
public class SiRPACServlet extends HttpServlet
{
final static public String REVISION = "$Id: SiRPACServlet.java,v 1.10 2000/10/17 20:34:46 barstow Exp $";
// The email address for bug reports
private static final String MAIL_TO = "barstow@w3.org";
// Names of the POST parameters
// The XML'ized RDF
private static final String POST_TEXT = "RDF";
// Flag for turning on treating each Description as a bag
private static final String POST_BAG = "BAGS";
// Flag for turning off SiRPAC's stream parsing mode
private static final String POST_STREAM_MODE = "STREAM";
// Names of the servlet's parameters
private static final String SIRPAC_TMP_DIR = "SIRPAC_TMP_DIR";
private static final String GRAPH_VIZ_ROOT = "GRAPH_VIZ_ROOT";
private static final String GRAPH_VIZ_PATH = "GRAPH_VIZ_PATH";
private static final String GRAPH_VIZ_LIB_DIR = "GRAPH_VIZ_LIB_DIR";
private static final String GRAPH_VIZ_FONT_DIR = "GRAPH_VIZ_FONT_DIR";
// Variables for the servlet's parameters
private static String m_SiRPACTmpDir = null;
private static String m_GraphVizPath = null;
private static String m_GraphVizFontDir = null;
private static String m_GraphVizLibDir = null;
// Names of environment variable need by GraphVis
private static String DOTFONTPATH = "DOTFONTPATH";
private static String LD_LIBRARY_PATH = "LD_LIBRARY_PATH";
// Names used for temporary files
private static final String TMP_FILE_PREFIX = "sirpac_";
private static final String TMP_DIR_SUFFIX = ".tmp";
private static final String DOT_SUFFIX = ".dot";
private static final String GIF_SUFFIX = ".gif";
// Default GraphViz parameter names and their default values
private static final String NODE_COLOR = "NODE_COLOR";
private static final String DEFAULT_NODE_COLOR = "black";
private static final String NODE_TEXT_COLOR = "NODE_TEXT_COLOR";
private static final String DEFAULT_NODE_TEXT_COLOR = "black";
private static final String EDGE_COLOR = "EDGE_COLOR";
private static final String DEFAULT_EDGE_COLOR = "black";
private static final String EDGE_TEXT_COLOR = "EDGE_TEXT_COLOR";
private static final String DEFAULT_EDGE_TEXT_COLOR = "black";
private static final String ORIENTATION = "ORIENTATION";
private static final String DEFAULT_ORIENTATION = "TB"; // Top to Bottom
private static final String FONT_SIZE = "FONT_SIZE";
private static final String DEFAULT_FONT_SIZE = "10";
// Fonts are not currently configurable
private static final String DEFAULT_FONT = "arial";
// Servlet name
private static final String SERVLET_NAME = "SiRPACServlet";
// The parser
private SiRPAC m_sirpac = null;
// The error handler
private ErrorStore m_errorHandler;
/*
* Create a File object in the m_SiRPACTmpDir directory
*
*@param directory the file's directory
*@param prefix the file's prefix name (not its directory)
*@param suffix the file's suffix or extension name
*@return a File object if a temporary file is created; null otherwise
*/
private File createTempFile (String directory, String prefix, String suffix) {
File f;
try {
File d = new File(directory);
f = File.createTempFile(prefix, suffix, d);
} catch (Exception e) {
return null;
}
return f;
}
/*
* Invokes the GraphVis program to create a GIF image from the
* the given DOT data file
*
*@param dotFileName the name of the DOT data file
*@param gifFileName the name of the GIF data file
*@return true if success; false if any failure occurs
*/
private boolean generateGifFile(String dotFileName, String gifFileName) {
String environment[] = {DOTFONTPATH + "=" + m_GraphVizFontDir,
LD_LIBRARY_PATH + "=" + m_GraphVizLibDir};
String cmdArray[] = {m_GraphVizPath, "-Tgif", "-o", gifFileName, dotFileName};
Runtime rt = Runtime.getRuntime();
try {
Process p = rt.exec(cmdArray, environment);
p.waitFor();
} catch (Exception e) {
return false;
}
return true;
}
/*
* Returns a parameter from a request or the parameter's default
* value.
*
*@param req a Servlet request
*@return if the request contains the specfied parameter its value
* in the request is returned; otherwise its default value is
* returned
*/
private String getParameter(HttpServletRequest req, String param, String defString) {
String s = req.getParameter(param);
return (s == null) ? defString : s;
}
/*
* If the request contains any graph-related parameters, pass them
* to the graph consumer for handling
*
*@param req the response
*@param consumer the GraphViz consumer
*/
private void processGraphParameters (HttpServletRequest req, GraphVizDumpConsumer consumer) {
// Look for colors
String s;
String nodeColor = getParameter (req, NODE_COLOR, DEFAULT_NODE_COLOR);
String nodeTextColor = getParameter (req, NODE_TEXT_COLOR, DEFAULT_NODE_TEXT_COLOR);
String edgeColor = getParameter (req, EDGE_COLOR, DEFAULT_EDGE_COLOR);
String edgeTextColor = getParameter (req, EDGE_TEXT_COLOR, DEFAULT_EDGE_TEXT_COLOR);
String fontSize = getParameter (req, FONT_SIZE, DEFAULT_FONT_SIZE);
// Orientation must be either
String orientation = req.getParameter (ORIENTATION);
if (orientation.equals("Left to Right"))
orientation = "LR";
else
orientation = DEFAULT_ORIENTATION;
// Add an attribute for all of the graph's nodes
consumer.addGraphAttribute("node [fontname=" + DEFAULT_FONT +
",fontsize=" + fontSize +
",color=" + nodeColor +
",fontcolor=" + nodeTextColor + "]");
// Add an attribute for all of the graph's edges
consumer.addGraphAttribute("edge [fontname=" + DEFAULT_FONT +
",fontsize=" + fontSize +
",color=" + edgeColor +
",fontcolor=" + edgeTextColor + "]");
// Add an attribute for the orientation
consumer.addGraphAttribute("rankdir=" + orientation + ";");
}
/*
* Generate a graph of the RDF data model
*
*@param out the servlet's output stream
*@param rdf the RDF text
*@param req a Servlet request
*/
private void generateGraph (ServletOutputStream out, String rdf, HttpServletRequest req) {
try {
out.println("<hr title=\"visualisation\">");
out.println("<h3>Graph of the data model</h3>");
// Stop if any of the parameters are missing
if (m_SiRPACTmpDir == null || m_GraphVizPath == null ||
m_GraphVizFontDir == null || m_GraphVizLibDir == null) {
// Put the paths in a comment in the returned content
out.println("<!-- SIRPAC TMP = " + m_SiRPACTmpDir);
out.println("GRAPH VIZ = " + m_GraphVizPath);
out.println("GRAPH LIB = " + m_GraphVizLibDir);
out.println("GRAPH FON = " + m_GraphVizFontDir + " -->");
out.println("Servlet initialization failed. A graph cannot be generated.");
return;
}
// The temporary directory
String tmpDir = m_SiRPACTmpDir;
// Must generate a unique file name that the DOT consumer
// will use
File dotFile = createTempFile(tmpDir, TMP_FILE_PREFIX, DOT_SUFFIX);
if (dotFile == null) {
out.println("Failed to create a temporary DOT file. A graph cannot be generated.");
return;
}
// Create a PrintWriter for the GraphViz consumer
FileWriter fw = new FileWriter(dotFile);
PrintWriter pw = new PrintWriter(fw);
// Run the parser using the DOT consumer to capture
// the output in a file
StringReader sr = new StringReader (rdf);
InputSource is = new InputSource (sr);
GraphVizDumpConsumer consumer = new GraphVizDumpConsumer(pw);
// Process any graph-related parameters in the request
processGraphParameters(req, consumer);
try {
m_sirpac.parse(is, consumer);
} catch (Exception e) {
out.println("An attempt to generate the graph data failed ("
+ e.getMessage() + ").");
pw.close();
dotFile.delete();
return;
}
// Must close the DOT input file so the GraphViz can
// open and read it
pw.close();
// Must generate a unique file name for the GIF file
// that will be created
File gifFile = createTempFile(tmpDir, TMP_FILE_PREFIX, GIF_SUFFIX);
if (gifFile == null) {
out.println("Failed to create a temporary GIF file. A graph cannot be generated.");
dotFile.delete();
return;
}
// Pass the DOT data file to the GraphViz dot program
// so it can create a GIF image of the data model
String dotFileName = dotFile.getAbsolutePath();
String gifFileName = gifFile.getAbsolutePath();
if (!generateGifFile(dotFileName, gifFileName)) {
out.println("An attempt to create a graph failed.");
dotFile.delete();
gifFile.delete();
return;
}
// Cleanup
dotFile.delete();
// NOTE: Cannot delete the GIF file here because its
// pathname is returned to the client
String imagePath = SERVLET_NAME +
TMP_DIR_SUFFIX + File.separator +
gifFile.getName();
if (gifFile.length() > 0)
out.println("<img src=\"" + imagePath + "\"/>");
else
out.println("The graph image file is empty.");
} catch (Exception e) {
System.err.println("Exception: " + e.getMessage());
}
}
/*
* Search the given string for substring "key"
* and if it is found, replace it with string "replacement"
*
*@param input the input string
*@param key the string to search for
*@param replacement the string to replace all occurences of "key"
*@return if no substitutions are done, input is returned; otherwise
* a new string is returned.
*/
private String replaceString(String input, String key, String replacement) {
StringBuffer sb = new StringBuffer("");
StringTokenizer st = new StringTokenizer(input, key);
// Must handle the case where the input string begins with the key
if (input.startsWith(key))
sb = sb.append(replacement);
while (st.hasMoreTokens()) {
sb = sb.append(st.nextToken());
if (st.hasMoreTokens())
sb = sb.append(replacement);
}
if (sb.length() >= 1)
return sb.toString();
else
return input;
}
/*
* Print the document's header info
*
*@param out the servlet's output stream
*/
private void printDocumentHeader (ServletOutputStream out) {
try {
out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"");
out.println(" \"http://www.w3.org/TR/REC-html40/loose.dtd\">");
out.println("<HTML><HEAD>");
out.println("<TITLE>RDF creation</TITLE>");
out.println("<LINK HREF=\"rdf.css\" REL=\"stylesheet\">");
out.println("</HEAD>");
out.println("<BODY>");
} catch (Exception e) {
System.err.println("Exception: " + e.getMessage());
}
}
/*
* Print the rdf listing
*
*@param out the servlet's output stream
*@param rdf the RDF code
*/
private void printListing (ServletOutputStream out, String rdf) {
try {
out.println("<hr title=\"original source\">");
out.println("<h3>The original RDF/XML document</h3>");
out.println("<pre>");
String s = replaceString(rdf, "<", "<");
StringTokenizer st = new StringTokenizer(s, "\n");
// Now output the RDF one line at a time with line numbers
int lineNum = 1;
while (st.hasMoreTokens()) {
out.print ("<a name=\"" + lineNum + "\">" + lineNum +
"</a>: " + st.nextToken());
lineNum++;
}
out.println("</pre>");
} catch (Exception e) {
System.err.println("Exception: " + e.getMessage());
}
}
/*
* Print the header for the triple listing
*
*@param out the servlet's output stream
*/
private void printTripleHeader (ServletOutputStream out) {
try {
out.println("<hr title=\"triples\">");
out.println("<h3>Triples of the data model</h3>");
// The output for each triple will be pre-formatted
out.println("<pre>");
} catch (Exception e) {
System.err.println("Exception: " + e.getMessage());
}
}
/*
* Print the footer info for the triple listing
*
*@param out the servlet's output stream
*/
private void printTripleFooter (ServletOutputStream out) {
try {
out.println("</pre>");
} catch (Exception e) {
System.err.println("Exception: " + e.getMessage());
}
}
/*
* Print the document's footer info
*
*@param out the servlet's output stream
*@param rdf the RDF code
*/
private void printDocumentFooter (ServletOutputStream out, String rdf) {
try {
out.println("<hr title=\"Problem reporting\">");
out.println("<h3>Feedback</h3>");
out.println("<p>If you suspect that SiRPAC produced an error, please enter an explanation below and then press the <b>Submit problem report</b> button, to mail the report (and listing) to <i>" + MAIL_TO + "</i></p>");
out.println("<form enctype=\"text/plain\" method=\"post\" action=\"mailto:" + MAIL_TO + "\">");
out.println("<textarea cols=\"60\" rows=\"4\" name=\"report\"></textarea>");
out.println("<p><input type=\"hidden\" name=\"RDF\" value=\"<?xml version="1.0"?>");
// The listing is being passed as a parameter so the '<'
// and '"' characters must be replaced with < and ",
// respectively
String s1 = replaceString(rdf, "<", "<");
String s2 = replaceString(s1, "\"", """);
out.println(s2 + "\">");
out.println("<input type=\"submit\" value=\"Submit problem report\">");
out.println("</form>");
out.println("<hr><a href=\"/description\">Back</a> to main page.");
out.println("</BODY>");
out.println("</HTML>");
} catch (Exception e) {
System.err.println("Exception: " + e.getMessage());
}
}
/*
* Servlet's get info method
*/
public String getServletInfo () {
return "Servlet Wrapper for SiRPAC. This is revision " + REVISION;
}
/*
* Servlet's init method
*
*@param config the servlet's configuration object
*/
public void init(ServletConfig config) throws ServletException {
super.init (config);
m_sirpac = new SiRPAC();
m_errorHandler = new ErrorStore();
m_sirpac.setErrorHandler(m_errorHandler);
// Cache the parameters
m_SiRPACTmpDir = config.getInitParameter(SIRPAC_TMP_DIR);
// All of the Graph Viz paths extend from GRAPH_VIZ_ROOT
String GraphVizRoot = config.getInitParameter(GRAPH_VIZ_ROOT);
m_GraphVizPath = GraphVizRoot + "/" + config.getInitParameter(GRAPH_VIZ_PATH);
m_GraphVizFontDir = GraphVizRoot + "/" + config.getInitParameter(GRAPH_VIZ_FONT_DIR);
m_GraphVizLibDir = GraphVizRoot + "/" + config.getInitParameter(GRAPH_VIZ_LIB_DIR);
}
/*
* Servlet's destroy info method
*/
public void destroy () {
super.destroy ();
}
/*
* Servlet's doGet info method - NOT supported
*
*@param req the request
*@param res the response
*/
public void doGet (HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
ServletOutputStream out = res.getOutputStream ();
res.setContentType ("text/html");
out.println ("<h1>GET is NOT supported!</h1>\n\n<p>Please send RDF through POST!</p>\n");
}
/*
* Servlet's doPost method
*
*@param req the request
*@param res the response
*/
public void doPost (HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
ServletOutputStream out = res.getOutputStream ();
String sRDF = req.getParameter (POST_TEXT);
String sBags = req.getParameter (POST_BAG);
String sStreamMode = req.getParameter (POST_STREAM_MODE);
StringReader sr = new StringReader (sRDF);
InputSource is = new InputSource (sr);
boolean error = false;
SiRPACServletDumpConsumer consumer = new SiRPACServletDumpConsumer();
// Re-initialize the parser
m_sirpac = new SiRPAC();
m_errorHandler = new ErrorStore();
m_sirpac.setErrorHandler(m_errorHandler);
printDocumentHeader (out);
printListing (out, sRDF);
printTripleHeader (out);
try {
// Override the default triple output handler
consumer.setOutputStream(out);
// Toggle Bag handling - always false unless explicitly
// included in the request
m_sirpac.createBags (false);
if (sBags != null && sBags.equals ("on"))
m_sirpac.createBags (true);
// Set parser's streaming mode
if (sStreamMode != null && sBags.equals ("off"))
m_sirpac.setStreamMode (false);
m_sirpac.parse(is, consumer);
generateGraph(out, sRDF, req);
} catch (SAXException e) {
error = true;
} catch (Exception e) {
error = true;
e.printStackTrace ();
}
printTripleFooter(out);
res.setContentType ("text/html");
if (error) {
out.println ("<h1>Errors during parsing</h1>\n");
out.println ("<pre>\n");
// Make the line number a link to the listing
out.println ("Fatal error: " + m_errorHandler.getErrorMessage());
out.println (" (Line number = " + "<a href=\"#" +
m_errorHandler.getLineNumber() + "\">" +
m_errorHandler.getLineNumber() + "</a>" +
", Column number = " +
m_errorHandler.getColumnNumber() + ")");
out.println ("</pre>\n\n");
}
printDocumentFooter(out, sRDF);
}
}
Webmaster