提交 47d30ba4 编写于 作者: L lancea

6843995: RowSet 1.1 updates

Reviewed-by: darcy, valeriep
上级 ffe3a8bf
/*
* 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 com.sun.rowset;
import java.sql.SQLException;
import javax.sql.rowset.CachedRowSet;
import javax.sql.rowset.FilteredRowSet;
import javax.sql.rowset.JdbcRowSet;
import javax.sql.rowset.JoinRowSet;
import javax.sql.rowset.WebRowSet;
import javax.sql.rowset.RowSetFactory;
/**
* This is the implementation specific class for the
* <code>javax.sql.rowset.spi.RowSetFactory</code>. This is the platform
* default implementation for the Java SE platform.
*
* @author Lance Andersen
*
*
* @version 1.7
*/
public final class RowSetFactoryImpl implements RowSetFactory {
public CachedRowSet createCachedRowSet() throws SQLException {
return new com.sun.rowset.CachedRowSetImpl();
}
public FilteredRowSet createFilteredRowSet() throws SQLException {
return new com.sun.rowset.FilteredRowSetImpl();
}
public JdbcRowSet createJdbcRowSet() throws SQLException {
return new com.sun.rowset.JdbcRowSetImpl();
}
public JoinRowSet createJoinRowSet() throws SQLException {
return new com.sun.rowset.JoinRowSetImpl();
}
public WebRowSet createWebRowSet() throws SQLException {
return new com.sun.rowset.WebRowSetImpl();
}
}
/* /*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1523,9 +1523,12 @@ public interface CachedRowSet extends RowSet, Joinable { ...@@ -1523,9 +1523,12 @@ public interface CachedRowSet extends RowSet, Joinable {
* set to false, the changes will <b>not</b> be committed until one of the * set to false, the changes will <b>not</b> be committed until one of the
* <code>CachedRowSet</code> interface transaction methods is called. * <code>CachedRowSet</code> interface transaction methods is called.
* *
* @deprecated Because this field is final (it is part of an interface),
* its value cannot be changed.
* @see #commit * @see #commit
* @see #rollback * @see #rollback
*/ */
@Deprecated
public static final boolean COMMIT_ON_ACCEPT_CHANGES = true; public static final boolean COMMIT_ON_ACCEPT_CHANGES = true;
/** /**
...@@ -1620,3 +1623,4 @@ public interface CachedRowSet extends RowSet, Joinable { ...@@ -1620,3 +1623,4 @@ public interface CachedRowSet extends RowSet, Joinable {
public boolean previousPage() throws SQLException; public boolean previousPage() throws SQLException;
} }
/*
* 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.sql.SQLException;
/**
* An interface that defines the implementation of a factory that is used
* to obtain different types of {@code RowSet} implementations.
*
* @author Lance Andersen
* @since 1.7
*/
public interface RowSetFactory{
/**
* <p>Creates a new instance of a CachedRowSet.</p>
*
* @return A new instance of a CachedRowSet.
*
* @throws SQLException if a CachedRowSet cannot
* be created.
*
* @since 1.7
*/
public CachedRowSet createCachedRowSet() throws SQLException;
/**
* <p>Creates a new instance of a FilteredRowSet.</p>
*
* @return A new instance of a FilteredRowSet.
*
* @throws SQLException if a FilteredRowSet cannot
* be created.
*
* @since 1.7
*/
public FilteredRowSet createFilteredRowSet() throws SQLException;
/**
* <p>Creates a new instance of a JdbcRowSet.</p>
*
* @return A new instance of a JdbcRowSet.
*
* @throws SQLException if a JdbcRowSet cannot
* be created.
*
* @since 1.7
*/
public JdbcRowSet createJdbcRowSet() throws SQLException;
/**
* <p>Creates a new instance of a JoinRowSet.</p>
*
* @return A new instance of a JoinRowSet.
*
* @throws SQLException if a JoinRowSet cannot
* be created.
*
* @since 1.7
*/
public JoinRowSet createJoinRowSet() throws SQLException;
/**
* <p>Creates a new instance of a WebRowSet.</p>
*
* @return A new instance of a WebRowSet.
*
* @throws SQLException if a WebRowSet cannot
* be created.
*
* @since 1.7
*/
public WebRowSet createWebRowSet() throws SQLException;
}
\ No newline at end of file
/*
* 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.ServiceLoader;
import javax.sql.rowset.RowSetFactory;
/**
* 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 ServiceLocator API. The ServiceLocator API will look
* for a classname 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 (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
public Object 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() {
RowSetFactory theFactory = null;
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;
}
return theFactory;
}
/**
* Returns the requested System Property. If a {@code SecurityException}
* occurs, just return NULL
* @param propName - System property to retreive
* @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 = (String) AccessController.doPrivileged(new PrivilegedAction() {
public Object 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);
}
}
}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" <meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1"> content="text/html; charset=iso-8859-1">
<!-- <!--
Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it This code is free software; you can redistribute it and/or modify it
...@@ -78,7 +78,7 @@ object provides a fully updatable and scrollable tabular ...@@ -78,7 +78,7 @@ object provides a fully updatable and scrollable tabular
data structure as defined in the JDBC 3.0 specification. data structure as defined in the JDBC 3.0 specification.
<p> <p>
<li><a href="CachedRowSet.html"> <li><a href="CachedRowSet.html">
<b><code>CachedRowSet</code><sup><font size=-2>TM></font></sup</b></a> <b><code>CachedRowSet</code>&trade;</b></a>
- A <tt>CachedRowSet</tt> object is a JavaBeans<sup><font size=-2>TM</font></sup> - A <tt>CachedRowSet</tt> object is a JavaBeans<sup><font size=-2>TM</font></sup>
component that is scrollable, updatable, serializable, and generally disconnected from component that is scrollable, updatable, serializable, and generally disconnected from
the source of its data. A <tt>CachedRowSet</tt> object the source of its data. A <tt>CachedRowSet</tt> object
...@@ -148,7 +148,12 @@ href="spi/package-summary.html">javax.sql.rowset.spi</a> package for guidelines ...@@ -148,7 +148,12 @@ href="spi/package-summary.html">javax.sql.rowset.spi</a> package for guidelines
on <a href="spi/SyncProvider.html"><code>SyncProvider</code></a> implementations. on <a href="spi/SyncProvider.html"><code>SyncProvider</code></a> implementations.
<p> <p>
<ul> <ul>
<li><b>3.1 Role of the <code>BaseRowSet</code> Class</b> <li><b>3.1 Constructor</b>
<p>
All <code>RowSet</code> implementations <strong>must</strong> provide a
no-argument constructor.
</li>
<li><b>3.2 Role of the <code>BaseRowSet</code> Class</b>
<p> <p>
A compliant JDBC <code>RowSet</code> implementation <b>must</b> implement one or more A compliant JDBC <code>RowSet</code> implementation <b>must</b> implement one or more
standard interfaces specified in this package and and <b>may</b> extend the standard interfaces specified in this package and and <b>may</b> extend the
...@@ -215,7 +220,7 @@ by compliant implementations.<br> ...@@ -215,7 +220,7 @@ by compliant implementations.<br>
</table> </table>
</blockquote> </blockquote>
<p> <p>
<li><b>3.2 Connected RowSet Requirements</b> <li><b>3.3 Connected RowSet Requirements</b>
<p> <p>
The <code>JdbcRowSet</code> describes a <code>RowSet</code> object that <b>must</b> always The <code>JdbcRowSet</code> describes a <code>RowSet</code> object that <b>must</b> always
be connected to the originating data source. Implementations of the <code>JdbcRowSet</code> be connected to the originating data source. Implementations of the <code>JdbcRowSet</code>
...@@ -229,7 +234,7 @@ supply their needs by virtue of the presence of an underlying updatable and scro ...@@ -229,7 +234,7 @@ supply their needs by virtue of the presence of an underlying updatable and scro
<p> <p>
<li> <li>
<b>3.3 Disconnected RowSet Requirements</b> <b>3.4 Disconnected RowSet Requirements</b>
<p> <p>
A disconnected <code>RowSet</code> object, such as a <code>CachedRowSet</code> object, A disconnected <code>RowSet</code> object, such as a <code>CachedRowSet</code> object,
<b>should</b> delegate <b>should</b> delegate
...@@ -244,7 +249,7 @@ synchronization is required. A disconnected <code>RowSet</code> object should ...@@ -244,7 +249,7 @@ synchronization is required. A disconnected <code>RowSet</code> object should
therefore ensure that no therefore ensure that no
extraneous references remain on the <code>Connection</code> object. extraneous references remain on the <code>Connection</code> object.
<p> <p>
<li><b>3.4 Role of RowSetMetaDataImpl</b> <li><b>3.5 Role of RowSetMetaDataImpl</b>
<p> <p>
The <code>RowsetMetaDataImpl</code> class is a utility class that provides an implementation of the The <code>RowsetMetaDataImpl</code> class is a utility class that provides an implementation of the
<a href="../RowSetMetaData.html">RowSetMetaData</a> interface, supplying standard setter <a href="../RowSetMetaData.html">RowSetMetaData</a> interface, supplying standard setter
...@@ -252,7 +257,7 @@ method implementations for metadata for both connected and disconnected ...@@ -252,7 +257,7 @@ method implementations for metadata for both connected and disconnected
<code>RowSet</code> objects. All implementations are free to use this standard <code>RowSet</code> objects. All implementations are free to use this standard
implementation but are not required to do so. implementation but are not required to do so.
<p> <p>
<li><b>3.5 RowSetWarning Class</b> <li><b>3.6 RowSetWarning Class</b>
<p> <p>
The <code>RowSetWarning</code> class provides warnings that can be set The <code>RowSetWarning</code> class provides warnings that can be set
on <code>RowSet</code> implementations. on <code>RowSet</code> implementations.
...@@ -270,7 +275,7 @@ on it, and so on until there are no more warnings. ...@@ -270,7 +275,7 @@ on it, and so on until there are no more warnings.
<P> <P>
<li><b>3.6 The Joinable Interface</b> <li><b>3.7 The Joinable Interface</b>
<P> <P>
The <code>Joinable</code> interface provides both connected and disconnected The <code>Joinable</code> interface provides both connected and disconnected
<code>RowSet</code> objects with the capability to be added to a <code>RowSet</code> objects with the capability to be added to a
...@@ -279,6 +284,13 @@ A <code>RowSet</code> object that has implemented the <code>Joinable</code> ...@@ -279,6 +284,13 @@ A <code>RowSet</code> object that has implemented the <code>Joinable</code>
interface can set a match column, retrieve a match column, or unset a match column. interface can set a match column, retrieve a match column, or unset a match column.
A <code>JoinRowSet</code> object can then use the <code>RowSet</code> object's A <code>JoinRowSet</code> object can then use the <code>RowSet</code> object's
match column as a basis for adding the <code>RowSet</code> object. match column as a basis for adding the <code>RowSet</code> object.
</li>
<li><b>3.8 The RowSetFactory Interface</b>
<p>
A <code>RowSetFactory</code> implementation <strong>must</strong>
be provided.
</li>
</ul> </ul>
<h3><a name="relspec">4.0 Related Specifications</a></h3> <h3><a name="relspec">4.0 Related Specifications</a></h3>
......
/* /*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,13 +25,6 @@ ...@@ -25,13 +25,6 @@
package javax.sql.rowset.spi; package javax.sql.rowset.spi;
import java.util.Map;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Vector;
import java.util.Properties;
import java.util.Collection;
import java.util.StringTokenizer;
import java.util.logging.*; import java.util.logging.*;
import java.util.*; import java.util.*;
...@@ -216,68 +209,64 @@ public class SyncFactory { ...@@ -216,68 +209,64 @@ public class SyncFactory {
* Having a private constructor guarantees that no more than * Having a private constructor guarantees that no more than
* one <code>SyncProvider</code> object can exist at a time. * one <code>SyncProvider</code> object can exist at a time.
*/ */
private SyncFactory() {}; private SyncFactory() {
}
/** /**
* The standard property-id for a synchronization provider implementation * The standard property-id for a synchronization provider implementation
* name. * name.
*/ */
public static String ROWSET_SYNC_PROVIDER = public static final String ROWSET_SYNC_PROVIDER =
"rowset.provider.classname"; "rowset.provider.classname";
/** /**
* The standard property-id for a synchronization provider implementation * The standard property-id for a synchronization provider implementation
* vendor name. * vendor name.
*/ */
public static String ROWSET_SYNC_VENDOR = public static final String ROWSET_SYNC_VENDOR =
"rowset.provider.vendor"; "rowset.provider.vendor";
/** /**
* The standard property-id for a synchronization provider implementation * The standard property-id for a synchronization provider implementation
* version tag. * version tag.
*/ */
public static String ROWSET_SYNC_PROVIDER_VERSION = public static final String ROWSET_SYNC_PROVIDER_VERSION =
"rowset.provider.version"; "rowset.provider.version";
/** /**
* The standard resource file name. * The standard resource file name.
*/ */
private static String ROWSET_PROPERTIES = "rowset.properties"; private static String ROWSET_PROPERTIES = "rowset.properties";
/** /**
* The RI Optimistic Provider. * The RI Optimistic Provider.
*/ */
private static String default_provider = private static String default_provider =
"com.sun.rowset.providers.RIOptimisticProvider"; "com.sun.rowset.providers.RIOptimisticProvider";
/**
* Permission required to invoke setJNDIContext and setLogger
*/
private static final SQLPermission SET_SYNCFACTORY_PERMISSION =
new SQLPermission("setSyncFactory");
/** /**
* The initial JNDI context where <code>SyncProvider</code> implementations can * The initial JNDI context where <code>SyncProvider</code> implementations can
* be stored and from which they can be invoked. * be stored and from which they can be invoked.
*/ */
private static Context ic; private static Context ic;
/** /**
* The <code>Logger</code> object to be used by the <code>SyncFactory</code>. * The <code>Logger</code> object to be used by the <code>SyncFactory</code>.
*/ */
private static Logger rsLogger; private static Logger rsLogger;
/** /**
* *
*/ */
private static Level rsLevel; private static Level rsLevel;
/** /**
* The registry of available <code>SyncProvider</code> implementations. * The registry of available <code>SyncProvider</code> implementations.
* See section 2.0 of the class comment for <code>SyncFactory</code> for an * See section 2.0 of the class comment for <code>SyncFactory</code> for an
* explanation of how a provider can be added to this registry. * explanation of how a provider can be added to this registry.
*/ */
private static Hashtable implementations; private static Hashtable implementations;
/** /**
* Internal sync object used to maintain the SPI as a singleton * Internal sync object used to maintain the SPI as a singleton
*/ */
private static Object logSync = new Object(); private static Object logSync = new Object();
/** /**
* Internal PrintWriter field for logging facility * Internal PrintWriter field for logging facility
*/ */
...@@ -325,7 +314,7 @@ public class SyncFactory { ...@@ -325,7 +314,7 @@ public class SyncFactory {
* *
* @return the <code>SyncFactory</code> instance * @return the <code>SyncFactory</code> instance
*/ */
public static SyncFactory getSyncFactory(){ public static SyncFactory getSyncFactory() {
// This method uses the Singleton Design Pattern // This method uses the Singleton Design Pattern
// with Double-Checked Locking Pattern for // with Double-Checked Locking Pattern for
...@@ -339,9 +328,9 @@ public class SyncFactory { ...@@ -339,9 +328,9 @@ public class SyncFactory {
// that object. // that object.
// else go into synchronized block // else go into synchronized block
if(syncFactory == null){ if (syncFactory == null) {
synchronized(SyncFactory.class) { synchronized (SyncFactory.class) {
if(syncFactory == null){ if (syncFactory == null) {
syncFactory = new SyncFactory(); syncFactory = new SyncFactory();
} //end if } //end if
} //end synchronized block } //end synchronized block
...@@ -364,7 +353,6 @@ public class SyncFactory { ...@@ -364,7 +353,6 @@ public class SyncFactory {
implementations.remove(providerID); implementations.remove(providerID);
} }
} }
private static String colon = ":"; private static String colon = ":";
private static String strFileSep = "/"; private static String strFileSep = "/";
...@@ -395,7 +383,7 @@ public class SyncFactory { ...@@ -395,7 +383,7 @@ public class SyncFactory {
* Dependent on application * Dependent on application
*/ */
String strRowsetProperties = System.getProperty("rowset.properties"); String strRowsetProperties = System.getProperty("rowset.properties");
if ( strRowsetProperties != null) { if (strRowsetProperties != null) {
// Load user's implementation of SyncProvider // Load user's implementation of SyncProvider
// here. -Drowset.properties=/abc/def/pqr.txt // here. -Drowset.properties=/abc/def/pqr.txt
ROWSET_PROPERTIES = strRowsetProperties; ROWSET_PROPERTIES = strRowsetProperties;
...@@ -447,18 +435,15 @@ public class SyncFactory { ...@@ -447,18 +435,15 @@ public class SyncFactory {
} }
} }
} }
/** /**
* The internal boolean switch that indicates whether a JNDI * The internal boolean switch that indicates whether a JNDI
* context has been established or not. * context has been established or not.
*/ */
private static boolean jndiCtxEstablished = false; private static boolean jndiCtxEstablished = false;
/** /**
* The internal debug switch. * The internal debug switch.
*/ */
private static boolean debug = false; private static boolean debug = false;
/** /**
* Internal registry count for the number of providers contained in the * Internal registry count for the number of providers contained in the
* registry. * registry.
...@@ -475,9 +460,9 @@ public class SyncFactory { ...@@ -475,9 +460,9 @@ public class SyncFactory {
String key = null; String key = null;
String[] propertyNames = null; String[] propertyNames = null;
for (Enumeration e = p.propertyNames(); e.hasMoreElements() ;) { for (Enumeration e = p.propertyNames(); e.hasMoreElements();) {
String str = (String)e.nextElement(); String str = (String) e.nextElement();
int w = str.length(); int w = str.length();
...@@ -491,7 +476,7 @@ public class SyncFactory { ...@@ -491,7 +476,7 @@ public class SyncFactory {
propertyNames = getPropertyNames(false); propertyNames = getPropertyNames(false);
} else { } else {
// property index has been set. // property index has been set.
propertyNames = getPropertyNames(true, str.substring(w-1)); propertyNames = getPropertyNames(true, str.substring(w - 1));
} }
key = p.getProperty(propertyNames[0]); key = p.getProperty(propertyNames[0]);
...@@ -518,7 +503,7 @@ public class SyncFactory { ...@@ -518,7 +503,7 @@ public class SyncFactory {
String propertyIndex) { String propertyIndex) {
String dot = "."; String dot = ".";
String[] propertyNames = String[] propertyNames =
new String[] {SyncFactory.ROWSET_SYNC_PROVIDER, new String[]{SyncFactory.ROWSET_SYNC_PROVIDER,
SyncFactory.ROWSET_SYNC_VENDOR, SyncFactory.ROWSET_SYNC_VENDOR,
SyncFactory.ROWSET_SYNC_PROVIDER_VERSION}; SyncFactory.ROWSET_SYNC_PROVIDER_VERSION};
if (append) { if (append) {
...@@ -549,15 +534,21 @@ public class SyncFactory { ...@@ -549,15 +534,21 @@ public class SyncFactory {
* *
* @param providerID the unique identifier of the provider * @param providerID the unique identifier of the provider
* @return a <code>SyncProvider</code> implementation * @return a <code>SyncProvider</code> implementation
* @throws SyncFactoryException If the SyncProvider cannot be found or * @throws SyncFactoryException If the SyncProvider cannot be found,
* the providerID is {@code null}, or
* some error was encountered when trying to invoke this provider. * some error was encountered when trying to invoke this provider.
*/ */
public static SyncProvider getInstance(String providerID) public static SyncProvider getInstance(String providerID)
throws SyncFactoryException { throws SyncFactoryException {
if(providerID == null) {
throw new SyncFactoryException("The providerID cannot be null");
}
initMapIfNecessary(); // populate HashTable initMapIfNecessary(); // populate HashTable
initJNDIContext(); // check JNDI context for any additional bindings initJNDIContext(); // check JNDI context for any additional bindings
ProviderImpl impl = (ProviderImpl)implementations.get(providerID); ProviderImpl impl = (ProviderImpl) implementations.get(providerID);
if (impl == null) { if (impl == null) {
// Requested SyncProvider is unavailable. Return default provider. // Requested SyncProvider is unavailable. Return default provider.
...@@ -575,11 +566,10 @@ public class SyncFactory { ...@@ -575,11 +566,10 @@ public class SyncFactory {
* this SyncFactory and try to laod the SyncProvider class from * this SyncFactory and try to laod the SyncProvider class from
* there. * there.
**/ **/
c = Class.forName(providerID, true, cl); c = Class.forName(providerID, true, cl);
if (c != null) { if (c != null) {
return (SyncProvider)c.newInstance(); return (SyncProvider) c.newInstance();
} else { } else {
return new com.sun.rowset.providers.RIOptimisticProvider(); return new com.sun.rowset.providers.RIOptimisticProvider();
} }
...@@ -592,6 +582,7 @@ public class SyncFactory { ...@@ -592,6 +582,7 @@ public class SyncFactory {
throw new SyncFactoryException("ClassNotFoundException: " + e.getMessage()); throw new SyncFactoryException("ClassNotFoundException: " + e.getMessage());
} }
} }
/** /**
* Returns an Enumeration of currently registered synchronization * Returns an Enumeration of currently registered synchronization
* providers. A <code>RowSet</code> implementation may use any provider in * providers. A <code>RowSet</code> implementation may use any provider in
...@@ -618,10 +609,26 @@ public class SyncFactory { ...@@ -618,10 +609,26 @@ public class SyncFactory {
* <code>SyncProvider</code> implementations can log their events to * <code>SyncProvider</code> implementations can log their events to
* this object and the application can retrieve a handle to this * this object and the application can retrieve a handle to this
* object using the <code>getLogger</code> method. * object using the <code>getLogger</code> method.
* <p>
* This method checks to see that there is an {@code SQLPermission}
* object which grants the permission {@code setSyncFactory}
* before allowing the method to succeed. If a
* {@code SecurityManager} exists and its
* {@code checkPermission} method denies calling {@code setLogger},
* this method throws a
* {@code java.lang.SecurityException}.
* *
* @param logger A Logger object instance * @param logger A Logger object instance
* @throws java.lang.SecurityException if a security manager exists and its
* {@code checkPermission} method denies calling {@code setLogger}
* @see SecurityManager#checkPermission
*/ */
public static void setLogger(Logger logger) { public static void setLogger(Logger logger) {
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
}
rsLogger = logger; rsLogger = logger;
} }
...@@ -631,14 +638,28 @@ public class SyncFactory { ...@@ -631,14 +638,28 @@ public class SyncFactory {
* <code>SyncProvider</code> implementations can log their events * <code>SyncProvider</code> implementations can log their events
* to this object and the application can retrieve a handle to this * to this object and the application can retrieve a handle to this
* object using the <code>getLogger</code> method. * object using the <code>getLogger</code> method.
* <p>
* This method checks to see that there is an {@code SQLPermission}
* object which grants the permission {@code setSyncFactory}
* before allowing the method to succeed. If a
* {@code SecurityManager} exists and its
* {@code checkPermission} method denies calling {@code setLogger},
* this method throws a
* {@code java.lang.SecurityException}.
* *
* @param logger a Logger object instance * @param logger a Logger object instance
* @param level a Level object instance indicating the degree of logging * @param level a Level object instance indicating the degree of logging
* required * required
* @throws java.lang.SecurityException if a security manager exists and its
* {@code checkPermission} method denies calling {@code setLogger}
* @see SecurityManager#checkPermission
*/ */
public static void setLogger(Logger logger, Level level) { public static void setLogger(Logger logger, Level level) {
// singleton // singleton
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
}
rsLogger = logger; rsLogger = logger;
rsLogger.setLevel(level); rsLogger.setLevel(level);
} }
...@@ -651,7 +672,7 @@ public class SyncFactory { ...@@ -651,7 +672,7 @@ public class SyncFactory {
*/ */
public static Logger getLogger() throws SyncFactoryException { public static Logger getLogger() throws SyncFactoryException {
// only one logger per session // only one logger per session
if(rsLogger == null){ if (rsLogger == null) {
throw new SyncFactoryException("(SyncFactory) : No logger has been set"); throw new SyncFactoryException("(SyncFactory) : No logger has been set");
} }
return rsLogger; return rsLogger;
...@@ -660,12 +681,27 @@ public class SyncFactory { ...@@ -660,12 +681,27 @@ public class SyncFactory {
/** /**
* Sets the initial JNDI context from which SyncProvider implementations * Sets the initial JNDI context from which SyncProvider implementations
* can be retrieved from a JNDI namespace * can be retrieved from a JNDI namespace
* <p>
* This method checks to see that there is an {@code SQLPermission}
* object which grants the permission {@code setSyncFactory}
* before allowing the method to succeed. If a
* {@code SecurityManager} exists and its
* {@code checkPermission} method denies calling {@code setJNDIContext},
* this method throws a
* {@code java.lang.SecurityException}.
* *
* @param ctx a valid JNDI context * @param ctx a valid JNDI context
* @throws SyncFactoryException if the supplied JNDI context is null * @throws SyncFactoryException if the supplied JNDI context is null
* @throws java.lang.SecurityException if a security manager exists and its
* {@code checkPermission} method denies calling {@code setJNDIContext}
* @see SecurityManager#checkPermission
*/ */
public static void setJNDIContext(javax.naming.Context ctx) public static void setJNDIContext(javax.naming.Context ctx)
throws SyncFactoryException { throws SyncFactoryException {
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
}
if (ctx == null) { if (ctx == null) {
throw new SyncFactoryException("Invalid JNDI context supplied"); throw new SyncFactoryException("Invalid JNDI context supplied");
} }
...@@ -729,7 +765,7 @@ public class SyncFactory { ...@@ -729,7 +765,7 @@ public class SyncFactory {
Object elementObj = null; Object elementObj = null;
String element = null; String element = null;
while (bindings.hasMore()) { while (bindings.hasMore()) {
bd = (Binding)bindings.next(); bd = (Binding) bindings.next();
element = bd.getName(); element = bd.getName();
elementObj = bd.getObject(); elementObj = bd.getObject();
...@@ -741,7 +777,7 @@ public class SyncFactory { ...@@ -741,7 +777,7 @@ public class SyncFactory {
} }
if (syncProviderObj) { if (syncProviderObj) {
SyncProvider sync = (SyncProvider)elementObj; SyncProvider sync = (SyncProvider) elementObj;
properties.put(SyncFactory.ROWSET_SYNC_PROVIDER, properties.put(SyncFactory.ROWSET_SYNC_PROVIDER,
sync.getProviderID()); sync.getProviderID());
syncProviderObj = false; // reset syncProviderObj = false; // reset
...@@ -756,11 +792,12 @@ public class SyncFactory { ...@@ -756,11 +792,12 @@ public class SyncFactory {
} }
} }
/** /**
* Internal class that defines the lazy reference construct for each registered * Internal class that defines the lazy reference construct for each registered
* SyncProvider implementation. * SyncProvider implementation.
*/ */
class ProviderImpl extends SyncProvider { class ProviderImpl extends SyncProvider {
private String className = null; private String className = null;
private String vendorName = null; private String vendorName = null;
private String ver = null; private String ver = null;
...@@ -801,10 +838,9 @@ public class SyncFactory { ...@@ -801,10 +838,9 @@ public class SyncFactory {
public int getDataSourceLock() throws SyncProviderException { public int getDataSourceLock() throws SyncProviderException {
int dsLock = 0; int dsLock = 0;
try try {
{
dsLock = SyncFactory.getInstance(className).getDataSourceLock(); dsLock = SyncFactory.getInstance(className).getDataSourceLock();
} catch(SyncFactoryException sfEx) { } catch (SyncFactoryException sfEx) {
throw new SyncProviderException(sfEx.getMessage()); throw new SyncProviderException(sfEx.getMessage());
} }
...@@ -816,10 +852,9 @@ public class SyncFactory { ...@@ -816,10 +852,9 @@ public class SyncFactory {
int grade = 0; int grade = 0;
try try {
{
grade = SyncFactory.getInstance(className).getProviderGrade(); grade = SyncFactory.getInstance(className).getProviderGrade();
} catch(SyncFactoryException sfEx) { } catch (SyncFactoryException sfEx) {
// //
} }
...@@ -840,15 +875,13 @@ public class SyncFactory { ...@@ -840,15 +875,13 @@ public class SyncFactory {
} }
} }
*/ */
public javax.sql.RowSetReader getRowSetReader() { public javax.sql.RowSetReader getRowSetReader() {
RowSetReader rsReader = null;; RowSetReader rsReader = null;
try try {
{
rsReader = SyncFactory.getInstance(className).getRowSetReader(); rsReader = SyncFactory.getInstance(className).getRowSetReader();
} catch(SyncFactoryException sfEx) { } catch (SyncFactoryException sfEx) {
// //
} }
...@@ -859,22 +892,21 @@ public class SyncFactory { ...@@ -859,22 +892,21 @@ public class SyncFactory {
public javax.sql.RowSetWriter getRowSetWriter() { public javax.sql.RowSetWriter getRowSetWriter() {
RowSetWriter rsWriter = null; RowSetWriter rsWriter = null;
try try {
{
rsWriter = SyncFactory.getInstance(className).getRowSetWriter(); rsWriter = SyncFactory.getInstance(className).getRowSetWriter();
} catch(SyncFactoryException sfEx) { } catch (SyncFactoryException sfEx) {
// //
} }
return rsWriter; return rsWriter;
} }
public void setDataSourceLock(int param) public void setDataSourceLock(int param)
throws SyncProviderException { throws SyncProviderException {
try try {
{
SyncFactory.getInstance(className).setDataSourceLock(param); SyncFactory.getInstance(className).setDataSourceLock(param);
} catch(SyncFactoryException sfEx) { } catch (SyncFactoryException sfEx) {
throw new SyncProviderException(sfEx.getMessage()); throw new SyncProviderException(sfEx.getMessage());
} }
...@@ -884,14 +916,12 @@ public class SyncFactory { ...@@ -884,14 +916,12 @@ public class SyncFactory {
int view = 0; int view = 0;
try try {
{
view = SyncFactory.getInstance(className).supportsUpdatableView(); view = SyncFactory.getInstance(className).supportsUpdatableView();
} catch(SyncFactoryException sfEx) { } catch (SyncFactoryException sfEx) {
// //
} }
return view; return view;
} }
}
}
/* /*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -344,7 +344,7 @@ public abstract class SyncProvider { ...@@ -344,7 +344,7 @@ public abstract class SyncProvider {
* source without checking the validity of any data. * source without checking the validity of any data.
* *
*/ */
public static int GRADE_NONE = 1; public static final int GRADE_NONE = 1;
/** /**
* Indicates a low level optimistic synchronization grade with * Indicates a low level optimistic synchronization grade with
...@@ -354,7 +354,7 @@ public abstract class SyncProvider { ...@@ -354,7 +354,7 @@ public abstract class SyncProvider {
* returning this grade will check only rows that have changed. * returning this grade will check only rows that have changed.
* *
*/ */
public static int GRADE_CHECK_MODIFIED_AT_COMMIT = 2; public static final int GRADE_CHECK_MODIFIED_AT_COMMIT = 2;
/** /**
* Indicates a high level optimistic synchronization grade with * Indicates a high level optimistic synchronization grade with
...@@ -364,7 +364,7 @@ public abstract class SyncProvider { ...@@ -364,7 +364,7 @@ public abstract class SyncProvider {
* returning this grade will check all rows, including rows that have not * returning this grade will check all rows, including rows that have not
* changed. * changed.
*/ */
public static int GRADE_CHECK_ALL_AT_COMMIT = 3; public static final int GRADE_CHECK_ALL_AT_COMMIT = 3;
/** /**
* Indicates a pessimistic synchronization grade with * Indicates a pessimistic synchronization grade with
...@@ -374,7 +374,7 @@ public abstract class SyncProvider { ...@@ -374,7 +374,7 @@ public abstract class SyncProvider {
* implementation returning this grade will lock the row in the originating * implementation returning this grade will lock the row in the originating
* data source. * data source.
*/ */
public static int GRADE_LOCK_WHEN_MODIFIED = 4; public static final int GRADE_LOCK_WHEN_MODIFIED = 4;
/** /**
* Indicates the most pessimistic synchronization grade with * Indicates the most pessimistic synchronization grade with
...@@ -384,47 +384,47 @@ public abstract class SyncProvider { ...@@ -384,47 +384,47 @@ public abstract class SyncProvider {
* table affected by the original statement used to populate a * table affected by the original statement used to populate a
* <code>RowSet</code> object. * <code>RowSet</code> object.
*/ */
public static int GRADE_LOCK_WHEN_LOADED = 5; public static final int GRADE_LOCK_WHEN_LOADED = 5;
/** /**
* Indicates that no locks remain on the originating data source. This is the default * Indicates that no locks remain on the originating data source. This is the default
* lock setting for all <code>SyncProvider</code> implementations unless * lock setting for all <code>SyncProvider</code> implementations unless
* otherwise directed by a <code>RowSet</code> object. * otherwise directed by a <code>RowSet</code> object.
*/ */
public static int DATASOURCE_NO_LOCK = 1; public static final int DATASOURCE_NO_LOCK = 1;
/** /**
* Indicates that a lock is placed on the rows that are touched by the original * Indicates that a lock is placed on the rows that are touched by the original
* SQL statement used to populate the <code>RowSet</code> object * SQL statement used to populate the <code>RowSet</code> object
* that is using this <code>SyncProvider</code> object. * that is using this <code>SyncProvider</code> object.
*/ */
public static int DATASOURCE_ROW_LOCK = 2; public static final int DATASOURCE_ROW_LOCK = 2;
/** /**
* Indicates that a lock is placed on all tables that are touched by the original * Indicates that a lock is placed on all tables that are touched by the original
* SQL statement used to populate the <code>RowSet</code> object * SQL statement used to populate the <code>RowSet</code> object
* that is using this <code>SyncProvider</code> object. * that is using this <code>SyncProvider</code> object.
*/ */
public static int DATASOURCE_TABLE_LOCK = 3; public static final int DATASOURCE_TABLE_LOCK = 3;
/** /**
* Indicates that a lock is placed on the entire data source that is the source of * Indicates that a lock is placed on the entire data source that is the source of
* data for the <code>RowSet</code> object * data for the <code>RowSet</code> object
* that is using this <code>SyncProvider</code> object. * that is using this <code>SyncProvider</code> object.
*/ */
public static int DATASOURCE_DB_LOCK = 4; public static final int DATASOURCE_DB_LOCK = 4;
/** /**
* Indicates that a <code>SyncProvider</code> implementation * Indicates that a <code>SyncProvider</code> implementation
* supports synchronization between a <code>RowSet</code> object and * supports synchronization between a <code>RowSet</code> object and
* the SQL <code>VIEW</code> used to populate it. * the SQL <code>VIEW</code> used to populate it.
*/ */
public static int UPDATABLE_VIEW_SYNC = 5; public static final int UPDATABLE_VIEW_SYNC = 5;
/** /**
* Indicates that a <code>SyncProvider</code> implementation * Indicates that a <code>SyncProvider</code> implementation
* does <B>not</B> support synchronization between a <code>RowSet</code> * does <B>not</B> support synchronization between a <code>RowSet</code>
* object and the SQL <code>VIEW</code> used to populate it. * object and the SQL <code>VIEW</code> used to populate it.
*/ */
public static int NONUPDATABLE_VIEW_SYNC = 6; public static final int NONUPDATABLE_VIEW_SYNC = 6;
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册