package org.iso_relax.verifier;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
/**
* VerifierFactory
*
* @since Feb. 23, 2001
* @version Apr. 17, 2001
* @author ASAMI, Tomoharu (asami@zeomtech.com)
* @author <a href="mailto:kohsukekawaguchi@yahoo.com">Kohsuke KAWAGUCHI</a>
*/
public abstract class VerifierFactory {
/**
* parses a schema at the specified location and returns a Verifier object
* that validates documents by using that schema.
*
* <p>
* Some of XML parsers accepts filenames as well as URLs, while others
* reject them. Therefore, to parse a file as a schema, you should use
* a File object.
*
* @param uri URI of a schema file
*/
public Verifier newVerifier(String uri)
throws VerifierConfigurationException, SAXException, IOException {
return compileSchema(uri).newVerifier();
}
/**
* parses a schema from the specified file and returns a Verifier object
* that validates documents by using that schema.
*
* @param uri File of a schema file
*/
public Verifier newVerifier(File file)
throws VerifierConfigurationException, SAXException, IOException {
return compileSchema(file).newVerifier();
}
/**
* parses a schema from the specified InputStream and returns a Verifier object
* that validates documents by using that schema.
*/
public Verifier newVerifier(InputStream stream)
throws VerifierConfigurationException, SAXException, IOException {
return compileSchema( stream, null ).newVerifier();
}
/**
* parses a schema from the specified InputStream and returns a Verifier object
* that validates documents by using that schema.
*
* @param systemId
* System ID of this stream.
*/
public Verifier newVerifier(InputStream stream, String systemId )
throws VerifierConfigurationException, SAXException, IOException {
return compileSchema(stream,systemId).newVerifier();
}
/**
* parses a schema from the specified InputSource and returns a Verifier object
* that validates documents by using that schema.
*
* @param source InputSource of a schema file
*/
public Verifier newVerifier(InputSource source)
throws VerifierConfigurationException, SAXException, IOException {
return compileSchema(source).newVerifier();
}
/**
* processes a schema into a Schema object, which is a compiled representation
* of a schema.
*
* The obtained schema object can then be used concurrently across multiple
* threads.
*/
public abstract Schema compileSchema( InputSource is )
throws VerifierConfigurationException, SAXException, IOException;
/**
* processes a schema into a Schema object, which is a compiled representation
* of a schema.
*
* The obtained schema object can then be used concurrently across multiple
* threads.
*
* <p>
* Some of XML parsers accepts filenames as well as URLs, while others
* reject them. Therefore, to parse a file as a schema, you should use
* a File object.
*
* @param url
* A source url of a schema file to be compiled.
*/
public Schema compileSchema( String url )
throws VerifierConfigurationException, SAXException, IOException {
return compileSchema( new InputSource(url) );
}
/**
* processes a schema into a Schema object, which is a compiled representation
* of a schema.
*
* The obtained schema object can then be used concurrently across multiple
* threads.
*
* @param stream
* A stream object that holds a schema.
*/
public Schema compileSchema( InputStream stream )
throws VerifierConfigurationException, SAXException, IOException {
return compileSchema(stream,null);
}
/**
* processes a schema into a Schema object, which is a compiled representation
* of a schema.
*
* The obtained schema object can then be used concurrently across multiple
* threads.
*
* @param systemId
* The system Id of this input stream.
*/
public Schema compileSchema( InputStream stream, String systemId )
throws VerifierConfigurationException, SAXException, IOException {
InputSource is = new InputSource(stream);
is.setSystemId(systemId);
return compileSchema(is);
}
/**
* processes a schema into a Schema object, which is a compiled representation
* of a schema.
*
* The obtained schema object can then be used concurrently across multiple
* threads.
*
* @param file
* A schema file to be compiled
*/
public Schema compileSchema( File f )
throws VerifierConfigurationException, SAXException, IOException {
String uri = "file:" + f.getAbsolutePath();
if (File.separatorChar == '\\') {
uri = uri.replace('\\', '/');
}
return compileSchema(new InputSource(uri));
}
/**
* Indicates whether if the feature is supported, or not.
*
* @param feature feature name
*/
public boolean isFeature(String feature)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (Verifier.FEATURE_HANDLER.equals(feature) ||
Verifier.FEATURE_FILTER.equals(feature))
return true;
throw new SAXNotRecognizedException(feature);
}
/**
* Sets feature value
*
* @param feature feature name
* @param value feature value
*/
public void setFeature(String feature, boolean value)
throws SAXNotRecognizedException, SAXNotSupportedException {
throw new SAXNotRecognizedException(feature);
}
/**
* Gets property value
*
* @param property property name
*/
public Object getProperty(String property)
throws SAXNotRecognizedException, SAXNotSupportedException {
throw new SAXNotRecognizedException(property);
}
/**
* Sets property value
*
* @param property property name
* @param value property value
*/
public void setProperty(String property, Object value)
throws SAXNotRecognizedException, SAXNotSupportedException {
throw new SAXNotRecognizedException(property);
}
private EntityResolver resolver = null;
/**
* Sets an EntityResolver
*
* This entity resolver is used to resolve entities encountered while
* parsing a schema.
*/
public void setEntityResolver( EntityResolver _resolver ) {
this.resolver = _resolver;
}
/**
* Gets the current entity resolver, which was set by
* the <code>SetEntityResolver</code> method.
*/
public EntityResolver getEntityResolver() {
return resolver;
}
/**
* Creates a new instance of a VerifierFactory.
*
* @deprecated
*/
public static VerifierFactory newInstance()
throws VerifierConfigurationException {
return newInstance("http://www.xml.gr.jp/xmlns/relaxNamespace");
}
/**
* Creates a new instance of a VerifierFactory for the specified schema language.
*
* @param language
* URI that specifies the schema language.
*
* <p>
* It is preferable to use the namespace URI of the schema language
* to designate the schema language. For example,
*
* <table><thead>
* <tr>
* <td>URI</td>
* <td>language</td>
* </tr>
* </thead><tbody>
* <tr>
* <td><tt>http://relaxng.org/ns/structure/0.9</tt></td>
* <td><a href="http://www.oasis-open.org/committees/relax-ng/">
* RELAX NG
* </a></td>
* </tr><tr>
* <td><tt>http://www.xml.gr.jp/xmlns/relaxCore</tt></td>
* <td><a href="http://www.xml.gr.jp/relax">
* RELAX Core
* </a></td>
* </tr><tr>
* <td><tt>http://www.xml.gr.jp/xmlns/relaxNamespace</tt></td>
* <td><a href="http://www.xml.gr.jp/relax">
* RELAX Namespace
* </a></td>
* </tr><tr>
* <td><tt>http://www.thaiopensource.com/trex</tt></td>
* <td><a href="http://www.thaiopensource.com/trex">
* TREX
* </a></td>
* </tr><tr>
* <td><tt>http://www.w3.org/2001/XMLSchema</tt></td>
* <td><a href="http://www.w3.org/TR/xmlschema-1">
* W3C XML Schema
* </a></td>
* </tr><tr>
* <td><tt>http://www.w3.org/XML/1998/namespace</tt></td>
* <td><a href="http://www.w3.org/TR/REC-xml">
* XML DTD
* </a></td>
* </tr>
* </tbody></table>
*
* @param classLoader
* This class loader is used to search the available implementation.
*
* @return
* a non-null valid VerifierFactory instance.
*
* @exception VerifierConfigurationException
* if no implementation is available for the specified language.
*/
public static VerifierFactory newInstance(String language,ClassLoader classLoader) throws VerifierConfigurationException {
Iterator itr = providers( VerifierFactoryLoader.class, classLoader );
while(itr.hasNext()) {
VerifierFactoryLoader loader = (VerifierFactoryLoader)itr.next();
try {
VerifierFactory factory = loader.createFactory(language);
if(factory!=null) return factory;
} catch (Throwable t) {} // ignore any error
}
throw new VerifierConfigurationException("no validation engine available for: "+language);
}
public static VerifierFactory newInstance(String language) throws VerifierConfigurationException {
return newInstance(language,VerifierFactoryLoader.class.getClassLoader());
}
private static HashMap providerMap = new HashMap();
// K.K: the following providers method is copied from Apache Batik project.
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
/*
* version Service.java,v 1.1 2001/04/27 19:55:44 deweese Exp
*/
private static synchronized Iterator providers(Class cls,ClassLoader cl) {
String serviceFile = "META-INF/services/"+cls.getName();
// System.out.println("File: " + serviceFile);
Vector v = (Vector)providerMap.get(serviceFile);
if (v != null)
return v.iterator();
v = new Vector();
providerMap.put(serviceFile, v);
Enumeration e;
try {
e = cl.getResources(serviceFile);
} catch (IOException ioe) {
return v.iterator();
}
while (e.hasMoreElements()) {
try {
URL u = (URL)e.nextElement();
// System.out.println("URL: " + u);
InputStream is = u.openStream();
Reader r = new InputStreamReader(is, "UTF-8");
BufferedReader br = new BufferedReader(r);
String line = br.readLine();
while (line != null) {
try {
// First strip any comment...
int idx = line.indexOf('#');
if (idx != -1)
line = line.substring(0, idx);
// Trim whitespace.
line = line.trim();
// If nothing left then loop around...
if (line.length() == 0) {
line = br.readLine();
continue;
}
// System.out.println("Line: " + line);
// Try and load the class
Object obj = cl.loadClass(line).newInstance();
// stick it into our vector...
v.add(obj);
} catch (Exception ex) {
// Just try the next line
// ex.printStackTrace();
}
line = br.readLine();
}
} catch (Exception ex) {
// Just try the next file...
}
}
return v.iterator();
}
}