Annotation of java/classes/org/w3c/rdf/examples/SiRPACServlet.java, revision 1.6
1.1 barstow 1: /**
2: * SiRPACServlet - Simple RDF Parser & Compiler Servlet wrapper
3: *
4: * Copyright © World Wide Web Consortium, (Massachusetts Institute of
5: * Technology, Institut National de Recherche en Informatique et en
6: * Automatique, Keio University).
7: *
8: * All Rights Reserved.
9: *
10: * Please see the full Copyright clause at
11: * <http://www.w3.org/Consortium/Legal/copyright-software.html>
12: *
1.3 barstow 13: * This servlet is a wrapper for the SiRPAC RDF parser. The servlet
14: * expects two incoming variables through the POST method:
15: *
1.4 barstow 16: * 1. "RDF" - the RDF/XML document
17: * 2. "BAGS" - if "on", each Description should have its own Bag;
18: * the default is not to do this.
1.1 barstow 19: *
20: * @author Janne Saarela <jsaarela@w3.org>
21: *
1.3 barstow 22: * Major re-write to support AT&T GraphVis tool by Arthur Barstow
23: * <barstow@w3.org>
1.1 barstow 24: */
25:
26: package org.w3c.rdf.examples;
27:
28: import java.io.*;
29: import java.util.StringTokenizer;
30: import java.util.Enumeration;
31: import javax.servlet.*;
32: import javax.servlet.http.*;
33:
34: import org.xml.sax.InputSource;
35: import org.xml.sax.Parser;
36: import org.xml.sax.SAXException;
37: import org.xml.sax.helpers.*;
38:
39: import org.w3c.rdf.model.*;
40: import org.w3c.rdf.syntax.*;
41: import org.w3c.rdf.syntax.RDFConsumer;
42: import org.w3c.rdf.util.xml.DumpConsumer;
43: import org.w3c.rdf.util.xml.ErrorStore;
44: import org.w3c.rdf.implementation.model.StatementImpl;
45: import org.w3c.rdf.implementation.model.NodeFactoryImpl;
46: import org.w3c.rdf.implementation.syntax.sirpac.*;
47:
48: public class SiRPACServlet extends HttpServlet
49: {
1.6 ! barstow 50: final static public String REVISION = "$Id: SiRPACServlet.java,v 1.5 2000/10/09 15:24:17 barstow Exp $";
1.1 barstow 51:
1.4 barstow 52: // @@ The email address for bug reports
53: private static final String MAIL_TO = "barstow@w3.org";
1.3 barstow 54:
55: // Names of the servlet's parameters
1.5 barstow 56: private static final String SIRPAC_TMP_DIR = "SIRPAC_TMP_DIR";
57: private static final String GRAPH_VIZ_ROOT = "GRAPH_VIZ_ROOT";
58: private static final String GRAPH_VIZ_PATH = "GRAPH_VIZ_PATH";
59: private static final String GRAPH_VIZ_LIB_DIR = "GRAPH_VIZ_LIB_DIR";
60: private static final String GRAPH_VIZ_FONT_DIR = "GRAPH_VIZ_FONT_DIR";
1.3 barstow 61:
62: // Variables for the servlet's parameters
1.5 barstow 63: private static String m_SiRPACTmpDir = null;
64: private static String m_GraphVizPath = null;
65: private static String m_GraphVizFontDir = null;
66: private static String m_GraphVizLibDir = null;
1.4 barstow 67:
68: // Names of environment variable need by GraphVis
69: private static String DOTFONTPATH = "DOTFONTPATH";
70: private static String LD_LIBRARY_PATH = "LD_LIBRARY_PATH";
71:
72: // Names used for temporary files
73: private static final String TMP_FILE_PREFIX = "sirpac_";
74: private static final String TMP_DIR_SUFFIX = ".tmp";
75: private static final String DOT_SUFFIX = ".dot";
76: private static final String GIF_SUFFIX = ".gif";
1.3 barstow 77:
1.6 ! barstow 78: // Default GraphViz parameter names and their default values
! 79: private static final String NODE_COLOR = "NODE_COLOR";
! 80: private static final String DEFAULT_NODE_COLOR = "black";
! 81:
! 82: private static final String NODE_TEXT_COLOR = "NODE_TEXT_COLOR";
! 83: private static final String DEFAULT_NODE_TEXT_COLOR = "black";
! 84:
! 85: private static final String EDGE_COLOR = "EDGE_COLOR";
! 86: private static final String DEFAULT_EDGE_COLOR = "black";
! 87:
! 88: private static final String EDGE_TEXT_COLOR = "EDGE_TEXT_COLOR";
! 89: private static final String DEFAULT_EDGE_TEXT_COLOR = "black";
! 90:
! 91: private static final String ORIENTATION = "ORIENTATION";
! 92: private static final String DEFAULT_ORIENTATION = "TB"; // Top to Bottom
! 93:
! 94: private static final String FONT_SIZE = "FONT_SIZE";
! 95: private static final String DEFAULT_FONT_SIZE = "10";
! 96:
! 97: // Fonts are not currently configurable
! 98: private static final String DEFAULT_FONT = "arial";
! 99:
1.3 barstow 100: // The parser
101: private SiRPAC m_sirpac = null;
102: // The error handler
103: private ErrorStore m_errorHandler;
1.1 barstow 104:
1.3 barstow 105: /*
1.4 barstow 106: * Create a File object in the m_SiRPACTmpDir directory
1.3 barstow 107: *
1.4 barstow 108: *@param directory the file's directory
109: *@param prefix the file's prefix name (not its directory)
110: *@param suffix the file's suffix or extension name
111: *@return a File object if a temporary file is created; null otherwise
1.3 barstow 112: */
1.4 barstow 113: private File createTempFile (String directory, String prefix, String suffix) {
114: File f;
115: try {
116: File d = new File(directory);
117: f = File.createTempFile(prefix, suffix, d);
118: } catch (Exception e) {
119: return null;
120: }
121: return f;
122: }
123:
124: /*
125: * Invokes the GraphVis program to create a GIF image from the
126: * the given DOT data file
127: *
128: *@param dotFileName the name of the DOT data file
129: *@param gifFileName the name of the GIF data file
130: *@return true if success; false if any failure occurs
131: */
132: private boolean generateGifFile(String dotFileName, String gifFileName) {
1.5 barstow 133: String environment[] = {DOTFONTPATH + "=" + m_GraphVizFontDir,
134: LD_LIBRARY_PATH + "=" + m_GraphVizLibDir};
1.4 barstow 135:
1.5 barstow 136: String cmdArray[] = {m_GraphVizPath, "-Tgif", "-o", gifFileName, dotFileName};
1.4 barstow 137:
138: Runtime rt = Runtime.getRuntime();
139: try {
140: Process p = rt.exec(cmdArray, environment);
141: p.waitFor();
142: } catch (Exception e) {
143: return false;
144: }
145:
146: return true;
1.3 barstow 147: }
1.1 barstow 148:
1.3 barstow 149: /*
1.6 ! barstow 150: * Returns a parameter from a request or the parameter's default
! 151: * value.
! 152: *
! 153: *@param req a Servlet request
! 154: *@return if the request contains the specfied parameter its value
! 155: * in the request is returned; otherwise its default value is
! 156: * returned
! 157: */
! 158: private String getParameter(HttpServletRequest req, String param, String defString) {
! 159: String s = req.getParameter(param);
! 160: return (s == null) ? defString : s;
! 161: }
! 162:
! 163: /*
! 164: * If the request contains any graph-related parameters, pass them
! 165: * to the graph consumer for handling
! 166: *
! 167: *@param req the response
! 168: *@param consumer the GraphViz consumer
! 169: */
! 170: private void processGraphParameters (HttpServletRequest req, GraphVizDumpConsumer consumer) {
! 171: // Look for colors
! 172:
! 173: String s;
! 174:
! 175: String nodeColor = getParameter (req, NODE_COLOR, DEFAULT_NODE_COLOR);
! 176: String nodeTextColor = getParameter (req, NODE_TEXT_COLOR, DEFAULT_NODE_TEXT_COLOR);
! 177: String edgeColor = getParameter (req, EDGE_COLOR, DEFAULT_EDGE_COLOR);
! 178: String edgeTextColor = getParameter (req, EDGE_TEXT_COLOR, DEFAULT_EDGE_TEXT_COLOR);
! 179: String fontSize = getParameter (req, FONT_SIZE, DEFAULT_FONT_SIZE);
! 180:
! 181: // Orientation must be either
! 182: String orientation = req.getParameter (ORIENTATION);
! 183: if (orientation.equals("Left to Right"))
! 184: orientation = "LR";
! 185: else
! 186: orientation = DEFAULT_ORIENTATION;
! 187:
! 188: // Add an attribute for all of the graph's nodes
! 189: consumer.addGraphAttribute("node [fontname=" + DEFAULT_FONT +
! 190: ",fontsize=" + fontSize +
! 191: ",color=" + nodeColor +
! 192: ",fontcolor=" + nodeTextColor + "]");
! 193:
! 194: // Add an attribute for all of the graph's edges
! 195: consumer.addGraphAttribute("edge [fontname=" + DEFAULT_FONT +
! 196: ",fontsize=" + fontSize +
! 197: ",color=" + edgeColor +
! 198: ",fontcolor=" + edgeTextColor + "]");
! 199:
! 200: // Add an attribute for the orientation
! 201: consumer.addGraphAttribute("rankdir=" + orientation + ";");
! 202: }
! 203:
! 204: /*
1.3 barstow 205: * Generate a graph of the RDF data model
206: *
1.4 barstow 207: *@param out the servlet's output stream
1.6 ! barstow 208: *@param rdf the RDF text
! 209: *@param req a Servlet request
1.3 barstow 210: */
211: private void generateGraph (ServletOutputStream out, String rdf, HttpServletRequest req) {
1.2 barstow 212: try {
213: out.println("<hr title=\"visualisation\">");
1.3 barstow 214: out.println("<h3>Graph of the data model</h3>");
215:
1.4 barstow 216: // Stop if any of the parameters are missing
1.5 barstow 217: if (m_SiRPACTmpDir == null || m_GraphVizPath == null ||
218: m_GraphVizFontDir == null || m_GraphVizLibDir == null) {
1.3 barstow 219: out.println("Servlet initialization failed. A graph cannot be generated.");
220: return;
221: }
222:
1.4 barstow 223: // The temporary directory
224: String tmpDir = m_SiRPACTmpDir;
1.3 barstow 225:
1.4 barstow 226: // Must generate a unique file name that the DOT consumer
227: // will use
228: File dotFile = createTempFile(tmpDir, TMP_FILE_PREFIX, DOT_SUFFIX);
229: if (dotFile == null) {
230: out.println("Failed to create a temporary DOT file. A graph cannot be generated.");
1.3 barstow 231: return;
232: }
233:
234: // Create a PrintWriter for the GraphViz consumer
1.4 barstow 235: FileWriter fw = new FileWriter(dotFile);
1.3 barstow 236: PrintWriter pw = new PrintWriter(fw);
237:
238: // Run the parser using the DOT consumer to capture
239: // the output in a file
240: StringReader sr = new StringReader (rdf);
241: InputSource is = new InputSource (sr);
242: GraphVizDumpConsumer consumer = new GraphVizDumpConsumer(pw);
243:
1.6 ! barstow 244: // Process any graph-related parameters in the request
! 245: processGraphParameters(req, consumer);
! 246:
1.3 barstow 247: try {
248: m_sirpac.parse(is, consumer);
249: } catch (Exception e) {
250: out.println("An attempt to generate the graph data failed ("
251: + e.getMessage() + ").");
1.4 barstow 252: pw.close();
253: dotFile.delete();
1.3 barstow 254: return;
255: }
256:
1.4 barstow 257: // Must close the DOT input file so the GraphViz can
258: // open and read it
259: pw.close();
260:
261: // Must generate a unique file name for the GIF file
262: // that will be created
263: File gifFile = createTempFile(tmpDir, TMP_FILE_PREFIX, GIF_SUFFIX);
264: if (gifFile == null) {
265: out.println("Failed to create a temporary GIF file. A graph cannot be generated.");
266: dotFile.delete();
267: return;
268: }
269:
1.3 barstow 270: // Pass the DOT data file to the GraphViz dot program
1.4 barstow 271: // so it can create a GIF image of the data model
272: String dotFileName = dotFile.getAbsolutePath();
273: String gifFileName = gifFile.getAbsolutePath();
274:
275: if (!generateGifFile(dotFileName, gifFileName)) {
276: out.println("An attempt to create a graph failed.");
277: dotFile.delete();
278: gifFile.delete();
279: return;
280: }
1.3 barstow 281:
1.4 barstow 282: // @@ Cleanup
283: // dotFile.delete();
1.3 barstow 284:
1.4 barstow 285: // @@ Delete the GIF file
1.3 barstow 286:
1.4 barstow 287: String imagePath = HttpUtils.getRequestURL(req).toString() +
288: TMP_DIR_SUFFIX + File.separator + gifFile.getName();
1.2 barstow 289:
1.4 barstow 290: if (gifFile.length() > 0)
291: out.println("<img src=\"" + imagePath + "\"/>");
292: else
293: out.println("The graph image file is empty.");
1.2 barstow 294:
295: } catch (Exception e) {
296: System.err.println("Exception: " + e.getMessage());
297: }
298: }
299:
300: /*
1.3 barstow 301: * Search the given string for substring "key"
1.2 barstow 302: * and if it is found, replace it with string "replacement"
303: *
1.4 barstow 304: *@param input the input string
305: *@param key the string to search for
306: *@param replacement the string to replace all occurences of "key"
1.2 barstow 307: *@return if no substitutions are done, input is returned; otherwise
308: * a new string is returned.
309: */
310: private String replaceString(String input, String key, String replacement) {
311: StringBuffer sb = new StringBuffer("");
312: StringTokenizer st = new StringTokenizer(input, key);
313:
314: // Must handle the case where the input string begins with the key
315: if (input.startsWith(key))
316: sb = sb.append(replacement);
317: while (st.hasMoreTokens()) {
318: sb = sb.append(st.nextToken());
319: if (st.hasMoreTokens())
320: sb = sb.append(replacement);
321: }
322: if (sb.length() >= 1)
323: return sb.toString();
324: else
325: return input;
326: }
327:
1.3 barstow 328: /*
329: * Print the document's header info
330: *
331: *@param out the servlet's output stream
332: */
1.1 barstow 333: private void printDocumentHeader (ServletOutputStream out) {
334:
335: try {
336:
337: out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"");
338: out.println(" \"http://www.w3.org/TR/REC-html40/loose.dtd\">");
339: out.println("<HTML><HEAD>");
340: out.println("<TITLE>RDF creation</TITLE>");
341: out.println("<LINK HREF=\"rdf.css\" REL=\"stylesheet\">");
342: out.println("</HEAD>");
343: out.println("<BODY>");
344:
345: } catch (Exception e) {
1.2 barstow 346: System.err.println("Exception: " + e.getMessage());
1.1 barstow 347: }
348: }
349:
1.3 barstow 350: /*
351: * Print the rdf listing
352: *
353: *@param out the servlet's output stream
354: *@param rdf the RDF code
355: */
1.1 barstow 356: private void printListing (ServletOutputStream out, String rdf) {
357: try {
358: out.println("<hr title=\"original source\">");
359: out.println("<h3>The original RDF/XML document</h3>");
360: out.println("<pre>");
361:
1.2 barstow 362: String s = replaceString(rdf, "<", "<");
363: StringTokenizer st = new StringTokenizer(s, "\n");
1.1 barstow 364:
365: // Now output the RDF one line at a time with line numbers
366: int lineNum = 1;
367: while (st.hasMoreTokens()) {
368: out.print ("<a name=\"" + lineNum + "\">" + lineNum +
369: "</a>: " + st.nextToken());
370: lineNum++;
371: }
372:
373: out.println("</pre>");
374: } catch (Exception e) {
375: System.err.println("Exception: " + e.getMessage());
376: }
377: }
378:
1.3 barstow 379: /*
380: * Print the header for the triple listing
381: *
382: *@param out the servlet's output stream
383: */
1.1 barstow 384: private void printTripleHeader (ServletOutputStream out) {
385: try {
386: out.println("<hr title=\"triples\">");
387: out.println("<h3>Triples of the data model</h3>");
388:
389: // The output for each triple will be pre-formatted
390: out.println("<pre>");
391: } catch (Exception e) {
392: System.err.println("Exception: " + e.getMessage());
393: }
394: }
395:
1.3 barstow 396: /*
397: * Print the footer info for the triple listing
398: *
399: *@param out the servlet's output stream
400: */
1.1 barstow 401: private void printTripleFooter (ServletOutputStream out) {
402: try {
403: out.println("</pre>");
404: } catch (Exception e) {
405: System.err.println("Exception: " + e.getMessage());
406: }
407: }
1.3 barstow 408:
409: /*
410: * Print the document's footer info
411: *
412: *@param out the servlet's output stream
413: *@param rdf the RDF code
414: */
1.1 barstow 415: private void printDocumentFooter (ServletOutputStream out, String rdf) {
416: try {
417:
418: out.println("<hr title=\"Problem reporting\">");
419: out.println("<h3>Feedback</h3>");
1.2 barstow 420: 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>");
1.1 barstow 421: out.println("<form enctype=\"text/plain\" method=\"post\" action=\"mailto:" + MAIL_TO + "\">");
422: out.println("<textarea cols=\"60\" rows=\"4\" name=\"report\"></textarea>");
1.2 barstow 423: out.println("<p><input type=\"hidden\" name=\"RDF\" value=\"<?xml version="1.0"?>");
1.1 barstow 424:
1.2 barstow 425: // The listing is being passed as a parameter so the '<'
426: // and '"' characters must be replaced with < and ",
427: // respectively
428: String s1 = replaceString(rdf, "<", "<");
429: String s2 = replaceString(s1, "\"", """);
430: out.println(s2 + "\">");
1.1 barstow 431:
432: out.println("<input type=\"submit\" value=\"Submit problem report\">");
433: out.println("</form>");
434: out.println("<hr><a href=\"/description\">Back</a> to main page.");
435: out.println("</BODY>");
436: out.println("</HTML>");
437:
438: } catch (Exception e) {
1.2 barstow 439: System.err.println("Exception: " + e.getMessage());
1.1 barstow 440: }
441:
442: }
443:
1.3 barstow 444: /*
445: * Servlet's get info method
446: */
1.1 barstow 447: public String getServletInfo () {
448: return "Servlet Wrapper for SiRPAC. This is revision " + REVISION;
449: }
450:
1.3 barstow 451: /*
452: * Servlet's init method
453: *
454: *@param config the servlet's configuration object
455: */
1.1 barstow 456: public void init(ServletConfig config) throws ServletException {
457: super.init (config);
458:
459: m_sirpac = new SiRPAC();
460: m_errorHandler = new ErrorStore();
1.3 barstow 461: m_sirpac.setErrorHandler(m_errorHandler);
1.1 barstow 462:
1.3 barstow 463: // Cache the parameters
464: m_SiRPACTmpDir = config.getInitParameter(SIRPAC_TMP_DIR);
1.5 barstow 465:
466: // All of the Graph Viz paths extend from GRAPH_VIZ_ROOT
467: String GraphVizRoot = config.getInitParameter(GRAPH_VIZ_ROOT);
468:
469: m_GraphVizPath = GraphVizRoot + "/" + config.getInitParameter(GRAPH_VIZ_PATH);
470: m_GraphVizFontDir = GraphVizRoot + "/" + config.getInitParameter(GRAPH_VIZ_FONT_DIR);
471: m_GraphVizLibDir = GraphVizRoot + "/" + config.getInitParameter(GRAPH_VIZ_LIB_DIR);
1.1 barstow 472: }
473:
1.3 barstow 474: /*
475: * Servlet's destroy info method
476: */
1.1 barstow 477: public void destroy () {
478: super.destroy ();
479: }
480:
1.3 barstow 481: /*
1.4 barstow 482: * Servlet's doGet info method - NOT supported
1.3 barstow 483: *
484: *@param req the request
485: *@param res the response
486: */
1.1 barstow 487: public void doGet (HttpServletRequest req, HttpServletResponse res)
488: throws ServletException, IOException {
1.3 barstow 489:
1.1 barstow 490: ServletOutputStream out = res.getOutputStream ();
491:
492: res.setContentType ("text/html");
493:
1.3 barstow 494: out.println ("<h1>GET is NOT supported!</h1>\n\n<p>Please send RDF through POST!</p>\n");
1.1 barstow 495: }
496:
1.3 barstow 497: /*
498: * Servlet's doPost method
499: *
500: *@param req the request
501: *@param res the response
502: */
1.1 barstow 503: public void doPost (HttpServletRequest req, HttpServletResponse res)
504: throws ServletException, IOException {
505:
506: ServletOutputStream out = res.getOutputStream ();
507:
508: String sRDF = req.getParameter ("RDF");
509: String sBags = req.getParameter ("BAGS");
510: StringReader sr = new StringReader (sRDF);
511: InputSource is = new InputSource (sr);
1.3 barstow 512: boolean error = false;
1.1 barstow 513: SiRPACServletDumpConsumer consumer = new SiRPACServletDumpConsumer();
514:
515: printDocumentHeader (out);
516: printListing (out, sRDF);
517: printTripleHeader (out);
518:
519: try {
1.3 barstow 520: // Override the default triple output handler
1.1 barstow 521: consumer.setOutputStream(out);
522:
1.6 ! barstow 523: // Toggle Bag handling - always false unless explicitly
! 524: // included in the request
! 525: m_sirpac.createBags (false);
1.1 barstow 526: if (sBags != null && sBags.equals ("on"))
527: m_sirpac.createBags (true);
528:
529: m_sirpac.parse(is, consumer);
530:
1.3 barstow 531: generateGraph(out, sRDF, req);
1.2 barstow 532:
1.1 barstow 533: } catch (SAXException e) {
1.3 barstow 534: error = true;
1.1 barstow 535: } catch (Exception e) {
1.3 barstow 536: error = true;
1.1 barstow 537: e.printStackTrace ();
538: }
539:
540: printTripleFooter(out);
541:
542: res.setContentType ("text/html");
1.3 barstow 543:
544: if (error) {
1.1 barstow 545: out.println ("<h1>Errors during parsing</h1>\n");
546: out.println ("<pre>\n");
1.2 barstow 547:
548: // Make the line number a link to the listing
1.1 barstow 549: out.println ("Fatal error: " + m_errorHandler.getErrorMessage());
550: out.println (" (Line number = " + "<a href=\"#" +
551: m_errorHandler.getLineNumber() + "\">" +
552: m_errorHandler.getLineNumber() + "</a>" +
553: ", Column number = " +
554: m_errorHandler.getColumnNumber() + ")");
555:
556: out.println ("</pre>\n\n");
557: }
558:
559: printDocumentFooter(out, sRDF);
560: }
561: }
Webmaster