/* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed 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. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package javax.sql.rowset;import java.security.AccessController;import java.security.PrivilegedAction;import java.sql.SQLException;import java.util.ServiceConfigurationError;import java.util.ServiceLoader;/** * A factory API that enables applications to obtain a * {@code RowSetFactory} implementation that can be used to create different * types of {@code RowSet} implementations. * <p> * Example: * </p> * <pre> * RowSetFactory aFactory = RowSetProvider.newFactory(); * CachedRowSet crs = aFactory.createCachedRowSet(); * ... * RowSetFactory rsf = RowSetProvider.newFactory("com.sun.rowset.RowSetFactoryImpl", null); * WebRowSet wrs = rsf.createWebRowSet(); * </pre> *<p> * Tracing of this class may be enabled by setting the System property * {@code javax.sql.rowset.RowSetFactory.debug} to any value but {@code false}. * </p> * * @author Lance Andersen * @since 1.7 */public class RowSetProvider { private static final String ROWSET_DEBUG_PROPERTY = "javax.sql.rowset.RowSetProvider.debug"; private static final String ROWSET_FACTORY_IMPL = "com.sun.rowset.RowSetFactoryImpl"; private static final String ROWSET_FACTORY_NAME = "javax.sql.rowset.RowSetFactory"; /** * Internal debug flag. */ private static boolean debug = true; static { // Check to see if the debug property is set String val = getSystemProperty(ROWSET_DEBUG_PROPERTY); // Allow simply setting the prop to turn on debug debug = val != null && !"false".equals(val); } protected RowSetProvider () { } /** * <p>Creates a new instance of a <code>RowSetFactory</code> * implementation. This method uses the following * look up order to determine * the <code>RowSetFactory</code> implementation class to load:</p> * <ul> * <li> * The System property {@code javax.sql.rowset.RowSetFactory}. For example: * <ul> * <li> * -Djavax.sql.rowset.RowSetFactory=com.sun.rowset.RowSetFactoryImpl * </li> * </ul> * <li> * The {@link ServiceLoader} API. The {@code ServiceLoader} API will look * for a class name in the file * {@code META-INF/services/javax.sql.rowset.RowSetFactory} * in jars available to the runtime. For example, to have the the RowSetFactory * implementation {@code com.sun.rowset.RowSetFactoryImpl } loaded, the * entry in {@code META-INF/services/javax.sql.rowset.RowSetFactory} would be: * <ul> * <li> * {@code com.sun.rowset.RowSetFactoryImpl } * </li> * </ul> * </li> * <li> * Platform default <code>RowSetFactory</code> instance. * </li> * </ul> * * <p>Once an application has obtained a reference to a {@code RowSetFactory}, * it can use the factory to obtain RowSet instances.</p> * * @return New instance of a <code>RowSetFactory</code> * * @throws SQLException if the default factory class cannot be loaded, * instantiated. The cause will be set to actual Exception * * @see ServiceLoader * @since 1.7 */ public static RowSetFactory newFactory() throws SQLException { // Use the system property first RowSetFactory factory = null; String factoryClassName = null; try { trace("Checking for Rowset System Property..."); factoryClassName = getSystemProperty(ROWSET_FACTORY_NAME); if (factoryClassName != null) { trace("Found system property, value=" + factoryClassName); factory = (RowSetFactory) getFactoryClass(factoryClassName, null, true).newInstance(); } } catch (ClassNotFoundException e) { throw new SQLException( "RowSetFactory: " + factoryClassName + " not found", e); } catch (Exception e) { throw new SQLException( "RowSetFactory: " + factoryClassName + " could not be instantiated: " + e, e); } // Check to see if we found the RowSetFactory via a System property if (factory == null) { // If the RowSetFactory is not found via a System Property, now // look it up via the ServiceLoader API and if not found, use the // Java SE default. factory = loadViaServiceLoader(); factory = factory == null ? newFactory(ROWSET_FACTORY_IMPL, null) : factory; } return (factory); } /** * <p>Creates a new instance of a <code>RowSetFactory</code> from the * specified factory class name. * This function is useful when there are multiple providers in the classpath. * It gives more control to the application as it can specify which provider * should be loaded.</p> * * <p>Once an application has obtained a reference to a <code>RowSetFactory</code> * it can use the factory to obtain RowSet instances.</p> * * @param factoryClassName fully qualified factory class name that * provides an implementation of <code>javax.sql.rowset.RowSetFactory</code>. * * @param cl <code>ClassLoader</code> used to load the factory * class. If <code>null</code> current <code>Thread</code>'s context * classLoader is used to load the factory class. * * @return New instance of a <code>RowSetFactory</code> * * @throws SQLException if <code>factoryClassName</code> is * <code>null</code>, or the factory class cannot be loaded, instantiated. * * @see #newFactory() * * @since 1.7 */ public static RowSetFactory newFactory(String factoryClassName, ClassLoader cl) throws SQLException { trace("***In newInstance()"); try { Class providerClass = getFactoryClass(factoryClassName, cl, false); RowSetFactory instance = (RowSetFactory) providerClass.newInstance(); if (debug) { trace("Created new instance of " + providerClass + " using ClassLoader: " + cl); } return instance; } catch (ClassNotFoundException x) { throw new SQLException( "Provider " + factoryClassName + " not found", x); } catch (Exception x) { throw new SQLException( "Provider " + factoryClassName + " could not be instantiated: " + x, x); } } /* * Returns the class loader to be used. * @return The ClassLoader to use. * */ static private ClassLoader getContextClassLoader() throws SecurityException { return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { public ClassLoader run() { ClassLoader cl = null; cl = Thread.currentThread().getContextClassLoader(); if (cl == null) { cl = ClassLoader.getSystemClassLoader(); } return cl; } }); } /** * Attempt to load a class using the class loader supplied. If that fails * and fall back is enabled, the current (i.e. bootstrap) class loader is * tried. * * If the class loader supplied is <code>null</code>, first try using the * context class loader followed by the current class loader. * @return The class which was loaded */ static private Class getFactoryClass(String factoryClassName, ClassLoader cl, boolean doFallback) throws ClassNotFoundException { try { if (cl == null) { cl = getContextClassLoader(); if (cl == null) { throw new ClassNotFoundException(); } else { return cl.loadClass(factoryClassName); } } else { return cl.loadClass(factoryClassName); } } catch (ClassNotFoundException e) { if (doFallback) { // Use current class loader return Class.forName(factoryClassName, true, RowSetFactory.class.getClassLoader()); } else { throw e; } } } /** * Use the ServiceLoader mechanism to load the default RowSetFactory * @return default RowSetFactory Implementation */ static private RowSetFactory loadViaServiceLoader() throws SQLException { RowSetFactory theFactory = null; try { trace("***in loadViaServiceLoader():"); for (RowSetFactory factory : ServiceLoader.load(javax.sql.rowset.RowSetFactory.class)) { trace(" Loading done by the java.util.ServiceLoader :" + factory.getClass().getName()); theFactory = factory; break; } } catch (ServiceConfigurationError e) { throw new SQLException( "RowSetFactory: Error locating RowSetFactory using Service " + "Loader API: " + e, e); } return theFactory; } /** * Returns the requested System Property. If a {@code SecurityException} * occurs, just return NULL * @param propName - System property to retrieve * @return The System property value or NULL if the property does not exist * or a {@code SecurityException} occurs. */ static private String getSystemProperty(final String propName) { String property = null; try { property = AccessController.doPrivileged(new PrivilegedAction<String>() { public String run() { return System.getProperty(propName); } }); } catch (SecurityException se) { if (debug) { se.printStackTrace(); } } return property; } /** * Debug routine which will output tracing if the System Property * -Djavax.sql.rowset.RowSetFactory.debug is set * @param msg - The debug message to display */ private static void trace(String msg) { if (debug) { System.err.println("###RowSets: " + msg); } }}
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed 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. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.sql.rowset;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.sql.SQLException;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
/**
* A factory API that enables applications to obtain a
* {@code RowSetFactory} implementation that can be used to create different
* types of {@code RowSet} implementations.
* <p>
* Example:
* </p>
* <pre>
* RowSetFactory aFactory = RowSetProvider.newFactory();
* CachedRowSet crs = aFactory.createCachedRowSet();
* ...
* RowSetFactory rsf = RowSetProvider.newFactory("com.sun.rowset.RowSetFactoryImpl", null);
* WebRowSet wrs = rsf.createWebRowSet();
* </pre>
*<p>
* Tracing of this class may be enabled by setting the System property
* {@code javax.sql.rowset.RowSetFactory.debug} to any value but {@code false}.
* </p>
*
* @author Lance Andersen
* @since 1.7
*/
public class RowSetProvider {
private static final String ROWSET_DEBUG_PROPERTY = "javax.sql.rowset.RowSetProvider.debug";
private static final String ROWSET_FACTORY_IMPL = "com.sun.rowset.RowSetFactoryImpl";
private static final String ROWSET_FACTORY_NAME = "javax.sql.rowset.RowSetFactory";
/**
* Internal debug flag.
*/
private static boolean debug = true;
static {
// Check to see if the debug property is set
String val = getSystemProperty(ROWSET_DEBUG_PROPERTY);
// Allow simply setting the prop to turn on debug
debug = val != null && !"false".equals(val);
}
protected RowSetProvider () {
}
/**
* <p>Creates a new instance of a <code>RowSetFactory</code>
* implementation. This method uses the following
* look up order to determine
* the <code>RowSetFactory</code> implementation class to load:</p>
* <ul>
* <li>
* The System property {@code javax.sql.rowset.RowSetFactory}. For example:
* <ul>
* <li>
* -Djavax.sql.rowset.RowSetFactory=com.sun.rowset.RowSetFactoryImpl
* </li>
* </ul>
* <li>
* The {@link ServiceLoader} API. The {@code ServiceLoader} API will look
* for a class name in the file
* {@code META-INF/services/javax.sql.rowset.RowSetFactory}
* in jars available to the runtime. For example, to have the the RowSetFactory
* implementation {@code com.sun.rowset.RowSetFactoryImpl } loaded, the
* entry in {@code META-INF/services/javax.sql.rowset.RowSetFactory} would be:
* <ul>
* <li>
* {@code com.sun.rowset.RowSetFactoryImpl }
* </li>
* </ul>
* </li>
* <li>
* Platform default <code>RowSetFactory</code> instance.
* </li>
* </ul>
*
* <p>Once an application has obtained a reference to a {@code RowSetFactory},
* it can use the factory to obtain RowSet instances.</p>
*
* @return New instance of a <code>RowSetFactory</code>
*
* @throws SQLException if the default factory class cannot be loaded,
* instantiated. The cause will be set to actual Exception
*
* @see ServiceLoader
* @since 1.7
*/
public static RowSetFactory newFactory()
throws SQLException {
// Use the system property first
RowSetFactory factory = null;
String factoryClassName = null;
try {
trace("Checking for Rowset System Property...");
factoryClassName = getSystemProperty(ROWSET_FACTORY_NAME);
if (factoryClassName != null) {
trace("Found system property, value=" + factoryClassName);
factory = (RowSetFactory) getFactoryClass(factoryClassName, null, true).newInstance();
}
} catch (ClassNotFoundException e) {
throw new SQLException(
"RowSetFactory: " + factoryClassName + " not found", e);
} catch (Exception e) {
throw new SQLException(
"RowSetFactory: " + factoryClassName + " could not be instantiated: " + e,
e);
}
// Check to see if we found the RowSetFactory via a System property
if (factory == null) {
// If the RowSetFactory is not found via a System Property, now
// look it up via the ServiceLoader API and if not found, use the
// Java SE default.
factory = loadViaServiceLoader();
factory =
factory == null ? newFactory(ROWSET_FACTORY_IMPL, null) : factory;
}
return (factory);
}
/**
* <p>Creates a new instance of a <code>RowSetFactory</code> from the
* specified factory class name.
* This function is useful when there are multiple providers in the classpath.
* It gives more control to the application as it can specify which provider
* should be loaded.</p>
*
* <p>Once an application has obtained a reference to a <code>RowSetFactory</code>
* it can use the factory to obtain RowSet instances.</p>
*
* @param factoryClassName fully qualified factory class name that
* provides an implementation of <code>javax.sql.rowset.RowSetFactory</code>.
*
* @param cl <code>ClassLoader</code> used to load the factory
* class. If <code>null</code> current <code>Thread</code>'s context
* classLoader is used to load the factory class.
*
* @return New instance of a <code>RowSetFactory</code>
*
* @throws SQLException if <code>factoryClassName</code> is
* <code>null</code>, or the factory class cannot be loaded, instantiated.
*
* @see #newFactory()
*
* @since 1.7
*/
public static RowSetFactory newFactory(String factoryClassName, ClassLoader cl)
throws SQLException {
trace("***In newInstance()");
try {
Class providerClass = getFactoryClass(factoryClassName, cl, false);
RowSetFactory instance = (RowSetFactory) providerClass.newInstance();
if (debug) {
trace("Created new instance of " + providerClass +
" using ClassLoader: " + cl);
}
return instance;
} catch (ClassNotFoundException x) {
throw new SQLException(
"Provider " + factoryClassName + " not found", x);
} catch (Exception x) {
throw new SQLException(
"Provider " + factoryClassName + " could not be instantiated: " + x,
x);
}
}
/*
* Returns the class loader to be used.
* @return The ClassLoader to use.
*
*/
static private ClassLoader getContextClassLoader() throws SecurityException {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
ClassLoader cl = null;
cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
}
return cl;
}
});
}
/**
* Attempt to load a class using the class loader supplied. If that fails
* and fall back is enabled, the current (i.e. bootstrap) class loader is
* tried.
*
* If the class loader supplied is <code>null</code>, first try using the
* context class loader followed by the current class loader.
* @return The class which was loaded
*/
static private Class getFactoryClass(String factoryClassName, ClassLoader cl,
boolean doFallback) throws ClassNotFoundException {
try {
if (cl == null) {
cl = getContextClassLoader();
if (cl == null) {
throw new ClassNotFoundException();
} else {
return cl.loadClass(factoryClassName);
}
} else {
return cl.loadClass(factoryClassName);
}
} catch (ClassNotFoundException e) {
if (doFallback) {
// Use current class loader
return Class.forName(factoryClassName, true, RowSetFactory.class.getClassLoader());
} else {
throw e;
}
}
}
/**
* Use the ServiceLoader mechanism to load the default RowSetFactory
* @return default RowSetFactory Implementation
*/
static private RowSetFactory loadViaServiceLoader() throws SQLException {
RowSetFactory theFactory = null;
try {
trace("***in loadViaServiceLoader():");
for (RowSetFactory factory : ServiceLoader.load(javax.sql.rowset.RowSetFactory.class)) {
trace(" Loading done by the java.util.ServiceLoader :" + factory.getClass().getName());
theFactory = factory;
break;
}
} catch (ServiceConfigurationError e) {
throw new SQLException(
"RowSetFactory: Error locating RowSetFactory using Service "
+ "Loader API: " + e, e);
}
return theFactory;
}
/**
* Returns the requested System Property. If a {@code SecurityException}
* occurs, just return NULL
* @param propName - System property to retrieve
* @return The System property value or NULL if the property does not exist
* or a {@code SecurityException} occurs.
*/
static private String getSystemProperty(final String propName) {
String property = null;
try {
property = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty(propName);
}
});
} catch (SecurityException se) {
if (debug) {
se.printStackTrace();
}
}
return property;
}
/**
* Debug routine which will output tracing if the System Property
* -Djavax.sql.rowset.RowSetFactory.debug is set
* @param msg - The debug message to display
*/
private static void trace(String msg) {
if (debug) {
System.err.println("###RowSets: " + msg);
}
}
}