Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java
38918 views
/*1* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.sql.rowset;2627import java.security.AccessController;28import java.security.PrivilegedAction;29import java.sql.SQLException;30import java.util.PropertyPermission;31import java.util.ServiceConfigurationError;32import java.util.ServiceLoader;33import javax.sql.rowset.spi.SyncFactoryException;34import sun.reflect.misc.ReflectUtil;3536/**37* A factory API that enables applications to obtain a38* {@code RowSetFactory} implementation that can be used to create different39* types of {@code RowSet} implementations.40* <p>41* Example:42* </p>43* <pre>44* RowSetFactory aFactory = RowSetProvider.newFactory();45* CachedRowSet crs = aFactory.createCachedRowSet();46* ...47* RowSetFactory rsf = RowSetProvider.newFactory("com.sun.rowset.RowSetFactoryImpl", null);48* WebRowSet wrs = rsf.createWebRowSet();49* </pre>50*<p>51* Tracing of this class may be enabled by setting the System property52* {@code javax.sql.rowset.RowSetFactory.debug} to any value but {@code false}.53* </p>54*55* @author Lance Andersen56* @since 1.757*/58public class RowSetProvider {5960private static final String ROWSET_DEBUG_PROPERTY = "javax.sql.rowset.RowSetProvider.debug";61private static final String ROWSET_FACTORY_IMPL = "com.sun.rowset.RowSetFactoryImpl";62private static final String ROWSET_FACTORY_NAME = "javax.sql.rowset.RowSetFactory";63/**64* Internal debug flag.65*/66private static boolean debug = true;676869static {70// Check to see if the debug property is set71String val = getSystemProperty(ROWSET_DEBUG_PROPERTY);72// Allow simply setting the prop to turn on debug73debug = val != null && !"false".equals(val);74}7576/**77* RowSetProvider constructor78*/79protected RowSetProvider () {80}8182/**83* <p>Creates a new instance of a <code>RowSetFactory</code>84* implementation. This method uses the following85* look up order to determine86* the <code>RowSetFactory</code> implementation class to load:</p>87* <ul>88* <li>89* The System property {@code javax.sql.rowset.RowSetFactory}. For example:90* <ul>91* <li>92* -Djavax.sql.rowset.RowSetFactory=com.sun.rowset.RowSetFactoryImpl93* </li>94* </ul>95* <li>96* The {@link ServiceLoader} API. The {@code ServiceLoader} API will look97* for a class name in the file98* {@code META-INF/services/javax.sql.rowset.RowSetFactory}99* in jars available to the runtime. For example, to have the the RowSetFactory100* implementation {@code com.sun.rowset.RowSetFactoryImpl } loaded, the101* entry in {@code META-INF/services/javax.sql.rowset.RowSetFactory} would be:102* <ul>103* <li>104* {@code com.sun.rowset.RowSetFactoryImpl }105* </li>106* </ul>107* </li>108* <li>109* Platform default <code>RowSetFactory</code> instance.110* </li>111* </ul>112*113* <p>Once an application has obtained a reference to a {@code RowSetFactory},114* it can use the factory to obtain RowSet instances.</p>115*116* @return New instance of a <code>RowSetFactory</code>117*118* @throws SQLException if the default factory class cannot be loaded,119* instantiated. The cause will be set to actual Exception120*121* @see ServiceLoader122* @since 1.7123*/124public static RowSetFactory newFactory()125throws SQLException {126// Use the system property first127RowSetFactory factory = null;128String factoryClassName = null;129try {130trace("Checking for Rowset System Property...");131factoryClassName = getSystemProperty(ROWSET_FACTORY_NAME);132if (factoryClassName != null) {133trace("Found system property, value=" + factoryClassName);134factory = (RowSetFactory) ReflectUtil.newInstance(getFactoryClass(factoryClassName, null, true));135}136} catch (Exception e) {137throw new SQLException( "RowSetFactory: " + factoryClassName +138" could not be instantiated: ", e);139}140141// Check to see if we found the RowSetFactory via a System property142if (factory == null) {143// If the RowSetFactory is not found via a System Property, now144// look it up via the ServiceLoader API and if not found, use the145// Java SE default.146factory = loadViaServiceLoader();147factory =148factory == null ? newFactory(ROWSET_FACTORY_IMPL, null) : factory;149}150return (factory);151}152153/**154* <p>Creates a new instance of a <code>RowSetFactory</code> from the155* specified factory class name.156* This function is useful when there are multiple providers in the classpath.157* It gives more control to the application as it can specify which provider158* should be loaded.</p>159*160* <p>Once an application has obtained a reference to a <code>RowSetFactory</code>161* it can use the factory to obtain RowSet instances.</p>162*163* @param factoryClassName fully qualified factory class name that164* provides an implementation of <code>javax.sql.rowset.RowSetFactory</code>.165*166* @param cl <code>ClassLoader</code> used to load the factory167* class. If <code>null</code> current <code>Thread</code>'s context168* classLoader is used to load the factory class.169*170* @return New instance of a <code>RowSetFactory</code>171*172* @throws SQLException if <code>factoryClassName</code> is173* <code>null</code>, or the factory class cannot be loaded, instantiated.174*175* @see #newFactory()176*177* @since 1.7178*/179public static RowSetFactory newFactory(String factoryClassName, ClassLoader cl)180throws SQLException {181182trace("***In newInstance()");183184if(factoryClassName == null) {185throw new SQLException("Error: factoryClassName cannot be null");186}187try {188ReflectUtil.checkPackageAccess(factoryClassName);189} catch (java.security.AccessControlException e) {190throw new SQLException("Access Exception",e);191}192193try {194Class<?> providerClass = getFactoryClass(factoryClassName, cl, false);195RowSetFactory instance = (RowSetFactory) providerClass.newInstance();196if (debug) {197trace("Created new instance of " + providerClass +198" using ClassLoader: " + cl);199}200return instance;201} catch (ClassNotFoundException x) {202throw new SQLException(203"Provider " + factoryClassName + " not found", x);204} catch (Exception x) {205throw new SQLException(206"Provider " + factoryClassName + " could not be instantiated: " + x,207x);208}209}210211/*212* Returns the class loader to be used.213* @return The ClassLoader to use.214*215*/216static private ClassLoader getContextClassLoader() throws SecurityException {217return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {218219public ClassLoader run() {220ClassLoader cl = null;221222cl = Thread.currentThread().getContextClassLoader();223224if (cl == null) {225cl = ClassLoader.getSystemClassLoader();226}227228return cl;229}230});231}232233/**234* Attempt to load a class using the class loader supplied. If that fails235* and fall back is enabled, the current (i.e. bootstrap) class loader is236* tried.237*238* If the class loader supplied is <code>null</code>, first try using the239* context class loader followed by the current class loader.240* @return The class which was loaded241*/242static private Class<?> getFactoryClass(String factoryClassName, ClassLoader cl,243boolean doFallback) throws ClassNotFoundException {244try {245if (cl == null) {246cl = getContextClassLoader();247if (cl == null) {248throw new ClassNotFoundException();249} else {250return cl.loadClass(factoryClassName);251}252} else {253return cl.loadClass(factoryClassName);254}255} catch (ClassNotFoundException e) {256if (doFallback) {257// Use current class loader258return Class.forName(factoryClassName, true, RowSetFactory.class.getClassLoader());259} else {260throw e;261}262}263}264265/**266* Use the ServiceLoader mechanism to load the default RowSetFactory267* @return default RowSetFactory Implementation268*/269static private RowSetFactory loadViaServiceLoader() throws SQLException {270RowSetFactory theFactory = null;271try {272trace("***in loadViaServiceLoader():");273for (RowSetFactory factory : ServiceLoader.load(javax.sql.rowset.RowSetFactory.class)) {274trace(" Loading done by the java.util.ServiceLoader :" + factory.getClass().getName());275theFactory = factory;276break;277}278} catch (ServiceConfigurationError e) {279throw new SQLException(280"RowSetFactory: Error locating RowSetFactory using Service "281+ "Loader API: " + e, e);282}283return theFactory;284285}286287/**288* Returns the requested System Property. If a {@code SecurityException}289* occurs, just return NULL290* @param propName - System property to retrieve291* @return The System property value or NULL if the property does not exist292* or a {@code SecurityException} occurs.293*/294static private String getSystemProperty(final String propName) {295String property = null;296try {297property = AccessController.doPrivileged(new PrivilegedAction<String>() {298299public String run() {300return System.getProperty(propName);301}302}, null, new PropertyPermission(propName, "read"));303} catch (SecurityException se) {304trace("error getting " + propName + ": "+ se);305if (debug) {306se.printStackTrace();307}308}309return property;310}311312/**313* Debug routine which will output tracing if the System Property314* -Djavax.sql.rowset.RowSetFactory.debug is set315* @param msg - The debug message to display316*/317private static void trace(String msg) {318if (debug) {319System.err.println("###RowSets: " + msg);320}321}322}323324325