Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

XmlValidator.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2004 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Nicolas Modrzyk.
00022  * Contributor(s): 
00023  */
00024 
00025 package org.objectweb.cjdbc.common.xml;
00026 
00027 import java.io.BufferedReader;
00028 import java.io.File;
00029 import java.io.FileReader;
00030 import java.io.IOException;
00031 import java.io.InputStream;
00032 import java.io.StringReader;
00033 import java.util.ArrayList;
00034 
00035 import org.objectweb.cjdbc.common.i18n.Translate;
00036 import org.objectweb.cjdbc.common.util.Constants;
00037 import org.xml.sax.ErrorHandler;
00038 import org.xml.sax.InputSource;
00039 import org.xml.sax.SAXException;
00040 import org.xml.sax.SAXParseException;
00041 import org.xml.sax.XMLReader;
00042 import org.xml.sax.ext.LexicalHandler;
00043 import org.xml.sax.helpers.DefaultHandler;
00044 import org.xml.sax.helpers.XMLReaderFactory;
00045 
00046 /**
00047  * Validate a document and its DTD.
00048  * 
00049  * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
00050  */
00051 public class XmlValidator extends DefaultHandler
00052     implements
00053       ErrorHandler,
00054       LexicalHandler
00055 {
00056 
00057   /** XML parser. */
00058   private XMLReader parser;
00059   private String    pathToDtd;
00060   private boolean   isXmlValid = false;
00061   private boolean   isDtdValid = false;
00062   private String    xmlContent;
00063   private ArrayList errors;
00064   private ArrayList warnings;
00065 
00066   /**
00067    * Allow to use the xml validator as an external program
00068    * 
00069    * @param args the xmlfile and the dtd file
00070    * @throws Exception if fails
00071    */
00072   public static void main(String args[]) throws Exception
00073   {
00074     if (args.length < 1 || args.length > 2)
00075     {
00076       System.out.println("usage: XmlValidator [xmlFile] ([dtd]) ");
00077       System.exit(0);
00078     }
00079 
00080     String fileName = args[0];
00081     String dtdName = Constants.C_JDBC_DTD_FILE;
00082     if (args.length == 2)
00083       dtdName = args[1];
00084     else
00085       System.out.println("Using default DTD:" + Constants.C_JDBC_DTD_FILE);
00086 
00087     File dtd = null;
00088     dtd = new File(ClassLoader.getSystemResource(dtdName).getFile());
00089     File xmlFile = null;
00090     try
00091     {
00092       xmlFile = new File(ClassLoader.getSystemResource(fileName).getFile());
00093     }
00094     catch (RuntimeException e)
00095     {
00096       xmlFile = new File(fileName);
00097     }
00098 
00099     if (!dtd.exists())
00100     {
00101       System.out.println("Cannot find specified dtd");
00102       System.exit(1);
00103     }
00104     if (!xmlFile.exists())
00105     {
00106       System.out.println("Cannot find specified xml file");
00107       System.exit(1);
00108     }
00109 
00110     System.out.println("Validating:\tFile:" + xmlFile.getName() + " with dtd:"
00111         + dtd.getName());
00112 
00113     // Validate xml and dtd
00114     XmlValidator validator = new XmlValidator(dtd.getAbsolutePath(),
00115         new FileReader(xmlFile));
00116 
00117     // Display Results
00118     if (!validator.isDtdValid())
00119       System.out.println("[FAILED:Dtd is not valid]");
00120     else if (!validator.isXmlValid())
00121       System.out.println("[FAILED:xml is not valid]");
00122     else if (validator.isXmlValid())
00123       System.out.println("[OK]");
00124 
00125     if (validator.getLastException() != null)
00126     {
00127       ArrayList errors = validator.getExceptions();
00128       for (int i = 0; i < errors.size(); i++)
00129         System.out.println("\t(parsing error):"
00130             + ((Exception) errors.get(i)).getMessage());
00131     }
00132   }
00133 
00134   /**
00135    * Check the given dtd, and the given xml are valid.
00136    * 
00137    * @param pathToDtd path to dtd
00138    * @param xml source to parse as a string
00139    */
00140   public XmlValidator(String pathToDtd, String xml)
00141   {
00142     validate(pathToDtd, xml);
00143   }
00144 
00145   /**
00146    * @see #XmlValidator(String pathToDtd,String xml)
00147    */
00148   public XmlValidator(String pathToDtd, FileReader file) throws IOException
00149   {
00150     // Read the file
00151     BufferedReader in = new BufferedReader(file);
00152     StringBuffer xml = new StringBuffer();
00153     String line;
00154     do
00155     {
00156       line = in.readLine();
00157       if (line != null)
00158         xml.append(line.trim());
00159     }
00160     while (line != null);
00161     xmlContent = xml.toString();
00162     validate(pathToDtd, xmlContent);
00163   }
00164 
00165   /**
00166    * get the xml that was formatted
00167    * 
00168    * @return xml
00169    */
00170   public String getXmlContent()
00171   {
00172     return xmlContent;
00173   }
00174 
00175   /**
00176    * Starts the verification of the xml document AND the dtd
00177    * 
00178    * @param pathToDtd path
00179    * @param xml content
00180    */
00181   public void validate(String pathToDtd, String xml)
00182   {
00183     System.setProperty("org.xml.sax.driver",
00184         "org.apache.crimson.parser.XMLReaderImpl");
00185     errors = new ArrayList();
00186     warnings = new ArrayList();
00187     try
00188     {
00189       // Store dtd reference
00190       this.pathToDtd = pathToDtd;
00191       // Instantiate a new parser
00192       parser = XMLReaderFactory.createXMLReader();
00193       // Activate validation
00194       parser.setFeature("http://xml.org/sax/features/validation", true);
00195       // Install error handler
00196       parser.setErrorHandler(this);
00197       // Install document handler
00198       parser.setContentHandler(this);
00199       parser.setProperty("http://xml.org/sax/properties/lexical-handler", this);
00200       // Install local entity resolver
00201       parser.setEntityResolver(this);
00202       InputSource input = new InputSource(new StringReader(xml));
00203       parser.parse(input);
00204     }
00205     catch (Exception e)
00206     {
00207       //throw new Exception("Xml document can not be validated.");
00208       //e.printStackTrace();
00209       addError(e);
00210       isXmlValid = false;
00211     }
00212   }
00213 
00214   /**
00215    * Allows to parse the document with a local copy of the DTD whatever the
00216    * original <code>DOCTYPE</code> found. Warning, this method is called only
00217    * if the XML document contains a <code>DOCTYPE</code>.
00218    * 
00219    * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String,
00220    *           java.lang.String)
00221    */
00222   public InputSource resolveEntity(String publicId, String systemId)
00223       throws SAXException
00224   {
00225 
00226     File dtd = new File(pathToDtd);
00227     if (dtd.exists())
00228     {
00229       try
00230       {
00231         FileReader reader = new FileReader(dtd);
00232         return new InputSource(reader);
00233       }
00234       catch (Exception e)
00235       { //impossible
00236       }
00237     }
00238 
00239     InputStream stream = XmlValidator.class
00240         .getResourceAsStream("/" + pathToDtd);
00241     if (stream == null)
00242     {
00243       SAXException sax = new SAXException(Translate.get(
00244           "virtualdatabase.xml.dtd.not.found", pathToDtd));
00245       addError(sax);
00246       throw sax;
00247     }
00248 
00249     return new InputSource(stream);
00250   }
00251 
00252   /**
00253    * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
00254    */
00255   public void error(SAXParseException exception) throws SAXException
00256   {
00257     addError(exception);
00258   }
00259 
00260   /**
00261    * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
00262    */
00263   public void fatalError(SAXParseException exception) throws SAXException
00264   {
00265     addError(exception);
00266   }
00267 
00268   /**
00269    * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
00270    */
00271   public void warning(SAXParseException exception) throws SAXException
00272   {
00273     warnings.add(exception);
00274   }
00275 
00276   /**
00277    * @see org.xml.sax.ContentHandler#endDocument()
00278    */
00279   public void endDocument() throws SAXException
00280   {
00281     if (errors.size() == 0)
00282       this.isXmlValid = true;
00283   }
00284 
00285   /**
00286    * @return Returns the isXmlValid.
00287    */
00288   public boolean isValid()
00289   {
00290     return isXmlValid && isDtdValid;
00291   }
00292 
00293   /**
00294    * Return the last cause of parsing failure
00295    * 
00296    * @return exception, null if no exception
00297    */
00298   public Exception getLastException()
00299   {
00300     if (errors.size() == 0)
00301       return null;
00302     else
00303       return (Exception) errors.get(errors.size() - 1);
00304   }
00305 
00306   /**
00307    * Retrieve an <code>ArrayList</code> of all parsing exceptions
00308    * 
00309    * @return an <code>ArrayList</code> of <code>Exception</code>
00310    */
00311   public ArrayList getExceptions()
00312   {
00313     return errors;
00314   }
00315 
00316   /**
00317    * @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int)
00318    */
00319   public void comment(char[] ch, int start, int length) throws SAXException
00320   {
00321   }
00322 
00323   /**
00324    * @see org.xml.sax.ext.LexicalHandler#endCDATA()
00325    */
00326   public void endCDATA() throws SAXException
00327   {
00328   }
00329 
00330   /**
00331    * @see org.xml.sax.ext.LexicalHandler#endDTD()
00332    */
00333   public void endDTD() throws SAXException
00334   {
00335     if (errors.size() == 0)
00336     {
00337       isDtdValid = true;
00338     }
00339     else
00340     {
00341       isDtdValid = false;
00342     }
00343   }
00344 
00345   /**
00346    * @see org.xml.sax.ext.LexicalHandler#endEntity(java.lang.String)
00347    */
00348   public void endEntity(String name) throws SAXException
00349   {
00350   }
00351 
00352   /**
00353    * @see org.xml.sax.ext.LexicalHandler#startCDATA()
00354    */
00355   public void startCDATA() throws SAXException
00356   {
00357   }
00358 
00359   /**
00360    * @see org.xml.sax.ext.LexicalHandler#startDTD(java.lang.String,
00361    *           java.lang.String, java.lang.String)
00362    */
00363   public void startDTD(String name, String publicId, String systemId)
00364       throws SAXException
00365   {
00366   }
00367 
00368   /**
00369    * @see org.xml.sax.ext.LexicalHandler#startEntity(java.lang.String)
00370    */
00371   public void startEntity(String name) throws SAXException
00372   {
00373   }
00374 
00375   /**
00376    * @return Returns the isDtdValid.
00377    */
00378   public boolean isDtdValid()
00379   {
00380     return isDtdValid;
00381   }
00382 
00383   /**
00384    * @param isDtdValid The isDtdValid to set.
00385    */
00386   public void setDtdValid(boolean isDtdValid)
00387   {
00388     this.isDtdValid = isDtdValid;
00389   }
00390 
00391   /**
00392    * @return Returns the isXmlValid.
00393    */
00394   public boolean isXmlValid()
00395   {
00396     return isXmlValid;
00397   }
00398 
00399   /**
00400    * @param isXmlValid The isXmlValid to set.
00401    */
00402   public void setXmlValid(boolean isXmlValid)
00403   {
00404     this.isXmlValid = isXmlValid;
00405   }
00406 
00407   private void addError(Exception e)
00408   {
00409     errors.add(e);
00410   }
00411 
00412   /**
00413    * @return Returns the warnings.
00414    */
00415   public ArrayList getWarnings()
00416   {
00417     return warnings;
00418   }
00419 }

Generated on Mon Apr 11 22:01:35 2005 for C-JDBC by  doxygen 1.3.9.1