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

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

Webmaster