10133 lines · 431.3 KB · Java
RawDownload
         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