Project

General

Profile

1
/**
2
 *      Name: DBValidate.java
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
10
 * 
11
 *   Version: '$Id: DBValidate.java 185 2000-06-22 02:20:17Z jones $'
12
 */
13
package edu.ucsb.nceas.metacat;
14

    
15

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

    
22
import org.w3c.dom.*;
23
import org.xml.sax.*;
24
import org.xml.sax.XMLReader;
25
import org.xml.sax.helpers.XMLReaderFactory;
26

    
27
import com.arbortext.catalog.*;
28

    
29
/**
30
 * Name: DBValidate.java
31
 *       Purpose: A Class that validates XML documents
32
 * 			   This class is designed to be parser independent
33
 *    			   i.e. it uses only org.xml.sax classes
34
 * 			   It is tied to SAX 2.0 methods
35
 *     Copyright: 2000 Regents of the University of California and the
36
 *                National Center for Ecological Analysis and Synthesis
37
 *                April 28, 2000
38
 * 
39
 * @author Dan Higgins
40
 * @version 1.0
41
 */
42
public class DBValidate {
43
    
44
  /** Default parser name. */
45
  private static final String
46
      DEFAULT_PARSER = "org.apache.xerces.parsers.SAXParser";
47

    
48
  static int WARNING = 0;
49
  static int ERROR=1;
50
  static int FATAL_ERROR=2;
51

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

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

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

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

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

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

    
98
    parser.setEntityResolver(cer);
99
  }
100

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

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

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

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

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

    
198
    String doc = args[0];
199

    
200
    DBValidate gxv = new DBValidate(DEFAULT_PARSER);
201
    if (gxv.validate(doc)) {
202
      System.out.println("XML is valid.");
203
    } else {
204
      System.out.print(gxv.returnErrors());
205
    }
206
  }
207

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

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

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

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

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

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

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

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

    
296
    //
297
    // Data
298
    //
299

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

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

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