if(resBundle == null) { try { resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); } catch(IOException ioe) { throw new RuntimeException(ioe); } } setShowDeleted(false); setQueryTimeout(0); setMaxRows(0); setMaxFieldSize(0); setType(ResultSet.TYPE_SCROLL_INSENSITIVE); setConcurrency(ResultSet.CONCUR_UPDATABLE); if((rvh.size() > 0) && (isReadOnly() == false)) setReadOnly(false); else setReadOnly(true); setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); setEscapeProcessing(true); //setTypeMap(null); checkTransactionalWriter(); //Instantiating the vector for MatchColumns iMatchColumns = new Vector<Integer>(10); for(int i = 0; i < 10 ; i++) { iMatchColumns.add(i,Integer.valueOf(-1)); } strMatchColumns = new Vector<String>(10); for(int j = 0; j < 10; j++) { strMatchColumns.add(j,null); } } /** * Determine whether the SyncProvider's writer implements the * <code>TransactionalWriter<code> interface */ private void checkTransactionalWriter() { if (rowSetWriter != null) { Class c = rowSetWriter.getClass(); if (c != null) { Class[] theInterfaces = c.getInterfaces(); for (int i = 0; i < theInterfaces.length; i++) { if ((theInterfaces[i].getName()).indexOf("TransactionalWriter") > 0) { tXWriter = true; establishTransactionalWriter(); } } } } } /** * Sets an private field to all transaction bounddaries to be set */ private void establishTransactionalWriter() { tWriter = (TransactionalWriter)provider.getRowSetWriter(); } //----------------------------------------------------------------------- // Properties //----------------------------------------------------------------------- /** * Sets this <code>CachedRowSetImpl</code> object's command property * to the given <code>String</code> object and clears the parameters, * if any, that were set for the previous command. * <P> * The command property may not be needed * if the rowset is produced by a data source, such as a spreadsheet, * that does not support commands. Thus, this property is optional * and may be <code>null</code>. * * @param cmd a <code>String</code> object containing an SQL query * that will be set as the command; may be <code>null</code> * @throws SQLException if an error occurs */ public void setCommand(String cmd) throws SQLException { super.setCommand(cmd); if(!buildTableName(cmd).equals("")) { this.setTableName(buildTableName(cmd)); } } //--------------------------------------------------------------------- // Reading and writing data //--------------------------------------------------------------------- /** * Populates this <code>CachedRowSetImpl</code> object with data from * the given <code>ResultSet</code> object. This * method is an alternative to the method <code>execute</code> * for filling the rowset with data. The method <code>populate</code> * does not require that the properties needed by the method * <code>execute</code>, such as the <code>command</code> property, * be set. This is true because the method <code>populate</code> * is given the <code>ResultSet</code> object from * which to get data and thus does not need to use the properties * required for setting up a connection and executing this * <code>CachedRowSetImpl</code> object's command. * <P> * After populating this rowset with data, the method * <code>populate</code> sets the rowset's metadata and * then sends a <code>RowSetChangedEvent</code> object * to all registered listeners prior to returning. * * @param data the <code>ResultSet</code> object containing the data * to be read into this <code>CachedRowSetImpl</code> object * @throws SQLException if an error occurs; or the max row setting is * violated while populating the RowSet * @see #execute */ public void populate(ResultSet data) throws SQLException { int rowsFetched; Row currentRow; int numCols; int i; Map<String, Class<?>> map = getTypeMap(); Object obj; int mRows; if (data == null) { throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString()); } this.resultSet = data; // get the meta data for this ResultSet RSMD = data.getMetaData(); // set up the metadata RowSetMD = new RowSetMetaDataImpl(); initMetaData(RowSetMD, RSMD); // release the meta-data so that aren't tempted to use it. RSMD = null; numCols = RowSetMD.getColumnCount(); mRows = this.getMaxRows(); rowsFetched = 0; currentRow = null; while ( data.next()) { currentRow = new Row(numCols); if ( rowsFetched > mRows && mRows > 0) { rowsetWarning.setNextWarning(new RowSetWarning("Populating rows " + "setting has exceeded max row setting")); } for ( i = 1; i <= numCols; i++) { /* * check if the user has set a map. If no map * is set then use plain getObject. This lets * us work with drivers that do not support * getObject with a map in fairly sensible way */ if (map == null) { obj = data.getObject(i); } else { obj = data.getObject(i, map); } /* * the following block checks for the various * types that we have to serialize in order to * store - right now only structs have been tested */ if (obj instanceof Struct) { obj = new SerialStruct((Struct)obj, map); } else if (obj instanceof SQLData) { obj = new SerialStruct((SQLData)obj, map); } else if (obj instanceof Blob) { obj = new SerialBlob((Blob)obj); } else if (obj instanceof Clob) { obj = new SerialClob((Clob)obj); } else if (obj instanceof java.sql.Array) { if(map != null) obj = new SerialArray((java.sql.Array)obj, map); else obj = new SerialArray((java.sql.Array)obj); } ((Row)currentRow).initColumnObject(i, obj); } rowsFetched++; rvh.add(currentRow); } numRows = rowsFetched ; // Also rowsFetched should be equal to rvh.size() // notify any listeners that the rowset has changed notifyRowSetChanged(); } /** * Initializes the given <code>RowSetMetaData</code> object with the values * in the given <code>ResultSetMetaData</code> object. * * @param md the <code>RowSetMetaData</code> object for this * <code>CachedRowSetImpl</code> object, which will be set with * values from rsmd * @param rsmd the <code>ResultSetMetaData</code> object from which new * values for md will be read * @throws SQLException if an error occurs */ private void initMetaData(RowSetMetaDataImpl md, ResultSetMetaData rsmd) throws SQLException { int numCols = rsmd.getColumnCount(); md.setColumnCount(numCols); for (int col=1; col <= numCols; col++) { md.setAutoIncrement(col, rsmd.isAutoIncrement(col)); if(rsmd.isAutoIncrement(col)) updateOnInsert = true; md.setCaseSensitive(col, rsmd.isCaseSensitive(col)); md.setCurrency(col, rsmd.isCurrency(col)); md.setNullable(col, rsmd.isNullable(col)); md.setSigned(col, rsmd.isSigned(col)); md.setSearchable(col, rsmd.isSearchable(col)); /* * The PostgreSQL drivers sometimes return negative columnDisplaySize, * which causes an exception to be thrown. Check for it. */ int size = rsmd.getColumnDisplaySize(col); if (size < 0) { size = 0; } md.setColumnDisplaySize(col, size); md.setColumnLabel(col, rsmd.getColumnLabel(col)); md.setColumnName(col, rsmd.getColumnName(col)); md.setSchemaName(col, rsmd.getSchemaName(col)); /* * Drivers return some strange values for precision, for non-numeric data, including reports of * non-integer values; maybe we should check type, & set to 0 for non-numeric types. */ int precision = rsmd.getPrecision(col); if (precision < 0) { precision = 0; } md.setPrecision(col, precision); /* * It seems, from a bug report, that a driver can sometimes return a negative * value for scale. javax.sql.rowset.RowSetMetaDataImpl will throw an exception * if we attempt to set a negative value. As such, we'll check for this case. */ int scale = rsmd.getScale(col); if (scale < 0) { scale = 0; } md.setScale(col, scale); md.setTableName(col, rsmd.getTableName(col)); md.setCatalogName(col, rsmd.getCatalogName(col)); md.setColumnType(col, rsmd.getColumnType(col)); md.setColumnTypeName(col, rsmd.getColumnTypeName(col)); } if( conn != null){ // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods // must be implemented, therefore, the previous fix for 5055528 is being backed out dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy(); } } /** * Populates this <code>CachedRowSetImpl</code> object with data, * using the given connection to produce the result set from * which data will be read. A second form of this method, * which takes no arguments, uses the values from this rowset's * user, password, and either url or data source properties to * create a new database connection. The form of <code>execute</code> * that is given a connection ignores these properties. * * @param conn A standard JDBC <code>Connection</code> object that this * <code>CachedRowSet</code> object can pass to a synchronization provider * to establish a connection to the data source * @throws SQLException if an invalid <code>Connection</code> is supplied * or an error occurs in establishing the connection to the * data source * @see #populate * @see java.sql.Connection */ public void execute(Connection conn) throws SQLException { // store the connection so the reader can find it. setConnection(conn); if(getPageSize() != 0){ crsReader = (CachedRowSetReader)provider.getRowSetReader(); crsReader.setStartPosition(1); callWithCon = true; crsReader.readData((RowSetInternal)this); } // Now call the current reader's readData method else { rowSetReader.readData((RowSetInternal)this); } RowSetMD = (RowSetMetaDataImpl)this.getMetaData(); if(conn != null){ // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods // must be implemented, therefore, the previous fix for 5055528 is being backed out dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy(); } } /** * Sets this <code>CachedRowSetImpl</code> object's connection property * to the given <code>Connection</code> object. This method is called * internally by the version of the method <code>execute</code> that takes a * <code>Connection</code> object as an argument. The reader for this * <code>CachedRowSetImpl</code> object can retrieve the connection stored * in the rowset's connection property by calling its * <code>getConnection</code> method. * * @param connection the <code>Connection</code> object that was passed in * to the method <code>execute</code> and is to be stored * in this <code>CachedRowSetImpl</code> object's connection * property */ private void setConnection (Connection connection) { conn = connection; } /** * Propagates all row update, insert, and delete changes to the * underlying data source backing this <code>CachedRowSetImpl</code> * object. * <P> * <b>Note</b>In the reference implementation an optimistic concurrency implementation * is provided as a sample implementation of a the <code>SyncProvider</code> * abstract class. * <P> * This method fails if any of the updates cannot be propagated back * to the data source. When it fails, the caller can assume that * none of the updates are reflected in the data source. * When an exception is thrown, the current row * is set to the first "updated" row that resulted in an exception * unless the row that caused the exception is a "deleted" row. * In that case, when deleted rows are not shown, which is usually true, * the current row is not affected. * <P> * If no <code>SyncProvider</code> is configured, the reference implementation * leverages the <code>RIOptimisticProvider</code> available which provides the * default and reference synchronization capabilities for disconnected * <code>RowSets</code>. * * @throws SQLException if the cursor is on the insert row or the underlying * reference synchronization provider fails to commit the updates * to the datasource * @throws SyncProviderException if an internal error occurs within the * <code>SyncProvider</code> instance during either during the * process or at any time when the <code>SyncProvider</code> * instance touches the data source. * @see #acceptChanges(java.sql.Connection) * @see javax.sql.RowSetWriter * @see javax.sql.rowset.spi.SyncProvider */ public void acceptChanges() throws SyncProviderException { if (onInsertRow == true) { throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString()); } int saveCursorPos = cursorPos; boolean success = false; boolean conflict = false; try { if (rowSetWriter != null) { saveCursorPos = cursorPos; conflict = rowSetWriter.writeData((RowSetInternal)this); cursorPos = saveCursorPos; } if ((tXWriter) && this.COMMIT_ON_ACCEPT_CHANGES) { // do commit/rollback's here if (!conflict) { tWriter = (TransactionalWriter)rowSetWriter; tWriter.rollback(); success = false; } else { tWriter = (TransactionalWriter)rowSetWriter; if (tWriter instanceof CachedRowSetWriter) { ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert); } else { tWriter.commit(); } success = true; } } if (success == true) { setOriginal(); } else if (!(success) && !(this.COMMIT_ON_ACCEPT_CHANGES)) { throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.accfailed").toString()); } } catch (SyncProviderException spe) { throw spe; } catch (SQLException e) { e.printStackTrace(); throw new SyncProviderException(e.getMessage()); } catch (SecurityException e) { throw new SyncProviderException(e.getMessage()); } } /** * Propagates all row update, insert, and delete changes to the * data source backing this <code>CachedRowSetImpl</code> object * using the given <code>Connection</code> object. * <P> * The reference implementation <code>RIOptimisticProvider</code> * modifies its synchronization to a write back function given * the updated connection * The reference implementation modifies its synchronization behaviour * via the <code>SyncProvider</code> to ensure the synchronization * occurs according to the updated JDBC <code>Connection</code> * properties. * * @param con a standard JDBC <code>Connection</code> object * @throws SQLException if the cursor is on the insert row or the underlying * synchronization provider fails to commit the updates * back to the data source * @see #acceptChanges * @see javax.sql.RowSetWriter * @see javax.sql.rowset.spi.SyncFactory * @see javax.sql.rowset.spi.SyncProvider */ public void acceptChanges(Connection con) throws SyncProviderException{ setConnection(con); acceptChanges(); } /** * Restores this <code>CachedRowSetImpl</code> object to its original state, * that is, its state before the last set of changes. * <P> * Before returning, this method moves the cursor before the first row * and sends a <code>rowSetChanged</code> event to all registered * listeners. * @throws SQLException if an error is occurs rolling back the RowSet * state to the definied original value. * @see javax.sql.RowSetListener#rowSetChanged */ public void restoreOriginal() throws SQLException { Row currentRow; for (Iterator i = rvh.iterator(); i.hasNext();) { currentRow = (Row)i.next(); if (currentRow.getInserted() == true) { i.remove(); --numRows; } else { if (currentRow.getDeleted() == true) { currentRow.clearDeleted(); } if (currentRow.getUpdated() == true) { currentRow.clearUpdated(); } } } // move to before the first cursorPos = 0; // notify any listeners notifyRowSetChanged(); } /** * Releases the current contents of this <code>CachedRowSetImpl</code> * object and sends a <code>rowSetChanged</code> event object to all * registered listeners. * * @throws SQLException if an error occurs flushing the contents of * RowSet. * @see javax.sql.RowSetListener#rowSetChanged */ public void release() throws SQLException { initContainer(); notifyRowSetChanged(); } /** * Cancels deletion of the current row and notifies listeners that * a row has changed. * <P> * Note: This method can be ignored if deleted rows are not being shown, * which is the normal case.Lines 501–1000 of 10133. Previous lines Load more
if(resBundle == null) { try { resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); } catch(IOException ioe) { throw new RuntimeException(ioe); } } setShowDeleted(false); setQueryTimeout(0); setMaxRows(0); setMaxFieldSize(0); setType(ResultSet.TYPE_SCROLL_INSENSITIVE); setConcurrency(ResultSet.CONCUR_UPDATABLE); if((rvh.size() > 0) && (isReadOnly() == false)) setReadOnly(false); else setReadOnly(true); setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); setEscapeProcessing(true); //setTypeMap(null); checkTransactionalWriter(); //Instantiating the vector for MatchColumns iMatchColumns = new Vector<Integer>(10); for(int i = 0; i < 10 ; i++) { iMatchColumns.add(i,Integer.valueOf(-1)); } strMatchColumns = new Vector<String>(10); for(int j = 0; j < 10; j++) { strMatchColumns.add(j,null); } } /** * Determine whether the SyncProvider's writer implements the * <code>TransactionalWriter<code> interface */ private void checkTransactionalWriter() { if (rowSetWriter != null) { Class c = rowSetWriter.getClass(); if (c != null) { Class[] theInterfaces = c.getInterfaces(); for (int i = 0; i < theInterfaces.length; i++) { if ((theInterfaces[i].getName()).indexOf("TransactionalWriter") > 0) { tXWriter = true; establishTransactionalWriter(); } } } } } /** * Sets an private field to all transaction bounddaries to be set */ private void establishTransactionalWriter() { tWriter = (TransactionalWriter)provider.getRowSetWriter(); } //----------------------------------------------------------------------- // Properties //----------------------------------------------------------------------- /** * Sets this <code>CachedRowSetImpl</code> object's command property * to the given <code>String</code> object and clears the parameters, * if any, that were set for the previous command. * <P> * The command property may not be needed * if the rowset is produced by a data source, such as a spreadsheet, * that does not support commands. Thus, this property is optional * and may be <code>null</code>. * * @param cmd a <code>String</code> object containing an SQL query * that will be set as the command; may be <code>null</code> * @throws SQLException if an error occurs */ public void setCommand(String cmd) throws SQLException { super.setCommand(cmd); if(!buildTableName(cmd).equals("")) { this.setTableName(buildTableName(cmd)); } } //--------------------------------------------------------------------- // Reading and writing data //--------------------------------------------------------------------- /** * Populates this <code>CachedRowSetImpl</code> object with data from * the given <code>ResultSet</code> object. This * method is an alternative to the method <code>execute</code> * for filling the rowset with data. The method <code>populate</code> * does not require that the properties needed by the method * <code>execute</code>, such as the <code>command</code> property, * be set. This is true because the method <code>populate</code> * is given the <code>ResultSet</code> object from * which to get data and thus does not need to use the properties * required for setting up a connection and executing this * <code>CachedRowSetImpl</code> object's command. * <P> * After populating this rowset with data, the method * <code>populate</code> sets the rowset's metadata and * then sends a <code>RowSetChangedEvent</code> object * to all registered listeners prior to returning. * * @param data the <code>ResultSet</code> object containing the data * to be read into this <code>CachedRowSetImpl</code> object * @throws SQLException if an error occurs; or the max row setting is * violated while populating the RowSet * @see #execute */ public void populate(ResultSet data) throws SQLException { int rowsFetched; Row currentRow; int numCols; int i; Map<String, Class<?>> map = getTypeMap(); Object obj; int mRows; if (data == null) { throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString()); } this.resultSet = data; // get the meta data for this ResultSet RSMD = data.getMetaData(); // set up the metadata RowSetMD = new RowSetMetaDataImpl(); initMetaData(RowSetMD, RSMD); // release the meta-data so that aren't tempted to use it. RSMD = null; numCols = RowSetMD.getColumnCount(); mRows = this.getMaxRows(); rowsFetched = 0; currentRow = null; while ( data.next()) { currentRow = new Row(numCols); if ( rowsFetched > mRows && mRows > 0) { rowsetWarning.setNextWarning(new RowSetWarning("Populating rows " + "setting has exceeded max row setting")); } for ( i = 1; i <= numCols; i++) { /* * check if the user has set a map. If no map * is set then use plain getObject. This lets * us work with drivers that do not support * getObject with a map in fairly sensible way */ if (map == null) { obj = data.getObject(i); } else { obj = data.getObject(i, map); } /* * the following block checks for the various * types that we have to serialize in order to * store - right now only structs have been tested */ if (obj instanceof Struct) { obj = new SerialStruct((Struct)obj, map); } else if (obj instanceof SQLData) { obj = new SerialStruct((SQLData)obj, map); } else if (obj instanceof Blob) { obj = new SerialBlob((Blob)obj); } else if (obj instanceof Clob) { obj = new SerialClob((Clob)obj); } else if (obj instanceof java.sql.Array) { if(map != null) obj = new SerialArray((java.sql.Array)obj, map); else obj = new SerialArray((java.sql.Array)obj); } ((Row)currentRow).initColumnObject(i, obj); } rowsFetched++; rvh.add(currentRow); } numRows = rowsFetched ; // Also rowsFetched should be equal to rvh.size() // notify any listeners that the rowset has changed notifyRowSetChanged(); } /** * Initializes the given <code>RowSetMetaData</code> object with the values * in the given <code>ResultSetMetaData</code> object. * * @param md the <code>RowSetMetaData</code> object for this * <code>CachedRowSetImpl</code> object, which will be set with * values from rsmd * @param rsmd the <code>ResultSetMetaData</code> object from which new * values for md will be read * @throws SQLException if an error occurs */ private void initMetaData(RowSetMetaDataImpl md, ResultSetMetaData rsmd) throws SQLException { int numCols = rsmd.getColumnCount(); md.setColumnCount(numCols); for (int col=1; col <= numCols; col++) { md.setAutoIncrement(col, rsmd.isAutoIncrement(col)); if(rsmd.isAutoIncrement(col)) updateOnInsert = true; md.setCaseSensitive(col, rsmd.isCaseSensitive(col)); md.setCurrency(col, rsmd.isCurrency(col)); md.setNullable(col, rsmd.isNullable(col)); md.setSigned(col, rsmd.isSigned(col)); md.setSearchable(col, rsmd.isSearchable(col)); /* * The PostgreSQL drivers sometimes return negative columnDisplaySize, * which causes an exception to be thrown. Check for it. */ int size = rsmd.getColumnDisplaySize(col); if (size < 0) { size = 0; } md.setColumnDisplaySize(col, size); md.setColumnLabel(col, rsmd.getColumnLabel(col)); md.setColumnName(col, rsmd.getColumnName(col)); md.setSchemaName(col, rsmd.getSchemaName(col)); /* * Drivers return some strange values for precision, for non-numeric data, including reports of * non-integer values; maybe we should check type, & set to 0 for non-numeric types. */ int precision = rsmd.getPrecision(col); if (precision < 0) { precision = 0; } md.setPrecision(col, precision); /* * It seems, from a bug report, that a driver can sometimes return a negative * value for scale. javax.sql.rowset.RowSetMetaDataImpl will throw an exception * if we attempt to set a negative value. As such, we'll check for this case. */ int scale = rsmd.getScale(col); if (scale < 0) { scale = 0; } md.setScale(col, scale); md.setTableName(col, rsmd.getTableName(col)); md.setCatalogName(col, rsmd.getCatalogName(col)); md.setColumnType(col, rsmd.getColumnType(col)); md.setColumnTypeName(col, rsmd.getColumnTypeName(col)); } if( conn != null){ // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods // must be implemented, therefore, the previous fix for 5055528 is being backed out dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy(); } } /** * Populates this <code>CachedRowSetImpl</code> object with data, * using the given connection to produce the result set from * which data will be read. A second form of this method, * which takes no arguments, uses the values from this rowset's * user, password, and either url or data source properties to * create a new database connection. The form of <code>execute</code> * that is given a connection ignores these properties. * * @param conn A standard JDBC <code>Connection</code> object that this * <code>CachedRowSet</code> object can pass to a synchronization provider * to establish a connection to the data source * @throws SQLException if an invalid <code>Connection</code> is supplied * or an error occurs in establishing the connection to the * data source * @see #populate * @see java.sql.Connection */ public void execute(Connection conn) throws SQLException { // store the connection so the reader can find it. setConnection(conn); if(getPageSize() != 0){ crsReader = (CachedRowSetReader)provider.getRowSetReader(); crsReader.setStartPosition(1); callWithCon = true; crsReader.readData((RowSetInternal)this); } // Now call the current reader's readData method else { rowSetReader.readData((RowSetInternal)this); } RowSetMD = (RowSetMetaDataImpl)this.getMetaData(); if(conn != null){ // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods // must be implemented, therefore, the previous fix for 5055528 is being backed out dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy(); } } /** * Sets this <code>CachedRowSetImpl</code> object's connection property * to the given <code>Connection</code> object. This method is called * internally by the version of the method <code>execute</code> that takes a * <code>Connection</code> object as an argument. The reader for this * <code>CachedRowSetImpl</code> object can retrieve the connection stored * in the rowset's connection property by calling its * <code>getConnection</code> method. * * @param connection the <code>Connection</code> object that was passed in * to the method <code>execute</code> and is to be stored * in this <code>CachedRowSetImpl</code> object's connection * property */ private void setConnection (Connection connection) { conn = connection; } /** * Propagates all row update, insert, and delete changes to the * underlying data source backing this <code>CachedRowSetImpl</code> * object. * <P> * <b>Note</b>In the reference implementation an optimistic concurrency implementation * is provided as a sample implementation of a the <code>SyncProvider</code> * abstract class. * <P> * This method fails if any of the updates cannot be propagated back * to the data source. When it fails, the caller can assume that * none of the updates are reflected in the data source. * When an exception is thrown, the current row * is set to the first "updated" row that resulted in an exception * unless the row that caused the exception is a "deleted" row. * In that case, when deleted rows are not shown, which is usually true, * the current row is not affected. * <P> * If no <code>SyncProvider</code> is configured, the reference implementation * leverages the <code>RIOptimisticProvider</code> available which provides the * default and reference synchronization capabilities for disconnected * <code>RowSets</code>. * * @throws SQLException if the cursor is on the insert row or the underlying * reference synchronization provider fails to commit the updates * to the datasource * @throws SyncProviderException if an internal error occurs within the * <code>SyncProvider</code> instance during either during the * process or at any time when the <code>SyncProvider</code> * instance touches the data source. * @see #acceptChanges(java.sql.Connection) * @see javax.sql.RowSetWriter * @see javax.sql.rowset.spi.SyncProvider */ public void acceptChanges() throws SyncProviderException { if (onInsertRow == true) { throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString()); } int saveCursorPos = cursorPos; boolean success = false; boolean conflict = false; try { if (rowSetWriter != null) { saveCursorPos = cursorPos; conflict = rowSetWriter.writeData((RowSetInternal)this); cursorPos = saveCursorPos; } if ((tXWriter) && this.COMMIT_ON_ACCEPT_CHANGES) { // do commit/rollback's here if (!conflict) { tWriter = (TransactionalWriter)rowSetWriter; tWriter.rollback(); success = false; } else { tWriter = (TransactionalWriter)rowSetWriter; if (tWriter instanceof CachedRowSetWriter) { ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert); } else { tWriter.commit(); } success = true; } } if (success == true) { setOriginal(); } else if (!(success) && !(this.COMMIT_ON_ACCEPT_CHANGES)) { throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.accfailed").toString()); } } catch (SyncProviderException spe) { throw spe; } catch (SQLException e) { e.printStackTrace(); throw new SyncProviderException(e.getMessage()); } catch (SecurityException e) { throw new SyncProviderException(e.getMessage()); } } /** * Propagates all row update, insert, and delete changes to the * data source backing this <code>CachedRowSetImpl</code> object * using the given <code>Connection</code> object. * <P> * The reference implementation <code>RIOptimisticProvider</code> * modifies its synchronization to a write back function given * the updated connection * The reference implementation modifies its synchronization behaviour * via the <code>SyncProvider</code> to ensure the synchronization * occurs according to the updated JDBC <code>Connection</code> * properties. * * @param con a standard JDBC <code>Connection</code> object * @throws SQLException if the cursor is on the insert row or the underlying * synchronization provider fails to commit the updates * back to the data source * @see #acceptChanges * @see javax.sql.RowSetWriter * @see javax.sql.rowset.spi.SyncFactory * @see javax.sql.rowset.spi.SyncProvider */ public void acceptChanges(Connection con) throws SyncProviderException{ setConnection(con); acceptChanges(); } /** * Restores this <code>CachedRowSetImpl</code> object to its original state, * that is, its state before the last set of changes. * <P> * Before returning, this method moves the cursor before the first row * and sends a <code>rowSetChanged</code> event to all registered * listeners. * @throws SQLException if an error is occurs rolling back the RowSet * state to the definied original value. * @see javax.sql.RowSetListener#rowSetChanged */ public void restoreOriginal() throws SQLException { Row currentRow; for (Iterator i = rvh.iterator(); i.hasNext();) { currentRow = (Row)i.next(); if (currentRow.getInserted() == true) { i.remove(); --numRows; } else { if (currentRow.getDeleted() == true) { currentRow.clearDeleted(); } if (currentRow.getUpdated() == true) { currentRow.clearUpdated(); } } } // move to before the first cursorPos = 0; // notify any listeners notifyRowSetChanged(); } /** * Releases the current contents of this <code>CachedRowSetImpl</code> * object and sends a <code>rowSetChanged</code> event object to all * registered listeners. * * @throws SQLException if an error occurs flushing the contents of * RowSet. * @see javax.sql.RowSetListener#rowSetChanged */ public void release() throws SQLException { initContainer(); notifyRowSetChanged(); } /** * Cancels deletion of the current row and notifies listeners that * a row has changed. * <P> * Note: This method can be ignored if deleted rows are not being shown, * which is the normal case.