Annotation of java/classes/org/w3c/rdf/examples/SiRPACServlet.java, revision 1.21

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.19      barstow    16:  * RDF - the RDF in an XML syntax 
                     17:  *
                     18:  * BAGS - if "on", each Description should have its own Bag;
                     19:  *   the default is not to do this.
                     20:  *
                     21:  * STREAM - if "on", the stream mode is turned off so that aboutEach
                     22:  *   and aboutEachPrefix are supported.  It is off by default.
                     23:  *
                     24:  * SAVE_DOT_FILE - if "on", the DOT file is saved and a link to the
                     25:  *   file is provided to the user
                     26:  *
                     27:  * SAVE_RDF - if "on", the RDF will be copied to a file.
                     28:  *
                     29:  * URI - the URI to parse [instead of the RDF]; may not be specified
                     30:  *
                     31:  * ORIENTATION - the graph's orientation (left to right or top to
                     32:  *   bottom
                     33:  *
                     34:  * FONT_SIZE - the font size to use [10, 12, 14, 16 and 20 are supported]
                     35:  *
                     36:  * GRAPH_FORMAT - the graph's output format.  Supported values are:
                     37:  *
                     38:  *     GIF_EMBED - embed the graph as a GIF [the default]
                     39:  *     GIF_LINK - don't embed the GIF but create a link for it
                     40:  *     SVG_LINK - create the graph in SVG format and create a link to the file
1.20      barstow    41:  *     PNG_EMBED - create the graph in PNG format and embed the graph in the 
                     42:  *       document that is returned
                     43:  *     PNG_LINK - create the graph in PNG format and create a link to the file
1.19      barstow    44:  *     PS_LINK - create a PostScript image of the file and a link to the file
                     45:  *     HP_PCL_LINK - create a HPGL/2 - PCL (Laserwriter) image of the file 
                     46:  *       and a link to the file
                     47:  *     HP_GL_LINK - create a HPGL - PCL (pen plotter) image of the file and 
                     48:  *       a link to the file
                     49:  *     NO_GRAPH - do not generate a graph
1.1       barstow    50:  *
1.21    ! barstow    51:  * NTRIPLES if "on" the tabular output will be in the NTriples format;
        !            52:  *  otherwise a table of Subject, Predicate, Objects will be generated
        !            53:  *
1.7       barstow    54:  * @author Art Barstow <barstow@w3.org>
1.1       barstow    55:  *
1.7       barstow    56:  * The graphics package is AT&T's GraphVis tool.
1.1       barstow    57:  */
                     58: 
                     59: package org.w3c.rdf.examples;
                     60: 
                     61: import java.io.*;
1.16      barstow    62: import java.net.MalformedURLException;
                     63: import java.net.URL;
1.1       barstow    64: import java.util.StringTokenizer;
                     65: import java.util.Enumeration;
                     66: import javax.servlet.*;
                     67: import javax.servlet.http.*;
                     68: 
                     69: import org.xml.sax.InputSource;
                     70: import org.xml.sax.Parser;
                     71: import org.xml.sax.SAXException;
                     72: import org.xml.sax.helpers.*;
                     73: 
                     74: import org.w3c.rdf.model.*;
                     75: import org.w3c.rdf.syntax.*;
                     76: import org.w3c.rdf.syntax.RDFConsumer;
                     77: import org.w3c.rdf.util.xml.DumpConsumer;
                     78: import org.w3c.rdf.util.xml.ErrorStore;
1.16      barstow    79: import org.w3c.rdf.util.xml.GenericParser;
1.1       barstow    80: import org.w3c.rdf.implementation.model.StatementImpl;
                     81: import org.w3c.rdf.implementation.model.NodeFactoryImpl;
                     82: import org.w3c.rdf.implementation.syntax.sirpac.*;
                     83: 
                     84: public class SiRPACServlet extends HttpServlet
                     85: {
1.21    ! barstow    86:     final static public String REVISION = "$Id: SiRPACServlet.java,v 1.20 2001/02/22 23:04:14 barstow Exp $";
1.1       barstow    87: 
1.7       barstow    88:     // The email address for bug reports
1.4       barstow    89:     private static final String MAIL_TO = "barstow@w3.org";
1.10      barstow    90: 
1.19      barstow    91:     // Names of the POST parameters (described above) and their
                     92:     // defaults 
                     93:     private static final String TEXT            = "RDF";
                     94:     private static final String BAG             = "BAGS";
                     95:     private static final String STREAM_MODE     = "STREAM";
                     96:     private static final String SAVE_DOT_FILE   = "SAVE_DOT_FILE";
                     97:     private static final String SAVE_RDF        = "SAVE_RDF";
                     98:     private static final String URI             = "URI";
1.21    ! barstow    99:     private static final String NTRIPLES        = "NTRIPLES";
1.3       barstow   100:  
1.6       barstow   101:     private static final String NODE_COLOR         = "NODE_COLOR";
                    102:     private static final String DEFAULT_NODE_COLOR = "black";
                    103: 
                    104:     private static final String NODE_TEXT_COLOR         = "NODE_TEXT_COLOR";
                    105:     private static final String DEFAULT_NODE_TEXT_COLOR = "black";
                    106: 
                    107:     private static final String EDGE_COLOR         = "EDGE_COLOR";
                    108:     private static final String DEFAULT_EDGE_COLOR = "black";
                    109: 
                    110:     private static final String EDGE_TEXT_COLOR         = "EDGE_TEXT_COLOR";
                    111:     private static final String DEFAULT_EDGE_TEXT_COLOR = "black";
                    112: 
                    113:     private static final String ORIENTATION         = "ORIENTATION";
                    114:     private static final String DEFAULT_ORIENTATION = "TB";  // Top to Bottom
                    115: 
                    116:     private static final String FONT_SIZE         = "FONT_SIZE";
                    117:     private static final String DEFAULT_FONT_SIZE = "10";
                    118: 
1.19      barstow   119:     private static final String FORMAT              = "FORMAT";
                    120:     private static final String FORMAT_GIF_EMBED    = "GIF_EMBED";
                    121:     private static final String FORMAT_GIF_LINK     = "GIF_LINK";
                    122:     private static final String FORMAT_SVG_LINK     = "SVG_LINK";
1.20      barstow   123:     private static final String FORMAT_PNG_EMBED    = "PNG_EMBED";
                    124:     private static final String FORMAT_PNG_LINK     = "PNG_LINK";
1.19      barstow   125:     private static final String FORMAT_PS_LINK      = "PS_LINK";
                    126:     private static final String FORMAT_HP_PCL_LINK  = "HP_PCL_LINK";
                    127:     private static final String FORMAT_HP_GL_LINK   = "HP_GL_LINK";
                    128:     private static final String FORMAT_NO_GRAPH     = "NO_GRAPH";
                    129: 
1.6       barstow   130:     // Fonts are not currently configurable
                    131:     private static final String DEFAULT_FONT = "arial";
                    132: 
1.19      barstow   133:     // Names of the servlet's parameters - for Jigsaw web server
                    134:     private static final String SIRPAC_TMP_DIR       = "SIRPAC_TMP_DIR";
                    135:     private static final String GRAPH_VIZ_ROOT       = "GRAPH_VIZ_ROOT";
                    136:     private static final String GRAPH_VIZ_PATH       = "GRAPH_VIZ_PATH";
                    137:     private static final String GRAPH_VIZ_LIB_DIR    = "GRAPH_VIZ_LIB_DIR";
                    138:     private static final String GRAPH_VIZ_FONT_DIR   = "GRAPH_VIZ_FONT_DIR";
                    139: 
                    140:     // Variables for the servlet's parameters
                    141:     private static String m_SiRPACTmpDir      = null;
                    142:     private static String m_GraphVizPath      = null;
                    143:     private static String m_GraphVizFontDir   = null;
                    144:     private static String m_GraphVizLibDir    = null;
                    145: 
                    146:     // Names of environment variable need by GraphVis
                    147:     private static String DOTFONTPATH     = "DOTFONTPATH";
                    148:     private static String LD_LIBRARY_PATH = "LD_LIBRARY_PATH";
                    149: 
                    150:     // Names used for temporary files
                    151:     private static final String TMP_FILE_PREFIX = "sirpac_";
                    152:     private static final String SUFFIX_TMP_DIR  = ".tmp";
                    153:     private static final String SUFFIX_DOT      = ".dot";
                    154:     private static final String SUFFIX_RDF      = ".rdf";
                    155: 
                    156:     // Names used for file suffixes and for GraphViz's command line
                    157:     // option
                    158:     private static final String NAME_GIF      = "gif";
                    159:     private static final String NAME_HPGL     = "hpgl";
                    160:     private static final String NAME_PCL      = "pcl";
1.20      barstow   161:     private static final String NAME_PNG      = "png";
1.19      barstow   162:     private static final String NAME_PS       = "ps";
                    163:     private static final String NAME_SVG      = "svg";
                    164: 
                    165:     // Default GraphViz parameter names and their default values
1.8       barstow   166:     // Servlet name
                    167:     private static final String SERVLET_NAME = "SiRPACServlet";
                    168: 
1.3       barstow   169:     /*
1.4       barstow   170:      * Create a File object in the m_SiRPACTmpDir directory
1.3       barstow   171:      *
1.4       barstow   172:      *@param directory the file's directory
                    173:      *@param prefix the file's prefix name (not its directory)
                    174:      *@param suffix the file's suffix or extension name
                    175:      *@return a File object if a temporary file is created; null otherwise
1.3       barstow   176:      */
1.4       barstow   177:     private File createTempFile (String directory, String prefix, String suffix) {
                    178:         File f;
                    179:         try {
                    180:             File d = new File(directory);
                    181:             f = File.createTempFile(prefix, suffix, d);
                    182:         } catch (Exception e) {
                    183:             return null;
                    184:         }
                    185:         return f;
                    186:     }
                    187: 
1.14      barstow   188: 
                    189:     /*
                    190:      * Copy the given string of RDF to a file in the given directory
                    191:      *
                    192:      *@param dir the file's directory
                    193:      *@param rdf the string of RDF
                    194:      *@return void
                    195:      */
                    196: 
                    197:     private void copyRDFStringToFile(String tmpDir, String rdf) 
                    198:     {
                    199:         try {
                    200:             // Generate a unique file name 
1.19      barstow   201:             File tmpFile = createTempFile(tmpDir, TMP_FILE_PREFIX, SUFFIX_RDF);
1.14      barstow   202:             if (tmpFile == null) {
                    203:                 // Not really a critical error, just return
                    204:                 return;
                    205:             }
                    206: 
                    207:             // Create a PrintWriter for the GraphViz consumer
                    208:             FileWriter fw = new FileWriter(tmpFile);
                    209:             PrintWriter pw = new PrintWriter(fw);
                    210: 
                    211:             pw.println(rdf);
                    212:             pw.close();
                    213:         } catch (Exception e) {
                    214:             // Just return - not critical
                    215:             return;
                    216:         }
                    217:     }
                    218: 
1.4       barstow   219:     /*
1.19      barstow   220:      * Given the graph's format option, return either the corresponding
                    221:      * command line option for that option or the file name suffix for
                    222:      * the graph option.  For example GIF files have ".gif" for its
                    223:      * suffix and GraphViz uses "-Tgif" for the command line.
                    224:      *
                    225:      * NOTE: default is GIF.
                    226:      *
                    227:      *@param graphFormat the graph's output format
                    228:      *@param suffix.  If true, the name returned is for the graph's
                    229:      * file name suffix; otherwise, the name returned is for the
                    230:      * graph's command line option.
                    231:      *@return the suffix to use for the graph's output file
                    232:      */
                    233:     private String getFormatName(String graphFormat, boolean suffix) {
                    234: 
                    235:         String name = (suffix) ? "." : "-T";
                    236: 
1.20      barstow   237:         if (graphFormat.equals(FORMAT_PNG_EMBED)) return name + NAME_PNG;
                    238:         if (graphFormat.equals(FORMAT_PNG_LINK)) return name + NAME_PNG;
1.19      barstow   239:         if (graphFormat.equals(FORMAT_SVG_LINK)) return name + NAME_SVG;
                    240:         if (graphFormat.equals(FORMAT_PS_LINK)) return name + NAME_PS;
                    241:         if (graphFormat.equals(FORMAT_HP_GL_LINK)) return name + NAME_HPGL;
                    242:         if (graphFormat.equals(FORMAT_HP_PCL_LINK)) return name + NAME_PCL;
                    243:         
                    244:         return name + NAME_GIF;
                    245:     }
                    246: 
                    247:     /*
1.20      barstow   248:      * Invokes the GraphVis program to create a graph image from the
1.4       barstow   249:      * the given DOT data file
                    250:      *
                    251:      *@param dotFileName the name of the DOT data file
1.20      barstow   252:      *@param outputFileName the name of the output data file 
1.4       barstow   253:      *@return true if success; false if any failure occurs
                    254:      */
1.19      barstow   255:     private boolean generateOutputFile(String dotFileName, String outputFileName, String graphFormat) {
1.5       barstow   256:         String environment[] = {DOTFONTPATH     + "=" + m_GraphVizFontDir,
                    257:                                 LD_LIBRARY_PATH + "=" + m_GraphVizLibDir};
1.4       barstow   258: 
1.19      barstow   259:         String formatOption = getFormatName(graphFormat, false);
                    260: 
                    261:         String cmdArray[] = {m_GraphVizPath, formatOption, "-o", outputFileName, dotFileName};
1.4       barstow   262: 
                    263:         Runtime rt = Runtime.getRuntime();
                    264:         try {
                    265:             Process p = rt.exec(cmdArray, environment);
                    266:             p.waitFor();
                    267:         } catch (Exception e) {
                    268:             return false;
                    269:         }
                    270: 
                    271:         return true;
1.3       barstow   272:     }
1.1       barstow   273: 
1.3       barstow   274:     /*
1.6       barstow   275:      * Returns a parameter from a request or the parameter's default
                    276:      * value.
                    277:      *
                    278:      *@param req a Servlet request
                    279:      *@return if the request contains the specfied parameter its value
                    280:      *  in the request is returned; otherwise its default value is
                    281:      *  returned
                    282:      */
                    283:     private String getParameter(HttpServletRequest req, String param, String defString) {
                    284:         String s = req.getParameter(param);
                    285:         return (s == null) ? defString : s;
                    286:     }
                    287: 
                    288:     /*
                    289:      * If the request contains any graph-related parameters, pass them
                    290:      * to the graph consumer for handling
                    291:      *
                    292:      *@param req the response
                    293:      *@param consumer the GraphViz consumer
                    294:      */
                    295:     private void processGraphParameters (HttpServletRequest req, GraphVizDumpConsumer consumer) {
                    296:         // Look for colors
                    297: 
                    298:        String s;
                    299:        
                    300:         String nodeColor     = getParameter (req, NODE_COLOR, DEFAULT_NODE_COLOR);
                    301:         String nodeTextColor = getParameter (req, NODE_TEXT_COLOR, DEFAULT_NODE_TEXT_COLOR);
                    302:         String edgeColor     = getParameter (req, EDGE_COLOR, DEFAULT_EDGE_COLOR);
                    303:         String edgeTextColor = getParameter (req, EDGE_TEXT_COLOR, DEFAULT_EDGE_TEXT_COLOR);
                    304:         String fontSize = getParameter (req, FONT_SIZE, DEFAULT_FONT_SIZE);
                    305: 
                    306:         // Orientation must be either 
                    307:         String orientation = req.getParameter (ORIENTATION);
1.19      barstow   308:         if (orientation.equals("LR"))
1.6       barstow   309:             orientation = "LR";
                    310:         else
                    311:             orientation = DEFAULT_ORIENTATION;
                    312: 
                    313:         // Add an attribute for all of the graph's nodes
                    314:         consumer.addGraphAttribute("node [fontname=" + DEFAULT_FONT + 
                    315:                                    ",fontsize="  + fontSize +
                    316:                                    ",color="     + nodeColor +
                    317:                                    ",fontcolor=" + nodeTextColor + "]");
                    318: 
                    319:         // Add an attribute for all of the graph's edges
                    320:         consumer.addGraphAttribute("edge [fontname=" + DEFAULT_FONT + 
                    321:                                    ",fontsize="  + fontSize +
                    322:                                    ",color="     + edgeColor +
                    323:                                    ",fontcolor=" + edgeTextColor + "]");
                    324: 
                    325:         // Add an attribute for the orientation
                    326:         consumer.addGraphAttribute("rankdir=" + orientation + ";");
                    327:     }
                    328: 
                    329:     /*
1.3       barstow   330:      * Generate a graph of the RDF data model
                    331:      *
1.4       barstow   332:      *@param out the servlet's output stream
1.6       barstow   333:      *@param rdf the RDF text
                    334:      *@param req a Servlet request
1.19      barstow   335:      *@param source the name of input source
                    336:      *@param graphFormat the graph's format
                    337:      *@param saveRDF the RDF can be cached [saved to the file system]
                    338:      *@param saveDOTFile the DOT file should be cached
                    339:      *@param createBags the parser should create a bag for each Description
                    340:      *@param streamMode the parser's stream mode setting
1.3       barstow   341:      */
1.19      barstow   342:     private void generateGraph (ServletOutputStream out, String rdf, HttpServletRequest req, String source, String graphFormat, boolean saveRDF, boolean saveDOTFile, boolean createBags, boolean streamMode) {
1.2       barstow   343:         try {
                    344:             out.println("<hr title=\"visualisation\">");
1.3       barstow   345:             out.println("<h3>Graph of the data model</h3>");
                    346: 
1.4       barstow   347:             // Stop if any of the parameters are missing
1.19      barstow   348:             if (m_SiRPACTmpDir == null || 
                    349:                 m_GraphVizPath == null || 
                    350:                 m_GraphVizFontDir == null || 
                    351:                 m_GraphVizLibDir == null) { 
1.8       barstow   352:  
                    353:                 // Put the paths in a comment in the returned content
                    354:                 out.println("<!-- SIRPAC TMP = " + m_SiRPACTmpDir);
                    355:                 out.println("GRAPH VIZ  = " + m_GraphVizPath);
                    356:                 out.println("GRAPH LIB  = " + m_GraphVizLibDir);
                    357:                 out.println("GRAPH FON  = " + m_GraphVizFontDir + " -->");
                    358: 
1.3       barstow   359:                 out.println("Servlet initialization failed.  A graph cannot be generated.");
                    360:                 return;
                    361:             } 
                    362: 
1.4       barstow   363:             // The temporary directory
                    364:             String tmpDir = m_SiRPACTmpDir;
1.3       barstow   365: 
1.4       barstow   366:             // Must generate a unique file name that the DOT consumer
                    367:             // will use 
1.19      barstow   368:             File dotFile = createTempFile(tmpDir, TMP_FILE_PREFIX, SUFFIX_DOT);
1.4       barstow   369:             if (dotFile == null) {
                    370:                 out.println("Failed to create a temporary DOT file. A graph cannot be generated.");
1.3       barstow   371:                 return;
                    372:             }
                    373: 
                    374:             // Create a PrintWriter for the GraphViz consumer
1.4       barstow   375:             FileWriter fw = new FileWriter(dotFile);
1.3       barstow   376:             PrintWriter pw = new PrintWriter(fw);
                    377: 
                    378:             // Run the parser using the DOT consumer to capture
                    379:             // the output in a file
                    380:            StringReader         sr = new StringReader (rdf);
                    381:            InputSource          is = new InputSource (sr);
                    382:             GraphVizDumpConsumer consumer = new GraphVizDumpConsumer(pw);
                    383: 
1.6       barstow   384:             // Process any graph-related parameters in the request
                    385:             processGraphParameters(req, consumer);
1.15      barstow   386: 
                    387:             // Reinitialize the parser's genid counter so the genids
                    388:             // of the triple will match the genids of the graph
1.18      barstow   389:             SiRPAC  sirpac = new SiRPAC();
                    390:             ErrorStore    errorHandler = new ErrorStore();
                    391: 
                    392:             sirpac.setErrorHandler(errorHandler);
                    393:             sirpac.createBags (createBags);
                    394:             sirpac.setStreamMode (streamMode);
                    395:             sirpac.setSource(source);
1.6       barstow   396: 
1.3       barstow   397:            try {
1.18      barstow   398:                 sirpac.parse(is, consumer);
1.3       barstow   399:            } catch (Exception e) {
                    400:                 out.println("An attempt to generate the graph data failed ("
                    401:                             + e.getMessage() + ").");
1.4       barstow   402:                 pw.close();
                    403:                 dotFile.delete();
1.3       barstow   404:                 return;
                    405:            }
                    406: 
1.4       barstow   407:             // Must close the DOT input file so the GraphViz can
                    408:             // open and read it
                    409:             pw.close();
                    410: 
1.20      barstow   411:             // Must generate a unique file name for the output file
1.4       barstow   412:             // that will be created
1.19      barstow   413:             String suffix = getFormatName(graphFormat, true);
                    414:             File outputFile = createTempFile(tmpDir, TMP_FILE_PREFIX, suffix);
                    415:             if (outputFile == null) {
                    416:                 out.println("Failed to create a temporary file for the graph. A graph cannot be generated.");
1.4       barstow   417:                 dotFile.delete();
                    418:                 return;
                    419:             }
                    420: 
1.3       barstow   421:             // Pass the DOT data file to the GraphViz dot program
1.20      barstow   422:             // so it can create a graph image of the data model
1.4       barstow   423:             String dotFileName = dotFile.getAbsolutePath();
1.19      barstow   424:             String outputFileName = outputFile.getAbsolutePath();
1.4       barstow   425: 
1.19      barstow   426:             if (!generateOutputFile(dotFileName, outputFileName, graphFormat)) {
1.4       barstow   427:                 out.println("An attempt to create a graph failed.");
                    428:                 dotFile.delete();
1.19      barstow   429:                 outputFile.delete();
1.4       barstow   430:                 return;
                    431:             }
1.3       barstow   432: 
1.19      barstow   433:             // Handle the DOT file
                    434:             if (saveDOTFile) {
                    435:                 // Make the DOT file link'able if so requested
                    436:                 String dotPath = SERVLET_NAME + SUFFIX_TMP_DIR + 
                    437:                                  File.separator + dotFile.getName();
                    438:                 out.println("<a href=\"" + dotPath + "\">Get the DOT file.</a><br /><br />");
                    439:             }
                    440:             else {
                    441:                 // Delete it ...
                    442:                 dotFile.delete();
                    443:             }
1.3       barstow   444: 
1.20      barstow   445:             // NOTE: Cannot delete the output file here because its
1.9       barstow   446:             // pathname is returned to the client
1.19      barstow   447:             String imagePath = SERVLET_NAME + SUFFIX_TMP_DIR + File.separator + 
                    448:                                outputFile.getName();
                    449: 
                    450:             // Handle the embedded image formats first
1.20      barstow   451:             if (graphFormat.equals(FORMAT_GIF_EMBED) ||
                    452:                 graphFormat.equals(FORMAT_PNG_EMBED)) {
1.19      barstow   453:                 if (outputFile.length() > 0)
                    454:                     out.println("<img src=\"" + imagePath + "\"/>");
                    455:                 else
                    456:                     out.println("The graph image file is empty.");
                    457:             } else {
                    458:                 if (outputFile.length() > 0)
                    459:                     out.println("<a href=\"" + imagePath + "\">Get/view the graph's image file (" + suffix + ").</a><br /><br />");
                    460:                 else
                    461:                     out.println("The graph image file is empty.");
                    462:             }
1.2       barstow   463: 
1.14      barstow   464:             // One last thing to do before exiting - copy the RDF to a file
                    465:             if (saveRDF)
                    466:                 copyRDFStringToFile(tmpDir, rdf);
                    467: 
1.2       barstow   468:         } catch (Exception e) {
                    469:             System.err.println("Exception: " + e.getMessage());
                    470:         }
                    471:     }
                    472: 
                    473:     /*
1.3       barstow   474:      * Search the given string for substring "key"
1.2       barstow   475:      * and if it is found, replace it with string "replacement"
                    476:      *
1.4       barstow   477:      *@param input the input string
                    478:      *@param key the string to search for
                    479:      *@param replacement the string to replace all occurences of "key"
1.2       barstow   480:      *@return if no substitutions are done, input is returned; otherwise 
                    481:      * a new string is returned.
                    482:      */
1.12      barstow   483:     public static String replaceString(String input, String key, String replacement) {
1.2       barstow   484:         StringBuffer sb = new StringBuffer("");
                    485:         StringTokenizer st = new StringTokenizer(input, key);
                    486: 
                    487:         // Must handle the case where the input string begins with the key
                    488:         if (input.startsWith(key))
                    489:             sb = sb.append(replacement);
                    490:         while (st.hasMoreTokens()) {
                    491:             sb = sb.append(st.nextToken());
                    492:             if (st.hasMoreTokens())
                    493:                 sb = sb.append(replacement);
                    494:         }
                    495:         if (sb.length() >= 1)
                    496:             return sb.toString();
                    497:         else
                    498:             return input;
                    499:     }
                    500: 
1.3       barstow   501:     /*
                    502:      * Print the document's header info
                    503:      *
                    504:      *@param out the servlet's output stream
                    505:      */
1.1       barstow   506:     private void printDocumentHeader (ServletOutputStream out) {
                    507: 
                    508:         try {
                    509: 
                    510:             out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"");
                    511:             out.println("      \"http://www.w3.org/TR/REC-html40/loose.dtd\">");
                    512:             out.println("<HTML><HEAD>");
                    513:             out.println("<TITLE>RDF creation</TITLE>");
                    514:             out.println("<LINK HREF=\"rdf.css\" REL=\"stylesheet\">");
                    515:             out.println("</HEAD>");
                    516:             out.println("<BODY>");
                    517: 
                    518:         } catch (Exception e) {
1.2       barstow   519:             System.err.println("Exception: " + e.getMessage());
1.1       barstow   520:         }
                    521:     }
                    522: 
1.3       barstow   523:     /*
                    524:      * Print the rdf listing
                    525:      *
                    526:      *@param out the servlet's output stream
                    527:      *@param rdf the RDF code
                    528:      */
1.16      barstow   529:     private void printListing (ServletOutputStream out, String rdf, boolean needCR) {
1.1       barstow   530:         try {
                    531:             out.println("<hr title=\"original source\">");
                    532:             out.println("<h3>The original RDF/XML document</h3>");
                    533:             out.println("<pre>");
                    534: 
1.2       barstow   535:             String s = replaceString(rdf, "<", "&lt;");
                    536:             StringTokenizer st = new StringTokenizer(s, "\n");
1.1       barstow   537: 
                    538:             // Now output the RDF one line at a time with line numbers
                    539:             int lineNum = 1;
                    540:             while (st.hasMoreTokens()) {
1.16      barstow   541:                 if (needCR) 
                    542:                     out.print ("<a name=\"" + lineNum + "\">" + lineNum +
                    543:                                "</a>: " + st.nextToken() + "\n");
                    544:                 else
                    545:                     out.print ("<a name=\"" + lineNum + "\">" + lineNum +
                    546:                                "</a>: " + st.nextToken());
1.1       barstow   547:                 lineNum++;
                    548:             }
                    549: 
                    550:             out.println("</pre>");
                    551:         } catch (Exception e) {
                    552:             System.err.println("Exception: " + e.getMessage());
                    553:         }
                    554:     }
                    555: 
1.3       barstow   556:     /*
                    557:      * Print the header for the triple listing
                    558:      *
                    559:      *@param out the servlet's output stream
                    560:      */
1.21    ! barstow   561:     private void printTripleTableHeader (ServletOutputStream out, boolean nTriples) 
        !           562:     {
1.1       barstow   563:         try {
1.21    ! barstow   564:             if (nTriples) {
        !           565:                 out.println("<h3>Triples of the Data Model in N-Triples Format (Sub, Pred, Obj)</h3>");
        !           566:                 out.println("<pre>");
        !           567:             } else {
        !           568:                 out.println("<hr title=\"triples\">");
        !           569:                 out.println("<h3>Triples of the Data Model</h3>");
        !           570:                 out.println("<table border><tr>" +
        !           571:                            "<td><b>Number</b></td>" +
        !           572:                            "<td><b>Subject</b></td>" +
        !           573:                            "<td><b>Predicate</b></td>" +
        !           574:                            "<td><b>Object</b></td>" +
        !           575:                            "</tr>");
        !           576:             }
1.1       barstow   577:         } catch (Exception e) {
                    578:             System.err.println("Exception: " + e.getMessage());
                    579:         }
                    580:     }
                    581: 
1.3       barstow   582:     /*
                    583:      * Print the footer info for the triple listing
                    584:      *
                    585:      *@param out the servlet's output stream
                    586:      */
1.21    ! barstow   587:     private void printTripleTableFooter (ServletOutputStream out, 
        !           588:         SiRPACServletDumpConsumer consumer, boolean nTriples) 
        !           589:     {
1.1       barstow   590:         try {
1.21    ! barstow   591:             if (nTriples)
        !           592:                 out.println("</pre>");
        !           593:             else
        !           594:                 out.println("</table>");
1.14      barstow   595:             if (consumer != null)
                    596:                 out.println("<p>The number of triples = " + consumer.getNumStatements() + "</p>");
1.1       barstow   597:         } catch (Exception e) {
                    598:             System.err.println("Exception: " + e.getMessage());
                    599:         }
                    600:     }
1.3       barstow   601: 
                    602:     /*
                    603:      * Print the document's footer info
                    604:      *
                    605:      *@param out the servlet's output stream
                    606:      *@param rdf the RDF code
                    607:      */
1.1       barstow   608:     private void printDocumentFooter (ServletOutputStream out, String rdf) {
                    609:         try {
                    610: 
                    611:             out.println("<hr title=\"Problem reporting\">");
                    612:             out.println("<h3>Feedback</h3>");
1.2       barstow   613:             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   614:             out.println("<form enctype=\"text/plain\" method=\"post\" action=\"mailto:" + MAIL_TO + "\">");
                    615:             out.println("<textarea cols=\"60\" rows=\"4\" name=\"report\"></textarea>");
1.2       barstow   616:             out.println("<p><input type=\"hidden\" name=\"RDF\" value=\"&lt;?xml version=&quot;1.0&quot;?>");
1.1       barstow   617: 
1.2       barstow   618:             // The listing is being passed as a parameter so the '<' 
                    619:             // and '"' characters must be replaced with &lt; and &quot, 
                    620:             // respectively
1.16      barstow   621:             if (rdf != null) {
                    622:                 String s1 = replaceString(rdf, "<", "&lt;");
                    623:                 String s2 = replaceString(s1,  "\"", "&quot;");
                    624:                 out.println(s2 + "\">");
                    625:             }
1.1       barstow   626: 
                    627:             out.println("<input type=\"submit\" value=\"Submit problem report\">");
                    628:             out.println("</form>");
1.13      barstow   629:             out.println("<hr/>");
1.1       barstow   630:             out.println("</BODY>");
                    631:             out.println("</HTML>");
                    632: 
                    633:         } catch (Exception e) {
1.2       barstow   634:             System.err.println("Exception: " + e.getMessage());
1.1       barstow   635:         }
                    636: 
                    637:     }
                    638: 
1.3       barstow   639:     /*
1.16      barstow   640:      * Given a URI string, open it, read its contents into a String
                    641:      * and return the String
                    642:      *
                    643:      *@param uri the URI to open
                    644:      *@return the content at the URI or null if any error occurs
                    645:      */
                    646:     private String getByteStream (String uri) {
                    647:         try {
                    648:             URL url = new URL(uri);
                    649:             InputStream is = url.openStream();
                    650:             String s = new String("");
                    651: 
                    652:             int c;
                    653:             int numRead = 0;
                    654: 
                    655:             while ((c = is.read()) != -1) {
                    656:                 s += (char)c;
                    657:                 if (numRead == 15) {
                    658:                     // A server could return content but not the RDF/XML that
                    659:                     // we need.  Check the beginning of s and if it looks like
                    660:                     // a generic HTML message, return an error.
                    661:                     if (s.startsWith("<!DOCTYPE HTML"))
                    662:                         return null;
                    663:                 }
                    664:                 numRead++;
                    665:             }
                    666: 
                    667:             if (s.equals(""))
                    668:                 // Nothing was returned 
                    669:                 return null;
                    670: 
                    671:             return s;
                    672: 
                    673:         } catch (Exception e) {
                    674:             return null;
                    675:         }
                    676:     }
                    677: 
                    678:     /*
1.3       barstow   679:      * Servlet's get info method
                    680:      */
1.1       barstow   681:     public String getServletInfo () {
                    682:        return "Servlet Wrapper for SiRPAC. This is revision " + REVISION;
                    683:     }
                    684: 
1.3       barstow   685:     /*
                    686:      * Servlet's init method
                    687:      *
                    688:      *@param config the servlet's configuration object
                    689:      */
1.21    ! barstow   690:     public void init(ServletConfig config) throws ServletException 
        !           691:     {
1.1       barstow   692:        super.init (config);
                    693: 
1.3       barstow   694:         // Cache the parameters
                    695:         m_SiRPACTmpDir = config.getInitParameter(SIRPAC_TMP_DIR);
1.5       barstow   696: 
                    697:         // All of the Graph Viz paths extend from GRAPH_VIZ_ROOT
                    698:         String GraphVizRoot = config.getInitParameter(GRAPH_VIZ_ROOT);
                    699: 
                    700:         m_GraphVizPath = GraphVizRoot + "/" + config.getInitParameter(GRAPH_VIZ_PATH);
                    701:         m_GraphVizFontDir = GraphVizRoot + "/" + config.getInitParameter(GRAPH_VIZ_FONT_DIR);
                    702:         m_GraphVizLibDir = GraphVizRoot + "/" + config.getInitParameter(GRAPH_VIZ_LIB_DIR);
1.21    ! barstow   703: 
        !           704:         if (m_SiRPACTmpDir == null || GraphVizRoot == null) {
        !           705:            System.err.println (
        !           706:                 "<html>" +
        !           707:                 "<h1>Servlet Initialization Error</h1>" +
        !           708:                 "<h2>One or more of the following parameters has not been initialized: " + 
        !           709:                 SIRPAC_TMP_DIR + "," + GRAPH_VIZ_ROOT + "," +
        !           710:                 GRAPH_VIZ_FONT_DIR + "," + GRAPH_VIZ_LIB_DIR + "," +
        !           711:                 GRAPH_VIZ_PATH + "." + 
        !           712:                 "</h2></h1>" +
        !           713:                 "</html>");
        !           714:         }
1.1       barstow   715:     }
                    716: 
1.3       barstow   717:     /*
                    718:      * Servlet's destroy info method
                    719:      */
1.1       barstow   720:     public void destroy () {
                    721:        super.destroy ();
                    722:     }
                    723: 
1.3       barstow   724:     /*
1.4       barstow   725:      * Servlet's doGet info method - NOT supported
1.3       barstow   726:      *
                    727:      *@param req the request
                    728:      *@param res the response
                    729:      */
1.1       barstow   730:     public void doGet (HttpServletRequest req, HttpServletResponse res)
                    731:         throws ServletException, IOException {
1.3       barstow   732: 
1.1       barstow   733:        ServletOutputStream out = res.getOutputStream ();
                    734: 
                    735:        res.setContentType ("text/html");
                    736: 
1.3       barstow   737:        out.println ("<h1>GET is NOT supported!</h1>\n\n<p>Please send RDF through POST!</p>\n");
1.1       barstow   738:     }
                    739: 
1.3       barstow   740:     /*
                    741:      * Servlet's doPost method
                    742:      *
                    743:      *@param req the request
                    744:      *@param res the response
                    745:      */
1.1       barstow   746:     public void doPost (HttpServletRequest req, HttpServletResponse res)
                    747:         throws ServletException, IOException {
                    748: 
                    749:        ServletOutputStream out = res.getOutputStream ();
                    750: 
1.19      barstow   751:        String    sRDF         = req.getParameter (TEXT);
                    752:        String    sBags        = req.getParameter (BAG);
                    753:        String    sStreamMode  = req.getParameter (STREAM_MODE);
                    754:        String    sSaveRDF     = req.getParameter (SAVE_RDF);
                    755:        String    sSaveDOTFile = req.getParameter (SAVE_DOT_FILE);
                    756:        String    sURI         = req.getParameter (URI);
                    757:        String    sFormat      = req.getParameter (FORMAT);
1.21    ! barstow   758:        String    sNTriples    = req.getParameter (NTRIPLES);
1.16      barstow   759: 
1.18      barstow   760:        SiRPAC        sirpac = new SiRPAC();
                    761:         ErrorStore    errorHandler = new ErrorStore();
1.16      barstow   762:        InputSource   is = null;
                    763:         boolean       error = false;
                    764:         String        sError = null;
1.21    ! barstow   765:         boolean       nTriples = false;
1.16      barstow   766: 
1.21    ! barstow   767:         SiRPACServletDumpConsumer consumer = new SiRPACServletDumpConsumer();
        !           768:         if (sNTriples != null && sNTriples.equals("on")) {
        !           769:             nTriples = true;
        !           770:             consumer.setNTriplesOutput(true);
        !           771:         }
1.9       barstow   772: 
1.18      barstow   773:         // Initialize the parser
                    774:         sirpac.setErrorHandler(errorHandler);
1.1       barstow   775: 
1.16      barstow   776:         // If a URI was sent in the request, it takes precedence
                    777:         if (sURI != null && sURI.length() >= 1) {
                    778:             try {
                    779:                is  = GenericParser.getInputSource(sURI);
                    780:                 sRDF = getByteStream(sURI);
                    781:                 if (sRDF == null)
                    782:                     sError = "An attempt to load the RDF from URI '" + sURI + "' failed.  (The file may not exist or the server is down.)";
1.18      barstow   783:                 sirpac.setSource(sURI);
1.16      barstow   784:             } catch (MalformedURLException e) {
                    785:                 sError = "An attempt to load URI '" + sURI
                    786:                          + "' produced a MalforedURL Exception.\n["
                    787:                          + e.getMessage() + "]";
                    788:             } catch (IOException e) {
                    789:                 sError = "An attempt to load URI '" + sURI
                    790:                          + "' produced an IO Exception.\n["
                    791:                          + e.getMessage() + "]";
                    792:             }
                    793:         } else {
                    794:            StringReader  sr = new StringReader (sRDF);
                    795:            is = new InputSource (sr);
1.18      barstow   796:             sirpac.setSource("online:#");
1.16      barstow   797:         }
                    798: 
                    799:         if (sError != null) {
                    800:             printDocumentHeader (out);
                    801:            out.println ("<h1>" + sError + "</h1>\n");
                    802:             printDocumentFooter(out, null);
                    803:             return;
                    804:         }
                    805: 
1.1       barstow   806:         printDocumentHeader (out);
1.16      barstow   807:         printListing (out, sRDF, sURI != null && sURI.length() >= 1);
1.21    ! barstow   808:         printTripleTableHeader (out, nTriples);
1.1       barstow   809: 
                    810:        try {
1.3       barstow   811:             // Override the default triple output handler
1.1       barstow   812:             consumer.setOutputStream(out);
                    813: 
1.18      barstow   814:             // Create a bag per Description element? [off by default]
1.1       barstow   815:            if (sBags != null && sBags.equals ("on"))
1.18      barstow   816:                sirpac.createBags (true);
1.10      barstow   817: 
1.18      barstow   818:             // Set parser's streaming mode [on by default]
1.11      barstow   819:            if (sStreamMode != null && sStreamMode.equals ("on"))
1.18      barstow   820:                sirpac.setStreamMode (false);
1.1       barstow   821: 
1.18      barstow   822:             sirpac.parse(is, consumer);
1.1       barstow   823: 
1.21    ! barstow   824:             printTripleTableFooter(out, consumer, nTriples);
1.12      barstow   825: 
1.19      barstow   826:             if (sFormat != null && !sFormat.equals(FORMAT_NO_GRAPH)) {
                    827:                 generateGraph(out, 
                    828:                     sRDF, 
                    829:                     req, 
                    830:                     sirpac.source(),
                    831:                     sFormat,
                    832:                     (sSaveRDF != null) ? true : false,
                    833:                     (sSaveDOTFile != null && sSaveDOTFile.equals ("on") ? true : false),
                    834:                     (sBags != null && sBags.equals ("on") ? true : false),
                    835:                     (sStreamMode != null && sStreamMode.equals ("on") ? false : true));
                    836:             }
1.2       barstow   837: 
1.1       barstow   838:        } catch (SAXException e) {
1.3       barstow   839:             error = true;
1.1       barstow   840:        } catch (Exception e) {
1.3       barstow   841:             error = true;
1.1       barstow   842:            e.printStackTrace ();
                    843:        }
                    844: 
                    845:        res.setContentType ("text/html");
1.3       barstow   846: 
                    847:        if (error) {
1.21    ! barstow   848:             printTripleTableFooter(out, null, nTriples);
1.1       barstow   849:            out.println ("<h1>Errors during parsing</h1>\n");
                    850:             out.println ("<pre>\n");
1.2       barstow   851: 
                    852:             // Make the line number a link to the listing
1.18      barstow   853:             out.println ("Fatal error: " + errorHandler.getErrorMessage());
1.1       barstow   854:             out.println ("   (Line number = " + "<a href=\"#" + 
1.18      barstow   855:                          errorHandler.getLineNumber() + "\">" + 
                    856:                          errorHandler.getLineNumber() + "</a>" +
1.1       barstow   857:                          ", Column number = " + 
1.18      barstow   858:                          errorHandler.getColumnNumber() + ")");
1.1       barstow   859: 
                    860:            out.println ("</pre>\n\n");
                    861:        }
                    862: 
                    863:         printDocumentFooter(out, sRDF);
                    864:     }
                    865: }

Webmaster