/** * 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 * * * 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. * * @author Art Barstow * * 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.7 2000/10/10 21:52:33 barstow Exp $"; // The email address for bug reports private static final String MAIL_TO = "barstow@w3.org"; // 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"; // 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("
"); out.println("

Graph of the data model

"); // Stop if any of the parameters are missing if (m_SiRPACTmpDir == null || m_GraphVizPath == null || m_GraphVizFontDir == null || m_GraphVizLibDir == null) { 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(); // @@ Delete the GIF file String imagePath = HttpUtils.getRequestURL(req).toString() + TMP_DIR_SUFFIX + File.separator + gifFile.getName(); if (gifFile.length() > 0) out.println(""); 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(""); out.println(""); out.println("RDF creation"); out.println(""); out.println(""); out.println(""); } 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("
"); out.println("

The original RDF/XML document

"); out.println("
");

            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 ("" + lineNum +
                          ": " + st.nextToken());
                lineNum++;
            }

            out.println("
"); } 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("
"); out.println("

Triples of the data model

"); // The output for each triple will be pre-formatted out.println("
");
        } 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("
"); } 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("
"); out.println("

Feedback

"); out.println("

If you suspect that SiRPAC produced an error, please enter an explanation below and then press the Submit problem report button, to mail the report (and listing) to " + MAIL_TO + "

"); out.println("
"); out.println(""); out.println("

"); // 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(""); out.println("

"); out.println("
Back to main page."); out.println(""); out.println(""); } 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 ("

GET is NOT supported!

\n\n

Please send RDF through POST!

\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 ("RDF"); String sBags = req.getParameter ("BAGS"); StringReader sr = new StringReader (sRDF); InputSource is = new InputSource (sr); boolean error = false; SiRPACServletDumpConsumer consumer = new SiRPACServletDumpConsumer(); 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); 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 ("

Errors during parsing

\n"); out.println ("
\n");

            // Make the line number a link to the listing
            out.println ("Fatal error: " + m_errorHandler.getErrorMessage());
            out.println ("   (Line number = " + "" + 
                         m_errorHandler.getLineNumber() + "" +
                         ", Column number = " + 
                         m_errorHandler.getColumnNumber() + ")");

	    out.println ("
\n\n"); } printDocumentFooter(out, sRDF); } }