feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
967
jdkSrc/jdk8/javax/sql/rowset/spi/SyncFactory.java
Normal file
967
jdkSrc/jdk8/javax/sql/rowset/spi/SyncFactory.java
Normal file
@@ -0,0 +1,967 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, 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.spi;
|
||||
|
||||
import java.util.logging.*;
|
||||
import java.util.*;
|
||||
|
||||
import java.sql.*;
|
||||
import javax.sql.*;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
|
||||
import javax.naming.*;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* The Service Provider Interface (SPI) mechanism that generates <code>SyncProvider</code>
|
||||
* instances to be used by disconnected <code>RowSet</code> objects.
|
||||
* The <code>SyncProvider</code> instances in turn provide the
|
||||
* <code>javax.sql.RowSetReader</code> object the <code>RowSet</code> object
|
||||
* needs to populate itself with data and the
|
||||
* <code>javax.sql.RowSetWriter</code> object it needs to
|
||||
* propagate changes to its
|
||||
* data back to the underlying data source.
|
||||
* <P>
|
||||
* Because the methods in the <code>SyncFactory</code> class are all static,
|
||||
* there is only one <code>SyncFactory</code> object
|
||||
* per Java VM at any one time. This ensures that there is a single source from which a
|
||||
* <code>RowSet</code> implementation can obtain its <code>SyncProvider</code>
|
||||
* implementation.
|
||||
*
|
||||
* <h3>1.0 Overview</h3>
|
||||
* The <code>SyncFactory</code> class provides an internal registry of available
|
||||
* synchronization provider implementations (<code>SyncProvider</code> objects).
|
||||
* This registry may be queried to determine which
|
||||
* synchronization providers are available.
|
||||
* The following line of code gets an enumeration of the providers currently registered.
|
||||
* <PRE>
|
||||
* java.util.Enumeration e = SyncFactory.getRegisteredProviders();
|
||||
* </PRE>
|
||||
* All standard <code>RowSet</code> implementations must provide at least two providers:
|
||||
* <UL>
|
||||
* <LI>an optimistic provider for use with a <code>CachedRowSet</code> implementation
|
||||
* or an implementation derived from it
|
||||
* <LI>an XML provider, which is used for reading and writing XML, such as with
|
||||
* <code>WebRowSet</code> objects
|
||||
* </UL>
|
||||
* Note that the JDBC RowSet Implementations include the <code>SyncProvider</code>
|
||||
* implementations <code>RIOptimisticProvider</code> and <code>RIXmlProvider</code>,
|
||||
* which satisfy this requirement.
|
||||
* <P>
|
||||
* The <code>SyncFactory</code> class provides accessor methods to assist
|
||||
* applications in determining which synchronization providers are currently
|
||||
* registered with the <code>SyncFactory</code>.
|
||||
* <p>
|
||||
* Other methods let <code>RowSet</code> persistence providers be
|
||||
* registered or de-registered with the factory mechanism. This
|
||||
* allows additional synchronization provider implementations to be made
|
||||
* available to <code>RowSet</code> objects at run time.
|
||||
* <p>
|
||||
* Applications can apply a degree of filtering to determine the level of
|
||||
* synchronization that a <code>SyncProvider</code> implementation offers.
|
||||
* The following criteria determine whether a provider is
|
||||
* made available to a <code>RowSet</code> object:
|
||||
* <ol>
|
||||
* <li>If a particular provider is specified by a <code>RowSet</code> object, and
|
||||
* the <code>SyncFactory</code> does not contain a reference to this provider,
|
||||
* a <code>SyncFactoryException</code> is thrown stating that the synchronization
|
||||
* provider could not be found.
|
||||
*
|
||||
* <li>If a <code>RowSet</code> implementation is instantiated with a specified
|
||||
* provider and the specified provider has been properly registered, the
|
||||
* requested provider is supplied. Otherwise a <code>SyncFactoryException</code>
|
||||
* is thrown.
|
||||
*
|
||||
* <li>If a <code>RowSet</code> object does not specify a
|
||||
* <code>SyncProvider</code> implementation and no additional
|
||||
* <code>SyncProvider</code> implementations are available, the reference
|
||||
* implementation providers are supplied.
|
||||
* </ol>
|
||||
* <h3>2.0 Registering <code>SyncProvider</code> Implementations</h3>
|
||||
* <p>
|
||||
* Both vendors and developers can register <code>SyncProvider</code>
|
||||
* implementations using one of the following mechanisms.
|
||||
* <ul>
|
||||
* <LI><B>Using the command line</B><BR>
|
||||
* The name of the provider is supplied on the command line, which will add
|
||||
* the provider to the system properties.
|
||||
* For example:
|
||||
* <PRE>
|
||||
* -Drowset.provider.classname=com.fred.providers.HighAvailabilityProvider
|
||||
* </PRE>
|
||||
* <li><b>Using the Standard Properties File</b><BR>
|
||||
* The reference implementation is targeted
|
||||
* to ship with J2SE 1.5, which will include an additional resource file
|
||||
* that may be edited by hand. Here is an example of the properties file
|
||||
* included in the reference implementation:
|
||||
* <PRE>
|
||||
* #Default JDBC RowSet sync providers listing
|
||||
* #
|
||||
*
|
||||
* # Optimistic synchronization provider
|
||||
* rowset.provider.classname.0=com.sun.rowset.providers.RIOptimisticProvider
|
||||
* rowset.provider.vendor.0=Oracle Corporation
|
||||
* rowset.provider.version.0=1.0
|
||||
*
|
||||
* # XML Provider using standard XML schema
|
||||
* rowset.provider.classname.1=com.sun.rowset.providers.RIXMLProvider
|
||||
* rowset.provider.vendor.1=Oracle Corporation
|
||||
* rowset.provider.version.1=1.0
|
||||
* </PRE>
|
||||
* The <code>SyncFactory</code> checks this file and registers the
|
||||
* <code>SyncProvider</code> implementations that it contains. A
|
||||
* developer or vendor can add other implementations to this file.
|
||||
* For example, here is a possible addition:
|
||||
* <PRE>
|
||||
* rowset.provider.classname.2=com.fred.providers.HighAvailabilityProvider
|
||||
* rowset.provider.vendor.2=Fred, Inc.
|
||||
* rowset.provider.version.2=1.0
|
||||
* </PRE>
|
||||
*
|
||||
* <li><b>Using a JNDI Context</b><BR>
|
||||
* Available providers can be registered on a JNDI
|
||||
* context, and the <code>SyncFactory</code> will attempt to load
|
||||
* <code>SyncProvider</code> implementations from that JNDI context.
|
||||
* For example, the following code fragment registers a provider implementation
|
||||
* on a JNDI context. This is something a deployer would normally do. In this
|
||||
* example, <code>MyProvider</code> is being registered on a CosNaming
|
||||
* namespace, which is the namespace used by J2EE resources.
|
||||
* <PRE>
|
||||
* import javax.naming.*;
|
||||
*
|
||||
* Hashtable svrEnv = new Hashtable();
|
||||
* srvEnv.put(Context.INITIAL_CONTEXT_FACTORY, "CosNaming");
|
||||
*
|
||||
* Context ctx = new InitialContext(svrEnv);
|
||||
* com.fred.providers.MyProvider = new MyProvider();
|
||||
* ctx.rebind("providers/MyProvider", syncProvider);
|
||||
* </PRE>
|
||||
* </ul>
|
||||
* Next, an application will register the JNDI context with the
|
||||
* <code>SyncFactory</code> instance. This allows the <code>SyncFactory</code>
|
||||
* to browse within the JNDI context looking for <code>SyncProvider</code>
|
||||
* implementations.
|
||||
* <PRE>
|
||||
* Hashtable appEnv = new Hashtable();
|
||||
* appEnv.put(Context.INITIAL_CONTEXT_FACTORY, "CosNaming");
|
||||
* appEnv.put(Context.PROVIDER_URL, "iiop://hostname/providers");
|
||||
* Context ctx = new InitialContext(appEnv);
|
||||
*
|
||||
* SyncFactory.registerJNDIContext(ctx);
|
||||
* </PRE>
|
||||
* If a <code>RowSet</code> object attempts to obtain a <code>MyProvider</code>
|
||||
* object, the <code>SyncFactory</code> will try to locate it. First it searches
|
||||
* for it in the system properties, then it looks in the resource files, and
|
||||
* finally it checks the JNDI context that has been set. The <code>SyncFactory</code>
|
||||
* instance verifies that the requested provider is a valid extension of the
|
||||
* <code>SyncProvider</code> abstract class and then gives it to the
|
||||
* <code>RowSet</code> object. In the following code fragment, a new
|
||||
* <code>CachedRowSet</code> object is created and initialized with
|
||||
* <i>env</i>, which contains the binding to <code>MyProvider</code>.
|
||||
* <PRE>
|
||||
* Hashtable env = new Hashtable();
|
||||
* env.put(SyncFactory.ROWSET_SYNC_PROVIDER, "com.fred.providers.MyProvider");
|
||||
* CachedRowSet crs = new com.sun.rowset.CachedRowSetImpl(env);
|
||||
* </PRE>
|
||||
* Further details on these mechanisms are available in the
|
||||
* <code>javax.sql.rowset.spi</code> package specification.
|
||||
*
|
||||
* @author Jonathan Bruce
|
||||
* @see javax.sql.rowset.spi.SyncProvider
|
||||
* @see javax.sql.rowset.spi.SyncFactoryException
|
||||
*/
|
||||
public class SyncFactory {
|
||||
|
||||
/**
|
||||
* Creates a new <code>SyncFactory</code> object, which is the singleton
|
||||
* instance.
|
||||
* Having a private constructor guarantees that no more than
|
||||
* one <code>SyncProvider</code> object can exist at a time.
|
||||
*/
|
||||
private SyncFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard property-id for a synchronization provider implementation
|
||||
* name.
|
||||
*/
|
||||
public static final String ROWSET_SYNC_PROVIDER =
|
||||
"rowset.provider.classname";
|
||||
/**
|
||||
* The standard property-id for a synchronization provider implementation
|
||||
* vendor name.
|
||||
*/
|
||||
public static final String ROWSET_SYNC_VENDOR =
|
||||
"rowset.provider.vendor";
|
||||
/**
|
||||
* The standard property-id for a synchronization provider implementation
|
||||
* version tag.
|
||||
*/
|
||||
public static final String ROWSET_SYNC_PROVIDER_VERSION =
|
||||
"rowset.provider.version";
|
||||
/**
|
||||
* The standard resource file name.
|
||||
*/
|
||||
private static String ROWSET_PROPERTIES = "rowset.properties";
|
||||
|
||||
/**
|
||||
* 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
|
||||
* be stored and from which they can be invoked.
|
||||
*/
|
||||
private static Context ic;
|
||||
/**
|
||||
* The <code>Logger</code> object to be used by the <code>SyncFactory</code>.
|
||||
*/
|
||||
private static volatile Logger rsLogger;
|
||||
|
||||
/**
|
||||
* The registry of available <code>SyncProvider</code> implementations.
|
||||
* 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.
|
||||
*/
|
||||
private static Hashtable<String, SyncProvider> implementations;
|
||||
|
||||
/**
|
||||
* Adds the the given synchronization provider to the factory register. Guidelines
|
||||
* are provided in the <code>SyncProvider</code> specification for the
|
||||
* required naming conventions for <code>SyncProvider</code>
|
||||
* implementations.
|
||||
* <p>
|
||||
* Synchronization providers bound to a JNDI context can be
|
||||
* registered by binding a SyncProvider instance to a JNDI namespace.
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* SyncProvider p = new MySyncProvider();
|
||||
* InitialContext ic = new InitialContext();
|
||||
* ic.bind ("jdbc/rowset/MySyncProvider", p);
|
||||
* } </pre>
|
||||
*
|
||||
* Furthermore, an initial JNDI context should be set with the
|
||||
* <code>SyncFactory</code> using the <code>setJNDIContext</code> method.
|
||||
* The <code>SyncFactory</code> leverages this context to search for
|
||||
* available <code>SyncProvider</code> objects bound to the JNDI
|
||||
* context and its child nodes.
|
||||
*
|
||||
* @param providerID A <code>String</code> object with the unique ID of the
|
||||
* synchronization provider being registered
|
||||
* @throws SyncFactoryException if an attempt is made to supply an empty
|
||||
* or null provider name
|
||||
* @see #setJNDIContext
|
||||
*/
|
||||
public static synchronized void registerProvider(String providerID)
|
||||
throws SyncFactoryException {
|
||||
|
||||
ProviderImpl impl = new ProviderImpl();
|
||||
impl.setClassname(providerID);
|
||||
initMapIfNecessary();
|
||||
implementations.put(providerID, impl);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>SyncFactory</code> singleton.
|
||||
*
|
||||
* @return the <code>SyncFactory</code> instance
|
||||
*/
|
||||
public static SyncFactory getSyncFactory() {
|
||||
/*
|
||||
* Using Initialization on Demand Holder idiom as
|
||||
* Effective Java 2nd Edition,ITEM 71, indicates it is more performant
|
||||
* than the Double-Check Locking idiom.
|
||||
*/
|
||||
return SyncFactoryHolder.factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the designated currently registered synchronization provider from the
|
||||
* Factory SPI register.
|
||||
*
|
||||
* @param providerID The unique-id of the synchronization provider
|
||||
* @throws SyncFactoryException If an attempt is made to
|
||||
* unregister a SyncProvider implementation that was not registered.
|
||||
*/
|
||||
public static synchronized void unregisterProvider(String providerID)
|
||||
throws SyncFactoryException {
|
||||
initMapIfNecessary();
|
||||
if (implementations.containsKey(providerID)) {
|
||||
implementations.remove(providerID);
|
||||
}
|
||||
}
|
||||
private static String colon = ":";
|
||||
private static String strFileSep = "/";
|
||||
|
||||
private static synchronized void initMapIfNecessary() throws SyncFactoryException {
|
||||
|
||||
// Local implementation class names and keys from Properties
|
||||
// file, translate names into Class objects using Class.forName
|
||||
// and store mappings
|
||||
final Properties properties = new Properties();
|
||||
|
||||
if (implementations == null) {
|
||||
implementations = new Hashtable<>();
|
||||
|
||||
try {
|
||||
|
||||
// check if user is supplying his Synchronisation Provider
|
||||
// Implementation if not using Oracle's implementation.
|
||||
// properties.load(new FileInputStream(ROWSET_PROPERTIES));
|
||||
|
||||
// The rowset.properties needs to be in jdk/jre/lib when
|
||||
// integrated with jdk.
|
||||
// else it should be picked from -D option from command line.
|
||||
|
||||
// -Drowset.properties will add to standard properties. Similar
|
||||
// keys will over-write
|
||||
|
||||
/*
|
||||
* Dependent on application
|
||||
*/
|
||||
String strRowsetProperties;
|
||||
try {
|
||||
strRowsetProperties = AccessController.doPrivileged(new PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
return System.getProperty("rowset.properties");
|
||||
}
|
||||
}, null, new PropertyPermission("rowset.properties", "read"));
|
||||
} catch (Exception ex) {
|
||||
System.out.println("errorget rowset.properties: " + ex);
|
||||
strRowsetProperties = null;
|
||||
};
|
||||
|
||||
if (strRowsetProperties != null) {
|
||||
// Load user's implementation of SyncProvider
|
||||
// here. -Drowset.properties=/abc/def/pqr.txt
|
||||
ROWSET_PROPERTIES = strRowsetProperties;
|
||||
try (FileInputStream fis = new FileInputStream(ROWSET_PROPERTIES)) {
|
||||
properties.load(fis);
|
||||
}
|
||||
parseProperties(properties);
|
||||
}
|
||||
|
||||
/*
|
||||
* Always available
|
||||
*/
|
||||
ROWSET_PROPERTIES = "javax" + strFileSep + "sql" +
|
||||
strFileSep + "rowset" + strFileSep +
|
||||
"rowset.properties";
|
||||
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
try {
|
||||
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
|
||||
try (InputStream stream = (cl == null) ?
|
||||
ClassLoader.getSystemResourceAsStream(ROWSET_PROPERTIES)
|
||||
: cl.getResourceAsStream(ROWSET_PROPERTIES)) {
|
||||
if (stream == null) {
|
||||
throw new SyncFactoryException("Resource " + ROWSET_PROPERTIES + " not found");
|
||||
}
|
||||
properties.load(stream);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
} catch (PrivilegedActionException ex) {
|
||||
Throwable e = ex.getException();
|
||||
if (e instanceof SyncFactoryException) {
|
||||
throw (SyncFactoryException) e;
|
||||
} else {
|
||||
SyncFactoryException sfe = new SyncFactoryException();
|
||||
sfe.initCause(ex.getException());
|
||||
throw sfe;
|
||||
}
|
||||
}
|
||||
|
||||
parseProperties(properties);
|
||||
|
||||
// removed else, has properties should sum together
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new SyncFactoryException("Cannot locate properties file: " + e);
|
||||
} catch (IOException e) {
|
||||
throw new SyncFactoryException("IOException: " + e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now deal with -Drowset.provider.classname
|
||||
* load additional properties from -D command line
|
||||
*/
|
||||
properties.clear();
|
||||
String providerImpls;
|
||||
try {
|
||||
providerImpls = AccessController.doPrivileged(new PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
return System.getProperty(ROWSET_SYNC_PROVIDER);
|
||||
}
|
||||
}, null, new PropertyPermission(ROWSET_SYNC_PROVIDER, "read"));
|
||||
} catch (Exception ex) {
|
||||
providerImpls = null;
|
||||
}
|
||||
|
||||
if (providerImpls != null) {
|
||||
int i = 0;
|
||||
if (providerImpls.indexOf(colon) > 0) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(providerImpls, colon);
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
properties.put(ROWSET_SYNC_PROVIDER + "." + i, tokenizer.nextToken());
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
properties.put(ROWSET_SYNC_PROVIDER, providerImpls);
|
||||
}
|
||||
parseProperties(properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The internal debug switch.
|
||||
*/
|
||||
private static boolean debug = false;
|
||||
/**
|
||||
* Internal registry count for the number of providers contained in the
|
||||
* registry.
|
||||
*/
|
||||
private static int providerImplIndex = 0;
|
||||
|
||||
/**
|
||||
* Internal handler for all standard property parsing. Parses standard
|
||||
* ROWSET properties and stores lazy references into the the internal registry.
|
||||
*/
|
||||
private static void parseProperties(Properties p) {
|
||||
|
||||
ProviderImpl impl = null;
|
||||
String key = null;
|
||||
String[] propertyNames = null;
|
||||
|
||||
for (Enumeration<?> e = p.propertyNames(); e.hasMoreElements();) {
|
||||
|
||||
String str = (String) e.nextElement();
|
||||
|
||||
int w = str.length();
|
||||
|
||||
if (str.startsWith(SyncFactory.ROWSET_SYNC_PROVIDER)) {
|
||||
|
||||
impl = new ProviderImpl();
|
||||
impl.setIndex(providerImplIndex++);
|
||||
|
||||
if (w == (SyncFactory.ROWSET_SYNC_PROVIDER).length()) {
|
||||
// no property index has been set.
|
||||
propertyNames = getPropertyNames(false);
|
||||
} else {
|
||||
// property index has been set.
|
||||
propertyNames = getPropertyNames(true, str.substring(w - 1));
|
||||
}
|
||||
|
||||
key = p.getProperty(propertyNames[0]);
|
||||
impl.setClassname(key);
|
||||
impl.setVendor(p.getProperty(propertyNames[1]));
|
||||
impl.setVersion(p.getProperty(propertyNames[2]));
|
||||
implementations.put(key, impl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the parseProperties methods to disassemble each property tuple.
|
||||
*/
|
||||
private static String[] getPropertyNames(boolean append) {
|
||||
return getPropertyNames(append, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disassembles each property and its associated value. Also handles
|
||||
* overloaded property names that contain indexes.
|
||||
*/
|
||||
private static String[] getPropertyNames(boolean append,
|
||||
String propertyIndex) {
|
||||
String dot = ".";
|
||||
String[] propertyNames =
|
||||
new String[]{SyncFactory.ROWSET_SYNC_PROVIDER,
|
||||
SyncFactory.ROWSET_SYNC_VENDOR,
|
||||
SyncFactory.ROWSET_SYNC_PROVIDER_VERSION};
|
||||
if (append) {
|
||||
for (int i = 0; i < propertyNames.length; i++) {
|
||||
propertyNames[i] = propertyNames[i] +
|
||||
dot +
|
||||
propertyIndex;
|
||||
}
|
||||
return propertyNames;
|
||||
} else {
|
||||
return propertyNames;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal debug method that outputs the registry contents.
|
||||
*/
|
||||
private static void showImpl(ProviderImpl impl) {
|
||||
System.out.println("Provider implementation:");
|
||||
System.out.println("Classname: " + impl.getClassname());
|
||||
System.out.println("Vendor: " + impl.getVendor());
|
||||
System.out.println("Version: " + impl.getVersion());
|
||||
System.out.println("Impl index: " + impl.getIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>SyncProvider</code> instance identified by <i>providerID</i>.
|
||||
*
|
||||
* @param providerID the unique identifier of the provider
|
||||
* @return a <code>SyncProvider</code> implementation
|
||||
* @throws SyncFactoryException If the SyncProvider cannot be found,
|
||||
* the providerID is {@code null}, or
|
||||
* some error was encountered when trying to invoke this provider.
|
||||
*/
|
||||
public static SyncProvider getInstance(String providerID)
|
||||
throws SyncFactoryException {
|
||||
|
||||
if(providerID == null) {
|
||||
throw new SyncFactoryException("The providerID cannot be null");
|
||||
}
|
||||
|
||||
initMapIfNecessary(); // populate HashTable
|
||||
initJNDIContext(); // check JNDI context for any additional bindings
|
||||
|
||||
ProviderImpl impl = (ProviderImpl) implementations.get(providerID);
|
||||
|
||||
if (impl == null) {
|
||||
// Requested SyncProvider is unavailable. Return default provider.
|
||||
return new com.sun.rowset.providers.RIOptimisticProvider();
|
||||
}
|
||||
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(providerID);
|
||||
} catch (java.security.AccessControlException e) {
|
||||
SyncFactoryException sfe = new SyncFactoryException();
|
||||
sfe.initCause(e);
|
||||
throw sfe;
|
||||
}
|
||||
|
||||
// Attempt to invoke classname from registered SyncProvider list
|
||||
Class<?> c = null;
|
||||
try {
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
/**
|
||||
* The SyncProvider implementation of the user will be in
|
||||
* the classpath. We need to find the ClassLoader which loads
|
||||
* this SyncFactory and try to load the SyncProvider class from
|
||||
* there.
|
||||
**/
|
||||
c = Class.forName(providerID, true, cl);
|
||||
|
||||
if (c != null) {
|
||||
return (SyncProvider) c.newInstance();
|
||||
} else {
|
||||
return new com.sun.rowset.providers.RIOptimisticProvider();
|
||||
}
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new SyncFactoryException("IllegalAccessException: " + e.getMessage());
|
||||
} catch (InstantiationException e) {
|
||||
throw new SyncFactoryException("InstantiationException: " + e.getMessage());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new SyncFactoryException("ClassNotFoundException: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Enumeration of currently registered synchronization
|
||||
* providers. A <code>RowSet</code> implementation may use any provider in
|
||||
* the enumeration as its <code>SyncProvider</code> object.
|
||||
* <p>
|
||||
* At a minimum, the reference synchronization provider allowing
|
||||
* RowSet content data to be stored using a JDBC driver should be
|
||||
* possible.
|
||||
*
|
||||
* @return Enumeration A enumeration of available synchronization
|
||||
* providers that are registered with this Factory
|
||||
* @throws SyncFactoryException If an error occurs obtaining the registered
|
||||
* providers
|
||||
*/
|
||||
public static Enumeration<SyncProvider> getRegisteredProviders()
|
||||
throws SyncFactoryException {
|
||||
initMapIfNecessary();
|
||||
// return a collection of classnames
|
||||
// of type SyncProvider
|
||||
return implementations.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logging object to be used by the <code>SyncProvider</code>
|
||||
* implementation provided by the <code>SyncFactory</code>. All
|
||||
* <code>SyncProvider</code> implementations can log their events to
|
||||
* this object and the application can retrieve a handle to this
|
||||
* 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
|
||||
* @throws java.lang.SecurityException if a security manager exists and its
|
||||
* {@code checkPermission} method denies calling {@code setLogger}
|
||||
* @throws NullPointerException if the logger is null
|
||||
* @see SecurityManager#checkPermission
|
||||
*/
|
||||
public static void setLogger(Logger logger) {
|
||||
|
||||
SecurityManager sec = System.getSecurityManager();
|
||||
if (sec != null) {
|
||||
sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
|
||||
}
|
||||
|
||||
if(logger == null){
|
||||
throw new NullPointerException("You must provide a Logger");
|
||||
}
|
||||
rsLogger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logging object that is used by <code>SyncProvider</code>
|
||||
* implementations provided by the <code>SyncFactory</code> SPI. All
|
||||
* <code>SyncProvider</code> implementations can log their events
|
||||
* to this object and the application can retrieve a handle to this
|
||||
* 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 level a Level object instance indicating the degree of logging
|
||||
* required
|
||||
* @throws java.lang.SecurityException if a security manager exists and its
|
||||
* {@code checkPermission} method denies calling {@code setLogger}
|
||||
* @throws NullPointerException if the logger is null
|
||||
* @see SecurityManager#checkPermission
|
||||
* @see LoggingPermission
|
||||
*/
|
||||
public static void setLogger(Logger logger, Level level) {
|
||||
// singleton
|
||||
SecurityManager sec = System.getSecurityManager();
|
||||
if (sec != null) {
|
||||
sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
|
||||
}
|
||||
|
||||
if(logger == null){
|
||||
throw new NullPointerException("You must provide a Logger");
|
||||
}
|
||||
logger.setLevel(level);
|
||||
rsLogger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the logging object for applications to retrieve
|
||||
* synchronization events posted by SyncProvider implementations.
|
||||
* @return The {@code Logger} that has been specified for use by
|
||||
* {@code SyncProvider} implementations
|
||||
* @throws SyncFactoryException if no logging object has been set.
|
||||
*/
|
||||
public static Logger getLogger() throws SyncFactoryException {
|
||||
|
||||
Logger result = rsLogger;
|
||||
// only one logger per session
|
||||
if (result == null) {
|
||||
throw new SyncFactoryException("(SyncFactory) : No logger has been set");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initial JNDI context from which SyncProvider implementations
|
||||
* 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
|
||||
* @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 synchronized void setJNDIContext(javax.naming.Context ctx)
|
||||
throws SyncFactoryException {
|
||||
SecurityManager sec = System.getSecurityManager();
|
||||
if (sec != null) {
|
||||
sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
|
||||
}
|
||||
if (ctx == null) {
|
||||
throw new SyncFactoryException("Invalid JNDI context supplied");
|
||||
}
|
||||
ic = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls JNDI context initialization.
|
||||
*
|
||||
* @throws SyncFactoryException if an error occurs parsing the JNDI context
|
||||
*/
|
||||
private static synchronized void initJNDIContext() throws SyncFactoryException {
|
||||
|
||||
if ((ic != null) && (lazyJNDICtxRefresh == false)) {
|
||||
try {
|
||||
parseProperties(parseJNDIContext());
|
||||
lazyJNDICtxRefresh = true; // touch JNDI namespace once.
|
||||
} catch (NamingException e) {
|
||||
e.printStackTrace();
|
||||
throw new SyncFactoryException("SPI: NamingException: " + e.getExplanation());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new SyncFactoryException("SPI: Exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Internal switch indicating whether the JNDI namespace should be re-read.
|
||||
*/
|
||||
private static boolean lazyJNDICtxRefresh = false;
|
||||
|
||||
/**
|
||||
* Parses the set JNDI Context and passes bindings to the enumerateBindings
|
||||
* method when complete.
|
||||
*/
|
||||
private static Properties parseJNDIContext() throws NamingException {
|
||||
|
||||
NamingEnumeration<?> bindings = ic.listBindings("");
|
||||
Properties properties = new Properties();
|
||||
|
||||
// Hunt one level below context for available SyncProvider objects
|
||||
enumerateBindings(bindings, properties);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans each binding on JNDI context and determines if any binding is an
|
||||
* instance of SyncProvider, if so, add this to the registry and continue to
|
||||
* scan the current context using a re-entrant call to this method until all
|
||||
* bindings have been enumerated.
|
||||
*/
|
||||
private static void enumerateBindings(NamingEnumeration<?> bindings,
|
||||
Properties properties) throws NamingException {
|
||||
|
||||
boolean syncProviderObj = false; // move to parameters ?
|
||||
|
||||
try {
|
||||
Binding bd = null;
|
||||
Object elementObj = null;
|
||||
String element = null;
|
||||
while (bindings.hasMore()) {
|
||||
bd = (Binding) bindings.next();
|
||||
element = bd.getName();
|
||||
elementObj = bd.getObject();
|
||||
|
||||
if (!(ic.lookup(element) instanceof Context)) {
|
||||
// skip directories/sub-contexts
|
||||
if (ic.lookup(element) instanceof SyncProvider) {
|
||||
syncProviderObj = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (syncProviderObj) {
|
||||
SyncProvider sync = (SyncProvider) elementObj;
|
||||
properties.put(SyncFactory.ROWSET_SYNC_PROVIDER,
|
||||
sync.getProviderID());
|
||||
syncProviderObj = false; // reset
|
||||
}
|
||||
|
||||
}
|
||||
} catch (javax.naming.NotContextException e) {
|
||||
bindings.next();
|
||||
// Re-entrant call into method
|
||||
enumerateBindings(bindings, properties);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy initialization Holder class used by {@code getSyncFactory}
|
||||
*/
|
||||
private static class SyncFactoryHolder {
|
||||
static final SyncFactory factory = new SyncFactory();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal class that defines the lazy reference construct for each registered
|
||||
* SyncProvider implementation.
|
||||
*/
|
||||
class ProviderImpl extends SyncProvider {
|
||||
|
||||
private String className = null;
|
||||
private String vendorName = null;
|
||||
private String ver = null;
|
||||
private int index;
|
||||
|
||||
public void setClassname(String classname) {
|
||||
className = classname;
|
||||
}
|
||||
|
||||
public String getClassname() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public void setVendor(String vendor) {
|
||||
vendorName = vendor;
|
||||
}
|
||||
|
||||
public String getVendor() {
|
||||
return vendorName;
|
||||
}
|
||||
|
||||
public void setVersion(String providerVer) {
|
||||
ver = providerVer;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return ver;
|
||||
}
|
||||
|
||||
public void setIndex(int i) {
|
||||
index = i;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public int getDataSourceLock() throws SyncProviderException {
|
||||
|
||||
int dsLock = 0;
|
||||
try {
|
||||
dsLock = SyncFactory.getInstance(className).getDataSourceLock();
|
||||
} catch (SyncFactoryException sfEx) {
|
||||
|
||||
throw new SyncProviderException(sfEx.getMessage());
|
||||
}
|
||||
|
||||
return dsLock;
|
||||
}
|
||||
|
||||
public int getProviderGrade() {
|
||||
|
||||
int grade = 0;
|
||||
|
||||
try {
|
||||
grade = SyncFactory.getInstance(className).getProviderGrade();
|
||||
} catch (SyncFactoryException sfEx) {
|
||||
//
|
||||
}
|
||||
|
||||
return grade;
|
||||
}
|
||||
|
||||
public String getProviderID() {
|
||||
return className;
|
||||
}
|
||||
|
||||
/*
|
||||
public javax.sql.RowSetInternal getRowSetInternal() {
|
||||
try
|
||||
{
|
||||
return SyncFactory.getInstance(className).getRowSetInternal();
|
||||
} catch(SyncFactoryException sfEx) {
|
||||
//
|
||||
}
|
||||
}
|
||||
*/
|
||||
public javax.sql.RowSetReader getRowSetReader() {
|
||||
|
||||
RowSetReader rsReader = null;
|
||||
|
||||
try {
|
||||
rsReader = SyncFactory.getInstance(className).getRowSetReader();
|
||||
} catch (SyncFactoryException sfEx) {
|
||||
//
|
||||
}
|
||||
|
||||
return rsReader;
|
||||
|
||||
}
|
||||
|
||||
public javax.sql.RowSetWriter getRowSetWriter() {
|
||||
|
||||
RowSetWriter rsWriter = null;
|
||||
try {
|
||||
rsWriter = SyncFactory.getInstance(className).getRowSetWriter();
|
||||
} catch (SyncFactoryException sfEx) {
|
||||
//
|
||||
}
|
||||
|
||||
return rsWriter;
|
||||
}
|
||||
|
||||
public void setDataSourceLock(int param)
|
||||
throws SyncProviderException {
|
||||
|
||||
try {
|
||||
SyncFactory.getInstance(className).setDataSourceLock(param);
|
||||
} catch (SyncFactoryException sfEx) {
|
||||
|
||||
throw new SyncProviderException(sfEx.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public int supportsUpdatableView() {
|
||||
|
||||
int view = 0;
|
||||
|
||||
try {
|
||||
view = SyncFactory.getInstance(className).supportsUpdatableView();
|
||||
} catch (SyncFactoryException sfEx) {
|
||||
//
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
58
jdkSrc/jdk8/javax/sql/rowset/spi/SyncFactoryException.java
Normal file
58
jdkSrc/jdk8/javax/sql/rowset/spi/SyncFactoryException.java
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2004, 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.spi;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Indicates an error with <code>SyncFactory</code> mechanism. A disconnected
|
||||
* RowSet implementation cannot be used without a <code>SyncProvider</code>
|
||||
* being successfully instantiated
|
||||
*
|
||||
* @author Jonathan Bruce
|
||||
* @see javax.sql.rowset.spi.SyncFactory
|
||||
* @see javax.sql.rowset.spi.SyncFactoryException
|
||||
*/
|
||||
public class SyncFactoryException extends java.sql.SQLException {
|
||||
|
||||
/**
|
||||
* Creates new <code>SyncFactoryException</code> without detail message.
|
||||
*/
|
||||
public SyncFactoryException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an <code>SyncFactoryException</code> with the specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public SyncFactoryException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
static final long serialVersionUID = -4354595476433200352L;
|
||||
}
|
430
jdkSrc/jdk8/javax/sql/rowset/spi/SyncProvider.java
Normal file
430
jdkSrc/jdk8/javax/sql/rowset/spi/SyncProvider.java
Normal file
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, 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.spi;
|
||||
|
||||
import javax.sql.*;
|
||||
|
||||
/**
|
||||
* The synchronization mechanism that provides reader/writer capabilities for
|
||||
* disconnected <code>RowSet</code> objects.
|
||||
* A <code>SyncProvider</code> implementation is a class that extends the
|
||||
* <code>SyncProvider</code> abstract class.
|
||||
* <P>
|
||||
* A <code>SyncProvider</code> implementation is
|
||||
* identified by a unique ID, which is its fully qualified class name.
|
||||
* This name must be registered with the
|
||||
* <code>SyncFactory</code> SPI, thus making the implementation available to
|
||||
* all <code>RowSet</code> implementations.
|
||||
* The factory mechanism in the reference implementation uses this name to instantiate
|
||||
* the implementation, which can then provide a <code>RowSet</code> object with its
|
||||
* reader (a <code>javax.sql.RowSetReader</code> object) and its writer (a
|
||||
* <code>javax.sql.RowSetWriter</code> object).
|
||||
* <P>
|
||||
* The Jdbc <code>RowSet</code> Implementations specification provides two
|
||||
* reference implementations of the <code>SyncProvider</code> abstract class:
|
||||
* <code>RIOptimisticProvider</code> and <code>RIXMLProvider</code>.
|
||||
* The <code>RIOptimisticProvider</code> can set any <code>RowSet</code>
|
||||
* implementation with a <code>RowSetReader</code> object and a
|
||||
* <code>RowSetWriter</code> object. However, only the <code>RIXMLProvider</code>
|
||||
* implementation can set an <code>XmlReader</code> object and an
|
||||
* <code>XmlWriter</code> object. A <code>WebRowSet</code> object uses the
|
||||
* <code>XmlReader</code> object to read data in XML format to populate itself with that
|
||||
* data. It uses the <code>XmlWriter</code> object to write itself to a stream or
|
||||
* <code>java.io.Writer</code> object in XML format.
|
||||
*
|
||||
* <h3>1.0 Naming Convention for Implementations</h3>
|
||||
* As a guide to naming <code>SyncProvider</code>
|
||||
* implementations, the following should be noted:
|
||||
* <UL>
|
||||
* <li>The name for a <code>SyncProvider</code> implementation
|
||||
* is its fully qualified class name.
|
||||
* <li>It is recommended that vendors supply a
|
||||
* <code>SyncProvider</code> implementation in a package named <code>providers</code>.
|
||||
* </UL>
|
||||
* <p>
|
||||
* For instance, if a vendor named Fred, Inc. offered a
|
||||
* <code>SyncProvider</code> implementation, you could have the following:
|
||||
* <PRE>
|
||||
* Vendor name: Fred, Inc.
|
||||
* Domain name of vendor: com.fred
|
||||
* Package name: com.fred.providers
|
||||
* SyncProvider implementation class name: HighAvailabilityProvider
|
||||
*
|
||||
* Fully qualified class name of SyncProvider implementation:
|
||||
* com.fred.providers.HighAvailabilityProvider
|
||||
* </PRE>
|
||||
* <P>
|
||||
* The following line of code uses the fully qualified name to register
|
||||
* this implementation with the <code>SyncFactory</code> static instance.
|
||||
* <PRE>
|
||||
* SyncFactory.registerProvider(
|
||||
* "com.fred.providers.HighAvailabilityProvider");
|
||||
* </PRE>
|
||||
* <P>
|
||||
* The default <code>SyncProvider</code> object provided with the reference
|
||||
* implementation uses the following name:
|
||||
* <pre>
|
||||
* com.sun.rowset.providers.RIOptimisticProvider
|
||||
* </pre>
|
||||
* <p>
|
||||
* A vendor can register a <code>SyncProvider</code> implementation class name
|
||||
* with Oracle Corporation by sending email to jdbc@sun.com.
|
||||
* Oracle will maintain a database listing the
|
||||
* available <code>SyncProvider</code> implementations for use with compliant
|
||||
* <code>RowSet</code> implementations. This database will be similar to the
|
||||
* one already maintained to list available JDBC drivers.
|
||||
* <P>
|
||||
* Vendors should refer to the reference implementation synchronization
|
||||
* providers for additional guidance on how to implement a new
|
||||
* <code>SyncProvider</code> implementation.
|
||||
*
|
||||
* <h3>2.0 How a <code>RowSet</code> Object Gets Its Provider</h3>
|
||||
*
|
||||
* A disconnected <code>Rowset</code> object may get access to a
|
||||
* <code>SyncProvider</code> object in one of the following two ways:
|
||||
* <UL>
|
||||
* <LI>Using a constructor<BR>
|
||||
* <PRE>
|
||||
* CachedRowSet crs = new CachedRowSet(
|
||||
* "com.fred.providers.HighAvailabilitySyncProvider");
|
||||
* </PRE>
|
||||
* <LI>Using the <code>setSyncProvider</code> method
|
||||
* <PRE>
|
||||
* CachedRowSet crs = new CachedRowSet();
|
||||
* crs.setSyncProvider("com.fred.providers.HighAvailabilitySyncProvider");
|
||||
* </PRE>
|
||||
|
||||
* </UL>
|
||||
* <p>
|
||||
* By default, the reference implementations of the <code>RowSet</code> synchronization
|
||||
* providers are always available to the Java platform.
|
||||
* If no other pluggable synchronization providers have been correctly
|
||||
* registered, the <code>SyncFactory</code> will automatically generate
|
||||
* an instance of the default <code>SyncProvider</code> reference implementation.
|
||||
* Thus, in the preceding code fragment, if no implementation named
|
||||
* <code>com.fred.providers.HighAvailabilitySyncProvider</code> has been
|
||||
* registered with the <code>SyncFactory</code> instance, <i>crs</i> will be
|
||||
* assigned the default provider in the reference implementation, which is
|
||||
* <code>com.sun.rowset.providers.RIOptimisticProvider</code>.
|
||||
*
|
||||
* <h3>3.0 Violations and Synchronization Issues</h3>
|
||||
* If an update between a disconnected <code>RowSet</code> object
|
||||
* and a data source violates
|
||||
* the original query or the underlying data source constraints, this will
|
||||
* result in undefined behavior for all disconnected <code>RowSet</code> implementations
|
||||
* and their designated <code>SyncProvider</code> implementations.
|
||||
* Not defining the behavior when such violations occur offers greater flexibility
|
||||
* for a <code>SyncProvider</code>
|
||||
* implementation to determine its own best course of action.
|
||||
* <p>
|
||||
* A <code>SyncProvider</code> implementation
|
||||
* may choose to implement a specific handler to
|
||||
* handle a subset of query violations.
|
||||
* However if an original query violation or a more general data source constraint
|
||||
* violation is not handled by the <code>SyncProvider</code> implementation,
|
||||
* all <code>SyncProvider</code>
|
||||
* objects must throw a <code>SyncProviderException</code>.
|
||||
*
|
||||
* <h3>4.0 Updatable SQL VIEWs</h3>
|
||||
* It is possible for any disconnected or connected <code>RowSet</code> object to be populated
|
||||
* from an SQL query that is formulated originally from an SQL <code>VIEW</code>.
|
||||
* While in many cases it is possible for an update to be performed to an
|
||||
* underlying view, such an update requires additional metadata, which may vary.
|
||||
* The <code>SyncProvider</code> class provides two constants to indicate whether
|
||||
* an implementation supports updating an SQL <code>VIEW</code>.
|
||||
* <ul>
|
||||
* <li><code><b>NONUPDATABLE_VIEW_SYNC</b></code> - Indicates that a <code>SyncProvider</code>
|
||||
* implementation does not support synchronization with an SQL <code>VIEW</code> as the
|
||||
* underlying source of data for the <code>RowSet</code> object.
|
||||
* <li><code><b>UPDATABLE_VIEW_SYNC</b></code> - Indicates that a
|
||||
* <code>SyncProvider</code> implementation
|
||||
* supports synchronization with an SQL <code>VIEW</code> as the underlying source
|
||||
* of data.
|
||||
* </ul>
|
||||
* <P>
|
||||
* The default is for a <code>RowSet</code> object not to be updatable if it was
|
||||
* populated with data from an SQL <code>VIEW</code>.
|
||||
*
|
||||
* <h3>5.0 <code>SyncProvider</code> Constants</h3>
|
||||
* The <code>SyncProvider</code> class provides three sets of constants that
|
||||
* are used as return values or parameters for <code>SyncProvider</code> methods.
|
||||
* <code>SyncProvider</code> objects may be implemented to perform synchronization
|
||||
* between a <code>RowSet</code> object and its underlying data source with varying
|
||||
* degrees of of care. The first group of constants indicate how synchronization
|
||||
* is handled. For example, <code>GRADE_NONE</code> indicates that a
|
||||
* <code>SyncProvider</code> object will not take any care to see what data is
|
||||
* valid and will simply write the <code>RowSet</code> data to the data source.
|
||||
* <code>GRADE_MODIFIED_AT_COMMIT</code> indicates that the provider will check
|
||||
* only modified data for validity. Other grades check all data for validity
|
||||
* or set locks when data is modified or loaded.
|
||||
* <OL>
|
||||
* <LI>Constants to indicate the synchronization grade of a
|
||||
* <code>SyncProvider</code> object
|
||||
* <UL>
|
||||
* <LI>SyncProvider.GRADE_NONE
|
||||
* <LI>SyncProvider.GRADE_MODIFIED_AT_COMMIT
|
||||
* <LI>SyncProvider.GRADE_CHECK_ALL_AT_COMMIT
|
||||
* <LI>SyncProvider.GRADE_LOCK_WHEN_MODIFIED
|
||||
* <LI>SyncProvider.GRADE_LOCK_WHEN_LOADED
|
||||
* </UL>
|
||||
* <LI>Constants to indicate what locks are set on the data source
|
||||
* <UL>
|
||||
* <LI>SyncProvider.DATASOURCE_NO_LOCK
|
||||
* <LI>SyncProvider.DATASOURCE_ROW_LOCK
|
||||
* <LI>SyncProvider.DATASOURCE_TABLE_LOCK
|
||||
* <LI>SyncProvider.DATASOURCE_DB_LOCK
|
||||
* </UL>
|
||||
* <LI>Constants to indicate whether a <code>SyncProvider</code> object can
|
||||
* perform updates to an SQL <code>VIEW</code> <BR>
|
||||
* These constants are explained in the preceding section (4.0).
|
||||
* <UL>
|
||||
* <LI>SyncProvider.UPDATABLE_VIEW_SYNC
|
||||
* <LI>SyncProvider.NONUPDATABLE_VIEW_SYNC
|
||||
* </UL>
|
||||
* </OL>
|
||||
*
|
||||
* @author Jonathan Bruce
|
||||
* @see javax.sql.rowset.spi.SyncFactory
|
||||
* @see javax.sql.rowset.spi.SyncFactoryException
|
||||
*/
|
||||
public abstract class SyncProvider {
|
||||
|
||||
/**
|
||||
* Creates a default <code>SyncProvider</code> object.
|
||||
*/
|
||||
public SyncProvider() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique identifier for this <code>SyncProvider</code> object.
|
||||
*
|
||||
* @return a <code>String</code> object with the fully qualified class name of
|
||||
* this <code>SyncProvider</code> object
|
||||
*/
|
||||
public abstract String getProviderID();
|
||||
|
||||
/**
|
||||
* Returns a <code>javax.sql.RowSetReader</code> object, which can be used to
|
||||
* populate a <code>RowSet</code> object with data.
|
||||
*
|
||||
* @return a <code>javax.sql.RowSetReader</code> object
|
||||
*/
|
||||
public abstract RowSetReader getRowSetReader();
|
||||
|
||||
/**
|
||||
* Returns a <code>javax.sql.RowSetWriter</code> object, which can be
|
||||
* used to write a <code>RowSet</code> object's data back to the
|
||||
* underlying data source.
|
||||
*
|
||||
* @return a <code>javax.sql.RowSetWriter</code> object
|
||||
*/
|
||||
public abstract RowSetWriter getRowSetWriter();
|
||||
|
||||
/**
|
||||
* Returns a constant indicating the
|
||||
* grade of synchronization a <code>RowSet</code> object can expect from
|
||||
* this <code>SyncProvider</code> object.
|
||||
*
|
||||
* @return an int that is one of the following constants:
|
||||
* SyncProvider.GRADE_NONE,
|
||||
* SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT,
|
||||
* SyncProvider.GRADE_CHECK_ALL_AT_COMMIT,
|
||||
* SyncProvider.GRADE_LOCK_WHEN_MODIFIED,
|
||||
* SyncProvider.GRADE_LOCK_WHEN_LOADED
|
||||
*/
|
||||
public abstract int getProviderGrade();
|
||||
|
||||
|
||||
/**
|
||||
* Sets a lock on the underlying data source at the level indicated by
|
||||
* <i>datasource_lock</i>. This should cause the
|
||||
* <code>SyncProvider</code> to adjust its behavior by increasing or
|
||||
* decreasing the level of optimism it provides for a successful
|
||||
* synchronization.
|
||||
*
|
||||
* @param datasource_lock one of the following constants indicating the severity
|
||||
* level of data source lock required:
|
||||
* <pre>
|
||||
* SyncProvider.DATASOURCE_NO_LOCK,
|
||||
* SyncProvider.DATASOURCE_ROW_LOCK,
|
||||
* SyncProvider.DATASOURCE_TABLE_LOCK,
|
||||
* SyncProvider.DATASOURCE_DB_LOCK,
|
||||
* </pre>
|
||||
* @throws SyncProviderException if an unsupported data source locking level
|
||||
* is set.
|
||||
* @see #getDataSourceLock
|
||||
*/
|
||||
public abstract void setDataSourceLock(int datasource_lock)
|
||||
throws SyncProviderException;
|
||||
|
||||
/**
|
||||
* Returns the current data source lock severity level active in this
|
||||
* <code>SyncProvider</code> implementation.
|
||||
*
|
||||
* @return a constant indicating the current level of data source lock
|
||||
* active in this <code>SyncProvider</code> object;
|
||||
* one of the following:
|
||||
* <pre>
|
||||
* SyncProvider.DATASOURCE_NO_LOCK,
|
||||
* SyncProvider.DATASOURCE_ROW_LOCK,
|
||||
* SyncProvider.DATASOURCE_TABLE_LOCK,
|
||||
* SyncProvider.DATASOURCE_DB_LOCK
|
||||
* </pre>
|
||||
* @throws SyncProviderException if an error occurs determining the data
|
||||
* source locking level.
|
||||
* @see #setDataSourceLock
|
||||
|
||||
*/
|
||||
public abstract int getDataSourceLock()
|
||||
throws SyncProviderException;
|
||||
|
||||
/**
|
||||
* Returns whether this <code>SyncProvider</code> implementation
|
||||
* can perform synchronization between a <code>RowSet</code> object
|
||||
* and the SQL <code>VIEW</code> in the data source from which
|
||||
* the <code>RowSet</code> object got its data.
|
||||
*
|
||||
* @return an <code>int</code> saying whether this <code>SyncProvider</code>
|
||||
* object supports updating an SQL <code>VIEW</code>; one of the
|
||||
* following:
|
||||
* SyncProvider.UPDATABLE_VIEW_SYNC,
|
||||
* SyncProvider.NONUPDATABLE_VIEW_SYNC
|
||||
*/
|
||||
public abstract int supportsUpdatableView();
|
||||
|
||||
/**
|
||||
* Returns the release version of this <code>SyncProvider</code> instance.
|
||||
*
|
||||
* @return a <code>String</code> detailing the release version of the
|
||||
* <code>SyncProvider</code> implementation
|
||||
*/
|
||||
public abstract String getVersion();
|
||||
|
||||
/**
|
||||
* Returns the vendor name of this <code>SyncProvider</code> instance
|
||||
*
|
||||
* @return a <code>String</code> detailing the vendor name of this
|
||||
* <code>SyncProvider</code> implementation
|
||||
*/
|
||||
public abstract String getVendor();
|
||||
|
||||
/*
|
||||
* Standard description of synchronization grades that a SyncProvider
|
||||
* could provide.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Indicates that no synchronization with the originating data source is
|
||||
* provided. A <code>SyncProvider</code>
|
||||
* implementation returning this grade will simply attempt to write
|
||||
* updates in the <code>RowSet</code> object to the underlying data
|
||||
* source without checking the validity of any data.
|
||||
*
|
||||
*/
|
||||
public static final int GRADE_NONE = 1;
|
||||
|
||||
/**
|
||||
* Indicates a low level optimistic synchronization grade with
|
||||
* respect to the originating data source.
|
||||
*
|
||||
* A <code>SyncProvider</code> implementation
|
||||
* returning this grade will check only rows that have changed.
|
||||
*
|
||||
*/
|
||||
public static final int GRADE_CHECK_MODIFIED_AT_COMMIT = 2;
|
||||
|
||||
/**
|
||||
* Indicates a high level optimistic synchronization grade with
|
||||
* respect to the originating data source.
|
||||
*
|
||||
* A <code>SyncProvider</code> implementation
|
||||
* returning this grade will check all rows, including rows that have not
|
||||
* changed.
|
||||
*/
|
||||
public static final int GRADE_CHECK_ALL_AT_COMMIT = 3;
|
||||
|
||||
/**
|
||||
* Indicates a pessimistic synchronization grade with
|
||||
* respect to the originating data source.
|
||||
*
|
||||
* A <code>SyncProvider</code>
|
||||
* implementation returning this grade will lock the row in the originating
|
||||
* data source.
|
||||
*/
|
||||
public static final int GRADE_LOCK_WHEN_MODIFIED = 4;
|
||||
|
||||
/**
|
||||
* Indicates the most pessimistic synchronization grade with
|
||||
* respect to the originating
|
||||
* data source. A <code>SyncProvider</code>
|
||||
* implementation returning this grade will lock the entire view and/or
|
||||
* table affected by the original statement used to populate a
|
||||
* <code>RowSet</code> object.
|
||||
*/
|
||||
public static final int GRADE_LOCK_WHEN_LOADED = 5;
|
||||
|
||||
/**
|
||||
* Indicates that no locks remain on the originating data source. This is the default
|
||||
* lock setting for all <code>SyncProvider</code> implementations unless
|
||||
* otherwise directed by a <code>RowSet</code> object.
|
||||
*/
|
||||
public static final int DATASOURCE_NO_LOCK = 1;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* that is using this <code>SyncProvider</code> object.
|
||||
*/
|
||||
public static final int DATASOURCE_ROW_LOCK = 2;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* that is using this <code>SyncProvider</code> object.
|
||||
*/
|
||||
public static final int DATASOURCE_TABLE_LOCK = 3;
|
||||
|
||||
/**
|
||||
* Indicates that a lock is placed on the entire data source that is the source of
|
||||
* data for the <code>RowSet</code> object
|
||||
* that is using this <code>SyncProvider</code> object.
|
||||
*/
|
||||
public static final int DATASOURCE_DB_LOCK = 4;
|
||||
|
||||
/**
|
||||
* Indicates that a <code>SyncProvider</code> implementation
|
||||
* supports synchronization between a <code>RowSet</code> object and
|
||||
* the SQL <code>VIEW</code> used to populate it.
|
||||
*/
|
||||
public static final int UPDATABLE_VIEW_SYNC = 5;
|
||||
|
||||
/**
|
||||
* Indicates that a <code>SyncProvider</code> implementation
|
||||
* does <B>not</B> support synchronization between a <code>RowSet</code>
|
||||
* object and the SQL <code>VIEW</code> used to populate it.
|
||||
*/
|
||||
public static final int NONUPDATABLE_VIEW_SYNC = 6;
|
||||
}
|
164
jdkSrc/jdk8/javax/sql/rowset/spi/SyncProviderException.java
Normal file
164
jdkSrc/jdk8/javax/sql/rowset/spi/SyncProviderException.java
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2006, 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.spi;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import javax.sql.rowset.*;
|
||||
|
||||
/**
|
||||
* Indicates an error with the <code>SyncProvider</code> mechanism. This exception
|
||||
* is created by a <code>SyncProvider</code> abstract class extension if it
|
||||
* encounters violations in reading from or writing to the originating data source.
|
||||
* <P>
|
||||
* If it is implemented to do so, the <code>SyncProvider</code> object may also create a
|
||||
* <code>SyncResolver</code> object and either initialize the <code>SyncProviderException</code>
|
||||
* object with it at construction time or set it with the <code>SyncProvider</code> object at
|
||||
* a later time.
|
||||
* <P>
|
||||
* The method <code>acceptChanges</code> will throw this exception after the writer
|
||||
* has finished checking for conflicts and has found one or more conflicts. An
|
||||
* application may catch a <code>SyncProviderException</code> object and call its
|
||||
* <code>getSyncResolver</code> method to get its <code>SyncResolver</code> object.
|
||||
* See the code fragment in the interface comment for
|
||||
* <a href="SyncResolver.html"><code>SyncResolver</code></a> for an example.
|
||||
* This <code>SyncResolver</code> object will mirror the <code>RowSet</code>
|
||||
* object that generated the exception, except that it will contain only the values
|
||||
* from the data source that are in conflict. All other values in the <code>SyncResolver</code>
|
||||
* object will be <code>null</code>.
|
||||
* <P>
|
||||
* The <code>SyncResolver</code> object may be used to examine and resolve
|
||||
* each conflict in a row and then go to the next row with a conflict to
|
||||
* repeat the procedure.
|
||||
* <P>
|
||||
* A <code>SyncProviderException</code> object may or may not contain a description of the
|
||||
* condition causing the exception. The inherited method <code>getMessage</code> may be
|
||||
* called to retrieve the description if there is one.
|
||||
*
|
||||
* @author Jonathan Bruce
|
||||
* @see javax.sql.rowset.spi.SyncFactory
|
||||
* @see javax.sql.rowset.spi.SyncResolver
|
||||
* @see javax.sql.rowset.spi.SyncFactoryException
|
||||
*/
|
||||
public class SyncProviderException extends java.sql.SQLException {
|
||||
|
||||
/**
|
||||
* The instance of <code>javax.sql.rowset.spi.SyncResolver</code> that
|
||||
* this <code>SyncProviderException</code> object will return when its
|
||||
* <code>getSyncResolver</code> method is called.
|
||||
*/
|
||||
private SyncResolver syncResolver = null;
|
||||
|
||||
/**
|
||||
* Creates a new <code>SyncProviderException</code> object without a detail message.
|
||||
*/
|
||||
public SyncProviderException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a <code>SyncProviderException</code> object with the specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public SyncProviderException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a <code>SyncProviderException</code> object with the specified
|
||||
* <code>SyncResolver</code> instance.
|
||||
*
|
||||
* @param syncResolver the <code>SyncResolver</code> instance used to
|
||||
* to process the synchronization conflicts
|
||||
* @throws IllegalArgumentException if the <code>SyncResolver</code> object
|
||||
* is <code>null</code>.
|
||||
*/
|
||||
public SyncProviderException(SyncResolver syncResolver) {
|
||||
if (syncResolver == null) {
|
||||
throw new IllegalArgumentException("Cannot instantiate a SyncProviderException " +
|
||||
"with a null SyncResolver object");
|
||||
} else {
|
||||
this.syncResolver = syncResolver;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the <code>SyncResolver</code> object that has been set for
|
||||
* this <code>SyncProviderException</code> object, or
|
||||
* if none has been set, an instance of the default <code>SyncResolver</code>
|
||||
* implementation included in the reference implementation.
|
||||
* <P>
|
||||
* If a <code>SyncProviderException</code> object is thrown, an application
|
||||
* may use this method to generate a <code>SyncResolver</code> object
|
||||
* with which to resolve the conflict or conflicts that caused the
|
||||
* exception to be thrown.
|
||||
*
|
||||
* @return the <code>SyncResolver</code> object set for this
|
||||
* <code>SyncProviderException</code> object or, if none has
|
||||
* been set, an instance of the default <code>SyncResolver</code>
|
||||
* implementation. In addition, the default <code>SyncResolver</code>
|
||||
* implementation is also returned if the <code>SyncResolver()</code> or
|
||||
* <code>SyncResolver(String)</code> constructors are used to instantiate
|
||||
* the <code>SyncResolver</code> instance.
|
||||
*/
|
||||
public SyncResolver getSyncResolver() {
|
||||
if (syncResolver != null) {
|
||||
return syncResolver;
|
||||
} else {
|
||||
try {
|
||||
syncResolver = new com.sun.rowset.internal.SyncResolverImpl();
|
||||
} catch (SQLException sqle) {
|
||||
}
|
||||
return syncResolver;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <code>SyncResolver</code> object for this
|
||||
* <code>SyncProviderException</code> object to the one supplied.
|
||||
* If the argument supplied is <code>null</code>, a call to the method
|
||||
* <code>getSyncResolver</code> will return the default reference
|
||||
* implementation of the <code>SyncResolver</code> interface.
|
||||
*
|
||||
* @param syncResolver the <code>SyncResolver</code> object to be set;
|
||||
* cannot be <code>null</code>
|
||||
* @throws IllegalArgumentException if the <code>SyncResolver</code> object
|
||||
* is <code>null</code>.
|
||||
* @see #getSyncResolver
|
||||
*/
|
||||
public void setSyncResolver(SyncResolver syncResolver) {
|
||||
if (syncResolver == null) {
|
||||
throw new IllegalArgumentException("Cannot set a null SyncResolver " +
|
||||
"object");
|
||||
} else {
|
||||
this.syncResolver = syncResolver;
|
||||
}
|
||||
}
|
||||
|
||||
static final long serialVersionUID = -939908523620640692L;
|
||||
|
||||
}
|
375
jdkSrc/jdk8/javax/sql/rowset/spi/SyncResolver.java
Normal file
375
jdkSrc/jdk8/javax/sql/rowset/spi/SyncResolver.java
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, 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.spi;
|
||||
|
||||
import javax.sql.RowSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Defines a framework that allows applications to use a manual decision tree
|
||||
* to decide what should be done when a synchronization conflict occurs.
|
||||
* Although it is not mandatory for
|
||||
* applications to resolve synchronization conflicts manually, this
|
||||
* framework provides the means to delegate to the application when conflicts
|
||||
* arise.
|
||||
* <p>
|
||||
* Note that a conflict is a situation where the <code>RowSet</code> object's original
|
||||
* values for a row do not match the values in the data source, which indicates that
|
||||
* the data source row has been modified since the last synchronization. Note also that
|
||||
* a <code>RowSet</code> object's original values are the values it had just prior to the
|
||||
* the last synchronization, which are not necessarily its initial values.
|
||||
*
|
||||
*
|
||||
* <H2>Description of a <code>SyncResolver</code> Object</H2>
|
||||
*
|
||||
* A <code>SyncResolver</code> object is a specialized <code>RowSet</code> object
|
||||
* that implements the <code>SyncResolver</code> interface.
|
||||
* It <b>may</b> operate as either a connected <code>RowSet</code> object (an
|
||||
* implementation of the <code>JdbcRowSet</code> interface) or a connected
|
||||
* <code>RowSet</code> object (an implementation of the
|
||||
* <code>CachedRowSet</code> interface or one of its subinterfaces). For information
|
||||
* on the subinterfaces, see the
|
||||
* <a href="../package-summary.html"><code>javax.sql.rowset</code></a> package
|
||||
* description. The reference implementation for <code>SyncResolver</code> implements
|
||||
* the <code>CachedRowSet</code> interface, but other implementations
|
||||
* may choose to implement the <code>JdbcRowSet</code> interface to satisfy
|
||||
* particular needs.
|
||||
* <P>
|
||||
* After an application has attempted to synchronize a <code>RowSet</code> object with
|
||||
* the data source (by calling the <code>CachedRowSet</code>
|
||||
* method <code>acceptChanges</code>), and one or more conflicts have been found,
|
||||
* a rowset's <code>SyncProvider</code> object creates an instance of
|
||||
* <code>SyncResolver</code>. This new <code>SyncResolver</code> object has
|
||||
* the same number of rows and columns as the
|
||||
* <code>RowSet</code> object that was attempting the synchronization. The
|
||||
* <code>SyncResolver</code> object contains the values from the data source that caused
|
||||
* the conflict(s) and <code>null</code> for all other values.
|
||||
* In addition, it contains information about each conflict.
|
||||
*
|
||||
*
|
||||
* <H2>Getting and Using a <code>SyncResolver</code> Object</H2>
|
||||
*
|
||||
* When the method <code>acceptChanges</code> encounters conflicts, the
|
||||
* <code>SyncProvider</code> object creates a <code>SyncProviderException</code>
|
||||
* object and sets it with the new <code>SyncResolver</code> object. The method
|
||||
* <code>acceptChanges</code> will throw this exception, which
|
||||
* the application can then catch and use to retrieve the
|
||||
* <code>SyncResolver</code> object it contains. The following code snippet uses the
|
||||
* <code>SyncProviderException</code> method <code>getSyncResolver</code> to get
|
||||
* the <code>SyncResolver</code> object <i>resolver</i>.
|
||||
* <PRE>
|
||||
* {@code
|
||||
* } catch (SyncProviderException spe) {
|
||||
* SyncResolver resolver = spe.getSyncResolver();
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* }
|
||||
* </PRE>
|
||||
* <P>
|
||||
* With <i>resolver</i> in hand, an application can use it to get the information
|
||||
* it contains about the conflict or conflicts. A <code>SyncResolver</code> object
|
||||
* such as <i>resolver</i> keeps
|
||||
* track of the conflicts for each row in which there is a conflict. It also places a
|
||||
* lock on the table or tables affected by the rowset's command so that no more
|
||||
* conflicts can occur while the current conflicts are being resolved.
|
||||
* <P>
|
||||
* The following kinds of information can be obtained from a <code>SyncResolver</code>
|
||||
* object:
|
||||
*
|
||||
* <h3>What operation was being attempted when a conflict occurred</h3>
|
||||
* The <code>SyncProvider</code> interface defines four constants
|
||||
* describing states that may occur. Three
|
||||
* constants describe the type of operation (update, delete, or insert) that a
|
||||
* <code>RowSet</code> object was attempting to perform when a conflict was discovered,
|
||||
* and the fourth indicates that there is no conflict.
|
||||
* These constants are the possible return values when a <code>SyncResolver</code> object
|
||||
* calls the method <code>getStatus</code>.
|
||||
* <PRE>
|
||||
* {@code int operation = resolver.getStatus(); }
|
||||
* </PRE>
|
||||
*
|
||||
* <h3>The value in the data source that caused a conflict</h3>
|
||||
* A conflict exists when a value that a <code>RowSet</code> object has changed
|
||||
* and is attempting to write to the data source
|
||||
* has also been changed in the data source since the last synchronization. An
|
||||
* application can call the <code>SyncResolver</code> method
|
||||
* <code>getConflictValue</code > to retrieve the
|
||||
* value in the data source that is the cause of the conflict because the values in a
|
||||
* <code>SyncResolver</code> object are the conflict values from the data source.
|
||||
* <PRE>
|
||||
* java.lang.Object conflictValue = resolver.getConflictValue(2);
|
||||
* </PRE>
|
||||
* Note that the column in <i>resolver</i> can be designated by the column number,
|
||||
* as is done in the preceding line of code, or by the column name.
|
||||
* <P>
|
||||
* With the information retrieved from the methods <code>getStatus</code> and
|
||||
* <code>getConflictValue</code>, the application may make a determination as to
|
||||
* which value should be persisted in the data source. The application then calls the
|
||||
* <code>SyncResolver</code> method <code>setResolvedValue</code>, which sets the value
|
||||
* to be persisted in the <code>RowSet</code> object and also in the data source.
|
||||
* <PRE>
|
||||
* resolver.setResolvedValue("DEPT", 8390426);
|
||||
* </PRE>
|
||||
* In the preceding line of code,
|
||||
* the column name designates the column in the <code>RowSet</code> object
|
||||
* that is to be set with the given value. The column number can also be used to
|
||||
* designate the column.
|
||||
* <P>
|
||||
* An application calls the method <code>setResolvedValue</code> after it has
|
||||
* resolved all of the conflicts in the current conflict row and repeats this process
|
||||
* for each conflict row in the <code>SyncResolver</code> object.
|
||||
*
|
||||
*
|
||||
* <H2>Navigating a <code>SyncResolver</code> Object</H2>
|
||||
*
|
||||
* Because a <code>SyncResolver</code> object is a <code>RowSet</code> object, an
|
||||
* application can use all of the <code>RowSet</code> methods for moving the cursor
|
||||
* to navigate a <code>SyncResolver</code> object. For example, an application can
|
||||
* use the <code>RowSet</code> method <code>next</code> to get to each row and then
|
||||
* call the <code>SyncResolver</code> method <code>getStatus</code> to see if the row
|
||||
* contains a conflict. In a row with one or more conflicts, the application can
|
||||
* iterate through the columns to find any non-null values, which will be the values
|
||||
* from the data source that are in conflict.
|
||||
* <P>
|
||||
* To make it easier to navigate a <code>SyncResolver</code> object, especially when
|
||||
* there are large numbers of rows with no conflicts, the <code>SyncResolver</code>
|
||||
* interface defines the methods <code>nextConflict</code> and
|
||||
* <code>previousConflict</code>, which move only to rows
|
||||
* that contain at least one conflict value. Then an application can call the
|
||||
* <code>SyncResolver</code> method <code>getConflictValue</code>, supplying it
|
||||
* with the column number, to get the conflict value itself. The code fragment in the
|
||||
* next section gives an example.
|
||||
*
|
||||
* <H2>Code Example</H2>
|
||||
*
|
||||
* The following code fragment demonstrates how a disconnected <code>RowSet</code>
|
||||
* object <i>crs</i> might attempt to synchronize itself with the
|
||||
* underlying data source and then resolve the conflicts. In the <code>try</code>
|
||||
* block, <i>crs</i> calls the method <code>acceptChanges</code>, passing it the
|
||||
* <code>Connection</code> object <i>con</i>. If there are no conflicts, the
|
||||
* changes in <i>crs</i> are simply written to the data source. However, if there
|
||||
* is a conflict, the method <code>acceptChanges</code> throws a
|
||||
* <code>SyncProviderException</code> object, and the
|
||||
* <code>catch</code> block takes effect. In this example, which
|
||||
* illustrates one of the many ways a <code>SyncResolver</code> object can be used,
|
||||
* the <code>SyncResolver</code> method <code>nextConflict</code> is used in a
|
||||
* <code>while</code> loop. The loop will end when <code>nextConflict</code> returns
|
||||
* <code>false</code>, which will occur when there are no more conflict rows in the
|
||||
* <code>SyncResolver</code> object <i>resolver</i>. In This particular code fragment,
|
||||
* <i>resolver</i> looks for rows that have update conflicts (rows with the status
|
||||
* <code>SyncResolver.UPDATE_ROW_CONFLICT</code>), and the rest of this code fragment
|
||||
* executes only for rows where conflicts occurred because <i>crs</i> was attempting an
|
||||
* update.
|
||||
* <P>
|
||||
* After the cursor for <i>resolver</i> has moved to the next conflict row that
|
||||
* has an update conflict, the method <code>getRow</code> indicates the number of the
|
||||
* current row, and
|
||||
* the cursor for the <code>CachedRowSet</code> object <i>crs</i> is moved to
|
||||
* the comparable row in <i>crs</i>. By iterating
|
||||
* through the columns of that row in both <i>resolver</i> and <i>crs</i>, the conflicting
|
||||
* values can be retrieved and compared to decide which one should be persisted. In this
|
||||
* code fragment, the value in <i>crs</i> is the one set as the resolved value, which means
|
||||
* that it will be used to overwrite the conflict value in the data source.
|
||||
*
|
||||
* <PRE>
|
||||
* {@code
|
||||
* try {
|
||||
*
|
||||
* crs.acceptChanges(con);
|
||||
*
|
||||
* } catch (SyncProviderException spe) {
|
||||
*
|
||||
* SyncResolver resolver = spe.getSyncResolver();
|
||||
*
|
||||
* Object crsValue; // value in the RowSet object
|
||||
* Object resolverValue: // value in the SyncResolver object
|
||||
* Object resolvedValue: // value to be persisted
|
||||
*
|
||||
* while(resolver.nextConflict()) {
|
||||
* if(resolver.getStatus() == SyncResolver.UPDATE_ROW_CONFLICT) {
|
||||
* int row = resolver.getRow();
|
||||
* crs.absolute(row);
|
||||
*
|
||||
* int colCount = crs.getMetaData().getColumnCount();
|
||||
* for(int j = 1; j <= colCount; j++) {
|
||||
* if (resolver.getConflictValue(j) != null) {
|
||||
* crsValue = crs.getObject(j);
|
||||
* resolverValue = resolver.getConflictValue(j);
|
||||
* . . .
|
||||
* // compare crsValue and resolverValue to determine
|
||||
* // which should be the resolved value (the value to persist)
|
||||
* resolvedValue = crsValue;
|
||||
*
|
||||
* resolver.setResolvedValue(j, resolvedValue);
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }</PRE>
|
||||
* @author Jonathan Bruce
|
||||
*/
|
||||
|
||||
public interface SyncResolver extends RowSet {
|
||||
/**
|
||||
* Indicates that a conflict occurred while the <code>RowSet</code> object was
|
||||
* attempting to update a row in the data source.
|
||||
* The values in the data source row to be updated differ from the
|
||||
* <code>RowSet</code> object's original values for that row, which means that
|
||||
* the row in the data source has been updated or deleted since the last
|
||||
* synchronization.
|
||||
*/
|
||||
public static int UPDATE_ROW_CONFLICT = 0;
|
||||
|
||||
/**
|
||||
* Indicates that a conflict occurred while the <code>RowSet</code> object was
|
||||
* attempting to delete a row in the data source.
|
||||
* The values in the data source row to be updated differ from the
|
||||
* <code>RowSet</code> object's original values for that row, which means that
|
||||
* the row in the data source has been updated or deleted since the last
|
||||
* synchronization.
|
||||
*/
|
||||
public static int DELETE_ROW_CONFLICT = 1;
|
||||
|
||||
/**
|
||||
* Indicates that a conflict occurred while the <code>RowSet</code> object was
|
||||
* attempting to insert a row into the data source. This means that a
|
||||
* row with the same primary key as the row to be inserted has been inserted
|
||||
* into the data source since the last synchronization.
|
||||
*/
|
||||
public static int INSERT_ROW_CONFLICT = 2;
|
||||
|
||||
/**
|
||||
* Indicates that <b>no</b> conflict occurred while the <code>RowSet</code> object
|
||||
* was attempting to update, delete or insert a row in the data source. The values in
|
||||
* the <code>SyncResolver</code> will contain <code>null</code> values only as an indication
|
||||
* that no information in pertinent to the conflict resolution in this row.
|
||||
*/
|
||||
public static int NO_ROW_CONFLICT = 3;
|
||||
|
||||
/**
|
||||
* Retrieves the conflict status of the current row of this <code>SyncResolver</code>,
|
||||
* which indicates the operation
|
||||
* the <code>RowSet</code> object was attempting when the conflict occurred.
|
||||
*
|
||||
* @return one of the following constants:
|
||||
* <code>SyncResolver.UPDATE_ROW_CONFLICT</code>,
|
||||
* <code>SyncResolver.DELETE_ROW_CONFLICT</code>,
|
||||
* <code>SyncResolver.INSERT_ROW_CONFLICT</code>, or
|
||||
* <code>SyncResolver.NO_ROW_CONFLICT</code>
|
||||
*/
|
||||
public int getStatus();
|
||||
|
||||
/**
|
||||
* Retrieves the value in the designated column in the current row of this
|
||||
* <code>SyncResolver</code> object, which is the value in the data source
|
||||
* that caused a conflict.
|
||||
*
|
||||
* @param index an <code>int</code> designating the column in this row of this
|
||||
* <code>SyncResolver</code> object from which to retrieve the value
|
||||
* causing a conflict
|
||||
* @return the value of the designated column in the current row of this
|
||||
* <code>SyncResolver</code> object
|
||||
* @throws SQLException if a database access error occurs
|
||||
*/
|
||||
public Object getConflictValue(int index) throws SQLException;
|
||||
|
||||
/**
|
||||
* Retrieves the value in the designated column in the current row of this
|
||||
* <code>SyncResolver</code> object, which is the value in the data source
|
||||
* that caused a conflict.
|
||||
*
|
||||
* @param columnName a <code>String</code> object designating the column in this row of this
|
||||
* <code>SyncResolver</code> object from which to retrieve the value
|
||||
* causing a conflict
|
||||
* @return the value of the designated column in the current row of this
|
||||
* <code>SyncResolver</code> object
|
||||
* @throws SQLException if a database access error occurs
|
||||
*/
|
||||
public Object getConflictValue(String columnName) throws SQLException;
|
||||
|
||||
/**
|
||||
* Sets <i>obj</i> as the value in column <i>index</i> in the current row of the
|
||||
* <code>RowSet</code> object that is being synchronized. <i>obj</i>
|
||||
* is set as the value in the data source internally.
|
||||
*
|
||||
* @param index an <code>int</code> giving the number of the column into which to
|
||||
* set the value to be persisted
|
||||
* @param obj an <code>Object</code> that is the value to be set in the
|
||||
* <code>RowSet</code> object and persisted in the data source
|
||||
* @throws SQLException if a database access error occurs
|
||||
*/
|
||||
public void setResolvedValue(int index, Object obj) throws SQLException;
|
||||
|
||||
/**
|
||||
* Sets <i>obj</i> as the value in column <i>columnName</i> in the current row of the
|
||||
* <code>RowSet</code> object that is being synchronized. <i>obj</i>
|
||||
* is set as the value in the data source internally.
|
||||
*
|
||||
* @param columnName a <code>String</code> object giving the name of the column
|
||||
* into which to set the value to be persisted
|
||||
* @param obj an <code>Object</code> that is the value to be set in the
|
||||
* <code>RowSet</code> object and persisted in the data source
|
||||
* @throws SQLException if a database access error occurs
|
||||
*/
|
||||
public void setResolvedValue(String columnName, Object obj) throws SQLException;
|
||||
|
||||
/**
|
||||
* Moves the cursor down from its current position to the next row that contains
|
||||
* a conflict value. A <code>SyncResolver</code> object's
|
||||
* cursor is initially positioned before the first conflict row; the first call to the
|
||||
* method <code>nextConflict</code> makes the first conflict row the current row;
|
||||
* the second call makes the second conflict row the current row, and so on.
|
||||
* <p>
|
||||
* A call to the method <code>nextConflict</code> will implicitly close
|
||||
* an input stream if one is open and will clear the <code>SyncResolver</code>
|
||||
* object's warning chain.
|
||||
*
|
||||
* @return <code>true</code> if the new current row is valid; <code>false</code>
|
||||
* if there are no more rows
|
||||
* @throws SQLException if a database access error occurs or the result set type
|
||||
* is <code>TYPE_FORWARD_ONLY</code>
|
||||
*
|
||||
*/
|
||||
public boolean nextConflict() throws SQLException;
|
||||
|
||||
/**
|
||||
* Moves the cursor up from its current position to the previous conflict
|
||||
* row in this <code>SyncResolver</code> object.
|
||||
* <p>
|
||||
* A call to the method <code>previousConflict</code> will implicitly close
|
||||
* an input stream if one is open and will clear the <code>SyncResolver</code>
|
||||
* object's warning chain.
|
||||
*
|
||||
* @return <code>true</code> if the cursor is on a valid row; <code>false</code>
|
||||
* if it is off the result set
|
||||
* @throws SQLException if a database access error occurs or the result set type
|
||||
* is <code>TYPE_FORWARD_ONLY</code>
|
||||
*/
|
||||
public boolean previousConflict() throws SQLException;
|
||||
|
||||
}
|
83
jdkSrc/jdk8/javax/sql/rowset/spi/TransactionalWriter.java
Normal file
83
jdkSrc/jdk8/javax/sql/rowset/spi/TransactionalWriter.java
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, 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.spi;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.io.Reader;
|
||||
|
||||
import javax.sql.RowSetWriter;
|
||||
import javax.sql.rowset.*;
|
||||
import java.sql.Savepoint;
|
||||
|
||||
/**
|
||||
* A specialized interface that facilitates an extension of the standard
|
||||
* <code>SyncProvider</code> abstract class so that it has finer grained
|
||||
* transaction control.
|
||||
* <p>
|
||||
* If one or more disconnected <code>RowSet</code> objects are participating
|
||||
* in a global transaction, they may wish to coordinate their synchronization
|
||||
* commits to preserve data integrity and reduce the number of
|
||||
* synchronization exceptions. If this is the case, an application should set
|
||||
* the <code>CachedRowSet</code> constant <code>COMMIT_ON_ACCEPT_CHANGES</code>
|
||||
* to <code>false</code> and use the <code>commit</code> and <code>rollback</code>
|
||||
* methods defined in this interface to manage transaction boundaries.
|
||||
*/
|
||||
public interface TransactionalWriter extends RowSetWriter {
|
||||
|
||||
/**
|
||||
* Makes permanent all changes that have been performed by the
|
||||
* <code>acceptChanges</code> method since the last call to either the
|
||||
* <code>commit</code> or <code>rollback</code> methods.
|
||||
* This method should be used only when auto-commit mode has been disabled.
|
||||
*
|
||||
* @throws SQLException if a database access error occurs or the
|
||||
* <code>Connection</code> object within this <code>CachedRowSet</code>
|
||||
* object is in auto-commit mode
|
||||
*/
|
||||
public void commit() throws SQLException;
|
||||
|
||||
/**
|
||||
* Undoes all changes made in the current transaction. This method should be
|
||||
* used only when auto-commit mode has been disabled.
|
||||
*
|
||||
* @throws SQLException if a database access error occurs or the <code>Connection</code>
|
||||
* object within this <code>CachedRowSet</code> object is in auto-commit mode
|
||||
*/
|
||||
public void rollback() throws SQLException;
|
||||
|
||||
/**
|
||||
* Undoes all changes made in the current transaction made prior to the given
|
||||
* <code>Savepoint</code> object. This method should be used only when auto-commit
|
||||
* mode has been disabled.
|
||||
*
|
||||
* @param s a <code>Savepoint</code> object marking a savepoint in the current
|
||||
* transaction. All changes made before <i>s</i> was set will be undone.
|
||||
* All changes made after <i>s</i> was set will be made permanent.
|
||||
* @throws SQLException if a database access error occurs or the <code>Connection</code>
|
||||
* object within this <code>CachedRowSet</code> object is in auto-commit mode
|
||||
*/
|
||||
public void rollback(Savepoint s) throws SQLException;
|
||||
}
|
74
jdkSrc/jdk8/javax/sql/rowset/spi/XmlReader.java
Normal file
74
jdkSrc/jdk8/javax/sql/rowset/spi/XmlReader.java
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, 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.spi;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.io.Reader;
|
||||
|
||||
import javax.sql.RowSetReader;
|
||||
import javax.sql.rowset.*;
|
||||
|
||||
/**
|
||||
* A specialized interface that facilitates an extension of the
|
||||
* <code>SyncProvider</code> abstract class for XML orientated
|
||||
* synchronization providers.
|
||||
* <P>
|
||||
* <code>SyncProvider</code> implementations that supply XML data reader
|
||||
* capabilities such as output XML stream capabilities can implement this
|
||||
* interface to provide standard <code>XmlReader</code> objects to
|
||||
* <code>WebRowSet</code> implementations.
|
||||
* <p>
|
||||
* An <code>XmlReader</code> object is registered as the
|
||||
* XML reader for a <code>WebRowSet</code> by being assigned to the
|
||||
* rowset's <code>xmlReader</code> field. When the <code>WebRowSet</code>
|
||||
* object's <code>readXml</code> method is invoked, it in turn invokes
|
||||
* its XML reader's <code>readXML</code> method.
|
||||
*/
|
||||
public interface XmlReader extends RowSetReader {
|
||||
|
||||
/**
|
||||
* Reads and parses the given <code>WebRowSet</code> object from the given
|
||||
* input stream in XML format. The <code>xmlReader</code> field of the
|
||||
* given <code>WebRowSet</code> object must contain this
|
||||
* <code>XmlReader</code> object.
|
||||
* <P>
|
||||
* If a parsing error occurs, the exception that is thrown will
|
||||
* include information about the location of the error in the
|
||||
* original XML document.
|
||||
*
|
||||
* @param caller the <code>WebRowSet</code> object to be parsed, whose
|
||||
* <code>xmlReader</code> field must contain a reference to
|
||||
* this <code>XmlReader</code> object
|
||||
* @param reader the <code>java.io.Reader</code> object from which
|
||||
* <code>caller</code> will be read
|
||||
* @throws SQLException if a database access error occurs or
|
||||
* this <code>XmlReader</code> object is not the reader
|
||||
* for the given rowset
|
||||
*/
|
||||
public void readXML(WebRowSet caller, java.io.Reader reader)
|
||||
throws SQLException;
|
||||
|
||||
}
|
74
jdkSrc/jdk8/javax/sql/rowset/spi/XmlWriter.java
Normal file
74
jdkSrc/jdk8/javax/sql/rowset/spi/XmlWriter.java
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, 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.spi;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.io.Writer;
|
||||
|
||||
import javax.sql.RowSetWriter;
|
||||
import javax.sql.rowset.*;
|
||||
|
||||
/**
|
||||
* A specialized interface that facilitates an extension of the
|
||||
* <code>SyncProvider</code> abstract class for XML orientated
|
||||
* synchronization providers.
|
||||
* <p>
|
||||
* <code>SyncProvider</code> implementations that supply XML data writer
|
||||
* capabilities such as output XML stream capabilities can implement this
|
||||
* interface to provide standard <code>XmlWriter</code> objects to
|
||||
* <code>WebRowSet</code> implementations.
|
||||
* <P>
|
||||
* Writing a <code>WebRowSet</code> object includes printing the
|
||||
* rowset's data, metadata, and properties, all with the
|
||||
* appropriate XML tags.
|
||||
*/
|
||||
public interface XmlWriter extends RowSetWriter {
|
||||
|
||||
/**
|
||||
* Writes the given <code>WebRowSet</code> object to the specified
|
||||
* <code>java.io.Writer</code> output stream as an XML document.
|
||||
* This document includes the rowset's data, metadata, and properties
|
||||
* plus the appropriate XML tags.
|
||||
* <P>
|
||||
* The <code>caller</code> parameter must be a <code>WebRowSet</code>
|
||||
* object whose <code>XmlWriter</code> field contains a reference to
|
||||
* this <code>XmlWriter</code> object.
|
||||
*
|
||||
* @param caller the <code>WebRowSet</code> instance to be written,
|
||||
* for which this <code>XmlWriter</code> object is the writer
|
||||
* @param writer the <code>java.io.Writer</code> object that serves
|
||||
* as the output stream for writing <code>caller</code> as
|
||||
* an XML document
|
||||
* @throws SQLException if a database access error occurs or
|
||||
* this <code>XmlWriter</code> object is not the writer
|
||||
* for the given <code>WebRowSet</code> object
|
||||
*/
|
||||
public void writeXML(WebRowSet caller, java.io.Writer writer)
|
||||
throws SQLException;
|
||||
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user