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