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

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.55      duerst     66:  * URI - the URI of the RDF to validate
                     67:  *
                     68:  * PARSE - if "Parse RDF", then parse RDF from the textarea;
1.65      duerst     69:  *   else download from URI; if not present, prefer URI,
                     70:  *   but if URI is empty, parse RDF (old behavior).
1.1       barstow    71:  *
                     72:  * ORIENTATION - the graph's orientation (left to right or top to
1.16      barstow    73:  *   bottom); default is left to right
1.1       barstow    74:  *
1.16      barstow    75:  * FONT_SIZE - the font size to use (10, 12, 14, 16 and 20 are 
                     76:  *   supported); the default is 10
1.1       barstow    77:  *
1.65      duerst     78:  * NODE_COLOR - the color of nodes; default is black
                     79:  *
                     80:  * NODE_TEXT_COLOR - the color of the text in nodes; default is blue
                     81:  *
                     82:  * EDGE_COLOR - the color of edges; default is darkgreen
                     83:  *
                     84:  * EDGE_TEXT_COLOR - the color of the text on edges; default is red
                     85:  *
1.16      barstow    86:  * ANON_NODES_EMPTY - if "on", anonymous nodes are not labeled; otherwise
                     87:  *   anonymous nodes are labeled;
1.12      barstow    88:  *
                     89:  * TRIPLES_AND_GRAPH - support values are:
                     90:  *
1.16      barstow    91:  *     PRINT_BOTH - display triples and a graph (the default)
                     92:  *     PRINT_TRIPLES - only display the triples
                     93:  *     PRINT_GRAPH - only display the graph
1.12      barstow    94:  *
1.63      duerst     95:  * FORMAT - the graph's output format.  Supported values are:
1.1       barstow    96:  *
1.65      duerst     97:  *     GIF_EMBED - embed the graph as a GIF
1.1       barstow    98:  *     GIF_LINK - don't embed the GIF but create a link for it
                     99:  *     SVG_LINK - create the graph in SVG format and create a link to the file
1.71      epietrig  100:  *     SVG_EMBED - create the graph in SVG format and embed it in an object tag
                    101:  *     ISV_ZVTM - IsaViz/ZVTM (Dynamic View - requires Java Plug-in 1.4)
1.1       barstow   102:  *     PNG_EMBED - create the graph in PNG format and embed the graph in the 
1.65      duerst    103:  *       document that is returned (the default)
1.1       barstow   104:  *     PNG_LINK - create the graph in PNG format and create a link to the file
                    105:  *     PS_LINK - create a PostScript image of the file and a link to the file
                    106:  *     HP_PCL_LINK - create a HPGL/2 - PCL (Laserwriter) image of the file 
                    107:  *       and a link to the file
                    108:  *     HP_GL_LINK - create a HPGL - PCL (pen plotter) image of the file and 
                    109:  *       a link to the file
                    110:  *
                    111:  * NTRIPLES if "on" the tabular output will be in the NTriples format;
                    112:  *  otherwise a table of Subject, Predicate, Objects will be generated
                    113:  *
1.16      barstow   114:  ***********************************************************************
                    115:  *
                    116:  * Server Initialization - this servlet requires the following 
                    117:  *  parameters be set in the servlet's init() method - via the
                    118:  *  ServletConfig object:
1.1       barstow   119:  *
1.16      barstow   120:  * GRAPH_VIZ_ROOT - the absolute path of the top-level directory containing
                    121:  *   GraphViz's binary distribution
                    122:  *
1.68      duerst    123:  * GRAPH_VIZ_PATH - absolute or relative (based on GRAPH_VIZ_ROOT) path of
1.16      barstow   124:  *   the DOT executable (e.g. dotneato/dot) - the program used to generate
                    125:  *   a graph from a DOT file.
                    126:  *
1.68      duerst    127:  * GRAPH_VIZ_FONT_DIR - absolute or relative (based on GRAPH_VIZ_ROOT) path of
1.16      barstow   128:  *   the fonts directory used by GraphViz (e.g. Fonts)
                    129:  *
                    130:  * SERVLET_TMP_DIR - the absolute path of the directory to be used to
                    131:  *   store temporary files used by the servlet and GraphViz.  This 
                    132:  *   directory must be writable by the servlet.  
                    133:  *
                    134:  *   NOTE - Some files created by the servlet are not removed by 
                    135:  *     servlet (e.g. graph image files).
                    136:  *
                    137:  * If any of these parameters are not defined, the servlet will NOT 
                    138:  * validate the RDF.
                    139:  *
                    140:  ***********************************************************************
                    141:  *
                    142:  * Dependencies - this servlet requires the following Java packages
                    143:  *   as well as GraphViz (described above):
                    144:  *
                    145:  * ARP RDF parser: http://www.hpl.hp.co.uk/people/jjc/arp/download.html
                    146:  *
                    147:  * SAX-based XML parser: e.g. Xerces at http://xml.apache.org/
                    148:  *
                    149:  * Java servlet package: http://java.sun.com/products/servlet/archive.html
                    150:  *
                    151:  * Apache Regular Expression: http://jakarta.apache.org/builds/jakarta-regexp/release/v1.2/
                    152:  *
                    153:  ***********************************************************************
                    154:  *
                    155:  * Author: Art Barstow <barstow@w3.org>
1.30      duerst    156:  * Author (internationalization): Martin J. Duerst <duerst@w3.org>
1.69      epietrig  157:  * Author (maintenance): Emmanuel Pietriga <emmanuel@w3.org>
1.16      barstow   158:  *
1.76    ! epietrig  159:  * $Id: ARPServlet.java,v 1.75 2003/05/09 18:55:35 epietrig Exp $
1.16      barstow   160:  *
                    161:  ***********************************************************************/
1.1       barstow   162: 
1.16      barstow   163: // http://dev.w3.org/cvsweb/java/classes/org/w3c/rdf/examples/
                    164: package org.w3c.rdf.examples; 
1.1       barstow   165: 
                    166: import java.io.*;
                    167: import java.net.MalformedURLException;
                    168: import java.net.URL;
1.33      duerst    169: import java.net.URLConnection;
1.1       barstow   170: import java.util.StringTokenizer;
                    171: import java.util.Enumeration;
1.14      barstow   172: import java.util.Hashtable;
1.16      barstow   173: 
                    174: // http://java.sun.com/products/servlet/2.2/javadoc/javax/servlet/package-summary.html
                    175: import javax.servlet.*;         
1.1       barstow   176: import javax.servlet.http.*;
1.32      duerst    177: import javax.mail.internet.ContentType;
1.1       barstow   178: 
1.16      barstow   179: // http://xml.apache.org/apiDocs/org/xml/sax/package-summary.html
                    180: import org.xml.sax.InputSource;        
1.69      epietrig  181: //import org.xml.sax.Parser;
1.1       barstow   182: import org.xml.sax.SAXException;
                    183: import org.xml.sax.SAXParseException;
                    184: import org.xml.sax.ErrorHandler;
                    185: import org.xml.sax.helpers.*;
                    186: 
1.16      barstow   187: // http://jakarta.apache.org/regexp/apidocs/org/apache/regexp/RE.html
1.3       barstow   188: import org.apache.regexp.RE;
1.53      duerst    189: import org.apache.regexp.RESyntaxException;
1.3       barstow   190: 
1.16      barstow   191: // http://www.hpl.hp.co.uk/people/jjc/arp/apidocs/index.html
                    192: import com.hp.hpl.jena.rdf.arp.*; 
1.1       barstow   193: 
                    194: public class ARPServlet extends HttpServlet
                    195: {
1.76    ! epietrig  196:     final static public String REVISION = "$Id: ARPServlet.java,v 1.75 2003/05/09 18:55:35 epietrig Exp $";
1.1       barstow   197: 
                    198:     // The email address for bug reports
1.6       barstow   199:     private static final String MAIL_TO = "www-rdf-validator@w3.org";
1.1       barstow   200: 
                    201:     // Names of the POST parameters (described above) and their
1.12      barstow   202:     // defaults (if applicable)
                    203:     private static final String TEXT              = "RDF";
                    204:     private static final String SAVE_DOT_FILE     = "SAVE_DOT_FILE";
                    205:     private static final String SAVE_RDF          = "SAVE_RDF";
                    206:     private static final String EMBEDDED_RDF      = "EMBEDDED_RDF";
                    207:     private static final String URI               = "URI";
1.55      duerst    208:     private static final String PARSE             = "PARSE";
1.12      barstow   209:     private static final String NTRIPLES          = "NTRIPLES";
                    210:     private static final String ANON_NODES_EMPTY  = "ANON_NODES_EMPTY";
1.1       barstow   211:  
                    212:     private static final String NODE_COLOR         = "NODE_COLOR";
                    213:     private static final String DEFAULT_NODE_COLOR = "black";
                    214: 
                    215:     private static final String NODE_TEXT_COLOR         = "NODE_TEXT_COLOR";
1.65      duerst    216:     private static final String DEFAULT_NODE_TEXT_COLOR = "blue";
1.1       barstow   217: 
                    218:     private static final String EDGE_COLOR         = "EDGE_COLOR";
1.65      duerst    219:     private static final String DEFAULT_EDGE_COLOR = "darkgreen";
1.1       barstow   220: 
                    221:     private static final String EDGE_TEXT_COLOR         = "EDGE_TEXT_COLOR";
1.65      duerst    222:     private static final String DEFAULT_EDGE_TEXT_COLOR = "red";
1.1       barstow   223: 
                    224:     private static final String ORIENTATION         = "ORIENTATION";
1.65      duerst    225:     private static final String DEFAULT_ORIENTATION = "LR";  // Left to Right
1.1       barstow   226: 
                    227:     private static final String FONT_SIZE         = "FONT_SIZE";
                    228:     private static final String DEFAULT_FONT_SIZE = "10";
                    229: 
1.12      barstow   230:     // Print graph and/or triples
                    231:     private static final String TRIPLES_AND_GRAPH = "TRIPLES_AND_GRAPH";
                    232:     private static final String PRINT_BOTH        = "PRINT_BOTH";
                    233:     private static final String PRINT_TRIPLES     = "PRINT_TRIPLES";
                    234:     private static final String PRINT_GRAPH       = "PRINT_GRAPH";
                    235: 
                    236:     // Graph formats
1.1       barstow   237:     private static final String FORMAT              = "FORMAT";
                    238:     private static final String FORMAT_GIF_EMBED    = "GIF_EMBED";
                    239:     private static final String FORMAT_GIF_LINK     = "GIF_LINK";
                    240:     private static final String FORMAT_SVG_LINK     = "SVG_LINK";
1.71      epietrig  241:     private static final String FORMAT_SVG_EMBED     = "SVG_EMBED";
                    242:     private static final String FORMAT_ISV_ZVTM     = "ISV_ZVTM";
1.1       barstow   243:     private static final String FORMAT_PNG_EMBED    = "PNG_EMBED";
                    244:     private static final String FORMAT_PNG_LINK     = "PNG_LINK";
                    245:     private static final String FORMAT_PS_LINK      = "PS_LINK";
                    246:     private static final String FORMAT_HP_PCL_LINK  = "HP_PCL_LINK";
                    247:     private static final String FORMAT_HP_GL_LINK   = "HP_GL_LINK";
1.63      duerst    248:     private static final String DEFAULT_FORMAT      = "PNG_EMBED";
1.1       barstow   249: 
                    250:     // Fonts are not currently configurable
1.69      epietrig  251:     private static final String DEFAULT_TTF_FONT = "cyberbit";   //could changed to 'arialuni'
                    252:     private static final String DEFAULT_FONT = "Courier";   //could changed to 'arialuni' to get coverage for japanese/russian/...
1.1       barstow   253: 
                    254:     // Names of the servlet's parameters - for Jigsaw web server
                    255:     private static final String SERVLET_TMP_DIR    = "SERVLET_TMP_DIR";
                    256:     private static final String GRAPH_VIZ_ROOT     = "GRAPH_VIZ_ROOT";
                    257:     private static final String GRAPH_VIZ_PATH     = "GRAPH_VIZ_PATH";
                    258:     private static final String GRAPH_VIZ_FONT_DIR = "GRAPH_VIZ_FONT_DIR";
                    259: 
                    260:     // Variables for the servlet's parameters
                    261:     private static String m_ServletTmpDir   = null;
                    262:     private static String m_GraphVizPath    = null;
                    263:     private static String m_GraphVizFontDir = null;
                    264: 
1.30      duerst    265:     // Names of environment variable needed by GraphVis
1.1       barstow   266:     private static String DOTFONTPATH     = "DOTFONTPATH";
                    267:     private static String LD_LIBRARY_PATH = "LD_LIBRARY_PATH";
                    268: 
                    269:     // Names used for temporary files
                    270:     private static final String TMP_FILE_PREFIX = "servlet_";
                    271:     private static final String SUFFIX_TMP_DIR  = ".tmp";
                    272:     private static final String SUFFIX_DOT      = ".dot";
                    273:     private static final String SUFFIX_RDF      = ".rdf";
                    274: 
                    275:     // Names used for file suffixes and for GraphViz's command line
                    276:     // option
                    277:     private static final String NAME_GIF      = "gif";
                    278:     private static final String NAME_HPGL     = "hpgl";
                    279:     private static final String NAME_PCL      = "pcl";
                    280:     private static final String NAME_PNG      = "png";
                    281:     private static final String NAME_PS       = "ps";
                    282:     private static final String NAME_SVG      = "svg";
                    283: 
                    284:     // Default GraphViz parameter names and their default values
                    285:     // Servlet name
                    286:     private static final String SERVLET_NAME = "ARPServlet";
                    287: 
                    288:     // Name for the DOT file title
                    289:     private static final String DOT_TITLE = "dotfile";
                    290: 
1.30      duerst    291:     // The string to use to prefix anonymous nodes.
1.14      barstow   292:     private static final String ANON_NODE = "genid:";
                    293: 
1.1       barstow   294:     // The string to use for a namespace name when no
                    295:     // namespace is available - e.g. for the RDF that is
                    296:     // directly entered into the input form.
1.69      epietrig  297:     private static final String DEFAULT_NAMESPACE = "";
1.1       barstow   298: 
1.72      epietrig  299:     //used to detect whether the provided document contains at least one triple, or if it is not RDF at all
                    300:     //necessary because ARP does not report any error when parsing an XML document which does not contain any
                    301:     //RDF statement
                    302:     static boolean AT_LEAST_ONE_TRIPLE=false;
                    303: 
1.71      epietrig  304:     //colors for ISV-plugin texts (resources, properties and literals)
                    305:     private static float resTBh=0.33333334f;
                    306:     private static float resTBs=0.37142858f;
                    307:     private static float resTBv=0.4117647f;
                    308:     private static float prpTh=0.6680911f;
                    309:     private static float prpTs=0.56796116f;
                    310:     private static float prpTv=0.80784315f;
                    311:     private static float litTBh=0.12878788f;
                    312:     private static float litTBs=0.5f;
                    313:     private static float litTBv=0.5176471f;
                    314: 
1.53      duerst    315:     // exception used by getRDFfromURI
                    316:     private class getRDFException extends Exception {
                    317:         public getRDFException (String s) {
                    318:            super (s);
                    319:         }
                    320:     }
                    321: 
1.1       barstow   322:     /*
1.14      barstow   323:      * Create a File object from the given directory and file names
1.1       barstow   324:      *
                    325:      *@param directory the file's directory
                    326:      *@param prefix the file's prefix name (not its directory)
                    327:      *@param suffix the file's suffix or extension name
                    328:      *@return a File object if a temporary file is created; null otherwise
                    329:      */
1.4       barstow   330:     private File createTempFile (String directory, String prefix, String suffix) 
                    331:     {
1.1       barstow   332:         File f;
                    333:         try {
                    334:             File d = new File(directory);
                    335:             f = File.createTempFile(prefix, suffix, d);
                    336:         } catch (Exception e) {
                    337:             return null;
                    338:         }
                    339:         return f;
                    340:     }
                    341: 
                    342:     /*
                    343:      * Given a URI string, open it, read its contents into a String
                    344:      * and return the String
                    345:      *
                    346:      *@param uri the URI to open
                    347:      *@return the content at the URI or null if any error occurs
                    348:      */
1.53      duerst    349:     private String getRDFfromURI (String uri) throws getRDFException
1.4       barstow   350:     {
1.53      duerst    351:        /* add something like this code here, to allow reading from a file:
                    352:           (if we really want to allow this!)
                    353:           File ff = new File(uri);
                    354:           in = new FileInputStream(ff);
                    355:        */
                    356:        URL url = null;
                    357:        try {
                    358:            url = new URL(uri);
                    359:        } catch (MalformedURLException e) {
                    360:            throw new getRDFException("Malformed URI.");
                    361:        }
                    362: 
                    363:         URLConnection con = null;
                    364:        try {
                    365:            con = url.openConnection();
                    366:            con.setRequestProperty("Accept", "application/rdf+xml");
                    367:            con.connect();
                    368:        } catch (Exception e) {
                    369:            throw new getRDFException("Unable to open connection.");
                    370:        }
                    371:        String contentT = con.getContentType();
                    372:        String HTTPcharset = null;
                    373:        if (contentT != null) {
                    374:            ContentType contentType = null;
                    375:            try {
                    376:                contentType = new ContentType(con.getContentType());
                    377:            } catch (javax.mail.internet.ParseException e) {
                    378:                throw new getRDFException("Unparsable content type.");
1.32      duerst    379:            }
1.53      duerst    380:            HTTPcharset = contentType.getParameter("charset");
                    381:        }
                    382:        
                    383:        // need buffer for lookahead for encoding detection
                    384:        BufferedInputStream bis = null;
                    385:        try {
                    386:            bis = new BufferedInputStream(con.getInputStream());
                    387:        } catch (IOException e) {
                    388:            throw new getRDFException("Cannot open stream.");
                    389:        }
                    390:        bis.mark(200); // mark start so that we can get back to it
                    391:        String s = "";
                    392:        
1.54      duerst    393:        try {  // read start of file as bytes
                    394:            int c;
                    395:            int numRead = 0;
1.53      duerst    396:            while ((c = bis.read()) != -1) {
                    397:                s += (char)c;
1.54      duerst    398:                if (numRead++ >= 195) break;
1.53      duerst    399:            }
                    400:        } catch (IOException e) {
                    401:            throw new getRDFException("IOException while starting reading.");
                    402:        }
                    403:        
                    404:        if (s.equals(""))
                    405:            // Nothing was returned 
                    406:            throw new getRDFException("Empty document, ignored.");
                    407:        
                    408:        // A server could return content but not the RDF/XML that
                    409:        // we need.  Check the beginning of s and if it looks like
                    410:        // a generic HTML message, return an error.
                    411:        if (s.startsWith("<!DOCTYPE"))
                    412:            throw new getRDFException("Document looks like HTML, ignored.");
1.54      duerst    413: 
                    414:        String APPFcharset = null;  // 'charset' according to XML APP. F
                    415:        int ignoreBytes = 0;
                    416:        if (s.startsWith("\u00FE\u00FF")) {
                    417:            APPFcharset = "UTF-16BE";
                    418:            ignoreBytes = 2;
                    419:        }
                    420:        else if (s.startsWith("\u00FF\u00FE")) {
                    421:            APPFcharset = "UTF-16LE";
                    422:            ignoreBytes = 2;
                    423:        }
                    424:        else if (s.startsWith("\u00EF\u00BB\u00BF")) {
                    425:            APPFcharset = "UTF-8";
                    426:            ignoreBytes = 3;
                    427:        }
                    428:        else if (s.startsWith("\u0000<\u0000?")) {
                    429:            APPFcharset = "UTF-16BE";
                    430:        }
                    431:        else if (s.startsWith("<\u0000?\u0000")) {
                    432:            APPFcharset = "UTF-16LE";
                    433:        }
                    434:        else if (s.startsWith("<?xml")) {
1.69      epietrig  435:            APPFcharset = "iso-8859-1";  //to not loose any bytes 
1.54      duerst    436:        }
                    437:        else if (s.startsWith("\u004C\u006F\u00A7\u0094")) {
                    438:            APPFcharset = "CP037";  // EBCDIC
                    439:        }
1.69      epietrig  440:        else {
                    441:            APPFcharset = "iso-8859-1";  //to not loose any bytes
                    442:        }
                    443:        
1.54      duerst    444:        // convert start of xml input according to APPFcharset
                    445:        String xmlstart = null;
                    446:        try {
1.69      epietrig  447: //         System.err.println("---------------------------");
                    448: //         System.err.println("ignoreBytes="+ignoreBytes);
                    449: //         System.err.println("s="+s);
                    450: //         System.err.println("APPFcharset="+APPFcharset);
                    451: //         if (APPFcharset!=null){xmlstart = new String(s.substring(ignoreBytes).getBytes("iso-8859-1"), APPFcharset);}
                    452: //         else {xmlstart=new String(s.substring(ignoreBytes).getBytes("iso-8859-1"));APPFcharset = "UTF-8";}
1.54      duerst    453:            xmlstart = new String(s.substring(ignoreBytes).getBytes("iso-8859-1"), APPFcharset);
                    454:        } catch (UnsupportedEncodingException e) {
                    455:            throw new getRDFException("Unsupported encoding '"+APPFcharset+"'.");
                    456:        }
                    457:        RE r;
                    458:        try {
                    459:            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._]|-)*)\\3");
                    460:        } catch (RESyntaxException res) {
                    461:            throw new getRDFException("Wrong regular expression syntax.");
                    462:        }
                    463:        // r.setMatchFlags(MATCH_NORMAL | MATCH_SINGLELINE); 
                    464:        String XMLcharset = null;
                    465:        if (r.match(xmlstart) && r.getParenStart(0)==0)
                    466:            XMLcharset = r.getParen(4);
                    467:        if (HTTPcharset != null)
                    468:            HTTPcharset = HTTPcharset.toUpperCase(); 
                    469:        if (XMLcharset != null)
                    470:            XMLcharset = XMLcharset.toUpperCase(); 
                    471: 
                    472:        String finalCharset = null;
                    473:        if (HTTPcharset != null) { 
                    474:            if (XMLcharset != null && !HTTPcharset.equals(XMLcharset)) 
                    475:                throw new getRDFException("Charset conflict: Content-Type: "
                    476:                     + contentT+ ". XML encoding: " +  XMLcharset + ".");
                    477:            finalCharset = HTTPcharset; 
                    478:        } 
                    479:        else if (XMLcharset != null) 
                    480:            finalCharset = XMLcharset;
                    481:        if ((finalCharset != null && finalCharset.equals("UTF-16")) ||
                    482:                (finalCharset == null && APPFcharset.startsWith("UTF-16")))
                    483:            if (ignoreBytes == 2)
                    484:                finalCharset = APPFcharset;  // use correct endianness
                    485:            else
                    486:                throw new getRDFException("Illegal XML: UTF-16 without BOM.");
                    487:        if (finalCharset == null)
                    488:            finalCharset = "UTF-8";
                    489: 
                    490:        try {
                    491:            bis.reset();                 // move back to start of stream 
                    492:            bis.skip(ignoreBytes);       // skip BOM 
                    493:        } catch (IOException e) {
                    494:            throw new getRDFException("IOException while resetting stream.");
                    495:        }
                    496: 
                    497:        InputStreamReader isr = null; 
                    498:        try {
                    499:            isr = new InputStreamReader(bis, finalCharset); 
                    500:        } catch (UnsupportedEncodingException e) {
                    501:            throw new getRDFException("Unsupported encoding '"+finalCharset+"'.");
                    502:        }
1.76    ! epietrig  503:        StringBuffer sb=new StringBuffer("");
        !           504:        int bytenum=0;
        !           505:        try {// read whole file as characters
1.54      duerst    506:            int c;
                    507:            while ((c = isr.read()) != -1) {
                    508:                sb.append((char)c);
1.76    ! epietrig  509:                bytenum++;
1.54      duerst    510:            }
1.76    ! epietrig  511:        } 
        !           512:        catch (IOException e){
        !           513:            throw new getRDFException("Undecodable data when reading URI at byte "+bytenum+" using encoding '"+finalCharset+"'."+" Please check encoding and encoding declaration of your document.");
1.54      duerst    514:        }
1.76    ! epietrig  515:        // todo: fix encoding parameter in xml pseudo-PI
1.54      duerst    516:        return sb.toString();
1.1       barstow   517:     }
                    518: 
                    519:     /*
1.4       barstow   520:      * Copy the given string of RDF to a file in the given directory.
                    521:      * This is only done if the servlet is explictly asked to save
                    522:      * the RDF to a file.
1.1       barstow   523:      *
1.14      barstow   524:      *@param tmpDir the file's directory
1.1       barstow   525:      *@param rdf the string of RDF
                    526:      */
                    527:     private void copyRDFStringToFile(String tmpDir, String rdf) 
                    528:     {
                    529:         try {
                    530:             // Generate a unique file name 
                    531:             File tmpFile = createTempFile(tmpDir, TMP_FILE_PREFIX, SUFFIX_RDF);
                    532:             if (tmpFile == null) {
                    533:                 // Not really a critical error, just return
                    534:                 return;
                    535:             }
                    536: 
                    537:             // Create a PrintWriter for the GraphViz consumer
                    538:             FileWriter fw = new FileWriter(tmpFile);
                    539:             PrintWriter pw = new PrintWriter(fw);
                    540: 
                    541:             pw.println(rdf);
                    542:             pw.close();
                    543:         } catch (Exception e) {
1.4       barstow   544:             System.err.println(SERVLET_NAME + ": error occured trying to save RDF to file '" + tmpDir + TMP_FILE_PREFIX + SUFFIX_RDF + "'.");
1.1       barstow   545:             return;
                    546:         }
                    547:     }
                    548: 
                    549:     /*
                    550:      * Given the graph's format option, return either the corresponding
                    551:      * command line option for that option or the file name suffix for
                    552:      * the graph option.  For example GIF files have ".gif" for its
                    553:      * suffix and GraphViz uses "-Tgif" for the command line.
                    554:      *
1.69      epietrig  555:      * NOTE: default is PNG.
1.1       barstow   556:      *
                    557:      *@param graphFormat the graph's output format
                    558:      *@param suffix.  If true, the name returned is for the graph's
                    559:      * file name suffix; otherwise, the name returned is for the
                    560:      * graph's command line option.
                    561:      *@return the suffix to use for the graph's output file
                    562:      */
                    563:     private String getFormatName(String graphFormat, boolean suffix) {
                    564: 
                    565:         String name = (suffix) ? "." : "-T";
                    566: 
1.4       barstow   567:         if (graphFormat.equals(FORMAT_PNG_EMBED))   return name + NAME_PNG;
                    568:         if (graphFormat.equals(FORMAT_PNG_LINK))    return name + NAME_PNG;
1.69      epietrig  569:         if (graphFormat.equals(FORMAT_GIF_EMBED))   return name + NAME_GIF;
                    570:         if (graphFormat.equals(FORMAT_GIF_LINK))    return name + NAME_GIF;
1.4       barstow   571:         if (graphFormat.equals(FORMAT_SVG_LINK))    return name + NAME_SVG;
1.71      epietrig  572:        if (graphFormat.equals(FORMAT_SVG_EMBED))   return name + NAME_SVG;
                    573:         if (graphFormat.equals(FORMAT_ISV_ZVTM))    return name + NAME_SVG;
1.4       barstow   574:         if (graphFormat.equals(FORMAT_PS_LINK))     return name + NAME_PS;
                    575:         if (graphFormat.equals(FORMAT_HP_GL_LINK))  return name + NAME_HPGL;
1.1       barstow   576:         if (graphFormat.equals(FORMAT_HP_PCL_LINK)) return name + NAME_PCL;
                    577:         
1.69      epietrig  578:         return name + NAME_PNG;
1.1       barstow   579:     }
                    580: 
                    581:     /*
                    582:      * Invokes the GraphVis program to create a graph image from the
                    583:      * the given DOT data file
                    584:      *
                    585:      *@param dotFileName the name of the DOT data file
                    586:      *@param outputFileName the name of the output data file 
1.14      barstow   587:      *@param graphFormat the graph's format
1.1       barstow   588:      *@return true if success; false if any failure occurs
                    589:      */
1.8       barstow   590:     private boolean generateGraphFile(String dotFileName, 
1.4       barstow   591:        String outputFileName, String graphFormat) 
                    592:     {
1.16      barstow   593:         String environment[] = {DOTFONTPATH + "=" + m_GraphVizFontDir};
1.1       barstow   594: 
                    595:         String formatOption = getFormatName(graphFormat, false);
                    596: 
                    597:         String cmdArray[] = {m_GraphVizPath, formatOption, "-o", outputFileName, dotFileName};
                    598:         Runtime rt = Runtime.getRuntime();
                    599:         try {
                    600:             Process p = rt.exec(cmdArray, environment);
                    601:             p.waitFor();
1.10      barstow   602: 
1.1       barstow   603:         } catch (Exception e) {
                    604:             System.err.println("Error: generating OutputFile.");
                    605:             return false;
                    606:         }
                    607:         return true;
                    608:     }
                    609: 
                    610:     /*
                    611:      * Returns a parameter from a request or the parameter's default
                    612:      * value.
                    613:      *
                    614:      *@param req a Servlet request
1.14      barstow   615:      *@param param the name of the parameter
                    616:      *@param defString the string returned if the param is not found
1.1       barstow   617:      *@return if the request contains the specfied parameter its value
                    618:      *  in the request is returned; otherwise its default value is
                    619:      *  returned
                    620:      */
                    621:     private String getParameter(HttpServletRequest req, String param, 
                    622:         String defString) 
                    623:     {
                    624:         String s = req.getParameter(param);
                    625:         return (s == null) ? defString : s;
                    626:     }
                    627: 
                    628:     /*
                    629:      * If the request contains any graph-related parameters, pass them
                    630:      * to the graph consumer for handling
                    631:      *
                    632:      *@param req the response
1.14      barstow   633:      *@param pw the PrintWriter
1.1       barstow   634:      *@param consumer the GraphViz consumer
1.69      epietrig  635:      *@param bitmap true=generate a bitmap (GIF or PNG), false=generate PostScript, SVG, etc.
1.1       barstow   636:      */
1.69      epietrig  637:     private void processGraphParameters (HttpServletRequest req, PrintWriter pw,boolean bitmap)
1.1       barstow   638:     {
1.4       barstow   639:        // Print the graph header
                    640:         pw.println("digraph " + DOT_TITLE + "{ " );
1.1       barstow   641: 
                    642:         // Look for colors
1.4       barstow   643:         String nodeColor     = getParameter(req, NODE_COLOR, 
                    644:                                            DEFAULT_NODE_COLOR);
                    645:         String nodeTextColor = getParameter(req, NODE_TEXT_COLOR, 
                    646:                                            DEFAULT_NODE_TEXT_COLOR);
                    647:         String edgeColor     = getParameter(req, EDGE_COLOR, 
                    648:                                            DEFAULT_EDGE_COLOR);
                    649:         String edgeTextColor = getParameter(req, EDGE_TEXT_COLOR, 
                    650:                                            DEFAULT_EDGE_TEXT_COLOR);
                    651:         String fontSize      = getParameter(req, FONT_SIZE, 
                    652:                                            DEFAULT_FONT_SIZE);
1.1       barstow   653: 
1.65      duerst    654:         // Orientation must be either LR or TB
1.1       barstow   655:         String orientation = req.getParameter (ORIENTATION);
1.65      duerst    656:         if (orientation == null || !orientation.equals("TB"))
1.1       barstow   657:             orientation = DEFAULT_ORIENTATION;
                    658: 
                    659:         // Add an attribute for all of the graph's nodes
1.69      epietrig  660:         pw.println("node [fontname=\"" + ((bitmap) ? DEFAULT_TTF_FONT : DEFAULT_FONT) + 
                    661:                    "\",fontsize="  + fontSize +
1.7       barstow   662:                    ",color="     + nodeColor +
1.12      barstow   663:                    ",fontcolor=" + nodeTextColor + "];");
1.1       barstow   664: 
                    665:         // Add an attribute for all of the graph's edges
1.69      epietrig  666:         pw.println("edge [fontname=\"" + ((bitmap) ? DEFAULT_TTF_FONT : DEFAULT_FONT) + 
                    667:                    "\",fontsize="  + fontSize +
1.8       barstow   668:                    ",color="     + edgeColor +
                    669:                    ",fontcolor=" + edgeTextColor + "];");
1.1       barstow   670: 
                    671:         // Add an attribute for the orientation
                    672:         pw.println("rankdir=" + orientation + ";");
                    673:     }
                    674: 
                    675:     private static class SaxErrorHandler implements org.xml.sax.ErrorHandler
                    676:     { 
1.22      duerst    677:         PrintWriter out;
1.1       barstow   678:         boolean silent = false;
1.5       barstow   679:        String fatalErrors = "";
                    680:        String errors = "";
                    681:        String warnings = "";
1.69      epietrig  682:        String datatypeErrors="";
1.1       barstow   683: 
                    684:         /*
                    685:          * Constructuor for a SaxErrorHandler 
                    686:          *
1.22      duerst    687:         *@param out the servlet's PrintWriter
1.1       barstow   688:         *@param silent if false, output is suprressed
                    689:          */
1.22      duerst    690:         public SaxErrorHandler(PrintWriter out, boolean silent) 
1.1       barstow   691:         {
                    692:             this.out = out;
                    693:             this.silent = silent;
                    694:         }
                    695: 
                    696:         /*
                    697:          * Create a formatted string from the exception's message
                    698:          *
1.5       barstow   699:         *@param e the SAX Parse Exception
1.1       barstow   700:         *@return a formatted string
                    701:          */
                    702:         private static String format(org.xml.sax.SAXParseException e) 
                    703:         {
                    704:             String msg = e.getMessage();
                    705:             if (msg == null)
                    706:                 msg = e.toString();
1.70      epietrig  707:            msg = replaceString(msg,"&","&amp;");
                    708:            msg = replaceString(msg,"<","&lt;");
                    709:            msg = replaceString(msg,">","&gt;");
                    710:            msg = replaceString(msg,"\"","&quot;");
1.71      epietrig  711:            msg = replaceString(msg,"'","&apos;");
1.1       barstow   712:             return msg + "[Line = " + e.getLineNumber() + ", Column = " + e.getColumnNumber() + "]";
                    713:         }
                    714: 
                    715:         /*
                    716:          * Handle a parse error
                    717:          *
1.5       barstow   718:         *@param e the SAX Parse Exception
1.1       barstow   719:         */
                    720:         public void error(org.xml.sax.SAXParseException e) 
                    721:             throws org.xml.sax.SAXException 
                    722:         {
                    723:             if (this.silent) return;
                    724: 
1.69      epietrig  725:            if (e instanceof com.hp.hpl.jena.rdf.arp.ParseException){
                    726:                com.hp.hpl.jena.rdf.arp.ParseException pe=(com.hp.hpl.jena.rdf.arp.ParseException)e;
1.71      epietrig  727: //             if (pe.getErrorNumber()==com.hp.hpl.jena.rdf.arp.ARP.WARN_NOT_SUPPORTED && pe.getMessage().indexOf("datatyping")!=-1){
                    728: //                 datatypeErrors+=String.valueOf(pe.getLineNumber())+", ";
                    729: //             }
                    730: //             else {
1.69      epietrig  731:                    this.errors += "Error: " + format(e) + "<br />";
1.71      epietrig  732: //             }
1.69      epietrig  733:            }
                    734:            else {this.errors += "Error: " + format(e) + "<br />";}
1.1       barstow   735:         }
                    736:     
                    737:         /*
                    738:          * Handle a fatal parse error
                    739:          *
1.5       barstow   740:         *@param e the SAX Parse Exception
1.1       barstow   741:         */
                    742:         public void fatalError(org.xml.sax.SAXParseException e) 
                    743:             throws org.xml.sax.SAXException 
                    744:         {
                    745:             if (this.silent) return;
                    746: 
1.5       barstow   747:            this.fatalErrors += "FatalError: " + format(e) + "<br />";
1.1       barstow   748:         }
                    749:     
                    750:         /*
                    751:          * Handle a parse warning
                    752:          *
1.5       barstow   753:         *@param e the SAX Parse Exception
1.1       barstow   754:         */
                    755:         public void warning(org.xml.sax.SAXParseException e) 
                    756:             throws org.xml.sax.SAXException 
                    757:         {
                    758:             if (this.silent) return;
                    759: 
1.69      epietrig  760:            if (e instanceof com.hp.hpl.jena.rdf.arp.ParseException){
1.71      epietrig  761: //             com.hp.hpl.jena.rdf.arp.ParseException pe=(com.hp.hpl.jena.rdf.arp.ParseException)e;
                    762: //             if (pe.getErrorNumber()==com.hp.hpl.jena.rdf.arp.ARP.WARN_NOT_SUPPORTED && pe.getMessage().indexOf("datatyping")!=-1){
                    763: //                 datatypeErrors+=String.valueOf(pe.getLineNumber())+", ";
                    764: //             }
                    765: //             else {
1.69      epietrig  766:                    this.warnings += "Warning: " + format(e) + "<br />";
1.71      epietrig  767: //             }
1.69      epietrig  768:            }
1.71      epietrig  769:            else {this.errors += "Warning: " + format(e) + "<br />";}
1.1       barstow   770:         }
1.5       barstow   771: 
                    772:         /*
                    773:          * Return the error messages
                    774:          *
                    775:         *@return the error messages or an empty string if there are
                    776:         * no messages
                    777:         */
                    778:        public String getErrors()
                    779:        {
                    780:           return this.errors;
                    781:        }
                    782: 
1.69      epietrig  783:        public String getDatatypeErrors()
                    784:        {
                    785:           return this.datatypeErrors;
                    786:        }
                    787: 
1.5       barstow   788:         /*
                    789:          * Return the fatal error messages
                    790:          *
                    791:         *@return the fatal error messages or an empty string if there are
                    792:         * no messages
                    793:         */
                    794:        public String getFatalErrors()
                    795:        {
                    796:           return this.fatalErrors;
                    797:        }
                    798: 
                    799:         /*
                    800:          * Return the warning messages
                    801:          *
                    802:         *@return the warning messages or an empty string if there are
                    803:         * no messages
                    804:         */
                    805:        public String getWarnings()
                    806:        {
                    807:           return this.warnings;
                    808:        }
1.1       barstow   809:     } 
                    810: 
                    811:     /*
                    812:      * Generate a graph of the RDF data model
                    813:      *
1.64      duerst    814:      *@param out the servlet's output Writer
1.4       barstow   815:      *@param pw the graph file's PrintWriter
                    816:      *@param dotFile the File handle for the graph file
1.1       barstow   817:      *@param rdf the RDF text
                    818:      *@param req a Servlet request
                    819:      *@param graphFormat the graph's format
                    820:      *@param saveRDF the RDF can be cached [saved to the file system]
                    821:      *@param saveDOTFile the DOT file should be cached
                    822:      */
1.22      duerst    823:     private void generateGraph(PrintWriter out, PrintWriter pw,
1.4       barstow   824:        File dotFile, String rdf, HttpServletRequest req, String graphFormat, 
1.1       barstow   825:         boolean saveRDF, boolean saveDOTFile) 
                    826:     {
                    827:         try {
1.67      duerst    828:             out.println("<hr title='visualisation' />");
1.66      duerst    829:             out.println("<h3><a name='graph' id='graph'>" +
                    830:                         "Graph of the data model</a></h3>");
1.1       barstow   831: 
                    832:             // The temporary directory
                    833:             String tmpDir = m_ServletTmpDir;
                    834: 
                    835:             // Add the graph footer
                    836:             pw.println( " }");
                    837: 
1.4       barstow   838:             // Close the DOT input file so the GraphViz can
1.1       barstow   839:             // open and read it
                    840:             pw.close();
                    841: 
                    842:             // Generate a unique file name for the output file
                    843:             // that will be created
                    844:             String suffix = getFormatName(graphFormat, true);
                    845:             File outputFile = createTempFile(tmpDir, TMP_FILE_PREFIX, suffix);
                    846:             if (outputFile == null) {
                    847:                 out.println("Failed to create a temporary file for the graph. A graph cannot be generated.");
                    848:                 dotFile.delete();
                    849:                 return;
                    850:             }
                    851: 
                    852:             // Pass the DOT data file to the GraphViz dot program
                    853:             // so it can create a graph image of the data model
                    854:             String dotFileName = dotFile.getAbsolutePath();
                    855:             String outputFileName = outputFile.getAbsolutePath();
                    856: 
1.8       barstow   857:             if (!generateGraphFile(dotFileName, outputFileName, graphFormat)) {
1.1       barstow   858:                 out.println("An attempt to create a graph failed.");
                    859:                 dotFile.delete();
                    860:                 outputFile.delete();
                    861:                 return;
                    862:             }
                    863:             // Handle the DOT file
                    864:             if (saveDOTFile) {
                    865:                 // Make the DOT file link'able if so requested
                    866:                 String dotPath = SERVLET_NAME + SUFFIX_TMP_DIR + 
                    867:                                  File.separator + dotFile.getName();
                    868:                 out.println("<a href=\"" + dotPath + "\">Download the DOT file.</a><br /><br />");
                    869:             }
                    870:             else {
                    871:                 // Delete it ...
                    872:                 dotFile.delete();
                    873:             }
                    874: 
                    875:             // NOTE: Cannot delete the output file here because its
                    876:             // pathname is returned to the client
                    877:             String imagePath = SERVLET_NAME + SUFFIX_TMP_DIR + File.separator + 
                    878:                                outputFile.getName();
                    879: 
                    880:             // Handle the embedded image formats first
                    881:             if (graphFormat.equals(FORMAT_GIF_EMBED) ||
                    882:                 graphFormat.equals(FORMAT_PNG_EMBED)) {
                    883:                 if (outputFile.length() > 0)
1.67      duerst    884:                     out.println("<img alt='graph representation of RDF data' " +
                    885:                                 "src='" + imagePath + "'/>");
1.1       barstow   886:                 else
                    887:                     out.println("The graph image file is empty.");
1.71      epietrig  888:             } 
                    889:            else if (graphFormat.equals(FORMAT_SVG_EMBED)){
                    890:                if (outputFile.length() > 0){
1.73      epietrig  891:                    out.println("<object type=\"image/svg+xml\" name=\"rdfsvg\" data=\"http://www.w3.org/RDF/Validator/"+imagePath+"\" width=\"640\" height=\"480\">Your browser does not support the &lt;object&gt; tag. The SVG representation of the model cannot be embedded in this page. You can use <b>SVG - link</b> or update your browser to a version supporting the &lt;object&gt; tag.</object>");
1.71      epietrig  892:                }
                    893:                 else
                    894:                     out.println("The graph image file is empty.");
                    895:            }
                    896:            else if (graphFormat.equals(FORMAT_ISV_ZVTM)){
                    897:                if (outputFile.length() > 0){
1.75      epietrig  898:                    out.println("<applet code=\"org.w3c.IsaViz.applet.IsvBrowser.class\"");
                    899:                    out.println("archive=\"lib/zvtm.jar,lib/isvapp.jar,lib/xercesImpl.jar,lib/xmlParserAPIs.jar\"");
                    900:                    out.println("width=\"640\" height=\"480\">");
                    901:                    out.println("<param name=\"type\" value=\"application/x-java-applet;version=1.4\" />");
                    902:                    out.println("<param name=\"scriptable\" value=\"false\" />");
                    903:                    out.println("<param name=\"width\" value=\"640\" />");
                    904:                    out.println("<param name=\"height\" value=\"480\" />");
                    905:                    out.println("<param name=\"svgFile\" value=\"http://www.w3.org/RDF/Validator/"+imagePath+"\" />");
1.71      epietrig  906:                    out.println("</applet>");
                    907:                }
                    908:                 else
                    909:                     out.println("The graph image file is empty.");
                    910:            }
                    911:            else {
1.1       barstow   912:                 if (outputFile.length() > 0)
                    913:                     out.println("<a href=\"" + imagePath + "\">Get/view the graph's image file (" + suffix + ").</a><br /><br />");
                    914:                 else
                    915:                     out.println("The graph image file is empty.");
                    916:             }
                    917: 
                    918:             // One last thing to do before exiting - copy the RDF to a file
                    919:             if (saveRDF)
                    920:                 copyRDFStringToFile(tmpDir, rdf);
                    921: 
                    922:         } catch (Exception e) {
                    923:             System.err.println("Exception generating graph: " + e.getMessage());
                    924:         }
                    925:     }
                    926: 
                    927:     /*
                    928:      * Search the given string for substring "key"
                    929:      * and if it is found, replace it with string "replacement"
                    930:      *
                    931:      *@param input the input string
                    932:      *@param key the string to search for
                    933:      *@param replacement the string to replace all occurences of "key"
1.3       barstow   934:      *@return if no substitutions are done, input is returned; otherwise
1.1       barstow   935:      * a new string is returned.
                    936:      */
                    937:     public static String replaceString(String input, String key, 
                    938:         String replacement) 
                    939:     {
1.3       barstow   940:         try {
                    941:             RE re = new RE(key);
                    942:             return re.subst(input, replacement);
1.53      duerst    943:         } catch (RESyntaxException e) {
1.3       barstow   944:             return input;
1.1       barstow   945:         }
                    946:     }
                    947: 
                    948:     /*
                    949:      * Print the document's header info
                    950:      *
1.64      duerst    951:      *@param out the servlet's output Writer
1.1       barstow   952:      */
1.22      duerst    953:     private void printDocumentHeader (PrintWriter out) 
1.1       barstow   954:     {
                    955:         try {
                    956: 
1.66      duerst    957:             out.println( "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" +
1.6       barstow   958:                 "      \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" +
1.56      duerst    959:                 "<html><head>\n" +
1.66      duerst    960:                 "<title>RDF Validator Results</title>\n" +
1.56      duerst    961:                 "<link href='http://www.w3.org/StyleSheets/base.css' " +
                    962:                 "rel='stylesheet' type='text/css'/>\n" +
                    963:                 "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>\n" +
                    964:                "<style type='text/css'>\n" +
1.67      duerst    965:                "  td {" +
1.6       barstow   966:                "    background:#EEEEEE;" +
                    967:                "    font-family:'courier new',courier,serif;" +
1.67      duerst    968:                "    border-style: solid;" +
                    969:                 "    border-width: 1px;" +
                    970:                 "    border-color: black;" +
                    971:                 "    padding: 2px;" +
                    972:                "  }" +
                    973:                 "  table {" +
                    974:                "    border-style: solid;" +
                    975:                 "    border-width: 1px;" +
                    976:                 "    border-color: black;" +
1.6       barstow   977:                "  }" +
1.56      duerst    978:                "</style>\n" +
                    979:                 "</head>\n" +
1.66      duerst    980:                 "<body>\n" +
                    981:                 "<h1><a href='http://www.w3.org/'><img\n" +
                    982:                 "src='http://www.w3.org/Icons/WWW/w3c_home' alt='W3C' border='0'\n" +
                    983:                 "    height='48' width='72' /></a>\n" +
                    984:                 "RDF Validation Results\n" +
1.71      epietrig  985: //                      "<p>classpath="+System.getProperty("java.class.path")+"</p>"+
1.66      duerst    986:                 "<a href='http://www.w3.org/RDF/'\n" +
                    987:                 "    title='RDF Resource Description Framework'><img border='0'\n" +
                    988:                 "    src='http://www.w3.org/RDF/icons/rdf_powered_button.48'\n" +
                    989:                 "    alt='RDF Resource Description Framework Powered Icon' /></a></h1>\n" +
                    990:                "<p><a href='#source'>Source</a> | " +
                    991:                 "<a href='#triples'>Triples</a> | " +
                    992:                 "<a href='#messages'>Messages</a> | " +
                    993:                 "<a href='#graph'>Graph</a> | " +
1.69      epietrig  994:                 "<a href='#feedback'>Feedback</a> | " +
                    995:                 "<a href='http://www.w3.org/RDF/Validator/'>Back to Validator Input</a></p>");
1.1       barstow   996: 
                    997:         } catch (Exception e) {
1.8       barstow   998:             System.err.println("Exception (printDocumentHeader): " + e.getMessage());
1.1       barstow   999:         }
                   1000:     }
                   1001: 
                   1002:     /*
                   1003:      * Print the rdf listing
                   1004:      *
1.64      duerst   1005:      *@param out the servlet's output Writer
1.1       barstow  1006:      *@param rdf the RDF code
1.14      barstow  1007:      *@param needCR if true, add a CarriageReturn to the output; if false,
                   1008:      * do not add it
1.1       barstow  1009:      */
1.22      duerst   1010:     private void printListing (PrintWriter out, String rdf, 
1.1       barstow  1011:         boolean needCR) 
                   1012:     {
                   1013:         try {
1.67      duerst   1014:             out.println("<hr title='original source' />" +
1.66      duerst   1015:                         "<h3><a name='source' id='source'>" +
                   1016:                        "The original RDF/XML document</a></h3>" +
1.8       barstow  1017:                         "<pre>");
1.1       barstow  1018: 
1.57      duerst   1019:             String s = replaceString(rdf, "&", "&amp;");
1.59      duerst   1020:             s = replaceString(s, "<", "&lt;");
1.1       barstow  1021:             
                   1022:             // Now output the RDF one line at a time with line numbers
                   1023:             int lineNum = 1;
                   1024:             int nl = 0;
                   1025:             String terminator = needCR?"\n":"";
                   1026:             do {
                   1027:                 String tok;
                   1028:                 nl = s.indexOf('\n');
                   1029:                 if ( nl == -1 ) {
                   1030:                     tok = s;
                   1031:                 } else {
                   1032:                     tok = s.substring(0,nl);
                   1033:                     s = s.substring(nl+1);
                   1034:                 }
1.8       barstow  1035:                 out.print("<a name=\"" + lineNum + "\">" + lineNum +
                   1036:                           "</a>: " + tok + terminator);
1.1       barstow  1037:                 lineNum++;
                   1038:             } while ( nl != -1 );
                   1039: 
                   1040:             out.println("</pre>");
                   1041:         } catch (Exception e) {
1.8       barstow  1042:             System.err.println("Exception (printListing): " + e.getMessage());
1.1       barstow  1043:         }
                   1044:     }
                   1045: 
                   1046:     /*
                   1047:      * Print the header for the triple listing
                   1048:      *
1.64      duerst   1049:      *@param out the servlet's output Writer
1.14      barstow  1050:      *@param nTriples if true, output is N-Triples syntax
1.1       barstow  1051:      */
1.22      duerst   1052:     private void printTripleTableHeader (PrintWriter out, boolean nTriples) 
1.1       barstow  1053:     {
                   1054:         try {
                   1055:             if (nTriples) {
1.66      duerst   1056:                 out.println("<h3><a name='triples' id='triples'>" +
                   1057:                    "Triples of the Data Model in " +
1.6       barstow  1058:                    "<a href=\"http://www.w3.org/2001/sw/RDFCore/ntriples/\">" +
1.66      duerst   1059:                    "N-Triples</a> Format (Sub, Pred, Obj)</a></h3>" +
1.6       barstow  1060:                    "<pre>");
1.1       barstow  1061:             } else {
1.67      duerst   1062:                 out.println("<hr title='triples' />");
1.66      duerst   1063:                 out.println("<h3><a name='triples' id='triples'>" +
                   1064:                             "Triples of the Data Model</a></h3>");
1.67      duerst   1065:                 out.println("<table frame='border' rules='all'><tr>" +
1.1       barstow  1066:                            "<td><b>Number</b></td>" +
                   1067:                            "<td><b>Subject</b></td>" +
                   1068:                            "<td><b>Predicate</b></td>" +
                   1069:                            "<td><b>Object</b></td>" +
                   1070:                            "</tr>");
                   1071:             }
                   1072:         } catch (Exception e) {
1.8       barstow  1073:             System.err.println("Exception (printTripleTableHeader): " + e.getMessage());
1.1       barstow  1074:         }
                   1075:     }
                   1076: 
                   1077:     /*
                   1078:      * Print the footer info for the triple listing
                   1079:      *
1.64      duerst   1080:      *@param out the servlet's output Writer
1.14      barstow  1081:      *@param nTriples if true, output is N-Triples syntax
1.1       barstow  1082:      */
1.22      duerst   1083:     private void printTripleTableFooter (PrintWriter out, 
1.1       barstow  1084:         boolean nTriples) 
                   1085:     {
                   1086:         try {
                   1087:             if (nTriples)
                   1088:                 out.println("</pre>");
                   1089:             else
                   1090:                 out.println("</table>");
                   1091:         } catch (Exception e) {
1.8       barstow  1092:             System.err.println("Exception (printTripleTableFooter): " + e.getMessage());
1.1       barstow  1093:         }
                   1094:     }
                   1095:     
                   1096:     /*
                   1097:      * Print the document's footer info
                   1098:      *
1.64      duerst   1099:      *@param out the servlet's output Writer
1.1       barstow  1100:      *@param rdf the RDF code
                   1101:      */
1.22      duerst   1102:     private void printDocumentFooter (PrintWriter out, String rdf) 
1.1       barstow  1103:     {
                   1104:         try {
                   1105: 
1.8       barstow  1106:             String s;
                   1107: 
1.67      duerst   1108:             s = "<hr title='Problem reporting' />" +
1.66      duerst   1109:                 "<h3><a name='feedback' id='feedback'>Feedback</a></h3>" +
1.8       barstow  1110:                 "<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>" +
                   1111:                 "<form enctype='text/plain' method='post' action='mailto:" + MAIL_TO + "'>" +
1.9       barstow  1112:                 "<textarea cols='60' rows='4' name='report'></textarea>";
1.8       barstow  1113:             out.println(s);
1.1       barstow  1114: 
1.70      epietrig 1115:            out.println("<input type='hidden' name='RDF' value=\"&lt;?xml version=&quot;1.0&quot;&gt;");
1.9       barstow  1116: 
1.1       barstow  1117:             // The listing is being passed as a parameter so the '<' 
                   1118:             // and '"' characters must be replaced with &lt; and &quot, 
                   1119:             // respectively
                   1120:             if (rdf != null) {
1.9       barstow  1121:                 String s1;
1.61      duerst   1122:                s1 = replaceString(rdf, "&",  "&amp;");
                   1123:                 s1 = replaceString(s1,  "<",  "&lt;");
1.11      barstow  1124:                 s1 = replaceString(s1,  ">",  "&gt;");
1.9       barstow  1125:                 s1 = replaceString(s1,  "\"", "&quot;");
                   1126:                 out.println(s1);
1.1       barstow  1127:             }
1.61      duerst   1128:             out.println("\" />");
1.1       barstow  1129: 
1.61      duerst   1130:             out.println("<input type='submit' value='Submit problem report' />" +
1.75      epietrig 1131:                         "</form>");
1.1       barstow  1132: 
1.69      epietrig 1133:            s=  "<p><a href='#source'>Source</a> | " +
                   1134:                 "<a href='#triples'>Triples</a> | " +
                   1135:                 "<a href='#messages'>Messages</a> | " +
                   1136:                 "<a href='#graph'>Graph</a> | " +
                   1137:                 "<a href='#feedback'>Feedback</a> | " +
                   1138:                 "<a href='http://www.w3.org/RDF/Validator/'>Back to Validator Input</a></p>";
                   1139: 
                   1140:            out.println(s);
1.75      epietrig 1141:            out.println("</body></html>");
1.69      epietrig 1142: 
1.1       barstow  1143:         } catch (Exception e) {
1.8       barstow  1144:             System.err.println("Exception (printDocumentFooter): " + e.getMessage());
1.1       barstow  1145:         }
                   1146:     }
                   1147: 
                   1148:     /*
1.71      epietrig 1149:      * Create a formatted string from the exception's message
                   1150:      *
                   1151:      *@param e any exception other than a SAXParseException
                   1152:      *@return a formatted string
                   1153:      */
                   1154:     private static String formatOtherThanSAXParseEx(Exception e)
                   1155:     {
                   1156:        String msg = e.getMessage();
                   1157:        if (msg == null)
                   1158:            msg = e.toString();
                   1159:        msg = replaceString(msg,"&","&amp;");
                   1160:        msg = replaceString(msg,"<","&lt;");
                   1161:        msg = replaceString(msg,">","&gt;");
                   1162:        msg = replaceString(msg,"\"","&quot;");
                   1163:        msg = replaceString(msg,"'","&apos;");
                   1164:        return msg;
                   1165:     }
                   1166: 
                   1167:     /*
1.1       barstow  1168:      * Servlet's get info method
                   1169:      */
                   1170:     public String getServletInfo () {
                   1171:        return "Servlet wrapper for the ARP RDF parser. This is revision " + REVISION;
                   1172:     }
                   1173: 
                   1174:     /*
                   1175:      * Servlet's init method
                   1176:      *
                   1177:      *@param config the servlet's configuration object
                   1178:      *@throws ServletException
                   1179:      */
                   1180:     public void init(ServletConfig config) throws ServletException 
                   1181:     {
                   1182:        super.init (config);
                   1183: 
                   1184:         // Cache the parameters
                   1185:         m_ServletTmpDir = config.getInitParameter(SERVLET_TMP_DIR);
                   1186: 
1.68      duerst   1187:         // Graph Viz paths extend from GRAPH_VIZ_ROOT unless absolute
1.1       barstow  1188:         String GraphVizRoot = config.getInitParameter(GRAPH_VIZ_ROOT);
                   1189: 
1.68      duerst   1190:         m_GraphVizPath = config.getInitParameter(GRAPH_VIZ_PATH);
                   1191:         m_GraphVizPath = (m_GraphVizPath.startsWith("/") ? "" : (GraphVizRoot + "/")) + m_GraphVizPath;
                   1192:         m_GraphVizFontDir = config.getInitParameter(GRAPH_VIZ_FONT_DIR);
                   1193:         m_GraphVizFontDir = (m_GraphVizFontDir.startsWith("/") ? "" : (GraphVizRoot + "/")) + m_GraphVizFontDir;
1.1       barstow  1194: 
1.68      duerst   1195:         if (m_ServletTmpDir == null || (GraphVizRoot == null &&
                   1196:                (!m_GraphVizPath.startsWith("/") || !m_GraphVizFontDir.startsWith("/")))) {
1.1       barstow  1197:            System.err.println (
                   1198:                 "<html>" +
                   1199:                 "<h1>Servlet Initialization Error</h1>" +
                   1200:                 "<h2>One or more of the following parameters has not been initialized: " + 
                   1201:                 SERVLET_TMP_DIR + "," + GRAPH_VIZ_ROOT + "," +
1.16      barstow  1202:                 GRAPH_VIZ_FONT_DIR + "," + GRAPH_VIZ_PATH + "." +
1.1       barstow  1203:                 "</h2>" +
                   1204:                 "</html>");
                   1205:         }
                   1206:     }
                   1207: 
                   1208:     /*
                   1209:      * Servlet's destroy info method
                   1210:      */
                   1211:     public void destroy () {
                   1212:        super.destroy ();
                   1213:     }
                   1214: 
                   1215:     /*
1.60      duerst   1216:      * Servlet's doGet info method - supported for testing
1.1       barstow  1217:      *
                   1218:      *@param req the request
                   1219:      *@param res the response
                   1220:      *@throws ServletException, IOException
                   1221:      */
                   1222:     public void doGet (HttpServletRequest req, HttpServletResponse res)
                   1223:         throws ServletException, IOException 
                   1224:     {
                   1225:         String sRDF = req.getParameter(TEXT);
                   1226:        String sURI = req.getParameter(URI);
                   1227: 
1.60      duerst   1228:         sRDF = (sRDF == null) ? "" : sRDF;
                   1229:         sURI = (sURI == null) ? "" : sURI;
1.1       barstow  1230: 
1.20      duerst   1231:        try {
1.60      duerst   1232:             sRDF = java.net.URLDecoder.decode(sRDF);
                   1233:             sURI = java.net.URLDecoder.decode(sURI);
1.20      duerst   1234:        } catch (Exception e) {
                   1235:             System.err.println("Exception: URLDecoder.decode()");
                   1236:        }
1.60      duerst   1237: 
                   1238:         process(req, res, sRDF, sURI);
1.1       barstow  1239:     }
                   1240: 
                   1241:     /*
                   1242:      * Servlet's doPost method
                   1243:      *
                   1244:      *@param req the request
                   1245:      *@param res the response
1.17      duerst   1246:      *@throws ServletException, IOException, java.io.UnsupportedEncodingException
1.1       barstow  1247:      */
                   1248:     public void doPost (HttpServletRequest req, HttpServletResponse res)
                   1249:         throws ServletException, IOException 
                   1250:     {
1.19      duerst   1251:        // String encoding = req.getCharacterEncoding();
                   1252:         // if (encoding == null) {
                   1253:        //    req.setCharacterEncoding("UTF-8");
                   1254:        // }
1.60      duerst   1255:        String sRDF = req.getParameter(TEXT);
                   1256:        String sURI = req.getParameter(URI);
1.1       barstow  1257: 
1.60      duerst   1258:         sRDF = (sRDF == null) ? "" : sRDF;
                   1259:         sURI = (sURI == null) ? "" : sURI;
1.1       barstow  1260: 
                   1261:         process(req,res,sRDF, sURI);
                   1262:     }
                   1263: 
                   1264:     /*
                   1265:      * Output a Resource in NTriples syntax
                   1266:      *
1.64      duerst   1267:      *@param out the servlet's output Writer
1.1       barstow  1268:      *@param r the Resource to output
                   1269:      */
1.22      duerst   1270:     static private void printResource(PrintWriter out, AResource r)
1.1       barstow  1271:     {
1.26      duerst   1272:         if (r.isAnonymous() )
                   1273:             out.print("_:j" + r.getAnonymousID() + " ");
                   1274:         else
                   1275:            out.print("&lt;" + r.getURI() + "&gt; ");
1.1       barstow  1276:     }
                   1277: 
                   1278:     /*
1.18      duerst   1279:      * Convert to Hex and padd left with zeroes
                   1280:      *
                   1281:      *@param in the integer to convert and padd
                   1282:      *@param in the length of the result
                   1283:      *@return the padded string
                   1284:      */
                   1285:      // MJD: is there an easier way to do this?
1.20      duerst   1286:     static private String hexPadd (int number, int length)
1.18      duerst   1287:     {
                   1288:        String t = Integer.toHexString(number).toUpperCase();
1.20      duerst   1289:        int hexlength = t.length();
1.18      duerst   1290: 
                   1291:         if ( hexlength > length ) {    // too long, truncate
                   1292:            hexlength = length;
                   1293:        }
                   1294: 
1.20      duerst   1295:        int zerolength = length - hexlength;
1.18      duerst   1296:        String r = "";
                   1297: 
                   1298:        for (int i=0; i < zerolength; i++) {
                   1299:            r += "0";
                   1300:        }
                   1301:        for (int i=0; i < hexlength; i++) {
1.24      duerst   1302:            r += t.charAt(i);
1.18      duerst   1303:        }
                   1304:        return r;
                   1305:     }
                   1306: 
                   1307:     /*
1.1       barstow  1308:      * Output a Literal in NTriples syntax
                   1309:      *
1.64      duerst   1310:      *@param out the servlet's output Writer
1.1       barstow  1311:      *@param l the Literal to output
                   1312:      */
1.22      duerst   1313:     static private void printNTripleLiteral(PrintWriter out, ALiteral l) 
1.1       barstow  1314:     {
1.28      duerst   1315:         out.print("\"");
                   1316:         char ar[] = l.toString().toCharArray();
1.1       barstow  1317: 
1.28      duerst   1318:         for (int i=0;i<ar.length;i++) {
                   1319:             switch (ar[i]) {
                   1320:                 case '\\':
                   1321:                     out.print("\\\\");
                   1322:                     break;
                   1323:                 case '"':
                   1324:                     out.print("\\\"");
                   1325:                     break;
                   1326:                 case '\n':
                   1327:                     out.print("\\n");
                   1328:                     break;
                   1329:                 case '\r':
                   1330:                     out.print("\\r");
                   1331:                     break;
                   1332:                 case '\t':
                   1333:                     out.print("\\t");
                   1334:                     break;
                   1335:                 default:
                   1336:                     if ( ar[i] >= 32 && ar[i] <= 127 )
                   1337:                         out.print(ar[i]);
                   1338:                     else if ( ar[i] < 0xD800 || ar[i] >= 0xE000)
                   1339:                        out.print("\\u" + hexPadd(ar[i], 4) );
                   1340:                    else  {  // deal with surrogates
                   1341:                             // check for correct surrogate pair
                   1342:                              // this code should probably move somewhere else:
                   1343:                              // check when we get the input
                   1344:                         if ( ar[i] >= 0xDC00 ) {
                   1345:                            out.print("{{{error: lone low surrogate}}}");
1.18      duerst   1346:                        }
1.28      duerst   1347:                        else if ( ++i >= ar.length ) {
                   1348:                             out.print("{{{error: lone surrogate at end of string}}}");
                   1349:                        }
                   1350:                        else if ( ar[i] < 0xDC00 || ar[i] >= 0xE000 ) {
                   1351:                            out.print("{{{error: high surrogate not followed by low surrogate}}}");
                   1352:                        }
                   1353:                        // no errors, actually print
                   1354:                        else {
                   1355:                            int scalarvalue = 0x10000 + (ar[i-1] * 1024) + ar[i];
                   1356:                            out.print("\\U" + hexPadd(scalarvalue, 8) );
                   1357:                        }
                   1358:                    }
1.1       barstow  1359:             }
1.28      duerst   1360:         }
                   1361:         out.print("\" ");
1.1       barstow  1362:     }
                   1363: 
                   1364:     /*
                   1365:      * Control point for outputing an triple in NTriple syntax
                   1366:      *
1.64      duerst   1367:      *@param out the servlet's output Writer
1.1       barstow  1368:      *@param subj the subject
                   1369:      *@param pred the predicate
                   1370:      *@param objRes the object as a Resource (may be null)
                   1371:      *@param objLit the object as a Literal (may be null)
                   1372:      */
1.22      duerst   1373:     static private void printNTriple(PrintWriter out, AResource subj, 
1.1       barstow  1374:         AResource pred, AResource objRes, ALiteral objLit) 
                   1375:     {
1.27      duerst   1376:         printResource(out, subj);
                   1377:         printResource(out, pred);
                   1378:         if (objRes != null)
                   1379:             printResource(out, objRes);
                   1380:         else
                   1381:             printNTripleLiteral(out, objLit);
                   1382:         out.println(".");
1.1       barstow  1383:     }
                   1384: 
                   1385:     /*
                   1386:      * Create a HTML anchor from the URI or anonNode of the
                   1387:      * given Resource
                   1388:      *
1.14      barstow  1389:      *@param r the Resource
1.1       barstow  1390:      *@return the string as an HTML anchor
                   1391:      */
                   1392:     static private String addAnchor(AResource r) 
                   1393:     {
                   1394:         if (r.isAnonymous())
1.14      barstow  1395:             return ANON_NODE + r.getAnonymousID();
1.1       barstow  1396:         else
                   1397:             return "<a href='" + r.getURI() + "'>" + r.getURI() + "</a>";
                   1398:     }
                   1399: 
                   1400:     /*
                   1401:      * Output a triple as a row in HTML
                   1402:      *
1.64      duerst   1403:      *@param out the servlet's output Writer
1.1       barstow  1404:      *@param subj the subject
                   1405:      *@param pred the predicate
                   1406:      *@param objRes the object as a Resource (may be null)
                   1407:      *@param objLit the object as a Literal (may be null)
                   1408:      *@param num the statement number
                   1409:      */
1.22      duerst   1410:     static private void printTableRow(PrintWriter out, AResource subj, 
1.1       barstow  1411:         AResource pred, AResource objRes, ALiteral objLit, int num) 
                   1412:     {
1.27      duerst   1413:         out.println("<tr><td>" + num + "</td>");
                   1414:         out.println("<td>" + addAnchor(subj) + "</td>");
                   1415:         out.println("<td>" + addAnchor(pred) + "</td>");
                   1416:         if (objRes != null)
                   1417:             out.println("<td>" + addAnchor(objRes) + "</td>");
                   1418:         else {
                   1419:             out.println("<td>");
                   1420:             String s1 = objLit.toString().trim();
                   1421:             s1 = replaceString(s1, "<", "&lt;");
                   1422:             s1 = replaceString(s1, ">", "&gt;");
1.74      epietrig 1423:             s1 = replaceString(s1, "&", "&amp;");
                   1424:            s1 = "&quot;"+s1+"&quot;";
                   1425:            if (objLit.getLang()!=null && objLit.getLang().length()>0){//add language info if it exists
                   1426:                s1+="@"+objLit.getLang();
                   1427:            }
                   1428:            if (objLit.getDatatypeURI()!=null){//add datatype info if it exists
                   1429:                String s3=objLit.getDatatypeURI();
                   1430:                s3 = replaceString(s3, "<", "&lt;");
                   1431:                s3 = replaceString(s3, ">", "&gt;");
                   1432:                s3 = replaceString(s3, "&", "&amp;");
                   1433:                if (s3.length()>0){
                   1434:                    s1+="^^"+s3;
                   1435:                }
                   1436:            }
1.27      duerst   1437:             out.println(s1);
                   1438:             out.println("</td>");
                   1439:         }
                   1440:         out.println("</tr>");
1.1       barstow  1441:     }
                   1442: 
1.4       barstow  1443:     private static class SH implements StatementHandler 
1.1       barstow  1444:     {
1.22      duerst   1445:         PrintWriter out;
1.12      barstow  1446:         PrintWriter pw;
1.1       barstow  1447:         boolean isNTriples;
1.12      barstow  1448:         boolean printTriples;
                   1449:         boolean printGraph;
                   1450:         boolean anonNodesEmpty;
1.14      barstow  1451:         int numStatements;
                   1452:         int numLiterals;
                   1453:        Hashtable subjects;
                   1454:        int numSubjects;
1.71      epietrig 1455:        String gFormat;
1.1       barstow  1456:   
                   1457:         /*
1.4       barstow  1458:          * Constructuor for the StatementHandler.  The primary
                   1459:         * responsiblitly is to cache init variables
1.1       barstow  1460:          *
1.64      duerst   1461:         *@param out the servlet's output Writer
1.4       barstow  1462:         *@param pw the Dot file's PrintWriter
1.1       barstow  1463:         *  syntax; otherwise use HTML syntax
1.12      barstow  1464:         *@param isNTriples if true, output using the NTriples
                   1465:         *@param printTriples if true, print the triples
                   1466:         *@param printGraph if true, create the graph file
                   1467:         *@param printGraph if true, anonomyous nodes should be empty
1.1       barstow  1468:         */
1.22      duerst   1469:         public SH(PrintWriter out, PrintWriter pw, boolean isNTriples, 
1.71      epietrig 1470:             boolean printTriples, boolean printGraph, boolean anonNodesEmpty,String graphFormat)
1.1       barstow  1471:         {
                   1472:             this.out = out;
1.12      barstow  1473:             this.pw = pw;
1.1       barstow  1474:             this.isNTriples = isNTriples;
1.12      barstow  1475:             this.printTriples = printTriples;
                   1476:             this.printGraph = printGraph;
                   1477:             this.anonNodesEmpty = anonNodesEmpty;
1.14      barstow  1478: 
                   1479:             this.numStatements = 0;
                   1480:             this.numLiterals = 0;
                   1481: 
                   1482:            this.subjects = new Hashtable();
                   1483:            this.numSubjects = 0;
1.71      epietrig 1484:            this.gFormat=graphFormat;
1.4       barstow  1485:         }
                   1486: 
                   1487:         /*
                   1488:          * Generic handler for a Resource/Resource/Resource triple (S/P/O).
                   1489:         * Dispatches to the methods that do the real work.
                   1490:          *
                   1491:         *@param subj the subject
                   1492:         *@param pred the predicate
                   1493:         *@param obj the object (as a Resource)
                   1494:         */
                   1495:         public void statement(AResource subj, AResource pred, AResource obj) 
                   1496:         {
1.72      epietrig 1497:            if (!ARPServlet.AT_LEAST_ONE_TRIPLE){ARPServlet.AT_LEAST_ONE_TRIPLE=true;}
1.12      barstow  1498:            if (printTriples)
                   1499:                 statementResource(subj, pred, obj);
                   1500:            if (printGraph)
                   1501:                statementDotResource(subj, pred, obj);
1.4       barstow  1502:         }
                   1503: 
                   1504:         /*
                   1505:          * Generic handler for a Resource/Resource/Resource triple (S/P/O).
                   1506:         * Dispatches to the methods that do the real work.
                   1507:          *
                   1508:         *@param subj the subject
                   1509:         *@param pred the predicate
                   1510:         *@param obj the object (as a Literal)
                   1511:         */
                   1512:         public void statement(AResource subj, AResource pred, ALiteral lit) 
                   1513:         {
1.72      epietrig 1514:            if (!ARPServlet.AT_LEAST_ONE_TRIPLE){ARPServlet.AT_LEAST_ONE_TRIPLE=true;}
1.13      barstow  1515:             numLiterals++;
1.12      barstow  1516:            if (printTriples)
                   1517:                 statementLiteral(subj, pred, lit);
                   1518:            if (printGraph)
                   1519:                 statementDotLiteral(subj, pred, lit);
1.1       barstow  1520:         }
                   1521: 
                   1522:         /*
                   1523:          * Handler for a Resource/Resource/Resource triple (S/P/O)
                   1524:         * Outputs the given triple using NTriples or HTML syntax.
                   1525:          *
                   1526:         *@param subj the subject
                   1527:         *@param pred the predicate
                   1528:         *@param obj the object (as a Resource)
                   1529:         */
1.4       barstow  1530:         public void statementResource(AResource subj, AResource pred, AResource obj) 
1.1       barstow  1531:         {
                   1532:             numStatements++;
                   1533: 
                   1534:             if (this.isNTriples)
                   1535:                 printNTriple(out, subj, pred, obj, null);
                   1536:             else
                   1537:                 printTableRow(out, subj, pred, obj, null, this.numStatements);
                   1538:         }
1.4       barstow  1539: 
1.1       barstow  1540:         /*
                   1541:          * Handler for a Resource/Resource/Literal triple (S/P/O)
                   1542:         * Outputs the given triple using NTriples or HTML syntax.
                   1543:          *
                   1544:         *@param subj the subject
                   1545:         *@param pred the predicate
                   1546:         *@param obj the object (as a Literal)
                   1547:         */
1.4       barstow  1548:         public void statementLiteral(AResource subj, AResource pred, ALiteral lit) 
1.1       barstow  1549:         {
                   1550:             numStatements++;
                   1551: 
                   1552:             if (this.isNTriples)
                   1553:                 printNTriple(out, subj, pred, null, lit);
                   1554:             else
                   1555:                 printTableRow(out, subj, pred, null, lit, this.numStatements);
                   1556:         }
1.4       barstow  1557: 
1.12      barstow  1558:        /* 
                   1559:         * Print the first part of a triple's Dot file.  See below for
                   1560:         * more info.  This is the same regardless if the triple's
                   1561:         * object is a Resource or a Literal
                   1562:         *
                   1563:         *@param subj the subject
                   1564:         */
                   1565:         public void printFirstPart(AResource subj) 
                   1566:        {
1.14      barstow  1567:             if (subj.isAnonymous()) {
1.12      barstow  1568:                if (this.anonNodesEmpty) {
1.14      barstow  1569:                    Integer n = (Integer) subjects.get(subj.getAnonymousID());
                   1570:                    if (n == null) {
                   1571:                        this.numSubjects++;
                   1572:                        subjects.put(subj.getAnonymousID(), new Integer(this.numSubjects));
1.71      epietrig 1573:                         this.pw.println("\"" + ANON_NODE + subj.getAnonymousID() + "\" [label=\"   \"];");
1.14      barstow  1574:                    }
1.12      barstow  1575:                }
1.14      barstow  1576:                 this.pw.print("\"" + ANON_NODE + subj.getAnonymousID());
1.12      barstow  1577:             } else {
1.71      epietrig 1578:                if (gFormat!=null && gFormat.equals(FORMAT_ISV_ZVTM)){
                   1579:                    this.pw.println("\"" + subj.getURI() + "\" [fontcolor=\""+Float.toString(ARPServlet.resTBh)+","+Float.toString(ARPServlet.resTBs)+","+Float.toString(ARPServlet.resTBv)+"\",URL=\"" +subj.getURI() + "\"];");
                   1580:                }
                   1581:                else {
                   1582:                    this.pw.println("\"" + subj.getURI() + "\" [URL=\"" +subj.getURI() + "\"];");
                   1583:                }
1.12      barstow  1584:                 this.pw.print("\"" + subj.getURI());
                   1585:             }
                   1586:        }
                   1587: 
1.4       barstow  1588:         /*
                   1589:          * Handler for a Resource/Resource/Resource triple (S/P/O).
                   1590:         * Outputs the given triple using Dot syntax.
1.12      barstow  1591:         *
                   1592:         * Each triple will be output in three lines of DOT code as
                   1593:         * follows (not including the complication of anon nodes 
                   1594:         * and the possiblity that the anon nodes may be named 
                   1595:         * with an empty string):
                   1596:         *
                   1597:         *   1. "<subject>" [URL="<subject">];
                   1598:         *   2. "<subject>" -> "<object>" [label="<predicate>",URL="<predicate>"];
                   1599:         *   3. "<object>"  [URL="<object>"];
1.4       barstow  1600:          *
                   1601:         *@param subj the subject
                   1602:         *@param pred the predicate
                   1603:         *@param obj the object (as a Resource)
                   1604:         */
                   1605:         public void statementDotResource(AResource subj, AResource pred, AResource obj) 
                   1606:         {
                   1607:            if (this.pw == null) return;
                   1608: 
1.12      barstow  1609:            printFirstPart(subj);
                   1610:            
                   1611:             this.pw.print("\" -> ");
1.4       barstow  1612: 
1.7       barstow  1613:             if (obj.isAnonymous()) {
1.12      barstow  1614:                if (this.anonNodesEmpty) {
1.71      epietrig 1615:                    if (gFormat!=null && gFormat.equals(FORMAT_ISV_ZVTM)){
                   1616:                        this.pw.println("\"" + ANON_NODE +obj.getAnonymousID() + "\" [fontcolor=\""+Float.toString(ARPServlet.prpTh)+","+Float.toString(ARPServlet.prpTs)+","+Float.toString(ARPServlet.prpTv)+"\",label=\"" + pred.getURI() + "\",URL=\"" + pred.getURI() + "\"];");
                   1617:                    }
                   1618:                    else {
                   1619:                        this.pw.println("\"" + ANON_NODE +obj.getAnonymousID() + "\" [label=\"" + pred.getURI() + "\",URL=\"" + pred.getURI() + "\"];");
                   1620:                    }
1.12      barstow  1621:                } else {
1.71      epietrig 1622:                    if (gFormat!=null && gFormat.equals(FORMAT_ISV_ZVTM)){
                   1623:                        this.pw.println("\"" + ANON_NODE + obj.getAnonymousID() + "\" [fontcolor=\""+Float.toString(ARPServlet.prpTh)+","+Float.toString(ARPServlet.prpTs)+","+Float.toString(ARPServlet.prpTv)+"\",label=\"" + pred.getURI() + "\",URL=\"" +pred.getURI() + "\"];");
                   1624:                    }
                   1625:                    else {
                   1626:                        this.pw.println("\"" + ANON_NODE + obj.getAnonymousID() + "\" [label=\"" + pred.getURI() + "\",URL=\"" +pred.getURI() + "\"];");
                   1627:                    }
1.12      barstow  1628:                }
1.7       barstow  1629:             } else {
1.71      epietrig 1630:                if (gFormat!=null && gFormat.equals(FORMAT_ISV_ZVTM)){
                   1631:                    this.pw.println("\"" + obj.getURI() + "\" [fontcolor=\""+Float.toString(ARPServlet.prpTh)+","+Float.toString(ARPServlet.prpTs)+","+Float.toString(ARPServlet.prpTv)+"\",label=\"" +pred.getURI() + "\",URL=\"" + pred.getURI() + "\"];");
                   1632:                    this.pw.println("\"" + obj.getURI() + "\" [fontcolor=\""+Float.toString(resTBh)+","+Float.toString(resTBs)+","+Float.toString(resTBv)+"\",URL=\"" +obj.getURI() + "\"];");
                   1633:                }
                   1634:                else {
                   1635:                    this.pw.println("\"" + obj.getURI() + "\" [label=\"" +pred.getURI() + "\",URL=\"" + pred.getURI() + "\"];");
                   1636:                    this.pw.println("\"" + obj.getURI() + "\" [URL=\"" +obj.getURI() + "\"];");
                   1637:                }
1.14      barstow  1638:            }
1.4       barstow  1639:         }
                   1640: 
                   1641:         /*
                   1642:          * Handler for a Resource/Resource/Literal triple (S/P/O).
                   1643:         * Outputs the given triple using Dot syntax.
1.12      barstow  1644:         *
                   1645:         * Each triple will be output in three lines of DOT code as
                   1646:         * follows (not including the complication of anon nodes 
                   1647:         * and the possiblity that the anon nodes may be named 
                   1648:         * with an empty string):
                   1649:          *
                   1650:         *   1. "<subject>" [URL="<subject">];
                   1651:         *   2. "<subject>" -> "<literal>" [label="<predicate>",URL="<predicate>"];
                   1652:         *   3. "<literal>" [shape="box"];
1.4       barstow  1653:          *
                   1654:         *@param subj the subject
                   1655:         *@param pred the predicate
                   1656:         *@param obj the object (as a Literal)
                   1657:         */
                   1658:         public void statementDotLiteral(AResource subj, AResource pred, ALiteral lit) 
                   1659:         {
                   1660:            if (this.pw == null) return;
                   1661: 
1.12      barstow  1662:            printFirstPart(subj);  // Same as Res/Res/Res
1.4       barstow  1663: 
                   1664:             /*
                   1665:              * Before outputing the object (Literal) do the following:
                   1666:              *
                   1667:              * o GraphViz/DOT cannot handle embedded line terminators characters
                   1668:              *   so they must be replaced with spaces
                   1669:              * o Limit the number of chars to make the graph legible
                   1670:              * o Escape double quotes
                   1671:              */
                   1672:             String s1 = new String(lit.toString());
                   1673:             s1 = s1.replace('\n', ' ');
                   1674:             s1 = s1.replace('\f', ' ');
                   1675:             s1 = s1.replace('\r', ' ');
                   1676:             if (s1.indexOf('"') != -1)
                   1677:                 s1 = replaceString(s1, "\"", "\\\"");
                   1678: 
                   1679:             // Anything beyond 80 chars makes the graph too large
                   1680:             String tmpObject;
                   1681:             if (s1.length() >= 80)
                   1682:                 tmpObject = s1.substring(0, 80) + " ...";
                   1683:             else
                   1684:                 tmpObject = s1.substring(0, s1.length());
                   1685: 
1.13      barstow  1686:            // Create a temporary label for the literal so that if
                   1687:            // it is duplicated it will be unique in the graph and
                   1688:            // thus have its own node.
                   1689:            String tmpName = "Literal_" + Integer.toString(this.numLiterals);
                   1690:             this.pw.print("\" -> \"" + tmpName);
1.4       barstow  1691: 
1.71      epietrig 1692:            if (gFormat!=null && gFormat.equals(FORMAT_ISV_ZVTM)){
                   1693:                this.pw.println("\" [fontcolor=\""+Float.toString(ARPServlet.prpTh)+","+Float.toString(ARPServlet.prpTs)+","+Float.toString(ARPServlet.prpTv)+"\",label=\"" + pred.getURI() + "\",URL=\""    + pred.getURI() + "\"];");
                   1694:                this.pw.println("\"" + tmpName + "\" [fontcolor=\""+Float.toString(litTBh)+","+Float.toString(litTBs)+","+Float.toString(litTBv)+"\",shape=box,label=\"" + tmpObject + "\"];");
                   1695:            }
                   1696:            else {
                   1697:                this.pw.println("\" [label=\"" + pred.getURI() + "\",URL=\""    + pred.getURI() + "\"];");
                   1698:                this.pw.println("\"" + tmpName + "\" [shape=box,label=\"" + tmpObject + "\"];");
                   1699:            }
1.4       barstow  1700:         }
                   1701:     }
                   1702: 
1.22      duerst   1703:     private void printErrorMessages(PrintWriter out, SaxErrorHandler eh)
1.5       barstow  1704:     {
1.66      duerst   1705:         try {
                   1706:             String s;
                   1707:             boolean c = true;
                   1708: 
                   1709:            out.println("<h2><a name='messages' id='messages'>" +
                   1710:                        "Validation Results</a></h2>");
                   1711: 
                   1712:             s = eh.getFatalErrors();
                   1713:             if (s != null && s.length() >= 1) {
                   1714:                 out.println("<h3>Fatal Error Messages</h3>" + s);
                   1715:                c = false;
                   1716:            }
                   1717: 
                   1718:             s = eh.getErrors();
                   1719:             if (s != null && s.length() >= 1) {
                   1720:                 out.println("<h3>Error Messages</h3>" + s);
                   1721:                c = false;
                   1722:            }
                   1723: 
                   1724:             s = eh.getWarnings();
                   1725:             if (s != null && s.length() >= 1) {
                   1726:                 out.println("<h3>Warning Messages</h3>" + s);
                   1727:                c = false;
                   1728:            }
1.5       barstow  1729: 
1.72      epietrig 1730:             if (c){
                   1731:                if (AT_LEAST_ONE_TRIPLE){
                   1732:                    out.println("<p>Your RDF document validated successfully.</p>");
                   1733:                }
                   1734:                else {
                   1735:                    out.println("<p>Error: Your document does not contain any RDF statement.</p>");
                   1736:                }
                   1737:                AT_LEAST_ONE_TRIPLE=false;
                   1738:            }
1.69      epietrig 1739: 
1.72      epietrig 1740:            /*the following should not happen anymore, as we use ARP2 which supports datatypes, but leave it there for now, just in case*/
1.69      epietrig 1741:            s = eh.getDatatypeErrors();
                   1742:            if (s != null && s.length() >= 2){//2 to prevent an arrayindexoutofbounds exception
                   1743:                out.println("<h3>Note about datatypes</h3>");
                   1744:                out.println("<p>Datatypes are used on lines "+s.substring(0,s.length()-2)+". This RDF feature is not yet supported by the RDF Validator. Literals are treated as untyped.</p>");
                   1745:            }
                   1746: 
1.5       barstow  1747:        } catch (Exception e) {
                   1748:            System.err.println(SERVLET_NAME + ": Error printing error messages.");
                   1749:        }
                   1750:     }
                   1751: 
                   1752:     /*
                   1753:      * Initialize the graph output file.  If an error occurs, this
                   1754:      * function will print an error message.
                   1755:      *
1.64      duerst   1756:      *@param out the servlet's output Writer
1.5       barstow  1757:      *@req the servlet request object
                   1758:      *@return the File object for the graph file; null if an error occurs
                   1759:      */
1.22      duerst   1760:     private File initGraphFile(PrintWriter out, 
1.4       barstow  1761:        HttpServletRequest req)
                   1762:     {
                   1763:         try {
                   1764:             // Stop if any of the parameters are missing
                   1765:             if (m_ServletTmpDir   == null || 
                   1766:                 m_GraphVizPath    == null || 
1.16      barstow  1767:                 m_GraphVizFontDir == null)
1.4       barstow  1768:            {
                   1769:                 // Put the paths in a comment in the returned content
                   1770:                 out.println("<!-- SERVLET_TMP_DIR = " + m_ServletTmpDir);
                   1771:                 out.println("GRAPH_VIZ_PATH = " + m_GraphVizPath);
                   1772:                 out.println("GRAPH_FONT_DIR  = " + m_GraphVizFontDir + " -->");
                   1773: 
1.12      barstow  1774:                 out.println("<h1>Servlet initialization failed</h1>");
                   1775:                out.println("Please send a message to <a href='mailto:" + MAIL_TO +  "'>" + MAIL_TO + "</a> and mention this problem.");
1.4       barstow  1776:                 return null;
                   1777:             } 
                   1778:        } catch (Exception e) {
                   1779:            System.err.println("Unable to create a temporary graph file. A graph cannot be generated.");
                   1780:            return null;
                   1781:        }
                   1782: 
                   1783:         File dotFile = null;
                   1784: 
1.27      duerst   1785:         // Must generate a unique file name that the DOT handler will use 
                   1786:         dotFile = createTempFile(m_ServletTmpDir, TMP_FILE_PREFIX, SUFFIX_DOT);
                   1787:         if (dotFile == null) {
                   1788:             out.println("<h1>Failed to create a temporary graph file. A graph cannot be generated.</h1>");
                   1789:             return null;
                   1790:         }
1.4       barstow  1791: 
                   1792:        return dotFile;
1.1       barstow  1793:     }
1.6       barstow  1794: 
                   1795:     /*
                   1796:      * Check if the given URI is supported or not
                   1797:      *
1.64      duerst   1798:      *@param out the servlet's output Writer
1.6       barstow  1799:      *@param uri the URI to check
                   1800:      *@return true if the URI is supported; false otherwise
                   1801:      */
1.22      duerst   1802:     private boolean isURISupported(PrintWriter out, String uri)
1.6       barstow  1803:     {
                   1804:        try {
                   1805:            if (uri.length() >= 4 && uri.substring(0,4).equalsIgnoreCase("file")) {
                   1806:                out.println("<h1>file URI Schemes are NOT Supported</h1>");
                   1807:                out.println("URIs from the 'file' URI scheme are not supported by this servlet.");
                   1808:                return false;
                   1809:            }
                   1810:         } catch (Exception e) {
                   1811:            System.err.println("Exception in isURISupported.");
                   1812:            return false;
                   1813:        }
                   1814: 
                   1815:        return true;
                   1816:     }
1.1       barstow  1817:     
                   1818:     /*
                   1819:      * Handle the servlets doGet or doPut request
                   1820:      *
                   1821:      *@param req the servlet's request
                   1822:      *@param res the servlet's response
                   1823:      *@throws SevletException, IOException
                   1824:      */
                   1825:     private void process(HttpServletRequest req, HttpServletResponse res, 
1.52      duerst   1826:         String sRDF, String sURI) throws ServletException, IOException 
1.1       barstow  1827:     {
1.12      barstow  1828:        String sSaveRDF         = req.getParameter (SAVE_RDF);
                   1829:        String sSaveDOTFile     = req.getParameter (SAVE_DOT_FILE);
                   1830:        String sNTriples        = req.getParameter (NTRIPLES);
                   1831:        String sEmbedded        = req.getParameter (EMBEDDED_RDF);
                   1832:        String sTriplesAndGraph = req.getParameter (TRIPLES_AND_GRAPH);
                   1833:        String sAnonNodesEmpty  = req.getParameter (ANON_NODES_EMPTY);
1.60      duerst   1834:        String sParse           = req.getParameter (PARSE);
1.63      duerst   1835:        String sFormat          = req.getParameter (FORMAT);
                   1836:        if (sFormat==null)
                   1837:            sFormat = DEFAULT_FORMAT;
1.12      barstow  1838: 
                   1839:         // Set the print flags
                   1840:         boolean printTriples = true;
                   1841:        boolean printGraph = true;
                   1842:        if (sTriplesAndGraph != null) {
                   1843:            if (sTriplesAndGraph.equals(PRINT_TRIPLES)) 
                   1844:                printGraph = false;
                   1845:            if (sTriplesAndGraph.equals(PRINT_GRAPH))
                   1846:                printTriples = false;
                   1847:        } 
1.1       barstow  1848: 
1.12      barstow  1849:        // Determine if printing the triples and/or graph
                   1850:         boolean anonNodesEmpty = (sAnonNodesEmpty != null) ? true : false;
1.1       barstow  1851:         boolean nTriples = (sNTriples != null) ? true : false;
1.12      barstow  1852: 
1.10      barstow  1853:         // ARP parser has embedded = true by default so if user
                   1854:         // wants embedding, must set it to false
                   1855:         boolean embedded = (sEmbedded != null) ? false : true;
1.1       barstow  1856: 
1.60      duerst   1857:         res.setContentType ("text/html;charset=utf-8");
                   1858:         PrintWriter out = res.getWriter ();
                   1859:         printDocumentHeader (out);
1.65      duerst   1860: 
1.60      duerst   1861:        boolean parseRDF = true;
                   1862:        if (sParse != null)
                   1863:             parseRDF = sParse.equals("Parse RDF");
1.65      duerst   1864:         else if (!sURI.equals(""))  // continue even if PARSE is not present
1.60      duerst   1865:             parseRDF = false;            
                   1866: 
1.65      duerst   1867:        if (parseRDF)  sURI = "";
                   1868:        else           sRDF = "";
                   1869: 
                   1870:         // getting encoding right: bad hack, but it works :-(
1.60      duerst   1871:         sRDF = new String(sRDF.getBytes("iso-8859-1"), "utf-8");
                   1872:        sURI = new String(sURI.getBytes("iso-8859-1"), "utf-8");
                   1873: 
                   1874:         if ((!parseRDF && sURI.equals("")) || (parseRDF && sRDF.equals(""))) {
                   1875:             out.println("<h1>" + (parseRDF ? "RDF" : "URI")
                   1876:                           + " was not specified.</h1>");
                   1877:            printDocumentFooter(out, null);
                   1878:             return;
                   1879:         }
                   1880: 
1.1       barstow  1881:         String xmlBase = DEFAULT_NAMESPACE;
                   1882: 
1.60      duerst   1883:         if (!sURI.equals("")) {
1.6       barstow  1884: 
                   1885:            // First check for unsupported URIs
                   1886:            if (!isURISupported(out, sURI)) {
                   1887:                 printDocumentFooter(out, null);
                   1888:                 return;
                   1889:            }
                   1890: 
1.1       barstow  1891:             xmlBase = sURI;
1.53      duerst   1892:            try {
                   1893:                sRDF = getRDFfromURI(sURI);
                   1894:                if (sRDF == null)
                   1895:                    throw new getRDFException("The URI may not exist or the server is down.@@");
                   1896:            } catch (getRDFException e) {
                   1897:                out.println("<h1>RDF Load Error</h1>");
                   1898:                out.println("An attempt to load the RDF from URI '" + sURI +
                   1899:                            "' failed.  (" + e.getMessage() + ")");
                   1900:                printDocumentFooter(out, null);
                   1901:                return;
                   1902:            }
1.1       barstow  1903:         }
1.4       barstow  1904:  
                   1905:        PrintWriter pw = null; // The writer for the graph file
1.65      duerst   1906:        OutputStreamWriter osw = null;
1.4       barstow  1907:        File dotFile = null;   // The graph file
1.63      duerst   1908:         if (printGraph) {
1.4       barstow  1909:            dotFile = initGraphFile(out, req);
                   1910:            if (dotFile == null)
                   1911:                // Assume error has been reported
                   1912:                return;
                   1913:             // Create a PrintWriter for the DOT handler
1.65      duerst   1914:            FileOutputStream fos = new FileOutputStream(dotFile);
                   1915:            if (fos != null)
                   1916:                osw = new OutputStreamWriter(fos, "utf-8");
                   1917:            if (osw != null)
                   1918:                 pw = new PrintWriter(osw);
1.4       barstow  1919:            if (pw != null)
                   1920:                 // Add the graph header
1.69      epietrig 1921:                 processGraphParameters (req, pw, (sFormat.equals(FORMAT_PNG_EMBED)) || (sFormat.equals(FORMAT_PNG_LINK)) || (sFormat.equals(FORMAT_GIF_EMBED)) || (sFormat.equals(FORMAT_GIF_LINK)));
1.4       barstow  1922:        }
                   1923: 
                   1924:        // Create the StatementHandler - it will handle triples for
                   1925:        // the table/ntriples and the graph file
1.71      epietrig 1926:         SH sh = new SH(out, pw, nTriples, printTriples, printGraph, anonNodesEmpty,sFormat);
1.4       barstow  1927: 
                   1928:         // Create the ErrorHandler 
                   1929:         SaxErrorHandler errorHandler = new SaxErrorHandler(out, false);
                   1930: 
                   1931:         // Create and initialize the parser
1.71      epietrig 1932: 
                   1933: //     System.err.println("-----------------------------------------------");
                   1934: //     System.err.println("Determining class for ARP");
                   1935: //     String arp="com.hp.hpl.jena.rdf.arp.ARP";
                   1936: //     try {
                   1937: //         Class c = Class.forName (arp);
                   1938: //         String classRes = "/"+arp.replace ('.', '/')+
                   1939: //             ".class";
                   1940: //         System.out.println ("Class "+arp+
                   1941: //                             " URL: "+c.getResource (classRes));
                   1942: //     }
                   1943: //     catch (Throwable t)
                   1944: //             {
                   1945: //                 System.out.println ("Unable to locate class "+arp);
                   1946: //             }
                   1947: 
1.4       barstow  1948:        ARP parser = new com.hp.hpl.jena.rdf.arp.ARP();
                   1949:         parser.setErrorHandler(errorHandler);
                   1950:         parser.setStatementHandler(sh);
1.10      barstow  1951:         parser.setEmbedding(embedded);
1.72      epietrig 1952:        parser.setStrictErrorMode();
1.61      duerst   1953:         printListing (out, sRDF, !parseRDF);
1.12      barstow  1954: 
                   1955:         if (printTriples)
                   1956:             printTripleTableHeader (out, nTriples);
1.1       barstow  1957: 
                   1958:         try {
1.52      duerst   1959:            StringReader  sr = new StringReader (sRDF);
1.69      epietrig 1960:            if (xmlBase!=null && xmlBase.length()>0){parser.load(sr, xmlBase);}
                   1961:            else {parser.load(sr);}
1.1       barstow  1962:         } catch (Exception ex) {
1.66      duerst   1963:            out.println ("<h1><a name='messages' id='messages'>Parser " +
                   1964:                          "Loading Error</a></h1>");
1.71      epietrig 1965:            out.println ("Exception parsing: " +formatOtherThanSAXParseEx(ex));
1.53      duerst   1966:             printDocumentFooter(out, null);
                   1967:             return;
1.1       barstow  1968:         }
                   1969: 
1.12      barstow  1970:         if (printTriples)
                   1971:             printTripleTableFooter(out, nTriples);
1.5       barstow  1972: 
                   1973:        printErrorMessages(out, errorHandler);
1.1       barstow  1974: 
1.52      duerst   1975:         res.flushBuffer();
1.12      barstow  1976:         if (sFormat != null && printGraph) {
1.4       barstow  1977:             generateGraph(out, pw, dotFile, sRDF, req, sFormat,
1.1       barstow  1978:                           (sSaveRDF != null) ? true : false,
                   1979:                           (sSaveDOTFile != null && sSaveDOTFile.equals ("on") ? true : false));
                   1980:         }
                   1981: 
                   1982: 
1.61      duerst   1983:         if (!parseRDF)
1.9       barstow  1984:             printDocumentFooter(out, null);
                   1985:         else
                   1986:             printDocumentFooter(out, sRDF);
1.1       barstow  1987:     }
                   1988: }

Webmaster