Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that validates XML documents
4
 *             This class is designed to be 'parser independent
5
 *             i.e. it uses only org.xml.sax classes
6
 *             It is tied to SAX 2.0 methods
7
 *  Copyright: 2000 Regents of the University of California and the
8
 *             National Center for Ecological Analysis and Synthesis
9
 *    Authors: Dan Higgins, Matt Jones
10
 * 
11
 *   '$Author: jones $'
12
 *     '$Date: 2000-06-26 03:35:05 -0700 (Mon, 26 Jun 2000) $'
13
 * '$Revision: 203 $'
14
 */
15
package edu.ucsb.nceas.metacat;
16

    
17

    
18
import java.net.URL;
19
import java.net.MalformedURLException;
20
import java.util.*;
21
import java.io.*;
22
import java.lang.reflect.*;
23

    
24
import org.w3c.dom.*;
25
import org.xml.sax.*;
26
import org.xml.sax.XMLReader;
27
import org.xml.sax.helpers.XMLReaderFactory;
28

    
29
import com.arbortext.catalog.*;
30

    
31
/**
32
 * Name: DBValidate.java
33
 *       Purpose: A Class that validates XML documents
34
 * 			   This class is designed to be parser independent
35
 *    			   i.e. it uses only org.xml.sax classes
36
 * 			   It is tied to SAX 2.0 methods
37
 *     Copyright: 2000 Regents of the University of California and the
38
 *                National Center for Ecological Analysis and Synthesis
39
 *                April 28, 2000
40
 * 
41
 * @author Dan Higgins
42
 * @version 1.0
43
 */
44
public class DBValidate {
45
    
46
  static int WARNING = 0;
47
  static int ERROR=1;
48
  static int FATAL_ERROR=2;
49

    
50
  XMLReader parser;
51
  ErrorStorer ef;
52
  String xml_doc; // document to be parsed
53
    
54
  /** Construct a new validation object */
55
  public DBValidate(String parserName) {
56

    
57
    try {
58
      // Get an instance of the parser
59
      parser = XMLReaderFactory.createXMLReader(parserName);
60
      parser.setFeature("http://xml.org/sax/features/validation",true);
61
      //parser.setValidationMode(true);     // Oracle
62
    } catch (Exception e) {
63
      System.err.println("Could not create parser!!!");
64
    }
65

    
66
    CatalogEntityResolver cer = new CatalogEntityResolver();
67
    try {
68
      Catalog myCatalog = new Catalog();
69
      myCatalog.loadSystemCatalogs();
70
      cer.setCatalog(myCatalog);
71
    } catch (Exception e) {System.out.println("Problem creating Catalog!");}
72

    
73
    parser.setEntityResolver(cer);
74
  }
75
    
76
  /** Construct a new validation object */
77
  public DBValidate(String parserName, String xmlcatalogfile)  {
78

    
79
    try {
80
      // Get an instance of the parser
81
      parser = XMLReaderFactory.createXMLReader(parserName);
82
      parser.setFeature("http://xml.org/sax/features/validation",true);
83
      //parser.setValidationMode(true);     // Oracle
84
    } catch (Exception e) {
85
      System.err.println("Could not create parser!!!");
86
    }
87

    
88
    CatalogEntityResolver cer = new CatalogEntityResolver();
89
    try {
90
      Catalog myCatalog = new Catalog();
91
      myCatalog.loadSystemCatalogs();
92
      myCatalog.parseCatalog(xmlcatalogfile);
93
      cer.setCatalog(myCatalog);
94
    } catch (Exception e) {System.out.println("Problem creating Catalog!");}
95

    
96
    parser.setEntityResolver(cer);
97
  }
98

    
99
  /** 
100
   * validate an xml document against its DTD
101
   *
102
   * @param doc the filename of the document to validate
103
   */
104
  public boolean validate(String doc) {
105
    xml_doc = doc;    
106
    ef = new ErrorStorer();
107
    ef.resetErrors();
108
    parser.setErrorHandler(ef);
109
    try {
110
      parser.parse((createURL(xml_doc)).toString());
111
    } catch (IOException e) {
112
      System.out.println("IOException:Could not parse :"+xml_doc);
113
      ParseError eip = null;
114
      eip = new ParseError("",0,0,"",
115
                "IOException:Could not parse :"+xml_doc);
116
      if (ef.errorNodes == null)  ef.errorNodes = new Vector();
117
      ef.errorNodes.addElement(eip);
118
        
119
    } catch (Exception e) {} 
120

    
121
      // {System.out.println("Exception parsing:Could not parse :"+xml_doc);} 
122
    
123
    if (ef != null && ef.getErrorNodes()!=null && 
124
      ef.getErrorNodes().size() > 0 ) {
125
      return false; 
126
    } else {
127
      return true;
128
    }
129
  }
130
    
131
  /** 
132
   * validate an xml document against its DTD
133
   *
134
   * @param xmldoc the String containing the xml document to validate
135
   */
136
  public boolean validateString(String xmldoc) {
137
    // string is actual XML here, NOT URL or file name    
138
    ef = new ErrorStorer();
139
    ef.resetErrors();
140
    parser.setErrorHandler(ef);
141
      
142
    InputSource is = new InputSource(new StringReader(xmldoc));
143
    try {
144
      parser.parse(is);
145
    }
146
    catch (Exception e) {System.out.println("Error in parsing!");}
147

    
148
    if (ef != null && ef.getErrorNodes()!=null && 
149
      ef.getErrorNodes().size() > 0 ) {
150
      return false; 
151
    } else {
152
      return true;
153
    }
154
  }
155
    
156
  /** provide a list of errors fromthe validation process */
157
  public String returnErrors() {
158
    String errorstring = "";
159
    if (ef != null && ef.getErrorNodes()!=null && 
160
        ef.getErrorNodes().size() > 0 ) {
161
      Vector errors = ef.getErrorNodes();
162
      for (Enumeration e = errors.elements() ; e.hasMoreElements() ;) {
163
        errorstring = errorstring +
164
                      ((ParseError)(e.nextElement())).getMsg()+"\n";
165
        errorstring = errorstring + "----\n";
166
      }
167
    } else {
168
      errorstring = "No errors were detected!!!";
169
    }
170
    return errorstring;
171
  }
172
              
173
  /** Create a URL object from either a URL string or a plain file name. */
174
  private URL createURL(String name) throws Exception {
175
    try {
176
      URL u = new URL(name);
177
      return u;
178
    } catch (MalformedURLException ex) {
179
    }
180
    URL u = new URL("file:" + new File(name).getAbsolutePath());
181
    return u;
182
  }    
183

    
184
  /** 
185
   * main method for testing 
186
   * <p>
187
   * Usage: java DBValidate <xmlfile or URL>
188
   */
189
  public static void main(String[] args) {
190

    
191
    if (args.length != 1) {
192
      System.out.println("Usage: java DBValidate <xmlfile or URL>");
193
      System.exit(0);
194
    }
195

    
196
    String doc = args[0];
197

    
198
    MetaCatUtil util = new MetaCatUtil();
199
    DBValidate gxv = new DBValidate(util.getOption("saxparser"));
200
    if (gxv.validate(doc)) {
201
      System.out.println("XML is valid.");
202
    } else {
203
      System.out.print(gxv.returnErrors());
204
    }
205
  }
206

    
207
    
208
  /**
209
   * ErrorStorer has been revised here to simply create a Vector of 
210
   * ParseError objects
211
   *
212
   */
213
  class ErrorStorer implements ErrorHandler {
214

    
215
    //
216
    // Data
217
    //
218
    Vector errorNodes = null;
219
        
220
    /**
221
     * Constructor
222
     */
223
    public ErrorStorer() {
224
    }
225

    
226
    /**
227
     * The client is is allowed to get a reference to the Hashtable,
228
     * and so could corrupt it, or add to it...
229
     */
230
    public Vector getErrorNodes() {
231
        return errorNodes;
232
    }
233

    
234
    /**
235
     * The ParseError object for the node key is returned.
236
     * If the node doesn't have errors, null is returned.
237
     */
238
    public Object getError() {
239
        if (errorNodes == null)
240
            return null;
241
        return errorNodes;
242
    }
243
        
244
    /**
245
     * Reset the error storage.
246
     */
247
    public void resetErrors() {
248
        if (errorNodes != null)
249
        errorNodes.removeAllElements();
250
    }
251
    
252
    /***/
253
    public void warning(SAXParseException ex) {
254
        handleError(ex, WARNING);
255
    }
256

    
257
    public void error(SAXParseException ex) {
258
        handleError(ex, ERROR);
259
    }
260

    
261
    public void fatalError(SAXParseException ex) throws SAXException {
262
        handleError(ex, FATAL_ERROR);
263
    }
264
        
265
    private void handleError(SAXParseException ex, int type) {
266
      // System.out.println("!!! handleError: "+ex.getMessage());
267

    
268
      StringBuffer errorString = new StringBuffer();
269
      errorString.append("at line number, ");
270
      errorString.append(ex.getLineNumber());
271
      errorString.append(": ");
272
      errorString.append(ex.getMessage());
273

    
274
      if (errorNodes == null) {
275
        errorNodes = new Vector();
276
      }
277
      ParseError eip = null;
278
      eip = new ParseError(ex.getSystemId(),ex.getLineNumber(),
279
            ex.getColumnNumber(),"",errorString.toString());
280
        
281
      // put it in the Hashtable.
282
      errorNodes.addElement(eip);
283
    }
284
        
285
  }
286
    
287
  /**
288
   * The ParseError class wraps up all the error info from
289
   * the ErrorStorer's error method.
290
   *
291
   * @see ErrorStorer
292
   */
293
  class ParseError extends Object {
294

    
295
    //
296
    // Data
297
    //
298

    
299
    String fileName;
300
    int lineNo;
301
    int charOffset;
302
    Object key;
303
    String msg;
304

    
305
    /**
306
     * Constructor
307
     */
308
    public ParseError(String fileName, int lineNo, int charOffset,
309
                       Object key, String msg) {
310
      this. fileName=fileName;
311
      this. lineNo=lineNo;
312
      this. charOffset=charOffset;
313
      this. key=key;
314
      this. msg=msg;
315
    }
316

    
317
    //
318
    // Getters...
319
    //
320
    public String getFileName() { return fileName; }
321
    public int getLineNo() { return lineNo; }
322
    public int getCharOffset() { return charOffset;}
323
    public Object getKey() { return key; }
324
    public String getMsg() { return msg; }
325
    public void setMsg(String s) { msg = s; }
326
  }
327
}
328

    
329
/**
330
 * '$Log$
331
 * 'Revision 1.6.2.3  2000/06/25 23:38:16  jones
332
 * 'Added RCSfile keyword
333
 * '
334
 * 'Revision 1.6.2.2  2000/06/25 23:34:18  jones
335
 * 'Changed documentation formatting, added log entries at bottom of source files
336
 * ''
337
 */
(15-15/24)