Path: blob/aarch64-shenandoah-jdk8u272-b10/jaxp/src/org/w3c/dom/bootstrap/DOMImplementationRegistry.java
86410 views
/*1* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation. Oracle designates this6* particular file as subject to the "Classpath" exception as provided7* by Oracle in the LICENSE file that accompanied this code.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*/2324/*25* This file is available under and governed by the GNU General Public26* License version 2 only, as published by the Free Software Foundation.27* However, the following notice accompanied the original version of this28* file and, per its terms, should not be removed:29*30* Copyright (c) 2004 World Wide Web Consortium,31*32* (Massachusetts Institute of Technology, European Research Consortium for33* Informatics and Mathematics, Keio University). All Rights Reserved. This34* work is distributed under the W3C(r) Software License [1] in the hope that35* it will be useful, but WITHOUT ANY WARRANTY; without even the implied36* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.37*38* [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-2002123139*/404142package org.w3c.dom.bootstrap;4344import java.util.StringTokenizer;45import java.util.Vector;46import org.w3c.dom.DOMImplementationSource;47import org.w3c.dom.DOMImplementationList;48import org.w3c.dom.DOMImplementation;49import java.io.InputStream;50import java.io.BufferedReader;51import java.io.InputStreamReader;52import java.security.AccessController;53import java.security.PrivilegedAction;5455/**56* A factory that enables applications to obtain instances of57* <code>DOMImplementation</code>.58*59* <p>60* Example:61* </p>62*63* <pre class='example'>64* // get an instance of the DOMImplementation registry65* DOMImplementationRegistry registry =66* DOMImplementationRegistry.newInstance();67* // get a DOM implementation the Level 3 XML module68* DOMImplementation domImpl =69* registry.getDOMImplementation("XML 3.0");70* </pre>71*72* <p>73* This provides an application with an implementation-independent starting74* point. DOM implementations may modify this class to meet new security75* standards or to provide *additional* fallbacks for the list of76* DOMImplementationSources.77* </p>78*79* @see DOMImplementation80* @see DOMImplementationSource81* @since DOM Level 382*/83public final class DOMImplementationRegistry {84/**85* The system property to specify the86* DOMImplementationSource class names.87*/88public static final String PROPERTY =89"org.w3c.dom.DOMImplementationSourceList";9091/**92* Default columns per line.93*/94private static final int DEFAULT_LINE_LENGTH = 80;9596/**97* The list of DOMImplementationSources.98*/99private Vector sources;100101/**102* Default class name.103*/104private static final String FALLBACK_CLASS =105"com.sun.org.apache.xerces.internal.dom.DOMXSImplementationSourceImpl";106private static final String DEFAULT_PACKAGE =107"com.sun.org.apache.xerces.internal.dom";108/**109* Private constructor.110* @param srcs Vector List of DOMImplementationSources111*/112private DOMImplementationRegistry(final Vector srcs) {113sources = srcs;114}115116/**117* Obtain a new instance of a <code>DOMImplementationRegistry</code>.118*119120* The <code>DOMImplementationRegistry</code> is initialized by the121* application or the implementation, depending on the context, by122* first checking the value of the Java system property123* <code>org.w3c.dom.DOMImplementationSourceList</code> and124* the service provider whose contents are at125* "<code>META_INF/services/org.w3c.dom.DOMImplementationSourceList</code>".126* The value of this property is a white-space separated list of127* names of availables classes implementing the128* <code>DOMImplementationSource</code> interface. Each class listed129* in the class name list is instantiated and any exceptions130* encountered are thrown to the application.131*132* @return an initialized instance of DOMImplementationRegistry133* @throws ClassNotFoundException134* If any specified class can not be found135* @throws InstantiationException136* If any specified class is an interface or abstract class137* @throws IllegalAccessException138* If the default constructor of a specified class is not accessible139* @throws ClassCastException140* If any specified class does not implement141* <code>DOMImplementationSource</code>142*/143public static DOMImplementationRegistry newInstance()144throws145ClassNotFoundException,146InstantiationException,147IllegalAccessException,148ClassCastException {149Vector sources = new Vector();150151ClassLoader classLoader = getClassLoader();152// fetch system property:153String p = getSystemProperty(PROPERTY);154155//156// if property is not specified then use contents of157// META_INF/org.w3c.dom.DOMImplementationSourceList from classpath158if (p == null) {159p = getServiceValue(classLoader);160}161if (p == null) {162//163// DOM Implementations can modify here to add *additional* fallback164// mechanisms to access a list of default DOMImplementationSources.165//fall back to JAXP implementation class com.sun.org.apache.xerces.internal.dom.DOMXSImplementationSourceImpl166p = FALLBACK_CLASS;167}168if (p != null) {169StringTokenizer st = new StringTokenizer(p);170while (st.hasMoreTokens()) {171String sourceName = st.nextToken();172// make sure we have access to restricted packages173boolean internal = false;174if (System.getSecurityManager() != null) {175if (sourceName != null && sourceName.startsWith(DEFAULT_PACKAGE)) {176internal = true;177}178}179Class sourceClass = null;180if (classLoader != null && !internal) {181sourceClass = classLoader.loadClass(sourceName);182} else {183sourceClass = Class.forName(sourceName);184}185DOMImplementationSource source =186(DOMImplementationSource) sourceClass.newInstance();187sources.addElement(source);188}189}190return new DOMImplementationRegistry(sources);191}192193/**194* Return the first implementation that has the desired195* features, or <code>null</code> if none is found.196*197* @param features198* A string that specifies which features are required. This is199* a space separated list in which each feature is specified by200* its name optionally followed by a space and a version number.201* This is something like: "XML 1.0 Traversal +Events 2.0"202* @return An implementation that has the desired features,203* or <code>null</code> if none found.204*/205public DOMImplementation getDOMImplementation(final String features) {206int size = sources.size();207String name = null;208for (int i = 0; i < size; i++) {209DOMImplementationSource source =210(DOMImplementationSource) sources.elementAt(i);211DOMImplementation impl = source.getDOMImplementation(features);212if (impl != null) {213return impl;214}215}216return null;217}218219/**220* Return a list of implementations that support the221* desired features.222*223* @param features224* A string that specifies which features are required. This is225* a space separated list in which each feature is specified by226* its name optionally followed by a space and a version number.227* This is something like: "XML 1.0 Traversal +Events 2.0"228* @return A list of DOMImplementations that support the desired features.229*/230public DOMImplementationList getDOMImplementationList(final String features) {231final Vector implementations = new Vector();232int size = sources.size();233for (int i = 0; i < size; i++) {234DOMImplementationSource source =235(DOMImplementationSource) sources.elementAt(i);236DOMImplementationList impls =237source.getDOMImplementationList(features);238for (int j = 0; j < impls.getLength(); j++) {239DOMImplementation impl = impls.item(j);240implementations.addElement(impl);241}242}243return new DOMImplementationList() {244public DOMImplementation item(final int index) {245if (index >= 0 && index < implementations.size()) {246try {247return (DOMImplementation)248implementations.elementAt(index);249} catch (ArrayIndexOutOfBoundsException e) {250return null;251}252}253return null;254}255256public int getLength() {257return implementations.size();258}259};260}261262/**263* Register an implementation.264*265* @param s The source to be registered, may not be <code>null</code>266*/267public void addSource(final DOMImplementationSource s) {268if (s == null) {269throw new NullPointerException();270}271if (!sources.contains(s)) {272sources.addElement(s);273}274}275276/**277*278* Gets a class loader.279*280* @return A class loader, possibly <code>null</code>281*/282private static ClassLoader getClassLoader() {283try {284ClassLoader contextClassLoader = getContextClassLoader();285286if (contextClassLoader != null) {287return contextClassLoader;288}289} catch (Exception e) {290// Assume that the DOM application is in a JRE 1.1, use the291// current ClassLoader292return DOMImplementationRegistry.class.getClassLoader();293}294return DOMImplementationRegistry.class.getClassLoader();295}296297/**298* This method attempts to return the first line of the resource299* META_INF/services/org.w3c.dom.DOMImplementationSourceList300* from the provided ClassLoader.301*302* @param classLoader classLoader, may not be <code>null</code>.303* @return first line of resource, or <code>null</code>304*/305private static String getServiceValue(final ClassLoader classLoader) {306String serviceId = "META-INF/services/" + PROPERTY;307// try to find services in CLASSPATH308try {309InputStream is = getResourceAsStream(classLoader, serviceId);310311if (is != null) {312BufferedReader rd;313try {314rd =315new BufferedReader(new InputStreamReader(is, "UTF-8"),316DEFAULT_LINE_LENGTH);317} catch (java.io.UnsupportedEncodingException e) {318rd =319new BufferedReader(new InputStreamReader(is),320DEFAULT_LINE_LENGTH);321}322String serviceValue = rd.readLine();323rd.close();324if (serviceValue != null && serviceValue.length() > 0) {325return serviceValue;326}327}328} catch (Exception ex) {329return null;330}331return null;332}333334/**335* A simple JRE (Java Runtime Environment) 1.1 test336*337* @return <code>true</code> if JRE 1.1338*/339private static boolean isJRE11() {340try {341Class c = Class.forName("java.security.AccessController");342// java.security.AccessController existed since 1.2 so, if no343// exception was thrown, the DOM application is running in a JRE344// 1.2 or higher345return false;346} catch (Exception ex) {347// ignore348}349return true;350}351352/**353* This method returns the ContextClassLoader or <code>null</code> if354* running in a JRE 1.1355*356* @return The Context Classloader357*/358private static ClassLoader getContextClassLoader() {359return isJRE11()360? null361: (ClassLoader)362AccessController.doPrivileged(new PrivilegedAction() {363public Object run() {364ClassLoader classLoader = null;365try {366classLoader =367Thread.currentThread().getContextClassLoader();368} catch (SecurityException ex) {369}370return classLoader;371}372});373}374375/**376* This method returns the system property indicated by the specified name377* after checking access control privileges. For a JRE 1.1, this check is378* not done.379*380* @param name the name of the system property381* @return the system property382*/383private static String getSystemProperty(final String name) {384return isJRE11()385? (String) System.getProperty(name)386: (String) AccessController.doPrivileged(new PrivilegedAction() {387public Object run() {388return System.getProperty(name);389}390});391}392393/**394* This method returns an Inputstream for the reading resource395* META_INF/services/org.w3c.dom.DOMImplementationSourceList after checking396* access control privileges. For a JRE 1.1, this check is not done.397*398* @param classLoader classLoader399* @param name the resource400* @return an Inputstream for the resource specified401*/402private static InputStream getResourceAsStream(final ClassLoader classLoader,403final String name) {404if (isJRE11()) {405InputStream ris;406if (classLoader == null) {407ris = ClassLoader.getSystemResourceAsStream(name);408} else {409ris = classLoader.getResourceAsStream(name);410}411return ris;412} else {413return (InputStream)414AccessController.doPrivileged(new PrivilegedAction() {415public Object run() {416InputStream ris;417if (classLoader == null) {418ris =419ClassLoader.getSystemResourceAsStream(name);420} else {421ris = classLoader.getResourceAsStream(name);422}423return ris;424}425});426}427}428}429430431