org.j3d.util.SAXEntityResolver Maven / Gradle / Ivy
/*****************************************************************************
* J3D.org Copyright (c) 2000
* Java Source
*
* This source is licensed under the GNU LGPL v2.1
* Please read http://www.gnu.org/copyleft/lgpl.html for more information
*
****************************************************************************/
package org.j3d.util;
// External imports
import java.io.InputStream;
import java.io.IOException;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
/**
* An entity resolver for both DOM and SAX models of the SAX document.
*
* The entity resolver only handles queries for the DTD. It will find
* any URI that ends in *.dtd and return an {@link org.xml.sax.InputSource}.
*
* As the SAX specification does not yet define what the system resource
* ID is, we'll take a guess. The current resolution scheme only strips the
* name of the DTD from the URI and attempts to find that in the classpath.
*
* To determine the DTD name it will search from the end of the string until it
* finds a '/' character. The resulting string is treated as a filename to
* search for. This filename is then found in the CLASSPATH used by the
* application using the standard Java resolution rules. Note that we do not
* need to implement any more intelligent behaviour than this because if the
* System or PublicID returned are files or URLs, the standard parser
* mechanisms will load them. The only more intelligent behaviour that we may
* wish to add in the future will be to resolve a full URN if we are given it.
*
* The current implementation ignores the publicId information.
*
* @author Justin Couch
* @version $Revision: 1.4 $
*/
public class SAXEntityResolver implements EntityResolver
{
/** A root directory to find the DTD files under */
private String dtdRootDirectory;
/**
* Set a root directory to locate DTDs in. Setting to null clears the
* root directory and finds it directly in the classpath. No check is done
* to validate that this path actually exists in the classpath at the
* time of setting
*
* @param dir The directory to use or null to clear
*/
public void setDTDRootDirectory(String dir)
{
dtdRootDirectory = dir;
}
/**
* Resolve the combination of system and public identifiers. This
* resolver ignores the publicId information.
*
* @param publicId The public identifier to use (if set)
* @param systemId The system identifier to resolve
* @return An input source to the entity or null if not handled
* @throws IOException An error reading the stream
*/
@Override
public InputSource resolveEntity(String publicId, String systemId)
throws IOException
{
/*
System.out.println("Entity Resolver called.");
System.out.println(" publicID: " + publicId);
System.out.println(" systemID: " + systemId);
*/
InputSource ret_val = null;
InputStream is = resolveDTD(systemId);
if(is != null)
{
ret_val = new InputSource(is);
ret_val.setPublicId(publicId);
ret_val.setSystemId(systemId);
}
return ret_val;
}
/**
* Resolve the DTD uri and return an InputStream used by this.
*
* @param uri The DTD uri to resolve
* @return An input stream to the entity or null if not handled
* @throws IOException An error reading the stream
*/
private InputStream resolveDTD(String uri) throws IOException
{
InputStream ret_val = null;
// grab the system ID and remove the last word from it prior to
// a '/' (if one exists).
int pos = uri.lastIndexOf('/');
String filename = uri;
if(pos != -1)
{
filename = uri.substring(pos + 1);
}
if(dtdRootDirectory != null)
{
filename = dtdRootDirectory + '/' + filename;
}
ClassLoader cl = ClassLoader.getSystemClassLoader();
ret_val = cl.getResourceAsStream(filename);
return ret_val;
}
}