Annotation of java/classes/org/w3c/rdf/examples/ARPServlet.java, revision 1.19

1.16      barstow     1: /***********************************************************************
                      2:  *
                      3:  * ARPServlet - this servlet implements an RDF Validation service.  As
                      4:  *  of this writing, the following RDF validation service used this
                      5:  *  servlet:
                      6:  *
                      7:  *   http://www.w3.org/RDF/Validator/
                      8:  *
                      9:  ***********************************************************************
1.1       barstow    10:  *
                     11:  * Copyright © World Wide Web Consortium, (Massachusetts Institute of
                     12:  * Technology, Institut National de Recherche en Informatique et en
                     13:  * Automatique, Keio University).
                     14:  *
                     15:  * All Rights Reserved.
                     16:  *
                     17:  * Please see the full Copyright clause at
                     18:  * <http://www.w3.org/Consortium/Legal/copyright-software.html>
                     19:  *
1.16      barstow    20:  ***********************************************************************
                     21:  *
                     22:  * This servlet is a wrapper for the ARP RDF parser.  See the following
                     23:  * for information about the ARP RDF parser:
                     24:  *
                     25:  *  http://www.hpl.hp.co.uk/people/jjc/arp/
                     26:  *
                     27:  ***********************************************************************
                     28:  *
                     29:  * Implementation notes:
                     30:  *
                     31:  * o This servlet supports the HTTP POST operation; it does not 
                     32:  *  support the HTTP GET operation
                     33:  *
                     34:  * o Depending upon the parameters given to the servlet it may 
                     35:  *  invoke a GraphViz suprocess to generate a graph of the RDF.  
                     36:  *  See the following for more information about GraphViz:
1.1       barstow    37:  *
1.16      barstow    38:  *   http://www.research.att.com/sw/tools/graphviz/
1.1       barstow    39:  *
1.16      barstow    40:  *  The servlet assumes version 1.7.4 of GraphViz.
1.1       barstow    41:  *
1.16      barstow    42:  * o Depending upon the parameters given to the servlet, the RDF
                     43:  *  to be validated may be copied to a file.  The name of the file
                     44:  *  is automatically generated via Java's temporary file APIs.  The
                     45:  *  location of the directory where the file is stored is configured
                     46:  *  via the serverlet's init() method.  See below for more information.
                     47:  *
                     48:  * o See the section on Server Initialization for more information.
                     49:  *
                     50:  ***********************************************************************
                     51:  *
                     52:  * HTTP POST parameters - the servlet expects/assumes the following 
                     53:  *  variables are defined via the HTTP POST request:
                     54:  *
                     55:  * RDF - the RDF (assumed to be in RDF/XML syntax) to be validated
                     56:  *
                     57:  * SAVE_DOT_FILE - if "on", the GraphViz DOT file is saved and a 
                     58:  *   link to the file is returned; otherwise the DOT file is not saved
                     59:  *
                     60:  * SAVE_RDF - if "on", the RDF will be copied to a file; otherwise
                     61:  *   the RDF is not copied to a file
1.1       barstow    62:  *
1.10      barstow    63:  * EMBEDDED_RDF - if "on", then the RDF is not enclosed in <RDF>...</RDF>
1.16      barstow    64:  *   tags; otherwise it assumed that the is enclosed in these tags.
1.10      barstow    65:  *
1.16      barstow    66:  * URI - the URI of the RDF to validate; this parameter may not be 
                     67:  *   specified; if this parameter and the RDF parameter are both 
                     68:  *   specified, this parameter takes precedence
1.1       barstow    69:  *
                     70:  * ORIENTATION - the graph's orientation (left to right or top to
1.16      barstow    71:  *   bottom); default is left to right
1.1       barstow    72:  *
1.16      barstow    73:  * FONT_SIZE - the font size to use (10, 12, 14, 16 and 20 are 
                     74:  *   supported); the default is 10
1.1       barstow    75:  *
1.16      barstow    76:  * ANON_NODES_EMPTY - if "on", anonymous nodes are not labeled; otherwise
                     77:  *   anonymous nodes are labeled;
1.12      barstow    78:  *
                     79:  * TRIPLES_AND_GRAPH - support values are:
                     80:  *
1.16      barstow    81:  *     PRINT_BOTH - display triples and a graph (the default)
                     82:  *     PRINT_TRIPLES - only display the triples
                     83:  *     PRINT_GRAPH - only display the graph
1.12      barstow    84:  *
1.1       barstow    85:  * GRAPH_FORMAT - the graph's output format.  Supported values are:
                     86:  *
1.16      barstow    87:  *     GIF_EMBED - embed the graph as a GIF (the default)
1.1       barstow    88:  *     GIF_LINK - don't embed the GIF but create a link for it
                     89:  *     SVG_LINK - create the graph in SVG format and create a link to the file
                     90:  *     PNG_EMBED - create the graph in PNG format and embed the graph in the 
                     91:  *       document that is returned
                     92:  *     PNG_LINK - create the graph in PNG format and create a link to the file
                     93:  *     PS_LINK - create a PostScript image of the file and a link to the file
                     94:  *     HP_PCL_LINK - create a HPGL/2 - PCL (Laserwriter) image of the file 
                     95:  *       and a link to the file
                     96:  *     HP_GL_LINK - create a HPGL - PCL (pen plotter) image of the file and 
                     97:  *       a link to the file
                     98:  *
                     99:  * NTRIPLES if "on" the tabular output will be in the NTriples format;
                    100:  *  otherwise a table of Subject, Predicate, Objects will be generated
                    101:  *
1.16      barstow   102:  ***********************************************************************
                    103:  *
                    104:  * Server Initialization - this servlet requires the following 
                    105:  *  parameters be set in the servlet's init() method - via the
                    106:  *  ServletConfig object:
1.1       barstow   107:  *
1.16      barstow   108:  * GRAPH_VIZ_ROOT - the absolute path of the top-level directory containing
                    109:  *   GraphViz's binary distribution
                    110:  *
                    111:  * GRAPH_VIZ_PATH - the relative path (based on GRAPH_VIZ_ROOT) of
                    112:  *   the DOT executable (e.g. dotneato/dot) - the program used to generate
                    113:  *   a graph from a DOT file.
                    114:  *
                    115:  * GRAPH_VIZ_FONT_DIR - the relative path (based on GRAPH_VIZ_ROOT) of
                    116:  *   the fonts directory used by GraphViz (e.g. Fonts)
                    117:  *
                    118:  * SERVLET_TMP_DIR - the absolute path of the directory to be used to
                    119:  *   store temporary files used by the servlet and GraphViz.  This 
                    120:  *   directory must be writable by the servlet.  
                    121:  *
                    122:  *   NOTE - Some files created by the servlet are not removed by 
                    123:  *     servlet (e.g. graph image files).
                    124:  *
                    125:  * If any of these parameters are not defined, the servlet will NOT 
                    126:  * validate the RDF.
                    127:  *
                    128:  ***********************************************************************
                    129:  *
                    130:  * Dependencies - this servlet requires the following Java packages
                    131:  *   as well as GraphViz (described above):
                    132:  *
                    133:  * ARP RDF parser: http://www.hpl.hp.co.uk/people/jjc/arp/download.html
                    134:  *
                    135:  * SAX-based XML parser: e.g. Xerces at http://xml.apache.org/
                    136:  *
                    137:  * Java servlet package: http://java.sun.com/products/servlet/archive.html
                    138:  *
                    139:  * Apache Regular Expression: http://jakarta.apache.org/builds/jakarta-regexp/release/v1.2/
                    140:  *
                    141:  ***********************************************************************
                    142:  *
                    143:  * Author: Art Barstow <barstow@w3.org>
                    144:  *
1.19    ! duerst    145:  * $Id: ARPServlet.java,v 1.18 2002/07/17 08:11:28 duerst Exp $
1.16      barstow   146:  *
                    147:  ***********************************************************************/
1.1       barstow   148: 
1.16      barstow   149: // http://dev.w3.org/cvsweb/java/classes/org/w3c/rdf/examples/
                    150: package org.w3c.rdf.examples; 
1.1       barstow   151: 
                    152: import java.io.*;
                    153: import java.net.MalformedURLException;
                    154: import java.net.URL;
                    155: import java.util.StringTokenizer;
                    156: import java.util.Enumeration;
1.14      barstow   157: import java.util.Hashtable;
1.16      barstow   158: 
                    159: // http://java.sun.com/products/servlet/2.2/javadoc/javax/servlet/package-summary.html
                    160: import javax.servlet.*;         
1.1       barstow   161: import javax.servlet.http.*;
                    162: 
1.16      barstow   163: // http://xml.apache.org/apiDocs/org/xml/sax/package-summary.html
                    164: import org.xml.sax.InputSource;        
1.1       barstow   165: import org.xml.sax.Parser;
                    166: import org.xml.sax.SAXException;
                    167: import org.xml.sax.SAXParseException;
                    168: import org.xml.sax.ErrorHandler;
                    169: import org.xml.sax.helpers.*;
                    170: 
1.16      barstow   171: // http://jakarta.apache.org/regexp/apidocs/org/apache/regexp/RE.html
1.3       barstow   172: import org.apache.regexp.RE;
                    173: 
1.16      barstow   174: // http://www.hpl.hp.co.uk/people/jjc/arp/apidocs/index.html
                    175: import com.hp.hpl.jena.rdf.arp.*; 
1.1       barstow   176: 
                    177: public class ARPServlet extends HttpServlet
                    178: {
1.19    ! duerst    179:     final static public String REVISION = "$Id: ARPServlet.java,v 1.18 2002/07/17 08:11:28 duerst Exp $";
1.1       barstow   180: 
                    181:     // The email address for bug reports
1.6       barstow   182:     private static final String MAIL_TO = "www-rdf-validator@w3.org";
1.1       barstow   183: 
                    184:     // Names of the POST parameters (described above) and their
1.12      barstow   185:     // defaults (if applicable)
                    186:     private static final String TEXT              = "RDF";
                    187:     private static final String SAVE_DOT_FILE     = "SAVE_DOT_FILE";
                    188:     private static final String SAVE_RDF          = "SAVE_RDF";
                    189:     private static final String EMBEDDED_RDF      = "EMBEDDED_RDF";
                    190:     private static final String URI               = "URI";
                    191:     private static final String NTRIPLES          = "NTRIPLES";
                    192:     private static final String ANON_NODES_EMPTY  = "ANON_NODES_EMPTY";
1.1       barstow   193:  
                    194:     private static final String NODE_COLOR         = "NODE_COLOR";
                    195:     private static final String DEFAULT_NODE_COLOR = "black";
                    196: 
                    197:     private static final String NODE_TEXT_COLOR         = "NODE_TEXT_COLOR";
                    198:     private static final String DEFAULT_NODE_TEXT_COLOR = "black";
                    199: 
                    200:     private static final String EDGE_COLOR         = "EDGE_COLOR";
                    201:     private static final String DEFAULT_EDGE_COLOR = "black";
                    202: 
                    203:     private static final String EDGE_TEXT_COLOR         = "EDGE_TEXT_COLOR";
                    204:     private static final String DEFAULT_EDGE_TEXT_COLOR = "black";
                    205: 
                    206:     private static final String ORIENTATION         = "ORIENTATION";
                    207:     private static final String DEFAULT_ORIENTATION = "TB";  // Top to Bottom
                    208: 
                    209:     private static final String FONT_SIZE         = "FONT_SIZE";
                    210:     private static final String DEFAULT_FONT_SIZE = "10";
                    211: 
1.12      barstow   212:     // Print graph and/or triples
                    213:     private static final String TRIPLES_AND_GRAPH = "TRIPLES_AND_GRAPH";
                    214:     private static final String PRINT_BOTH        = "PRINT_BOTH";
                    215:     private static final String PRINT_TRIPLES     = "PRINT_TRIPLES";
                    216:     private static final String PRINT_GRAPH       = "PRINT_GRAPH";
                    217: 
                    218:     // Graph formats
1.1       barstow   219:     private static final String FORMAT              = "FORMAT";
                    220:     private static final String FORMAT_GIF_EMBED    = "GIF_EMBED";
                    221:     private static final String FORMAT_GIF_LINK     = "GIF_LINK";
                    222:     private static final String FORMAT_SVG_LINK     = "SVG_LINK";
                    223:     private static final String FORMAT_PNG_EMBED    = "PNG_EMBED";
                    224:     private static final String FORMAT_PNG_LINK     = "PNG_LINK";
                    225:     private static final String FORMAT_PS_LINK      = "PS_LINK";
                    226:     private static final String FORMAT_HP_PCL_LINK  = "HP_PCL_LINK";
                    227:     private static final String FORMAT_HP_GL_LINK   = "HP_GL_LINK";
                    228: 
                    229:     // Fonts are not currently configurable
                    230:     private static final String DEFAULT_FONT = "arial";
                    231: 
                    232:     // Names of the servlet's parameters - for Jigsaw web server
                    233:     private static final String SERVLET_TMP_DIR    = "SERVLET_TMP_DIR";
                    234:     private static final String GRAPH_VIZ_ROOT     = "GRAPH_VIZ_ROOT";
                    235:     private static final String GRAPH_VIZ_PATH     = "GRAPH_VIZ_PATH";
                    236:     private static final String GRAPH_VIZ_FONT_DIR = "GRAPH_VIZ_FONT_DIR";
                    237: 
                    238:     // Variables for the servlet's parameters
                    239:     private static String m_ServletTmpDir   = null;
                    240:     private static String m_GraphVizPath    = null;
                    241:     private static String m_GraphVizFontDir = null;
                    242: 
                    243:     // Names of environment variable need by GraphVis
                    244:     private static String DOTFONTPATH     = "DOTFONTPATH";
                    245:     private static String LD_LIBRARY_PATH = "LD_LIBRARY_PATH";
                    246: 
                    247:     // Names used for temporary files
                    248:     private static final String TMP_FILE_PREFIX = "servlet_";
                    249:     private static final String SUFFIX_TMP_DIR  = ".tmp";
                    250:     private static final String SUFFIX_DOT      = ".dot";
                    251:     private static final String SUFFIX_RDF      = ".rdf";
                    252: 
                    253:     // Names used for file suffixes and for GraphViz's command line
                    254:     // option
                    255:     private static final String NAME_GIF      = "gif";
                    256:     private static final String NAME_HPGL     = "hpgl";
                    257:     private static final String NAME_PCL      = "pcl";
                    258:     private static final String NAME_PNG      = "png";
                    259:     private static final String NAME_PS       = "ps";
                    260:     private static final String NAME_SVG      = "svg";
                    261: 
                    262:     // Default GraphViz parameter names and their default values
                    263:     // Servlet name
                    264:     private static final String SERVLET_NAME = "ARPServlet";
                    265: 
                    266:     // Name for the DOT file title
                    267:     private static final String DOT_TITLE = "dotfile";
                    268: 
1.14      barstow   269:     // The string to use for to prefix anonymous nodes.
                    270:     private static final String ANON_NODE = "genid:";
                    271: 
1.1       barstow   272:     // The string to use for a namespace name when no
                    273:     // namespace is available - e.g. for the RDF that is
                    274:     // directly entered into the input form.
1.14      barstow   275:     private static final String DEFAULT_NAMESPACE = "online:";
1.1       barstow   276: 
                    277:     /*
1.14      barstow   278:      * Create a File object from the given directory and file names
1.1       barstow   279:      *
                    280:      *@param directory the file's directory
                    281:      *@param prefix the file's prefix name (not its directory)
                    282:      *@param suffix the file's suffix or extension name
                    283:      *@return a File object if a temporary file is created; null otherwise
                    284:      */
1.4       barstow   285:     private File createTempFile (String directory, String prefix, String suffix) 
                    286:     {
1.1       barstow   287:         File f;
                    288:         try {
                    289:             File d = new File(directory);
                    290:             f = File.createTempFile(prefix, suffix, d);
                    291:         } catch (Exception e) {
                    292:             return null;
                    293:         }
                    294:         return f;
                    295:     }
                    296: 
                    297:     /*
                    298:      * Given a URI string, open it, read its contents into a String
                    299:      * and return the String
                    300:      *
                    301:      *@param uri the URI to open
                    302:      *@return the content at the URI or null if any error occurs
                    303:      */
1.4       barstow   304:     private String getByteStream (String uri) 
                    305:     {
1.1       barstow   306:         try {
                    307:             URL url = new URL(uri);
                    308:             InputStream is = url.openStream();
                    309:             String s = new String("");
                    310: 
                    311:             int c;
                    312:             int numRead = 0;
                    313: 
                    314:             while ((c = is.read()) != -1) {
                    315:                 s += (char)c;
                    316:                 if (numRead == 15) {
                    317:                     // A server could return content but not the RDF/XML that
                    318:                     // we need.  Check the beginning of s and if it looks like
                    319:                     // a generic HTML message, return an error.
                    320:                     if (s.startsWith("<!DOCTYPE"))
                    321:                         return null;
                    322:                 }
                    323:                 numRead++;
                    324:             }
                    325: 
                    326:             if (s.equals(""))
                    327:                 // Nothing was returned 
                    328:                 return null;
                    329: 
                    330:             return s;
                    331: 
                    332:         } catch (Exception e) {
                    333:             return null;
                    334:         }
                    335:     }
                    336: 
                    337:     /*
1.4       barstow   338:      * Copy the given string of RDF to a file in the given directory.
                    339:      * This is only done if the servlet is explictly asked to save
                    340:      * the RDF to a file.
1.1       barstow   341:      *
1.14      barstow   342:      *@param tmpDir the file's directory
1.1       barstow   343:      *@param rdf the string of RDF
                    344:      */
                    345:     private void copyRDFStringToFile(String tmpDir, String rdf) 
                    346:     {
                    347:         try {
                    348:             // Generate a unique file name 
                    349:             File tmpFile = createTempFile(tmpDir, TMP_FILE_PREFIX, SUFFIX_RDF);
                    350:             if (tmpFile == null) {
                    351:                 // Not really a critical error, just return
                    352:                 return;
                    353:             }
                    354: 
                    355:             // Create a PrintWriter for the GraphViz consumer
                    356:             FileWriter fw = new FileWriter(tmpFile);
                    357:             PrintWriter pw = new PrintWriter(fw);
                    358: 
                    359:             pw.println(rdf);
                    360:             pw.close();
                    361:         } catch (Exception e) {
1.4       barstow   362:             System.err.println(SERVLET_NAME + ": error occured trying to save RDF to file '" + tmpDir + TMP_FILE_PREFIX + SUFFIX_RDF + "'.");
1.1       barstow   363:             return;
                    364:         }
                    365:     }
                    366: 
                    367:     /*
                    368:      * Given the graph's format option, return either the corresponding
                    369:      * command line option for that option or the file name suffix for
                    370:      * the graph option.  For example GIF files have ".gif" for its
                    371:      * suffix and GraphViz uses "-Tgif" for the command line.
                    372:      *
                    373:      * NOTE: default is GIF.
                    374:      *
                    375:      *@param graphFormat the graph's output format
                    376:      *@param suffix.  If true, the name returned is for the graph's
                    377:      * file name suffix; otherwise, the name returned is for the
                    378:      * graph's command line option.
                    379:      *@return the suffix to use for the graph's output file
                    380:      */
                    381:     private String getFormatName(String graphFormat, boolean suffix) {
                    382: 
                    383:         String name = (suffix) ? "." : "-T";
                    384: 
1.4       barstow   385:         if (graphFormat.equals(FORMAT_PNG_EMBED))   return name + NAME_PNG;
                    386:         if (graphFormat.equals(FORMAT_PNG_LINK))    return name + NAME_PNG;
                    387:         if (graphFormat.equals(FORMAT_SVG_LINK))    return name + NAME_SVG;
                    388:         if (graphFormat.equals(FORMAT_PS_LINK))     return name + NAME_PS;
                    389:         if (graphFormat.equals(FORMAT_HP_GL_LINK))  return name + NAME_HPGL;
1.1       barstow   390:         if (graphFormat.equals(FORMAT_HP_PCL_LINK)) return name + NAME_PCL;
                    391:         
                    392:         return name + NAME_GIF;
                    393:     }
                    394: 
                    395:     /*
                    396:      * Invokes the GraphVis program to create a graph image from the
                    397:      * the given DOT data file
                    398:      *
                    399:      *@param dotFileName the name of the DOT data file
                    400:      *@param outputFileName the name of the output data file 
1.14      barstow   401:      *@param graphFormat the graph's format
1.1       barstow   402:      *@return true if success; false if any failure occurs
                    403:      */
1.8       barstow   404:     private boolean generateGraphFile(String dotFileName, 
1.4       barstow   405:        String outputFileName, String graphFormat) 
                    406:     {
1.16      barstow   407:         String environment[] = {DOTFONTPATH + "=" + m_GraphVizFontDir};
1.1       barstow   408: 
                    409:         String formatOption = getFormatName(graphFormat, false);
                    410: 
                    411:         String cmdArray[] = {m_GraphVizPath, formatOption, "-o", outputFileName, dotFileName};
                    412:         Runtime rt = Runtime.getRuntime();
                    413:         try {
                    414:             Process p = rt.exec(cmdArray, environment);
                    415:             p.waitFor();
1.10      barstow   416: 
1.1       barstow   417:         } catch (Exception e) {
                    418:             System.err.println("Error: generating OutputFile.");
                    419:             return false;
                    420:         }
                    421:         return true;
                    422:     }
                    423: 
                    424:     /*
                    425:      * Returns a parameter from a request or the parameter's default
                    426:      * value.
                    427:      *
                    428:      *@param req a Servlet request
1.14      barstow   429:      *@param param the name of the parameter
                    430:      *@param defString the string returned if the param is not found
1.1       barstow   431:      *@return if the request contains the specfied parameter its value
                    432:      *  in the request is returned; otherwise its default value is
                    433:      *  returned
                    434:      */
                    435:     private String getParameter(HttpServletRequest req, String param, 
                    436:         String defString) 
                    437:     {
                    438:         String s = req.getParameter(param);
                    439:         return (s == null) ? defString : s;
                    440:     }
                    441: 
                    442:     /*
                    443:      * If the request contains any graph-related parameters, pass them
                    444:      * to the graph consumer for handling
                    445:      *
                    446:      *@param req the response
1.14      barstow   447:      *@param pw the PrintWriter
1.1       barstow   448:      *@param consumer the GraphViz consumer
                    449:      */
1.14      barstow   450:     private void processGraphParameters (HttpServletRequest req, PrintWriter pw)
1.1       barstow   451:     {
1.4       barstow   452:        // Print the graph header
                    453:         pw.println("digraph " + DOT_TITLE + "{ " );
1.1       barstow   454: 
                    455:         // Look for colors
1.4       barstow   456:         String nodeColor     = getParameter(req, NODE_COLOR, 
                    457:                                            DEFAULT_NODE_COLOR);
                    458:         String nodeTextColor = getParameter(req, NODE_TEXT_COLOR, 
                    459:                                            DEFAULT_NODE_TEXT_COLOR);
                    460:         String edgeColor     = getParameter(req, EDGE_COLOR, 
                    461:                                            DEFAULT_EDGE_COLOR);
                    462:         String edgeTextColor = getParameter(req, EDGE_TEXT_COLOR, 
                    463:                                            DEFAULT_EDGE_TEXT_COLOR);
                    464:         String fontSize      = getParameter(req, FONT_SIZE, 
                    465:                                            DEFAULT_FONT_SIZE);
1.1       barstow   466: 
                    467:         // Orientation must be either 
                    468:         String orientation = req.getParameter (ORIENTATION);
                    469:         if (orientation.equals("LR"))
                    470:             orientation = "LR";
                    471:         else
                    472:             orientation = DEFAULT_ORIENTATION;
                    473: 
                    474:         // Add an attribute for all of the graph's nodes
                    475:         pw.println("node [fontname=" + DEFAULT_FONT + 
1.7       barstow   476:                    ",fontsize="  + fontSize +
                    477:                    ",color="     + nodeColor +
1.12      barstow   478:                    ",fontcolor=" + nodeTextColor + "];");
1.1       barstow   479: 
                    480:         // Add an attribute for all of the graph's edges
                    481:         pw.println("edge [fontname=" + DEFAULT_FONT + 
1.8       barstow   482:                    ",fontsize="  + fontSize +
                    483:                    ",color="     + edgeColor +
                    484:                    ",fontcolor=" + edgeTextColor + "];");
1.1       barstow   485: 
                    486:         // Add an attribute for the orientation
                    487:         pw.println("rankdir=" + orientation + ";");
                    488:     }
                    489: 
                    490:     private static class SaxErrorHandler implements org.xml.sax.ErrorHandler
                    491:     { 
                    492:         ServletOutputStream out;
                    493:         boolean silent = false;
1.5       barstow   494:        String fatalErrors = "";
                    495:        String errors = "";
                    496:        String warnings = "";
1.1       barstow   497: 
                    498:         /*
                    499:          * Constructuor for a SaxErrorHandler 
                    500:          *
                    501:         *@param out the servlet's output stream
                    502:         *@param silent if false, output is suprressed
                    503:          */
                    504:         public SaxErrorHandler(ServletOutputStream out, boolean silent) 
                    505:         {
                    506:             this.out = out;
                    507:             this.silent = silent;
                    508:         }
                    509: 
                    510:         /*
                    511:          * Create a formatted string from the exception's message
                    512:          *
1.5       barstow   513:         *@param e the SAX Parse Exception
1.1       barstow   514:         *@return a formatted string
                    515:          */
                    516:         private static String format(org.xml.sax.SAXParseException e) 
                    517:         {
                    518:             String msg = e.getMessage();
                    519:             if (msg == null)
                    520:                 msg = e.toString();
                    521:             return msg + "[Line = " + e.getLineNumber() + ", Column = " + e.getColumnNumber() + "]";
                    522:         }
                    523: 
                    524:         /*
                    525:          * Handle a parse error
                    526:          *
1.5       barstow   527:         *@param e the SAX Parse Exception
1.1       barstow   528:         */
                    529:         public void error(org.xml.sax.SAXParseException e) 
                    530:             throws org.xml.sax.SAXException 
                    531:         {
                    532:             if (this.silent) return;
                    533: 
1.5       barstow   534:            this.errors += "Error: " + format(e) + "<br />";
1.1       barstow   535:         }
                    536:     
                    537:         /*
                    538:          * Handle a fatal parse error
                    539:          *
1.5       barstow   540:         *@param e the SAX Parse Exception
1.1       barstow   541:         */
                    542:         public void fatalError(org.xml.sax.SAXParseException e) 
                    543:             throws org.xml.sax.SAXException 
                    544:         {
                    545:             if (this.silent) return;
                    546: 
1.5       barstow   547:            this.fatalErrors += "FatalError: " + format(e) + "<br />";
1.1       barstow   548:         }
                    549:     
                    550:         /*
                    551:          * Handle a parse warning
                    552:          *
1.5       barstow   553:         *@param e the SAX Parse Exception
1.1       barstow   554:         */
                    555:         public void warning(org.xml.sax.SAXParseException e) 
                    556:             throws org.xml.sax.SAXException 
                    557:         {
                    558:             if (this.silent) return;
                    559: 
1.5       barstow   560:            this.warnings += "Warning: " + format(e) + "<br />";
1.1       barstow   561:         }
1.5       barstow   562: 
                    563:         /*
                    564:          * Return the error messages
                    565:          *
                    566:         *@return the error messages or an empty string if there are
                    567:         * no messages
                    568:         */
                    569:        public String getErrors()
                    570:        {
                    571:           return this.errors;
                    572:        }
                    573: 
                    574:         /*
                    575:          * Return the fatal error messages
                    576:          *
                    577:         *@return the fatal error messages or an empty string if there are
                    578:         * no messages
                    579:         */
                    580:        public String getFatalErrors()
                    581:        {
                    582:           return this.fatalErrors;
                    583:        }
                    584: 
                    585:         /*
                    586:          * Return the warning messages
                    587:          *
                    588:         *@return the warning messages or an empty string if there are
                    589:         * no messages
                    590:         */
                    591:        public String getWarnings()
                    592:        {
                    593:           return this.warnings;
                    594:        }
1.1       barstow   595:     } 
                    596: 
                    597:     /*
                    598:      * Generate a graph of the RDF data model
                    599:      *
                    600:      *@param out the servlet's output stream
1.4       barstow   601:      *@param pw the graph file's PrintWriter
                    602:      *@param dotFile the File handle for the graph file
1.1       barstow   603:      *@param rdf the RDF text
                    604:      *@param req a Servlet request
                    605:      *@param graphFormat the graph's format
                    606:      *@param saveRDF the RDF can be cached [saved to the file system]
                    607:      *@param saveDOTFile the DOT file should be cached
                    608:      */
1.8       barstow   609:     private void generateGraph(ServletOutputStream out, PrintWriter pw,
1.4       barstow   610:        File dotFile, String rdf, HttpServletRequest req, String graphFormat, 
1.1       barstow   611:         boolean saveRDF, boolean saveDOTFile) 
                    612:     {
                    613:         try {
                    614:             out.println("<hr title=\"visualisation\">");
                    615:             out.println("<h3>Graph of the data model</h3>");
                    616: 
                    617:             // The temporary directory
                    618:             String tmpDir = m_ServletTmpDir;
                    619: 
                    620:             // Add the graph footer
                    621:             pw.println( " }");
                    622: 
1.4       barstow   623:             // Close the DOT input file so the GraphViz can
1.1       barstow   624:             // open and read it
                    625:             pw.close();
                    626: 
                    627:             // Generate a unique file name for the output file
                    628:             // that will be created
                    629:             String suffix = getFormatName(graphFormat, true);
                    630:             File outputFile = createTempFile(tmpDir, TMP_FILE_PREFIX, suffix);
                    631:             if (outputFile == null) {
                    632:                 out.println("Failed to create a temporary file for the graph. A graph cannot be generated.");
                    633:                 dotFile.delete();
                    634:                 return;
                    635:             }
                    636: 
                    637:             // Pass the DOT data file to the GraphViz dot program
                    638:             // so it can create a graph image of the data model
                    639:             String dotFileName = dotFile.getAbsolutePath();
                    640:             String outputFileName = outputFile.getAbsolutePath();
                    641: 
1.8       barstow   642:             if (!generateGraphFile(dotFileName, outputFileName, graphFormat)) {
1.1       barstow   643:                 out.println("An attempt to create a graph failed.");
                    644:                 dotFile.delete();
                    645:                 outputFile.delete();
                    646:                 return;
                    647:             }
                    648:             // Handle the DOT file
                    649:             if (saveDOTFile) {
                    650:                 // Make the DOT file link'able if so requested
                    651:                 String dotPath = SERVLET_NAME + SUFFIX_TMP_DIR + 
                    652:                                  File.separator + dotFile.getName();
                    653:                 out.println("<a href=\"" + dotPath + "\">Download the DOT file.</a><br /><br />");
                    654:             }
                    655:             else {
                    656:                 // Delete it ...
                    657:                 dotFile.delete();
                    658:             }
                    659: 
                    660:             // NOTE: Cannot delete the output file here because its
                    661:             // pathname is returned to the client
                    662:             String imagePath = SERVLET_NAME + SUFFIX_TMP_DIR + File.separator + 
                    663:                                outputFile.getName();
                    664: 
                    665:             // Handle the embedded image formats first
                    666:             if (graphFormat.equals(FORMAT_GIF_EMBED) ||
                    667:                 graphFormat.equals(FORMAT_PNG_EMBED)) {
                    668:                 if (outputFile.length() > 0)
                    669:                     out.println("<img src=\"" + imagePath + "\"/>");
                    670:                 else
                    671:                     out.println("The graph image file is empty.");
                    672:             } else {
                    673:                 if (outputFile.length() > 0)
                    674:                     out.println("<a href=\"" + imagePath + "\">Get/view the graph's image file (" + suffix + ").</a><br /><br />");
                    675:                 else
                    676:                     out.println("The graph image file is empty.");
                    677:             }
                    678: 
                    679:             // One last thing to do before exiting - copy the RDF to a file
                    680:             if (saveRDF)
                    681:                 copyRDFStringToFile(tmpDir, rdf);
                    682: 
                    683:         } catch (Exception e) {
                    684:             System.err.println("Exception generating graph: " + e.getMessage());
                    685:         }
                    686:     }
                    687: 
                    688:     /*
                    689:      * Search the given string for substring "key"
                    690:      * and if it is found, replace it with string "replacement"
                    691:      *
                    692:      *@param input the input string
                    693:      *@param key the string to search for
                    694:      *@param replacement the string to replace all occurences of "key"
1.3       barstow   695:      *@return if no substitutions are done, input is returned; otherwise
1.1       barstow   696:      * a new string is returned.
                    697:      */
                    698:     public static String replaceString(String input, String key, 
                    699:         String replacement) 
                    700:     {
1.3       barstow   701:         try {
                    702:             RE re = new RE(key);
                    703:             return re.subst(input, replacement);
                    704:         } catch (Exception e) {
                    705:             return input;
1.1       barstow   706:         }
                    707:     }
                    708: 
                    709:     /*
                    710:      * Print the document's header info
                    711:      *
                    712:      *@param out the servlet's output stream
                    713:      */
                    714:     private void printDocumentHeader (ServletOutputStream out) 
                    715:     {
                    716:         try {
                    717: 
1.6       barstow   718:             out.println( "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"" +
                    719:                 "      \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" +
                    720:                 "<html><head>" +
                    721:                 "<title>RDF Validator</title>" +
                    722:                 "<link href='http://www.w3.org/StyleSheets/base.css' rel='stylesheet' type='text/css'/>" +
                    723:                "<style type='text/css'>" +
                    724:                "  TD {" +
                    725:                "    background:#EEEEEE;" +
                    726:                "    font-family:'courier new',courier,serif;" +
                    727:                "  }" +
                    728:                "</style>" +
                    729:                 "</head>" +
                    730:                 "<body>");
1.1       barstow   731: 
                    732:         } catch (Exception e) {
1.8       barstow   733:             System.err.println("Exception (printDocumentHeader): " + e.getMessage());
1.1       barstow   734:         }
                    735:     }
                    736: 
                    737:     /*
                    738:      * Print the rdf listing
                    739:      *
                    740:      *@param out the servlet's output stream
                    741:      *@param rdf the RDF code
1.14      barstow   742:      *@param needCR if true, add a CarriageReturn to the output; if false,
                    743:      * do not add it
1.1       barstow   744:      */
                    745:     private void printListing (ServletOutputStream out, String rdf, 
                    746:         boolean needCR) 
                    747:     {
                    748:         try {
1.8       barstow   749:             out.println("<hr title=\"original source\">" +
                    750:                         "<h3>The original RDF/XML document</h3>" +
                    751:                         "<pre>");
1.1       barstow   752: 
                    753:             String s = replaceString(rdf, "<", "&lt;");
                    754:             
                    755:             // Now output the RDF one line at a time with line numbers
                    756:             int lineNum = 1;
                    757:             int nl = 0;
                    758:             String terminator = needCR?"\n":"";
                    759:             do {
                    760:                 String tok;
                    761:                 nl = s.indexOf('\n');
                    762:                 if ( nl == -1 ) {
                    763:                     tok = s;
                    764:                 } else {
                    765:                     tok = s.substring(0,nl);
                    766:                     s = s.substring(nl+1);
                    767:                 }
1.8       barstow   768:                 out.print("<a name=\"" + lineNum + "\">" + lineNum +
                    769:                           "</a>: " + tok + terminator);
1.1       barstow   770:                 lineNum++;
                    771:             } while ( nl != -1 );
                    772: 
                    773:             out.println("</pre>");
                    774:         } catch (Exception e) {
1.8       barstow   775:             System.err.println("Exception (printListing): " + e.getMessage());
1.1       barstow   776:         }
                    777:     }
                    778: 
                    779:     /*
                    780:      * Print the header for the triple listing
                    781:      *
                    782:      *@param out the servlet's output stream
1.14      barstow   783:      *@param nTriples if true, output is N-Triples syntax
1.1       barstow   784:      */
                    785:     private void printTripleTableHeader (ServletOutputStream out, boolean nTriples) 
                    786:     {
                    787:         try {
                    788:             if (nTriples) {
1.6       barstow   789:                 out.println("<h3>Triples of the Data Model in " +
                    790:                    "<a href=\"http://www.w3.org/2001/sw/RDFCore/ntriples/\">" +
                    791:                    "N-Triples</a> Format (Sub, Pred, Obj)</h3>" +
                    792:                    "<pre>");
1.1       barstow   793:             } else {
                    794:                 out.println("<hr title=\"triples\">");
                    795:                 out.println("<h3>Triples of the Data Model</h3>");
                    796:                 out.println("<table border><tr>" +
                    797:                            "<td><b>Number</b></td>" +
                    798:                            "<td><b>Subject</b></td>" +
                    799:                            "<td><b>Predicate</b></td>" +
                    800:                            "<td><b>Object</b></td>" +
                    801:                            "</tr>");
                    802:             }
                    803:         } catch (Exception e) {
1.8       barstow   804:             System.err.println("Exception (printTripleTableHeader): " + e.getMessage());
1.1       barstow   805:         }
                    806:     }
                    807: 
                    808:     /*
                    809:      * Print the footer info for the triple listing
                    810:      *
                    811:      *@param out the servlet's output stream
1.14      barstow   812:      *@param nTriples if true, output is N-Triples syntax
1.1       barstow   813:      */
                    814:     private void printTripleTableFooter (ServletOutputStream out, 
                    815:         boolean nTriples) 
                    816:     {
                    817:         try {
                    818:             if (nTriples)
                    819:                 out.println("</pre>");
                    820:             else
                    821:                 out.println("</table>");
                    822:         } catch (Exception e) {
1.8       barstow   823:             System.err.println("Exception (printTripleTableFooter): " + e.getMessage());
1.1       barstow   824:         }
                    825:     }
                    826:     
                    827:     /*
                    828:      * Print the document's footer info
                    829:      *
                    830:      *@param out the servlet's output stream
                    831:      *@param rdf the RDF code
                    832:      */
                    833:     private void printDocumentFooter (ServletOutputStream out, String rdf) 
                    834:     {
                    835:         try {
                    836: 
1.8       barstow   837:             String s;
                    838: 
                    839:             s = "<hr title=\"Problem reporting\">" +
                    840:                 "<h3>Feedback</h3>" +
                    841:                 "<p>If you suspect the parser is in 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>" +
                    842:                 "<form enctype='text/plain' method='post' action='mailto:" + MAIL_TO + "'>" +
1.9       barstow   843:                 "<textarea cols='60' rows='4' name='report'></textarea>";
1.8       barstow   844:             out.println(s);
1.1       barstow   845: 
1.9       barstow   846:             out.println("<input type='hidden' name='RDF' value=\"&lt;?xml version=&quot;1.0&quot;&gt;");
                    847: 
1.1       barstow   848:             // The listing is being passed as a parameter so the '<' 
                    849:             // and '"' characters must be replaced with &lt; and &quot, 
                    850:             // respectively
                    851:             if (rdf != null) {
1.9       barstow   852:                 String s1;
                    853:                 s1 = replaceString(rdf, "<",  "&lt;");
1.11      barstow   854:                 s1 = replaceString(s1,  ">",  "&gt;");
1.9       barstow   855:                 s1 = replaceString(s1,  "\"", "&quot;");
                    856:                 out.println(s1);
1.1       barstow   857:             }
1.9       barstow   858:             out.println("\"\\>");
1.1       barstow   859: 
1.8       barstow   860:             out.println("<input type='submit' value='Submit problem report'\\>" +
1.9       barstow   861:                         "</form></body></html>");
1.1       barstow   862: 
                    863:         } catch (Exception e) {
1.8       barstow   864:             System.err.println("Exception (printDocumentFooter): " + e.getMessage());
1.1       barstow   865:         }
                    866:     }
                    867: 
                    868:     /*
                    869:      * Servlet's get info method
                    870:      */
                    871:     public String getServletInfo () {
                    872:        return "Servlet wrapper for the ARP RDF parser. This is revision " + REVISION;
                    873:     }
                    874: 
                    875:     /*
                    876:      * Servlet's init method
                    877:      *
                    878:      *@param config the servlet's configuration object
                    879:      *@throws ServletException
                    880:      */
                    881:     public void init(ServletConfig config) throws ServletException 
                    882:     {
                    883:        super.init (config);
                    884: 
                    885:         // Cache the parameters
                    886:         m_ServletTmpDir = config.getInitParameter(SERVLET_TMP_DIR);
                    887: 
                    888:         // All of the Graph Viz paths extend from GRAPH_VIZ_ROOT
                    889:         String GraphVizRoot = config.getInitParameter(GRAPH_VIZ_ROOT);
                    890: 
                    891:         m_GraphVizPath = GraphVizRoot + "/" + config.getInitParameter(GRAPH_VIZ_PATH);
                    892:         m_GraphVizFontDir = GraphVizRoot + "/" + config.getInitParameter(GRAPH_VIZ_FONT_DIR);
                    893: 
                    894:         if (m_ServletTmpDir == null || GraphVizRoot == null) {
                    895:            System.err.println (
                    896:                 "<html>" +
                    897:                 "<h1>Servlet Initialization Error</h1>" +
                    898:                 "<h2>One or more of the following parameters has not been initialized: " + 
                    899:                 SERVLET_TMP_DIR + "," + GRAPH_VIZ_ROOT + "," +
1.16      barstow   900:                 GRAPH_VIZ_FONT_DIR + "," + GRAPH_VIZ_PATH + "." +
1.1       barstow   901:                 "</h2>" +
                    902:                 "</html>");
                    903:         }
                    904:     }
                    905: 
                    906:     /*
                    907:      * Servlet's destroy info method
                    908:      */
                    909:     public void destroy () {
                    910:        super.destroy ();
                    911:     }
                    912: 
                    913:     /*
                    914:      * Servlet's doGet info method - NOT supported
                    915:      *
                    916:      *@param req the request
                    917:      *@param res the response
                    918:      *@throws ServletException, IOException
                    919:      */
                    920:     public void doGet (HttpServletRequest req, HttpServletResponse res)
                    921:         throws ServletException, IOException 
                    922:     {
                    923:         String sRDF = req.getParameter(TEXT);
                    924:        String sURI = req.getParameter(URI);
                    925: 
                    926:         if (sURI == null && sRDF == null) {
                    927:            ServletOutputStream out = res.getOutputStream ();
                    928: 
1.6       barstow   929:             out.println("<h1>Data Error</h1>" +
                    930:                 "Must specify the RDF (RDF is a string) or the URI parameter." +
                    931:                 "</h1>");
1.1       barstow   932:             return;
                    933:         }
                    934: 
                    935:         process(req, res, 
                    936:                 (sRDF != null) ? java.net.URLDecoder.decode(sRDF) : null, 
                    937:                 (sURI != null) ? java.net.URLDecoder.decode(sURI) : null);
                    938:     }
                    939: 
                    940:     /*
1.19    ! duerst    941:      * Convenience method to convert some String wrongly read in with iso-8859-1 to utf-8
        !           942:      *
        !           943:      *@param str the String (input and output)
        !           944:      */
        !           945:     private String ISO88591toUTF8 (String str)
        !           946:     {
        !           947:         return String(str.getBytes("iso-8859-1"), "utf-8");
        !           948:     }
        !           949: 
        !           950:     /*
1.1       barstow   951:      * Servlet's doPost method
                    952:      *
                    953:      *@param req the request
                    954:      *@param res the response
1.17      duerst    955:      *@throws ServletException, IOException, java.io.UnsupportedEncodingException
1.1       barstow   956:      */
                    957:     public void doPost (HttpServletRequest req, HttpServletResponse res)
                    958:         throws ServletException, IOException 
                    959:     {
1.19    ! duerst    960:        // String encoding = req.getCharacterEncoding();
        !           961:         // if (encoding == null) {
        !           962:        //    req.setCharacterEncoding("UTF-8");
        !           963:        // }
        !           964:        String sRDF = ISO88591toUTF8 (req.getParameter (TEXT));
        !           965:        String sURI = ISO88591toUTF8 (req.getParameter (URI));
1.1       barstow   966: 
                    967:         if (sURI == null && sRDF == null) {
                    968:            ServletOutputStream out = res.getOutputStream ();
                    969: 
                    970:             out.println("<h1>Neither the RDF or an URI was specified" + 
                    971:                         "and one of them must be specified.</h1>");
                    972:             return;
                    973:         }
                    974: 
                    975:         process(req,res,sRDF, sURI);
                    976:     }
                    977: 
                    978:     /*
                    979:      * Output a Resource in NTriples syntax
                    980:      *
                    981:      *@param out the servlet's output stream
                    982:      *@param r the Resource to output
                    983:      */
                    984:     static private void printResource(ServletOutputStream out, AResource r)
                    985:     {
                    986:         try { 
                    987:             if (r.isAnonymous() )
                    988:                 out.print("_:j" + r.getAnonymousID() + " ");
                    989:             else
                    990:                 out.print("&lt;" + r.getURI() + "&gt; ");
                    991:         } catch (IOException ioe) {
                    992:             System.err.println("IOException: printing resource.");
                    993:         }
                    994:     }
                    995: 
                    996:     /*
1.18      duerst    997:      * Convert to Hex and padd left with zeroes
                    998:      *
                    999:      *@param in the integer to convert and padd
                   1000:      *@param in the length of the result
                   1001:      *@return the padded string
                   1002:      */
                   1003:      // MJD: is there an easier way to do this?
                   1004:     static private String hexPadd (Integer number, Integer length)
                   1005:     {
                   1006:        String t = Integer.toHexString(number).toUpperCase();
                   1007:        Integer hexlength = t.length();
                   1008: 
                   1009:         if ( hexlength > length ) {    // too long, truncate
                   1010:            hexlength = length;
                   1011:        }
                   1012: 
                   1013:        Integer zerolength = length - hexlength;
                   1014:        String r = "";
                   1015: 
                   1016:        for (int i=0; i < zerolength; i++) {
                   1017:            r += "0";
                   1018:        }
                   1019:        for (int i=0; i < hexlength; i++) {
                   1020:            r += t.CharAt(i);
                   1021:        }
                   1022:        return r;
                   1023:     }
                   1024: 
                   1025:     /*
1.1       barstow  1026:      * Output a Literal in NTriples syntax
                   1027:      *
                   1028:      *@param out the servlet's output stream
                   1029:      *@param l the Literal to output
                   1030:      */
1.3       barstow  1031:     static private void printNTripleLiteral(ServletOutputStream out, ALiteral l) 
1.1       barstow  1032:     {
                   1033:         try {
                   1034:             out.print("\"");
                   1035:             char ar[] = l.toString().toCharArray();
                   1036: 
                   1037:             for (int i=0;i<ar.length;i++) {
                   1038:                 switch (ar[i]) {
                   1039:                     case '\\':
                   1040:                         out.print("\\\\");
                   1041:                         break;
                   1042:                     case '"':
                   1043:                         out.print("\\\"");
                   1044:                         break;
                   1045:                     case '\n':
                   1046:                         out.print("\\n");
                   1047:                         break;
                   1048:                     case '\r':
                   1049:                         out.print("\\r");
                   1050:                         break;
                   1051:                     case '\t':
                   1052:                         out.print("\\t");
                   1053:                         break;
1.18      duerst   1054:                     default:
                   1055:                         if ( ar[i] >= 32 && ar[i] <= 127 )
                   1056:                             out.print(ar[i]);
                   1057:                        else if ( ar[i] < 0xD800 || ar[i] >= 0xE000)
                   1058:                            out.print("\\u" + hexPadd(Integer.toHexString(ar[i]).toUpperCase(), 4) );
                   1059:                        else // deal with surrogates {
                   1060:                            // check for correct surrogate pair
                   1061:                             // this code should probably move somewhere else:
                   1062:                             // check when we get the input
                   1063:                             if ( ar[i] >= 0xDC00 ) {
                   1064:                                out.print("{{{error: lone low surrogate}}}");
                   1065:                            }
                   1066:                            else if ( ++i >= ar.length ) {
                   1067:                                 out.print("{{{error: lone surrogate at end of string}}}");
                   1068:                            }
                   1069:                            else if ( ar[i] < 0xDC00 || ar[i] >= 0xE000 ) {
                   1070:                                out.print("{{{error: high surrogate not followed by low surrogate}}}");
                   1071:                            }
                   1072:                            // no errors, actually print
                   1073:                            else {
                   1074:                                Integer scalarvalue = 0x10000 + (ar[i-1] * 1024) + ar[i];
                   1075:                                out.print("\\U" + hexPadd(Integer.toHexString(scalarvalue).toUpperCase(), 8) );
                   1076:                            }
                   1077:                        }
1.1       barstow  1078:                 }
                   1079:             }
                   1080:             out.print("\" ");
                   1081:         } catch (IOException ioe) {
                   1082:             System.err.println("IOException: printing literal.");
                   1083:         }
                   1084:     }
                   1085: 
                   1086:     /*
                   1087:      * Control point for outputing an triple in NTriple syntax
                   1088:      *
                   1089:      *@param out the servlet's output stream
                   1090:      *@param subj the subject
                   1091:      *@param pred the predicate
                   1092:      *@param objRes the object as a Resource (may be null)
                   1093:      *@param objLit the object as a Literal (may be null)
                   1094:      */
                   1095:     static private void printNTriple(ServletOutputStream out, AResource subj, 
                   1096:         AResource pred, AResource objRes, ALiteral objLit) 
                   1097:     {
                   1098:         try { 
                   1099:             printResource(out, subj);
                   1100:             printResource(out, pred);
                   1101:             if (objRes != null)
                   1102:                 printResource(out, objRes);
                   1103:             else
1.3       barstow  1104:                 printNTripleLiteral(out, objLit);
1.1       barstow  1105:             out.println(".");
                   1106:         } catch (IOException ioe) {
                   1107:             System.err.println("IOException: printing NTriple.");
                   1108:         }
                   1109:     }
                   1110: 
                   1111:     /*
                   1112:      * Create a HTML anchor from the URI or anonNode of the
                   1113:      * given Resource
                   1114:      *
1.14      barstow  1115:      *@param r the Resource
1.1       barstow  1116:      *@return the string as an HTML anchor
                   1117:      */
                   1118:     static private String addAnchor(AResource r) 
                   1119:     {
                   1120:         if (r.isAnonymous())
1.14      barstow  1121:             return ANON_NODE + r.getAnonymousID();
1.1       barstow  1122:         else
                   1123:             return "<a href='" + r.getURI() + "'>" + r.getURI() + "</a>";
                   1124:     }
                   1125: 
                   1126:     /*
                   1127:      * Output a triple as a row in HTML
                   1128:      *
                   1129:      *@param out the servlet's output stream
                   1130:      *@param subj the subject
                   1131:      *@param pred the predicate
                   1132:      *@param objRes the object as a Resource (may be null)
                   1133:      *@param objLit the object as a Literal (may be null)
                   1134:      *@param num the statement number
                   1135:      */
                   1136:     static private void printTableRow(ServletOutputStream out, AResource subj, 
                   1137:         AResource pred, AResource objRes, ALiteral objLit, int num) 
                   1138:     {
                   1139:         try { 
                   1140:             out.println("<tr><td>" + num + "</td>");
                   1141:             out.println("<td>" + addAnchor(subj) + "</td>");
                   1142:             out.println("<td>" + addAnchor(pred) + "</td>");
                   1143:             if (objRes != null)
                   1144:                 out.println("<td>" + addAnchor(objRes) + "</td>");
                   1145:             else {
                   1146:                 out.println("<td>");
1.3       barstow  1147:                 String s1 = objLit.toString().trim();
                   1148:                 s1 = replaceString(s1, "<", "&lt;");
                   1149:                 s1 = replaceString(s1, ">", "&gt;");
                   1150:                 out.println(s1);
1.1       barstow  1151:                 out.println("</td>");
                   1152:             }
                   1153:             out.println("</tr>");
                   1154:         } catch (IOException ioe) {
                   1155:             System.err.println("IOException: printing TableRow.");
                   1156:         }
                   1157:     }
                   1158: 
1.4       barstow  1159:     private static class SH implements StatementHandler 
1.1       barstow  1160:     {
                   1161:         ServletOutputStream out;
1.12      barstow  1162:         PrintWriter pw;
1.1       barstow  1163:         boolean isNTriples;
1.12      barstow  1164:         boolean printTriples;
                   1165:         boolean printGraph;
                   1166:         boolean anonNodesEmpty;
1.14      barstow  1167:         int numStatements;
                   1168:         int numLiterals;
                   1169:        Hashtable subjects;
                   1170:        int numSubjects;
1.1       barstow  1171:   
                   1172:         /*
1.4       barstow  1173:          * Constructuor for the StatementHandler.  The primary
                   1174:         * responsiblitly is to cache init variables
1.1       barstow  1175:          *
                   1176:         *@param out the servlet's output stream
1.4       barstow  1177:         *@param pw the Dot file's PrintWriter
1.1       barstow  1178:         *  syntax; otherwise use HTML syntax
1.12      barstow  1179:         *@param isNTriples if true, output using the NTriples
                   1180:         *@param printTriples if true, print the triples
                   1181:         *@param printGraph if true, create the graph file
                   1182:         *@param printGraph if true, anonomyous nodes should be empty
1.1       barstow  1183:         */
1.12      barstow  1184:         public SH(ServletOutputStream out, PrintWriter pw, boolean isNTriples, 
                   1185:             boolean printTriples, boolean printGraph, boolean anonNodesEmpty)
1.1       barstow  1186:         {
                   1187:             this.out = out;
1.12      barstow  1188:             this.pw = pw;
1.1       barstow  1189:             this.isNTriples = isNTriples;
1.12      barstow  1190:             this.printTriples = printTriples;
                   1191:             this.printGraph = printGraph;
                   1192:             this.anonNodesEmpty = anonNodesEmpty;
1.14      barstow  1193: 
                   1194:             this.numStatements = 0;
                   1195:             this.numLiterals = 0;
                   1196: 
                   1197:            this.subjects = new Hashtable();
                   1198:            this.numSubjects = 0;
1.4       barstow  1199:         }
                   1200: 
                   1201:         /*
                   1202:          * Generic handler for a Resource/Resource/Resource triple (S/P/O).
                   1203:         * Dispatches to the methods that do the real work.
                   1204:          *
                   1205:         *@param subj the subject
                   1206:         *@param pred the predicate
                   1207:         *@param obj the object (as a Resource)
                   1208:         */
                   1209:         public void statement(AResource subj, AResource pred, AResource obj) 
                   1210:         {
1.12      barstow  1211:            if (printTriples)
                   1212:                 statementResource(subj, pred, obj);
                   1213:            if (printGraph)
                   1214:                statementDotResource(subj, pred, obj);
1.4       barstow  1215:         }
                   1216: 
                   1217:         /*
                   1218:          * Generic handler for a Resource/Resource/Resource triple (S/P/O).
                   1219:         * Dispatches to the methods that do the real work.
                   1220:          *
                   1221:         *@param subj the subject
                   1222:         *@param pred the predicate
                   1223:         *@param obj the object (as a Literal)
                   1224:         */
                   1225:         public void statement(AResource subj, AResource pred, ALiteral lit) 
                   1226:         {
1.13      barstow  1227:             numLiterals++;
                   1228: 
1.12      barstow  1229:            if (printTriples)
                   1230:                 statementLiteral(subj, pred, lit);
                   1231:            if (printGraph)
                   1232:                 statementDotLiteral(subj, pred, lit);
1.1       barstow  1233:         }
                   1234: 
                   1235:         /*
                   1236:          * Handler for a Resource/Resource/Resource triple (S/P/O)
                   1237:         * Outputs the given triple using NTriples or HTML syntax.
                   1238:          *
                   1239:         *@param subj the subject
                   1240:         *@param pred the predicate
                   1241:         *@param obj the object (as a Resource)
                   1242:         */
1.4       barstow  1243:         public void statementResource(AResource subj, AResource pred, AResource obj) 
1.1       barstow  1244:         {
                   1245:             numStatements++;
                   1246: 
                   1247:             if (this.isNTriples)
                   1248:                 printNTriple(out, subj, pred, obj, null);
                   1249:             else
                   1250:                 printTableRow(out, subj, pred, obj, null, this.numStatements);
                   1251:         }
1.4       barstow  1252: 
1.1       barstow  1253:         /*
                   1254:          * Handler for a Resource/Resource/Literal triple (S/P/O)
                   1255:         * Outputs the given triple using NTriples or HTML syntax.
                   1256:          *
                   1257:         *@param subj the subject
                   1258:         *@param pred the predicate
                   1259:         *@param obj the object (as a Literal)
                   1260:         */
1.4       barstow  1261:         public void statementLiteral(AResource subj, AResource pred, ALiteral lit) 
1.1       barstow  1262:         {
                   1263:             numStatements++;
                   1264: 
                   1265:             if (this.isNTriples)
                   1266:                 printNTriple(out, subj, pred, null, lit);
                   1267:             else
                   1268:                 printTableRow(out, subj, pred, null, lit, this.numStatements);
                   1269:         }
1.4       barstow  1270: 
1.12      barstow  1271:        /* 
                   1272:         * Print the first part of a triple's Dot file.  See below for
                   1273:         * more info.  This is the same regardless if the triple's
                   1274:         * object is a Resource or a Literal
                   1275:         *
                   1276:         *@param subj the subject
                   1277:         */
                   1278:         public void printFirstPart(AResource subj) 
                   1279:        {
1.14      barstow  1280:             if (subj.isAnonymous()) {
1.12      barstow  1281:                if (this.anonNodesEmpty) {
1.14      barstow  1282:                    Integer n = (Integer) subjects.get(subj.getAnonymousID());
                   1283:                    if (n == null) {
                   1284:                        this.numSubjects++;
                   1285:                        subjects.put(subj.getAnonymousID(), new Integer(this.numSubjects));
                   1286:                         this.pw.println("\"" + ANON_NODE + 
                   1287:                            subj.getAnonymousID() + "\" [label=\"   \"];");
                   1288:                    }
1.12      barstow  1289:                }
1.14      barstow  1290:                 this.pw.print("\"" + ANON_NODE + subj.getAnonymousID());
1.12      barstow  1291:             } else {
                   1292:                 this.pw.println("\"" + subj.getURI() + "\" [URL=\"" +
                   1293:                    subj.getURI() + "\"];");
                   1294:                 this.pw.print("\"" + subj.getURI());
                   1295:             }
                   1296:        }
                   1297: 
1.4       barstow  1298:         /*
                   1299:          * Handler for a Resource/Resource/Resource triple (S/P/O).
                   1300:         * Outputs the given triple using Dot syntax.
1.12      barstow  1301:         *
                   1302:         * Each triple will be output in three lines of DOT code as
                   1303:         * follows (not including the complication of anon nodes 
                   1304:         * and the possiblity that the anon nodes may be named 
                   1305:         * with an empty string):
                   1306:         *
                   1307:         *   1. "<subject>" [URL="<subject">];
                   1308:         *   2. "<subject>" -> "<object>" [label="<predicate>",URL="<predicate>"];
                   1309:         *   3. "<object>"  [URL="<object>"];
1.4       barstow  1310:          *
                   1311:         *@param subj the subject
                   1312:         *@param pred the predicate
                   1313:         *@param obj the object (as a Resource)
                   1314:         */
                   1315:         public void statementDotResource(AResource subj, AResource pred, AResource obj) 
                   1316:         {
                   1317:            if (this.pw == null) return;
                   1318: 
1.12      barstow  1319:            printFirstPart(subj);
                   1320:            
                   1321:             this.pw.print("\" -> ");
1.4       barstow  1322: 
1.7       barstow  1323:             if (obj.isAnonymous()) {
1.12      barstow  1324:                if (this.anonNodesEmpty) {
1.14      barstow  1325:                     this.pw.println("\"" + ANON_NODE + 
1.15      barstow  1326:                        obj.getAnonymousID() + 
                   1327:                        "\" [label=\"" + pred.getURI() + "\",URL=\"" + 
                   1328:                        pred.getURI() + "\"];");
1.12      barstow  1329:                } else {
1.15      barstow  1330:                     this.pw.println("\"" + ANON_NODE + obj.getAnonymousID() + 
                   1331:                        "\" [label=\"" + pred.getURI() + "\",URL=\"" + 
                   1332:                        pred.getURI() + "\"];");
1.12      barstow  1333:                }
1.7       barstow  1334:             } else {
1.14      barstow  1335:                 this.pw.println("\"" + obj.getURI() + "\" [label=\"" +
                   1336:                    pred.getURI() + "\",URL=\"" + pred.getURI() + "\"];");
1.12      barstow  1337:                this.pw.println("\"" + obj.getURI() + "\" [URL=\"" +
                   1338:                    obj.getURI() + "\"];");
1.14      barstow  1339:            }
1.4       barstow  1340:         }
                   1341: 
                   1342:         /*
                   1343:          * Handler for a Resource/Resource/Literal triple (S/P/O).
                   1344:         * Outputs the given triple using Dot syntax.
1.12      barstow  1345:         *
                   1346:         * Each triple will be output in three lines of DOT code as
                   1347:         * follows (not including the complication of anon nodes 
                   1348:         * and the possiblity that the anon nodes may be named 
                   1349:         * with an empty string):
                   1350:          *
                   1351:         *   1. "<subject>" [URL="<subject">];
                   1352:         *   2. "<subject>" -> "<literal>" [label="<predicate>",URL="<predicate>"];
                   1353:         *   3. "<literal>" [shape="box"];
1.4       barstow  1354:          *
                   1355:         *@param subj the subject
                   1356:         *@param pred the predicate
                   1357:         *@param obj the object (as a Literal)
                   1358:         */
                   1359:         public void statementDotLiteral(AResource subj, AResource pred, ALiteral lit) 
                   1360:         {
                   1361:            if (this.pw == null) return;
                   1362: 
1.12      barstow  1363:            printFirstPart(subj);  // Same as Res/Res/Res
1.4       barstow  1364: 
                   1365:             /*
                   1366:              * Before outputing the object (Literal) do the following:
                   1367:              *
                   1368:              * o GraphViz/DOT cannot handle embedded line terminators characters
                   1369:              *   so they must be replaced with spaces
                   1370:              * o Limit the number of chars to make the graph legible
                   1371:              * o Escape double quotes
                   1372:              */
                   1373:             String s1 = new String(lit.toString());
                   1374:             s1 = s1.replace('\n', ' ');
                   1375:             s1 = s1.replace('\f', ' ');
                   1376:             s1 = s1.replace('\r', ' ');
                   1377:             if (s1.indexOf('"') != -1)
                   1378:                 s1 = replaceString(s1, "\"", "\\\"");
                   1379: 
                   1380:             // Anything beyond 80 chars makes the graph too large
                   1381:             String tmpObject;
                   1382:             if (s1.length() >= 80)
                   1383:                 tmpObject = s1.substring(0, 80) + " ...";
                   1384:             else
                   1385:                 tmpObject = s1.substring(0, s1.length());
                   1386: 
1.13      barstow  1387:            // Create a temporary label for the literal so that if
                   1388:            // it is duplicated it will be unique in the graph and
                   1389:            // thus have its own node.
                   1390:            String tmpName = "Literal_" + Integer.toString(this.numLiterals);
                   1391:             this.pw.print("\" -> \"" + tmpName);
1.4       barstow  1392: 
1.14      barstow  1393:             this.pw.println("\" [label=\"" + pred.getURI() + 
                   1394:                            "\",URL=\""    + pred.getURI() + "\"];");
1.4       barstow  1395: 
1.13      barstow  1396:             this.pw.println("\"" + tmpName + "\" [shape=box,label=\"" + tmpObject + "\"];");
1.4       barstow  1397:         }
                   1398:     }
                   1399: 
1.5       barstow  1400:     private void printErrorMessages(ServletOutputStream out, 
                   1401:        SaxErrorHandler eh)
                   1402:     {
                   1403:        try {
                   1404:            String s;
                   1405: 
                   1406:            s = eh.getFatalErrors();
                   1407:            if (s != null && s.length() >= 1)
                   1408:                out.println("<h2>Fatal Error Messages</h2>" + s);
                   1409: 
                   1410:            s = eh.getErrors();
                   1411:            if (s != null && s.length() >= 1)
                   1412:                out.println("<h2>Error Messages</h2>" + s);
                   1413: 
                   1414:            s = eh.getWarnings();
                   1415:            if (s != null && s.length() >= 1)
                   1416:                out.println("<h2>Warning Messages</h2>" + s);
                   1417:        } catch (Exception e) {
                   1418:            System.err.println(SERVLET_NAME + ": Error printing error messages.");
                   1419:        }
                   1420:     }
                   1421: 
                   1422:     /*
                   1423:      * Initialize the graph output file.  If an error occurs, this
                   1424:      * function will print an error message.
                   1425:      *
                   1426:      *@param out the servlet's output stream
                   1427:      *@req the servlet request object
                   1428:      *@return the File object for the graph file; null if an error occurs
                   1429:      */
1.4       barstow  1430:     private File initGraphFile(ServletOutputStream out, 
                   1431:        HttpServletRequest req)
                   1432:     {
                   1433:         try {
                   1434:             // Stop if any of the parameters are missing
                   1435:             if (m_ServletTmpDir   == null || 
                   1436:                 m_GraphVizPath    == null || 
1.16      barstow  1437:                 m_GraphVizFontDir == null)
1.4       barstow  1438:            {
                   1439:                 // Put the paths in a comment in the returned content
                   1440:                 out.println("<!-- SERVLET_TMP_DIR = " + m_ServletTmpDir);
                   1441:                 out.println("GRAPH_VIZ_PATH = " + m_GraphVizPath);
                   1442:                 out.println("GRAPH_FONT_DIR  = " + m_GraphVizFontDir + " -->");
                   1443: 
1.12      barstow  1444:                 out.println("<h1>Servlet initialization failed</h1>");
                   1445:                out.println("Please send a message to <a href='mailto:" + MAIL_TO +  "'>" + MAIL_TO + "</a> and mention this problem.");
1.4       barstow  1446:                 return null;
                   1447:             } 
                   1448:        } catch (Exception e) {
                   1449:            System.err.println("Unable to create a temporary graph file. A graph cannot be generated.");
                   1450:            return null;
                   1451:        }
                   1452: 
                   1453:         File dotFile = null;
                   1454: 
                   1455:         try {
                   1456:             // Must generate a unique file name that the DOT handler will use 
                   1457:             dotFile = createTempFile(m_ServletTmpDir, TMP_FILE_PREFIX, SUFFIX_DOT);
                   1458:             if (dotFile == null) {
                   1459:                 out.println("<h1>Failed to create a temporary graph file. A graph cannot be generated.</h1>");
                   1460:                 return null;
                   1461:             }
                   1462: 
                   1463:        } catch (IOException ioe) {
                   1464:           try {
                   1465:                 out.println("<h1>Unable to create a temporary graph file. A graph cannot be generated.</h1>");
                   1466:           } catch (Exception e2) {
                   1467:               System.err.println("Unable to create a temporary graph file. A graph cannot be generated.");
                   1468:           }
                   1469:        }
                   1470: 
                   1471:        return dotFile;
1.1       barstow  1472:     }
1.6       barstow  1473: 
                   1474:     /*
                   1475:      * Check if the given URI is supported or not
                   1476:      *
                   1477:      *@param out the servlet's output stream
                   1478:      *@param uri the URI to check
                   1479:      *@return true if the URI is supported; false otherwise
                   1480:      */
                   1481:     private boolean isURISupported(ServletOutputStream out, String uri)
                   1482:     {
                   1483:        try {
                   1484:            if (uri.length() >= 4 && uri.substring(0,4).equalsIgnoreCase("file")) {
                   1485:                out.println("<h1>file URI Schemes are NOT Supported</h1>");
                   1486:                out.println("URIs from the 'file' URI scheme are not supported by this servlet.");
                   1487:                return false;
                   1488:            }
                   1489:         } catch (Exception e) {
                   1490:            System.err.println("Exception in isURISupported.");
                   1491:            return false;
                   1492:        }
                   1493: 
                   1494:        return true;
                   1495:     }
1.1       barstow  1496:     
                   1497:     /*
                   1498:      * Handle the servlets doGet or doPut request
                   1499:      *
                   1500:      *@param req the servlet's request
                   1501:      *@param res the servlet's response
                   1502:      *@throws SevletException, IOException
                   1503:      */
                   1504:     private void process(HttpServletRequest req, HttpServletResponse res, 
                   1505:         String sRDF, String sURI) throws ServletException, IOException 
                   1506:     {
                   1507:        ServletOutputStream out = res.getOutputStream ();
                   1508: 
1.10      barstow  1509:         res.setContentType ("text/html");
                   1510: 
1.12      barstow  1511:        String sSaveRDF         = req.getParameter (SAVE_RDF);
                   1512:        String sSaveDOTFile     = req.getParameter (SAVE_DOT_FILE);
                   1513:        String sFormat          = req.getParameter (FORMAT);
                   1514:        String sNTriples        = req.getParameter (NTRIPLES);
                   1515:        String sEmbedded        = req.getParameter (EMBEDDED_RDF);
                   1516:        String sTriplesAndGraph = req.getParameter (TRIPLES_AND_GRAPH);
                   1517:        String sAnonNodesEmpty  = req.getParameter (ANON_NODES_EMPTY);
                   1518: 
                   1519:         // Set the print flags
                   1520:         boolean printTriples = true;
                   1521:        boolean printGraph = true;
                   1522:        if (sTriplesAndGraph != null) {
                   1523:            if (sTriplesAndGraph.equals(PRINT_TRIPLES)) 
                   1524:                printGraph = false;
                   1525:            if (sTriplesAndGraph.equals(PRINT_GRAPH))
                   1526:                printTriples = false;
                   1527:        } 
1.1       barstow  1528: 
1.12      barstow  1529:        // Determine if printing the triples and/or graph
                   1530:         boolean anonNodesEmpty = (sAnonNodesEmpty != null) ? true : false;
1.1       barstow  1531:         boolean nTriples = (sNTriples != null) ? true : false;
1.12      barstow  1532: 
1.10      barstow  1533:         // ARP parser has embedded = true by default so if user
                   1534:         // wants embedding, must set it to false
                   1535:         boolean embedded = (sEmbedded != null) ? false : true;
1.1       barstow  1536: 
                   1537:         String sError = null;
                   1538: 
                   1539:         InputStream in = null;
                   1540:         String xmlBase = DEFAULT_NAMESPACE;
                   1541: 
                   1542:         printDocumentHeader (out);
                   1543:         
                   1544:         if (sURI != null && sURI.length() >= 1) {
1.6       barstow  1545: 
                   1546:            // First check for unsupported URIs
                   1547:            if (!isURISupported(out, sURI)) {
                   1548:                 printDocumentFooter(out, null);
                   1549:                 return;
                   1550:            }
                   1551: 
1.1       barstow  1552:             xmlBase = sURI;
                   1553:             try {
                   1554:                 File ff = new File(sURI);
                   1555:                 in = new FileInputStream(ff);
1.6       barstow  1556:             } catch (Exception ignore) {
1.1       barstow  1557:                 try {
                   1558:                     URL url;
                   1559:                     url=new URL(sURI);
                   1560:                     in = url.openStream();
                   1561:                     sRDF = getByteStream(sURI);
                   1562:                     if (sRDF == null)
1.6       barstow  1563:                         sError = "error";
1.1       barstow  1564:                 } catch (Exception e) {
1.6       barstow  1565:                     sError = "error";
1.1       barstow  1566:                 }
                   1567:             }
                   1568:         }
                   1569: 
                   1570:         if (sError != null) {
1.6       barstow  1571:             out.println("<h1>RDF Load Error</h1>");
                   1572:             out.println("An attempt to load the RDF from URI '" + sURI + "' failed.  (The URI may not exist or the server is down.)");
1.1       barstow  1573:             printDocumentFooter(out, null);
                   1574:             return;
                   1575:         }
1.4       barstow  1576:  
                   1577:        PrintWriter pw = null; // The writer for the graph file
                   1578:        File dotFile = null;   // The graph file
1.12      barstow  1579:         if (sFormat != null && printGraph) {
1.4       barstow  1580:            dotFile = initGraphFile(out, req);
                   1581:            if (dotFile == null)
                   1582:                // Assume error has been reported
                   1583:                return;
                   1584: 
                   1585:             // Create a PrintWriter for the DOT handler
                   1586:             FileWriter fw = new FileWriter(dotFile);
                   1587:            if (fw != null)
                   1588:                 pw = new PrintWriter(fw);
                   1589:            if (pw != null)
                   1590:                 // Add the graph header
                   1591:                 processGraphParameters (req, pw);
                   1592:        }
                   1593: 
                   1594:        // Create the StatementHandler - it will handle triples for
                   1595:        // the table/ntriples and the graph file
1.12      barstow  1596:         SH sh = new SH(out, pw, nTriples, printTriples, printGraph, anonNodesEmpty);
1.4       barstow  1597: 
                   1598:         // Create the ErrorHandler 
                   1599:         SaxErrorHandler errorHandler = new SaxErrorHandler(out, false);
                   1600: 
                   1601:         // Create and initialize the parser
                   1602:        ARP parser = new com.hp.hpl.jena.rdf.arp.ARP();
                   1603:         parser.setErrorHandler(errorHandler);
                   1604:         parser.setStatementHandler(sh);
1.10      barstow  1605:         parser.setEmbedding(embedded);
1.1       barstow  1606: 
                   1607:         printListing (out, sRDF, sURI != null && sURI.length() >= 1);
1.12      barstow  1608: 
                   1609:         if (printTriples)
                   1610:             printTripleTableHeader (out, nTriples);
1.1       barstow  1611: 
                   1612:         try {
                   1613:             if (sURI != null && sURI.length() >= 1) {
                   1614:                 parser.load(in, xmlBase);
                   1615:             } else {
                   1616:                StringReader  sr = new StringReader (sRDF);
                   1617:                 parser.load(sr, xmlBase);
                   1618:             }
                   1619:         } catch (IOException ioe) {
                   1620:             sError = "IOError parsing: " + sURI + ": " + ioe.toString();
                   1621:         } catch (Exception ex) {
                   1622:             sError = "Exception parsing: " + sURI + ": " + ex.toString();
                   1623:         }
                   1624: 
1.12      barstow  1625:         if (printTriples)
                   1626:             printTripleTableFooter(out, nTriples);
1.5       barstow  1627: 
                   1628:        printErrorMessages(out, errorHandler);
1.1       barstow  1629: 
                   1630:         if (sError != null) {
1.6       barstow  1631:            out.println ("<h1>Parser Loading Error</h1>");
                   1632:            out.println (sError);
1.1       barstow  1633:             printDocumentFooter(out, null);
                   1634:             return;
                   1635:         }
                   1636: 
1.10      barstow  1637:         res.flushBuffer();
1.12      barstow  1638:         if (sFormat != null && printGraph) {
1.4       barstow  1639:             generateGraph(out, pw, dotFile, sRDF, req, sFormat,
1.1       barstow  1640:                           (sSaveRDF != null) ? true : false,
                   1641:                           (sSaveDOTFile != null && sSaveDOTFile.equals ("on") ? true : false));
                   1642:         }
                   1643: 
                   1644: 
1.9       barstow  1645:         if (sURI != null && sURI.length() >= 1)
                   1646:             printDocumentFooter(out, null);
                   1647:         else
                   1648:             printDocumentFooter(out, sRDF);
1.1       barstow  1649:     }
                   1650: }

Webmaster