/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, Lotus
 * Development Corporation., http://www.lotus.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.DefaultHandler;

/* Use JAXP SAXParser to parse 1 .xml file or all the .xml files in a directory.
 * Takes 1 or 2 command-line arguments:
 *   Argument 1 (required) is a file name or directory name.
 *   Argument 2 (optional) is a log file name. If ommitted, messages are written to screen.
 */
public class Validate
{
  static int numXMLFiles = 0;
  static int numValidFiles = 0;
  static int numInvalidFiles = 0;
  static int numFilesMissingDoctype = 0;
  static int numMalformedFiles = 0;
  static boolean useLogFile = false;
  static StringBuffer buff = new StringBuffer();

  public static void main(String[] args)
    throws FileNotFoundException, IOException, ParserConfigurationException, SAXException
  {
    if (args.length == 0 || args.length > 2)
    {
      System.out.println("\nEnter 'java validate -help' for information about running Validate");
      return;
    }
    if (args[0].toLowerCase().equals("-help"))
    { 
      String sep = "\n====================================================\n";
      String a = "Validate uses Xerces to parse the xml files in the directory you specify or the individual xml file you specify. The parser validates each document (checks that it conforms to its DOCTYPE).\n";
      String b = "Each xml file should contain a DOCTYPE declaration.\n\n";
      String c = "Validate takes 1 or 2 arguments:\n";
      String d = " Argument 1 specifies a directory or an individual xml file.\n";
      String e = " Argument 2 specifies a log file. If you include this argument, Validate appends messages to this file. If you do not, Validate writes messages to the screen.\n";
      System.out.println(sep+a+b+c+d+e+sep);
      return;
    }    
    try
    {
      Validate v = new Validate();
      v.validate(args);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }    
  }
  
  void validate(String[] args)
    throws FileNotFoundException, IOException, ParserConfigurationException, SAXException
  {
    File dir = new File(args[0]);
   
    // User may include a 2nd argument for the log file. 
    useLogFile = (args.length == 2);
   
    if (dir.isFile()) // Just checking one file.
    {
      parse(null,args[0]);
    }
    else if (dir.isDirectory())  // Checking the contents of a directory.
    {
      // Only interested in .xml files.
      XMLFileFilter filter = new XMLFileFilter();
      String [] files = dir.list(filter);
      for (int i = 0; i <files.length; i++)
      { 
        parse(dir.toString(),files[i]); // All the work is done here.
        
        if (!useLogFile) 
        // Write messages to screen after parsing each file.
        {
          System.out.print(buff.toString());
          buff = new StringBuffer();
        }
      }
    }
    else // Command-line argument is no good!
    {
      System.out.println(args[0] + " not found!");
      return;
    }
    // Provide user with a summary.
    buff.append("================SUMMARY=============================\n");
    if (numXMLFiles > 1)
      buff.append("Parsed " + numXMLFiles + " .xml files in " +  args[0] + ".\n");
    if (numValidFiles > 1)
      buff.append( numValidFiles + " files are valid.\n");
    else if (numValidFiles == 1)
      buff.append( numValidFiles + " file is valid.\n");
    if (numInvalidFiles > 1)
      buff.append(numInvalidFiles + " files are not valid.\n");
    else if (numInvalidFiles == 1)
      buff.append( numInvalidFiles + " file is not valid.\n");
    if (numMalformedFiles > 1)
      buff.append(numMalformedFiles + " files are not well-formed.\n");
    else if (numMalformedFiles == 1)
      buff.append( numMalformedFiles + " file is not well-formed.\n");
    if (numFilesMissingDoctype > 1)
      buff.append(numFilesMissingDoctype + " files do not contain a DOCTYPE declaration.\n");
    else if (numFilesMissingDoctype == 1)
      buff.append(numFilesMissingDoctype + " file does not contain a DOCTYPE declaration.\n");
     
    if (!useLogFile)
      System.out.print(buff.toString());
    else
    {
      // If log file exists, append.
      FileWriter writer = new FileWriter(args[1], true);
      writer.write(new java.util.Date().toString()+ "\n");
      writer.write(buff.toString());
      writer.close();     
      System.out.println("Done with validation. See " + args[1] + ".");
    }
  }
  
  // Parse each XML file.
  void parse(String dir, String filename)
     throws FileNotFoundException, IOException, ParserConfigurationException, SAXException
  {
    try 
    {
      File f = new File(dir, filename);
      StringBuffer errorBuff = new StringBuffer();
      InputSource input = new InputSource(new FileInputStream(f));
      // Set systemID so parser can find the dtd with a relative URL in the source document.
      input.setSystemId(f.toString());
      SAXParserFactory spfact = SAXParserFactory.newInstance();
       
      spfact.setValidating(true);
      spfact.setNamespaceAware(true);
            
      SAXParser parser = spfact.newSAXParser();
      XMLReader reader = parser.getXMLReader();
      
      //Instantiate inner-class error and lexical handler.
      Handler handler = new Handler(filename, errorBuff);
      reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
      parser.parse(input, handler);

      if (handler.containsDTD && !handler.errorOrWarning) // valid
      {
        buff.append("VALID " + filename +"\n");
        numValidFiles++;
      }
      else if (handler.containsDTD) // not valid
      {
        buff.append ("NOT VALID " + filename + "\n");
        buff.append(errorBuff.toString());
        numInvalidFiles++;
      }
      else // no DOCTYPE to use for validation
      {
        buff.append("NO DOCTYPE DECLARATION " + filename + "\n");
        numFilesMissingDoctype++;
      }
    }
    catch (Exception e) // Serious problem!
    {
      buff.append("NOT WELL-FORMED " + filename + ". " + e.getMessage() + "\n");
      numMalformedFiles++;
    }
    finally
    {
      numXMLFiles++;
    }
  }
  // Inner classes
  
  // Only interested in parsing .xml files.
  class XMLFileFilter implements FilenameFilter
  {
    public boolean accept(File dir, String fileName)
    {
      return fileName.toLowerCase().endsWith(".xml") && new File(dir.toString(),fileName).isFile();
    }
  }
  
  // Catch any errors or warnings, and verify presence of doctype statement.
  class Handler extends DefaultHandler implements LexicalHandler
  {
    boolean errorOrWarning;
    boolean containsDTD;
    String sourceFile;
    StringBuffer errorBuff;  
  
    Handler(String sourceFile, StringBuffer errorBuff)
    {
      super();
      this.sourceFile = sourceFile;
      this.errorBuff = errorBuff;
      errorOrWarning = false;
      containsDTD = false;
    }
    
    public void error(SAXParseException exc)
    {
      errorBuff.append(sourceFile + " Error: " + exc.getMessage()+ "\n");    
      errorOrWarning = true;
    }
    public void warning(SAXParseException exc)
    {
      errorBuff.append(sourceFile + " Warning:" + exc.getMessage()+ "\n");   
      errorOrWarning = true;
    }

    // LexicalHandler methods; all no-op except startDTD().
    
    // Set containsDTD to true when startDTD event occurs.
    public void startDTD (String name, String publicId, String systemId)
	    throws SAXException
    {
      containsDTD = true;
    }
 
    public void endDTD () throws SAXException
    {}  
  
    public void startEntity (String name) throws SAXException
    {}
  
    public void endEntity (String name) throws SAXException
    {}
  
    public void startCDATA () throws SAXException
    {}
  
    public void endCDATA () throws SAXException
    {}
  
    public void comment (char ch[], int start, int length) throws SAXException
    {}
  }
}