diff options
Diffstat (limited to 'libjava/classpath/external/w3c_dom/org/w3c/dom/bootstrap/DOMImplementationRegistry.java')
-rw-r--r-- | libjava/classpath/external/w3c_dom/org/w3c/dom/bootstrap/DOMImplementationRegistry.java | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/libjava/classpath/external/w3c_dom/org/w3c/dom/bootstrap/DOMImplementationRegistry.java b/libjava/classpath/external/w3c_dom/org/w3c/dom/bootstrap/DOMImplementationRegistry.java new file mode 100644 index 00000000000..be73f396bd8 --- /dev/null +++ b/libjava/classpath/external/w3c_dom/org/w3c/dom/bootstrap/DOMImplementationRegistry.java @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2004 World Wide Web Consortium, + * + * (Massachusetts Institute of Technology, European Research Consortium for + * Informatics and Mathematics, Keio University). All Rights Reserved. This + * work is distributed under the W3C(r) Software License [1] in the hope that + * it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + */ + + +package org.w3c.dom.bootstrap; + +import java.util.StringTokenizer; +import java.util.Vector; +import org.w3c.dom.DOMImplementationSource; +import org.w3c.dom.DOMImplementationList; +import org.w3c.dom.DOMImplementation; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * A factory that enables applications to obtain instances of + * <code>DOMImplementation</code>. + * + * <p> + * Example: + * </p> + * + * <pre class='example'> + * // get an instance of the DOMImplementation registry + * DOMImplementationRegistry registry = + * DOMImplementationRegistry.newInstance(); + * // get a DOM implementation the Level 3 XML module + * DOMImplementation domImpl = + * registry.getDOMImplementation("XML 3.0"); + * </pre> + * + * <p> + * This provides an application with an implementation-independent starting + * point. DOM implementations may modify this class to meet new security + * standards or to provide *additional* fallbacks for the list of + * DOMImplementationSources. + * </p> + * + * @see DOMImplementation + * @see DOMImplementationSource + * @since DOM Level 3 + */ +public final class DOMImplementationRegistry { + /** + * The system property to specify the + * DOMImplementationSource class names. + */ + public static final String PROPERTY = + "org.w3c.dom.DOMImplementationSourceList"; + + /** + * Default columns per line. + */ + private static final int DEFAULT_LINE_LENGTH = 80; + + /** + * The list of DOMImplementationSources. + */ + private Vector sources; + + /** + * Private constructor. + * @param srcs Vector List of DOMImplementationSources + */ + private DOMImplementationRegistry(final Vector srcs) { + sources = srcs; + } + + /** + * Obtain a new instance of a <code>DOMImplementationRegistry</code>. + * + + * The <code>DOMImplementationRegistry</code> is initialized by the + * application or the implementation, depending on the context, by + * first checking the value of the Java system property + * <code>org.w3c.dom.DOMImplementationSourceList</code> and + * the the service provider whose contents are at + * "<code>META_INF/services/org.w3c.dom.DOMImplementationSourceList</code>" + * The value of this property is a white-space separated list of + * names of availables classes implementing the + * <code>DOMImplementationSource</code> interface. Each class listed + * in the class name list is instantiated and any exceptions + * encountered are thrown to the application. + * + * @return an initialized instance of DOMImplementationRegistry + * @throws ClassNotFoundException + * If any specified class can not be found + * @throws InstantiationException + * If any specified class is an interface or abstract class + * @throws IllegalAccessException + * If the default constructor of a specified class is not accessible + * @throws ClassCastException + * If any specified class does not implement + * <code>DOMImplementationSource</code> + */ + public static DOMImplementationRegistry newInstance() + throws + ClassNotFoundException, + InstantiationException, + IllegalAccessException, + ClassCastException { + Vector sources = new Vector(); + + ClassLoader classLoader = getClassLoader(); + // fetch system property: + String p = getSystemProperty(PROPERTY); + + // + // if property is not specified then use contents of + // META_INF/org.w3c.dom.DOMImplementationSourceList from classpath + if (p == null) { + p = getServiceValue(classLoader); + } + if (p == null) { + // + // DOM Implementations can modify here to add *additional* fallback + // mechanisms to access a list of default DOMImplementationSources. + p = "gnu.xml.dom.ImplementationSource"; + } + if (p != null) { + StringTokenizer st = new StringTokenizer(p); + while (st.hasMoreTokens()) { + String sourceName = st.nextToken(); + // Use context class loader, falling back to Class.forName + // if and only if this fails... + Class sourceClass = null; + if (classLoader != null) { + sourceClass = classLoader.loadClass(sourceName); + } else { + sourceClass = Class.forName(sourceName); + } + DOMImplementationSource source = + (DOMImplementationSource) sourceClass.newInstance(); + sources.addElement(source); + } + } + return new DOMImplementationRegistry(sources); + } + + /** + * Return the first implementation that has the desired + * features, or <code>null</code> if none is found. + * + * @param features + * A string that specifies which features are required. This is + * a space separated list in which each feature is specified by + * its name optionally followed by a space and a version number. + * This is something like: "XML 1.0 Traversal +Events 2.0" + * @return An implementation that has the desired features, + * or <code>null</code> if none found. + */ + public DOMImplementation getDOMImplementation(final String features) { + int size = sources.size(); + String name = null; + for (int i = 0; i < size; i++) { + DOMImplementationSource source = + (DOMImplementationSource) sources.elementAt(i); + DOMImplementation impl = source.getDOMImplementation(features); + if (impl != null) { + return impl; + } + } + return null; + } + + /** + * Return a list of implementations that support the + * desired features. + * + * @param features + * A string that specifies which features are required. This is + * a space separated list in which each feature is specified by + * its name optionally followed by a space and a version number. + * This is something like: "XML 1.0 Traversal +Events 2.0" + * @return A list of DOMImplementations that support the desired features. + */ + public DOMImplementationList getDOMImplementationList(final String features) { + final Vector implementations = new Vector(); + int size = sources.size(); + for (int i = 0; i < size; i++) { + DOMImplementationSource source = + (DOMImplementationSource) sources.elementAt(i); + DOMImplementationList impls = + source.getDOMImplementationList(features); + for (int j = 0; j < impls.getLength(); j++) { + DOMImplementation impl = impls.item(j); + implementations.addElement(impl); + } + } + return new DOMImplementationList() { + public DOMImplementation item(final int index) { + if (index >= 0 && index < implementations.size()) { + try { + return (DOMImplementation) + implementations.elementAt(index); + } catch (ArrayIndexOutOfBoundsException e) { + return null; + } + } + return null; + } + + public int getLength() { + return implementations.size(); + } + }; + } + + /** + * Register an implementation. + * + * @param s The source to be registered, may not be <code>null</code> + */ + public void addSource(final DOMImplementationSource s) { + if (s == null) { + throw new NullPointerException(); + } + if (!sources.contains(s)) { + sources.addElement(s); + } + } + + /** + * + * Gets a class loader. + * + * @return A class loader, possibly <code>null</code> + */ + private static ClassLoader getClassLoader() { + try { + ClassLoader contextClassLoader = getContextClassLoader(); + + if (contextClassLoader != null) { + return contextClassLoader; + } + } catch (Exception e) { + // Assume that the DOM application is in a JRE 1.1, use the + // current ClassLoader + return DOMImplementationRegistry.class.getClassLoader(); + } + return DOMImplementationRegistry.class.getClassLoader(); + } + + /** + * This method attempts to return the first line of the resource + * META_INF/services/org.w3c.dom.DOMImplementationSourceList + * from the provided ClassLoader. + * + * @param classLoader classLoader, may not be <code>null</code>. + * @return first line of resource, or <code>null</code> + */ + private static String getServiceValue(final ClassLoader classLoader) { + String serviceId = "META-INF/services/" + PROPERTY; + // try to find services in CLASSPATH + try { + InputStream is = getResourceAsStream(classLoader, serviceId); + + if (is != null) { + BufferedReader rd; + try { + rd = + new BufferedReader(new InputStreamReader(is, "UTF-8"), + DEFAULT_LINE_LENGTH); + } catch (java.io.UnsupportedEncodingException e) { + rd = + new BufferedReader(new InputStreamReader(is), + DEFAULT_LINE_LENGTH); + } + String serviceValue = rd.readLine(); + rd.close(); + if (serviceValue != null && serviceValue.length() > 0) { + return serviceValue; + } + } + } catch (Exception ex) { + return null; + } + return null; + } + + /** + * A simple JRE (Java Runtime Environment) 1.1 test + * + * @return <code>true</code> if JRE 1.1 + */ + private static boolean isJRE11() { + try { + Class c = Class.forName("java.security.AccessController"); + // java.security.AccessController existed since 1.2 so, if no + // exception was thrown, the DOM application is running in a JRE + // 1.2 or higher + return false; + } catch (Exception ex) { + // ignore + } + return true; + } + + /** + * This method returns the ContextClassLoader or <code>null</code> if + * running in a JRE 1.1 + * + * @return The Context Classloader + */ + private static ClassLoader getContextClassLoader() { + return isJRE11() + ? null + : (ClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ClassLoader classLoader = null; + try { + classLoader = + Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + return classLoader; + } + }); + } + + /** + * This method returns the system property indicated by the specified name + * after checking access control privileges. For a JRE 1.1, this check is + * not done. + * + * @param name the name of the system property + * @return the system property + */ + private static String getSystemProperty(final String name) { + return isJRE11() + ? (String) System.getProperty(name) + : (String) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return System.getProperty(name); + } + }); + } + + /** + * This method returns an Inputstream for the reading resource + * META_INF/services/org.w3c.dom.DOMImplementationSourceList after checking + * access control privileges. For a JRE 1.1, this check is not done. + * + * @param classLoader classLoader + * @param name the resource + * @return an Inputstream for the resource specified + */ + private static InputStream getResourceAsStream(final ClassLoader classLoader, + final String name) { + if (isJRE11()) { + InputStream ris; + if (classLoader == null) { + ris = ClassLoader.getSystemResourceAsStream(name); + } else { + ris = classLoader.getResourceAsStream(name); + } + return ris; + } else { + return (InputStream) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + InputStream ris; + if (classLoader == null) { + ris = + ClassLoader.getSystemResourceAsStream(name); + } else { + ris = classLoader.getResourceAsStream(name); + } + return ris; + } + }); + } + } +} |