1 /* 2 * Copyright (c) 2003, 2010, 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 package com.sun.rowset.providers; 27 28 import com.sun.rowset.JdbcRowSetResourceBundle; 29 import javax.sql.*; 30 import java.io.*; 31 32 import javax.sql.rowset.spi.*; 33 import com.sun.rowset.internal.*; 34 35 /** 36 * The reference implementation of a JDBC Rowset synchronization provider 37 * providing optimistic synchronization with a relational datastore 38 * using any JDBC technology-enabled driver. 39 * 40 * <h3>1.0 Backgroud</h3> 41 * This synchronization provider is registered with the 42 * <code>SyncFactory</code> by default as the 43 * <code>com.sun.rowset.providers.RIOptimisticProvider</code>. 44 * As an extension of the <code>SyncProvider</code> abstract 45 * class, it provides the reader and writer classes required by disconnected 46 * rowsets as <code>javax.sql.RowSetReader</code> and <code>javax.sql.RowSetWriter</code> 47 * interface implementations. As a reference implementation, 48 * <code>RIOptimisticProvider</code> provides a 49 * fully functional implementation offering a medium grade classification of 50 * syncrhonization, namely GRADE_CHECK_MODIFIED_AT_COMMIT. A 51 * disconnected <code>RowSet</code> implementation using the 52 * <code>RIOptimisticProvider</code> can expect the writer to 53 * check only rows that have been modified in the <code>RowSet</code> against 54 * the values in the data source. If there is a conflict, that is, if a value 55 * in the data source has been changed by another party, the 56 * <code>RIOptimisticProvider</code> will not write any of the changes to the data 57 * source and will throw a <code>SyncProviderException</code> object. 58 * 59 * <h3>2.0 Usage</h3> 60 * Standard disconnected <code>RowSet</code> implementations may opt to use this 61 * <code>SyncProvider</code> implementation in one of two ways: 62 * <OL> 63 * <LI>By specifically calling the <code>setSyncProvider</code> method 64 defined in the <code>CachedRowSet</code> interface 65 * <pre> 66 * CachedRowset crs = new FooCachedRowSetImpl(); 67 * crs.setSyncProvider("com.sun.rowset.providers.RIOptimisticProvider"); 68 * </pre> 69 * <LI>By specifying it in the constructor of the <code>RowSet</code> 70 * implementation 71 * <pre> 72 * CachedRowset crs = new FooCachedRowSetImpl( 73 * "com.sun.rowset.providers.RIOptimisticProvider"); 74 * </pre> 75 * </OL> 76 * Note that because the <code>RIOptimisticProvider</code> implementation is 77 * the default provider, it will always be the provider when no provider ID is 78 * specified to the constructor. 79 * <P> 80 * See the standard <code>RowSet</code> reference implementations in the 81 * <code>com.sun.rowset</code> package for more details. 82 * 83 * @author Jonathan Bruce 84 * @see javax.sql.rowset.spi.SyncProvider 85 * @see javax.sql.rowset.spi.SyncProviderException 86 * @see javax.sql.rowset.spi.SyncFactory 87 * @see javax.sql.rowset.spi.SyncFactoryException 88 * 89 */ 90 public final class RIOptimisticProvider extends SyncProvider implements Serializable { 91 92 private CachedRowSetReader reader; 93 private CachedRowSetWriter writer; 94 95 /** 96 * The unique provider identifier. 97 */ 98 private String providerID = "com.sun.rowset.providers.RIOptimisticProvider"; 99 100 /** 101 * The vendor name of this SyncProvider implementation 102 */ 103 private String vendorName = "Oracle Corporation"; 104 105 /** 106 * The version number of this SyncProvider implementation 107 */ 108 private String versionNumber = "1.0"; 109 110 /** 111 * ResourceBundle 112 */ 113 private JdbcRowSetResourceBundle resBundle; 114 115 /** 116 * Creates an <code>RIOptimisticProvider</code> object initialized with the 117 * fully qualified class name of this <code>SyncProvider</code> implementation 118 * and a default reader and writer. 119 * <P> 120 * This provider is available to all disconnected <code>RowSet</code> implementations 121 * as the default persistence provider. 122 */ 123 public RIOptimisticProvider() { 124 providerID = this.getClass().getName(); 125 reader = new CachedRowSetReader(); 126 writer = new CachedRowSetWriter(); 127 try { 128 resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); 129 } catch(IOException ioe) { 130 throw new RuntimeException(ioe); 131 } 132 } 133 134 /** 135 * Returns the <code>'javax.sql.rowset.providers.RIOptimisticProvider'</code> 136 * provider identification string. 137 * 138 * @return String Provider ID of this persistence provider 139 */ 140 public String getProviderID() { 141 return providerID; 142 } 143 144 /** 145 * Returns the <code>javax.sql.RowSetWriter</code> object for this 146 * <code>RIOptimisticProvider</code> object. This is the writer that will 147 * write changes made to the <code>Rowset</code> object back to the data source. 148 * 149 * @return the <code>javax.sql.RowSetWriter</code> object for this 150 * <code>RIOptimisticProvider</code> object 151 */ 152 public RowSetWriter getRowSetWriter() { 153 try { 154 writer.setReader(reader); 155 } catch (java.sql.SQLException e) {} 156 return writer; 157 } 158 159 /** 160 * Returns the <code>javax.sql.RowSetReader</code> object for this 161 * <code>RIOptimisticProvider</code> object. This is the reader that will 162 * populate a <code>RowSet</code> object using this <code>RIOptimisticProvider</code>. 163 * 164 * @return the <code>javax.sql.RowSetReader</code> object for this 165 * <code>RIOptimisticProvider</code> object 166 */ 167 public RowSetReader getRowSetReader() { 168 return reader; 169 } 170 171 /** 172 * Returns the <code>SyncProvider</code> grade of synchronization that 173 * <code>RowSet</code> objects can expect when using this 174 * implementation. As an optimisic synchonization provider, the writer 175 * will only check rows that have been modified in the <code>RowSet</code> 176 * object. 177 */ 178 public int getProviderGrade() { 179 return SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT; 180 } 181 182 /** 183 * Modifies the data source lock severity according to the standard 184 * <code>SyncProvider</code> classifications. 185 * 186 * @param datasource_lock An <code>int</code> indicating the level of locking to be 187 * set; must be one of the following constants: 188 * <PRE> 189 * SyncProvider.DATASOURCE_NO_LOCK, 190 * SyncProvider.DATASOURCE_ROW_LOCK, 191 * SyncProvider.DATASOURCE_TABLE_LOCK, 192 * SyncProvider.DATASOURCE_DB_LOCk 193 * </PRE> 194 * @throws SyncProviderException if the parameter specified is not 195 * <code>SyncProvider.DATASOURCE_NO_LOCK</code> 196 */ 197 public void setDataSourceLock(int datasource_lock) throws SyncProviderException { 198 if(datasource_lock != SyncProvider.DATASOURCE_NO_LOCK ) { 199 throw new SyncProviderException(resBundle.handleGetObject("riop.locking").toString()); 200 } 201 } 202 203 /** 204 * Returns the active data source lock severity in this 205 * reference implementation of the <code>SyncProvider</code> 206 * abstract class. 207 * 208 * @return <code>SyncProvider.DATASOURCE_NO_LOCK</code>. 209 * The reference implementation does not support data source locks. 210 */ 211 public int getDataSourceLock() throws SyncProviderException { 212 return SyncProvider.DATASOURCE_NO_LOCK; 213 } 214 215 /** 216 * Returns the supported updatable view abilities of the 217 * reference implementation of the <code>SyncProvider</code> 218 * abstract class. 219 * 220 * @return <code>SyncProvider.NONUPDATABLE_VIEW_SYNC</code>. The 221 * the reference implementation does not support updating tables 222 * that are the source of a view. 223 */ 224 public int supportsUpdatableView() { 225 return SyncProvider.NONUPDATABLE_VIEW_SYNC; 226 } 227 228 /** 229 * Returns the release version ID of the Reference Implementation Optimistic 230 * Synchronization Provider. 231 * 232 * @return the <code>String</code> detailing the version number of this SyncProvider 233 */ 234 public String getVersion() { 235 return this.versionNumber; 236 } 237 238 /** 239 * Returns the vendor name of the Reference Implementation Optimistic 240 * Synchronization Provider 241 * 242 * @return the <code>String</code> detailing the vendor name of this 243 * SyncProvider 244 */ 245 public String getVendor() { 246 return this.vendorName; 247 } 248 249 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { 250 // Default state initialization happens here 251 ois.defaultReadObject(); 252 // Initialization of transient Res Bundle happens here . 253 try { 254 resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); 255 } catch(IOException ioe) { 256 throw new RuntimeException(ioe); 257 } 258 259 } 260 static final long serialVersionUID =-3143367176751761936L; 261 262 }