1 /*
   2  * Copyright (c)  2003, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /**
  27  * The standard classes and interfaces that a third party vendor has to
  28  * use in its implementation of a synchronization provider. These classes and
  29  * interfaces are referred to as the Service Provider Interface (SPI).  To make it possible
  30  * for a <code>RowSet</code> object to use an implementation, the vendor must register
  31  * it with the <code>SyncFactory</code> singleton. (See the class comment for
  32  * <code>SyncProvider</code> for a full explanation of the registration process and
  33  * the naming convention to be used.)
  34  *
  35  * <h2>Table of Contents</h2>
  36  * <ul>
  37  * <li><a href="#pkgspec">1.0 Package Specification</a>
  38  * <li><a href="#arch">2.0 Service Provider Architecture</a>
  39  * <li><a href="#impl">3.0 Implementer's Guide</a>
  40  * <li><a href="#resolving">4.0 Resolving Synchronization Conflicts</a>
  41  * <li><a href="#relspec">5.0 Related Specifications</a>
  42  * <li><a href="#reldocs">6.0 Related Documentation</a>
  43  * </ul>
  44  *
  45  * <h3><a id="pkgspec">1.0 Package Specification</a></h3>
  46  * <P>
  47  * The following classes and interfaces make up the <code>javax.sql.rowset.spi</code>
  48  * package:
  49  * <UL>
  50  *  <LI><code>SyncFactory</code>
  51  *  <LI><code>SyncProvider</code>
  52  *  <LI><code>SyncFactoryException</code>
  53  *  <LI><code>SyncProviderException</code>
  54  *  <LI><code>SyncResolver</code>
  55  *  <LI><code>XmlReader</code>
  56  *  <LI><code>XmlWriter</code>
  57  *  <LI><code>TransactionalWriter</code>
  58  * </UL>
  59  * The following interfaces, in the <code>javax.sql</code> package, are also part of the SPI:
  60  * <UL>
  61  *  <LI><code>RowSetReader</code>
  62  *  <LI><code>RowSetWriter</code>
  63  * </UL>
  64  * <P>
  65  * A <code>SyncProvider</code> implementation provides a disconnected <code>RowSet</code>
  66  * object with the mechanisms for reading data into it and for writing data that has been
  67  * modified in it
  68  * back to the underlying data source.  A <i>reader</i>, a <code>RowSetReader</code> or
  69  * <code>XMLReader</code> object, reads data into a <code>RowSet</code> object when the
  70  * <code>CachedRowSet</code> methods <code>execute</code> or <code>populate</code>
  71  * are called.  A <i>writer</i>, a <code>RowSetWriter</code> or <code>XMLWriter</code>
  72  * object, writes changes back to the underlying data source when the
  73  * <code>CachedRowSet</code> method <code>acceptChanges</code> is called.
  74  * <P>
  75  * The process of writing changes in a <code>RowSet</code> object to its data source
  76  * is known as <i>synchronization</i>.  The <code>SyncProvider</code> implementation that a
  77  * <code>RowSet</code> object is using determines the level of synchronization that the
  78  * <code>RowSet</code> object's writer uses. The various levels of synchronization are
  79  * referred to as <i>grades</i>.
  80  * <P>
  81  * The lower grades of synchronization are
  82  * known as <i>optimistic</i> concurrency levels because they optimistically
  83  * assume that there will be no conflicts or very few conflicts.  A conflict exists when
  84  * the same data modified in the <code>RowSet</code> object has also been modified
  85  * in the data source. Using the optimistic concurrency model means that if there
  86  * is a conflict, modifications to either the data source or the <code>RowSet</code>
  87  * object will be lost.
  88  * <P>
  89  * Higher grades of synchronization are called <i>pessimistic</i> because they assume
  90  * that others will be accessing the data source and making modifications.  These
  91  * grades set varying levels of locks to increase the chances that no conflicts
  92  * occur.
  93  * <P>
  94  * The lowest level of synchronization is simply writing any changes made to the
  95  * <code>RowSet</code> object to its underlying data source.  The writer does
  96  * nothing to check for conflicts.
  97  * If there is a conflict and the data
  98  * source values are overwritten, the changes other parties have made by to the data
  99  * source are lost.
 100  * <P>
 101  * The <code>RIXMLProvider</code> implementation uses the lowest level
 102  * of synchronization and just writes <code>RowSet</code> changes to the data source.
 103  *
 104  * <P>
 105  * For the next level up, the
 106  * writer checks to see if there are any conflicts, and if there are,
 107  * it does not write anything to the data source.  The problem with this concurrency
 108  * level is that if another party has modified the corresponding data in the data source
 109  * since the <code>RowSet</code> object got its data,
 110  * the changes made to the <code>RowSet</code> object are lost. The
 111  * <code>RIOptimisticProvider</code> implementation uses this level of synchronization.
 112  * <P>
 113  * At higher levels of synchronization, referred to as pessimistic concurrency,
 114  * the writer take steps to avoid conflicts by setting locks. Setting locks
 115  * can vary from setting a lock on a single row to setting a lock on a table
 116  * or the entire data source. The level of synchronization is therefore a tradeoff
 117  * between the ability of users to access the data source concurrently and the  ability
 118  * of the writer to keep the data in the <code>RowSet</code> object and its data source
 119  * synchronized.
 120  * <P>
 121  * It is a requirement that all disconnected <code>RowSet</code> objects
 122  * (<code>CachedRowSet</code>, <code>FilteredRowSet</code>, <code>JoinRowSet</code>,
 123  * and <code>WebRowSet</code> objects) obtain their <code>SyncProvider</code> objects
 124  * from the <code>SyncFactory</code> mechanism.
 125  * <P>
 126  * The reference implementation (RI) provides two synchronization providers.
 127  *    <UL>
 128  *       <LI><b><code>RIOptimisticProvider</code></b> <br>
 129  *            The default provider that the <code>SyncFactory</code> instance will
 130  *            supply to a disconnected <code>RowSet</code> object when no provider
 131  *            implementation is specified.<BR>
 132  *            This synchronization provider uses an optimistic concurrency model,
 133  *            assuming that there will be few conflicts among users
 134  *            who are accessing the same data in a database.  It avoids
 135  *            using locks; rather, it checks to see if there is a conflict
 136  *            before trying to synchronize the <code>RowSet</code> object and the
 137  *            data source. If there is a conflict, it does nothing, meaning that
 138  *            changes to the <code>RowSet</code> object are not persisted to the data
 139  *            source.
 140  *        <LI><B><code>RIXMLProvider</code></B> <BR>
 141  *             A synchronization provider that can be used with a
 142  *             <code>WebRowSet</code> object, which is a rowset that can be written
 143  *             in XML format or read from XML format. The
 144  *             <code>RIXMLProvider</code> implementation does no checking at all for
 145  *             conflicts and simply writes any updated data in the
 146  *             <code>WebRowSet</code> object to the underlying data source.
 147  *             <code>WebRowSet</code> objects use this provider when they are
 148  *             dealing with XML data.
 149  *     </UL>
 150  *
 151  *  These <code>SyncProvider</code> implementations
 152  *  are bundled with the reference implementation, which makes them always available to
 153  *  <code>RowSet</code> implementations.
 154  *  <code>SyncProvider</code> implementations make themselves available by being
 155  *  registered with the <code>SyncFactory</code> singleton.  When a <code>RowSet</code>
 156  *  object requests a provider, by specifying it in the constructor or as an argument to the
 157  *  <code>CachedRowSet</code> method <code>setSyncProvider</code>,
 158  *  the <code>SyncFactory</code> singleton
 159  *  checks to see if the requested provider has been registered with it.
 160  *  If it has, the <code>SyncFactory</code> creates an instance of it and passes it to the
 161  *  requesting <code>RowSet</code> object.
 162  *  If the <code>SyncProvider</code> implementation that is specified has not been registered,
 163  *  the <code>SyncFactory</code> singleton causes a <code>SyncFactoryException</code> object
 164  *  to be thrown.  If no provider is specified,
 165  *  the <code>SyncFactory</code> singleton will create an instance of the default
 166  *  provider implementation, <code>RIOptimisticProvider</code>,
 167  *  and pass it to the requesting <code>RowSet</code> object.
 168  *
 169  * <P>
 170  * If a <code>WebRowSet</code> object does not specify a provider in its constructor, the
 171  * <code>SyncFactory</code> will give it an instance of <code>RIOptimisticProvider</code>.
 172  * However, the constructor for <code>WebRowSet</code> is implemented to set the provider
 173  * to the <code>RIXMLProvider</code>, which reads and writes a <code>RowSet</code> object
 174  *  in XML format.
 175  *  <P>
 176  * See the <a href="SyncProvider.html">SyncProvider</a> class
 177  *  specification for further details.
 178  * <p>
 179  * Vendors may develop a <code>SyncProvider</code> implementation with any one of the possible
 180  * levels of synchronization, thus giving <code>RowSet</code> objects a choice of
 181  * synchronization mechanisms.
 182  *
 183  * <h3><a id="arch">2.0 Service Provider Interface Architecture</a></h3>
 184  * <b>2.1 Overview</b>
 185  * <p>
 186  * The Service Provider Interface provides a pluggable mechanism by which
 187  * <code>SyncProvider</code> implementations can be registered and then generated when
 188  * required. The lazy reference mechanism employed by the <code>SyncFactory</code> limits
 189  * unnecessary resource consumption by not creating an instance until it is
 190  * required by a disconnected
 191  * <code>RowSet</code> object. The <code>SyncFactory</code> class also provides
 192  * a standard API to configure logging options and streams that <b>may</b> be provided
 193  * by a particular <code>SyncProvider</code> implementation.
 194  * <p>
 195  * <b>2.2 Registering with the <code>SyncFactory</code></b>
 196  * <p>
 197  * A third party <code>SyncProvider</code> implementation must be registered with the
 198  * <code>SyncFactory</code> in order for a disconnected <code>RowSet</code> object
 199  * to obtain it and thereby use its <code>javax.sql.RowSetReader</code> and
 200  * <code>javax.sql.RowSetWriter</code>
 201  * implementations. The following registration mechanisms are available to all
 202  * <code>SyncProvider</code> implementations:
 203  * <ul>
 204  * <li><b>System properties</b> - Properties set at the command line. These
 205  * properties are set at run time and apply system-wide per invocation of the Java
 206  * application. See the section <a href="#reldocs">"Related Documentation"</a>
 207  * further related information.
 208  *
 209  * <li><b>Property Files</b> - Properties specified in a standard property file.
 210  * This can be specified using a System Property or by modifying a standard
 211  * property file located in the platform run-time. The
 212  * reference implementation of this technology includes a standard property
 213  * file than can be edited to add additional <code>SyncProvider</code> objects.
 214  *
 215  * <li><b>JNDI Context</b> - Available providers can be registered on a JNDI
 216  * context. The <code>SyncFactory</code> will attempt to load <code>SyncProvider</code>
 217  * objects bound to the context and register them with the factory. This
 218  * context must be supplied to the <code>SyncFactory</code> for the mechanism to
 219  * function correctly.
 220  * </ul>
 221  * <p>
 222  * Details on how to specify the system properties or properties in a property file
 223  * and how to configure the JNDI Context are explained in detail in the
 224  * <a href="SyncFactory.html"><code>SyncFactory</code></a> class description.
 225  * <p>
 226  * <b>2.3 SyncFactory Provider Instance Generation Policies</b>
 227  * <p>
 228  * The <code>SyncFactory</code> generates a requested <code>SyncProvider</code>
 229  * object if the provider has been correctly registered.  The
 230  * following policies are adhered to when either a disconnected <code>RowSet</code> object
 231  * is instantiated with a specified <code>SyncProvider</code> implementation or is
 232  * reconfigured at runtime with an alternative <code>SyncProvider</code> object.
 233  * <ul>
 234  * <li> If a <code>SyncProvider</code> object is specified and the <code>SyncFactory</code>
 235  * contains <i>no</i> reference to the provider, a <code>SyncFactoryException</code> is
 236  * thrown.
 237  *
 238  * <li> If a <code>SyncProvider</code> object is specified and the <code>SyncFactory</code>
 239  * contains a reference to the provider, the requested provider is supplied.
 240  *
 241  * <li> If no <code>SyncProvider</code> object is specified, the reference
 242  * implementation provider <code>RIOptimisticProvider</code> is supplied.
 243  * </ul>
 244  * <p>
 245  * These policies are explored in more detail in the <a href="SyncFactory.html">
 246  * <code>SyncFactory</code></a> class.
 247  *
 248  * <h3><a id="impl">3.0 SyncProvider Implementer's Guide</a></h3>
 249  *
 250  * <b>3.1 Requirements</b>
 251  * <p>
 252  * A compliant <code>SyncProvider</code> implementation that is fully pluggable
 253  * into the <code>SyncFactory</code> <b>must</b> extend and implement all
 254  * abstract methods in the <a href="SyncProvider.html"><code>SyncProvider</code></a>
 255  * class. In addition, an implementation <b>must</b> determine the
 256  * grade, locking and updatable view capabilities defined in the
 257  * <code>SyncProvider</code> class definition. One or more of the
 258  * <code>SyncProvider</code> description criteria <b>must</b> be supported. It
 259  * is expected that vendor implementations will offer a range of grade, locking, and
 260  * updatable view capabilities.
 261  * <p>
 262  * Furthermore, the <code>SyncProvider</code> naming convention <b>must</b> be followed as
 263  * detailed in the <a href="SyncProvider.html"><code>SyncProvider</code></a> class
 264  * description.
 265  * <p>
 266  * <b>3.2 Grades</b>
 267  * <p>
 268  * JSR 114 defines a set of grades to describe the quality of synchronization
 269  * a <code>SyncProvider</code> object can offer a disconnected <code>RowSet</code>
 270  * object. These grades are listed from the lowest quality of service to the highest.
 271  * <ul>
 272  * <li><b>GRADE_NONE</b> - No synchronization with the originating data source is
 273  * provided. A <code>SyncProvider</code> implementation returning this grade will simply
 274  * attempt to write any data that has changed in the <code>RowSet</code> object to the
 275  *underlying data source, overwriting whatever is there. No attempt is made to compare
 276  * original values with current values to see if there is a conflict. The
 277  * <code>RIXMLProvider</code> is implemented with this grade.
 278  *
 279  * <li><b>GRADE_CHECK_MODIFIED_AT_COMMIT</b> - A low grade of optimistic synchronization.
 280  * A <code>SyncProvider</code> implementation returning this grade
 281  * will check for conflicts in rows that have changed between the last synchronization
 282  * and the current synchronization under way. Any changes in the originating data source
 283  * that have been modified will not be reflected in the disconnected <code>RowSet</code>
 284  * object. If there are no conflicts, changes in the <code>RowSet</code> object will be
 285  * written to the data source. If there are conflicts, no changes are written.
 286  * The <code>RIOptimisticProvider</code> implementation uses this grade.
 287  *
 288  * <li><b>GRADE_CHECK_ALL_AT_COMMIT</b> - A high grade of optimistic synchronization.
 289  * A <code>SyncProvider</code> implementation   returning this grade
 290  * will check all rows, including rows that have not changed in the disconnected
 291  * <code>RowSet</code> object. In this way, any changes to rows in the underlying
 292  * data source will be reflected in the disconnected <code>RowSet</code> object
 293  * when the synchronization finishes successfully.
 294  *
 295  * <li><b>GRADE_LOCK_WHEN_MODIFIED</b> - A pessimistic grade of synchronization.
 296  * <code>SyncProvider</code> implementations returning this grade will lock
 297  * the row in the originating  data source that corresponds to the row being changed
 298  * in the <code>RowSet</code> object to reduce the possibility of other
 299  * processes modifying the same data in the data source.
 300  *
 301  * <li><b>GRADE_LOCK_WHEN_LOADED</b> - A higher pessimistic synchronization grade.
 302  * A <code>SyncProvider</code> implementation returning this grade will lock
 303  * the entire view and/or  table affected by the original query used to
 304  * populate a <code>RowSet</code> object.
 305  * </ul>
 306  * <p>
 307  * <b>3.3 Locks</b>
 308  * <p>
 309  * JSR 114 defines a set of constants that specify whether any locks have been
 310  * placed on a <code>RowSet</code> object's underlying data source and, if so,
 311  * on which constructs the locks are placed.  These locks will remain on the data
 312  * source while the <code>RowSet</code> object is disconnected from the data source.
 313  * <P>
 314  * These constants <b>should</b> be considered complementary to the
 315  * grade constants. The default setting for the majority of grade settings requires
 316  * that no data source locks remain when a <code>RowSet</code> object is disconnected
 317  * from its data source.
 318  * The grades <code>GRADE_LOCK_WHEN_MODIFIED</code> and
 319  * <code>GRADE_LOCK_WHEN_LOADED</code> allow a disconnected <code>RowSet</code> object
 320  * to have a fine-grained control over the degree of locking.
 321  * <ul>
 322  * <li><b>DATASOURCE_NO_LOCK</b> - No locks remain on the originating data source.
 323  * This is the default lock setting for all <code>SyncProvider</code> implementations
 324  * unless otherwise directed by a <code>RowSet</code> object.
 325  *
 326  * <li><b>DATASOURCE_ROW_LOCK</b> - A lock is placed on the rows that are touched by
 327  * the original SQL query used to populate the <code>RowSet</code> object.
 328  *
 329  * <li><b>DATASOURCE_TABLE_LOCK</b> - A lock is placed on all tables that are touched
 330  * by the query that was used to populate the <code>RowSet</code> object.
 331  *
 332  * <li><b>DATASOURCE_DB_LOCK</b>
 333  * A lock is placed on the entire data source that is used by the <code>RowSet</code>
 334  * object.
 335  * </ul>
 336  * <p>
 337  * <b>3.4 Updatable Views</b>
 338  * <p>
 339  * A <code>RowSet</code> object may be populated with data from an SQL <code>VIEW</code>.
 340  * The following constants indicate whether a <code>SyncProvider</code> object can
 341  * update data in the table or tables from which the <code>VIEW</code> was derived.
 342  * <ul>
 343  * <li><b>UPDATABLE_VIEW_SYNC</b>
 344  * Indicates that a <code>SyncProvider</code> implementation  supports synchronization
 345  * to the table or tables from which the SQL <code>VIEW</code> used to populate
 346  * a <code>RowSet</code> object is derived.
 347  *
 348  * <li><b>NONUPDATABLE_VIEW_SYNC</b>
 349  * Indicates that a <code>SyncProvider</code> implementation  does <b>not</b> support
 350  * synchronization to the table or tables from which the SQL <code>VIEW</code>
 351  * used to populate  a <code>RowSet</code> object is derived.
 352  * </ul>
 353  * <p>
 354  * <b>3.5 Usage of <code>SyncProvider</code> Grading and Locking</b>
 355  * <p>
 356  * In the example below, the reference <code>CachedRowSetImpl</code> implementation
 357  * reconfigures its current <code>SyncProvider</code> object by calling the
 358  * <code>setSyncProvider</code> method.<br>
 359  *
 360  * <PRE>
 361  *   CachedRowSetImpl crs = new CachedRowSetImpl();
 362  *   crs.setSyncProvider("com.foo.bar.HASyncProvider");
 363  * </PRE>
 364  *   An application can retrieve the <code>SyncProvider</code> object currently in use
 365  * by a disconnected <code>RowSet</code> object. It can also retrieve the
 366  * grade of synchronization with which the provider was implemented and the degree of
 367  * locking currently in use.  In addition, an application has the flexibility to set
 368  * the degree of locking to be used, which can increase the possibilities for successful
 369  * synchronization.  These operation are shown in the following code fragment.
 370  * <PRE>
 371  *   SyncProvider sync = crs.getSyncProvider();
 372  *
 373  *   switch (sync.getProviderGrade()) {
 374  *   case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT
 375  *         //A high grade of optimistic synchronization
 376  *    break;
 377  *    case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT
 378  *         //A low grade of optimistic synchronization
 379  *    break;
 380  *    case: SyncProvider.GRADE_LOCK_WHEN_LOADED
 381  *         // A pessimistic synchronization grade
 382  *    break;
 383  *    case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED
 384  *         // A pessimistic synchronization grade
 385  *    break;
 386  *    case: SyncProvider.GRADE_NONE
 387  *      // No synchronization with the originating data source provided
 388  *    break;
 389  *    }
 390  *
 391  *    switch (sync.getDataSourcLock() {
 392  *      case: SyncProvider.DATASOURCE_DB_LOCK
 393  *       // A lock is placed on the entire datasource that is used by the
 394  *       // <code>RowSet</code> object
 395  *       break;
 396  *
 397  *      case: SyncProvider.DATASOURCE_NO_LOCK
 398  *       // No locks remain on the  originating data source.
 399  *      break;
 400  *
 401  *      case: SyncProvider.DATASOURCE_ROW_LOCK
 402  *       // A lock is placed on the rows that are  touched by the original
 403  *       // SQL statement used to populate
 404  *       // the RowSet object that is using the SyncProvider
 405  *       break;
 406  *
 407  *      case: DATASOURCE_TABLE_LOCK
 408  *       // A lock is placed on  all tables that are touched by the original
 409  *       // SQL statement used to populated
 410  *       // the RowSet object that is using the SyncProvider
 411  *      break;
 412  *
 413  * </PRE>
 414  *    It is also possible using the static utility method in the
 415  * <code>SyncFactory</code> class to determine the list of <code>SyncProvider</code>
 416  * implementations currently registered with the <code>SyncFactory</code>.
 417  *
 418  * <pre>
 419  *       Enumeration e = SyncFactory.getRegisteredProviders();
 420  * </pre>
 421  *
 422  *
 423  * <h3><a id="resolving">4.0 Resolving Synchronization Conflicts</a></h3>
 424  *
 425  * The interface <code>SyncResolver</code> provides a way for an application to
 426  * decide manually what to do when a conflict occurs. When the <code>CachedRowSet</code>
 427  * method <code>acceptChanges</code> finishes and has detected one or more conflicts,
 428  * it throws a <code>SyncProviderException</code> object.  An application can
 429  * catch the exception and
 430  * have it retrieve a <code>SyncResolver</code> object by calling the method
 431  * <code>SyncProviderException.getSyncResolver()</code>.
 432  * <P>
 433  * A <code>SyncResolver</code> object, which is a special kind of
 434  * <code>CachedRowSet</code> object or
 435  * a <code>JdbcRowSet</code> object that has implemented the <code>SyncResolver</code>
 436  * interface,  examines the conflicts row by row. It is a duplicate of the
 437  * <code>RowSet</code> object being synchronized except that it contains only the data
 438  * from the data source this is causing a conflict. All of the other column values are
 439  * set to <code>null</code>. To navigate from one conflict value to another, a
 440  * <code>SyncResolver</code> object provides the methods <code>nextConflict</code> and
 441  * <code>previousConflict</code>.
 442  * <P>
 443  * The <code>SyncResolver</code> interface also
 444  * provides methods for doing the following:
 445  * <UL>
 446  *  <LI>finding out whether the conflict involved an update, a delete, or an insert
 447  *  <LI>getting the value in the data source that caused the conflict
 448  *  <LI>setting the value that should be in the data source if it needs to be changed
 449  *      or setting the value that should be in the <code>RowSet</code> object if it needs
 450  *      to be changed
 451  * </UL>
 452  * <P>
 453  * When the <code>CachedRowSet</code> method <code>acceptChanges</code> is called, it
 454  * delegates to the <code>RowSet</code> object's  <code>SyncProvider</code> object.
 455  * How the writer provided by that <code>SyncProvider</code> object is implemented
 456  * determines what level (grade) of checking for conflicts will be done.  After all
 457  * checking for conflicts is completed and one or more conflicts has been found, the method
 458  * <code>acceptChanges</code> throws a <code>SyncProviderException</code> object. The
 459  * application can catch the exception and use it to obtain a <code>SyncResolver</code> object.
 460  * <P>
 461  * The application can then use <code>SyncResolver</code> methods to get information
 462  * about each conflict and decide what to do.  If the application logic or the user
 463  * decides that a value in the <code>RowSet</code> object should be the one to
 464  * persist, the application or user can overwrite the data source value with it.
 465  * <P>
 466  * The comment for the <code>SyncResolver</code> interface has more detail.
 467  *
 468  * <h3><a id="relspec">5.0 Related Specifications</a></h3>
 469  * <ul>
 470  * <li><a href="http://docs.oracle.com/javase/jndi/tutorial/index.html">JNDI</a>
 471  * <li><a href="{@docRoot}/java.logging/java/util/logging/package-summary.html">Java Logging
 472  * APIs</a>
 473  * </ul>
 474  * <h3><a id="reldocs">6.0 Related Documentation</a></h3>
 475  * <ul>
 476  * <li><a href="http://docs.oracle.com/javase/tutorial/jdbc/">DataSource for JDBC
 477  * Connections</a>
 478  * </ul>
 479  */
 480 package javax.sql.rowset.spi;