undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,157 @@
/*
* Copyright (c) 2005, 2022, 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 com.sun.rowset;
import java.io.*;
import java.util.*;
/**
* This class is used to help in localization of resources,
* especially the exception strings.
*
* @author Amit Handa
*/
public class JdbcRowSetResourceBundle implements Serializable {
/**
* This <code>String</code> variable stores the location
* of the resource bundle location.
*/
private static String fileName;
/**
* This variable will hold the <code>PropertyResourceBundle</code>
* of the text to be internationalized.
*/
private transient PropertyResourceBundle propResBundle;
/**
* The constructor initializes to this object
*
*/
private static volatile JdbcRowSetResourceBundle jpResBundle;
/**
* The variable which will represent the properties
* the suffix or extension of the resource bundle.
**/
private static final String PROPERTIES = "properties";
/**
* The variable to represent underscore
**/
private static final String UNDERSCORE = "_";
/**
* The variable which will represent dot
**/
private static final String DOT = ".";
/**
* The variable which will represent the slash.
**/
private static final String SLASH = "/";
/**
* The variable where the default resource bundle will
* be placed.
**/
private static final String PATH = "com.sun.rowset.RowSetResourceBundle";
/**
* The constructor which initializes the resource bundle.
* Note this is a private constructor and follows Singleton
* Design Pattern.
*
* @throws IOException if unable to load the ResourceBundle
* according to locale or the default one.
*/
private JdbcRowSetResourceBundle () throws IOException {
// Try to load the resource bundle according
// to the locale. Else if no bundle found according
// to the locale load the default.
// In default case the default locale resource bundle
// should always be loaded else it
// will be difficult to throw appropriate
// exception string messages.
Locale locale = Locale.getDefault();
// Load appropriate bundle according to locale
propResBundle = (PropertyResourceBundle) ResourceBundle.getBundle(PATH,
locale, JdbcRowSetResourceBundle.class.getModule());
}
/**
* This method is used to get a handle to the
* initialized instance of this class. Note that
* at any time there is only one instance of this
* class initialized which will be returned.
*
* @throws IOException if unable to find the RowSetResourceBundle.properties
*/
public static JdbcRowSetResourceBundle getJdbcRowSetResourceBundle()
throws IOException {
if(jpResBundle == null){
synchronized(JdbcRowSetResourceBundle.class) {
if(jpResBundle == null){
jpResBundle = new JdbcRowSetResourceBundle();
} //end if
} //end synchronized block
} //end if
return jpResBundle;
}
/**
* This method returns an enumerated handle of the keys
* which correspond to values translated to various locales.
*
* @return an enumeration of keys which have messages translated to
* corresponding locales.
*/
@SuppressWarnings("rawtypes")
public Enumeration getKeys() {
return propResBundle.getKeys();
}
/**
* This method takes the key as an argument and
* returns the corresponding value reading it
* from the Resource Bundle loaded earlier.
*
* @return value in locale specific language
* according to the key passed.
*/
public Object handleGetObject(String key) {
return propResBundle.handleGetObject(key);
}
static final long serialVersionUID = 436199386225359954L;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2010, 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 com.sun.rowset;
import java.sql.SQLException;
import javax.sql.rowset.CachedRowSet;
import javax.sql.rowset.FilteredRowSet;
import javax.sql.rowset.JdbcRowSet;
import javax.sql.rowset.JoinRowSet;
import javax.sql.rowset.WebRowSet;
import javax.sql.rowset.RowSetFactory;
/**
* This is the implementation specific class for the
* <code>javax.sql.rowset.spi.RowSetFactory</code>. This is the platform
* default implementation for the Java SE platform.
*
* @author Lance Andersen
*
*
* @version 1.7
*/
public final class RowSetFactoryImpl implements RowSetFactory {
public CachedRowSet createCachedRowSet() throws SQLException {
return new com.sun.rowset.CachedRowSetImpl();
}
public FilteredRowSet createFilteredRowSet() throws SQLException {
return new com.sun.rowset.FilteredRowSetImpl();
}
public JdbcRowSet createJdbcRowSet() throws SQLException {
return new com.sun.rowset.JdbcRowSetImpl();
}
public JoinRowSet createJoinRowSet() throws SQLException {
return new com.sun.rowset.JoinRowSetImpl();
}
public WebRowSet createWebRowSet() throws SQLException {
return new com.sun.rowset.WebRowSetImpl();
}
}

View file

@ -0,0 +1,169 @@
#
# Copyright (c) 2005, 2024, 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.
#
# CacheRowSetImpl exceptions
cachedrowsetimpl.populate = Invalid ResultSet object supplied to populate method
cachedrowsetimpl.invalidp = Invalid persistence provider generated
cachedrowsetimpl.nullhash = Cannot instantiate CachedRowSetImpl instance. Null Hashtable supplied to constructor
cachedrowsetimpl.invalidop = Invalid operation while on insert row
cachedrowsetimpl.accfailed = acceptChanges Failed
cachedrowsetimpl.invalidcp = Invalid cursor position
cachedrowsetimpl.illegalop = Illegal operation on non-inserted row
cachedrowsetimpl.clonefail = Clone failed: {0}
cachedrowsetimpl.invalidcol = Invalid column index
cachedrowsetimpl.invalcolnm = Invalid column name
cachedrowsetimpl.boolfail = getBoolen Failed on value ( {0} ) in column {1}
cachedrowsetimpl.bytefail = getByte Failed on value ( {0} ) in column {1}
cachedrowsetimpl.shortfail = getShort Failed on value ( {0} ) in column {1}
cachedrowsetimpl.intfail = getInt Failed on value ( {0} ) in column {1}
cachedrowsetimpl.longfail = getLong Failed on value ( {0} ) in column {1}
cachedrowsetimpl.floatfail = getFloat failed on value ( {0} ) in column {1}
cachedrowsetimpl.doublefail = getDouble failed on value ( {0} ) in column {1}
cachedrowsetimpl.dtypemismt = Data Type Mismatch
cachedrowsetimpl.datefail = getDate Failed on value ( {0} ) in column {1} no conversion available
cachedrowsetimpl.timefail = getTime failed on value ( {0} ) in column {1} no conversion available
cachedrowsetimpl.posupdate = Positioned updates not supported
cachedrowsetimpl.unableins = Unable to instantiate : {0}
cachedrowsetimpl.beforefirst = beforeFirst : Invalid cursor operation
cachedrowsetimpl.first = First : Invalid cursor operation
cachedrowsetimpl.last = last : TYPE_FORWARD_ONLY
cachedrowsetimpl.absolute = absolute : Invalid cursor position
cachedrowsetimpl.relative = relative : Invalid cursor position
cachedrowsetimpl.asciistream = read failed for ascii stream
cachedrowsetimpl.binstream = read failed on binary stream
cachedrowsetimpl.failedins = Failed on insert row
cachedrowsetimpl.updateins = updateRow called while on insert row
cachedrowsetimpl.movetoins = moveToInsertRow : CONCUR_READ_ONLY
cachedrowsetimpl.movetoins1 = moveToInsertRow : no meta data
cachedrowsetimpl.movetoins2 = moveToInsertRow : invalid number of columns
cachedrowsetimpl.tablename = Table name cannot be null
cachedrowsetimpl.keycols = Invalid key columns
cachedrowsetimpl.opnotsupp = Operation not supported by Database
cachedrowsetimpl.matchcols = Match columns are not the same as those set
cachedrowsetimpl.setmatchcols = Set Match columns before getting them
cachedrowsetimpl.matchcols1 = Match columns should be greater than 0
cachedrowsetimpl.matchcols2 = Match columns should be empty or null string
cachedrowsetimpl.unsetmatch = Columns being unset are not the same as set
cachedrowsetimpl.unsetmatch1 = Use column name as argument to unsetMatchColumn
cachedrowsetimpl.unsetmatch2 = Use column ID as argument to unsetMatchColumn
cachedrowsetimpl.numrows = Number of rows is less than zero or less than fetch size
cachedrowsetimpl.startpos = Start position cannot be negative
cachedrowsetimpl.nextpage = Populate data before calling
cachedrowsetimpl.pagesize = Page size cannot be less than zero
cachedrowsetimpl.pagesize1 = Page size cannot be greater than maxRows
cachedrowsetimpl.fwdonly = ResultSet is forward only
cachedrowsetimpl.type = Type is : {0}
cachedrowsetimpl.opnotysupp = Operation not yet supported
cachedrowsetimpl.featnotsupp = Feature not supported
# WebRowSetImpl exceptions
webrowsetimpl.nullhash = Cannot instantiate WebRowSetImpl instance. Null Hashtable supplied to constructor
webrowsetimpl.invalidwr = Invalid writer
webrowsetimpl.invalidrd = Invalid reader
#FilteredRowSetImpl exceptions
filteredrowsetimpl.relative = relative : Invalid cursor operation
filteredrowsetimpl.absolute = absolute : Invalid cursor operation
filteredrowsetimpl.notallowed = This value is not allowed through the filter
#JoinRowSetImpl exceptions
joinrowsetimpl.notinstance = Not an instance of rowset
joinrowsetimpl.matchnotset = Match Column not set for join
joinrowsetimpl.numnotequal = Number of elements in rowset not equal to match column
joinrowsetimpl.notdefined = This is not a defined type of join
joinrowsetimpl.notsupported = This type of join is not supported
joinrowsetimpl.initerror = JoinRowSet initialization error
joinrowsetimpl.genericerr = Generic joinrowset initial error
joinrowsetimpl.emptyrowset = Empty rowset cannot be added to this JoinRowSet
#JdbcRowSetImpl exceptions
jdbcrowsetimpl.invalstate = Invalid state
jdbcrowsetimpl.connect = JdbcRowSet (connect) JNDI unable to connect
jdbcrowsetimpl.paramtype = Unable to deduce param type
jdbcrowsetimpl.matchcols = Match Columns are not the same as those set
jdbcrowsetimpl.setmatchcols = Set the match columns before getting them
jdbcrowsetimpl.matchcols1 = Match columns should be greater than 0
jdbcrowsetimpl.matchcols2 = Match columns cannot be null or empty string
jdbcrowsetimpl.unsetmatch = Columns being unset are not the same as those set
jdbcrowsetimpl.usecolname = Use column name as argument to unsetMatchColumn
jdbcrowsetimpl.usecolid = Use column ID as argument to unsetMatchColumn
jdbcrowsetimpl.resnotupd = ResultSet is not updatable
jdbcrowsetimpl.opnotysupp = Operation not yet supported
jdbcrowsetimpl.featnotsupp = Feature not supported
#CachedRowSetReader exceptions
crsreader.connect = (JNDI) Unable to connect
crsreader.paramtype = Unable to deduce param type
crsreader.connecterr = Internal Error in RowSetReader: no connection or command
crsreader.datedetected = Detected a Date
crsreader.caldetected = Detected a Calendar
#CachedRowSetWriter exceptions
crswriter.connect = Unable to get connection
crswriter.tname = writeData cannot determine table name
crswriter.params1 = Value of params1 : {0}
crswriter.params2 = Value of params2 : {0}
crswriter.conflictsno = conflicts while synchronizing
#InsertRow exceptions
insertrow.novalue = No value has been inserted
#SyncResolverImpl exceptions
syncrsimpl.indexval = Index value out of range
syncrsimpl.noconflict = This column not in conflict
syncrsimpl.syncnotpos = Synchronization is not possible
syncrsimpl.valtores = Value to be resolved can either be in the database or in cachedrowset
#WebRowSetXmlReader exception
wrsxmlreader.invalidcp = End of RowSet reached. Invalid cursor position
wrsxmlreader.readxml = readXML : {0}
wrsxmlreader.parseerr = ** Parsing Error : {0} , line : {1} , uri : {2}
#WebRowSetXmlWriter exceptions
wrsxmlwriter.ioex = IOException : {0}
wrsxmlwriter.sqlex = SQLException : {0}
wrsxmlwriter.failedwrite = Failed to write value
wsrxmlwriter.notproper = Not a proper type
#XmlReaderContentHandler exceptions
xmlrch.errmap = Error setting Map : {0}
xmlrch.errmetadata = Error setting metadata : {0}
xmlrch.errinsertval = Error inserting values : {0}
xmlrch.errconstr = Error constructing row : {0}
xmlrch.errdel = Error deleting row : {0}
xmlrch.errinsert = Error constructing insert row : {0}
xmlrch.errinsdel = Error constructing insdel row : {0}
xmlrch.errupdate = Error constructing update row : {0}
xmlrch.errupdrow = Error updating row : {0}
xmlrch.chars = characters :
xmlrch.badvalue = Bad value ; non-nullable property
xmlrch.badvalue1 = Bad value ; non-nullable metadata
xmlrch.warning = ** Warning : {0} , line : {1} , uri : {2}
#RIOptimisticProvider Exceptions
riop.locking = Locking classification is not supported
#RIXMLProvider exceptions
rixml.unsupp = Unsupported with RIXMLProvider

View file

@ -0,0 +1,169 @@
#
# Copyright (c) 2005, 2024, 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.
#
# CacheRowSetImpl exceptions
cachedrowsetimpl.populate = Ungültiges ResultSet-Objekt zum Auffüllen der Methode angegeben
cachedrowsetimpl.invalidp = Ungültiger Persistence-Provider generiert
cachedrowsetimpl.nullhash = CachedRowSetImpl-Instanz kann nicht instanziiert werden. Null-Hashtabelle für Constructor angegeben
cachedrowsetimpl.invalidop = Ungültiger Vorgang beim Zeileneinfügen
cachedrowsetimpl.accfailed = acceptChanges nicht erfolgreich
cachedrowsetimpl.invalidcp = Ungültige Cursorposition
cachedrowsetimpl.illegalop = Unzulässiger Vorgang bei nicht eingefügter Zeile
cachedrowsetimpl.clonefail = Klonen nicht erfolgreich: {0}
cachedrowsetimpl.invalidcol = Ungültiger Spaltenindex
cachedrowsetimpl.invalcolnm = Ungültiger Spaltenname
cachedrowsetimpl.boolfail = getBoolen bei Wert ( {0} ) in Spalte {1} nicht erfolgreich
cachedrowsetimpl.bytefail = getByte bei Wert ( {0} ) in Spalte {1} nicht erfolgreich
cachedrowsetimpl.shortfail = getShort bei Wert ( {0} ) in Spalte {1} nicht erfolgreich
cachedrowsetimpl.intfail = getInt bei Wert ( {0} ) in Spalte {1} nicht erfolgreich
cachedrowsetimpl.longfail = getLong bei Wert ( {0} ) in Spalte {1} nicht erfolgreich
cachedrowsetimpl.floatfail = getFloat bei Wert ( {0} ) in Spalte {1} nicht erfolgreich
cachedrowsetimpl.doublefail = getDouble bei Wert ( {0} ) in Spalte {1} nicht erfolgreich
cachedrowsetimpl.dtypemismt = Keine Datentypübereinstimmung
cachedrowsetimpl.datefail = getDate bei Wert ( {0} ) in Spalte {1} nicht erfolgreich. Keine Konvertierung möglich
cachedrowsetimpl.timefail = getTime bei Wert ( {0} ) in Spalte {1} nicht erfolgreich. Keine Konvertierung möglich
cachedrowsetimpl.posupdate = Positionierte Updates werden nicht unterstützt
cachedrowsetimpl.unableins = Keine Instanziierung möglich: {0}
cachedrowsetimpl.beforefirst = beforeFirst: Ungültiger Cursorvorgang
cachedrowsetimpl.first = First: Ungültiger Cursorvorgang
cachedrowsetimpl.last = last: TYPE_FORWARD_ONLY
cachedrowsetimpl.absolute = absolute: Ungültige Cursorposition
cachedrowsetimpl.relative = relative: Ungültige Cursorposition
cachedrowsetimpl.asciistream = Lesen von ASCII-Stream nicht erfolgreich
cachedrowsetimpl.binstream = Lesen von Binär-Stream nicht erfolgreich
cachedrowsetimpl.failedins = Fehler beim Zeileneinfügen
cachedrowsetimpl.updateins = updateRow beim Zeileneinfügen aufgerufen
cachedrowsetimpl.movetoins = moveToInsertRow: CONCUR_READ_ONLY
cachedrowsetimpl.movetoins1 = moveToInsertRow: keine Metadaten
cachedrowsetimpl.movetoins2 = moveToInsertRow: ungültige Spaltenanzahl
cachedrowsetimpl.tablename = Tabellenname darf nicht null sein
cachedrowsetimpl.keycols = Ungültige Schlüsselspalten
cachedrowsetimpl.opnotsupp = Vorgang nicht von Datenbank unterstützt
cachedrowsetimpl.matchcols = Übereinstimmungsspalten entsprechen nicht den festgelegten Spalten
cachedrowsetimpl.setmatchcols = Übereinstimmungsspalten müssen vor dem Abrufen festgelegt werden
cachedrowsetimpl.matchcols1 = Wert für Übereinstimmungsspalten muss größer als 0 sein
cachedrowsetimpl.matchcols2 = Übereinstimmungsspalten müssen leer sein oder eine Nullzeichenfolge aufweisen
cachedrowsetimpl.unsetmatch = Spalten, deren Wert aufgehoben wird, entsprechen nicht den festgelegten Spalten
cachedrowsetimpl.unsetmatch1 = Spaltenname als Argument für unsetMatchColumn verwenden
cachedrowsetimpl.unsetmatch2 = Spalten-ID als Argument für unsetMatchColumn verwenden
cachedrowsetimpl.numrows = Zeilenanzahl ist kleiner als null oder kleiner als Abrufgröße
cachedrowsetimpl.startpos = Startposition darf keinen Negativwert aufweisen
cachedrowsetimpl.nextpage = Daten müssen vor dem Aufruf ausgefüllt werden
cachedrowsetimpl.pagesize = Seitengröße darf nicht kleiner als null sein
cachedrowsetimpl.pagesize1 = Seitengröße darf nicht größer als maxRows sein
cachedrowsetimpl.fwdonly = ResultSet kann nur vorwärts gerichtet sein
cachedrowsetimpl.type = Typ ist: {0}
cachedrowsetimpl.opnotysupp = Vorgang noch nicht unterstützt
cachedrowsetimpl.featnotsupp = Feature nicht unterstützt
# WebRowSetImpl exceptions
webrowsetimpl.nullhash = WebRowSetImpl-Instanz kann nicht instanziiert werden. Null-Hashtabelle für Constructor angegeben
webrowsetimpl.invalidwr = Ungültiger Writer
webrowsetimpl.invalidrd = Ungültiger Reader
#FilteredRowSetImpl exceptions
filteredrowsetimpl.relative = relative: Ungültiger Cursorvorgang
filteredrowsetimpl.absolute = absolute: Ungültiger Cursorvorgang
filteredrowsetimpl.notallowed = Kein zulässiger Wert im Filter
#JoinRowSetImpl exceptions
joinrowsetimpl.notinstance = Keine Instanz von rowset
joinrowsetimpl.matchnotset = Übereinstimmungsspalte wurde nicht für Join festgelegt
joinrowsetimpl.numnotequal = Elementanzahl in rowset nicht gleich Übereinstimmungsspalte
joinrowsetimpl.notdefined = Kein definierter Join-Typ
joinrowsetimpl.notsupported = Join-Typ wird nicht unterstützt
joinrowsetimpl.initerror = JoinRowSet-Initialisierungsfehler
joinrowsetimpl.genericerr = Generischer JoinRowSet-Initialisierungsfehler
joinrowsetimpl.emptyrowset = Leeres rowset kann nicht zu diesem JoinRowSet hinzugefügt werden
#JdbcRowSetImpl exceptions
jdbcrowsetimpl.invalstate = Ungültiger Status
jdbcrowsetimpl.connect = JdbcRowSet (verbinden), keine JNDI-Verbindung möglich
jdbcrowsetimpl.paramtype = Parametertyp kann nicht abgeleitet werden
jdbcrowsetimpl.matchcols = Übereinstimmungsspalten entsprechen nicht den festgelegten Spalten
jdbcrowsetimpl.setmatchcols = Übereinstimmungsspalten müssen vor dem Abrufen festgelegt werden
jdbcrowsetimpl.matchcols1 = Wert für Übereinstimmungsspalten muss größer als 0 sein
jdbcrowsetimpl.matchcols2 = Übereinstimmungsspalten können keine Null- oder leere Zeichenfolge aufweisen
jdbcrowsetimpl.unsetmatch = Spalten, deren Wert aufgehoben wird, entsprechen nicht den festgelegten Spalten
jdbcrowsetimpl.usecolname = Spaltenname als Argument für unsetMatchColumn verwenden
jdbcrowsetimpl.usecolid = Spalten-ID als Argument für unsetMatchColumn verwenden
jdbcrowsetimpl.resnotupd = ResultSet kann nicht aktualisiert werden
jdbcrowsetimpl.opnotysupp = Vorgang noch nicht unterstützt
jdbcrowsetimpl.featnotsupp = Feature nicht unterstützt
#CachedRowSetReader exceptions
crsreader.connect = (JNDI) Verbindung nicht möglich
crsreader.paramtype = Parametertyp kann nicht abgeleitet werden
crsreader.connecterr = Interner Fehler in RowSetReader: Keine Verbindung oder kein Befehl
crsreader.datedetected = Datum festgestellt
crsreader.caldetected = Kalender festgestellt
#CachedRowSetWriter exceptions
crswriter.connect = Verbindung kann nicht hergestellt werden
crswriter.tname = writeData kann Tabellennamen nicht bestimmen
crswriter.params1 = Wert für params1: {0}
crswriter.params2 = Wert für params2: {0}
crswriter.conflictsno = Konflikte beim Synchronisieren
#InsertRow exceptions
insertrow.novalue = Es wurde kein Wert eingefügt
#SyncResolverImpl exceptions
syncrsimpl.indexval = Indexwert liegt außerhalb des Bereichs
syncrsimpl.noconflict = Kein Konflikt bei dieser Spalte
syncrsimpl.syncnotpos = Keine Synchronisierung möglich
syncrsimpl.valtores = Aufzulösender Wert kann sich entweder in der Datenbank oder in cachedrowset befinden
#WebRowSetXmlReader exception
wrsxmlreader.invalidcp = Ende von RowSet wurde erreicht. Ungültige Cursorposition
wrsxmlreader.readxml = readXML: {0}
wrsxmlreader.parseerr = ** Parsingfehler: {0}, Zeile: {1} , URI: {2}
#WebRowSetXmlWriter exceptions
wrsxmlwriter.ioex = IOException: {0}
wrsxmlwriter.sqlex = SQLException: {0}
wrsxmlwriter.failedwrite = Schreiben des Wertes nicht erfolgreich
wsrxmlwriter.notproper = Kein zulässiger Typ
#XmlReaderContentHandler exceptions
xmlrch.errmap = Fehler beim Festlegen der Zuordnung: {0}
xmlrch.errmetadata = Fehler beim Festlegen der Metadaten: {0}
xmlrch.errinsertval = Fehler beim Einfügen der Werte: {0}
xmlrch.errconstr = Fehler beim Erstellen der Zeile: {0}
xmlrch.errdel = Fehler beim Löschen der Zeile: {0}
xmlrch.errinsert = Fehler beim Erstellen der Einfügezeile: {0}
xmlrch.errinsdel = Fehler beim Erstellen der Einfüge- oder Löschzeile: {0}
xmlrch.errupdate = Fehler beim Erstellen der Updatezeile: {0}
xmlrch.errupdrow = Fehler beim Aktualisieren der Zeile: {0}
xmlrch.chars = Zeichen:
xmlrch.badvalue = Ungültiger Wert. Eigenschaft kann nicht auf null gesetzt werden
xmlrch.badvalue1 = Ungültiger Wert. Metadaten können nicht auf null gesetzt werden
xmlrch.warning = ** Warnung: {0}, Zeile: {1} , URI: {2}
#RIOptimisticProvider Exceptions
riop.locking = Sperren der Klassifizierung wird nicht unterstützt
#RIXMLProvider exceptions
rixml.unsupp = Keine Unterstützung bei RIXMLProvider

View file

@ -0,0 +1,169 @@
#
# Copyright (c) 2005, 2024, 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.
#
# CacheRowSetImpl exceptions
cachedrowsetimpl.populate = Se ha proporcionado un objeto ResultSet no válido para el método de relleno
cachedrowsetimpl.invalidp = El proveedor de persistencia generado no es válido
cachedrowsetimpl.nullhash = La instancia CachedRowSetImpl no se puede crear. Se ha proporcionado una tabla hash nula al constructor
cachedrowsetimpl.invalidop = Operación no válida al insertar fila
cachedrowsetimpl.accfailed = Fallo de acceptChanges
cachedrowsetimpl.invalidcp = Posición de cursor no válida
cachedrowsetimpl.illegalop = Operación no permitida en fila no insertada
cachedrowsetimpl.clonefail = Fallo en la clonación: {0}
cachedrowsetimpl.invalidcol = Índice de columnas no válido
cachedrowsetimpl.invalcolnm = Nombre de columna no válido
cachedrowsetimpl.boolfail = Fallo de getBoolen en valor ( {0} ) de columna {1}
cachedrowsetimpl.bytefail = Fallo de getByte en valor ( {0} ) de columna {1}
cachedrowsetimpl.shortfail = Fallo de getShort en valor ( {0} ) de columna {1}
cachedrowsetimpl.intfail = Fallo de getInt en valor ( {0} ) de columna {1}
cachedrowsetimpl.longfail = Fallo de getLong en valor ( {0} ) de columna {1}
cachedrowsetimpl.floatfail = Fallo de getFloat en valor ( {0} ) de columna {1}
cachedrowsetimpl.doublefail = Fallo de getDouble en valor ( {0} ) de columna {1}
cachedrowsetimpl.dtypemismt = Discordancia entre Tipos de Datos
cachedrowsetimpl.datefail = Fallo de getDate en valor ( {0} ) de columna {1}. No es posible convertir
cachedrowsetimpl.timefail = Fallo de getTime en valor ( {0} ) de columna {1}. No es posible convertir
cachedrowsetimpl.posupdate = Actualizaciones posicionadas no soportadas
cachedrowsetimpl.unableins = No se ha podido crear la instancia: {0}
cachedrowsetimpl.beforefirst = beforeFirst: Operación de cursor no válida
cachedrowsetimpl.first = First: Operación de cursor no válida
cachedrowsetimpl.last = last : TYPE_FORWARD_ONLY
cachedrowsetimpl.absolute = absolute: Posición de cursor no válida
cachedrowsetimpl.relative = relative: Posición de cursor no válida
cachedrowsetimpl.asciistream = fallo en lectura de flujo de caracteres ascii
cachedrowsetimpl.binstream = fallo de lectura de flujo binario
cachedrowsetimpl.failedins = Fallo en inserción de fila
cachedrowsetimpl.updateins = llamada a updateRow mientras se insertaba fila
cachedrowsetimpl.movetoins = moveToInsertRow : CONCUR_READ_ONLY
cachedrowsetimpl.movetoins1 = moveToInsertRow: no hay metadatos
cachedrowsetimpl.movetoins2 = moveToInsertRow: número de columnas no válido
cachedrowsetimpl.tablename = El nombre de la tabla no puede ser nulo
cachedrowsetimpl.keycols = Columnas clave no válidas
cachedrowsetimpl.opnotsupp = La base de datos no admite esta operación
cachedrowsetimpl.matchcols = Las columnas coincidentes no concuerdan con las definidas
cachedrowsetimpl.setmatchcols = Defina las columnas coincidentes antes de obtenerlas
cachedrowsetimpl.matchcols1 = Las columnas coincidentes deben ser mayores que 0
cachedrowsetimpl.matchcols2 = Las columnas coincidentes deben estar vacías o ser una cadena nula
cachedrowsetimpl.unsetmatch = Las columnas cuya definición se está anulando no concuerdan con las definidas
cachedrowsetimpl.unsetmatch1 = Use el nombre de columna como argumento en unsetMatchColumn
cachedrowsetimpl.unsetmatch2 = Use el identificador de columna como argumento en unsetMatchColumn
cachedrowsetimpl.numrows = El número de filas es menor que cero o menor que el tamaño recuperado
cachedrowsetimpl.startpos = La posición de inicio no puede ser negativa
cachedrowsetimpl.nextpage = Rellene los datos antes de realizar la llamada
cachedrowsetimpl.pagesize = El tamaño de página no puede ser menor que cero
cachedrowsetimpl.pagesize1 = El tamaño de página no puede ser mayor que maxRows
cachedrowsetimpl.fwdonly = ResultSet sólo se reenvía
cachedrowsetimpl.type = El tipo es: {0}
cachedrowsetimpl.opnotysupp = Operación no soportada todavía
cachedrowsetimpl.featnotsupp = Función no soportada
# WebRowSetImpl exceptions
webrowsetimpl.nullhash = La instancia WebRowSetImpl no se puede crear. Se ha proporcionado una tabla hash nula al constructor
webrowsetimpl.invalidwr = Escritor no válido
webrowsetimpl.invalidrd = Lector no válido
#FilteredRowSetImpl exceptions
filteredrowsetimpl.relative = relative: Operación de cursor no válida
filteredrowsetimpl.absolute = absolute: Operación de cursor no válida
filteredrowsetimpl.notallowed = El filtro no admite este valor
#JoinRowSetImpl exceptions
joinrowsetimpl.notinstance = No es una instancia de rowset
joinrowsetimpl.matchnotset = Las columnas coincidentes no están definidas para la unión
joinrowsetimpl.numnotequal = El número de elementos de rowset y el de columnas coincidentes no es el mismo
joinrowsetimpl.notdefined = No es un tipo de unión definido
joinrowsetimpl.notsupported = Este tipo de unión no está soportado
joinrowsetimpl.initerror = Error de inicialización de JoinRowSet
joinrowsetimpl.genericerr = Error de inicialización genérico de joinrowset
joinrowsetimpl.emptyrowset = No se puede agregar un juego de filas vacío a este JoinRowSet
#JdbcRowSetImpl exceptions
jdbcrowsetimpl.invalstate = Estado no válido
jdbcrowsetimpl.connect = JdbcRowSet (connect): JNDI no se puede conectar
jdbcrowsetimpl.paramtype = No se puede deducir el tipo de parámetro
jdbcrowsetimpl.matchcols = Las columnas coincidentes no concuerdan con las definidas
jdbcrowsetimpl.setmatchcols = Defina las columnas coincidentes antes de obtenerlas
jdbcrowsetimpl.matchcols1 = Las columnas coincidentes deben ser mayores que 0
jdbcrowsetimpl.matchcols2 = Las columnas coincidentes no pueden estar vacías ni ser una cadena nula
jdbcrowsetimpl.unsetmatch = Las columnas cuya definición se está anulando no concuerdan con las definidas
jdbcrowsetimpl.usecolname = Use el nombre de columna como argumento en unsetMatchColumn
jdbcrowsetimpl.usecolid = Use el identificador de columna como argumento en unsetMatchColumn
jdbcrowsetimpl.resnotupd = ResultSet no se puede actualizar
jdbcrowsetimpl.opnotysupp = Operación no soportada todavía
jdbcrowsetimpl.featnotsupp = Función no soportada
#CachedRowSetReader exceptions
crsreader.connect = (JNDI) No se ha podido conectar
crsreader.paramtype = No se ha podido deducir el tipo de parámetro
crsreader.connecterr = Error interno en RowSetReader: no hay conexión o comando
crsreader.datedetected = Fecha Detectada
crsreader.caldetected = Calendario Detectado
#CachedRowSetWriter exceptions
crswriter.connect = No se ha podido obtener una conexión
crswriter.tname = writeData no puede determinar el nombre de tabla
crswriter.params1 = Valor de params1: {0}
crswriter.params2 = Valor de params2: {0}
crswriter.conflictsno = conflictos en la sincronización
#InsertRow exceptions
insertrow.novalue = No se ha insertado ningún valor
#SyncResolverImpl exceptions
syncrsimpl.indexval = El valor de índice está fuera de rango
syncrsimpl.noconflict = Esta columna no está en conflicto
syncrsimpl.syncnotpos = No se puede sincronizar
syncrsimpl.valtores = El valor que se debe resolver puede estar en la base de datos o en cachedrowset
#WebRowSetXmlReader exception
wrsxmlreader.invalidcp = Se ha llegado al final de RowSet. Posición de cursor no válida
wrsxmlreader.readxml = readXML : {0}
wrsxmlreader.parseerr = ** Error de análisis: {0} , línea: {1} , uri: {2}
#WebRowSetXmlWriter exceptions
wrsxmlwriter.ioex = IOException : {0}
wrsxmlwriter.sqlex = SQLException : {0}
wrsxmlwriter.failedwrite = Error al escribir el valor
wsrxmlwriter.notproper = Tipo incorrecto
#XmlReaderContentHandler exceptions
xmlrch.errmap = Error al definir la asignación: {0}
xmlrch.errmetadata = Error al definir metadatos: {0}
xmlrch.errinsertval = Error al insertar los valores: {0}
xmlrch.errconstr = Error al construir la fila: {0}
xmlrch.errdel = Error al suprimir la fila: {0}
xmlrch.errinsert = Error al construir la fila de inserción: {0}
xmlrch.errinsdel = Error al construir la fila de inserción o supresión: {0}
xmlrch.errupdate = Error al construir la fila de actualización: {0}
xmlrch.errupdrow = Error al actualizar la fila: {0}
xmlrch.chars = caracteres:
xmlrch.badvalue = Valor incorrecto; la propiedad no puede ser nula
xmlrch.badvalue1 = Valor incorrecto; los metadatos no pueden ser nulos
xmlrch.warning = ** Advertencia: {0} , línea: {1} , uri: {2}
#RIOptimisticProvider Exceptions
riop.locking = No se permite bloquear la clasificación
#RIXMLProvider exceptions
rixml.unsupp = No soportado con RIXMLProvider

View file

@ -0,0 +1,169 @@
#
# Copyright (c) 2005, 2024, 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.
#
# CacheRowSetImpl exceptions
cachedrowsetimpl.populate = L'objet ResultSet fourni en entrée de la méthode n'est pas valide
cachedrowsetimpl.invalidp = Le fournisseur de persistance généré n'est pas valide
cachedrowsetimpl.nullhash = Impossible de créer une instance de CachedRowSetImpl. Table de hachage NULL fournie au constructeur
cachedrowsetimpl.invalidop = Opération non valide lors de l'insertion de ligne
cachedrowsetimpl.accfailed = Echec de acceptChanges
cachedrowsetimpl.invalidcp = Position du curseur non valide
cachedrowsetimpl.illegalop = Opération non admise sur une ligne non insérée
cachedrowsetimpl.clonefail = Echec du clonage : {0}
cachedrowsetimpl.invalidcol = Index de colonne non valide
cachedrowsetimpl.invalcolnm = Nom de colonne non valide
cachedrowsetimpl.boolfail = Echec de getBoolen pour la valeur ({0}) de la colonne {1}
cachedrowsetimpl.bytefail = Echec de getByte pour la valeur ({0}) de la colonne {1}
cachedrowsetimpl.shortfail = Echec de getShort pour la valeur ({0}) de la colonne {1}
cachedrowsetimpl.intfail = Echec de getInt pour la valeur ({0}) de la colonne {1}
cachedrowsetimpl.longfail = Echec de getLong pour la valeur ({0}) de la colonne {1}
cachedrowsetimpl.floatfail = Echec de getFloat pour la valeur ({0}) de la colonne {1}
cachedrowsetimpl.doublefail = Echec de getDouble pour la valeur ({0}) de la colonne {1}
cachedrowsetimpl.dtypemismt = Le type de données ne correspond pas
cachedrowsetimpl.datefail = Echec de getDate pour la valeur ({0}) de la colonne {1} - Aucune conversion possible
cachedrowsetimpl.timefail = Echec de getTime pour la valeur ({0}) de la colonne {1} - Aucune conversion possible
cachedrowsetimpl.posupdate = Mises à jour choisies non prises en charge
cachedrowsetimpl.unableins = Instanciation impossible : {0}
cachedrowsetimpl.beforefirst = beforeFirst : opération de curseur non valide
cachedrowsetimpl.first = First : opération de curseur non valide
cachedrowsetimpl.last = last : TYPE_FORWARD_ONLY
cachedrowsetimpl.absolute = absolute : position de curseur non valide
cachedrowsetimpl.relative = relative : position de curseur non valide
cachedrowsetimpl.asciistream = échec de la lecture pour le flux ASCII
cachedrowsetimpl.binstream = échec de la lecture pour le flux binaire
cachedrowsetimpl.failedins = Echec de l'insertion de ligne
cachedrowsetimpl.updateins = appel de updateRow lors de l'insertion de ligne
cachedrowsetimpl.movetoins = moveToInsertRow : CONCUR_READ_ONLY
cachedrowsetimpl.movetoins1 = moveToInsertRow : aucune métadonnée
cachedrowsetimpl.movetoins2 = moveToInsertRow : nombre de colonnes non valide
cachedrowsetimpl.tablename = Le nom de la table ne peut pas être NULL
cachedrowsetimpl.keycols = Colonnes de clé non valides
cachedrowsetimpl.opnotsupp = Opération non prise en charge par la base de données
cachedrowsetimpl.matchcols = Les colonnes correspondantes ne sont pas les mêmes que les colonnes définies
cachedrowsetimpl.setmatchcols = Définir les colonnes correspondantes avant de les prendre
cachedrowsetimpl.matchcols1 = Les colonnes correspondantes doivent être supérieures à zéro
cachedrowsetimpl.matchcols2 = Les colonnes correspondantes doivent êtres vides ou ne contenir que des chaînes NULL
cachedrowsetimpl.unsetmatch = Les colonnes définies et non définies sont différentes
cachedrowsetimpl.unsetmatch1 = Utiliser le nom de colonne comme argument pour unsetMatchColumn
cachedrowsetimpl.unsetmatch2 = Utiliser l'ID de colonne comme argument pour unsetMatchColumn
cachedrowsetimpl.numrows = Le nombre de lignes est inférieur à zéro ou à la taille d'extraction
cachedrowsetimpl.startpos = La position de départ ne peut pas être négative
cachedrowsetimpl.nextpage = Entrer les données avant l'appel
cachedrowsetimpl.pagesize = La taille de la page ne peut pas être négative
cachedrowsetimpl.pagesize1 = La taille de la page ne peut pas être supérieure à maxRows
cachedrowsetimpl.fwdonly = ResultSet va en avant seulement
cachedrowsetimpl.type = Le type est : {0}
cachedrowsetimpl.opnotysupp = Opération non encore prise en charge
cachedrowsetimpl.featnotsupp = Fonctionnalité non prise en charge
# WebRowSetImpl exceptions
webrowsetimpl.nullhash = Impossible de créer une instance de WebRowSetImpl. Table de hachage NULL fournie au constructeur
webrowsetimpl.invalidwr = Processus d'écriture non valide
webrowsetimpl.invalidrd = Processus de lecture non valide
#FilteredRowSetImpl exceptions
filteredrowsetimpl.relative = relative : opération de curseur non valide
filteredrowsetimpl.absolute = absolute : opération de curseur non valide
filteredrowsetimpl.notallowed = Cette valeur n'est pas autorisée via le filtre
#JoinRowSetImpl exceptions
joinrowsetimpl.notinstance = N'est pas une instance de RowSet
joinrowsetimpl.matchnotset = Les colonnes correspondantes ne sont pas définies pour la jointure
joinrowsetimpl.numnotequal = Le nombre d'éléments dans RowSet est différent du nombre de colonnes correspondantes
joinrowsetimpl.notdefined = Ce n'est pas un type de jointure défini
joinrowsetimpl.notsupported = Ce type de jointure n'est pas pris en charge
joinrowsetimpl.initerror = Erreur d'initialisation de JoinRowSet
joinrowsetimpl.genericerr = Erreur initiale générique de JoinRowSet
joinrowsetimpl.emptyrowset = Impossible d'ajouter un objet RowSet vide à ce JoinRowSet
#JdbcRowSetImpl exceptions
jdbcrowsetimpl.invalstate = Etat non valide
jdbcrowsetimpl.connect = Impossible de connecter JNDI JdbcRowSet (connexion)
jdbcrowsetimpl.paramtype = Impossible de déduire le type de paramètre
jdbcrowsetimpl.matchcols = Les colonnes correspondantes ne sont pas les mêmes que les colonnes définies
jdbcrowsetimpl.setmatchcols = Définir les colonnes correspondantes avant de les prendre
jdbcrowsetimpl.matchcols1 = Les colonnes correspondantes doivent être supérieures à zéro
jdbcrowsetimpl.matchcols2 = Les colonnes correspondantes ne doivent pas êtres NULL ni contenir des chaînes vides
jdbcrowsetimpl.unsetmatch = Les colonnes non définies ne sont pas les mêmes que les colonnes définies
jdbcrowsetimpl.usecolname = Utiliser le nom de colonne comme argument pour unsetMatchColumn
jdbcrowsetimpl.usecolid = Utiliser l'ID de colonne comme argument pour unsetMatchColumn
jdbcrowsetimpl.resnotupd = La mise à jour de ResultSet est interdite
jdbcrowsetimpl.opnotysupp = Opération non encore prise en charge
jdbcrowsetimpl.featnotsupp = Fonctionnalité non prise en charge
#CachedRowSetReader exceptions
crsreader.connect = Impossible de connecter (JNDI)
crsreader.paramtype = Impossible de déduire le type de paramètre
crsreader.connecterr = Erreur interne dans RowSetReader : pas de connexion ni de commande
crsreader.datedetected = Une date a été détectée
crsreader.caldetected = Un calendrier a été détecté
#CachedRowSetWriter exceptions
crswriter.connect = Impossible d'obtenir la connexion
crswriter.tname = writeData ne peut pas déterminer le nom de la table
crswriter.params1 = Valeur de params1 : {0}
crswriter.params2 = Valeur de params2 : {0}
crswriter.conflictsno = conflits lors de la synchronisation
#InsertRow exceptions
insertrow.novalue = Aucune valeur n'a été insérée
#SyncResolverImpl exceptions
syncrsimpl.indexval = Valeur d'index hors plage
syncrsimpl.noconflict = Cette colonne n'est pas en conflit
syncrsimpl.syncnotpos = La synchronisation est impossible
syncrsimpl.valtores = La valeur à résoudre peut être soit dans la base de données, soit dans CachedrowSet
#WebRowSetXmlReader exception
wrsxmlreader.invalidcp = Fin de RowSet atteinte. Position de curseur non valide
wrsxmlreader.readxml = readXML : {0}
wrsxmlreader.parseerr = ** Erreur d''analyse : {0} , ligne : {1} , URI : {2}
#WebRowSetXmlWriter exceptions
wrsxmlwriter.ioex = Exception d''E/S : {0}
wrsxmlwriter.sqlex = Exception SQL : {0}
wrsxmlwriter.failedwrite = Echec d'écriture de la valeur
wsrxmlwriter.notproper = N'est pas un type correct
#XmlReaderContentHandler exceptions
xmlrch.errmap = Erreur lors de la définition du mappage : {0}
xmlrch.errmetadata = Erreur lors de la définition des métadonnées : {0}
xmlrch.errinsertval = Erreur lors de l''insertion des valeurs : {0}
xmlrch.errconstr = Erreur lors de la construction de la ligne : {0}
xmlrch.errdel = Erreur lors de la suppression de la ligne : {0}
xmlrch.errinsert = Erreur lors de la construction de la ligne à insérer : {0}
xmlrch.errinsdel = Erreur lors de la construction de la ligne insdel : {0}
xmlrch.errupdate = Erreur lors de la construction de la ligne à mettre à jour : {0}
xmlrch.errupdrow = Erreur lors de la mise à jour de la ligne : {0}
xmlrch.chars = caractères :
xmlrch.badvalue = Valeur incorrecte ; cette propriété ne peut pas être NULL
xmlrch.badvalue1 = Valeur incorrecte ; ces métadonnées ne peuvent pas être NULL
xmlrch.warning = ** Avertissement : {0} , ligne : {1} , URI : {2}
#RIOptimisticProvider Exceptions
riop.locking = Le verrouillage de la classification n'est pas pris en charge
#RIXMLProvider exceptions
rixml.unsupp = Non pris en charge avec RIXMLProvider

View file

@ -0,0 +1,169 @@
#
# Copyright (c) 2005, 2024, 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.
#
# CacheRowSetImpl exceptions
cachedrowsetimpl.populate = Oggetto ResultSet non valido fornito per l'inserimento dati nel metodo
cachedrowsetimpl.invalidp = Generato provider di persistenza non valido
cachedrowsetimpl.nullhash = Impossibile creare istanza CachedRowSetImpl. Tabella hash nulla fornita al costruttore
cachedrowsetimpl.invalidop = Operazione non valida nella riga di inserimento
cachedrowsetimpl.accfailed = acceptChanges non riuscito
cachedrowsetimpl.invalidcp = Posizione cursore non valida
cachedrowsetimpl.illegalop = Operazione non valida nella riga non inserita
cachedrowsetimpl.clonefail = Copia non riuscita: {0}
cachedrowsetimpl.invalidcol = Indice di colonna non valido
cachedrowsetimpl.invalcolnm = Nome di colonna non valido
cachedrowsetimpl.boolfail = getBoolen non riuscito per il valore ( {0} ) nella colonna {1}
cachedrowsetimpl.bytefail = getByte non riuscito per il valore ( {0} ) nella colonna {1}
cachedrowsetimpl.shortfail = getShort non riuscito per il valore ( {0} ) nella colonna {1}
cachedrowsetimpl.intfail = getInt non riuscito per il valore ( {0} ) nella colonna {1}
cachedrowsetimpl.longfail = getLong non riuscito per il valore ( {0} ) nella colonna {1}
cachedrowsetimpl.floatfail = getFloat non riuscito per il valore ( {0} ) nella colonna {1}
cachedrowsetimpl.doublefail = getDouble non riuscito per il valore ( {0} ) nella colonna {1}
cachedrowsetimpl.dtypemismt = Mancata corrispondenza tipo di dati
cachedrowsetimpl.datefail = getDate non riuscito per il valore ( {0} ) nella colonna {1}. Nessuna conversione disponibile.
cachedrowsetimpl.timefail = getTime non riuscito per il valore ( {0} ) nella colonna {1}. Nessuna conversione disponibile.
cachedrowsetimpl.posupdate = Aggiornamenti posizionati non supportati
cachedrowsetimpl.unableins = Impossibile creare istanza: {0}
cachedrowsetimpl.beforefirst = beforeFirst: operazione cursore non valida
cachedrowsetimpl.first = First: operazione cursore non valida
cachedrowsetimpl.last = last: TYPE_FORWARD_ONLY
cachedrowsetimpl.absolute = absolute: posizione cursore non valida
cachedrowsetimpl.relative = relative: posizione cursore non valida
cachedrowsetimpl.asciistream = lettura non riuscita per il flusso ascii
cachedrowsetimpl.binstream = lettura non riuscita per il flusso binario
cachedrowsetimpl.failedins = operazione non riuscita nella riga di inserimento
cachedrowsetimpl.updateins = updateRow chiamato nella riga di inserimento
cachedrowsetimpl.movetoins = moveToInsertRow: CONCUR_READ_ONLY
cachedrowsetimpl.movetoins1 = moveToInsertRow: nessun metadato
cachedrowsetimpl.movetoins2 = moveToInsertRow: numero di colonne non valido
cachedrowsetimpl.tablename = Il nome di tabella non può essere nullo
cachedrowsetimpl.keycols = Colonne chiave non valide
cachedrowsetimpl.opnotsupp = Operazione non supportata dal database
cachedrowsetimpl.matchcols = Le colonne di corrispondenza non coincidono con le colonne impostate
cachedrowsetimpl.setmatchcols = Impostare le colonne di corrispondenza prima di recuperarle
cachedrowsetimpl.matchcols1 = Le colonne di corrispondenza devono essere superiori a 0
cachedrowsetimpl.matchcols2 = Le colonne di corrispondenza devono essere una stringa vuota o nulla
cachedrowsetimpl.unsetmatch = Le colonne rimosse non coincidono con le colonne impostate
cachedrowsetimpl.unsetmatch1 = Utilizzare il nome di colonna come argomento per unsetMatchColumn
cachedrowsetimpl.unsetmatch2 = Utilizzare l'ID di colonna come argomento per unsetMatchColumn
cachedrowsetimpl.numrows = Il numero di righe è inferiore a zero o alla dimensione di recupero
cachedrowsetimpl.startpos = La posizione iniziale non può essere negativa
cachedrowsetimpl.nextpage = Inserire i dati prima di chiamare
cachedrowsetimpl.pagesize = La dimensione della pagina non può essere inferiore a zero
cachedrowsetimpl.pagesize1 = La dimensione della pagina non può essere superiore a maxRows
cachedrowsetimpl.fwdonly = ResultSet è a solo inoltro
cachedrowsetimpl.type = Il tipo è: {0}
cachedrowsetimpl.opnotysupp = Operazione attualmente non supportata
cachedrowsetimpl.featnotsupp = Funzione non supportata
# WebRowSetImpl exceptions
webrowsetimpl.nullhash = Impossibile creare istanza WebRowSetImpl. Tabella hash nulla fornita al costruttore
webrowsetimpl.invalidwr = Processo di scrittura non valido
webrowsetimpl.invalidrd = Processo di lettura non valido
#FilteredRowSetImpl exceptions
filteredrowsetimpl.relative = relative: operazione cursore non valida
filteredrowsetimpl.absolute = absolute: operazione cursore non valida
filteredrowsetimpl.notallowed = Questo valore non è consentito nel filtro
#JoinRowSetImpl exceptions
joinrowsetimpl.notinstance = Non è un'istanza di rowset
joinrowsetimpl.matchnotset = Colonna di corrispondenza non impostata per l'unione
joinrowsetimpl.numnotequal = Numero di elementi in rowset diverso dalla colonna di corrispondenza
joinrowsetimpl.notdefined = Non è un tipo di unione definito
joinrowsetimpl.notsupported = Questo tipo di unione non è supportato
joinrowsetimpl.initerror = Errore di inizializzazione di JoinRowSet
joinrowsetimpl.genericerr = Errore iniziale di joinrowset generico
joinrowsetimpl.emptyrowset = Impossibile aggiungere un set di righe vuoto al JoinRowSet corrente
#JdbcRowSetImpl exceptions
jdbcrowsetimpl.invalstate = Stato non valido
jdbcrowsetimpl.connect = JdbcRowSet (connessione): impossibile stabilire una connessione con JNDI
jdbcrowsetimpl.paramtype = Impossibile dedurre il tipo di parametro
jdbcrowsetimpl.matchcols = Le colonne di corrispondenza non coincidono con le colonne impostate
jdbcrowsetimpl.setmatchcols = Impostare le colonne di corrispondenza prima di recuperarle
jdbcrowsetimpl.matchcols1 = Le colonne di corrispondenza devono essere superiori a 0
jdbcrowsetimpl.matchcols2 = Le colonne di corrispondenza non possono essere una stringa vuota o nulla
jdbcrowsetimpl.unsetmatch = Le colonne rimosse non coincidono con le colonne impostate
jdbcrowsetimpl.usecolname = Utilizzare il nome di colonna come argomento per unsetMatchColumn
jdbcrowsetimpl.usecolid = Utilizzare l'ID di colonna come argomento per unsetMatchColumn
jdbcrowsetimpl.resnotupd = ResultSet non è aggiornabile
jdbcrowsetimpl.opnotysupp = Operazione attualmente non supportata
jdbcrowsetimpl.featnotsupp = Funzione non supportata
#CachedRowSetReader exceptions
crsreader.connect = (JNDI) Impossibile stabilire una connessione
crsreader.paramtype = Impossibile dedurre il tipo di parametro
crsreader.connecterr = Errore interno in RowSetReader: nessuna connessione o comando
crsreader.datedetected = È stata rilevata una data
crsreader.caldetected = È stato rilevato un calendario
#CachedRowSetWriter exceptions
crswriter.connect = Impossibile stabilire una connessione
crswriter.tname = writeData non riesce a determinare il nome di tabella
crswriter.params1 = Valore dei parametri 1: {0}
crswriter.params2 = Valore dei parametri 2: {0}
crswriter.conflictsno = Conflitti durante la sincronizzazione
#InsertRow exceptions
insertrow.novalue = Non è stato inserito alcun valore
#SyncResolverImpl exceptions
syncrsimpl.indexval = Valore indice non compreso nell'intervallo
syncrsimpl.noconflict = Questa colonna non è in conflitto
syncrsimpl.syncnotpos = Impossibile eseguire la sincronizzazione
syncrsimpl.valtores = Il valore da risolvere può essere nel database o in cachedrowset
#WebRowSetXmlReader exception
wrsxmlreader.invalidcp = Raggiunta la fine di RowSet. Posizione cursore non valida
wrsxmlreader.readxml = readXML: {0}
wrsxmlreader.parseerr = **Errore di analisi: {0}, riga: {1}, URI: {2}
#WebRowSetXmlWriter exceptions
wrsxmlwriter.ioex = IOException: {0}
wrsxmlwriter.sqlex = SQLException: {0}
wrsxmlwriter.failedwrite = Impossibile scrivere il valore
wsrxmlwriter.notproper = Non un tipo corretto
#XmlReaderContentHandler exceptions
xmlrch.errmap = Errore durante l''impostazione della mappa: {0}
xmlrch.errmetadata = Errore durante l''impostazione dei metadati: {0}
xmlrch.errinsertval = Errore durante l''inserimento dei valori: {0}
xmlrch.errconstr = Errore durante la costruzione della riga: {0}
xmlrch.errdel = Errore durante l''eliminazione della riga: {0}
xmlrch.errinsert = Errore durante la costruzione della riga di inserimento: {0}
xmlrch.errinsdel = Errore durante la costruzione della riga insdel: {0}
xmlrch.errupdate = Errore durante la costruzione della riga di aggiornamento: {0}
xmlrch.errupdrow = Errore durante l''aggiornamento della riga: {0}
xmlrch.chars = caratteri:
xmlrch.badvalue = valore non valido; proprietà non annullabile
xmlrch.badvalue1 = valore non valido; metadati non annullabili
xmlrch.warning = **Avvertenza: {0}, riga: {1}, URI: {2}
#RIOptimisticProvider Exceptions
riop.locking = La classificazione di blocco non è supportata
#RIXMLProvider exceptions
rixml.unsupp = Non supportato con RIXMLProvider

View file

@ -0,0 +1,169 @@
#
# Copyright (c) 2005, 2024, 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.
#
# CacheRowSetImpl exceptions
cachedrowsetimpl.populate = populateメソッドに無効なResultSetオブジェクトが使用されました
cachedrowsetimpl.invalidp = 無効な永続性プロバイダが生成されました
cachedrowsetimpl.nullhash = CachedRowSetImplインスタンスをインスタンス化できません。コンストラクタにnullのHashtableが使用されました
cachedrowsetimpl.invalidop = 挿入行での無効な操作
cachedrowsetimpl.accfailed = acceptChangesの失敗
cachedrowsetimpl.invalidcp = 無効なカーソル位置
cachedrowsetimpl.illegalop = 挿入されなかった行の不正な操作
cachedrowsetimpl.clonefail = クローンの失敗: {0}
cachedrowsetimpl.invalidcol = 無効な列索引
cachedrowsetimpl.invalcolnm = 無効な列名
cachedrowsetimpl.boolfail = 列{1}の値({0})でgetBooleanが失敗しました
cachedrowsetimpl.bytefail = 列{1}の値({0})でgetByteが失敗しました
cachedrowsetimpl.shortfail = 列{1}の値({0})でgetShortが失敗しました
cachedrowsetimpl.intfail = 列{1}の値({0})でgetIntが失敗しました
cachedrowsetimpl.longfail = 列{1}の値({0})でgetLongが失敗しました
cachedrowsetimpl.floatfail = 列{1}の値({0})でgetFloatが失敗しました
cachedrowsetimpl.doublefail = 列{1}の値({0})でgetDoubleが失敗しました
cachedrowsetimpl.dtypemismt = データ型の不一致
cachedrowsetimpl.datefail = 列{1}の値({0})でgetDateが失敗。変換できません
cachedrowsetimpl.timefail = 列{1}の値({0})でgetTimeが失敗。変換できません
cachedrowsetimpl.posupdate = 位置決めされた更新がサポートされません
cachedrowsetimpl.unableins = インスタンス化できない: {0}
cachedrowsetimpl.beforefirst = beforeFirst: 無効なカーソル操作
cachedrowsetimpl.first = First: 無効なカーソル操作
cachedrowsetimpl.last = last: TYPE_FORWARD_ONLY
cachedrowsetimpl.absolute = absolute: 無効なカーソル位置
cachedrowsetimpl.relative = relative: 無効なカーソル位置
cachedrowsetimpl.asciistream = asciiストリームの読込みが失敗しました
cachedrowsetimpl.binstream = バイナリ・ストリームの読込みが失敗しました
cachedrowsetimpl.failedins = 行の挿入に失敗
cachedrowsetimpl.updateins = 挿入行においてupdateRowが呼び出されました
cachedrowsetimpl.movetoins = moveToInsertRow: CONCUR_READ_ONLY
cachedrowsetimpl.movetoins1 = moveToInsertRow: メタデータなし
cachedrowsetimpl.movetoins2 = moveToInsertRow: 無効な列数
cachedrowsetimpl.tablename = 表名にnullは使用できません
cachedrowsetimpl.keycols = 無効なキー列
cachedrowsetimpl.opnotsupp = データベースでサポートされない操作
cachedrowsetimpl.matchcols = 一致列が列のセットと同じではありません
cachedrowsetimpl.setmatchcols = 一致列を取得する前に設定してください
cachedrowsetimpl.matchcols1 = 一致列は0より大きい必要があります
cachedrowsetimpl.matchcols2 = 一致列は空かnull文字列である必要があります
cachedrowsetimpl.unsetmatch = 設定解除されている列はセットと同じではありません
cachedrowsetimpl.unsetmatch1 = unsetMatchColumnへの引数として列名を使用してください
cachedrowsetimpl.unsetmatch2 = unsetMatchColumnへの引数として列IDを使用してください
cachedrowsetimpl.numrows = 行数がゼロまたはフェッチ・サイズより小さいです
cachedrowsetimpl.startpos = 開始位置を負にすることはできません
cachedrowsetimpl.nextpage = 呼出し前にデータを移入します
cachedrowsetimpl.pagesize = ページ・サイズをゼロより小さくすることはできません
cachedrowsetimpl.pagesize1 = ページ・サイズをmaxRowsより大きくすることができません
cachedrowsetimpl.fwdonly = ResultSetは順方向のみです
cachedrowsetimpl.type = タイプ: {0}
cachedrowsetimpl.opnotysupp = まだサポートされていない操作
cachedrowsetimpl.featnotsupp = サポートされていない機能
# WebRowSetImpl exceptions
webrowsetimpl.nullhash = WebRowSetImplインスタンスをインスタンス化できません。コンストラクタにnullのHashtableが使用されました
webrowsetimpl.invalidwr = 無効なライター
webrowsetimpl.invalidrd = 無効なリーダー
#FilteredRowSetImpl exceptions
filteredrowsetimpl.relative = relative: 無効なカーソル操作
filteredrowsetimpl.absolute = absolute: 無効なカーソル操作
filteredrowsetimpl.notallowed = この値はフィルタで許容されません
#JoinRowSetImpl exceptions
joinrowsetimpl.notinstance = 行セットのインスタンスではありません
joinrowsetimpl.matchnotset = 一致列が結合用に設定されていません
joinrowsetimpl.numnotequal = 行セットの要素数が一致列と等しくありません
joinrowsetimpl.notdefined = 定義された結合のタイプではありません
joinrowsetimpl.notsupported = このタイプの結合はサポートされていません
joinrowsetimpl.initerror = JoinRowSet初期化エラー
joinrowsetimpl.genericerr = 一般的なjoinrowset初期エラー
joinrowsetimpl.emptyrowset = このJoinRowSetに空の行セットを追加することはできません
#JdbcRowSetImpl exceptions
jdbcrowsetimpl.invalstate = 無効な状態
jdbcrowsetimpl.connect = JdbcRowSet (connect): JNDIが接続できません
jdbcrowsetimpl.paramtype = パラメータ・タイプを推定できません
jdbcrowsetimpl.matchcols = 一致列が列のセットと同じではありません
jdbcrowsetimpl.setmatchcols = 一致列を取得する前に設定してください
jdbcrowsetimpl.matchcols1 = 一致列は0より大きい必要があります
jdbcrowsetimpl.matchcols2 = 一致列を空またはnull文字列にすることはできません
jdbcrowsetimpl.unsetmatch = 設定解除されている列はセットと同じではありません
jdbcrowsetimpl.usecolname = unsetMatchColumnへの引数として列名を使用してください
jdbcrowsetimpl.usecolid = unsetMatchColumnへの引数として列IDを使用してください
jdbcrowsetimpl.resnotupd = ResultSetは更新できません
jdbcrowsetimpl.opnotysupp = まだサポートされていない操作
jdbcrowsetimpl.featnotsupp = サポートされていない機能
#CachedRowSetReader exceptions
crsreader.connect = (JNDI)接続できません
crsreader.paramtype = パラメータ・タイプを推定できません
crsreader.connecterr = RowSetReaderの内部エラー: 接続またはコマンドなし
crsreader.datedetected = 日付を検出しました
crsreader.caldetected = カレンダを検出しました
#CachedRowSetWriter exceptions
crswriter.connect = 接続を取得できません
crswriter.tname = writeDataが表名を判別できません
crswriter.params1 = params1の値: {0}
crswriter.params2 = params2の値: {0}
crswriter.conflictsno = 同期中に競合が発生します
#InsertRow exceptions
insertrow.novalue = 値は挿入されていません
#SyncResolverImpl exceptions
syncrsimpl.indexval = 範囲外の索引値
syncrsimpl.noconflict = この列は競合していません
syncrsimpl.syncnotpos = 同期できません
syncrsimpl.valtores = 解決される値はデータベースまたはcachedrowsetにある可能性があります
#WebRowSetXmlReader exception
wrsxmlreader.invalidcp = RowSetの最後に到達しました。無効なカーソル位置
wrsxmlreader.readxml = readXML: {0}
wrsxmlreader.parseerr = **解析エラー: {0}、行: {1}、URI: {2}
#WebRowSetXmlWriter exceptions
wrsxmlwriter.ioex = IOException: {0}
wrsxmlwriter.sqlex = SQLException: {0}
wrsxmlwriter.failedwrite = 値の書込みに失敗しました
wsrxmlwriter.notproper = 適切なタイプではありません
#XmlReaderContentHandler exceptions
xmlrch.errmap = Map設定エラー: {0}
xmlrch.errmetadata = メタデータ設定エラー: {0}
xmlrch.errinsertval = 値の挿入エラー: {0}
xmlrch.errconstr = 行の生成エラー: {0}
xmlrch.errdel = 行の削除エラー: {0}
xmlrch.errinsert = 挿入行の生成エラー: {0}
xmlrch.errinsdel = insdel行の生成エラー: {0}
xmlrch.errupdate = 更新行の生成エラー: {0}
xmlrch.errupdrow = 行の更新エラー: {0}
xmlrch.chars = 文字:
xmlrch.badvalue = 不正な値: nullにできないプロパティ
xmlrch.badvalue1 = 不正な値: nullにできないメタデータ
xmlrch.warning = **警告: {0}、行: {1}、URI: {2}
#RIOptimisticProvider Exceptions
riop.locking = ロックの分類はサポートされていません
#RIXMLProvider exceptions
rixml.unsupp = RIXMLProviderでは未サポート

View file

@ -0,0 +1,169 @@
#
# Copyright (c) 2005, 2024, 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.
#
# CacheRowSetImpl exceptions
cachedrowsetimpl.populate = 부적합한 ResultSet 객체가 제공되어 메소드를 채울 수 없습니다.
cachedrowsetimpl.invalidp = 부적합한 지속성 제공자가 생성되었습니다.
cachedrowsetimpl.nullhash = CachedRowSetImpl 인스턴스를 인스턴스화할 수 없습니다. 생성자에 널 Hashtable이 제공되었습니다.
cachedrowsetimpl.invalidop = 행을 삽입하는 중 부적합한 작업이 수행되었습니다.
cachedrowsetimpl.accfailed = acceptChanges를 실패했습니다.
cachedrowsetimpl.invalidcp = 커서 위치가 부적합합니다.
cachedrowsetimpl.illegalop = 삽입된 행이 아닌 행에서 잘못된 작업이 수행되었습니다.
cachedrowsetimpl.clonefail = 복제 실패: {0}
cachedrowsetimpl.invalidcol = 열 인덱스가 부적합합니다.
cachedrowsetimpl.invalcolnm = 열 이름이 부적합합니다.
cachedrowsetimpl.boolfail = {1} 열의 값({0})에서 getBoolen을 실패했습니다.
cachedrowsetimpl.bytefail = {1} 열의 값({0})에서 getByte를 실패했습니다.
cachedrowsetimpl.shortfail = {1} 열의 값({0})에서 getShort를 실패했습니다.
cachedrowsetimpl.intfail = {1} 열의 값({0})에서 getInt를 실패했습니다.
cachedrowsetimpl.longfail = {1} 열의 값({0})에서 getLong을 실패했습니다.
cachedrowsetimpl.floatfail = {1} 열의 값({0})에서 getFloat를 실패했습니다.
cachedrowsetimpl.doublefail = {1} 열의 값({0})에서 getDouble을 실패했습니다.
cachedrowsetimpl.dtypemismt = 데이터 유형이 일치하지 않습니다.
cachedrowsetimpl.datefail = {1} 열의 값({0})에서 getDate를 실패했습니다. 변환할 수 없습니다.
cachedrowsetimpl.timefail = {1} 열의 값({0})에서 getTime을 실패했습니다. 변환할 수 없습니다.
cachedrowsetimpl.posupdate = 위치가 지정된 업데이트가 지원되지 않습니다.
cachedrowsetimpl.unableins = 인스턴스화할 수 없음: {0}
cachedrowsetimpl.beforefirst = beforeFirst: 커서 작업이 부적합합니다.
cachedrowsetimpl.first = 처음: 커서 작업이 부적합합니다.
cachedrowsetimpl.last = 마지막: TYPE_FORWARD_ONLY
cachedrowsetimpl.absolute = 절대: 커서 위치가 부적합합니다.
cachedrowsetimpl.relative = 상대: 커서 위치가 부적합합니다.
cachedrowsetimpl.asciistream = ASCII 스트림에 대한 읽기를 실패했습니다.
cachedrowsetimpl.binstream = 바이너리 스트림에서 읽기를 실패했습니다.
cachedrowsetimpl.failedins = 행 삽입을 실패했습니다.
cachedrowsetimpl.updateins = 행을 삽입하는 중 updateRow가 호출되었습니다.
cachedrowsetimpl.movetoins = moveToInsertRow: CONCUR_READ_ONLY
cachedrowsetimpl.movetoins1 = moveToInsertRow: 메타데이터가 없습니다.
cachedrowsetimpl.movetoins2 = moveToInsertRow: 열 수가 부적합합니다.
cachedrowsetimpl.tablename = 테이블 이름은 널일 수 없습니다.
cachedrowsetimpl.keycols = 키 열이 부적합합니다.
cachedrowsetimpl.opnotsupp = 데이터베이스에서 지원하지 않는 작업입니다.
cachedrowsetimpl.matchcols = 일치 열이 설정된 열과 동일하지 않습니다.
cachedrowsetimpl.setmatchcols = 일치 열을 설정한 후 가져오십시오.
cachedrowsetimpl.matchcols1 = 일치 열은 0개 이상이어야 합니다.
cachedrowsetimpl.matchcols2 = 일치 열은 비어 있거나 널 문자열이어야 합니다.
cachedrowsetimpl.unsetmatch = 설정을 해제하려는 열이 설정된 열과 다릅니다.
cachedrowsetimpl.unsetmatch1 = 열 이름을 unsetMatchColumn의 인수로 사용하십시오.
cachedrowsetimpl.unsetmatch2 = 열 ID를 unsetMatchColumn의 인수로 사용하십시오.
cachedrowsetimpl.numrows = 행 수가 0보다 작거나 인출 크기보다 작습니다.
cachedrowsetimpl.startpos = 시작 위치는 음수일 수 없습니다.
cachedrowsetimpl.nextpage = 호출하기 전에 데이터를 채우십시오.
cachedrowsetimpl.pagesize = 페이지 크기는 0보다 작을 수 없습니다.
cachedrowsetimpl.pagesize1 = 페이지 크기는 maxRows보다 클 수 없습니다.
cachedrowsetimpl.fwdonly = ResultSet는 전달 전용입니다.
cachedrowsetimpl.type = 유형: {0}
cachedrowsetimpl.opnotysupp = 작업이 아직 지원되지 않습니다.
cachedrowsetimpl.featnotsupp = 기능이 지원되지 않습니다.
# WebRowSetImpl exceptions
webrowsetimpl.nullhash = WebRowSetImpl 인스턴스를 인스턴스화할 수 없습니다. 생성자에 널 Hashtable이 제공되었습니다.
webrowsetimpl.invalidwr = 기록 장치가 부적합합니다.
webrowsetimpl.invalidrd = 읽기 프로그램이 부적합합니다.
#FilteredRowSetImpl exceptions
filteredrowsetimpl.relative = 상대: 커서 작업이 부적합합니다.
filteredrowsetimpl.absolute = 절대: 커서 작업이 부적합합니다.
filteredrowsetimpl.notallowed = 이 값은 필터를 통과할 수 없습니다.
#JoinRowSetImpl exceptions
joinrowsetimpl.notinstance = Rowset의 인스턴스가 아닙니다.
joinrowsetimpl.matchnotset = 조인할 일치 열이 설정되지 않았습니다.
joinrowsetimpl.numnotequal = Rowset의 요소 수가 일치 열과 같지 않습니다.
joinrowsetimpl.notdefined = 정의된 조인 유형이 아닙니다.
joinrowsetimpl.notsupported = 이 조인 유형은 지원되지 않습니다.
joinrowsetimpl.initerror = JoinRowSet 초기화 오류
joinrowsetimpl.genericerr = 일반 joinrowset 초기 오류
joinrowsetimpl.emptyrowset = 빈 rowset를 이 JoinRowSet에 추가할 수 없습니다.
#JdbcRowSetImpl exceptions
jdbcrowsetimpl.invalstate = 상태가 부적합합니다.
jdbcrowsetimpl.connect = JdbcRowSet(접속) JNDI가 접속할 수 없습니다.
jdbcrowsetimpl.paramtype = 매개변수 유형을 추론할 수 없습니다.
jdbcrowsetimpl.matchcols = 일치 열이 설정된 열과 동일하지 않습니다.
jdbcrowsetimpl.setmatchcols = 일치 열을 설정한 후 가져오십시오.
jdbcrowsetimpl.matchcols1 = 일치 열은 0개 이상이어야 합니다.
jdbcrowsetimpl.matchcols2 = 일치 열은 널 또는 빈 문자열일 수 없습니다.
jdbcrowsetimpl.unsetmatch = 설정을 해제하려는 열이 설정된 열과 다릅니다.
jdbcrowsetimpl.usecolname = 열 이름을 unsetMatchColumn의 인수로 사용하십시오.
jdbcrowsetimpl.usecolid = 열 ID를 unsetMatchColumn의 인수로 사용하십시오.
jdbcrowsetimpl.resnotupd = ResultSet를 업데이트할 수 없습니다.
jdbcrowsetimpl.opnotysupp = 작업이 아직 지원되지 않습니다.
jdbcrowsetimpl.featnotsupp = 기능이 지원되지 않습니다.
#CachedRowSetReader exceptions
crsreader.connect = (JNDI) 접속할 수 없습니다.
crsreader.paramtype = 매개변수 유형을 추론할 수 없습니다.
crsreader.connecterr = RowSetReader에 내부 오류 발생: 접속 또는 명령이 없습니다.
crsreader.datedetected = 날짜를 감지함
crsreader.caldetected = 달력을 감지함
#CachedRowSetWriter exceptions
crswriter.connect = 접속할 수 없습니다.
crswriter.tname = writeData에서 테이블 이름을 확인할 수 없습니다.
crswriter.params1 = params1의 값: {0}
crswriter.params2 = params2의 값: {0}
crswriter.conflictsno = 동기화하는 중 충돌함
#InsertRow exceptions
insertrow.novalue = 값이 삽입되지 않았습니다.
#SyncResolverImpl exceptions
syncrsimpl.indexval = 인덱스 값이 범위를 벗어났습니다.
syncrsimpl.noconflict = 이 열은 충돌하지 않습니다.
syncrsimpl.syncnotpos = 동기화할 수 없습니다.
syncrsimpl.valtores = 분석할 값이 데이터베이스 또는 cachedrowset에 있을 수 있습니다.
#WebRowSetXmlReader exception
wrsxmlreader.invalidcp = RowSet의 끝에 도달했습니다. 커서 위치가 부적합합니다.
wrsxmlreader.readxml = readXML: {0}
wrsxmlreader.parseerr = ** 구문분석 오류: {0}, 행: {1}, URI: {2}
#WebRowSetXmlWriter exceptions
wrsxmlwriter.ioex = IOException : {0}
wrsxmlwriter.sqlex = SQLException : {0}
wrsxmlwriter.failedwrite = 값 쓰기를 실패했습니다.
wsrxmlwriter.notproper = 적절한 유형이 아닙니다.
#XmlReaderContentHandler exceptions
xmlrch.errmap = 맵을 설정하는 중 오류 발생: {0}
xmlrch.errmetadata = 메타데이터를 설정하는 중 오류 발생: {0}
xmlrch.errinsertval = 값을 삽입하는 중 오류 발생: {0}
xmlrch.errconstr = 행을 생성하는 중 오류 발생: {0}
xmlrch.errdel = 행을 삭제하는 중 오류 발생: {0}
xmlrch.errinsert = insert 행을 생성하는 중 오류 발생: {0}
xmlrch.errinsdel = insdel 행을 생성하는 중 오류 발생: {0}
xmlrch.errupdate = update 행을 생성하는 중 오류 발생: {0}
xmlrch.errupdrow = 행을 업데이트하는 중 오류 발생: {0}
xmlrch.chars = 문자:
xmlrch.badvalue = 잘못된 값: 널일 수 없는 속성입니다.
xmlrch.badvalue1 = 잘못된 값: 널일 수 없는 메타데이터입니다.
xmlrch.warning = ** 경고: {0}, 행: {1}, URI: {2}
#RIOptimisticProvider Exceptions
riop.locking = 분류 잠금이 지원되지 않습니다.
#RIXMLProvider exceptions
rixml.unsupp = RIXMLProvider에서 지원되지 않습니다.

View file

@ -0,0 +1,169 @@
#
# Copyright (c) 2005, 2024, 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.
#
# CacheRowSetImpl exceptions
cachedrowsetimpl.populate = Objeto ResultSet inválido fornecido para preencher o método
cachedrowsetimpl.invalidp = Fornecedor de persistências inválido gerado
cachedrowsetimpl.nullhash = Não é possível instanciar a instância CachedRowSetImpl. Hashtable Nulo fornecido ao construtor
cachedrowsetimpl.invalidop = Operação inválida durante a inserção de linha
cachedrowsetimpl.accfailed = Falha em acceptChanges
cachedrowsetimpl.invalidcp = Posição inválida do cursor
cachedrowsetimpl.illegalop = Operação inválida em linha não inserida
cachedrowsetimpl.clonefail = Falha ao clonar: {0}
cachedrowsetimpl.invalidcol = Índice de coluna inválido
cachedrowsetimpl.invalcolnm = Nome de coluna inválido
cachedrowsetimpl.boolfail = Falha em getBoolen no valor ( {0} ) na coluna {1}
cachedrowsetimpl.bytefail = Falha em getByte no valor ( {0} ) na coluna {1}
cachedrowsetimpl.shortfail = Falha em getShort no valor ( {0} ) na coluna {1}
cachedrowsetimpl.intfail = Falha em getInt no valor ( {0} ) na coluna {1}
cachedrowsetimpl.longfail = Falha em getLong no valor ( {0} ) na coluna {1}
cachedrowsetimpl.floatfail = Falha em getFloat no valor ( {0} ) na coluna {1}
cachedrowsetimpl.doublefail = Falha em getDouble no valor ( {0} ) na coluna {1}
cachedrowsetimpl.dtypemismt = Tipo de Dados Incompatível
cachedrowsetimpl.datefail = Falha em getDate no valor ( {0} ) na coluna {1} sem conversão disponível
cachedrowsetimpl.timefail = Falha em getTime no valor ( {0} ) na coluna {1} sem conversão disponível
cachedrowsetimpl.posupdate = Atualizações posicionadas não suportadas
cachedrowsetimpl.unableins = Não é possível instanciar : {0}
cachedrowsetimpl.beforefirst = beforeFirst : Operação do cursor inválida
cachedrowsetimpl.first = First : Operação inválida do cursor
cachedrowsetimpl.last = last : TYPE_FORWARD_ONLY
cachedrowsetimpl.absolute = absolute : Posição inválida do cursor
cachedrowsetimpl.relative = relative : Posição inválida do cursor
cachedrowsetimpl.asciistream = falha na leitura do fluxo ascii
cachedrowsetimpl.binstream = falha na leitura do fluxo binário
cachedrowsetimpl.failedins = Falha ao inserir a linha
cachedrowsetimpl.updateins = updateRow chamado durante a inserção de linha
cachedrowsetimpl.movetoins = moveToInsertRow : CONCUR_READ_ONLY
cachedrowsetimpl.movetoins1 = moveToInsertRow : sem metadados
cachedrowsetimpl.movetoins2 = moveToInsertRow : número de colunas inválido
cachedrowsetimpl.tablename = O nome da tabela não pode ser nulo
cachedrowsetimpl.keycols = Colunas de chaves inválidas
cachedrowsetimpl.opnotsupp = Operação não suportada pelo Banco de Dados
cachedrowsetimpl.matchcols = As colunas correspondentes não são iguais às colunas definidas
cachedrowsetimpl.setmatchcols = Definir Colunas correspondentes antes de obtê-las
cachedrowsetimpl.matchcols1 = As colunas correspondentes devem ser maior do que 0
cachedrowsetimpl.matchcols2 = As colunas correspondentes devem ser strings vazias ou nulas
cachedrowsetimpl.unsetmatch = As colunas não definidas não são iguais às colunas definidas
cachedrowsetimpl.unsetmatch1 = Usar o nome da coluna como argumento para unsetMatchColumn
cachedrowsetimpl.unsetmatch2 = Usar o ID da coluna como argumento para unsetMatchColumn
cachedrowsetimpl.numrows = O número de linhas é menor do que zero ou menor do que o tamanho obtido
cachedrowsetimpl.startpos = A posição de início não pode ser negativa
cachedrowsetimpl.nextpage = Preencher dados antes de chamar
cachedrowsetimpl.pagesize = O tamanho da página não pode ser menor do que zero
cachedrowsetimpl.pagesize1 = O tamanho da página não pode ser maior do que maxRows
cachedrowsetimpl.fwdonly = ResultSet é somente para frente
cachedrowsetimpl.type = O tipo é : {0}
cachedrowsetimpl.opnotysupp = Operação ainda não suportada
cachedrowsetimpl.featnotsupp = Recurso não suportado
# WebRowSetImpl exceptions
webrowsetimpl.nullhash = Não é possível instanciar a instância WebRowSetImpl. Hashtable nulo fornecido ao construtor
webrowsetimpl.invalidwr = Gravador inválido
webrowsetimpl.invalidrd = Leitor inválido
#FilteredRowSetImpl exceptions
filteredrowsetimpl.relative = relative : Operação inválida do cursor
filteredrowsetimpl.absolute = absolute : Operação inválida do cursor
filteredrowsetimpl.notallowed = Este valor não é permitido no filtro
#JoinRowSetImpl exceptions
joinrowsetimpl.notinstance = Não é uma instância do conjunto de linhas
joinrowsetimpl.matchnotset = Coluna Correspondente não definida para junção
joinrowsetimpl.numnotequal = Número de elementos no conjunto de linhas diferente da coluna correspondente
joinrowsetimpl.notdefined = Não é um tipo definido de junção
joinrowsetimpl.notsupported = Este tipo de junção não é suportada
joinrowsetimpl.initerror = Erro de inicialização do JoinRowSet
joinrowsetimpl.genericerr = Erro inicial de joinrowset genérico
joinrowsetimpl.emptyrowset = O conjunto de linha vazio não pode ser adicionado a este JoinRowSet
#JdbcRowSetImpl exceptions
jdbcrowsetimpl.invalstate = Estado inválido
jdbcrowsetimpl.connect = Não é possível conectar JdbcRowSet (connect) a JNDI
jdbcrowsetimpl.paramtype = Não é possível deduzir o tipo de parâmetro
jdbcrowsetimpl.matchcols = As Colunas Correspondentes não são iguais às colunas definidas
jdbcrowsetimpl.setmatchcols = Definir as colunas correspondentes antes de obtê-las
jdbcrowsetimpl.matchcols1 = As colunas correspondentes devem ser maior do que 0
jdbcrowsetimpl.matchcols2 = As colunas correspondentes não podem ser strings vazias ou nulas
jdbcrowsetimpl.unsetmatch = As colunas não definidas não são iguais às colunas definidas
jdbcrowsetimpl.usecolname = Usar o nome da coluna como argumento para unsetMatchColumn
jdbcrowsetimpl.usecolid = Usar o ID da coluna como argumento para unsetMatchColumn
jdbcrowsetimpl.resnotupd = ResultSet não é atualizável
jdbcrowsetimpl.opnotysupp = Operação ainda não suportada
jdbcrowsetimpl.featnotsupp = Recurso não suportado
#CachedRowSetReader exceptions
crsreader.connect = (JNDI) Não é possível conectar
crsreader.paramtype = Não é possível deduzir o tipo de parâmetro
crsreader.connecterr = Erro Interno no RowSetReader: sem conexão ou comando
crsreader.datedetected = Data Detectada
crsreader.caldetected = Calendário Detectado
#CachedRowSetWriter exceptions
crswriter.connect = Não é possível obter a conexão
crswriter.tname = writeData não pode determinar o nome da tabela
crswriter.params1 = Valor de params1 : {0}
crswriter.params2 = Valor de params2 : {0}
crswriter.conflictsno = conflitos durante a sincronização
#InsertRow exceptions
insertrow.novalue = Nenhum valor foi inserido
#SyncResolverImpl exceptions
syncrsimpl.indexval = Valor de índice fora da faixa
syncrsimpl.noconflict = Está coluna não está em conflito
syncrsimpl.syncnotpos = A sincronização não é possível
syncrsimpl.valtores = O valor a ser decidido pode estar no banco de dados ou no conjunto de linhas armazenado no cache
#WebRowSetXmlReader exception
wrsxmlreader.invalidcp = Fim de RowSet atingido. Posição inválida do cursor
wrsxmlreader.readxml = readXML : {0}
wrsxmlreader.parseerr = ** Erro de Parsing : {0} , linha : {1} , uri : {2}
#WebRowSetXmlWriter exceptions
wrsxmlwriter.ioex = IOException : {0}
wrsxmlwriter.sqlex = SQLException : {0}
wrsxmlwriter.failedwrite = Falha ao gravar o valor
wsrxmlwriter.notproper = Não é um tipo adequado
#XmlReaderContentHandler exceptions
xmlrch.errmap = Erro ao definir o Mapa : {0}
xmlrch.errmetadata = Erro ao definir metadados : {0}
xmlrch.errinsertval = Erro ao inserir valores : {0}
xmlrch.errconstr = Erro ao construir a linha : {0}
xmlrch.errdel = Erro ao excluir a linha : {0}
xmlrch.errinsert = Erro ao construir a linha de inserção : {0}
xmlrch.errinsdel = Erro ao construir a linha insdel : {0}
xmlrch.errupdate = Erro ao construir a linha de atualização : {0}
xmlrch.errupdrow = Erro ao atualizar a linha : {0}
xmlrch.chars = caracteres :
xmlrch.badvalue = Valor incorreto ; propriedade não anulável
xmlrch.badvalue1 = Valor incorreto ; metadado não anulável
xmlrch.warning = ** Advertência : {0} , linha : {1} , uri : {2}
#RIOptimisticProvider Exceptions
riop.locking = O bloqueio de classificação não é suportado
#RIXMLProvider exceptions
rixml.unsupp = Não suportado com RIXMLProvider

View file

@ -0,0 +1,169 @@
#
# Copyright (c) 2005, 2024, 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.
#
# CacheRowSetImpl exceptions
cachedrowsetimpl.populate = Ifyllningsmetoden fick ett ogiltigt ResultSet-objekt
cachedrowsetimpl.invalidp = En ogiltig beständig leverantör genererades
cachedrowsetimpl.nullhash = Kan inte instansiera CachedRowSetImpl. Null-hashtabell skickades till konstruktor
cachedrowsetimpl.invalidop = En ogiltig åtgärd utfördes på infogad rad
cachedrowsetimpl.accfailed = acceptChanges utfördes inte
cachedrowsetimpl.invalidcp = Ogiltigt markörläge
cachedrowsetimpl.illegalop = En otillåten åtgärd utfördes på en icke infogad rad
cachedrowsetimpl.clonefail = Kloningen utfördes inte: {0}
cachedrowsetimpl.invalidcol = Ogiltigt kolumnindex
cachedrowsetimpl.invalcolnm = Ogiltigt kolumnnamn
cachedrowsetimpl.boolfail = getBoolen utfördes inte för värdet ({0}) i kolumnen {1}
cachedrowsetimpl.bytefail = getByte utfördes inte för värdet ({0}) i kolumnen {1}
cachedrowsetimpl.shortfail = getShort utfördes inte för värdet ({0}) i kolumnen {1}
cachedrowsetimpl.intfail = getInt utfördes inte för värdet ({0}) i kolumnen {1}
cachedrowsetimpl.longfail = getLong utfördes inte för värdet ({0}) i kolumnen {1}
cachedrowsetimpl.floatfail = getFloat utfördes inte för värdet ({0}) i kolumnen {1}
cachedrowsetimpl.doublefail = getDouble utfördes inte för värdet ({0}) i kolumnen {1}
cachedrowsetimpl.dtypemismt = Felmatchad datatyp
cachedrowsetimpl.datefail = getDate utfördes inte för värdet ({0}) i kolumnen {1}, ingen konvertering tillgänglig
cachedrowsetimpl.timefail = getTime utfördes inte för värdet ({0}) i kolumnen {1}, ingen konvertering tillgänglig
cachedrowsetimpl.posupdate = Det finns inte stöd för positionerad uppdatering
cachedrowsetimpl.unableins = Kan inte instansiera {0}
cachedrowsetimpl.beforefirst = beforeFirst: Ogiltig marköråtgärd
cachedrowsetimpl.first = First: Ogiltig marköråtgärd
cachedrowsetimpl.last = last: TYPE_FORWARD_ONLY
cachedrowsetimpl.absolute = absolute: Markörpositionen är ogiltig
cachedrowsetimpl.relative = relative: Markörpositionen är ogiltig
cachedrowsetimpl.asciistream = kunde inte läsa ASCII-strömmen
cachedrowsetimpl.binstream = kunde inte läsa den binära strömmen
cachedrowsetimpl.failedins = Kunde inte infoga rad
cachedrowsetimpl.updateins = updateRow anropades från infogad rad
cachedrowsetimpl.movetoins = moveToInsertRow : CONCUR_READ_ONLY
cachedrowsetimpl.movetoins1 = moveToInsertRow: inga metadata
cachedrowsetimpl.movetoins2 = moveToInsertRow: ogiltigt antal kolumner
cachedrowsetimpl.tablename = Tabellnamnet kan inte vara null
cachedrowsetimpl.keycols = Ogiltiga nyckelkolumner
cachedrowsetimpl.opnotsupp = Databasen har inte stöd för denna åtgärd
cachedrowsetimpl.matchcols = Matchningskolumnerna är inte samma som de som ställts in
cachedrowsetimpl.setmatchcols = Ställ in matchningskolumnerna innan du hämtar dem
cachedrowsetimpl.matchcols1 = Matchningskolumnerna måste vara större än 0
cachedrowsetimpl.matchcols2 = Matchningskolumnerna måste vara tomma eller en null-sträng
cachedrowsetimpl.unsetmatch = Kolumnerna som återställs är inte samma som de som ställts in
cachedrowsetimpl.unsetmatch1 = Använd kolumnnamn som argument för unsetMatchColumn
cachedrowsetimpl.unsetmatch2 = Använd kolumn-id som argument för unsetMatchColumn
cachedrowsetimpl.numrows = Antalet rader understiger noll eller är mindre än hämtningsstorleken
cachedrowsetimpl.startpos = Startpositionen får inte vara negativ
cachedrowsetimpl.nextpage = Fyll i data innan anrop
cachedrowsetimpl.pagesize = Sidstorleken får inte understiga noll
cachedrowsetimpl.pagesize1 = Sidstorleken får inte överstiga maxRows
cachedrowsetimpl.fwdonly = ResultSet kan endast gå framåt
cachedrowsetimpl.type = Typ: {0}
cachedrowsetimpl.opnotysupp = Det finns ännu inget stöd för denna åtgärd
cachedrowsetimpl.featnotsupp = Funktionen stöds inte
# WebRowSetImpl exceptions
webrowsetimpl.nullhash = Kan inte instansiera WebRowSetImpl. Null-hashtabell skickades till konstruktor.
webrowsetimpl.invalidwr = Ogiltig skrivfunktion
webrowsetimpl.invalidrd = Ogiltig läsare
#FilteredRowSetImpl exceptions
filteredrowsetimpl.relative = relative: Ogiltig marköråtgärd
filteredrowsetimpl.absolute = absolute: Ogiltig marköråtgärd
filteredrowsetimpl.notallowed = Detta värde kommer att filtreras bort
#JoinRowSetImpl exceptions
joinrowsetimpl.notinstance = Detta är inte en instans av raduppsättning
joinrowsetimpl.matchnotset = Matchningskolumnen är inte inställd på koppling
joinrowsetimpl.numnotequal = Antal objekt i raduppsättning stämmer inte med matchningskolumnens
joinrowsetimpl.notdefined = Detta är inte någon definierad kopplingstyp
joinrowsetimpl.notsupported = Det finns inget stöd för denna kopplingstyp
joinrowsetimpl.initerror = Initieringsfel för JoinRowSet
joinrowsetimpl.genericerr = Allmänt initieringsfel för JoinRowSet
joinrowsetimpl.emptyrowset = Tomma raduppsättningar kan inte läggas till i denna JoinRowSet
#JdbcRowSetImpl exceptions
jdbcrowsetimpl.invalstate = Ogiltigt tillstånd
jdbcrowsetimpl.connect = JdbcRowSet (anslut) JNDI kan inte anslutas
jdbcrowsetimpl.paramtype = Kan inte härleda parametertypen
jdbcrowsetimpl.matchcols = Matchningskolumnerna är inte samma som de som ställts in
jdbcrowsetimpl.setmatchcols = Ställ in matchningskolumnerna innan du hämtar dem
jdbcrowsetimpl.matchcols1 = Matchningskolumnerna måste vara större än 0
jdbcrowsetimpl.matchcols2 = Matchningskolumnerna kan inte vara en null-sträng eller tomma
jdbcrowsetimpl.unsetmatch = Kolumnerna som återställs är inte samma som de som ställts in
jdbcrowsetimpl.usecolname = Använd kolumnnamn som argument för unsetMatchColumn
jdbcrowsetimpl.usecolid = Använd kolumn-id som argument för unsetMatchColumn
jdbcrowsetimpl.resnotupd = ResultSet är inte uppdateringsbart
jdbcrowsetimpl.opnotysupp = Det finns ännu inget stöd för denna åtgärd
jdbcrowsetimpl.featnotsupp = Funktionen stöds inte
#CachedRowSetReader exceptions
crsreader.connect = (JNDI) kan inte anslutas
crsreader.paramtype = Kan inte härleda parametertypen
crsreader.connecterr = Internt fel i RowSetReader: ingen anslutning eller inget kommando
crsreader.datedetected = Ett datum har identifierats
crsreader.caldetected = En kalender har identifierats
#CachedRowSetWriter exceptions
crswriter.connect = Kan inte upprätta anslutning
crswriter.tname = writeData kan inte fastställa tabellnamnet
crswriter.params1 = Parametervärde1: {0}
crswriter.params2 = Parametervärde2: {0}
crswriter.conflictsno = orsakar konflikt vid synkronisering
#InsertRow exceptions
insertrow.novalue = Inget värde har infogats
#SyncResolverImpl exceptions
syncrsimpl.indexval = Indexvärdet ligger utanför intervallet
syncrsimpl.noconflict = Kolumnen orsakar ingen konflikt
syncrsimpl.syncnotpos = Synkronisering är inte möjlig
syncrsimpl.valtores = Värdet som ska fastställas kan antingen finnas i databasen eller i cachedrowset
#WebRowSetXmlReader exception
wrsxmlreader.invalidcp = Slutet på RowSet har nåtts. Markörpositionen är ogiltig.
wrsxmlreader.readxml = readXML: {0}
wrsxmlreader.parseerr = ** Tolkningsfel: {0}, rad: {1}, URI: {2}
#WebRowSetXmlWriter exceptions
wrsxmlwriter.ioex = IOException: {0}
wrsxmlwriter.sqlex = SQLException: {0}
wrsxmlwriter.failedwrite = Kunde inte skriva värdet
wsrxmlwriter.notproper = Ingen riktig typ
#XmlReaderContentHandler exceptions
xmlrch.errmap = Ett fel inträffade vid inställning av mappning: {0}
xmlrch.errmetadata = Ett fel inträffade vid inställning av metadata: {0}
xmlrch.errinsertval = Ett fel inträffade vid infogning av värden: {0}
xmlrch.errconstr = Ett fel inträffade vid konstruktion av rad: {0}
xmlrch.errdel = Ett fel inträffade vid borttagning av rad: {0}
xmlrch.errinsert = Ett fel inträffade vid konstruktion av infogad rad: {0}
xmlrch.errinsdel = Ett fel inträffade vid konstruktion av insdel-rad: {0}
xmlrch.errupdate = Ett fel inträffade vid konstruktion av uppdateringsrad: {0}
xmlrch.errupdrow = Ett fel inträffade vid uppdatering av rad: {0}
xmlrch.chars = tecken:
xmlrch.badvalue = Felaktigt värde; egenskapen får inte ha värdet null
xmlrch.badvalue1 = Felaktigt värde; metadata får inte ha värdet null
xmlrch.warning = ** Varning! {0}, rad: {1}, URI: {2}
#RIOptimisticProvider Exceptions
riop.locking = Det finns inte stöd för denna låsningsklassificering
#RIXMLProvider exceptions
rixml.unsupp = RIXMLProvider har inte stöd för detta

View file

@ -0,0 +1,169 @@
#
# Copyright (c) 2005, 2024, 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.
#
# CacheRowSetImpl exceptions
cachedrowsetimpl.populate = 提供给填充方法的 ResultSet 对象无效
cachedrowsetimpl.invalidp = 生成的持久性提供方无效
cachedrowsetimpl.nullhash = 无法实例化 CachedRowSetImpl 实例。提供给构造器的 Hashtable 为空值
cachedrowsetimpl.invalidop = 对插入行执行的操作无效
cachedrowsetimpl.accfailed = acceptChanges 失败
cachedrowsetimpl.invalidcp = 光标位置无效
cachedrowsetimpl.illegalop = 对非插入行执行的操作非法
cachedrowsetimpl.clonefail = 克隆失败: {0}
cachedrowsetimpl.invalidcol = 列索引无效
cachedrowsetimpl.invalcolnm = 列名无效
cachedrowsetimpl.boolfail = 对列 {1} 中的值 ({0}) 执行 getBoolen 失败
cachedrowsetimpl.bytefail = 对列 {1} 中的值 ({0}) 执行 getByte 失败
cachedrowsetimpl.shortfail = 对列 {1} 中的值 ({0}) 执行 getShort 失败
cachedrowsetimpl.intfail = 对列 {1} 中的值 ({0}) 执行 getInt 失败
cachedrowsetimpl.longfail = 对列 {1} 中的值 ({0}) 执行 getLong 失败
cachedrowsetimpl.floatfail = 对列 {1} 中的值 ({0}) 执行 getFloat 失败
cachedrowsetimpl.doublefail = 对列 {1} 中的值 ({0}) 执行 getDouble 失败
cachedrowsetimpl.dtypemismt = 数据类型不匹配
cachedrowsetimpl.datefail = 对列 {1} 中的值 ({0}) 执行 getDate 失败, 无可用转换
cachedrowsetimpl.timefail = 对列 {1} 中的值 ({0}) 执行 getTime 失败, 无可用转换
cachedrowsetimpl.posupdate = 不支持定位更新
cachedrowsetimpl.unableins = 无法实例化: {0}
cachedrowsetimpl.beforefirst = beforeFirst: 光标操作无效
cachedrowsetimpl.first = First: 光标操作无效
cachedrowsetimpl.last = last: TYPE_FORWARD_ONLY
cachedrowsetimpl.absolute = absolute: 光标位置无效
cachedrowsetimpl.relative = relative: 光标位置无效
cachedrowsetimpl.asciistream = 未能读取 ASCII 流
cachedrowsetimpl.binstream = 未能读取二进制流
cachedrowsetimpl.failedins = 对插入行执行操作失败
cachedrowsetimpl.updateins = 为插入行调用 updateRow
cachedrowsetimpl.movetoins = moveToInsertRow: CONCUR_READ_ONLY
cachedrowsetimpl.movetoins1 = moveToInsertRow: 无元数据
cachedrowsetimpl.movetoins2 = moveToInsertRow: 列数无效
cachedrowsetimpl.tablename = 表名不能为空值
cachedrowsetimpl.keycols = 关键字列无效
cachedrowsetimpl.opnotsupp = 操作不受数据库支持
cachedrowsetimpl.matchcols = 匹配列与设置的那些匹配列不同
cachedrowsetimpl.setmatchcols = 在获取匹配列之前先设置匹配列
cachedrowsetimpl.matchcols1 = 匹配列数应当大于 0
cachedrowsetimpl.matchcols2 = 匹配列数应当为空或空值字符串
cachedrowsetimpl.unsetmatch = 要取消设置的列与设置的列不同
cachedrowsetimpl.unsetmatch1 = 使用列名作为 unsetMatchColumn 的参数
cachedrowsetimpl.unsetmatch2 = 使用列 ID 作为 unsetMatchColumn 的参数
cachedrowsetimpl.numrows = 行数小于零或小于要提取的行数
cachedrowsetimpl.startpos = 起始位置不能为负数
cachedrowsetimpl.nextpage = 在调用之前先填充数据
cachedrowsetimpl.pagesize = 页面大小不能小于零
cachedrowsetimpl.pagesize1 = 页面大小不能大于 maxRows
cachedrowsetimpl.fwdonly = ResultSet 的类型为仅向前类型
cachedrowsetimpl.type = 类型为: {0}
cachedrowsetimpl.opnotysupp = 尚不支持该操作
cachedrowsetimpl.featnotsupp = 尚不支持该功能
# WebRowSetImpl exceptions
webrowsetimpl.nullhash = 无法实例化 WebRowSetImpl 实例。提供给构造器的 Hashtable 为空值
webrowsetimpl.invalidwr = 写进程无效
webrowsetimpl.invalidrd = 读进程无效
#FilteredRowSetImpl exceptions
filteredrowsetimpl.relative = relative: 光标操作无效
filteredrowsetimpl.absolute = absolute: 光标操作无效
filteredrowsetimpl.notallowed = 不允许此值通过筛选器
#JoinRowSetImpl exceptions
joinrowsetimpl.notinstance = 不是 RowSet 的实例
joinrowsetimpl.matchnotset = 未设置匹配列以进行联接
joinrowsetimpl.numnotequal = RowSet 中的元素个数不等于匹配列数
joinrowsetimpl.notdefined = 这不是定义的联接类型
joinrowsetimpl.notsupported = 不支持此联接类型
joinrowsetimpl.initerror = JoinRowSet 初始化错误
joinrowsetimpl.genericerr = 一般 joinrowset 初始错误
joinrowsetimpl.emptyrowset = 无法将空 RowSet 添加到此 JoinRowSet
#JdbcRowSetImpl exceptions
jdbcrowsetimpl.invalstate = 状态无效
jdbcrowsetimpl.connect = JdbcRowSet (连接) JNDI 无法连接
jdbcrowsetimpl.paramtype = 无法推断参数类型
jdbcrowsetimpl.matchcols = 匹配列与设置的那些匹配列不同
jdbcrowsetimpl.setmatchcols = 在获取匹配列之前先设置匹配列
jdbcrowsetimpl.matchcols1 = 匹配列数应当大于 0
jdbcrowsetimpl.matchcols2 = 匹配列不能为空值或空字符串
jdbcrowsetimpl.unsetmatch = 要取消设置的列与设置的列不同
jdbcrowsetimpl.usecolname = 使用列名作为 unsetMatchColumn 的参数
jdbcrowsetimpl.usecolid = 使用列 ID 作为 unsetMatchColumn 的参数
jdbcrowsetimpl.resnotupd = ResultSet 不可更新
jdbcrowsetimpl.opnotysupp = 尚不支持该操作
jdbcrowsetimpl.featnotsupp = 尚不支持该功能
#CachedRowSetReader exceptions
crsreader.connect = (JNDI) 无法连接
crsreader.paramtype = 无法推断参数类型
crsreader.connecterr = RowSetReader 中出现内部错误: 无连接或命令
crsreader.datedetected = 检测到日期
crsreader.caldetected = 检测到日历
#CachedRowSetWriter exceptions
crswriter.connect = 无法获取连接
crswriter.tname = writeData 无法确定表名
crswriter.params1 = params1 的值: {0}
crswriter.params2 = params2 的值: {0}
crswriter.conflictsno = 同步时发生冲突
#InsertRow exceptions
insertrow.novalue = 尚未插入任何值
#SyncResolverImpl exceptions
syncrsimpl.indexval = 索引值超出范围
syncrsimpl.noconflict = 此列不冲突
syncrsimpl.syncnotpos = 不能同步
syncrsimpl.valtores = 要解析的值可以在数据库中, 也可以在 CachedRowSet 中
#WebRowSetXmlReader exception
wrsxmlreader.invalidcp = 已到达 RowSet 的结尾。光标位置无效
wrsxmlreader.readxml = readXML: {0}
wrsxmlreader.parseerr = ** 解析错误: {0}, 行: {1}, URI: {2}
#WebRowSetXmlWriter exceptions
wrsxmlwriter.ioex = IOException: {0}
wrsxmlwriter.sqlex = SQLException: {0}
wrsxmlwriter.failedwrite = 无法写入值
wsrxmlwriter.notproper = 类型不正确
#XmlReaderContentHandler exceptions
xmlrch.errmap = 设置映射时出错: {0}
xmlrch.errmetadata = 设置元数据时出错: {0}
xmlrch.errinsertval = 插入值时出错: {0}
xmlrch.errconstr = 构造行时出错: {0}
xmlrch.errdel = 删除行时出错: {0}
xmlrch.errinsert = 构造插入行时出错: {0}
xmlrch.errinsdel = 构造 insdel 行时出错: {0}
xmlrch.errupdate = 构造更新行时出错: {0}
xmlrch.errupdrow = 更新行时出错: {0}
xmlrch.chars = 字符:
xmlrch.badvalue = 值错误; 属性不可为空值
xmlrch.badvalue1 = 值错误; 元数据不可为空值
xmlrch.warning = ** 警告: {0}, 行: {1}, URI: {2}
#RIOptimisticProvider Exceptions
riop.locking = 不支持锁定分类
#RIXMLProvider exceptions
rixml.unsupp = 不支持 RIXMLProvider

View file

@ -0,0 +1,169 @@
#
# Copyright (c) 2005, 2024, 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.
#
# CacheRowSetImpl exceptions
cachedrowsetimpl.populate = 為植入方法提供的 ResultSet 物件無效
cachedrowsetimpl.invalidp = 產生的持續性提供者無效
cachedrowsetimpl.nullhash = 無法建立 CachedRowSetImpl 執行處理。為建構子提供的 Hashtable 為空值
cachedrowsetimpl.invalidop = 插入列時的作業無效
cachedrowsetimpl.accfailed = acceptChanges 失敗
cachedrowsetimpl.invalidcp = 游標位置無效
cachedrowsetimpl.illegalop = 非插入列上存在無效作業
cachedrowsetimpl.clonefail = 複製失敗: {0}
cachedrowsetimpl.invalidcol = 欄索引無效
cachedrowsetimpl.invalcolnm = 欄名無效
cachedrowsetimpl.boolfail = 對欄 {1} 中的值 ( {0} ) 執行 getBoolen 失敗
cachedrowsetimpl.bytefail = 對欄 {1} 中的值 ( {0} ) 執行 getByte 失敗
cachedrowsetimpl.shortfail = 對欄 {1} 中的值 ( {0} ) 執行 getShort 失敗
cachedrowsetimpl.intfail = 對欄 {1} 中的值 ( {0} ) 執行 getInt 失敗
cachedrowsetimpl.longfail = 對欄 {1} 中的值 ( {0} ) 執行 getLong 失敗
cachedrowsetimpl.floatfail = 對欄 {1} 中的值 ( {0} ) 執行 getFloat 失敗
cachedrowsetimpl.doublefail = 對欄 {1} 中的值 ( {0} ) 執行 getDouble 失敗
cachedrowsetimpl.dtypemismt = 資料類型不相符
cachedrowsetimpl.datefail = 對欄 {1} 中的值 ( {0} ) 執行 getDate 失敗,未進行轉換
cachedrowsetimpl.timefail = 對欄 {1} 中的值 ( {0} ) 執行 getTime 失敗,未進行轉換
cachedrowsetimpl.posupdate = 不支援定位的更新
cachedrowsetimpl.unableins = 無法建立: {0}
cachedrowsetimpl.beforefirst = beforeFirst: 游標作業無效
cachedrowsetimpl.first = First: 游標作業無效
cachedrowsetimpl.last = last : TYPE_FORWARD_ONLY
cachedrowsetimpl.absolute = absolute: 游標位置無效
cachedrowsetimpl.relative = relative: 游標位置無效
cachedrowsetimpl.asciistream = 讀取 ascii 串流失敗
cachedrowsetimpl.binstream = 讀取二進位串流失敗
cachedrowsetimpl.failedins = 插入列失敗
cachedrowsetimpl.updateins = 插入列時呼叫 updateRow
cachedrowsetimpl.movetoins = moveToInsertRow: CONCUR_READ_ONLY
cachedrowsetimpl.movetoins1 = moveToInsertRow: 沒有描述資料
cachedrowsetimpl.movetoins2 = moveToInsertRow: 欄數無效
cachedrowsetimpl.tablename = 表格名稱不能為空值
cachedrowsetimpl.keycols = 關鍵欄無效
cachedrowsetimpl.opnotsupp = 資料庫不支援作業
cachedrowsetimpl.matchcols = 匹配欄和設定的欄不同
cachedrowsetimpl.setmatchcols = 在取得匹配欄之前設定它們
cachedrowsetimpl.matchcols1 = 匹配欄應大於 0
cachedrowsetimpl.matchcols2 = 匹配欄應為空白字串或空值字串
cachedrowsetimpl.unsetmatch = 取消設定的欄和設定的欄不同
cachedrowsetimpl.unsetmatch1 = 使用欄名作為 unsetMatchColumn 的引數
cachedrowsetimpl.unsetmatch2 = 使用欄 ID 作為 unsetMatchColumn 的引數
cachedrowsetimpl.numrows = 列數小於零或小於擷取大小
cachedrowsetimpl.startpos = 起始位置不能為負數
cachedrowsetimpl.nextpage = 在呼叫之前植入資料
cachedrowsetimpl.pagesize = 頁面大小不能小於零
cachedrowsetimpl.pagesize1 = 頁面大小不能大於 maxRows
cachedrowsetimpl.fwdonly = ResultSet 只能向前進行
cachedrowsetimpl.type = 類型是: {0}
cachedrowsetimpl.opnotysupp = 尚不支援該作業
cachedrowsetimpl.featnotsupp = 不支援該功能
# WebRowSetImpl exceptions
webrowsetimpl.nullhash = 無法建立 WebRowSetImpl 執行處理。為建構子提供的 Hashtable 為空值
webrowsetimpl.invalidwr = 寫入器無效
webrowsetimpl.invalidrd = 讀取器無效
#FilteredRowSetImpl exceptions
filteredrowsetimpl.relative = relative: 游標作業無效
filteredrowsetimpl.absolute = absolute: 游標作業無效
filteredrowsetimpl.notallowed = 不允許此值通過篩選
#JoinRowSetImpl exceptions
joinrowsetimpl.notinstance = 不是 rowset 的執行處理
joinrowsetimpl.matchnotset = 未設定用於連結的匹配欄
joinrowsetimpl.numnotequal = rowset 中的元素數不等於匹配欄
joinrowsetimpl.notdefined = 這不是連結的已定義類型
joinrowsetimpl.notsupported = 不支援此類連結
joinrowsetimpl.initerror = JoinRowSet 初始化錯誤
joinrowsetimpl.genericerr = 一般的 joinrowset 初始化錯誤
joinrowsetimpl.emptyrowset = 無法將空 rowset 新增至此 JoinRowSet
#JdbcRowSetImpl exceptions
jdbcrowsetimpl.invalstate = 狀態無效
jdbcrowsetimpl.connect = JdbcRowSet (連線) JNDI 無法連線
jdbcrowsetimpl.paramtype = 無法推斷參數類型
jdbcrowsetimpl.matchcols = 匹配欄和設定的欄不同
jdbcrowsetimpl.setmatchcols = 要先設定匹配欄,才能取得它們
jdbcrowsetimpl.matchcols1 = 匹配欄應大於 0
jdbcrowsetimpl.matchcols2 = 匹配欄不能為空白字串或空值字串
jdbcrowsetimpl.unsetmatch = 取消設定的欄和設定的欄不同
jdbcrowsetimpl.usecolname = 使用欄名作為 unsetMatchColumn 的引數
jdbcrowsetimpl.usecolid = 使用欄 ID 作為 unsetMatchColumn 的引數
jdbcrowsetimpl.resnotupd = ResultSet 不可更新
jdbcrowsetimpl.opnotysupp = 尚不支援該作業
jdbcrowsetimpl.featnotsupp = 不支援該功能
#CachedRowSetReader exceptions
crsreader.connect = (JNDI) 無法連線
crsreader.paramtype = 無法推斷參數類型
crsreader.connecterr = RowSetReader 中出現內部錯誤: 無連線或命令
crsreader.datedetected = 偵測到日期
crsreader.caldetected = 偵測到行事曆
#CachedRowSetWriter exceptions
crswriter.connect = 無法取得連線
crswriter.tname = writeData 不能決定表格名稱
crswriter.params1 = params1 的值: {0}
crswriter.params2 = params2 的值: {0}
crswriter.conflictsno = 同步化時發生衝突
#InsertRow exceptions
insertrow.novalue = 尚未插入值
#SyncResolverImpl exceptions
syncrsimpl.indexval = 索引值超出範圍
syncrsimpl.noconflict = 此欄不衝突
syncrsimpl.syncnotpos = 不可能同步化
syncrsimpl.valtores = 要解析的值可位於資料庫或 cachedrowset 中
#WebRowSetXmlReader exception
wrsxmlreader.invalidcp = 已到達 RowSet 結尾。游標位置無效
wrsxmlreader.readxml = readXML: {0}
wrsxmlreader.parseerr = ** 剖析錯誤: {0},行: {1}uri: {2}
#WebRowSetXmlWriter exceptions
wrsxmlwriter.ioex = IOException : {0}
wrsxmlwriter.sqlex = SQLException : {0}
wrsxmlwriter.failedwrite = 寫入值失敗
wsrxmlwriter.notproper = 不是正確類型
#XmlReaderContentHandler exceptions
xmlrch.errmap = 設定對映時發生錯誤: {0}
xmlrch.errmetadata = 設定描述資料時發生錯誤: {0}
xmlrch.errinsertval = 插入值時發生錯誤: {0}
xmlrch.errconstr = 建構列時發生錯誤: {0}
xmlrch.errdel = 刪除列時發生錯誤: {0}
xmlrch.errinsert = 建構插入列時發生錯誤 : {0}
xmlrch.errinsdel = 建構 insdel 列時發生錯誤: {0}
xmlrch.errupdate = 建構更新列時發生錯誤: {0}
xmlrch.errupdrow = 更新列時發生錯誤: {0}
xmlrch.chars = 字元:
xmlrch.badvalue = 錯誤的值; 屬性不能為空值
xmlrch.badvalue1 = 錯誤的值; 描述資料不能為空值
xmlrch.warning = ** 警告: {0},行: {1}uri: {2}
#RIOptimisticProvider Exceptions
riop.locking = 不支援鎖定分類
#RIXMLProvider exceptions
rixml.unsupp = RIXMLProvider 不支援

View file

@ -0,0 +1,293 @@
/*
* Copyright (c) 2003, 2021, 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 com.sun.rowset;
import java.sql.*;
import javax.sql.*;
import java.io.*;
import java.math.*;
import java.util.*;
import java.text.*;
import org.xml.sax.*;
import javax.sql.rowset.*;
import javax.sql.rowset.spi.*;
import com.sun.rowset.providers.*;
import com.sun.rowset.internal.*;
/**
* The standard implementation of the <code>WebRowSet</code> interface. See the interface
* definition for full behavior and implementation requirements.
*
* @author Jonathan Bruce, Amit Handa
*/
public class WebRowSetImpl extends CachedRowSetImpl implements WebRowSet {
/**
* The <code>WebRowSetXmlReader</code> object that this
* <code>WebRowSet</code> object will call when the method
* <code>WebRowSet.readXml</code> is invoked.
*/
private WebRowSetXmlReader xmlReader;
/**
* The <code>WebRowSetXmlWriter</code> object that this
* <code>WebRowSet</code> object will call when the method
* <code>WebRowSet.writeXml</code> is invoked.
*/
private WebRowSetXmlWriter xmlWriter;
/* This stores the cursor position prior to calling the writeXML.
* This variable is used after the write to restore the position
* to the point where the writeXml was called.
*/
private int curPosBfrWrite;
@SuppressWarnings("serial")
private SyncProvider provider;
/**
* Constructs a new <code>WebRowSet</code> object initialized with the
* default values for a <code>CachedRowSet</code> object instance. This
* provides the <code>RIOptimistic</code> provider to deliver
* synchronization capabilities to relational datastores and a default
* <code>WebRowSetXmlReader</code> object and a default
* <code>WebRowSetXmlWriter</code> object to enable XML output
* capabilities.
*
* @throws SQLException if an error occurs in configuring the default
* synchronization providers for relational and XML providers.
*/
public WebRowSetImpl() throws SQLException {
super();
// %%%
// Needs to use to SPI XmlReader,XmlWriters
//
xmlReader = new WebRowSetXmlReader();
xmlWriter = new WebRowSetXmlWriter();
}
/**
* Constructs a new <code>WebRowSet</code> object initialized with the
* synchronization SPI provider properties as specified in the <code>Hashtable</code>. If
* this hashtable is empty or is <code>null</code> the default constructor is invoked.
*
* @throws SQLException if an error occurs in configuring the specified
* synchronization providers for the relational and XML providers; or
* if the Hashtanle is null
*/
@SuppressWarnings("rawtypes")
public WebRowSetImpl(Hashtable env) throws SQLException {
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
if ( env == null) {
throw new SQLException(resBundle.handleGetObject("webrowsetimpl.nullhash").toString());
}
String providerName =
(String)env.get(javax.sql.rowset.spi.SyncFactory.ROWSET_SYNC_PROVIDER);
// set the Reader, this maybe overridden latter
provider = SyncFactory.getInstance(providerName);
// xmlReader = provider.getRowSetReader();
// xmlWriter = provider.getRowSetWriter();
}
/**
* Populates this <code>WebRowSet</code> object with the
* data in the given <code>ResultSet</code> object and writes itself
* to the given <code>java.io.Writer</code> object in XML format.
* This includes the rowset's data, properties, and metadata.
*
* @throws SQLException if an error occurs writing out the rowset
* contents to XML
*/
public void writeXml(ResultSet rs, java.io.Writer writer)
throws SQLException {
// WebRowSetImpl wrs = new WebRowSetImpl();
this.populate(rs);
// Store the cursor position before writing
curPosBfrWrite = this.getRow();
this.writeXml(writer);
}
/**
* Writes this <code>WebRowSet</code> object to the given
* <code>java.io.Writer</code> object in XML format. This
* includes the rowset's data, properties, and metadata.
*
* @throws SQLException if an error occurs writing out the rowset
* contents to XML
*/
public void writeXml(java.io.Writer writer) throws SQLException {
// %%%
// This will change to a XmlReader, which over-rides the default
// Xml that is used when a WRS is instantiated.
// WebRowSetXmlWriter xmlWriter = getXmlWriter();
if (xmlWriter != null) {
// Store the cursor position before writing
curPosBfrWrite = this.getRow();
xmlWriter.writeXML(this, writer);
} else {
throw new SQLException(resBundle.handleGetObject("webrowsetimpl.invalidwr").toString());
}
}
/**
* Reads this <code>WebRowSet</code> object in its XML format.
*
* @throws SQLException if a database access error occurs
*/
public void readXml(java.io.Reader reader) throws SQLException {
// %%%
// This will change to a XmlReader, which over-rides the default
// Xml that is used when a WRS is instantiated.
//WebRowSetXmlReader xmlReader = getXmlReader();
try {
if (reader != null) {
xmlReader.readXML(this, reader);
// Position is before the first row
// The cursor position is to be stored while serializng
// and deserializing the WebRowSet Object.
if(curPosBfrWrite == 0) {
this.beforeFirst();
}
// Return the position back to place prior to callin writeXml
else {
this.absolute(curPosBfrWrite);
}
} else {
throw new SQLException(resBundle.handleGetObject("webrowsetimpl.invalidrd").toString());
}
} catch (Exception e) {
throw new SQLException(e.getMessage());
}
}
// Stream based methods
/**
* Reads a stream based XML input to populate this <code>WebRowSet</code>
* object.
*
* @throws SQLException if a data source access error occurs
* @throws IOException if a IO exception occurs
*/
public void readXml(java.io.InputStream iStream) throws SQLException, IOException {
if (iStream != null) {
xmlReader.readXML(this, iStream);
// Position is before the first row
// The cursor position is to be stored while serializng
// and deserializing the WebRowSet Object.
if(curPosBfrWrite == 0) {
this.beforeFirst();
}
// Return the position back to place prior to callin writeXml
else {
this.absolute(curPosBfrWrite);
}
} else {
throw new SQLException(resBundle.handleGetObject("webrowsetimpl.invalidrd").toString());
}
}
/**
* Writes this <code>WebRowSet</code> object to the given <code> OutputStream</code>
* object in XML format.
* Creates an output stream of the internal state and contents of a
* <code>WebRowSet</code> for XML proceessing
*
* @throws SQLException if a datasource access error occurs
* @throws IOException if an IO exception occurs
*/
public void writeXml(java.io.OutputStream oStream) throws SQLException, IOException {
if (xmlWriter != null) {
// Store the cursor position before writing
curPosBfrWrite = this.getRow();
xmlWriter.writeXML(this, oStream);
} else {
throw new SQLException(resBundle.handleGetObject("webrowsetimpl.invalidwr").toString());
}
}
/**
* Populates this <code>WebRowSet</code> object with the
* data in the given <code>ResultSet</code> object and writes itself
* to the given <code>java.io.OutputStream</code> object in XML format.
* This includes the rowset's data, properties, and metadata.
*
* @throws SQLException if a datasource access error occurs
* @throws IOException if an IO exception occurs
*/
public void writeXml(ResultSet rs, java.io.OutputStream oStream) throws SQLException, IOException {
this.populate(rs);
// Store the cursor position before writing
curPosBfrWrite = this.getRow();
this.writeXml(oStream);
}
/**
* This method re populates the resBundle
* during the deserialization process
*
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID = -8771775154092422943L;
}

View file

@ -0,0 +1,102 @@
/*
* Copyright (c) 2003, 2021, 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 com.sun.rowset.internal;
import java.sql.*;
import java.io.*;
import java.util.Arrays;
/**
* The abstract base class from which the classes <code>Row</code>
* The class <code>BaseRow</code> stores
* a row's original values as an array of <code>Object</code>
* values, which can be retrieved with the method <code>getOrigRow</code>.
* This class also provides methods for getting and setting individual
* values in the row.
* <P>
* A row's original values are the values it contained before it was last
* modified. For example, when the <code>CachedRowSet</code>method
* <code>acceptChanges</code> is called, it will reset a row's original
* values to be the row's current values. Then, when the row is modified,
* the values that were previously the current values will become the row's
* original values (the values the row had immediately before it was modified).
* If a row has not been modified, its original values are its initial values.
* <P>
* Subclasses of this class contain more specific details, such as
* the conditions under which an exception is thrown or the bounds for
* index parameters.
*/
public abstract class BaseRow implements Serializable, Cloneable {
/**
* Specify the serialVersionUID
*/
private static final long serialVersionUID = 4152013523511412238L;
/**
* The array containing the original values for this <code>BaseRow</code>
* object.
* @serial
*/
@SuppressWarnings("serial") // Array component type is not Serializable
protected Object[] origVals;
/**
* Retrieves the values that this row contained immediately
* prior to its last modification.
*
* @return an array of <code>Object</code> values containing this row's
* original values
*/
public Object[] getOrigRow() {
Object[] origRow = this.origVals;
return (origRow == null) ? null: Arrays.copyOf(origRow, origRow.length);
}
/**
* Retrieves the array element at the given index, which is
* the original value of column number <i>idx</i> in this row.
*
* @param idx the index of the element to return
* @return the <code>Object</code> value at the given index into this
* row's array of original values
* @throws SQLException if there is an error
*/
public abstract Object getColumnObject(int idx) throws SQLException;
/**
* Sets the element at the given index into this row's array of
* original values to the given value. Implementations of the classes
* <code>Row</code> and determine what happens
* when the cursor is on the insert row and when it is on any other row.
*
* @param idx the index of the element to be set
* @param obj the <code>Object</code> to which the element at index
* <code>idx</code> to be set
* @throws SQLException if there is an error
*/
public abstract void setColumnObject(int idx, Object obj) throws SQLException;
}

View file

@ -0,0 +1,510 @@
/*
* Copyright (c) 2003, 2011, 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 com.sun.rowset.internal;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import java.io.*;
import java.lang.reflect.*;
import com.sun.rowset.*;
import javax.sql.rowset.*;
import javax.sql.rowset.spi.*;
/**
* The facility called by the <code>RIOptimisticProvider</code> object
* internally to read data into it. The calling <code>RowSet</code> object
* must have implemented the <code>RowSetInternal</code> interface
* and have the standard <code>CachedRowSetReader</code> object set as its
* reader.
* <P>
* This implementation always reads all rows of the data source,
* and it assumes that the <code>command</code> property for the caller
* is set with a query that is appropriate for execution by a
* <code>PreparedStatement</code> object.
* <P>
* Typically the <code>SyncFactory</code> manages the <code>RowSetReader</code> and
* the <code>RowSetWriter</code> implementations using <code>SyncProvider</code> objects.
* Standard JDBC RowSet implementations provide an object instance of this
* reader by invoking the <code>SyncProvider.getRowSetReader()</code> method.
*
* @author Jonathan Bruce
* @see javax.sql.rowset.spi.SyncProvider
* @see javax.sql.rowset.spi.SyncFactory
* @see javax.sql.rowset.spi.SyncFactoryException
*/
public class CachedRowSetReader implements RowSetReader, Serializable {
/**
* The field that keeps track of whether the writer associated with
* this <code>CachedRowSetReader</code> object's rowset has been called since
* the rowset was populated.
* <P>
* When this <code>CachedRowSetReader</code> object reads data into
* its rowset, it sets the field <code>writerCalls</code> to 0.
* When the writer associated with the rowset is called to write
* data back to the underlying data source, its <code>writeData</code>
* method calls the method <code>CachedRowSetReader.reset</code>,
* which increments <code>writerCalls</code> and returns <code>true</code>
* if <code>writerCalls</code> is 1. Thus, <code>writerCalls</code> equals
* 1 after the first call to <code>writeData</code> that occurs
* after the rowset has had data read into it.
*
* @serial
*/
private int writerCalls = 0;
private boolean userCon = false;
private int startPosition;
private JdbcRowSetResourceBundle resBundle;
public CachedRowSetReader() {
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Reads data from a data source and populates the given
* <code>RowSet</code> object with that data.
* This method is called by the rowset internally when
* the application invokes the method <code>execute</code>
* to read a new set of rows.
* <P>
* After clearing the rowset of its contents, if any, and setting
* the number of writer calls to <code>0</code>, this reader calls
* its <code>connect</code> method to make
* a connection to the rowset's data source. Depending on which
* of the rowset's properties have been set, the <code>connect</code>
* method will use a <code>DataSource</code> object or the
* <code>DriverManager</code> facility to make a connection to the
* data source.
* <P>
* Once the connection to the data source is made, this reader
* executes the query in the calling <code>CachedRowSet</code> object's
* <code>command</code> property. Then it calls the rowset's
* <code>populate</code> method, which reads data from the
* <code>ResultSet</code> object produced by executing the rowset's
* command. The rowset is then populated with this data.
* <P>
* This method's final act is to close the connection it made, thus
* leaving the rowset disconnected from its data source.
*
* @param caller a <code>RowSet</code> object that has implemented
* the <code>RowSetInternal</code> interface and had
* this <code>CachedRowSetReader</code> object set as
* its reader
* @throws SQLException if there is a database access error, there is a
* problem making the connection, or the command property has not
* been set
*/
public void readData(RowSetInternal caller) throws SQLException
{
Connection con = null;
try {
CachedRowSet crs = (CachedRowSet)caller;
// Get rid of the current contents of the rowset.
/**
* Checking added to verify whether page size has been set or not.
* If set then do not close the object as certain parameters need
* to be maintained.
*/
if(crs.getPageSize() == 0 && crs.size() >0 ) {
// When page size is not set,
// crs.size() will show the total no of rows.
crs.close();
}
writerCalls = 0;
// Get a connection. This reader assumes that the necessary
// properties have been set on the caller to let it supply a
// connection.
userCon = false;
con = this.connect(caller);
// Check our assumptions.
if (con == null || crs.getCommand() == null)
throw new SQLException(resBundle.handleGetObject("crsreader.connecterr").toString());
try {
con.setTransactionIsolation(crs.getTransactionIsolation());
} catch (Exception ex) {
;
}
// Use JDBC to read the data.
PreparedStatement pstmt = con.prepareStatement(crs.getCommand());
// Pass any input parameters to JDBC.
decodeParams(caller.getParams(), pstmt);
try {
pstmt.setMaxRows(crs.getMaxRows());
pstmt.setMaxFieldSize(crs.getMaxFieldSize());
pstmt.setEscapeProcessing(crs.getEscapeProcessing());
pstmt.setQueryTimeout(crs.getQueryTimeout());
} catch (Exception ex) {
/*
* drivers may not support the above - esp. older
* drivers being used by the bridge..
*/
throw new SQLException(ex.getMessage());
}
if(crs.getCommand().toLowerCase().indexOf("select") != -1) {
// can be (crs.getCommand()).indexOf("select")) == 0
// because we will be getting resultset when
// it may be the case that some false select query with
// select coming in between instead of first.
// if ((crs.getCommand()).indexOf("?")) does not return -1
// implies a Prepared Statement like query exists.
ResultSet rs = pstmt.executeQuery();
if(crs.getPageSize() == 0){
crs.populate(rs);
}
else {
/**
* If page size has been set then create a ResultSet object that is scrollable using a
* PreparedStatement handle.Also call the populate(ResultSet,int) function to populate
* a page of data as specified by the page size.
*/
pstmt = con.prepareStatement(crs.getCommand(),ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
decodeParams(caller.getParams(), pstmt);
try {
pstmt.setMaxRows(crs.getMaxRows());
pstmt.setMaxFieldSize(crs.getMaxFieldSize());
pstmt.setEscapeProcessing(crs.getEscapeProcessing());
pstmt.setQueryTimeout(crs.getQueryTimeout());
} catch (Exception ex) {
/*
* drivers may not support the above - esp. older
* drivers being used by the bridge..
*/
throw new SQLException(ex.getMessage());
}
rs = pstmt.executeQuery();
crs.populate(rs,startPosition);
}
rs.close();
} else {
pstmt.executeUpdate();
}
// Get the data.
pstmt.close();
try {
con.commit();
} catch (SQLException ex) {
;
}
// only close connections we created...
if (getCloseConnection() == true)
con.close();
}
catch (SQLException ex) {
// Throw an exception if reading fails for any reason.
throw ex;
} finally {
try {
// only close connections we created...
if (con != null && getCloseConnection() == true) {
try {
if (!con.getAutoCommit()) {
con.rollback();
}
} catch (Exception dummy) {
/*
* not an error condition, we're closing anyway, but
* we'd like to clean up any locks if we can since
* it is not clear the connection pool will clean
* these connections in a timely manner
*/
}
con.close();
con = null;
}
} catch (SQLException e) {
// will get exception if something already went wrong, but don't
// override that exception with this one
}
}
}
/**
* Checks to see if the writer associated with this reader needs
* to reset its state. The writer will need to initialize its state
* if new contents have been read since the writer was last called.
* This method is called by the writer that was registered with
* this reader when components were being wired together.
*
* @return <code>true</code> if writer associated with this reader needs
* to reset the values of its fields; <code>false</code> otherwise
* @throws SQLException if an access error occurs
*/
public boolean reset() throws SQLException {
writerCalls++;
return writerCalls == 1;
}
/**
* Establishes a connection with the data source for the given
* <code>RowSet</code> object. If the rowset's <code>dataSourceName</code>
* property has been set, this method uses the JNDI API to retrieve the
* <code>DataSource</code> object that it can use to make the connection.
* If the url, username, and password properties have been set, this
* method uses the <code>DriverManager.getConnection</code> method to
* make the connection.
* <P>
* This method is used internally by the reader and writer associated with
* the calling <code>RowSet</code> object; an application never calls it
* directly.
*
* @param caller a <code>RowSet</code> object that has implemented
* the <code>RowSetInternal</code> interface and had
* this <code>CachedRowSetReader</code> object set as
* its reader
* @return a <code>Connection</code> object that represents a connection
* to the caller's data source
* @throws SQLException if an access error occurs
*/
public Connection connect(RowSetInternal caller) throws SQLException {
// Get a JDBC connection.
if (caller.getConnection() != null) {
// A connection was passed to execute(), so use it.
// As we are using a connection the user gave us we
// won't close it.
userCon = true;
return caller.getConnection();
}
else if (((RowSet)caller).getDataSourceName() != null) {
// Connect using JNDI.
try {
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup
(((RowSet)caller).getDataSourceName());
// Check for username, password,
// if it exists try getting a Connection handle through them
// else try without these
// else throw SQLException
if(((RowSet)caller).getUsername() != null) {
return ds.getConnection(((RowSet)caller).getUsername(),
((RowSet)caller).getPassword());
} else {
return ds.getConnection();
}
}
catch (javax.naming.NamingException ex) {
SQLException sqlEx = new SQLException(resBundle.handleGetObject("crsreader.connect").toString());
sqlEx.initCause(ex);
throw sqlEx;
}
} else if (((RowSet)caller).getUrl() != null) {
// Connect using the driver manager.
return DriverManager.getConnection(((RowSet)caller).getUrl(),
((RowSet)caller).getUsername(),
((RowSet)caller).getPassword());
}
else {
return null;
}
}
/**
* Sets the parameter placeholders
* in the rowset's command (the given <code>PreparedStatement</code>
* object) with the parameters in the given array.
* This method, called internally by the method
* <code>CachedRowSetReader.readData</code>, reads each parameter, and
* based on its type, determines the correct
* <code>PreparedStatement.setXXX</code> method to use for setting
* that parameter.
*
* @param params an array of parameters to be used with the given
* <code>PreparedStatement</code> object
* @param pstmt the <code>PreparedStatement</code> object that is the
* command for the calling rowset and into which
* the given parameters are to be set
* @throws SQLException if an access error occurs
*/
@SuppressWarnings("deprecation")
private void decodeParams(Object[] params,
PreparedStatement pstmt) throws SQLException {
// There is a corresponding decodeParams in JdbcRowSetImpl
// which does the same as this method. This is a design flaw.
// Update the JdbcRowSetImpl.decodeParams when you update
// this method.
// Adding the same comments to JdbcRowSetImpl.decodeParams.
int arraySize;
Object[] param = null;
for (int i=0; i < params.length; i++) {
if (params[i] instanceof Object[]) {
param = (Object[])params[i];
if (param.length == 2) {
if (param[0] == null) {
pstmt.setNull(i + 1, ((Integer)param[1]).intValue());
continue;
}
if (param[0] instanceof java.sql.Date ||
param[0] instanceof java.sql.Time ||
param[0] instanceof java.sql.Timestamp) {
System.err.println(resBundle.handleGetObject("crsreader.datedetected").toString());
if (param[1] instanceof java.util.Calendar) {
System.err.println(resBundle.handleGetObject("crsreader.caldetected").toString());
pstmt.setDate(i + 1, (java.sql.Date)param[0],
(java.util.Calendar)param[1]);
continue;
}
else {
throw new SQLException(resBundle.handleGetObject("crsreader.paramtype").toString());
}
}
if (param[0] instanceof Reader) {
pstmt.setCharacterStream(i + 1, (Reader)param[0],
((Integer)param[1]).intValue());
continue;
}
/*
* What's left should be setObject(int, Object, scale)
*/
if (param[1] instanceof Integer) {
pstmt.setObject(i + 1, param[0], ((Integer)param[1]).intValue());
continue;
}
} else if (param.length == 3) {
if (param[0] == null) {
pstmt.setNull(i + 1, ((Integer)param[1]).intValue(),
(String)param[2]);
continue;
}
if (param[0] instanceof java.io.InputStream) {
switch (((Integer)param[2]).intValue()) {
case CachedRowSetImpl.UNICODE_STREAM_PARAM:
pstmt.setUnicodeStream(i + 1,
(java.io.InputStream)param[0],
((Integer)param[1]).intValue());
break;
case CachedRowSetImpl.BINARY_STREAM_PARAM:
pstmt.setBinaryStream(i + 1,
(java.io.InputStream)param[0],
((Integer)param[1]).intValue());
break;
case CachedRowSetImpl.ASCII_STREAM_PARAM:
pstmt.setAsciiStream(i + 1,
(java.io.InputStream)param[0],
((Integer)param[1]).intValue());
break;
default:
throw new SQLException(resBundle.handleGetObject("crsreader.paramtype").toString());
}
}
/*
* no point at looking at the first element now;
* what's left must be the setObject() cases.
*/
if (param[1] instanceof Integer && param[2] instanceof Integer) {
pstmt.setObject(i + 1, param[0], ((Integer)param[1]).intValue(),
((Integer)param[2]).intValue());
continue;
}
throw new SQLException(resBundle.handleGetObject("crsreader.paramtype").toString());
} else {
// common case - this catches all SQL92 types
pstmt.setObject(i + 1, params[i]);
continue;
}
} else {
// Try to get all the params to be set here
pstmt.setObject(i + 1, params[i]);
}
}
}
/**
* Assists in determining whether the current connection was created by this
* CachedRowSet to ensure incorrect connections are not prematurely terminated.
*
* @return a boolean giving the status of whether the connection has been closed.
*/
protected boolean getCloseConnection() {
if (userCon == true)
return false;
return true;
}
/**
* This sets the start position in the ResultSet from where to begin. This is
* called by the Reader in the CachedRowSetImpl to set the position on the page
* to begin populating from.
* @param pos integer indicating the position in the <code>ResultSet</code> to begin
* populating from.
*/
public void setStartPosition(int pos){
startPosition = pos;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID =5049738185801363801L;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,179 @@
/*
* Copyright (c) 2003, 2010, 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 com.sun.rowset.internal;
import com.sun.rowset.JdbcRowSetResourceBundle;
import java.sql.*;
import javax.sql.*;
import java.io.*;
import java.util.*;
/**
* A class used internally to manage a <code>CachedRowSet</code> object's
* insert row. This class keeps track of the number of columns in the
* insert row and which columns have had a value inserted. It provides
* methods for retrieving a column value, setting a column value, and finding
* out whether the insert row is complete.
*/
public class InsertRow extends BaseRow implements Serializable, Cloneable {
/**
* An internal <code>BitSet</code> object used to keep track of the
* columns in this <code>InsertRow</code> object that have had a value
* inserted.
*/
private BitSet colsInserted;
/**
* The number of columns in this <code>InsertRow</code> object.
*/
private int cols;
private JdbcRowSetResourceBundle resBundle;
/**
* Creates an <code>InsertRow</code> object initialized with the
* given number of columns, an array for keeping track of the
* original values in this insert row, and a
* <code>BitSet</code> object with the same number of bits as
* there are columns.
*
* @param numCols an <code>int</code> indicating the number of columns
* in this <code>InsertRow</code> object
*/
public InsertRow(int numCols) {
origVals = new Object[numCols];
colsInserted = new BitSet(numCols);
cols = numCols;
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Sets the bit in this <code>InsertRow</code> object's internal
* <code>BitSet</code> object that corresponds to the specified column
* in this <code>InsertRow</code> object. Setting a bit indicates
* that a value has been set.
*
* @param col the number of the column to be marked as inserted;
* the first column is <code>1</code>
*/
protected void markColInserted(int col) {
colsInserted.set(col);
}
/**
* Indicates whether this <code>InsertRow</code> object has a value
* for every column that cannot be null.
* @param RowSetMD the <code>RowSetMetaData</code> object for the
* <code>CachedRowSet</code> object that maintains this
* <code>InsertRow</code> object
* @return <code>true</code> if this <code>InsertRow</code> object is
* complete; <code>false</code> otherwise
* @throws SQLException if there is an error accessing data
*/
public boolean isCompleteRow(RowSetMetaData RowSetMD) throws SQLException {
for (int i = 0; i < cols; i++) {
if (colsInserted.get(i) == false &&
RowSetMD.isNullable(i + 1) ==
ResultSetMetaData.columnNoNulls) {
return false;
}
}
return true;
}
/**
* Clears all the bits in the internal <code>BitSet</code> object
* maintained by this <code>InsertRow</code> object. Clearing all the bits
* indicates that none of the columns have had a value inserted.
*/
public void initInsertRow() {
for (int i = 0; i < cols; i++) {
colsInserted.clear(i);
}
}
/**
* Retrieves the value of the designated column in this
* <code>InsertRow</code> object. If no value has been inserted
* into the designated column, this method throws an
* <code>SQLException</code>.
*
* @param idx the column number of the value to be retrieved;
* the first column is <code>1</code>
* @throws SQLException if no value has been inserted into
* the designated column
*/
public Object getColumnObject(int idx) throws SQLException {
if (colsInserted.get(idx - 1) == false) {
throw new SQLException(resBundle.handleGetObject("insertrow.novalue").toString());
}
return (origVals[idx - 1]);
}
/**
* Sets the element in this <code>InsertRow</code> object's
* internal array of original values that corresponds to the
* designated column with the given value. If the third
* argument is <code>true</code>,
* which means that the cursor is on the insert row, this
* <code>InsertRow</code> object's internal <code>BitSet</code> object
* is set so that the bit corresponding to the column being set is
* turned on.
*
* @param idx the number of the column in the insert row to be set;
* the first column is <code>1</code>
* @param val the value to be set
*/
public void setColumnObject(int idx, Object val) {
origVals[idx - 1] = val;
markColInserted(idx - 1);
}
/**
* This method re populates the resBundle
* during the deserialization process
*
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID = 1066099658102869344L;
}

View file

@ -0,0 +1,342 @@
/*
* Copyright (c) 2003, 2021, 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 com.sun.rowset.internal;
import java.sql.*;
import java.io.*;
import java.lang.*;
import java.util.*;
/**
* A class that keeps track of a row's values. A <code>Row</code> object
* maintains an array of current column values and an array of original
* column values, and it provides methods for getting and setting the
* value of a column. It also keeps track of which columns have
* changed and whether the change was a delete, insert, or update.
* <P>
* Note that column numbers for rowsets start at <code>1</code>,
* whereas the first element of an array or bitset is <code>0</code>.
* The argument for the method <code>getColumnUpdated</code> refers to
* the column number in the rowset (the first column is <code>1</code>);
* the argument for <code>setColumnUpdated</code> refers to the index
* into the rowset's internal bitset (the first bit is <code>0</code>).
*/
public class Row extends BaseRow implements Serializable, Cloneable {
static final long serialVersionUID = 5047859032611314762L;
/**
* An array containing the current column values for this <code>Row</code>
* object.
* @serial
*/
@SuppressWarnings("serial") // Array component type is not Serializable
private Object[] currentVals;
/**
* A <code>BitSet</code> object containing a flag for each column in
* this <code>Row</code> object, with each flag indicating whether or
* not the value in the column has been changed.
* @serial
*/
private BitSet colsChanged;
/**
* A <code>boolean</code> indicating whether or not this <code>Row</code>
* object has been deleted. <code>true</code> indicates that it has
* been deleted; <code>false</code> indicates that it has not.
* @serial
*/
private boolean deleted;
/**
* A <code>boolean</code> indicating whether or not this <code>Row</code>
* object has been updated. <code>true</code> indicates that it has
* been updated; <code>false</code> indicates that it has not.
* @serial
*/
private boolean updated;
/**
* A <code>boolean</code> indicating whether or not this <code>Row</code>
* object has been inserted. <code>true</code> indicates that it has
* been inserted; <code>false</code> indicates that it has not.
* @serial
*/
private boolean inserted;
/**
* The number of columns in this <code>Row</code> object.
* @serial
*/
private int numCols;
/**
* Creates a new <code>Row</code> object with the given number of columns.
* The newly-created row includes an array of original values,
* an array for storing its current values, and a <code>BitSet</code>
* object for keeping track of which column values have been changed.
*/
public Row(int numCols) {
origVals = new Object[numCols];
currentVals = new Object[numCols];
colsChanged = new BitSet(numCols);
this.numCols = numCols;
}
/**
* Creates a new <code>Row</code> object with the given number of columns
* and with its array of original values initialized to the given array.
* The new <code>Row</code> object also has an array for storing its
* current values and a <code>BitSet</code> object for keeping track
* of which column values have been changed.
*/
public Row(int numCols, Object[] vals) {
origVals = new Object[numCols];
System.arraycopy(vals, 0, origVals, 0, numCols);
currentVals = new Object[numCols];
colsChanged = new BitSet(numCols);
this.numCols = numCols;
}
/**
*
* This method is called internally by the <code>CachedRowSet.populate</code>
* methods.
*
* @param idx the number of the column in this <code>Row</code> object
* that is to be set; the index of the first column is
* <code>1</code>
* @param val the new value to be set
*/
public void initColumnObject(int idx, Object val) {
origVals[idx - 1] = val;
}
/**
*
* This method is called internally by the <code>CachedRowSet.updateXXX</code>
* methods.
*
* @param idx the number of the column in this <code>Row</code> object
* that is to be set; the index of the first column is
* <code>1</code>
* @param val the new value to be set
*/
public void setColumnObject(int idx, Object val) {
currentVals[idx - 1] = val;
setColUpdated(idx - 1);
}
/**
* Retrieves the column value stored in the designated column of this
* <code>Row</code> object.
*
* @param columnIndex the index of the column value to be retrieved;
* the index of the first column is <code>1</code>
* @return an <code>Object</code> in the Java programming language that
* represents the value stored in the designated column
* @throws SQLException if there is a database access error
*/
public Object getColumnObject(int columnIndex) throws SQLException {
if (getColUpdated(columnIndex - 1)) {
return(currentVals[columnIndex - 1]); // maps to array!!
} else {
return(origVals[columnIndex - 1]); // maps to array!!
}
}
/**
* Indicates whether the designated column of this <code>Row</code> object
* has been changed.
* @param idx the index into the <code>BitSet</code> object maintained by
* this <code>Row</code> object to keep track of which column
* values have been modified; the index of the first bit is
* <code>0</code>
* @return <code>true</code> if the designated column value has been changed;
* <code>false</code> otherwise
*
*/
public boolean getColUpdated(int idx) {
return colsChanged.get(idx);
}
/**
* Sets this <code>Row</code> object's <code>deleted</code> field
* to <code>true</code>.
*
* @see #getDeleted
*/
public void setDeleted() { // %%% was public
deleted = true;
}
/**
* Retrieves the value of this <code>Row</code> object's <code>deleted</code> field,
* which will be <code>true</code> if one or more of its columns has been
* deleted.
* @return <code>true</code> if a column value has been deleted; <code>false</code>
* otherwise
*
* @see #setDeleted
*/
public boolean getDeleted() {
return(deleted);
}
/**
* Sets the <code>deleted</code> field for this <code>Row</code> object to
* <code>false</code>.
*/
public void clearDeleted() {
deleted = false;
}
/**
* Sets the value of this <code>Row</code> object's <code>inserted</code> field
* to <code>true</code>.
*
* @see #getInserted
*/
public void setInserted() {
inserted = true;
}
/**
* Retrieves the value of this <code>Row</code> object's <code>inserted</code> field,
* which will be <code>true</code> if this row has been inserted.
* @return <code>true</code> if this row has been inserted; <code>false</code>
* otherwise
*
* @see #setInserted
*/
public boolean getInserted() {
return(inserted);
}
/**
* Sets the <code>inserted</code> field for this <code>Row</code> object to
* <code>false</code>.
*/
public void clearInserted() { // %%% was public
inserted = false;
}
/**
* Retrieves the value of this <code>Row</code> object's
* <code>updated</code> field.
* @return <code>true</code> if this <code>Row</code> object has been
* updated; <code>false</code> if it has not
*
* @see #setUpdated
*/
public boolean getUpdated() {
return(updated);
}
/**
* Sets the <code>updated</code> field for this <code>Row</code> object to
* <code>true</code> if one or more of its column values has been changed.
*
* @see #getUpdated
*/
public void setUpdated() {
// only mark something as updated if one or
// more of the columns has been changed.
for (int i = 0; i < numCols; i++) {
if (getColUpdated(i) == true) {
updated = true;
return;
}
}
}
/**
* Sets the bit at the given index into this <code>Row</code> object's internal
* <code>BitSet</code> object, indicating that the corresponding column value
* (column <code>idx</code> + 1) has been changed.
*
* @param idx the index into the <code>BitSet</code> object maintained by
* this <code>Row</code> object; the first bit is at index
* <code>0</code>
*
*/
private void setColUpdated(int idx) {
colsChanged.set(idx);
}
/**
* Sets the <code>updated</code> field for this <code>Row</code> object to
* <code>false</code>, sets all the column values in this <code>Row</code>
* object's internal array of current values to <code>null</code>, and clears
* all of the bits in the <code>BitSet</code> object maintained by this
* <code>Row</code> object.
*/
public void clearUpdated() {
updated = false;
for (int i = 0; i < numCols; i++) {
currentVals[i] = null;
colsChanged.clear(i);
}
}
/**
* Sets the column values in this <code>Row</code> object's internal
* array of original values with the values in its internal array of
* current values, sets all the values in this <code>Row</code>
* object's internal array of current values to <code>null</code>,
* clears all the bits in this <code>Row</code> object's internal bitset,
* and sets its <code>updated</code> field to <code>false</code>.
* <P>
* This method is called internally by the <code>CachedRowSet</code>
* method <code>makeRowOriginal</code>.
*/
public void moveCurrentToOrig() {
for (int i = 0; i < numCols; i++) {
if (getColUpdated(i) == true) {
origVals[i] = currentVals[i];
currentVals[i] = null;
colsChanged.clear(i);
}
}
updated = false;
}
/**
* Returns the row on which the cursor is positioned.
*
* @return the <code>Row</code> object on which the <code>CachedRowSet</code>
* implementation objects's cursor is positioned
*/
public BaseRow getCurrentRow() {
return null;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,237 @@
/*
* Copyright (c) 2003, 2010, 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 com.sun.rowset.internal;
import java.sql.*;
import javax.sql.*;
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;
import com.sun.rowset.*;
import java.text.MessageFormat;
import javax.sql.rowset.*;
import javax.sql.rowset.spi.*;
/**
* An implementation of the <code>XmlReader</code> interface, which
* reads and parses an XML formatted <code>WebRowSet</code> object.
* This implementation uses an <code>org.xml.sax.Parser</code> object
* as its parser.
*/
public class WebRowSetXmlReader implements XmlReader, Serializable {
private JdbcRowSetResourceBundle resBundle;
public WebRowSetXmlReader(){
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Parses the given <code>WebRowSet</code> object, getting its input from
* the given <code>java.io.Reader</code> object. The parser will send
* notifications of parse events to the rowset's
* <code>XmlReaderDocHandler</code>, which will build the rowset as
* an XML document.
* <P>
* This method is called internally by the method
* <code>WebRowSet.readXml</code>.
* <P>
* If a parsing error occurs, the exception thrown will include
* information for locating 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
* the parser will get its input
* @exception SQLException if a database access error occurs or
* this <code>WebRowSetXmlReader</code> object is not the
* reader for the given rowset
* @see XmlReaderContentHandler
*/
public void readXML(WebRowSet caller, java.io.Reader reader) throws SQLException {
try {
// Crimson Parser(as in J2SE 1.4.1 is NOT able to handle
// Reader(s)(FileReader).
//
// But getting the file as a Stream works fine. So we are going to take
// the reader but send it as a InputStream to the parser. Note that this
// functionality needs to work against any parser
// Crimson(J2SE 1.4.x) / Xerces(J2SE 1.5.x).
InputSource is = new InputSource(reader);
DefaultHandler dh = new XmlErrorHandler();
XmlReaderContentHandler hndr = new XmlReaderContentHandler((RowSet)caller);
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
SAXParser parser = factory.newSAXParser() ;
parser.setProperty(
"http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
XMLReader reader1 = parser.getXMLReader() ;
reader1.setEntityResolver(new XmlResolver());
reader1.setContentHandler(hndr);
reader1.setErrorHandler(dh);
reader1.parse(is);
} catch (SAXParseException err) {
System.out.println (MessageFormat.format(resBundle.handleGetObject("wrsxmlreader.parseerr").toString(), new Object[]{ err.getMessage (), err.getLineNumber(), err.getSystemId()}));
err.printStackTrace();
throw new SQLException(err.getMessage());
} catch (SAXException e) {
Exception x = e;
if (e.getException () != null)
x = e.getException();
x.printStackTrace ();
throw new SQLException(x.getMessage());
}
// Will be here if trying to write beyond the RowSet limits
catch (ArrayIndexOutOfBoundsException aie) {
throw new SQLException(resBundle.handleGetObject("wrsxmlreader.invalidcp").toString());
}
catch (Throwable e) {
throw new SQLException(MessageFormat.format(resBundle.handleGetObject("wrsxmlreader.readxml").toString() , e.getMessage()));
}
}
/**
* Parses the given <code>WebRowSet</code> object, getting its input from
* the given <code>java.io.InputStream</code> object. The parser will send
* notifications of parse events to the rowset's
* <code>XmlReaderDocHandler</code>, which will build the rowset as
* an XML document.
* <P>
* Using streams is a much faster way than using <code>java.io.Reader</code>
* <P>
* This method is called internally by the method
* <code>WebRowSet.readXml</code>.
* <P>
* If a parsing error occurs, the exception thrown will include
* information for locating 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 iStream the <code>java.io.InputStream</code> object from which
* the parser will get its input
* @throws SQLException if a database access error occurs or
* this <code>WebRowSetXmlReader</code> object is not the
* reader for the given rowset
* @see XmlReaderContentHandler
*/
public void readXML(WebRowSet caller, java.io.InputStream iStream) throws SQLException {
try {
InputSource is = new InputSource(iStream);
DefaultHandler dh = new XmlErrorHandler();
XmlReaderContentHandler hndr = new XmlReaderContentHandler((RowSet)caller);
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
SAXParser parser = factory.newSAXParser() ;
parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
XMLReader reader1 = parser.getXMLReader() ;
reader1.setEntityResolver(new XmlResolver());
reader1.setContentHandler(hndr);
reader1.setErrorHandler(dh);
reader1.parse(is);
} catch (SAXParseException err) {
System.out.println (MessageFormat.format(resBundle.handleGetObject("wrsxmlreader.parseerr").toString(), new Object[]{err.getLineNumber(), err.getSystemId() }));
System.out.println(" " + err.getMessage ());
err.printStackTrace();
throw new SQLException(err.getMessage());
} catch (SAXException e) {
Exception x = e;
if (e.getException () != null)
x = e.getException();
x.printStackTrace ();
throw new SQLException(x.getMessage());
}
// Will be here if trying to write beyond the RowSet limits
catch (ArrayIndexOutOfBoundsException aie) {
throw new SQLException(resBundle.handleGetObject("wrsxmlreader.invalidcp").toString());
}
catch (Throwable e) {
throw new SQLException(MessageFormat.format(resBundle.handleGetObject("wrsxmlreader.readxml").toString() , e.getMessage()));
}
}
/**
* For code coverage purposes only right now
*
*/
public void readData(RowSetInternal caller) {
}
/**
* This method re populates the resBundle
* during the deserialization process
*
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID = -9127058392819008014L;
}

View file

@ -0,0 +1,680 @@
/*
* Copyright (c) 2003, 2022, 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 com.sun.rowset.internal;
import com.sun.rowset.JdbcRowSetResourceBundle;
import java.sql.*;
import javax.sql.*;
import java.io.*;
import java.text.MessageFormat;
import java.util.*;
import javax.sql.rowset.*;
import javax.sql.rowset.spi.*;
/**
* An implementation of the {@code XmlWriter} interface, which writes a
* {@code WebRowSet} object to an output stream as an XML document.
*/
public class WebRowSetXmlWriter implements XmlWriter, Serializable {
/**
* The {@code java.io.Writer} object to which this {@code WebRowSetXmlWriter}
* object will write when its {@code writeXML} method is called. The value
* for this field is set with the {@code java.io.Writer} object given
* as the second argument to the {@code writeXML} method.
*/
private transient java.io.Writer writer;
/**
* The {@code java.util.Stack} object that this {@code WebRowSetXmlWriter}
* object will use for storing the tags to be used for writing the calling
* {@code WebRowSet} object as an XML document.
*/
private java.util.Stack<String> stack;
private JdbcRowSetResourceBundle resBundle;
public WebRowSetXmlWriter() {
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Writes the given {@code WebRowSet} object as an XML document
* using the given {@code java.io.Writer} object. The XML document
* will include the {@code WebRowSet} object's data, metadata, and
* properties. If a data value has been updated, that information is also
* included.
* <P>
* This method is called by the {@code XmlWriter} object that is
* referenced in the calling {@code WebRowSet} object's
* {@code xmlWriter} field. The {@code XmlWriter.writeXML}
* method passes to this method the arguments that were supplied to it.
*
* @param caller the {@code WebRowSet} object to be written; must
* be a rowset for which this {@code WebRowSetXmlWriter} object
* is the writer
* @param wrt the {@code java.io.Writer} object to which
* {@code caller} will be written
* @exception SQLException if a database access error occurs or
* this {@code WebRowSetXmlWriter} object is not the writer
* for the given rowset
* @see XmlWriter#writeXML
*/
public void writeXML(WebRowSet caller, java.io.Writer wrt)
throws SQLException {
// create a new stack for tag checking.
stack = new java.util.Stack<>();
writer = wrt;
writeRowSet(caller);
}
/**
* Writes the given {@code WebRowSet} object as an XML document
* using the given {@code java.io.OutputStream} object. The XML document
* will include the {@code WebRowSet} object's data, metadata, and
* properties. If a data value has been updated, that information is also
* included.
* <P>
* Using stream is a faster way than using {@code java.io.Writer}
*
* This method is called by the {@code XmlWriter} object that is
* referenced in the calling {@code WebRowSet} object's
* {@code xmlWriter} field. The {@code XmlWriter.writeXML}
* method passes to this method the arguments that were supplied to it.
*
* @param caller the {@code WebRowSet} object to be written; must
* be a rowset for which this {@code WebRowSetXmlWriter} object
* is the writer
* @param oStream the {@code java.io.OutputStream} object to which
* {@code caller} will be written
* @throws SQLException if a database access error occurs or
* this {@code WebRowSetXmlWriter} object is not the writer
* for the given rowset
* @see XmlWriter#writeXML
*/
public void writeXML(WebRowSet caller, java.io.OutputStream oStream)
throws SQLException {
// create a new stack for tag checking.
stack = new java.util.Stack<>();
writer = new OutputStreamWriter(oStream);
writeRowSet(caller);
}
/**
*
*
* @exception SQLException if a database access error occurs
*/
private void writeRowSet(WebRowSet caller) throws SQLException {
try {
startHeader();
writeProperties(caller);
writeMetaData(caller);
writeData(caller);
endHeader();
} catch (java.io.IOException ex) {
throw new SQLException(MessageFormat.format(resBundle.handleGetObject("wrsxmlwriter.ioex").toString(), ex.getMessage()));
}
}
private void startHeader() throws java.io.IOException {
setTag("webRowSet");
writer.write("<?xml version=\"1.0\"?>\n");
writer.write("<webRowSet xmlns=\"http://java.sun.com/xml/ns/jdbc\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
writer.write("xsi:schemaLocation=\"http://java.sun.com/xml/ns/jdbc http://java.sun.com/xml/ns/jdbc/webrowset.xsd\">\n");
}
private void endHeader() throws java.io.IOException {
endTag("webRowSet");
}
/**
*
*
* @exception SQLException if a database access error occurs
*/
private void writeProperties(WebRowSet caller) throws java.io.IOException {
beginSection("properties");
try {
propString("command", processSpecialCharacters(caller.getCommand()));
propInteger("concurrency", caller.getConcurrency());
propString("datasource", caller.getDataSourceName());
propBoolean("escape-processing",
caller.getEscapeProcessing());
try {
propInteger("fetch-direction", caller.getFetchDirection());
} catch(SQLException sqle) {
// it may be the case that fetch direction has not been set
// fetchDir == 0
// in that case it will throw a SQLException.
// To avoid that catch it here
}
propInteger("fetch-size", caller.getFetchSize());
propInteger("isolation-level",
caller.getTransactionIsolation());
beginSection("key-columns");
int[] kc = caller.getKeyColumns();
for (int i = 0; kc != null && i < kc.length; i++)
propInteger("column", kc[i]);
endSection("key-columns");
//Changed to beginSection and endSection for maps for proper indentation
beginSection("map");
Map<String, Class<?>> typeMap = caller.getTypeMap();
if(typeMap != null) {
for(Map.Entry<String, Class<?>> mm : typeMap.entrySet()) {
propString("type", mm.getKey());
propString("class", mm.getValue().getName());
}
}
endSection("map");
propInteger("max-field-size", caller.getMaxFieldSize());
propInteger("max-rows", caller.getMaxRows());
propInteger("query-timeout", caller.getQueryTimeout());
propBoolean("read-only", caller.isReadOnly());
int itype = caller.getType();
String strType = "";
if(itype == 1003) {
strType = "ResultSet.TYPE_FORWARD_ONLY";
} else if(itype == 1004) {
strType = "ResultSet.TYPE_SCROLL_INSENSITIVE";
} else if(itype == 1005) {
strType = "ResultSet.TYPE_SCROLL_SENSITIVE";
}
propString("rowset-type", strType);
propBoolean("show-deleted", caller.getShowDeleted());
propString("table-name", caller.getTableName());
propString("url", caller.getUrl());
beginSection("sync-provider");
// Remove the string after "@xxxx"
// before writing it to the xml file.
String strProviderInstance = (caller.getSyncProvider()).toString();
String strProvider = strProviderInstance.substring(0, (caller.getSyncProvider()).toString().indexOf('@'));
propString("sync-provider-name", strProvider);
propString("sync-provider-vendor", "Oracle Corporation");
propString("sync-provider-version", "1.0");
propInteger("sync-provider-grade", caller.getSyncProvider().getProviderGrade());
propInteger("data-source-lock", caller.getSyncProvider().getDataSourceLock());
endSection("sync-provider");
} catch (SQLException ex) {
throw new java.io.IOException(MessageFormat.format(resBundle.handleGetObject("wrsxmlwriter.sqlex").toString(), ex.getMessage()));
}
endSection("properties");
}
/**
*
*
* @exception SQLException if a database access error occurs
*/
private void writeMetaData(WebRowSet caller) throws java.io.IOException {
int columnCount;
beginSection("metadata");
try {
ResultSetMetaData rsmd = caller.getMetaData();
columnCount = rsmd.getColumnCount();
propInteger("column-count", columnCount);
for (int colIndex = 1; colIndex <= columnCount; colIndex++) {
beginSection("column-definition");
propInteger("column-index", colIndex);
propBoolean("auto-increment", rsmd.isAutoIncrement(colIndex));
propBoolean("case-sensitive", rsmd.isCaseSensitive(colIndex));
propBoolean("currency", rsmd.isCurrency(colIndex));
propInteger("nullable", rsmd.isNullable(colIndex));
propBoolean("signed", rsmd.isSigned(colIndex));
propBoolean("searchable", rsmd.isSearchable(colIndex));
propInteger("column-display-size",rsmd.getColumnDisplaySize(colIndex));
propString("column-label", rsmd.getColumnLabel(colIndex));
propString("column-name", rsmd.getColumnName(colIndex));
propString("schema-name", rsmd.getSchemaName(colIndex));
propInteger("column-precision", rsmd.getPrecision(colIndex));
propInteger("column-scale", rsmd.getScale(colIndex));
propString("table-name", rsmd.getTableName(colIndex));
propString("catalog-name", rsmd.getCatalogName(colIndex));
propInteger("column-type", rsmd.getColumnType(colIndex));
propString("column-type-name", rsmd.getColumnTypeName(colIndex));
endSection("column-definition");
}
} catch (SQLException ex) {
throw new java.io.IOException(MessageFormat.format(resBundle.handleGetObject("wrsxmlwriter.sqlex").toString(), ex.getMessage()));
}
endSection("metadata");
}
/**
*
*
* @exception SQLException if a database access error occurs
*/
private void writeData(WebRowSet caller) throws java.io.IOException {
ResultSet rs;
try {
ResultSetMetaData rsmd = caller.getMetaData();
int columnCount = rsmd.getColumnCount();
int i;
beginSection("data");
caller.beforeFirst();
caller.setShowDeleted(true);
while (caller.next()) {
if (caller.rowDeleted() && caller.rowInserted()) {
beginSection("modifyRow");
} else if (caller.rowDeleted()) {
beginSection("deleteRow");
} else if (caller.rowInserted()) {
beginSection("insertRow");
} else {
beginSection("currentRow");
}
for (i = 1; i <= columnCount; i++) {
if (caller.columnUpdated(i)) {
rs = caller.getOriginalRow();
rs.next();
beginTag("columnValue");
writeValue(i, (RowSet)rs);
endTag("columnValue");
beginTag("updateRow");
writeValue(i, caller);
endTag("updateRow");
} else {
beginTag("columnValue");
writeValue(i, caller);
endTag("columnValue");
}
}
endSection(); // this is unchecked
}
endSection("data");
} catch (SQLException ex) {
throw new java.io.IOException(MessageFormat.format(resBundle.handleGetObject("wrsxmlwriter.sqlex").toString(), ex.getMessage()));
}
}
private void writeValue(int idx, RowSet caller) throws java.io.IOException {
try {
int type = caller.getMetaData().getColumnType(idx);
switch (type) {
case java.sql.Types.BIT:
case java.sql.Types.BOOLEAN:
boolean b = caller.getBoolean(idx);
if (caller.wasNull())
writeNull();
else
writeBoolean(b);
break;
case java.sql.Types.TINYINT:
case java.sql.Types.SMALLINT:
short s = caller.getShort(idx);
if (caller.wasNull())
writeNull();
else
writeShort(s);
break;
case java.sql.Types.INTEGER:
int i = caller.getInt(idx);
if (caller.wasNull())
writeNull();
else
writeInteger(i);
break;
case java.sql.Types.BIGINT:
long l = caller.getLong(idx);
if (caller.wasNull())
writeNull();
else
writeLong(l);
break;
case java.sql.Types.REAL:
case java.sql.Types.FLOAT:
float f = caller.getFloat(idx);
if (caller.wasNull())
writeNull();
else
writeFloat(f);
break;
case java.sql.Types.DOUBLE:
double d = caller.getDouble(idx);
if (caller.wasNull())
writeNull();
else
writeDouble(d);
break;
case java.sql.Types.NUMERIC:
case java.sql.Types.DECIMAL:
writeBigDecimal(caller.getBigDecimal(idx));
break;
case java.sql.Types.BINARY:
case java.sql.Types.VARBINARY:
case java.sql.Types.LONGVARBINARY:
break;
case java.sql.Types.DATE:
java.sql.Date date = caller.getDate(idx);
if (caller.wasNull())
writeNull();
else
writeLong(date.getTime());
break;
case java.sql.Types.TIME:
java.sql.Time time = caller.getTime(idx);
if (caller.wasNull())
writeNull();
else
writeLong(time.getTime());
break;
case java.sql.Types.TIMESTAMP:
java.sql.Timestamp ts = caller.getTimestamp(idx);
if (caller.wasNull())
writeNull();
else
writeLong(ts.getTime());
break;
case java.sql.Types.CHAR:
case java.sql.Types.VARCHAR:
case java.sql.Types.LONGVARCHAR:
writeStringData(caller.getString(idx));
break;
default:
System.out.println(resBundle.handleGetObject("wsrxmlwriter.notproper").toString());
//Need to take care of BLOB, CLOB, Array, Ref here
}
} catch (SQLException ex) {
throw new java.io.IOException(resBundle.handleGetObject("wrsxmlwriter.failedwrite").toString()+ ex.getMessage());
}
}
/*
* This begins a new tag with a indent
*
*/
private void beginSection(String tag) throws java.io.IOException {
// store the current tag
setTag(tag);
writeIndent(stack.size());
// write it out
writer.write("<" + tag + ">\n");
}
/*
* This closes a tag started by beginTag with a indent
*
*/
private void endSection(String tag) throws java.io.IOException {
writeIndent(stack.size());
String beginTag = getTag();
if(beginTag.indexOf("webRowSet") != -1) {
beginTag ="webRowSet";
}
if (tag.equals(beginTag) ) {
// get the current tag and write it out
writer.write("</" + beginTag + ">\n");
} else {
;
}
writer.flush();
}
private void endSection() throws java.io.IOException {
writeIndent(stack.size());
// get the current tag and write it out
String beginTag = getTag();
writer.write("</" + beginTag + ">\n");
writer.flush();
}
private void beginTag(String tag) throws java.io.IOException {
// store the current tag
setTag(tag);
writeIndent(stack.size());
// write tag out
writer.write("<" + tag + ">");
}
private void endTag(String tag) throws java.io.IOException {
String beginTag = getTag();
if (tag.equals(beginTag)) {
// get the current tag and write it out
writer.write("</" + beginTag + ">\n");
} else {
;
}
writer.flush();
}
private void emptyTag(String tag) throws java.io.IOException {
// write an emptyTag
writer.write("<" + tag + "/>");
}
private void setTag(String tag) {
// add the tag to stack
stack.push(tag);
}
private String getTag() {
return stack.pop();
}
private void writeNull() throws java.io.IOException {
emptyTag("null");
}
private void writeStringData(String s) throws java.io.IOException {
if (s == null) {
writeNull();
} else if (s.isEmpty()) {
writeEmptyString();
} else {
s = processSpecialCharacters(s);
writer.write(s);
}
}
private void writeString(String s) throws java.io.IOException {
if (s != null) {
writer.write(s);
} else {
writeNull();
}
}
private void writeShort(short s) throws java.io.IOException {
writer.write(Short.toString(s));
}
private void writeLong(long l) throws java.io.IOException {
writer.write(Long.toString(l));
}
private void writeInteger(int i) throws java.io.IOException {
writer.write(Integer.toString(i));
}
private void writeBoolean(boolean b) throws java.io.IOException {
writer.write(Boolean.toString(b));
}
private void writeFloat(float f) throws java.io.IOException {
writer.write(Float.toString(f));
}
private void writeDouble(double d) throws java.io.IOException {
writer.write(Double.toString(d));
}
private void writeBigDecimal(java.math.BigDecimal bd) throws java.io.IOException {
if (bd != null)
writer.write(bd.toString());
else
emptyTag("null");
}
private void writeIndent(int tabs) throws java.io.IOException {
// indent...
for (int i = 1; i < tabs; i++) {
writer.write(" ");
}
}
private void propString(String tag, String s) throws java.io.IOException {
beginTag(tag);
writeString(s);
endTag(tag);
}
private void propInteger(String tag, int i) throws java.io.IOException {
beginTag(tag);
writeInteger(i);
endTag(tag);
}
private void propBoolean(String tag, boolean b) throws java.io.IOException {
beginTag(tag);
writeBoolean(b);
endTag(tag);
}
private void writeEmptyString() throws java.io.IOException {
emptyTag("emptyString");
}
/**
* Purely for code coverage purposes..
*/
public boolean writeData(RowSetInternal caller) {
return false;
}
/**
* This function has been added for the processing of special characters
* like <,>,'," and & in the data to be serialized. These have to be taken
* of specifically or else there will be parsing error while trying to read
* the contents of the XML file.
**/
private String processSpecialCharacters(String s) {
if(s == null) {
return null;
}
char []charStr = s.toCharArray();
String specialStr = "";
for(int i = 0; i < charStr.length; i++) {
if(charStr[i] == '&') {
specialStr = specialStr.concat("&amp;");
} else if(charStr[i] == '<') {
specialStr = specialStr.concat("&lt;");
} else if(charStr[i] == '>') {
specialStr = specialStr.concat("&gt;");
} else if(charStr[i] == '\'') {
specialStr = specialStr.concat("&apos;");
} else if(charStr[i] == '\"') {
specialStr = specialStr.concat("&quot;");
} else {
specialStr = specialStr.concat(String.valueOf(charStr[i]));
}
}
s = specialStr;
return s;
}
/**
* This method re populates the resBundle
* during the deserialization process
*
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID = 7163134986189677641L;
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2003, 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 com.sun.rowset.internal;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import com.sun.rowset.*;
import javax.sql.rowset.*;
/**
* An implementation of the <code>DefaultHandler</code> interface, which
* handles all the errors, fatalerrors and warnings while reading the xml file.
* This is the ErrorHandler which helps <code>WebRowSetXmlReader</code>
* to handle any errors while reading the xml data.
*/
public class XmlErrorHandler extends DefaultHandler {
public int errorCounter = 0;
public void error(SAXParseException e) throws SAXException {
errorCounter++;
}
public void fatalError(SAXParseException e) throws SAXException {
errorCounter++;
}
public void warning(SAXParseException exception) throws SAXException {
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2003, 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 com.sun.rowset.internal;
import org.xml.sax.*;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
/**
* An implementation of the <code>EntityResolver</code> interface, which
* reads and parses an XML formatted <code>WebRowSet</code> object.
* This is an implementation of org.xml.sax
*
*/
public class XmlResolver implements EntityResolver {
public InputSource resolveEntity(String publicId, String systemId) {
String schemaName = systemId.substring(systemId.lastIndexOf('/'));
if(systemId.startsWith("http://java.sun.com/xml/ns/jdbc")) {
return new InputSource(this.getClass().getResourceAsStream(schemaName));
} else {
// use the default behaviour
return null;
}
}
}

View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 2003, 2023, 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.
*/
/**
* Provides five standard implementations of the standard JDBC {@code RowSet} implementation
* interface definitions. These reference implementations are included with the J2SE version
* 1.5 platform and represent the benchmark standard {@code RowSet} implementations as verified
* by the Test Compatibility Kit (TCK) as mandated by the Java Community Process.
* <br>
*
* <h2>1.0 Available JDBC RowSet Reference Implementations </h2>
* The following implementations are provided:<br>
*
* <blockquote><b>{@code JdbcRowSetImpl}</b> - The {@code javax.sql.rowset.JdbcRowSet}
* interface reference implementation. <br>
* <br>
* <b>{@code CachedRowSetImpl}</b> - The {@code javax.sql.rowset.CachedRowSet} interface
* reference implementation.<br>
* <br>
* <b>{@code WebRowSetImpl}</b> - The {@code javax.sql.rowset.WebRowSet} interface
* reference implementation.<br>
* <br>
* <b>{@code FilteredRowSetImpl}</b> - The {@code javax.sql.rowset.FilteredRowSet}
* interface reference implementation.<br>
* <br>
* <b>{@code JoinRowSetImpl}</b> - The {@code javax.sql.rowset.JoinRowSet} interface
* reference implementation.<br>
* </blockquote>
*
* All details on their expected behavior, including their interactions with the {@code SyncProvider}
* SPI and helper classes are provided in the interface definitions in the {@code javax.sql.rowset}
* package specification.<br>
*
* <h2>2.0 Usage</h2>
* The reference implementations represent robust implementations of the standard
* {@code RowSet} interfaces defined in the {@code javax.sql.rowset} package.
* All disconnected {@code RowSet} implementations, such as the {@code CachedRowSetImpl}
* and {@code WebRowSetImpl}, are flexible enough to use the {@code SyncFactory} SPIs to
* leverage non-reference implementation {@code SyncProvider} implementations to obtain
* differing synchronization semantics. Furthermore, developers and vendors alike are free
* to use these implementations and integrate them into their products just as they
* can with to other components of the Java platform.<br>
*
* <h2>3.0 Extending the JDBC RowSet Implementations</h2>
*
* The JDBC {@code RowSet} reference implementations are provided as non-final
* classes so that any developer can extend them to provide additional features
* while maintaining the core required standard functionality and compatibility. It
* is anticipated that many vendors and developers will extend the standard feature
* set to their particular needs. The website for JDBC Technology will
* provider a portal where implementations can be listed, similar to the way it
* provides a site for JDBC drivers.
* @since 1.5
*/
package com.sun.rowset;

View file

@ -0,0 +1,262 @@
/*
* Copyright (c) 2003, 2022, 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 com.sun.rowset.providers;
import com.sun.rowset.JdbcRowSetResourceBundle;
import javax.sql.*;
import java.io.*;
import javax.sql.rowset.spi.*;
import com.sun.rowset.internal.*;
/**
* The reference implementation of a JDBC Rowset synchronization provider
* providing optimistic synchronization with a relational datastore
* using any JDBC technology-enabled driver.
*
* <h2>1.0 Background</h2>
* This synchronization provider is registered with the
* <code>SyncFactory</code> by default as the
* <code>com.sun.rowset.providers.RIOptimisticProvider</code>.
* As an extension of the <code>SyncProvider</code> abstract
* class, it provides the reader and writer classes required by disconnected
* rowsets as <code>javax.sql.RowSetReader</code> and <code>javax.sql.RowSetWriter</code>
* interface implementations. As a reference implementation,
* <code>RIOptimisticProvider</code> provides a
* fully functional implementation offering a medium grade classification of
* synchronization, namely GRADE_CHECK_MODIFIED_AT_COMMIT. A
* disconnected <code>RowSet</code> implementation using the
* <code>RIOptimisticProvider</code> can expect the writer to
* check only rows that have been modified in the <code>RowSet</code> against
* the values in the data source. If there is a conflict, that is, if a value
* in the data source has been changed by another party, the
* <code>RIOptimisticProvider</code> will not write any of the changes to the data
* source and will throw a <code>SyncProviderException</code> object.
*
* <h2>2.0 Usage</h2>
* Standard disconnected <code>RowSet</code> implementations may opt to use this
* <code>SyncProvider</code> implementation in one of two ways:
* <OL>
* <LI>By specifically calling the <code>setSyncProvider</code> method
defined in the <code>CachedRowSet</code> interface
* <pre>
* CachedRowset crs = new FooCachedRowSetImpl();
* crs.setSyncProvider("com.sun.rowset.providers.RIOptimisticProvider");
* </pre>
* <LI>By specifying it in the constructor of the <code>RowSet</code>
* implementation
* <pre>
* CachedRowset crs = new FooCachedRowSetImpl(
* "com.sun.rowset.providers.RIOptimisticProvider");
* </pre>
* </OL>
* Note that because the <code>RIOptimisticProvider</code> implementation is
* the default provider, it will always be the provider when no provider ID is
* specified to the constructor.
* <P>
* See the standard <code>RowSet</code> reference implementations in the
* <code>com.sun.rowset</code> package for more details.
*
* @author Jonathan Bruce
* @see javax.sql.rowset.spi.SyncProvider
* @see javax.sql.rowset.spi.SyncProviderException
* @see javax.sql.rowset.spi.SyncFactory
* @see javax.sql.rowset.spi.SyncFactoryException
*
*/
public final class RIOptimisticProvider extends SyncProvider implements Serializable {
private CachedRowSetReader reader;
private CachedRowSetWriter writer;
/**
* The unique provider identifier.
*/
private String providerID = "com.sun.rowset.providers.RIOptimisticProvider";
/**
* The vendor name of this SyncProvider implementation
*/
private String vendorName = "Oracle Corporation";
/**
* The version number of this SyncProvider implementation
*/
private String versionNumber = "1.0";
/**
* ResourceBundle
*/
private JdbcRowSetResourceBundle resBundle;
/**
* Creates an <code>RIOptimisticProvider</code> object initialized with the
* fully qualified class name of this <code>SyncProvider</code> implementation
* and a default reader and writer.
* <P>
* This provider is available to all disconnected <code>RowSet</code> implementations
* as the default persistence provider.
*/
public RIOptimisticProvider() {
providerID = this.getClass().getName();
reader = new CachedRowSetReader();
writer = new CachedRowSetWriter();
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Returns the <code>'javax.sql.rowset.providers.RIOptimisticProvider'</code>
* provider identification string.
*
* @return String Provider ID of this persistence provider
*/
public String getProviderID() {
return providerID;
}
/**
* Returns the <code>javax.sql.RowSetWriter</code> object for this
* <code>RIOptimisticProvider</code> object. This is the writer that will
* write changes made to the <code>Rowset</code> object back to the data source.
*
* @return the <code>javax.sql.RowSetWriter</code> object for this
* <code>RIOptimisticProvider</code> object
*/
public RowSetWriter getRowSetWriter() {
try {
writer.setReader(reader);
} catch (java.sql.SQLException e) {}
return writer;
}
/**
* Returns the <code>javax.sql.RowSetReader</code> object for this
* <code>RIOptimisticProvider</code> object. This is the reader that will
* populate a <code>RowSet</code> object using this <code>RIOptimisticProvider</code>.
*
* @return the <code>javax.sql.RowSetReader</code> object for this
* <code>RIOptimisticProvider</code> object
*/
public RowSetReader getRowSetReader() {
return reader;
}
/**
* Returns the <code>SyncProvider</code> grade of synchronization that
* <code>RowSet</code> objects can expect when using this
* implementation. As an optimistic synchronization provider, the writer
* will only check rows that have been modified in the <code>RowSet</code>
* object.
*/
public int getProviderGrade() {
return SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT;
}
/**
* Modifies the data source lock severity according to the standard
* <code>SyncProvider</code> classifications.
*
* @param datasource_lock An <code>int</code> indicating the level of locking to be
* set; must be one of the following constants:
* <PRE>
* SyncProvider.DATASOURCE_NO_LOCK,
* SyncProvider.DATASOURCE_ROW_LOCK,
* SyncProvider.DATASOURCE_TABLE_LOCK,
* SyncProvider.DATASOURCE_DB_LOCk
* </PRE>
* @throws SyncProviderException if the parameter specified is not
* <code>SyncProvider.DATASOURCE_NO_LOCK</code>
*/
public void setDataSourceLock(int datasource_lock) throws SyncProviderException {
if(datasource_lock != SyncProvider.DATASOURCE_NO_LOCK ) {
throw new SyncProviderException(resBundle.handleGetObject("riop.locking").toString());
}
}
/**
* Returns the active data source lock severity in this
* reference implementation of the <code>SyncProvider</code>
* abstract class.
*
* @return <code>SyncProvider.DATASOURCE_NO_LOCK</code>.
* The reference implementation does not support data source locks.
*/
public int getDataSourceLock() throws SyncProviderException {
return SyncProvider.DATASOURCE_NO_LOCK;
}
/**
* Returns the supported updatable view abilities of the
* reference implementation of the <code>SyncProvider</code>
* abstract class.
*
* @return <code>SyncProvider.NONUPDATABLE_VIEW_SYNC</code>. The
* the reference implementation does not support updating tables
* that are the source of a view.
*/
public int supportsUpdatableView() {
return SyncProvider.NONUPDATABLE_VIEW_SYNC;
}
/**
* Returns the release version ID of the Reference Implementation Optimistic
* Synchronization Provider.
*
* @return the <code>String</code> detailing the version number of this SyncProvider
*/
public String getVersion() {
return this.versionNumber;
}
/**
* Returns the vendor name of the Reference Implementation Optimistic
* Synchronization Provider
*
* @return the <code>String</code> detailing the vendor name of this
* SyncProvider
*/
public String getVendor() {
return this.vendorName;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID =-3143367176751761936L;
}

View file

@ -0,0 +1,248 @@
/*
* Copyright (c) 2003, 2022, 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 com.sun.rowset.providers;
import com.sun.rowset.JdbcRowSetResourceBundle;
import java.io.IOException;
import java.sql.*;
import javax.sql.*;
import javax.sql.rowset.spi.*;
/**
* A reference implementation of a JDBC RowSet synchronization provider
* with the ability to read and write rowsets in well formed XML using the
* standard WebRowSet schema.
*
* <h2>1.0 Background</h2>
* This synchronization provider is registered with the
* <code>SyncFactory</code> by default as the
* <code>com.sun.rowset.providers.RIXMLProvider</code>.
* <P>
* A <code>WebRowSet</code> object uses an <code>RIXMLProvider</code> implementation
* to read an XML data source or to write itself in XML format using the
* <code>WebRowSet</code> XML schema definition available at
* <pre>
* <a href="http://xmlns.jcp.org/xml/ns//jdbc/webrowset.xsd">http://xmlns.jcp.org/xml/ns//jdbc/webrowset.xsd</a>
* </pre>
* The <code>RIXMLProvider</code> implementation has a synchronization level of
* GRADE_NONE, which means that it does no checking at all for conflicts. It
* simply writes a <code>WebRowSet</code> object to a file.
* <h2>2.0 Usage</h2>
* A <code>WebRowSet</code> implementation is created with an <code>RIXMLProvider</code>
* by default.
* <pre>
* WebRowSet wrs = new FooWebRowSetImpl();
* </pre>
* The <code>SyncFactory</code> always provides an instance of
* <code>RIOptimisticProvider</code> when no provider is specified,
* but the implementation of the default constructor for <code>WebRowSet</code> sets the
* provider to be the <code>RIXMLProvider</code> implementation. Therefore,
* the following line of code is executed behind the scenes as part of the
* implementation of the default constructor.
* <pre>
* wrs.setSyncProvider("com.sun.rowset.providers.RIXMLProvider");
* </pre>
* See the standard <code>RowSet</code> reference implementations in the
* <code>com.sun.rowset</code> package for more details.
*
* @author Jonathan Bruce
* @see javax.sql.rowset.spi.SyncProvider
* @see javax.sql.rowset.spi.SyncProviderException
* @see javax.sql.rowset.spi.SyncFactory
* @see javax.sql.rowset.spi.SyncFactoryException
*/
public final class RIXMLProvider extends SyncProvider {
/**
* The unique provider identifier.
*/
private String providerID = "com.sun.rowset.providers.RIXMLProvider";
/**
* The vendor name of this SyncProvider implementation.
*/
private String vendorName = "Oracle Corporation";
/**
* The version number of this SyncProvider implementation.
*/
private String versionNumber = "1.0";
private JdbcRowSetResourceBundle resBundle;
private XmlReader xmlReader;
private XmlWriter xmlWriter;
/**
* This provider is available to all JDBC <code>RowSet</code> implementations as the
* default persistence provider.
*/
public RIXMLProvider() {
providerID = this.getClass().getName();
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Returns <code>"javax.sql.rowset.providers.RIXMLProvider"</code>, which is
* the fully qualified class name of this provider implementation.
*
* @return a <code>String</code> object with the fully specified class name of
* this <code>RIOptimisticProvider</code> implementation
*/
public String getProviderID() {
return providerID;
}
// additional methods that sit on top of reader/writer methods back to
// original datasource. Allow XML state to be written out and in
/**
* Sets this <code>WebRowSet</code> object's reader to the given
* <code>XmlReader</code> object.
*
* @throws SQLException if a database access error occurs
*/
public void setXmlReader(XmlReader reader) throws SQLException {
xmlReader = reader;
}
/**
* Sets this <code>WebRowSet</code> object's writer to the given
* <code>XmlWriter</code> object.
*
* @throws SQLException if a database access error occurs
*/
public void setXmlWriter(XmlWriter writer) throws SQLException {
xmlWriter = writer;
}
/**
* Retrieves the reader that this <code>WebRowSet</code> object
* will call when its <code>readXml</code> method is called.
*
* @return the <code>XmlReader</code> object for this SyncProvider
* @throws SQLException if a database access error occurs
*/
public XmlReader getXmlReader() throws SQLException {
return xmlReader;
}
/**
* Retrieves the writer that this <code>WebRowSet</code> object
* will call when its <code>writeXml</code> method is called.
*
* @return the <code>XmlWriter</code> for this SyncProvider
* @throws SQLException if a database access error occurs
*/
public XmlWriter getXmlWriter() throws SQLException {
return xmlWriter;
}
/**
* Returns the <code>SyncProvider</code> grade of syncrhonization that
* <code>RowSet</code> object instances can expect when using this
* implementation. As this implementation provides no synchronization
* facilities to the XML data source, the lowest grade is returned.
*
* @return the <code>SyncProvider</code> synchronization grade of this
* provider; must be one of the following constants:
* <PRE>
* SyncProvider.GRADE_NONE,
* SyncProvider.GRADE_MODIFIED_AT_COMMIT,
* SyncProvider.GRADE_CHECK_ALL_AT_COMMIT,
* SyncProvider.GRADE_LOCK_WHEN_MODIFIED,
* SyncProvider.GRADE_LOCK_WHEN_LOADED
* </PRE>
*
*/
public int getProviderGrade() {
return SyncProvider.GRADE_NONE;
}
/**
* Returns the default UPDATABLE_VIEW behavior of this reader
*
*/
public int supportsUpdatableView() {
return SyncProvider.NONUPDATABLE_VIEW_SYNC;
}
/**
* Returns the default DATASOURCE_LOCK behavior of this reader
*/
public int getDataSourceLock() throws SyncProviderException {
return SyncProvider.DATASOURCE_NO_LOCK;
}
/**
* Throws an unsupported operation exception as this method does
* function with non-locking XML data sources.
*/
public void setDataSourceLock(int lock) throws SyncProviderException {
throw new UnsupportedOperationException(resBundle.handleGetObject("rixml.unsupp").toString());
}
/**
* Returns a null object as RowSetWriters are not returned by this SyncProvider
*/
public RowSetWriter getRowSetWriter() {
return null;
}
/**
* Returns a null object as RowSetWriter objects are not returned by this
* SyncProvider
*/
public RowSetReader getRowSetReader() {
return null;
}
/**
* Returns the release version ID of the Reference Implementation Optimistic
* Synchronization Provider.
*
* @return the <code>String</code> detailing the version number of this SyncProvider
*/
public String getVersion() {
return this.versionNumber;
}
/**
* Returns the vendor name of the Reference Implementation Optimistic
* Synchronization Provider
*
* @return the <code>String</code> detailing the vendor name of this
* SyncProvider
*/
public String getVendor() {
return this.vendorName;
}
}

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2003, 2023, 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.
*/
/**
*
* Repository for the {@code RowSet} reference implementations of the
* {@code SyncProvider} abstract class. These implementations provide a
* disconnected {@code RowSet}
* object with the ability to synchronize the data in the underlying data
* source with its data. These implementations are provided as
* the default {@code SyncProvider} implementations and are accessible via the
* {@code SyncProvider} SPI managed by the {@code SyncFactory}.
*
* <h2>1.0 {@code SyncProvider} Reference Implementations</h2>
* The main job of a {@code SyncProvider} implementation is to manage
* the reader and writer mechanisms.
* The {@code SyncProvider} SPI, as specified in the {@code javax.sql.rowset.spi}
* package, provides a pluggable mechanism by which {@code javax.sql.RowSetReader}
* and {@code javax.sql.RowSetWriter} implementations can be supplied to a disconnected
* {@code RowSet} object.
* <P>
* A reader, a {@code javax.sql.RowSetReader}
* object, does the work necessary to populate a {@code RowSet} object with data.
* A writer, a {@code javax.sql.RowSetWriter} object, does the work necessary for
* synchronizing a {@code RowSet} object's data with the data in the originating
* source of data. Put another way, a writer writes a {@code RowSet}
* object's data back to the data source.
* <P>
* Generally speaking, the course of events is this. The reader makes a connection to
* the data source and reads the data from a {@code ResultSet} object into its
* {@code RowSet} object. Then it closes the connection. While
* the {@code RowSet} object is disconnected, an application makes some modifications
* to the data and calls the method {@code acceptChanges}. At this point, the
* writer is called to write the changes back to the database table or view
* from which the original data came. This is called <i>synchronization</i>.
* <P>
* If the data in the originating data source has not changed, there is no problem
* with just writing the {@code RowSet} object's new data to the data source.
* If it has changed, however, there is a conflict that needs to be resolved. One
* way to solve the problem is not to let the data in the data source be changed in
* the first place, which can be done by setting locks on a row, a table, or the
* whole data source. Setting locks is a way to avoid conflicts, but it can be
* very expensive. Another approach, which is at the other end of the spectrum,
* is simply to assume that no conflicts will occur and thus do nothing to avoid
* conflicts.
* Different {@code SyncProvider} implementations may handle synchronization in
* any of these ways, varying from doing no checking for
* conflicts, to doing various levels of checking, to guaranteeing that there are no
* conflicts.
* <P>
* The {@code SyncProvider} class offers methods to help a {@code RowSet}
* object discover and manage how a provider handles synchronization.
* The method {@code getProviderGrade} returns the
* grade of synchronization a provider offers. An application can
* direct the provider to use a particular level of locking by calling
* the method {@code setDataSourceLock} and specifying the level of locking desired.
* If a {@code RowSet} object's data came from an SQL {@code VIEW}, an
* application may call the method {@code supportsUpdatableView} to
* find out whether the {@code VIEW} can be updated.
* <P>
* Synchronization is done completely behind the scenes, so it is third party vendors of
* synchronization provider implementations who have to take care of this complex task.
* Application programmers can decide which provider to use and the level of locking to
* be done, but they are free from having to worry about the implementation details.
* <P>
* The JDBC {@code RowSet} Implementations reference implementation provides two
* implementations of the {@code SyncProvider} class:
*
* <UL>
* <LI>
* <b>{@code RIOptimisticProvider}</b> - provides the {@code javax.sql.RowSetReader}
* and {@code javax.sql.RowSetWriter} interface implementations and provides
* an optimistic concurrency model for synchronization. This model assumes that there
* will be few conflicts and therefore uses a relatively low grade of synchronization.
* If no other provider is available, this is the default provider that the
* {@code SyncFactory} will supply to a {@code RowSet} object.
* <br>
* <LI>
* <b>{@code RIXMLProvider}</b> - provides the {@code XmlReader} (an extension
* of the {@code javax.sql.RowSetReader} interface) and the {@code XmlWriter}
* (an extension of the {@code javax.sql.RowSetWriter} interface) to enable
* {@code WebRowSet} objects to write their state to a
* well formed XML document according to the {@code WebRowSet} XML schema
* definition.<br>
* </UL>
*
* <h2>2.0 Basics in RowSet Population &amp; Synchronization</h2>
* A rowset's first task is to populate itself with rows of column values.
* Generally, these rows will come from a relational database, so a rowset
* has properties that supply what is necessary for making a connection to
* a database and executing a query. A rowset that does not need to establish
* a connection and execute a command, such as one that gets its data from
* a tabular file instead of a relational database, does not need to have these
* properties set. The vast majority of RowSets, however, do need to set these
* properties. The general rule is that a RowSet is required to set only the
* properties that it uses.<br>
* <br>
* The {@code command} property contains the query that determines what
* data a {@code RowSet} will contain. Rowsets have methods for setting a query's
* parameter(s), which means that a query can be executed multiple times with
* different parameters to produce different result sets. Or the query can be
* changed to something completely new to get a new result set.
* <p>Once a rowset contains the rows from a {@code ResultSet} object or some
* other data source, its column values can be updated, and its rows can be
* inserted or deleted. Any method that causes a change in the rowset's values
* or cursor position also notifies any object that has been registered as
* a listener with the rowset. So, for example, a table that displays the rowset's
* data in an applet can be notified of changes and make updates as they
* occur.<br>
* <br>
* The changes made to a rowset can be propagated back to the original data
* source to keep the rowset and its data source synchronized. Although this
* involves many operations behind the scenes, it is completely transparent
* to the application programmer and remains the concern of the RowSet provider
* developer. All an application has to do is invoke the method {@code acceptChanges},
* and the data source backing the rowset will be updated to match the current
* values in the rowset. </p>
*
* <p>A disconnected rowset, such as a {@code CachedRowSet} or {@code WebRowSet}
* object, establishes a connection to populate itself with data from a database
* and then closes the connection. The {@code RowSet} object will remain
* disconnected until it wants to propagate changes back to its database table,
* which is optional. To write its changes back to the database (synchronize with
* the database), the rowset establishes a connection, write the changes, and then
* once again disconnects itself.<br>
* </p>
*
* <h2> 3.0 Other Possible Implementations</h2>
* There are many other possible implementations of the {@code SyncProvider} abstract
* class. One possibility is to employ a more robust synchronization model, which
* would give a {@code RowSet} object increased trust in the provider's
* ability to get any updates back to the original data source. Another possibility
* is a more formal synchronization mechanism such as SyncML
* (<a href="http://www.syncml.org/">http://www.syncml.org/</a>) <br>
* @since 1.5
*/
package com.sun.rowset.providers;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,161 @@
/*
* Copyright (c) 2003, 2019, 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;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import java.io.*;
import java.math.*;
/**
* The standard interface that all standard implementations of
* <code>FilteredRowSet</code> must implement. The <code>FilteredRowSetImpl</code> class
* provides the reference implementation which may be extended if required.
* Alternatively, a vendor is free to implement its own version
* by implementing this interface.
*
* <h2>1.0 Background</h2>
*
* There are occasions when a <code>RowSet</code> object has a need to provide a degree
* of filtering to its contents. One possible solution is to provide
* a query language for all standard <code>RowSet</code> implementations; however,
* this is an impractical approach for lightweight components such as disconnected
* <code>RowSet</code>
* objects. The <code>FilteredRowSet</code> interface seeks to address this need
* without supplying a heavyweight query language along with the processing that
* such a query language would require.
* <p>
* A JDBC <code>FilteredRowSet</code> standard implementation implements the
* <code>RowSet</code> interfaces and extends the
* <code>CachedRowSet</code> class. The
* <code>CachedRowSet</code> class provides a set of protected cursor manipulation
* methods, which a <code>FilteredRowSet</code> implementation can override
* to supply filtering support.
*
* <h2>2.0 Predicate Sharing</h2>
*
* If a <code>FilteredRowSet</code> implementation is shared using the
* inherited <code>createShared</code> method in parent interfaces, the
* <code>Predicate</code> should be shared without modification by all
* <code>FilteredRowSet</code> instance clones.
*
* <h2>3.0 Usage</h2>
* <p>
* By implementing a <code>Predicate</code> (see example in <a href="Predicate.html">Predicate</a>
* class JavaDoc), a <code>FilteredRowSet</code> could then be used as described
* below.
*
* <pre>
* {@code
* FilteredRowSet frs = new FilteredRowSetImpl();
* frs.populate(rs);
*
* Range name = new Range("Alpha", "Bravo", "columnName");
* frs.setFilter(name);
*
* frs.next() // only names from "Alpha" to "Bravo" will be returned
* }
* </pre>
* In the example above, we initialize a <code>Range</code> object which
* implements the <code>Predicate</code> interface. This object expresses
* the following constraints: All rows outputted or modified from this
* <code>FilteredRowSet</code> object must fall between the values 'Alpha' and
* 'Bravo' both values inclusive, in the column 'columnName'. If a filter is
* applied to a <code>FilteredRowSet</code> object that contains no data that
* falls within the range of the filter, no rows are returned.
* <p>
* This framework allows multiple classes implementing predicates to be
* used in combination to achieved the required filtering result with
* out the need for query language processing.
*
* <h2>4.0 Updating a <code>FilteredRowSet</code> Object</h2>
* The predicate set on a <code>FilteredRowSet</code> object
* applies a criterion on all rows in a
* <code>RowSet</code> object to manage a subset of rows in a <code>RowSet</code>
* object. This criterion governs the subset of rows that are visible and also
* defines which rows can be modified, deleted or inserted.
* <p>
* Therefore, the predicate set on a <code>FilteredRowSet</code> object must be
* considered as bi-directional and the set criterion as the gating mechanism
* for all views and updates to the <code>FilteredRowSet</code> object. Any attempt
* to update the <code>FilteredRowSet</code> that violates the criterion will
* result in a <code>SQLException</code> object being thrown.
* <p>
* The <code>FilteredRowSet</code> range criterion can be modified by applying
* a new <code>Predicate</code> object to the <code>FilteredRowSet</code>
* instance at any time. This is possible if no additional references to the
* <code>FilteredRowSet</code> object are detected. A new filter has an
* immediate effect on criterion enforcement within the
* <code>FilteredRowSet</code> object, and all subsequent views and updates will be
* subject to similar enforcement.
*
* <h2>5.0 Behavior of Rows Outside the Filter</h2>
* Rows that fall outside of the filter set on a <code>FilteredRowSet</code>
* object cannot be modified until the filter is removed or a
* new filter is applied.
* <p>
* Furthermore, only rows that fall within the bounds of a filter will be
* synchronized with the data source.
*
* @author Jonathan Bruce
* @since 1.5
*/
public interface FilteredRowSet extends WebRowSet {
/**
* Applies the given <code>Predicate</code> object to this
* <code>FilteredRowSet</code>
* object. The filter applies controls both to inbound and outbound views,
* constraining which rows are visible and which
* rows can be manipulated.
* <p>
* A new <code>Predicate</code> object may be set at any time. This has the
* effect of changing constraints on the <code>RowSet</code> object's data.
* In addition, modifying the filter at runtime presents issues whereby
* multiple components may be operating on one <code>FilteredRowSet</code> object.
* Application developers must take responsibility for managing multiple handles
* to <code>FilteredRowSet</code> objects when their underling <code>Predicate</code>
* objects change.
*
* @param p a <code>Predicate</code> object defining the filter for this
* <code>FilteredRowSet</code> object. Setting a <b>null</b> value
* will clear the predicate, allowing all rows to become visible.
*
* @throws SQLException if an error occurs when setting the
* <code>Predicate</code> object
*/
public void setFilter(Predicate p) throws SQLException;
/**
* Retrieves the active filter for this <code>FilteredRowSet</code> object.
*
* @return p the <code>Predicate</code> for this <code>FilteredRowSet</code>
* object; <code>null</code> if no filter has been set.
*/
public Predicate getFilter() ;
}

View file

@ -0,0 +1,289 @@
/*
* Copyright (c) 2003, 2019, 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;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import java.io.*;
import java.math.*;
import java.io.*;
/**
* The standard interface that all standard implementations of
* <code>JdbcRowSet</code> must implement.
*
* <h2>1.0 Overview</h2>
* A wrapper around a <code>ResultSet</code> object that makes it possible
* to use the result set as a JavaBeans
* component. Thus, a <code>JdbcRowSet</code> object can be one of the Beans that
* a tool makes available for composing an application. Because
* a <code>JdbcRowSet</code> is a connected rowset, that is, it continually
* maintains its connection to a database using a JDBC technology-enabled
* driver, it also effectively makes the driver a JavaBeans component.
* <P>
* Because it is always connected to its database, an instance of
* <code>JdbcRowSet</code>
* can simply take calls invoked on it and in turn call them on its
* <code>ResultSet</code> object. As a consequence, a result set can, for
* example, be a component in a Swing application.
* <P>
* Another advantage of a <code>JdbcRowSet</code> object is that it can be
* used to make a <code>ResultSet</code> object scrollable and updatable. All
* <code>RowSet</code> objects are by default scrollable and updatable. If
* the driver and database being used do not support scrolling and/or updating
* of result sets, an application can populate a <code>JdbcRowSet</code> object
* with the data of a <code>ResultSet</code> object and then operate on the
* <code>JdbcRowSet</code> object as if it were the <code>ResultSet</code>
* object.
*
* <h2>2.0 Creating a <code>JdbcRowSet</code> Object</h2>
* The reference implementation of the <code>JdbcRowSet</code> interface,
* <code>JdbcRowSetImpl</code>, provides an implementation of
* the default constructor. A new instance is initialized with
* default values, which can be set with new values as needed. A
* new instance is not really functional until its <code>execute</code>
* method is called. In general, this method does the following:
* <UL>
* <LI> establishes a connection with a database
* <LI> creates a <code>PreparedStatement</code> object and sets any of its
* placeholder parameters
* <LI> executes the statement to create a <code>ResultSet</code> object
* </UL>
* If the <code>execute</code> method is successful, it will set the
* appropriate private <code>JdbcRowSet</code> fields with the following:
* <UL>
* <LI> a <code>Connection</code> object -- the connection between the rowset
* and the database
* <LI> a <code>PreparedStatement</code> object -- the query that produces
* the result set
* <LI> a <code>ResultSet</code> object -- the result set that the rowset's
* command produced and that is being made, in effect, a JavaBeans
* component
* </UL>
* If these fields have not been set, meaning that the <code>execute</code>
* method has not executed successfully, no methods other than
* <code>execute</code> and <code>close</code> may be called on the
* rowset. All other public methods will throw an exception.
* <P>
* Before calling the <code>execute</code> method, however, the command
* and properties needed for establishing a connection must be set.
* The following code fragment creates a <code>JdbcRowSetImpl</code> object,
* sets the command and connection properties, sets the placeholder parameter,
* and then invokes the method <code>execute</code>.
* <PRE>
* JdbcRowSetImpl jrs = new JdbcRowSetImpl();
* jrs.setCommand("SELECT * FROM TITLES WHERE TYPE = ?");
* jrs.setURL("jdbc:myDriver:myAttribute");
* jrs.setUsername("cervantes");
* jrs.setPassword("sancho");
* jrs.setString(1, "BIOGRAPHY");
* jrs.execute();
* </PRE>
* The variable <code>jrs</code> now represents an instance of
* <code>JdbcRowSetImpl</code> that is a thin wrapper around the
* <code>ResultSet</code> object containing all the rows in the
* table <code>TITLES</code> where the type of book is biography.
* At this point, operations called on <code>jrs</code> will
* affect the rows in the result set, which is effectively a JavaBeans
* component.
* <P>
* The implementation of the <code>RowSet</code> method <code>execute</code> in the
* <code>JdbcRowSet</code> reference implementation differs from that in the
* <code>CachedRowSet</code>
* reference implementation to account for the different
* requirements of connected and disconnected <code>RowSet</code> objects.
*
* @author Jonathan Bruce
* @since 1.5
*/
public interface JdbcRowSet extends RowSet, Joinable {
/**
* Retrieves a <code>boolean</code> indicating whether rows marked
* for deletion appear in the set of current rows. If <code>true</code> is
* returned, deleted rows are visible with the current rows. If
* <code>false</code> is returned, rows are not visible with the set of
* current rows. The default value is <code>false</code>.
* <P>
* Standard rowset implementations may choose to restrict this behavior
* for security considerations or for certain deployment
* scenarios. The visibility of deleted rows is implementation-defined
* and does not represent standard behavior.
* <P>
* Note: Allowing deleted rows to remain visible complicates the behavior
* of some standard JDBC <code>RowSet</code> implementations methods.
* However, most rowset users can simply ignore this extra detail because
* only very specialized applications will likely want to take advantage of
* this feature.
*
* @return <code>true</code> if deleted rows are visible;
* <code>false</code> otherwise
* @exception SQLException if a rowset implementation is unable to
* to determine whether rows marked for deletion remain visible
* @see #setShowDeleted
*/
public boolean getShowDeleted() throws SQLException;
/**
* Sets the property <code>showDeleted</code> to the given
* <code>boolean</code> value. This property determines whether
* rows marked for deletion continue to appear in the set of current rows.
* If the value is set to <code>true</code>, deleted rows are immediately
* visible with the set of current rows. If the value is set to
* <code>false</code>, the deleted rows are set as invisible with the
* current set of rows.
* <P>
* Standard rowset implementations may choose to restrict this behavior
* for security considerations or for certain deployment
* scenarios. This is left as implementation-defined and does not
* represent standard behavior.
*
* @param b <code>true</code> if deleted rows should be shown;
* <code>false</code> otherwise
* @exception SQLException if a rowset implementation is unable to
* to reset whether deleted rows should be visible
* @see #getShowDeleted
*/
public void setShowDeleted(boolean b) throws SQLException;
/**
* Retrieves the first warning reported by calls on this <code>JdbcRowSet</code>
* object.
* If a second warning was reported on this <code>JdbcRowSet</code> object,
* it will be chained to the first warning and can be retrieved by
* calling the method <code>RowSetWarning.getNextWarning</code> on the
* first warning. Subsequent warnings on this <code>JdbcRowSet</code>
* object will be chained to the <code>RowSetWarning</code> objects
* returned by the method <code>RowSetWarning.getNextWarning</code>.
*
* The warning chain is automatically cleared each time a new row is read.
* This method may not be called on a <code>RowSet</code> object
* that has been closed;
* doing so will cause an <code>SQLException</code> to be thrown.
* <P>
* Because it is always connected to its data source, a <code>JdbcRowSet</code>
* object can rely on the presence of active
* <code>Statement</code>, <code>Connection</code>, and <code>ResultSet</code>
* instances. This means that applications can obtain additional
* <code>SQLWarning</code>
* notifications by calling the <code>getNextWarning</code> methods that
* they provide.
* Disconnected <code>Rowset</code> objects, such as a
* <code>CachedRowSet</code> object, do not have access to
* these <code>getNextWarning</code> methods.
*
* @return the first <code>RowSetWarning</code>
* object reported on this <code>JdbcRowSet</code> object
* or <code>null</code> if there are none
* @throws SQLException if this method is called on a closed
* <code>JdbcRowSet</code> object
* @see RowSetWarning
*/
public RowSetWarning getRowSetWarnings() throws SQLException;
/**
* Each <code>JdbcRowSet</code> contains a <code>Connection</code> object from
* the <code>ResultSet</code> or JDBC properties passed to it's constructors.
* This method wraps the <code>Connection</code> commit method to allow flexible
* auto commit or non auto commit transactional control support.
* <p>
* Makes all changes made since the previous commit/rollback permanent
* and releases any database locks currently held by this Connection
* object. This method should be used only when auto-commit mode has
* been disabled.
*
* @throws SQLException if a database access error occurs or this
* Connection object within this <code>JdbcRowSet</code> is in auto-commit mode
* @see java.sql.Connection#setAutoCommit
*/
public void commit() throws SQLException;
/**
* Each <code>JdbcRowSet</code> contains a <code>Connection</code> object from
* the original <code>ResultSet</code> or JDBC properties passed to it. This
* method wraps the <code>Connection</code>'s <code>getAutoCommit</code> method
* to allow an application to determine the <code>JdbcRowSet</code> transaction
* behavior.
* <p>
* Sets this connection's auto-commit mode to the given state. If a
* connection is in auto-commit mode, then all its SQL statements will
* be executed and committed as individual transactions. Otherwise, its
* SQL statements are grouped into transactions that are terminated by a
* call to either the method commit or the method rollback. By default,
* new connections are in auto-commit mode.
*
* @return {@code true} if auto-commit is enabled; {@code false} otherwise
* @throws SQLException if a database access error occurs
* @see java.sql.Connection#getAutoCommit()
*/
public boolean getAutoCommit() throws SQLException;
/**
* Each <code>JdbcRowSet</code> contains a <code>Connection</code> object from
* the original <code>ResultSet</code> or JDBC properties passed to it. This
* method wraps the <code>Connection</code>'s <code>getAutoCommit</code> method
* to allow an application to set the <code>JdbcRowSet</code> transaction behavior.
* <p>
* Sets the current auto-commit mode for this <code>Connection</code> object.
* @param autoCommit {@code true} to enable auto-commit; {@code false} to
* disable auto-commit
* @throws SQLException if a database access error occurs
* @see java.sql.Connection#setAutoCommit(boolean)
*/
public void setAutoCommit(boolean autoCommit) throws SQLException;
/**
* Each <code>JdbcRowSet</code> contains a <code>Connection</code> object from
* the original <code>ResultSet</code> or JDBC properties passed to it.
* Undoes all changes made in the current transaction and releases any
* database locks currently held by this <code>Connection</code> object. This method
* should be used only when auto-commit mode has been disabled.
*
* @throws SQLException if a database access error occurs or this <code>Connection</code>
* object within this <code>JdbcRowSet</code> is in auto-commit mode.
* @see #rollback(Savepoint)
*/
public void rollback() throws SQLException;
/**
* Each <code>JdbcRowSet</code> contains a <code>Connection</code> object from
* the original <code>ResultSet</code> or JDBC properties passed to it.
* Undoes all changes made in the current transaction to the last set savepoint
* and releases any database locks currently held by this <code>Connection</code>
* object. This method should be used only when auto-commit mode has been disabled.
* @param s The {@code Savepoint} to rollback to
* @throws SQLException if a database access error occurs or this <code>Connection</code>
* object within this <code>JdbcRowSet</code> is in auto-commit mode.
* @see #rollback
*/
public void rollback(Savepoint s) throws SQLException;
}

View file

@ -0,0 +1,537 @@
/*
* Copyright (c) 2003, 2019, 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;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import java.io.*;
import java.math.*;
import java.util.*;
import javax.sql.rowset.*;
/**
* The <code>JoinRowSet</code> interface provides a mechanism for combining related
* data from different <code>RowSet</code> objects into one <code>JoinRowSet</code>
* object, which represents an SQL <code>JOIN</code>.
* In other words, a <code>JoinRowSet</code> object acts as a
* container for the data from <code>RowSet</code> objects that form an SQL
* <code>JOIN</code> relationship.
* <P>
* The <code>Joinable</code> interface provides the methods for setting,
* retrieving, and unsetting a match column, the basis for
* establishing an SQL <code>JOIN</code> relationship. The match column may
* alternatively be set by supplying it to the appropriate version of the
* <code>JointRowSet</code> method <code>addRowSet</code>.
*
* <h2>1.0 Overview</h2>
* Disconnected <code>RowSet</code> objects (<code>CachedRowSet</code> objects
* and implementations extending the <code>CachedRowSet</code> interface)
* do not have a standard way to establish an SQL <code>JOIN</code> between
* <code>RowSet</code> objects without the expensive operation of
* reconnecting to the data source. The <code>JoinRowSet</code>
* interface is specifically designed to address this need.
* <P>
* Any <code>RowSet</code> object
* can be added to a <code>JoinRowSet</code> object to become
* part of an SQL <code>JOIN</code> relationship. This means that both connected
* and disconnected <code>RowSet</code> objects can be part of a <code>JOIN</code>.
* <code>RowSet</code> objects operating in a connected environment
* (<code>JdbcRowSet</code> objects) are
* encouraged to use the database to which they are already
* connected to establish SQL <code>JOIN</code> relationships between
* tables directly. However, it is possible for a
* <code>JdbcRowSet</code> object to be added to a <code>JoinRowSet</code> object
* if necessary.
* <P>
* Any number of <code>RowSet</code> objects can be added to an
* instance of <code>JoinRowSet</code> provided that they
* can be related in an SQL <code>JOIN</code>.
* By definition, the SQL <code>JOIN</code> statement is used to
* combine the data contained in two or more relational database tables based
* upon a common attribute. The <code>Joinable</code> interface provides the methods
* for establishing a common attribute, which is done by setting a
* <i>match column</i>. The match column commonly coincides with
* the primary key, but there is
* no requirement that the match column be the same as the primary key.
* By establishing and then enforcing column matches,
* a <code>JoinRowSet</code> object establishes <code>JOIN</code> relationships
* between <code>RowSet</code> objects without the assistance of an available
* relational database.
* <P>
* The type of <code>JOIN</code> to be established is determined by setting
* one of the <code>JoinRowSet</code> constants using the method
* <code>setJoinType</code>. The following SQL <code>JOIN</code> types can be set:
* <UL>
* <LI><code>CROSS_JOIN</code>
* <LI><code>FULL_JOIN</code>
* <LI><code>INNER_JOIN</code> - the default if no <code>JOIN</code> type has been set
* <LI><code>LEFT_OUTER_JOIN</code>
* <LI><code>RIGHT_OUTER_JOIN</code>
* </UL>
* Note that if no type is set, the <code>JOIN</code> will automatically be an
* inner join. The comments for the fields in the
* <code>JoinRowSet</code> interface explain these <code>JOIN</code> types, which are
* standard SQL <code>JOIN</code> types.
*
* <h2>2.0 Using a <code>JoinRowSet</code> Object for Creating a <code>JOIN</code></h2>
* When a <code>JoinRowSet</code> object is created, it is empty.
* The first <code>RowSet</code> object to be added becomes the basis for the
* <code>JOIN</code> relationship.
* Applications must determine which column in each of the
* <code>RowSet</code> objects to be added to the <code>JoinRowSet</code> object
* should be the match column. All of the
* <code>RowSet</code> objects must contain a match column, and the values in
* each match column must be ones that can be compared to values in the other match
* columns. The columns do not have to have the same name, though they often do,
* and they do not have to store the exact same data type as long as the data types
* can be compared.
* <P>
* A match column can be set in two ways:
* <ul>
* <li>By calling the <code>Joinable</code> method <code>setMatchColumn</code><br>
* This is the only method that can set the match column before a <code>RowSet</code>
* object is added to a <code>JoinRowSet</code> object. The <code>RowSet</code> object
* must have implemented the <code>Joinable</code> interface in order to use the method
* <code>setMatchColumn</code>. Once the match column value
* has been set, this method can be used to reset the match column at any time.
* <li>By calling one of the versions of the <code>JoinRowSet</code> method
* <code>addRowSet</code> that takes a column name or number (or an array of
* column names or numbers)<BR>
* Four of the five <code>addRowSet</code> methods take a match column as a parameter.
* These four methods set or reset the match column at the time a <code>RowSet</code>
* object is being added to a <code>JoinRowSet</code> object.
* </ul>
* <h2>3.0 Sample Usage</h2>
* <p>
* The following code fragment adds two <code>CachedRowSet</code>
* objects to a <code>JoinRowSet</code> object. Note that in this example,
* no SQL <code>JOIN</code> type is set, so the default <code>JOIN</code> type,
* which is <i>INNER_JOIN</i>, is established.
* <p>
* In the following code fragment, the table <code>EMPLOYEES</code>, whose match
* column is set to the first column (<code>EMP_ID</code>), is added to the
* <code>JoinRowSet</code> object <i>jrs</i>. Then
* the table <code>ESSP_BONUS_PLAN</code>, whose match column is likewise
* the <code>EMP_ID</code> column, is added. When this second
* table is added to <i>jrs</i>, only the rows in
* <code>ESSP_BONUS_PLAN</code> whose <code>EMP_ID</code> value matches an
* <code>EMP_ID</code> value in the <code>EMPLOYEES</code> table are added.
* In this case, everyone in the bonus plan is an employee, so all of the rows
* in the table <code>ESSP_BONUS_PLAN</code> are added to the <code>JoinRowSet</code>
* object. In this example, both <code>CachedRowSet</code> objects being added
* have implemented the <code>Joinable</code> interface and can therefore call
* the <code>Joinable</code> method <code>setMatchColumn</code>.
* <PRE>
* JoinRowSet jrs = new JoinRowSetImpl();
*
* ResultSet rs1 = stmt.executeQuery("SELECT * FROM EMPLOYEES");
* CachedRowSet empl = new CachedRowSetImpl();
* empl.populate(rs1);
* empl.setMatchColumn(1);
* jrs.addRowSet(empl);
*
* ResultSet rs2 = stmt.executeQuery("SELECT * FROM ESSP_BONUS_PLAN");
* CachedRowSet bonus = new CachedRowSetImpl();
* bonus.populate(rs2);
* bonus.setMatchColumn(1); // EMP_ID is the first column
* jrs.addRowSet(bonus);
* </PRE>
* <P>
* At this point, <i>jrs</i> is an inside JOIN of the two <code>RowSet</code> objects
* based on their <code>EMP_ID</code> columns. The application can now browse the
* combined data as if it were browsing one single <code>RowSet</code> object.
* Because <i>jrs</i> is itself a <code>RowSet</code> object, an application can
* navigate or modify it using <code>RowSet</code> methods.
* <PRE>
* jrs.first();
* int employeeID = jrs.getInt(1);
* String employeeName = jrs.getString(2);
* </PRE>
* <P>
* Note that because the SQL <code>JOIN</code> must be enforced when an application
* adds a second or subsequent <code>RowSet</code> object, there
* may be an initial degradation in performance while the <code>JOIN</code> is
* being performed.
* <P>
* The following code fragment adds an additional <code>CachedRowSet</code> object.
* In this case, the match column (<code>EMP_ID</code>) is set when the
* <code>CachedRowSet</code> object is added to the <code>JoinRowSet</code> object.
* <PRE>
* ResultSet rs3 = stmt.executeQuery("SELECT * FROM 401K_CONTRIB");
* CachedRowSet fourO1k = new CachedRowSetImpl();
* four01k.populate(rs3);
* jrs.addRowSet(four01k, 1);
* </PRE>
* <P>
* The <code>JoinRowSet</code> object <i>jrs</i> now contains values from all three
* tables. The data in each row in <i>four01k</i> in which the value for the
* <code>EMP_ID</code> column matches a value for the <code>EMP_ID</code> column
* in <i>jrs</i> has been added to <i>jrs</i>.
*
* <h2>4.0 <code>JoinRowSet</code> Methods</h2>
* The <code>JoinRowSet</code> interface supplies several methods for adding
* <code>RowSet</code> objects and for getting information about the
* <code>JoinRowSet</code> object.
* <UL>
* <LI>Methods for adding one or more <code>RowSet</code> objects<BR>
* These methods allow an application to add one <code>RowSet</code> object
* at a time or to add multiple <code>RowSet</code> objects at one time. In
* either case, the methods may specify the match column for each
* <code>RowSet</code> object being added.
* <LI>Methods for getting information<BR>
* One method retrieves the <code>RowSet</code> objects in the
* <code>JoinRowSet</code> object, and another method retrieves the
* <code>RowSet</code> names. A third method retrieves either the SQL
* <code>WHERE</code> clause used behind the scenes to form the
* <code>JOIN</code> or a text description of what the <code>WHERE</code>
* clause does.
* <LI>Methods related to the type of <code>JOIN</code><BR>
* One method sets the <code>JOIN</code> type, and five methods find out whether
* the <code>JoinRowSet</code> object supports a given type.
* <LI>A method to make a separate copy of the <code>JoinRowSet</code> object<BR>
* This method creates a copy that can be persisted to the data source.
* </UL>
*
* @since 1.5
*/
public interface JoinRowSet extends WebRowSet {
/**
* Adds the given <code>RowSet</code> object to this <code>JoinRowSet</code>
* object. If the <code>RowSet</code> object
* is the first to be added to this <code>JoinRowSet</code>
* object, it forms the basis of the <code>JOIN</code> relationship to be
* established.
* <P>
* This method should be used only when the given <code>RowSet</code>
* object already has a match column that was set with the <code>Joinable</code>
* method <code>setMatchColumn</code>.
* <p>
* Note: A <code>Joinable</code> object is any <code>RowSet</code> object
* that has implemented the <code>Joinable</code> interface.
*
* @param rowset the <code>RowSet</code> object that is to be added to this
* <code>JoinRowSet</code> object; it must implement the
* <code>Joinable</code> interface and have a match column set
* @throws SQLException if (1) an empty rowset is added to the to this
* <code>JoinRowSet</code> object, (2) a match column has not been
* set for <i>rowset</i>, or (3) <i>rowset</i>
* violates the active <code>JOIN</code>
* @see Joinable#setMatchColumn
*/
public void addRowSet(Joinable rowset) throws SQLException;
/**
* Adds the given <code>RowSet</code> object to this <code>JoinRowSet</code>
* object and sets the designated column as the match column for
* the <code>RowSet</code> object. If the <code>RowSet</code> object
* is the first to be added to this <code>JoinRowSet</code>
* object, it forms the basis of the <code>JOIN</code> relationship to be
* established.
* <P>
* This method should be used when <i>RowSet</i> does not already have a match
* column set.
*
* @param rowset the <code>RowSet</code> object that is to be added to this
* <code>JoinRowSet</code> object; it may implement the
* <code>Joinable</code> interface
* @param columnIdx an <code>int</code> that identifies the column to become the
* match column
* @throws SQLException if (1) <i>rowset</i> is an empty rowset or
* (2) <i>rowset</i> violates the active <code>JOIN</code>
* @see Joinable#unsetMatchColumn
*/
public void addRowSet(RowSet rowset, int columnIdx) throws SQLException;
/**
* Adds <i>rowset</i> to this <code>JoinRowSet</code> object and
* sets the designated column as the match column. If <i>rowset</i>
* is the first to be added to this <code>JoinRowSet</code>
* object, it forms the basis for the <code>JOIN</code> relationship to be
* established.
* <P>
* This method should be used when the given <code>RowSet</code> object
* does not already have a match column.
*
* @param rowset the <code>RowSet</code> object that is to be added to this
* <code>JoinRowSet</code> object; it may implement the
* <code>Joinable</code> interface
* @param columnName the <code>String</code> object giving the name of the
* column to be set as the match column
* @throws SQLException if (1) <i>rowset</i> is an empty rowset or
* (2) the match column for <i>rowset</i> does not satisfy the
* conditions of the <code>JOIN</code>
*/
public void addRowSet(RowSet rowset,
String columnName) throws SQLException;
/**
* Adds one or more <code>RowSet</code> objects contained in the given
* array of <code>RowSet</code> objects to this <code>JoinRowSet</code>
* object and sets the match column for
* each of the <code>RowSet</code> objects to the match columns
* in the given array of column indexes. The first element in
* <i>columnIdx</i> is set as the match column for the first
* <code>RowSet</code> object in <i>rowset</i>, the second element of
* <i>columnIdx</i> is set as the match column for the second element
* in <i>rowset</i>, and so on.
* <P>
* The first <code>RowSet</code> object added to this <code>JoinRowSet</code>
* object forms the basis for the <code>JOIN</code> relationship.
* <P>
* This method should be used when the given <code>RowSet</code> object
* does not already have a match column.
*
* @param rowset an array of one or more <code>RowSet</code> objects
* to be added to the <code>JOIN</code>; it may implement the
* <code>Joinable</code> interface
* @param columnIdx an array of <code>int</code> values indicating the index(es)
* of the columns to be set as the match columns for the <code>RowSet</code>
* objects in <i>rowset</i>
* @throws SQLException if (1) an empty rowset is added to this
* <code>JoinRowSet</code> object, (2) a match column is not set
* for a <code>RowSet</code> object in <i>rowset</i>, or (3)
* a <code>RowSet</code> object being added violates the active
* <code>JOIN</code>
*/
public void addRowSet(RowSet[] rowset,
int[] columnIdx) throws SQLException;
/**
* Adds one or more <code>RowSet</code> objects contained in the given
* array of <code>RowSet</code> objects to this <code>JoinRowSet</code>
* object and sets the match column for
* each of the <code>RowSet</code> objects to the match columns
* in the given array of column names. The first element in
* <i>columnName</i> is set as the match column for the first
* <code>RowSet</code> object in <i>rowset</i>, the second element of
* <i>columnName</i> is set as the match column for the second element
* in <i>rowset</i>, and so on.
* <P>
* The first <code>RowSet</code> object added to this <code>JoinRowSet</code>
* object forms the basis for the <code>JOIN</code> relationship.
* <P>
* This method should be used when the given <code>RowSet</code> object(s)
* does not already have a match column.
*
* @param rowset an array of one or more <code>RowSet</code> objects
* to be added to the <code>JOIN</code>; it may implement the
* <code>Joinable</code> interface
* @param columnName an array of <code>String</code> values indicating the
* names of the columns to be set as the match columns for the
* <code>RowSet</code> objects in <i>rowset</i>
* @throws SQLException if (1) an empty rowset is added to this
* <code>JoinRowSet</code> object, (2) a match column is not set
* for a <code>RowSet</code> object in <i>rowset</i>, or (3)
* a <code>RowSet</code> object being added violates the active
* <code>JOIN</code>
*/
public void addRowSet(RowSet[] rowset,
String[] columnName) throws SQLException;
/**
* Returns a <code>Collection</code> object containing the
* <code>RowSet</code> objects that have been added to this
* <code>JoinRowSet</code> object.
* This should return the 'n' number of RowSet contained
* within the <code>JOIN</code> and maintain any updates that have occurred while in
* this union.
*
* @return a <code>Collection</code> object consisting of the
* <code>RowSet</code> objects added to this <code>JoinRowSet</code>
* object
* @throws SQLException if an error occurs generating the
* <code>Collection</code> object to be returned
*/
public Collection<?> getRowSets() throws java.sql.SQLException;
/**
* Returns a <code>String</code> array containing the names of the
* <code>RowSet</code> objects added to this <code>JoinRowSet</code>
* object.
*
* @return a <code>String</code> array of the names of the
* <code>RowSet</code> objects in this <code>JoinRowSet</code>
* object
* @throws SQLException if an error occurs retrieving the names of
* the <code>RowSet</code> objects
* @see CachedRowSet#setTableName
*/
public String[] getRowSetNames() throws java.sql.SQLException;
/**
* Creates a new <code>CachedRowSet</code> object containing the
* data in this <code>JoinRowSet</code> object, which can be saved
* to a data source using the <code>SyncProvider</code> object for
* the <code>CachedRowSet</code> object.
* <P>
* If any updates or modifications have been applied to the JoinRowSet
* the CachedRowSet returned by the method will not be able to persist
* it's changes back to the originating rows and tables in the
* in the datasource. The CachedRowSet instance returned should not
* contain modification data and it should clear all properties of
* it's originating SQL statement. An application should reset the
* SQL statement using the <code>RowSet.setCommand</code> method.
* <p>
* In order to allow changes to be persisted back to the datasource
* to the originating tables, the <code>acceptChanges</code> method
* should be used and called on a JoinRowSet object instance. Implementations
* can leverage the internal data and update tracking in their
* implementations to interact with the SyncProvider to persist any
* changes.
*
* @return a CachedRowSet containing the contents of the JoinRowSet
* @throws SQLException if an error occurs assembling the CachedRowSet
* object
* @see javax.sql.RowSet
* @see javax.sql.rowset.CachedRowSet
* @see javax.sql.rowset.spi.SyncProvider
*/
public CachedRowSet toCachedRowSet() throws java.sql.SQLException;
/**
* Indicates if CROSS_JOIN is supported by a JoinRowSet
* implementation
*
* @return true if the CROSS_JOIN is supported; false otherwise
*/
public boolean supportsCrossJoin();
/**
* Indicates if INNER_JOIN is supported by a JoinRowSet
* implementation
*
* @return true is the INNER_JOIN is supported; false otherwise
*/
public boolean supportsInnerJoin();
/**
* Indicates if LEFT_OUTER_JOIN is supported by a JoinRowSet
* implementation
*
* @return true is the LEFT_OUTER_JOIN is supported; false otherwise
*/
public boolean supportsLeftOuterJoin();
/**
* Indicates if RIGHT_OUTER_JOIN is supported by a JoinRowSet
* implementation
*
* @return true is the RIGHT_OUTER_JOIN is supported; false otherwise
*/
public boolean supportsRightOuterJoin();
/**
* Indicates if FULL_JOIN is supported by a JoinRowSet
* implementation
*
* @return true is the FULL_JOIN is supported; false otherwise
*/
public boolean supportsFullJoin();
/**
* Allow the application to adjust the type of <code>JOIN</code> imposed
* on tables contained within the JoinRowSet object instance.
* Implementations should throw a SQLException if they do
* not support a given <code>JOIN</code> type.
*
* @param joinType the standard JoinRowSet.XXX static field definition
* of a SQL <code>JOIN</code> to re-configure a JoinRowSet instance on
* the fly.
* @throws SQLException if an unsupported <code>JOIN</code> type is set
* @see #getJoinType
*/
public void setJoinType(int joinType) throws SQLException;
/**
* Return a SQL-like description of the WHERE clause being used
* in a JoinRowSet object. An implementation can describe
* the WHERE clause of the SQL <code>JOIN</code> by supplying a SQL
* strings description of <code>JOIN</code> or provide a textual
* description to assist applications using a <code>JoinRowSet</code>
*
* @return whereClause a textual or SQL description of the logical
* WHERE clause used in the JoinRowSet instance
* @throws SQLException if an error occurs in generating a representation
* of the WHERE clause.
*/
public String getWhereClause() throws SQLException;
/**
* Returns a <code>int</code> describing the set SQL <code>JOIN</code> type
* governing this JoinRowSet instance. The returned type will be one of
* standard JoinRowSet types: <code>CROSS_JOIN</code>, <code>INNER_JOIN</code>,
* <code>LEFT_OUTER_JOIN</code>, <code>RIGHT_OUTER_JOIN</code> or
* <code>FULL_JOIN</code>.
*
* @return joinType one of the standard JoinRowSet static field
* definitions of a SQL <code>JOIN</code>. <code>JoinRowSet.INNER_JOIN</code>
* is returned as the default <code>JOIN</code> type is no type has been
* explicitly set.
* @throws SQLException if an error occurs determining the SQL <code>JOIN</code>
* type supported by the JoinRowSet instance.
* @see #setJoinType
*/
public int getJoinType() throws SQLException;
/**
* An ANSI-style <code>JOIN</code> providing a cross product of two tables
*/
public static int CROSS_JOIN = 0;
/**
* An ANSI-style <code>JOIN</code> providing a inner join between two tables. Any
* unmatched rows in either table of the join should be discarded.
*/
public static int INNER_JOIN = 1;
/**
* An ANSI-style <code>JOIN</code> providing a left outer join between two
* tables. In SQL, this is described where all records should be
* returned from the left side of the JOIN statement.
*/
public static int LEFT_OUTER_JOIN = 2;
/**
* An ANSI-style <code>JOIN</code> providing a right outer join between
* two tables. In SQL, this is described where all records from the
* table on the right side of the JOIN statement even if the table
* on the left has no matching record.
*/
public static int RIGHT_OUTER_JOIN = 3;
/**
* An ANSI-style <code>JOIN</code> providing a full JOIN. Specifies that all
* rows from either table be returned regardless of matching
* records on the other table.
*/
public static int FULL_JOIN = 4;
}

View file

@ -0,0 +1,292 @@
/*
* Copyright (c) 2003, 2019, 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;
import java.sql.SQLException;
/**
* <h2>1.0 Background</h2>
* The <code>Joinable</code> interface provides the methods for getting and
* setting a match column, which is the basis for forming the SQL <code>JOIN</code>
* formed by adding <code>RowSet</code> objects to a <code>JoinRowSet</code>
* object.
* <P>
* Any standard <code>RowSet</code> implementation <b>may</b> implement
* the <code>Joinable</code> interface in order to be
* added to a <code>JoinRowSet</code> object. Implementing this interface gives
* a <code>RowSet</code> object the ability to use <code>Joinable</code> methods,
* which set, retrieve, and get information about match columns. An
* application may add a
* <code>RowSet</code> object that has not implemented the <code>Joinable</code>
* interface to a <code>JoinRowSet</code> object, but to do so it must use one
* of the <code>JoinRowSet.addRowSet</code> methods that takes both a
* <code>RowSet</code> object and a match column or an array of <code>RowSet</code>
* objects and an array of match columns.
* <P>
* To get access to the methods in the <code>Joinable</code> interface, a
* <code>RowSet</code> object implements at least one of the
* five standard <code>RowSet</code> interfaces and also implements the
* <code>Joinable</code> interface. In addition, most <code>RowSet</code>
* objects extend the <code>BaseRowSet</code> class. For example:
* <pre>
* class MyRowSetImpl extends BaseRowSet implements CachedRowSet, Joinable {
* :
* :
* }
* </pre>
*
* <h2>2.0 Usage Guidelines</h2>
* <P>
* The methods in the <code>Joinable</code> interface allow a <code>RowSet</code> object
* to set a match column, retrieve a match column, or unset a match column, which is
* the column upon which an SQL <code>JOIN</code> can be based.
* An instance of a class that implements these methods can be added to a
* <code>JoinRowSet</code> object to allow an SQL <code>JOIN</code> relationship to
* be established.
*
* <pre>
* CachedRowSet crs = new MyRowSetImpl();
* crs.populate((ResultSet)rs);
* (Joinable)crs.setMatchColumnIndex(1);
*
* JoinRowSet jrs = new JoinRowSetImpl();
* jrs.addRowSet(crs);
* </pre>
* In the previous example, <i>crs</i> is a <code>CachedRowSet</code> object that
* has implemented the <code>Joinable</code> interface. In the following example,
* <i>crs2</i> has not, so it must supply the match column as an argument to the
* <code>addRowSet</code> method. This example assumes that column 1 is the match
* column.
* <PRE>
* CachedRowSet crs2 = new MyRowSetImpl();
* crs2.populate((ResultSet)rs);
*
* JoinRowSet jrs2 = new JoinRowSetImpl();
* jrs2.addRowSet(crs2, 1);
* </PRE>
* <p>
* The <code>JoinRowSet</code> interface makes it possible to get data from one or
* more <code>RowSet</code> objects consolidated into one table without having to incur
* the expense of creating a connection to a database. It is therefore ideally suited
* for use by disconnected <code>RowSet</code> objects. Nevertheless, any
* <code>RowSet</code> object <b>may</b> implement this interface
* regardless of whether it is connected or disconnected. Note that a
* <code>JdbcRowSet</code> object, being always connected to its data source, can
* become part of an SQL <code>JOIN</code> directly without having to become part
* of a <code>JoinRowSet</code> object.
*
* <h2>3.0 Managing Multiple Match Columns</h2>
* The index array passed into the <code>setMatchColumn</code> methods indicates
* how many match columns are being set (the length of the array) in addition to
* which columns will be used for the match. For example:
* <pre>
* int[] i = {1, 2, 4, 7}; // indicates four match columns, with column
* // indexes 1, 2, 4, 7 participating in the JOIN.
* Joinable.setMatchColumn(i);
* </pre>
* Subsequent match columns may be added as follows to a different <code>Joinable</code>
* object (a <code>RowSet</code> object that has implemented the <code>Joinable</code>
* interface).
* <pre>
* int[] w = {3, 2, 5, 3};
* Joinable2.setMatchColumn(w);
* </pre>
* When an application adds two or more <code>RowSet</code> objects to a
* <code>JoinRowSet</code> object, the order of the indexes in the array is
* particularly important. Each index of
* the array maps directly to the corresponding index of the previously added
* <code>RowSet</code> object. If overlap or underlap occurs, the match column
* data is maintained in the event an additional <code>Joinable</code> RowSet is
* added and needs to relate to the match column data. Therefore, applications
* can set multiple match columns in any order, but
* this order has a direct effect on the outcome of the <code>SQL</code> JOIN.
* <p>
* This assertion applies in exactly the same manner when column names are used
* rather than column indexes to indicate match columns.
*
* @see JoinRowSet
* @author Jonathan Bruce
* @since 1.5
*/
public interface Joinable {
/**
* Sets the designated column as the match column for this <code>RowSet</code>
* object. A <code>JoinRowSet</code> object can now add this <code>RowSet</code>
* object based on the match column.
* <p>
* Sub-interfaces such as the <code>CachedRowSet</code>
* interface define the method <code>CachedRowSet.setKeyColumns</code>, which allows
* primary key semantics to be enforced on specific columns.
* Implementations of the <code>setMatchColumn(int columnIdx)</code> method
* should ensure that the constraints on the key columns are maintained when
* a <code>CachedRowSet</code> object sets a primary key column as a match column.
*
* @param columnIdx an <code>int</code> identifying the index of the column to be
* set as the match column
* @throws SQLException if an invalid column index is set
* @see #setMatchColumn(int[])
* @see #unsetMatchColumn(int)
*
*/
public void setMatchColumn(int columnIdx) throws SQLException;
/**
* Sets the designated columns as the match column for this <code>RowSet</code>
* object. A <code>JoinRowSet</code> object can now add this <code>RowSet</code>
* object based on the match column.
*
* @param columnIdxes an array of <code>int</code> identifying the indexes of the
* columns to be set as the match columns
* @throws SQLException if an invalid column index is set
* @see #setMatchColumn(int[])
* @see #unsetMatchColumn(int[])
*/
public void setMatchColumn(int[] columnIdxes) throws SQLException;
/**
* Sets the designated column as the match column for this <code>RowSet</code>
* object. A <code>JoinRowSet</code> object can now add this <code>RowSet</code>
* object based on the match column.
* <p>
* Subinterfaces such as the <code>CachedRowSet</code> interface define
* the method <code>CachedRowSet.setKeyColumns</code>, which allows
* primary key semantics to be enforced on specific columns.
* Implementations of the <code>setMatchColumn(String columnIdx)</code> method
* should ensure that the constraints on the key columns are maintained when
* a <code>CachedRowSet</code> object sets a primary key column as a match column.
*
* @param columnName a <code>String</code> object giving the name of the column
* to be set as the match column
* @throws SQLException if an invalid column name is set, the column name
* is a null, or the column name is an empty string
* @see #unsetMatchColumn
* @see #setMatchColumn(int[])
*/
public void setMatchColumn(String columnName) throws SQLException;
/**
* Sets the designated columns as the match column for this <code>RowSet</code>
* object. A <code>JoinRowSet</code> object can now add this <code>RowSet</code>
* object based on the match column.
*
* @param columnNames an array of <code>String</code> objects giving the names
* of the column to be set as the match columns
* @throws SQLException if an invalid column name is set, the column name
* is a null, or the column name is an empty string
* @see #unsetMatchColumn
* @see #setMatchColumn(int[])
*/
public void setMatchColumn(String[] columnNames) throws SQLException;
/**
* Retrieves the indexes of the match columns that were set for this
* <code>RowSet</code> object with the method
* <code>setMatchColumn(int[] columnIdxes)</code>.
*
* @return an <code>int</code> array identifying the indexes of the columns
* that were set as the match columns for this <code>RowSet</code> object
* @throws SQLException if no match column has been set
* @see #setMatchColumn
* @see #unsetMatchColumn
*/
public int[] getMatchColumnIndexes() throws SQLException;
/**
* Retrieves the names of the match columns that were set for this
* <code>RowSet</code> object with the method
* <code>setMatchColumn(String [] columnNames)</code>.
*
* @return an array of <code>String</code> objects giving the names of the columns
* set as the match columns for this <code>RowSet</code> object
* @throws SQLException if no match column has been set
* @see #setMatchColumn
* @see #unsetMatchColumn
*
*/
public String[] getMatchColumnNames() throws SQLException;
/**
* Unsets the designated column as the match column for this <code>RowSet</code>
* object.
* <P>
* <code>RowSet</code> objects that implement the <code>Joinable</code> interface
* must ensure that a key-like constraint continues to be enforced until the
* method <code>CachedRowSet.unsetKeyColumns</code> has been called on the
* designated column.
*
* @param columnIdx an <code>int</code> that identifies the index of the column
* that is to be unset as a match column
* @throws SQLException if an invalid column index is designated or if
* the designated column was not previously set as a match
* column
* @see #setMatchColumn
*/
public void unsetMatchColumn(int columnIdx) throws SQLException;
/**
* Unsets the designated columns as the match column for this <code>RowSet</code>
* object.
*
* @param columnIdxes an array of <code>int</code> that identifies the indexes
* of the columns that are to be unset as match columns
* @throws SQLException if an invalid column index is designated or if
* the designated column was not previously set as a match
* column
* @see #setMatchColumn
*/
public void unsetMatchColumn(int[] columnIdxes) throws SQLException;
/**
* Unsets the designated column as the match column for this <code>RowSet</code>
* object.
* <P>
* <code>RowSet</code> objects that implement the <code>Joinable</code> interface
* must ensure that a key-like constraint continues to be enforced until the
* method <code>CachedRowSet.unsetKeyColumns</code> has been called on the
* designated column.
*
* @param columnName a <code>String</code> object giving the name of the column
* that is to be unset as a match column
* @throws SQLException if an invalid column name is designated or
* the designated column was not previously set as a match
* column
* @see #setMatchColumn
*/
public void unsetMatchColumn(String columnName) throws SQLException;
/**
* Unsets the designated columns as the match columns for this <code>RowSet</code>
* object.
*
* @param columnName an array of <code>String</code> objects giving the names of
* the columns that are to be unset as the match columns
* @throws SQLException if an invalid column name is designated or the
* designated column was not previously set as a match column
* @see #setMatchColumn
*/
public void unsetMatchColumn(String[] columnName) throws SQLException;
}

View file

@ -0,0 +1,163 @@
/*
* Copyright (c) 2003, 2019, 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;
import javax.sql.*;
import java.sql.*;
/**
* The standard interface that provides the framework for all
* <code>FilteredRowSet</code> objects to describe their filters.
*
* <h2>1.0 Background</h2>
* The <code>Predicate</code> interface is a standard interface that
* applications can implement to define the filter they wish to apply to a
* a <code>FilteredRowSet</code> object. A <code>FilteredRowSet</code>
* object consumes implementations of this interface and enforces the
* constraints defined in the implementation of the method <code>evaluate</code>.
* A <code>FilteredRowSet</code> object enforces the filter constraints in a
* bi-directional manner: It outputs only rows that are within
* the constraints of the filter; and conversely, it inserts, modifies, or updates
* only rows that are within the constraints of the filter.
*
* <h2>2.0 Implementation Guidelines</h2>
* In order to supply a predicate for the <code>FilteredRowSet</code>.
* this interface must be implemented. At this time, the JDBC RowSet
* Implementations (JSR-114) does not specify any standard filters definitions.
* By specifying a standard means and mechanism for a range of filters to be
* defined and deployed with both the reference and vendor implementations
* of the <code>FilteredRowSet</code> interface, this allows for a flexible
* and application motivated implementations of <code>Predicate</code> to emerge.
* <p>
* A sample implementation would look something like this:
* <pre>{@code
* public class Range implements Predicate {
*
* private int[] lo;
* private int[] hi;
* private int[] idx;
*
* public Range(int[] lo, int[] hi, int[] idx) {
* this.lo = lo;
* this.hi = hi;
* this.idx = idx;
* }
*
* public boolean evaluate(RowSet rs) {
*
* // Check the present row determine if it lies
* // within the filtering criteria.
*
* for (int i = 0; i < idx.length; i++) {
* int value;
* try {
* value = (Integer) rs.getObject(idx[i]);
* } catch (SQLException ex) {
* Logger.getLogger(Range.class.getName()).log(Level.SEVERE, null, ex);
* return false;
* }
*
* if (value < lo[i] && value > hi[i]) {
* // outside of filter constraints
* return false;
* }
* }
* // Within filter constraints
* return true;
* }
* }
* }</pre>
* <P>
* The example above implements a simple range predicate. Note, that
* implementations should but are not required to provide <code>String</code>
* and integer index based constructors to provide for JDBC RowSet Implementation
* applications that use both column identification conventions.
*
* @author Jonathan Bruce, Amit Handa
* @since 1.5
*
*/
// <h2>3.0 FilteredRowSet Internals</h2>
// internalNext, First, Last. Discuss guidelines on how to approach this
// and cite examples in reference implementations.
public interface Predicate {
/**
* This method is typically called a <code>FilteredRowSet</code> object
* internal methods (not public) that control the <code>RowSet</code> object's
* cursor moving from row to the next. In addition, if this internal method
* moves the cursor onto a row that has been deleted, the internal method will
* continue to ove the cursor until a valid row is found.
* @param rs The {@code RowSet} to be evaluated
* @return <code>true</code> if there are more rows in the filter;
* <code>false</code> otherwise
*/
public boolean evaluate(RowSet rs);
/**
* This method is called by a <code>FilteredRowSet</code> object
* to check whether the value lies between the filtering criterion (or criteria
* if multiple constraints exist) set using the <code>setFilter()</code> method.
* <P>
* The <code>FilteredRowSet</code> object will use this method internally
* while inserting new rows to a <code>FilteredRowSet</code> instance.
*
* @param value An <code>Object</code> value which needs to be checked,
* whether it can be part of this <code>FilterRowSet</code> object.
* @param column a <code>int</code> object that must match the
* SQL index of a column in this <code>RowSet</code> object. This must
* have been passed to <code>Predicate</code> as one of the columns
* for filtering while initializing a <code>Predicate</code>
* @return <code>true</code> if row value lies within the filter;
* <code>false</code> otherwise
* @throws SQLException if the column is not part of filtering criteria
*/
public boolean evaluate(Object value, int column) throws SQLException;
/**
* This method is called by the <code>FilteredRowSet</code> object
* to check whether the value lies between the filtering criteria set
* using the setFilter method.
* <P>
* The <code>FilteredRowSet</code> object will use this method internally
* while inserting new rows to a <code>FilteredRowSet</code> instance.
*
* @param value An <code>Object</code> value which needs to be checked,
* whether it can be part of this <code>FilterRowSet</code>.
*
* @param columnName a <code>String</code> object that must match the
* SQL name of a column in this <code>RowSet</code>, ignoring case. This must
* have been passed to <code>Predicate</code> as one of the columns for filtering
* while initializing a <code>Predicate</code>
*
* @return <code>true</code> if value lies within the filter; <code>false</code> otherwise
*
* @throws SQLException if the column is not part of filtering criteria
*/
public boolean evaluate(Object value, String columnName) throws SQLException;
}

View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 2010, 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;
import java.sql.SQLException;
/**
* An interface that defines the implementation of a factory that is used
* to obtain different types of {@code RowSet} implementations.
*
* @author Lance Andersen
* @since 1.7
*/
public interface RowSetFactory{
/**
* <p>Creates a new instance of a CachedRowSet.</p>
*
* @return A new instance of a CachedRowSet.
*
* @throws SQLException if a CachedRowSet cannot
* be created.
*
* @since 1.7
*/
public CachedRowSet createCachedRowSet() throws SQLException;
/**
* <p>Creates a new instance of a FilteredRowSet.</p>
*
* @return A new instance of a FilteredRowSet.
*
* @throws SQLException if a FilteredRowSet cannot
* be created.
*
* @since 1.7
*/
public FilteredRowSet createFilteredRowSet() throws SQLException;
/**
* <p>Creates a new instance of a JdbcRowSet.</p>
*
* @return A new instance of a JdbcRowSet.
*
* @throws SQLException if a JdbcRowSet cannot
* be created.
*
* @since 1.7
*/
public JdbcRowSet createJdbcRowSet() throws SQLException;
/**
* <p>Creates a new instance of a JoinRowSet.</p>
*
* @return A new instance of a JoinRowSet.
*
* @throws SQLException if a JoinRowSet cannot
* be created.
*
* @since 1.7
*/
public JoinRowSet createJoinRowSet() throws SQLException;
/**
* <p>Creates a new instance of a WebRowSet.</p>
*
* @return A new instance of a WebRowSet.
*
* @throws SQLException if a WebRowSet cannot
* be created.
*
* @since 1.7
*/
public WebRowSet createWebRowSet() throws SQLException;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,298 @@
/*
* Copyright (c) 2010, 2024, 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;
import java.sql.SQLException;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
/**
* A factory API that enables applications to obtain a
* {@code RowSetFactory} implementation that can be used to create different
* types of {@code RowSet} implementations.
* <p>
* Example:
* </p>
* <pre>
* RowSetFactory aFactory = RowSetProvider.newFactory();
* CachedRowSet crs = aFactory.createCachedRowSet();
* ...
* RowSetFactory rsf = RowSetProvider.newFactory("com.sun.rowset.RowSetFactoryImpl", null);
* WebRowSet wrs = rsf.createWebRowSet();
* </pre>
*<p>
* Tracing of this class may be enabled by setting the System property
* {@code javax.sql.rowset.RowSetFactory.debug} to any value but {@code false}.
* </p>
*
* @author Lance Andersen
* @since 1.7
*/
public class RowSetProvider {
private static final String ROWSET_DEBUG_PROPERTY = "javax.sql.rowset.RowSetProvider.debug";
private static final String ROWSET_FACTORY_IMPL = "com.sun.rowset.RowSetFactoryImpl";
private static final String ROWSET_FACTORY_NAME = "javax.sql.rowset.RowSetFactory";
/**
* Internal debug flag.
*/
private static boolean debug = true;
static {
// Check to see if the debug property is set
String val = System.getProperty(ROWSET_DEBUG_PROPERTY);
// Allow simply setting the prop to turn on debug
debug = val != null && !"false".equals(val);
}
/**
* RowSetProvider constructor
*/
protected RowSetProvider () {
}
/**
* <p>Creates a new instance of a <code>RowSetFactory</code>
* implementation. This method uses the following
* look up order to determine
* the <code>RowSetFactory</code> implementation class to load:</p>
* <ul>
* <li>
* The System property {@code javax.sql.rowset.RowSetFactory}. For example:
* <ul>
* <li>
* -Djavax.sql.rowset.RowSetFactory=com.sun.rowset.RowSetFactoryImpl
* </li>
* </ul>
* <li>
* The {@link ServiceLoader} API. The {@code ServiceLoader} API will look
* for a class name in the file
* {@code META-INF/services/javax.sql.rowset.RowSetFactory}
* in jars available to the runtime. For example, to have the RowSetFactory
* implementation {@code com.sun.rowset.RowSetFactoryImpl } loaded, the
* entry in {@code META-INF/services/javax.sql.rowset.RowSetFactory} would be:
* <ul>
* <li>
* {@code com.sun.rowset.RowSetFactoryImpl }
* </li>
* </ul>
* </li>
* <li>
* Platform default <code>RowSetFactory</code> instance.
* </li>
* </ul>
*
* <p>Once an application has obtained a reference to a {@code RowSetFactory},
* it can use the factory to obtain RowSet instances.</p>
*
* @return New instance of a <code>RowSetFactory</code>
*
* @throws SQLException if the default factory class cannot be loaded,
* instantiated. The cause will be set to actual Exception
*
* @see ServiceLoader
* @since 1.7
*/
public static RowSetFactory newFactory()
throws SQLException {
// Use the system property first
RowSetFactory factory = null;
String factoryClassName = null;
try {
trace("Checking for Rowset System Property...");
factoryClassName = System.getProperty(ROWSET_FACTORY_NAME);
if (factoryClassName != null) {
trace("Found system property, value=" + factoryClassName);
if (factoryClassName.equals(ROWSET_FACTORY_IMPL)) {
return defaultRowSetFactory();
}
// getFactoryClass takes care of adding the read edge if
// necessary
@SuppressWarnings("deprecation")
Object o = getFactoryClass(factoryClassName, null, false).newInstance();
factory = (RowSetFactory) o;
}
} catch (Exception e) {
throw new SQLException( "RowSetFactory: " + factoryClassName +
" could not be instantiated: ", e);
}
// Check to see if we found the RowSetFactory via a System property
if (factory == null) {
// If the RowSetFactory is not found via a System Property, now
// look it up via the ServiceLoader API and if not found, use the
// Java SE default.
factory = loadViaServiceLoader();
}
return factory == null ? defaultRowSetFactory() : factory;
}
private static RowSetFactory defaultRowSetFactory() {
return new com.sun.rowset.RowSetFactoryImpl();
}
/**
* <p>Creates a new instance of a <code>RowSetFactory</code> from the
* specified factory class name.
* This function is useful when there are multiple providers in the classpath.
* It gives more control to the application as it can specify which provider
* should be loaded.</p>
*
* <p>Once an application has obtained a reference to a <code>RowSetFactory</code>
* it can use the factory to obtain RowSet instances.</p>
*
* @param factoryClassName fully qualified factory class name that
* provides an implementation of <code>javax.sql.rowset.RowSetFactory</code>.
*
* @param cl <code>ClassLoader</code> used to load the factory
* class. If <code>null</code> current <code>Thread</code>'s context
* classLoader is used to load the factory class.
*
* @return New instance of a <code>RowSetFactory</code>
*
* @throws SQLException if <code>factoryClassName</code> is
* <code>null</code>, or the factory class cannot be loaded, instantiated.
*
* @see #newFactory()
*
* @since 1.7
*/
public static RowSetFactory newFactory(String factoryClassName, ClassLoader cl)
throws SQLException {
trace("***In newInstance()");
if(factoryClassName == null) {
throw new SQLException("Error: factoryClassName cannot be null");
}
try {
// getFactoryClass takes care of adding the read edge if
// necessary
Class<?> providerClass = getFactoryClass(factoryClassName, cl, false);
@SuppressWarnings("deprecation")
RowSetFactory instance = (RowSetFactory) providerClass.newInstance();
if (debug) {
trace("Created new instance of " + providerClass +
" using ClassLoader: " + cl);
}
return instance;
} catch (ClassNotFoundException x) {
throw new SQLException(
"Provider " + factoryClassName + " not found", x);
} catch (Exception x) {
throw new SQLException(
"Provider " + factoryClassName + " could not be instantiated: " + x,
x);
}
}
/*
* Returns the class loader to be used.
* @return The ClassLoader to use.
*
*/
private static ClassLoader getContextClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
}
return cl;
}
/**
* Attempt to load a class using the class loader supplied. If that fails
* and fall back is enabled, the current (i.e. bootstrap) class loader is
* tried.
*
* If the class loader supplied is <code>null</code>, first try using the
* context class loader followed by the current class loader.
* @return The class which was loaded
*/
private static Class<?> getFactoryClass(String factoryClassName, ClassLoader cl,
boolean doFallback) throws ClassNotFoundException {
Class<?> factoryClass = null;
try {
if (cl == null) {
cl = getContextClassLoader();
if (cl == null) {
throw new ClassNotFoundException();
} else {
factoryClass = cl.loadClass(factoryClassName);
}
} else {
factoryClass = cl.loadClass(factoryClassName);
}
} catch (ClassNotFoundException e) {
if (doFallback) {
// Use current class loader
factoryClass = Class.forName(factoryClassName, true, RowSetFactory.class.getClassLoader());
} else {
throw e;
}
}
return factoryClass;
}
/**
* Use the ServiceLoader mechanism to load the default RowSetFactory
* @return default RowSetFactory Implementation
*/
private static RowSetFactory loadViaServiceLoader() throws SQLException {
RowSetFactory theFactory = null;
try {
trace("***in loadViaServiceLoader():");
for (RowSetFactory factory : ServiceLoader.load(javax.sql.rowset.RowSetFactory.class)) {
trace(" Loading done by the java.util.ServiceLoader :" + factory.getClass().getName());
theFactory = factory;
break;
}
} catch (ServiceConfigurationError e) {
throw new SQLException(
"RowSetFactory: Error locating RowSetFactory using Service "
+ "Loader API: " + e, e);
}
return theFactory;
}
/**
* Debug routine which will output tracing if the System Property
* -Djavax.sql.rowset.RowSetFactory.debug is set
* @param msg - The debug message to display
*/
private static void trace(String msg) {
if (debug) {
System.err.println("###RowSets: " + msg);
}
}
}

View file

@ -0,0 +1,151 @@
/*
* Copyright (c) 2003, 2014, 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;
import java.sql.SQLException;
/**
* An extension of <code>SQLException</code> that provides information
* about database warnings set on <code>RowSet</code> objects.
* Warnings are silently chained to the object whose method call
* caused it to be reported.
* This class complements the <code>SQLWarning</code> class.
* <P>
* Rowset warnings may be retrieved from <code>JdbcRowSet</code>,
* <code>CachedRowSet</code>,
* <code>WebRowSet</code>, <code>FilteredRowSet</code>, or <code>JoinRowSet</code>
* implementations. To retrieve the first warning reported on any
* <code>RowSet</code>
* implementation, use the method <code>getRowSetWarnings</code> defined
* in the <code>JdbcRowSet</code> interface or the <code>CachedRowSet</code>
* interface. To retrieve a warning chained to the first warning, use the
* <code>RowSetWarning</code> method
* <code>getNextWarning</code>. To retrieve subsequent warnings, call
* <code>getNextWarning</code> on each <code>RowSetWarning</code> object that is
* returned.
* <P>
* The inherited methods <code>getMessage</code>, <code>getSQLState</code>,
* and <code>getErrorCode</code> retrieve information contained in a
* <code>RowSetWarning</code> object.
*
* @since 1.5
*/
public class RowSetWarning extends SQLException {
/**
* Constructs a <code>RowSetWarning</code> object
* with the given value for the reason; SQLState defaults to null,
* and vendorCode defaults to 0.
*
* @param reason a <code>String</code> object giving a description
* of the warning; if the <code>String</code> is <code>null</code>,
* this constructor behaves like the default (zero parameter)
* <code>RowSetWarning</code> constructor
*/
public RowSetWarning(String reason) {
super(reason);
}
/**
* Constructs a default <code>RowSetWarning</code> object. The reason
* defaults to <code>null</code>, SQLState defaults to null and vendorCode
* defaults to 0.
*/
public RowSetWarning() {
super();
}
/**
* Constructs a <code>RowSetWarning</code> object initialized with the
* given values for the reason and SQLState. The vendor code defaults to 0.
*
* If the <code>reason</code> or <code>SQLState</code> parameters are <code>null</code>,
* this constructor behaves like the default (zero parameter)
* <code>RowSetWarning</code> constructor.
*
* @param reason a <code>String</code> giving a description of the
* warning;
* @param SQLState an XOPEN code identifying the warning; if a non standard
* XOPEN <i>SQLState</i> is supplied, no exception is thrown.
*/
public RowSetWarning(java.lang.String reason, java.lang.String SQLState) {
super(reason, SQLState);
}
/**
* Constructs a fully specified <code>RowSetWarning</code> object initialized
* with the given values for the reason, SQLState and vendorCode.
*
* If the <code>reason</code>, or the <code>SQLState</code>
* parameters are <code>null</code>, this constructor behaves like the default
* (zero parameter) <code>RowSetWarning</code> constructor.
*
* @param reason a <code>String</code> giving a description of the
* warning;
* @param SQLState an XOPEN code identifying the warning; if a non standard
* XOPEN <i>SQLState</i> is supplied, no exception is thrown.
* @param vendorCode a database vendor-specific warning code
*/
public RowSetWarning(java.lang.String reason, java.lang.String SQLState, int vendorCode) {
super(reason, SQLState, vendorCode);
}
/**
* Retrieves the warning chained to this <code>RowSetWarning</code>
* object.
*
* @return the <code>RowSetWarning</code> object chained to this one; if no
* <code>RowSetWarning</code> object is chained to this one,
* <code>null</code> is returned (default value)
* @see #setNextWarning
*/
public RowSetWarning getNextWarning() {
SQLException warning = getNextException();
if ( warning == null || warning instanceof RowSetWarning) {
return (RowSetWarning)warning;
} else {
// The chained value isn't a RowSetWarning.
// This is a programming error by whoever added it to
// the RowSetWarning chain. We throw a Java "Error".
throw new Error("RowSetWarning chain holds value that is not a RowSetWarning: ");
}
}
/**
* Sets <i>warning</i> as the next warning, that is, the warning chained
* to this <code>RowSetWarning</code> object.
*
* @param warning the <code>RowSetWarning</code> object to be set as the
* next warning; if the <code>RowSetWarning</code> is null, this
* represents the finish point in the warning chain
* @see #getNextWarning
*/
public void setNextWarning(RowSetWarning warning) {
setNextException(warning);
}
static final long serialVersionUID = 6678332766434564774L;
}

View file

@ -0,0 +1,506 @@
/*
* Copyright (c) 2003, 2019, 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;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import java.io.*;
import java.math.*;
import org.xml.sax.*;
/**
* The standard interface that all implementations of a {@code WebRowSet}
* must implement.
*
* <h2>1.0 Overview</h2>
* The {@code WebRowSetImpl} provides the standard
* reference implementation, which may be extended if required.
* <P>
* The standard WebRowSet XML Schema definition is available at the following
* URI:
* <ul>
* <li>
* <a href="http://xmlns.jcp.org/xml/ns//jdbc/webrowset.xsd">http://xmlns.jcp.org/xml/ns//jdbc/webrowset.xsd</a>
* </li>
* </ul>
* It describes the standard XML document format required when describing a
* {@code RowSet} object in XML and must be used be all standard implementations
* of the {@code WebRowSet} interface to ensure interoperability. In addition,
* the {@code WebRowSet} schema uses specific SQL/XML Schema annotations,
* thus ensuring greater cross
* platform interoperability. This is an effort currently under way at the ISO
* organization. The SQL/XML definition is available at the following URI:
* <ul>
* <li>
* <a href="http://standards.iso.org/iso/9075/2002/12/sqlxml.xsd">http://standards.iso.org/iso/9075/2002/12/sqlxml.xsd</a>
* </li>
* </ul>
* The schema definition describes the internal data of a {@code RowSet} object
* in three distinct areas:
* <UL>
* <li>properties - These properties describe the standard synchronization
* provider properties in addition to the more general {@code RowSet} properties.
* </li>
* <li>metadata - This describes the metadata associated with the tabular structure governed by a
* {@code WebRowSet} object. The metadata described is closely aligned with the
* metadata accessible in the underlying {@code java.sql.ResultSet} interface.
* </li>
* <li>data - This describes the original data (the state of data since the
* last population
* or last synchronization of the {@code WebRowSet} object) and the current
* data. By keeping track of the delta between the original data and the current data,
* a {@code WebRowSet} maintains the ability to synchronize changes
* in its data back to the originating data source.
* </li>
* </ul>
*
* <h2>2.0 WebRowSet States</h2>
* The following sections demonstrates how a {@code WebRowSet} implementation
* should use the XML Schema to describe update, insert, and delete operations
* and to describe the state of a {@code WebRowSet} object in XML.
*
* <h2>2.1 State 1 - Outputting a {@code WebRowSet} Object to XML</h2>
* In this example, a {@code WebRowSet} object is created and populated with a simple 2 column,
* 5 row table from a data source. Having the 5 rows in a {@code WebRowSet} object
* makes it possible to describe them in XML. The
* metadata describing the various standard JavaBeans properties as defined
* in the RowSet interface plus the standard properties defined in
* the {@code CachedRowSet} interface
* provide key details that describe WebRowSet
* properties. Outputting the WebRowSet object to XML using the standard
* {@code writeXml} methods describes the internal properties as follows:
* <PRE>
* {@code
* <properties>
* <command>select co1, col2 from test_table</command>
* <concurrency>1</concurrency>
* <datasource/>
* <escape-processing>true</escape-processing>
* <fetch-direction>0</fetch-direction>
* <fetch-size>0</fetch-size>
* <isolation-level>1</isolation-level>
* <key-columns/>
* <map/>
* <max-field-size>0</max-field-size>
* <max-rows>0</max-rows>
* <query-timeout>0</query-timeout>
* <read-only>false</read-only>
* <rowset-type>TRANSACTION_READ_UNCOMMITTED</rowset-type>
* <show-deleted>false</show-deleted>
* <table-name/>
* <url>jdbc:thin:oracle</url>
* <sync-provider>
* <sync-provider-name>.com.rowset.provider.RIOptimisticProvider</sync-provider-name>
* <sync-provider-vendor>Oracle Corporation</sync-provider-vendor>
* <sync-provider-version>1.0</sync-provider-name>
* <sync-provider-grade>LOW</sync-provider-grade>
* <data-source-lock>NONE</data-source-lock>
* </sync-provider>
* </properties>
* } </PRE>
* The meta-data describing the make up of the WebRowSet is described
* in XML as detailed below. Note both columns are described between the
* {@code column-definition} tags.
* <PRE>
* {@code
* <metadata>
* <column-count>2</column-count>
* <column-definition>
* <column-index>1</column-index>
* <auto-increment>false</auto-increment>
* <case-sensitive>true</case-sensitive>
* <currency>false</currency>
* <nullable>1</nullable>
* <signed>false</signed>
* <searchable>true</searchable>
* <column-display-size>10</column-display-size>
* <column-label>COL1</column-label>
* <column-name>COL1</column-name>
* <schema-name/>
* <column-precision>10</column-precision>
* <column-scale>0</column-scale>
* <table-name/>
* <catalog-name/>
* <column-type>1</column-type>
* <column-type-name>CHAR</column-type-name>
* </column-definition>
* <column-definition>
* <column-index>2</column-index>
* <auto-increment>false</auto-increment>
* <case-sensitive>false</case-sensitive>
* <currency>false</currency>
* <nullable>1</nullable>
* <signed>true</signed>
* <searchable>true</searchable>
* <column-display-size>39</column-display-size>
* <column-label>COL2</column-label>
* <column-name>COL2</column-name>
* <schema-name/>
* <column-precision>38</column-precision>
* <column-scale>0</column-scale>
* <table-name/>
* <catalog-name/>
* <column-type>3</column-type>
* <column-type-name>NUMBER</column-type-name>
* </column-definition>
* </metadata>
* }</PRE>
* Having detailed how the properties and metadata are described, the following details
* how the contents of a {@code WebRowSet} object is described in XML. Note, that
* this describes a {@code WebRowSet} object that has not undergone any
* modifications since its instantiation.
* A {@code currentRow} tag is mapped to each row of the table structure that the
* {@code WebRowSet} object provides. A {@code columnValue} tag may contain
* either the {@code stringData} or {@code binaryData} tag, according to
* the SQL type that
* the XML value is mapping back to. The {@code binaryData} tag contains data in the
* Base64 encoding and is typically used for {@code BLOB} and {@code CLOB} type data.
* <PRE>
* {@code
* <data>
* <currentRow>
* <columnValue>
* firstrow
* </columnValue>
* <columnValue>
* 1
* </columnValue>
* </currentRow>
* <currentRow>
* <columnValue>
* secondrow
* </columnValue>
* <columnValue>
* 2
* </columnValue>
* </currentRow>
* <currentRow>
* <columnValue>
* thirdrow
* </columnValue>
* <columnValue>
* 3
* </columnValue>
* </currentRow>
* <currentRow>
* <columnValue>
* fourthrow
* </columnValue>
* <columnValue>
* 4
* </columnValue>
* </currentRow>
* </data>
* }</PRE>
* <h2>2.2 State 2 - Deleting a Row</h2>
* Deleting a row in a {@code WebRowSet} object involves simply moving to the row
* to be deleted and then calling the method {@code deleteRow}, as in any other
* {@code RowSet} object. The following
* two lines of code, in which <i>wrs</i> is a {@code WebRowSet} object, delete
* the third row.
* <PRE>
* wrs.absolute(3);
* wrs.deleteRow();
* </PRE>
* The XML description shows the third row is marked as a {@code deleteRow},
* which eliminates the third row in the {@code WebRowSet} object.
* <PRE>
* {@code
* <data>
* <currentRow>
* <columnValue>
* firstrow
* </columnValue>
* <columnValue>
* 1
* </columnValue>
* </currentRow>
* <currentRow>
* <columnValue>
* secondrow
* </columnValue>
* <columnValue>
* 2
* </columnValue>
* </currentRow>
* <deleteRow>
* <columnValue>
* thirdrow
* </columnValue>
* <columnValue>
* 3
* </columnValue>
* </deleteRow>
* <currentRow>
* <columnValue>
* fourthrow
* </columnValue>
* <columnValue>
* 4
* </columnValue>
* </currentRow>
* </data>
*} </PRE>
* <h2>2.3 State 3 - Inserting a Row</h2>
* A {@code WebRowSet} object can insert a new row by moving to the insert row,
* calling the appropriate updater methods for each column in the row, and then
* calling the method {@code insertRow}.
* <PRE>
* {@code
* wrs.moveToInsertRow();
* wrs.updateString(1, "fifththrow");
* wrs.updateString(2, "5");
* wrs.insertRow();
* }</PRE>
* The following code fragment changes the second column value in the row just inserted.
* Note that this code applies when new rows are inserted right after the current row,
* which is why the method {@code next} moves the cursor to the correct row.
* Calling the method {@code acceptChanges} writes the change to the data source.
*
* <PRE>
* {@code wrs.moveToCurrentRow();
* wrs.next();
* wrs.updateString(2, "V");
* wrs.acceptChanges();
* }</PRE>
* Describing this in XML demonstrates where the Java code inserts a new row and then
* performs an update on the newly inserted row on an individual field.
* <PRE>
* {@code
* <data>
* <currentRow>
* <columnValue>
* firstrow
* </columnValue>
* <columnValue>
* 1
* </columnValue>
* </currentRow>
* <currentRow>
* <columnValue>
* secondrow
* </columnValue>
* <columnValue>
* 2
* </columnValue>
* </currentRow>
* <currentRow>
* <columnValue>
* newthirdrow
* </columnValue>
* <columnValue>
* III
* </columnValue>
* </currentRow>
* <insertRow>
* <columnValue>
* fifthrow
* </columnValue>
* <columnValue>
* 5
* </columnValue>
* <updateValue>
* V
* </updateValue>
* </insertRow>
* <currentRow>
* <columnValue>
* fourthrow
* </columnValue>
* <columnValue>
* 4
* </columnValue>
* </currentRow>
* </date>
*} </PRE>
* <h2>2.4 State 4 - Modifying a Row</h2>
* Modifying a row produces specific XML that records both the new value and the
* value that was replaced. The value that was replaced becomes the original value,
* and the new value becomes the current value. The following
* code moves the cursor to a specific row, performs some modifications, and updates
* the row when complete.
* <PRE>
*{@code
* wrs.absolute(5);
* wrs.updateString(1, "new4thRow");
* wrs.updateString(2, "IV");
* wrs.updateRow();
* }</PRE>
* In XML, this is described by the {@code modifyRow} tag. Both the original and new
* values are contained within the tag for original row tracking purposes.
* <PRE>
* {@code
* <data>
* <currentRow>
* <columnValue>
* firstrow
* </columnValue>
* <columnValue>
* 1
* </columnValue>
* </currentRow>
* <currentRow>
* <columnValue>
* secondrow
* </columnValue>
* <columnValue>
* 2
* </columnValue>
* </currentRow>
* <currentRow>
* <columnValue>
* newthirdrow
* </columnValue>
* <columnValue>
* III
* </columnValue>
* </currentRow>
* <currentRow>
* <columnValue>
* fifthrow
* </columnValue>
* <columnValue>
* 5
* </columnValue>
* </currentRow>
* <modifyRow>
* <columnValue>
* fourthrow
* </columnValue>
* <updateValue>
* new4thRow
* </updateValue>
* <columnValue>
* 4
* </columnValue>
* <updateValue>
* IV
* </updateValue>
* </modifyRow>
* </data>
* }</PRE>
*
* @see javax.sql.rowset.JdbcRowSet
* @see javax.sql.rowset.CachedRowSet
* @see javax.sql.rowset.FilteredRowSet
* @see javax.sql.rowset.JoinRowSet
* @since 1.5
*/
public interface WebRowSet extends CachedRowSet {
/**
* Reads a {@code WebRowSet} object in its XML format from the given
* {@code Reader} object.
*
* @param reader the {@code java.io.Reader} stream from which this
* {@code WebRowSet} object will be populated
* @throws SQLException if a database access error occurs
*/
public void readXml(java.io.Reader reader) throws SQLException;
/**
* Reads a stream based XML input to populate this {@code WebRowSet}
* object.
*
* @param iStream the {@code java.io.InputStream} from which this
* {@code WebRowSet} object will be populated
* @throws SQLException if a data source access error occurs
* @throws IOException if an IO exception occurs
*/
public void readXml(java.io.InputStream iStream) throws SQLException, IOException;
/**
* Populates this {@code WebRowSet} object with
* the contents of the given {@code ResultSet} object and writes its
* data, properties, and metadata
* to the given {@code Writer} object in XML format.
* <p>
* NOTE: The {@code WebRowSet} cursor may be moved to write out the
* contents to the XML data source. If implemented in this way, the cursor <b>must</b>
* be returned to its position just prior to the {@code writeXml()} call.
*
* @param rs the {@code ResultSet} object with which to populate this
* {@code WebRowSet} object
* @param writer the {@code java.io.Writer} object to write to.
* @throws SQLException if an error occurs writing out the rowset
* contents in XML format
*/
public void writeXml(ResultSet rs, java.io.Writer writer) throws SQLException;
/**
* Populates this {@code WebRowSet} object with
* the contents of the given {@code ResultSet} object and writes its
* data, properties, and metadata
* to the given {@code OutputStream} object in XML format.
* <p>
* NOTE: The {@code WebRowSet} cursor may be moved to write out the
* contents to the XML data source. If implemented in this way, the cursor <b>must</b>
* be returned to its position just prior to the {@code writeXml()} call.
*
* @param rs the {@code ResultSet} object with which to populate this
* {@code WebRowSet} object
* @param oStream the {@code java.io.OutputStream} to write to
* @throws SQLException if a data source access error occurs
* @throws IOException if a IO exception occurs
*/
public void writeXml(ResultSet rs, java.io.OutputStream oStream) throws SQLException, IOException;
/**
* Writes the data, properties, and metadata for this {@code WebRowSet} object
* to the given {@code Writer} object in XML format.
*
* @param writer the {@code java.io.Writer} stream to write to
* @throws SQLException if an error occurs writing out the rowset
* contents to XML
*/
public void writeXml(java.io.Writer writer) throws SQLException;
/**
* Writes the data, properties, and metadata for this {@code WebRowSet} object
* to the given {@code OutputStream} object in XML format.
*
* @param oStream the {@code java.io.OutputStream} stream to write to
* @throws SQLException if a data source access error occurs
* @throws IOException if a IO exception occurs
*/
public void writeXml(java.io.OutputStream oStream) throws SQLException, IOException;
/**
* The public identifier for the XML Schema definition that defines the XML
* tags and their valid values for a {@code WebRowSet} implementation.
*/
public static String PUBLIC_XML_SCHEMA =
"--//Oracle Corporation//XSD Schema//EN";
/**
* The URL for the XML Schema definition file that defines the XML tags and
* their valid values for a {@code WebRowSet} implementation.
*/
public static String SCHEMA_SYSTEM_ID = "http://java.sun.com/xml/ns/jdbc/webrowset.xsd";
}

View file

@ -0,0 +1,288 @@
/*
* Copyright (c) 2017, 2023, 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.
*/
/**
* Standard interfaces and base classes for JDBC {@code RowSet}
* implementations. This package contains interfaces and classes
* that a standard {@code RowSet} implementation either implements or extends.
*
* <h2>Table of Contents</h2>
* <ul>
* <li><a href="#pkgspec">1.0 Package Specification</a>
* <li><a href="#stdrowset">2.0 Standard RowSet Definitions</a>
* <li><a href="#impl">3.0 Implementer's Guide</a>
* <li><a href="#relspec">4.0 Related Specifications</a>
* <li><a href="#reldocs">5.0 Related Documentation</a>
* </ul>
*
* <h3><a id="pkgspec">1.0 Package Specification</a></h3>
* This package specifies five standard JDBC {@code RowSet} interfaces.
* All five extend the
* {@link java.sql/javax.sql.RowSet} interface described in the JDBC 3.0
* specification. It is anticipated that additional definitions
* of more specialized JDBC {@code RowSet} types will emerge as this technology
* matures. Future definitions <i>should</i> be specified as subinterfaces using
* inheritance similar to the way it is used in this specification.
* <p>
* <i>Note:</i> The interface definitions provided in this package form the basis for
* all compliant JDBC {@code RowSet} implementations. Vendors and more advanced
* developers who intend to provide their own compliant {@code RowSet} implementations
* should pay particular attention to the assertions detailed in specification
* interfaces.
*
* <h3><a id="stdrowset">2.0 Standard RowSet Definitions</a></h3>
* <ul>
* <li><a href="JdbcRowSet.html"><b>{@code JdbcRowSet}</b></a> - A wrapper around
* a {@code ResultSet} object that makes it possible to use the result set as a
* JavaBeans component. Thus,
* a {@code JdbcRowSet} object can be a Bean that any tool
* makes available for assembling an application as part of a component based
* architecture. A {@code JdbcRowSet} object is a connected {@code RowSet}
* object, that is, it
* <b>must</b> continually maintain its connection to its data source using a JDBC
* technology-enabled driver ("JDBC driver"). In addition, a {@code JdbcRowSet}
* object provides a fully updatable and scrollable tabular
* data structure as defined in the JDBC 3.0 specification.
*
* <li><a href="CachedRowSet.html">
* <b>{@code CachedRowSet}</b></a>
* - A {@code CachedRowSet} object is a JavaBeans
* component that is scrollable, updatable, serializable, and generally disconnected from
* the source of its data. A {@code CachedRowSet} object
* typically contains rows from a result set, but it can also contain rows from any
* file with a tabular format, such as a spreadsheet. {@code CachedRowSet} implementations
* <b>must</b> use the {@code SyncFactory} to manage and obtain pluggable
* {@code SyncProvider} objects to provide synchronization between the
* disconnected {@code RowSet} object and the originating data source.
* Typically a {@code SyncProvider} implementation relies upon a JDBC
* driver to obtain connectivity to a particular data source.
* Further details on this mechanism are discussed in the <a
* href="spi/package-summary.html">{@code javax.sql.rowset.spi}</a> package
* specification.
*
* <li><a href="WebRowSet.html"><b>{@code WebRowSet}</b></a> - A
* {@code WebRowSet} object is an extension of {@code CachedRowSet}
* that can read and write a {@code RowSet} object in a well formed XML format.
* This class calls an <a href="spi/XmlReader.html">{@code XmlReader}</a> object
* (an extension of the {@link java.sql/javax.sql.RowSetReader RowSetReader}
* interface) to read a rowset in XML format. It calls an
* <a href="spi/XmlWriter.html">{@code XmlWriter}</a> object (an extension of the
* {@link java.sql/javax.sql.RowSetWriter RowSetWriter} interface)
* to write a rowset in XML format. The reader and writer required by
* {@code WebRowSet} objects are provided by the
* {@code SyncFactory} in the form of {@code SyncProvider}
* implementations. In order to ensure well formed XML usage, a standard generic XML
* Schema is defined and published at
* <a href="http://xmlns.jcp.org/xml/ns//jdbc/webrowset.xsd">
* {@code http://xmlns.jcp.org/xml/ns//jdbc/webrowset.xsd}</a>.
*
* <li><a href="FilteredRowSet.html"><b>{@code FilteredRowSet}</b></a> - A
* {@code FilteredRowSet} object provides filtering functionality in a programmatic
* and extensible way. There are many instances when a {@code RowSet} {@code object}
* has a need to provide filtering in its contents without sacrificing the disconnected
* environment, thus saving the expense of having to create a connection to the data source.
* Solutions to this need vary from providing heavyweight full scale
* SQL query abilities, to portable components, to more lightweight
* approaches. A {@code FilteredRowSet} object consumes
* an implementation of the {@link Predicate}
* interface, which <b>may</b> define a filter at run time. In turn, a
* {@code FilteredRowSet} object is tasked with enforcing the set filter for both
* inbound and outbound read and write operations. That is, all filters can be
* considered as bi-directional. No standard filters are defined;
* however, sufficient mechanics are specified to permit any required filter to be
* implemented.
*
* <li><a href="JoinRowSet.html"><b>{@code JoinRowSet}</b></a> - The {@code JoinRowSet}
* interface describes a mechanism by which relationships can be established between
* two or more standard {@code RowSet} implementations. Any number of {@code RowSet}
* objects can be added to a {@code JoinRowSet} object provided the {@code RowSet}objects
* can be related in a SQL {@code JOIN} like fashion. By definition, the SQL {@code JOIN}
* statement is used to combine the data contained in two (<i>or more</i>) relational
* database tables based upon a common attribute. By establishing and then enforcing
* column matches, a {@code JoinRowSet} object establishes relationships between
* {@code RowSet} instances without the need to touch the originating data source.
* </ul>
*
* <h3><a id="impl">3.0 Implementer's Guide</a></h3>
* Compliant implementations of JDBC {@code RowSet} Implementations
* <b>must</b> follow the assertions described in this specification. In accordance
* with the terms of the <a href="http://www.jcp.org">Java Community Process</a>, a
* Test Compatibility Kit (TCK) can be licensed to ensure compatibility with the
* specification. The following paragraphs outline a number of starting points for
* implementers of the standard JDBC {@code RowSet} definitions. Implementers
* should also consult the <i>Implementer's Guide</i> in the <a
* href="spi/package-summary.html">javax.sql.rowset.spi</a> package for guidelines
* on <a href="spi/SyncProvider.html">{@code SyncProvider}</a> implementations.
*
* <ul>
* <li><b>3.1 Constructor</b>
* <p>
* All {@code RowSet} implementations <strong>must</strong> provide a
* no-argument constructor.
* </li>
* <li><b>3.2 Role of the {@code BaseRowSet} Class</b>
* <p>
* A compliant JDBC {@code RowSet} implementation <b>must</b> implement one or more
* standard interfaces specified in this package and <b>may</b> extend the
* {@link javax.sql.rowset.BaseRowSet} abstract class. For example, a
* {@code CachedRowSet} implementation must implement the {@code CachedRowSet}
* interface and extend the {@code BaseRowSet} abstract class. The
* {@code BaseRowSet} class provides the standard architecture on which all
* {@code RowSet} implementations should be built, regardless of whether the
* {@code RowSet} objects exist in a connected or disconnected environment.
* The {@code BaseRowSet} abstract class provides any {@code RowSet} implementation
* with its base functionality, including property manipulation and event notification
* that is fully compliant with
* <a href="https://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html">JavaBeans</a>
* component requirements. As an example, all implementations provided in the
* reference implementations (contained in the {@code com.sun.rowset} package) use
* the {@code BaseRowSet} class as a basis for their implementations.
* <P>
* The following table illustrates the features that the {@code BaseRowSet}
* abstract class provides.
* <blockquote>
* <table class="striped" style="vertical-align:top; width:75%">
* <caption>Features in {@code BaseRowSet}</caption>
* <thead>
* <tr>
* <th scope="col">Feature</th>
* <th scope="col">Details</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th scope="row">Properties</th>
* <td>Provides standard JavaBeans property manipulation
* mechanisms to allow applications to get and set {@code RowSet} command and
* property values. Refer to the documentation of the {@code javax.sql.RowSet}
* interface (available in the JDBC 3.0 specification) for more details on
* the standard {@code RowSet} properties.</td>
* </tr>
* <tr>
* <th scope="row">Event notification</th>
* <td>Provides standard JavaBeans event notifications
* to registered event listeners. Refer to the documentation of {@code javax.sql.RowSetEvent}
* interface (available in the JDBC 3.0 specification) for
* more details on how to register and handle standard RowSet events generated
* by compliant implementations.</td>
* </tr>
* <tr>
* <th scope="row">Setters for a RowSet object's command</th>
* <td>Provides a complete set of setter methods
* for setting RowSet command parameters.</td>
* </tr>
* <tr>
* <th scope="row">Streams</th>
* <td>Provides fields for storing of stream instances
* in addition to providing a set of constants for stream type designation.</td>
* </tr>
* </tbody>
* </table>
* </blockquote>
*
* <li><b>3.3 Connected RowSet Requirements</b>
* <p>
* The {@code JdbcRowSet} describes a {@code RowSet} object that <b>must</b> always
* be connected to the originating data source. Implementations of the {@code JdbcRowSet}
* should ensure that this connection is provided solely by a JDBC driver.
* Furthermore, {@code RowSet} objects that are implementations of the
* {@code JdbcRowSet} interface and are therefore operating in a connected environment
* do not use the {@code SyncFactory} to obtain a {@code RowSetReader} object
* or a {@code RowSetWriter} object. They can safely rely on the JDBC driver to
* supply their needs by virtue of the presence of an underlying updatable and scrollable
* {@code ResultSet} implementation.
*
* <li>
* <b>3.4 Disconnected RowSet Requirements</b>
* <p>
* A disconnected {@code RowSet} object, such as a {@code CachedRowSet} object,
* <b>should</b> delegate
* connection management to a {@code SyncProvider} object provided by the
* {@code SyncFactory}. To ensure fully disconnected semantics, all
* disconnected {@code RowSet} objects <b>must</b> ensure
* that the original connection made to the data source to populate the {@code RowSet}
* object is closed to permit the garbage collector to recover and release resources. The
* {@code SyncProvider} object ensures that the critical JDBC properties are
* maintained in order to re-establish a connection to the data source when a
* synchronization is required. A disconnected {@code RowSet} object should
* therefore ensure that no
* extraneous references remain on the {@code Connection} object.
*
* <li><b>3.5 Role of RowSetMetaDataImpl</b>
* <p>
* The {@code RowsetMetaDataImpl} class is a utility class that provides an implementation of the
* {@link java.sql/javax.sql.RowSetMetaData RowSetMetaData} interface, supplying standard setter
* method implementations for metadata for both connected and disconnected
* {@code RowSet} objects. All implementations are free to use this standard
* implementation but are not required to do so.
*
* <li><b>3.6 RowSetWarning Class</b>
* <p>
* The {@code RowSetWarning} class provides warnings that can be set
* on {@code RowSet} implementations.
* Similar to {@link java.sql/java.sql.SQLWarning SQLWarning} objects,
* {@code RowSetWarning} objects are silently chained to the object whose method
* caused the warning to be thrown. All {@code RowSet} implementations <b>should</b>
* ensure that this chaining occurs if a warning is generated and also ensure that the
* warnings are available via the {@code getRowSetWarnings} method defined in either
* the {@code JdbcRowSet} interface or the {@code CachedRowSet} interface.
* After a warning has been retrieved with one of the
* {@code getRowSetWarnings} methods, the {@code RowSetWarning} method
* {@code getNextWarning} can be called on it to retrieve any warnings that might
* be chained on it. If a warning is returned, {@code getNextWarning} can be called
* on it, and so on until there are no more warnings.
*
* <li><b>3.7 The Joinable Interface</b>
* <P>
* The {@code Joinable} interface provides both connected and disconnected
* {@code RowSet} objects with the capability to be added to a
* {@code JoinRowSet} object in an SQL {@code JOIN} operation.
* A {@code RowSet} object that has implemented the {@code Joinable}
* interface can set a match column, retrieve a match column, or unset a match column.
* A {@code JoinRowSet} object can then use the {@code RowSet} object's
* match column as a basis for adding the {@code RowSet} object.
* </li>
*
* <li><b>3.8 The RowSetFactory Interface</b>
* <p>
* A {@code RowSetFactory} implementation <strong>must</strong>
* be provided.
* </li>
* </ul>
*
* <h3><a id="relspec">4.0 Related Specifications</a></h3>
* <ul>
* <li><a href="https://jcp.org/en/jsr/detail?id=221">JDBC 4.3 Specification</a>
* <li><a href="http://www.w3.org/XML/Schema">XML Schema</a>
* </ul>
*
* <h3><a id="reldocs">5.0 Related Documentation</a></h3>
* <ul>
* <li><a href="http://docs.oracle.com/javase/tutorial/jdbc/basics/rowset.html">
* JDBC RowSet Tutorial</a>
*</ul>
* @since 1.5
*/
package javax.sql.rowset;

View file

@ -0,0 +1,12 @@
#Default JDBC RowSet sync providers listing
#
# Optimistic synchonriztaion 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

View file

@ -0,0 +1,669 @@
/*
* Copyright (c) 2003, 2024, 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.serial;
import java.sql.*;
import java.util.Arrays;
import java.util.Map;
/**
* An input stream used for custom mapping user-defined types (UDTs).
* An <code>SQLInputImpl</code> object is an input stream that contains a
* stream of values that are the attributes of a UDT.
* <p>
* This class is used by the driver behind the scenes when the method
* <code>getObject</code> is called on an SQL structured or distinct type
* that has a custom mapping; a programmer never invokes
* <code>SQLInputImpl</code> methods directly. They are provided here as a
* convenience for those who write <code>RowSet</code> implementations.
* <P>
* The <code>SQLInputImpl</code> class provides a set of
* reader methods analogous to the <code>ResultSet</code> getter
* methods. These methods make it possible to read the values in an
* <code>SQLInputImpl</code> object.
* <P>
* The method <code>wasNull</code> is used to determine whether the
* the last value read was SQL <code>NULL</code>.
* <P>When the method <code>getObject</code> is called with an
* object of a class implementing the interface <code>SQLData</code>,
* the JDBC driver calls the method <code>SQLData.getSQLType</code>
* to determine the SQL type of the UDT being custom mapped. The driver
* creates an instance of <code>SQLInputImpl</code>, populating it with the
* attributes of the UDT. The driver then passes the input
* stream to the method <code>SQLData.readSQL</code>, which in turn
* calls the <code>SQLInputImpl</code> reader methods
* to read the attributes from the input stream.
* @since 1.5
* @see java.sql.SQLData
*/
public class SQLInputImpl implements SQLInput {
/**
* <code>true</code> if the last value returned was <code>SQL NULL</code>;
* <code>false</code> otherwise.
*/
private boolean lastValueWasNull;
/**
* The current index into the array of SQL structured type attributes
* that will be read from this <code>SQLInputImpl</code> object and
* mapped to the fields of a class in the Java programming language.
*/
private int idx;
/**
* The array of attributes to be read from this stream. The order
* of the attributes is the same as the order in which they were
* listed in the SQL definition of the UDT.
*/
private Object attrib[];
/**
* The type map to use when the method <code>readObject</code>
* is invoked. This is a <code>java.util.Map</code> object in which
* there may be zero or more entries. Each entry consists of the
* fully qualified name of a UDT (the value to be mapped) and the
* <code>Class</code> object for a class that implements
* <code>SQLData</code> (the Java class that defines how the UDT
* will be mapped).
*/
private Map<String,Class<?>> map;
/**
* Creates an <code>SQLInputImpl</code> object initialized with the
* given array of attributes and the given type map. If any of the
* attributes is a UDT whose name is in an entry in the type map,
* the attribute will be mapped according to the corresponding
* <code>SQLData</code> implementation.
*
* @param attributes an array of <code>Object</code> instances in which
* each element is an attribute of a UDT. The order of the
* attributes in the array is the same order in which
* the attributes were defined in the UDT definition.
* @param map a <code>java.util.Map</code> object containing zero or more
* entries, with each entry consisting of 1) a <code>String</code>
* giving the fully
* qualified name of the UDT and 2) the <code>Class</code> object
* for the <code>SQLData</code> implementation that defines how
* the UDT is to be mapped
* @throws SQLException if the <code>attributes</code> or the <code>map</code>
* is a <code>null</code> value
*/
public SQLInputImpl(Object[] attributes, Map<String,Class<?>> map)
throws SQLException
{
if ((attributes == null) || (map == null)) {
throw new SQLException("Cannot instantiate a SQLInputImpl " +
"object with null parameters");
}
// assign our local reference to the attribute stream
attrib = Arrays.copyOf(attributes, attributes.length);
// init the index point before the head of the stream
idx = -1;
// set the map
this.map = map;
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object
* as an <code>Object</code> in the Java programming language.
*
* @return the next value in the input stream
* as an <code>Object</code> in the Java programming language
* @throws SQLException if the read position is located at an invalid
* position or if there are no further values in the stream
*/
private Object getNextAttribute() throws SQLException {
if (++idx >= attrib.length) {
throw new SQLException("SQLInputImpl exception: Invalid read " +
"position");
} else {
lastValueWasNull = attrib[idx] == null;
return attrib[idx];
}
}
//================================================================
// Methods for reading attributes from the stream of SQL data.
// These methods correspond to the column-accessor methods of
// java.sql.ResultSet.
//================================================================
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object as
* a <code>String</code> in the Java programming language.
* <p>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type; this responsibility is delegated
* to the UDT mapping as defined by a <code>SQLData</code>
* implementation.
*
* @return the next attribute in this <code>SQLInputImpl</code> object;
* if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position or if there are no further values in the stream.
*/
public String readString() throws SQLException {
return (String)getNextAttribute();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object as
* a <code>boolean</code> in the Java programming language.
* <p>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type; this responsibility is delegated
* to the UDT mapping as defined by a <code>SQLData</code>
* implementation.
*
* @return the next attribute in this <code>SQLInputImpl</code> object;
* if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position or if there are no further values in the stream.
*/
public boolean readBoolean() throws SQLException {
Boolean attrib = (Boolean)getNextAttribute();
return (attrib == null) ? false : attrib.booleanValue();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object as
* a <code>byte</code> in the Java programming language.
* <p>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type; this responsibility is delegated
* to the UDT mapping as defined by a <code>SQLData</code>
* implementation.
*
* @return the next attribute in this <code>SQLInputImpl</code> object;
* if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position or if there are no further values in the stream
*/
public byte readByte() throws SQLException {
Byte attrib = (Byte)getNextAttribute();
return (attrib == null) ? 0 : attrib.byteValue();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object
* as a <code>short</code> in the Java programming language.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type; this responsibility is delegated
* to the UDT mapping as defined by a <code>SQLData</code> implementation.
*
* @return the next attribute in this <code>SQLInputImpl</code> object;
* if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position or if there are no more values in the stream
*/
public short readShort() throws SQLException {
Short attrib = (Short)getNextAttribute();
return (attrib == null) ? 0 : attrib.shortValue();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object
* as an <code>int</code> in the Java programming language.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type; this responsibility is delegated
* to the UDT mapping as defined by a <code>SQLData</code> implementation.
*
* @return the next attribute in this <code>SQLInputImpl</code> object;
* if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position or if there are no more values in the stream
*/
public int readInt() throws SQLException {
Integer attrib = (Integer)getNextAttribute();
return (attrib == null) ? 0 : attrib.intValue();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object
* as a <code>long</code> in the Java programming language.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type; this responsibility is delegated
* to the UDT mapping as defined by a <code>SQLData</code> implementation.
*
* @return the next attribute in this <code>SQLInputImpl</code> object;
* if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position or if there are no more values in the stream
*/
public long readLong() throws SQLException {
Long attrib = (Long)getNextAttribute();
return (attrib == null) ? 0 : attrib.longValue();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object
* as a <code>float</code> in the Java programming language.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type; this responsibility is delegated
* to the UDT mapping as defined by a <code>SQLData</code> implementation.
*
* @return the next attribute in this <code>SQLInputImpl</code> object;
* if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position or if there are no more values in the stream
*/
public float readFloat() throws SQLException {
Float attrib = (Float)getNextAttribute();
return (attrib == null) ? 0 : attrib.floatValue();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object
* as a <code>double</code> in the Java programming language.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type; this responsibility is delegated
* to the UDT mapping as defined by a <code>SQLData</code> implementation.
*
* @return the next attribute in this <code>SQLInputImpl</code> object;
* if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position or if there are no more values in the stream
*/
public double readDouble() throws SQLException {
Double attrib = (Double)getNextAttribute();
return (attrib == null) ? 0 : attrib.doubleValue();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object
* as a <code>java.math.BigDecimal</code>.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type; this responsibility is delegated
* to the UDT mapping as defined by a <code>SQLData</code> implementation.
*
* @return the next attribute in this <code>SQLInputImpl</code> object;
* if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position or if there are no more values in the stream
*/
public java.math.BigDecimal readBigDecimal() throws SQLException {
return (java.math.BigDecimal)getNextAttribute();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object
* as an array of bytes.
* <p>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type; this responsibility is delegated
* to the UDT mapping as defined by a <code>SQLData</code> implementation.
*
* @return the next attribute in this <code>SQLInputImpl</code> object;
* if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position or if there are no more values in the stream
*/
public byte[] readBytes() throws SQLException {
return (byte[])getNextAttribute();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> as
* a <code>java.sql.Date</code> object.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type; this responsibility is delegated
* to the UDT mapping as defined by a <code>SQLData</code> implementation.
*
* @return the next attribute in this <code>SQLInputImpl</code> object;
* if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position or if there are no more values in the stream
*/
public java.sql.Date readDate() throws SQLException {
return (java.sql.Date)getNextAttribute();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object as
* a <code>java.sql.Time</code> object.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type as this responsibility is delegated
* to the UDT mapping as implemented by a <code>SQLData</code>
* implementation.
*
* @return the attribute; if the value is <code>SQL NULL</code>, return
* <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position; or if there are no further values in the stream.
*/
public java.sql.Time readTime() throws SQLException {
return (java.sql.Time)getNextAttribute();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object as
* a <code>java.sql.Timestamp</code> object.
*
* @return the attribute; if the value is <code>SQL NULL</code>, return
* <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position; or if there are no further values in the stream.
*/
public java.sql.Timestamp readTimestamp() throws SQLException {
return (java.sql.Timestamp)getNextAttribute();
}
/**
* Retrieves the next attribute in this <code>SQLInputImpl</code> object
* as a stream of Unicode characters.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type as this responsibility is delegated
* to the UDT mapping as implemented by a <code>SQLData</code>
* implementation.
*
* @return the attribute; if the value is <code>SQL NULL</code>, return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position; or if there are no further values in the stream.
*/
public java.io.Reader readCharacterStream() throws SQLException {
return (java.io.Reader)getNextAttribute();
}
/**
* Returns the next attribute in this <code>SQLInputImpl</code> object
* as a stream of ASCII characters.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type as this responsibility is delegated
* to the UDT mapping as implemented by a <code>SQLData</code>
* implementation.
*
* @return the attribute; if the value is <code>SQL NULL</code>,
* return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position; or if there are no further values in the stream.
*/
public java.io.InputStream readAsciiStream() throws SQLException {
return (java.io.InputStream)getNextAttribute();
}
/**
* Returns the next attribute in this <code>SQLInputImpl</code> object
* as a stream of uninterpreted bytes.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type as this responsibility is delegated
* to the UDT mapping as implemented by a <code>SQLData</code>
* implementation.
*
* @return the attribute; if the value is <code>SQL NULL</code>, return
* <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position; or if there are no further values in the stream.
*/
public java.io.InputStream readBinaryStream() throws SQLException {
return (java.io.InputStream)getNextAttribute();
}
//================================================================
// Methods for reading items of SQL user-defined types from the stream.
//================================================================
/**
* Retrieves the value at the head of this <code>SQLInputImpl</code>
* object as an <code>Object</code> in the Java programming language. The
* actual type of the object returned is determined by the default
* mapping of SQL types to types in the Java programming language unless
* there is a custom mapping, in which case the type of the object
* returned is determined by this stream's type map.
* <P>
* The JDBC technology-enabled driver registers a type map with the stream
* before passing the stream to the application.
* <P>
* When the datum at the head of the stream is an SQL <code>NULL</code>,
* this method returns <code>null</code>. If the datum is an SQL
* structured or distinct type with a custom mapping, this method
* determines the SQL type of the datum at the head of the stream,
* constructs an object of the appropriate class, and calls the method
* <code>SQLData.readSQL</code> on that object. The <code>readSQL</code>
* method then calls the appropriate <code>SQLInputImpl.readXXX</code>
* methods to retrieve the attribute values from the stream.
*
* @return the value at the head of the stream as an <code>Object</code>
* in the Java programming language; <code>null</code> if
* the value is SQL <code>NULL</code>
* @throws SQLException if the read position is located at an invalid
* position; or if there are no further values in the stream.
*/
public Object readObject() throws SQLException {
Object attrib = getNextAttribute();
if (attrib instanceof Struct) {
Struct s = (Struct)attrib;
// look up the class in the map
Class<?> c = map.get(s.getSQLTypeName());
if (c != null) {
// create new instance of the class
SQLData obj = null;
try {
@SuppressWarnings("deprecation")
Object tmp = c.newInstance();
obj = (SQLData)tmp;
} catch (Exception ex) {
throw new SQLException("Unable to Instantiate: ", ex);
}
// get the attributes from the struct
Object attribs[] = s.getAttributes(map);
// create the SQLInput "stream"
SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
// read the values...
obj.readSQL(sqlInput, s.getSQLTypeName());
return obj;
}
}
return attrib;
}
/**
* Retrieves the value at the head of this <code>SQLInputImpl</code> object
* as a <code>Ref</code> object in the Java programming language.
*
* @return a <code>Ref</code> object representing the SQL
* <code>REF</code> value at the head of the stream; if the value
* is <code>SQL NULL</code> return <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position; or if there are no further values in the stream.
*/
public Ref readRef() throws SQLException {
return (Ref)getNextAttribute();
}
/**
* Retrieves the <code>BLOB</code> value at the head of this
* <code>SQLInputImpl</code> object as a <code>Blob</code> object
* in the Java programming language.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type as this responsibility is delegated
* to the UDT mapping as implemented by a <code>SQLData</code>
* implementation.
*
* @return a <code>Blob</code> object representing the SQL
* <code>BLOB</code> value at the head of this stream;
* if the value is <code>SQL NULL</code>, return
* <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position; or if there are no further values in the stream.
*/
public Blob readBlob() throws SQLException {
return (Blob)getNextAttribute();
}
/**
* Retrieves the <code>CLOB</code> value at the head of this
* <code>SQLInputImpl</code> object as a <code>Clob</code> object
* in the Java programming language.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type as this responsibility is delegated
* to the UDT mapping as implemented by a <code>SQLData</code>
* implementation.
*
* @return a <code>Clob</code> object representing the SQL
* <code>CLOB</code> value at the head of the stream;
* if the value is <code>SQL NULL</code>, return
* <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position; or if there are no further values in the stream.
*/
public Clob readClob() throws SQLException {
return (Clob)getNextAttribute();
}
/**
* Reads an SQL <code>ARRAY</code> value from the stream and
* returns it as an <code>Array</code> object in the Java programming
* language.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type as this responsibility is delegated
* to the UDT mapping as implemented by a <code>SQLData</code>
* implementation.
*
* @return an <code>Array</code> object representing the SQL
* <code>ARRAY</code> value at the head of the stream; *
* if the value is <code>SQL NULL</code>, return
* <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position; or if there are no further values in the stream.
*/
public Array readArray() throws SQLException {
return (Array)getNextAttribute();
}
/**
* Ascertains whether the last value read from this
* <code>SQLInputImpl</code> object was <code>null</code>.
*
* @return <code>true</code> if the SQL value read most recently was
* <code>null</code>; otherwise, <code>false</code>; by default it
* will return false
* @throws SQLException if an error occurs determining the last value
* read was a <code>null</code> value or not;
*/
public boolean wasNull() throws SQLException {
return lastValueWasNull;
}
/**
* Reads an SQL <code>DATALINK</code> value from the stream and
* returns it as an <code>URL</code> object in the Java programming
* language.
* <P>
* This method does not perform type-safe checking to determine if the
* returned type is the expected type as this responsibility is delegated
* to the UDT mapping as implemented by a <code>SQLData</code>
* implementation.
*
* @return an <code>URL</code> object representing the SQL
* <code>DATALINK</code> value at the head of the stream; *
* if the value is <code>SQL NULL</code>, return
* <code>null</code>
* @throws SQLException if the read position is located at an invalid
* position; or if there are no further values in the stream.
*/
public java.net.URL readURL() throws SQLException {
return (java.net.URL)getNextAttribute();
}
//---------------------------- JDBC 4.0 -------------------------
/**
* Reads an SQL <code>NCLOB</code> value from the stream and returns it as a
* <code>Clob</code> object in the Java programming language.
*
* @return a <code>NClob</code> object representing data of the SQL <code>NCLOB</code> value
* at the head of the stream; <code>null</code> if the value read is
* SQL <code>NULL</code>
* @exception SQLException if a database access error occurs
* @since 1.6
*/
public NClob readNClob() throws SQLException {
return (NClob)getNextAttribute();
}
/**
* Reads the next attribute in the stream and returns it as a <code>String</code>
* in the Java programming language. It is intended for use when
* accessing <code>NCHAR</code>,<code>NVARCHAR</code>
* and <code>LONGNVARCHAR</code> columns.
*
* @return the attribute; if the value is SQL <code>NULL</code>, returns <code>null</code>
* @exception SQLException if a database access error occurs
* @since 1.6
*/
public String readNString() throws SQLException {
return (String)getNextAttribute();
}
/**
* Reads an SQL <code>XML</code> value from the stream and returns it as a
* <code>SQLXML</code> object in the Java programming language.
*
* @return a <code>SQLXML</code> object representing data of the SQL <code>XML</code> value
* at the head of the stream; <code>null</code> if the value read is
* SQL <code>NULL</code>
* @exception SQLException if a database access error occurs
* @since 1.6
*/
public SQLXML readSQLXML() throws SQLException {
return (SQLXML)getNextAttribute();
}
/**
* Reads an SQL <code>ROWID</code> value from the stream and returns it as a
* <code>RowId</code> object in the Java programming language.
*
* @return a <code>RowId</code> object representing data of the SQL <code>ROWID</code> value
* at the head of the stream; <code>null</code> if the value read is
* SQL <code>NULL</code>
* @exception SQLException if a database access error occurs
* @since 1.6
*/
public RowId readRowId() throws SQLException {
return (RowId)getNextAttribute();
}
}

View file

@ -0,0 +1,631 @@
/*
* 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.serial;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.*;
import java.util.Map;
import java.util.Vector;
/**
* The output stream for writing the attributes of a
* custom-mapped user-defined type (UDT) back to the database.
* The driver uses this interface internally, and its
* methods are never directly invoked by an application programmer.
* <p>
* When an application calls the
* method <code>PreparedStatement.setObject</code>, the driver
* checks to see whether the value to be written is a UDT with
* a custom mapping. If it is, there will be an entry in a
* type map containing the <code>Class</code> object for the
* class that implements <code>SQLData</code> for this UDT.
* If the value to be written is an instance of <code>SQLData</code>,
* the driver will create an instance of <code>SQLOutputImpl</code>
* and pass it to the method <code>SQLData.writeSQL</code>.
* The method <code>writeSQL</code> in turn calls the
* appropriate <code>SQLOutputImpl.writeXXX</code> methods
* to write data from the <code>SQLData</code> object to
* the <code>SQLOutputImpl</code> output stream as the
* representation of an SQL user-defined type.
*
* @since 1.5
*/
public class SQLOutputImpl implements SQLOutput {
/**
* A reference to an existing vector that
* contains the attributes of a <code>Struct</code> object.
*/
@SuppressWarnings("rawtypes")
private Vector attribs;
/**
* The type map the driver supplies to a newly created
* <code>SQLOutputImpl</code> object. This type map
* indicates the <code>SQLData</code> class whose
* <code>writeSQL</code> method will be called. This
* method will in turn call the appropriate
* <code>SQLOutputImpl</code> writer methods.
*/
@SuppressWarnings("rawtypes")
private Map map;
/**
* Creates a new <code>SQLOutputImpl</code> object
* initialized with the given vector of attributes and
* type map. The driver will use the type map to determine
* which <code>SQLData.writeSQL</code> method to invoke.
* This method will then call the appropriate
* <code>SQLOutputImpl</code> writer methods in order and
* thereby write the attributes to the new output stream.
*
* @param attributes a <code>Vector</code> object containing the attributes of
* the UDT to be mapped to one or more objects in the Java
* programming language
*
* @param map a <code>java.util.Map</code> object containing zero or
* more entries, with each entry consisting of 1) a <code>String</code>
* giving the fully qualified name of a UDT and 2) the
* <code>Class</code> object for the <code>SQLData</code> implementation
* that defines how the UDT is to be mapped
* @throws SQLException if the <code>attributes</code> or the <code>map</code>
* is a <code>null</code> value
*/
public SQLOutputImpl(Vector<?> attributes, Map<String,?> map)
throws SQLException
{
if ((attributes == null) || (map == null)) {
throw new SQLException("Cannot instantiate a SQLOutputImpl " +
"instance with null parameters");
}
this.attribs = attributes;
this.map = map;
}
//================================================================
// Methods for writing attributes to the stream of SQL data.
// These methods correspond to the column-accessor methods of
// java.sql.ResultSet.
//================================================================
/**
* Writes a <code>String</code> in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>CHAR</code>, <code>VARCHAR</code>, or
* <code>LONGVARCHAR</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeString(String x) throws SQLException {
//System.out.println("Adding :"+x);
attribs.add(x);
}
/**
* Writes a <code>boolean</code> in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>BIT</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeBoolean(boolean x) throws SQLException {
attribs.add(Boolean.valueOf(x));
}
/**
* Writes a <code>byte</code> in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>BIT</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeByte(byte x) throws SQLException {
attribs.add(Byte.valueOf(x));
}
/**
* Writes a <code>short</code> in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>SMALLINT</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeShort(short x) throws SQLException {
attribs.add(Short.valueOf(x));
}
/**
* Writes an <code>int</code> in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>INTEGER</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeInt(int x) throws SQLException {
attribs.add(Integer.valueOf(x));
}
/**
* Writes a <code>long</code> in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>BIGINT</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeLong(long x) throws SQLException {
attribs.add(Long.valueOf(x));
}
/**
* Writes a <code>float</code> in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>REAL</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeFloat(float x) throws SQLException {
attribs.add(Float.valueOf(x));
}
/**
* Writes a <code>double</code> in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>DOUBLE</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeDouble(double x) throws SQLException{
attribs.add(Double.valueOf(x));
}
/**
* Writes a <code>java.math.BigDecimal</code> object in the Java programming
* language to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>NUMERIC</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeBigDecimal(java.math.BigDecimal x) throws SQLException{
attribs.add(x);
}
/**
* Writes an array of <code>bytes</code> in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>VARBINARY</code> or <code>LONGVARBINARY</code>
* before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeBytes(byte[] x) throws SQLException {
attribs.add(x);
}
/**
* Writes a <code>java.sql.Date</code> object in the Java programming
* language to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>DATE</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeDate(java.sql.Date x) throws SQLException {
attribs.add(x);
}
/**
* Writes a <code>java.sql.Time</code> object in the Java programming
* language to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>TIME</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeTime(java.sql.Time x) throws SQLException {
attribs.add(x);
}
/**
* Writes a <code>java.sql.Timestamp</code> object in the Java programming
* language to this <code>SQLOutputImpl</code> object. The driver converts
* it to an SQL <code>TIMESTAMP</code> before returning it to the database.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeTimestamp(java.sql.Timestamp x) throws SQLException {
attribs.add(x);
}
/**
* Writes a stream of Unicode characters to this
* <code>SQLOutputImpl</code> object. The driver will do any necessary
* conversion from Unicode to the database <code>CHAR</code> format.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
public void writeCharacterStream(java.io.Reader x) throws SQLException {
BufferedReader bufReader = new BufferedReader(x);
try {
int i;
while ((i = bufReader.read()) != -1) {
char ch = (char)i;
String strLine = bufReader.readLine();
writeString(ch + strLine);
}
} catch (IOException ioe) {
}
}
/**
* Writes a stream of ASCII characters to this
* <code>SQLOutputImpl</code> object. The driver will do any necessary
* conversion from ASCII to the database <code>CHAR</code> format.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
public void writeAsciiStream(java.io.InputStream x) throws SQLException {
BufferedReader bufReader = new BufferedReader(new InputStreamReader(x));
try {
int i;
while ((i = bufReader.read()) != -1) {
char ch = (char)i;
String strLine = bufReader.readLine();
writeString(ch + strLine);
}
} catch (IOException ioe) {
throw new SQLException(ioe.getMessage());
}
}
/**
* Writes a stream of uninterpreted bytes to this <code>SQLOutputImpl</code>
* object.
*
* @param x the value to pass to the database
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
public void writeBinaryStream(java.io.InputStream x) throws SQLException {
BufferedReader bufReader = new BufferedReader(new InputStreamReader(x));
try {
int i;
while ((i = bufReader.read()) != -1) {
char ch = (char)i;
String strLine = bufReader.readLine();
writeString(ch + strLine);
}
} catch (IOException ioe) {
throw new SQLException(ioe.getMessage());
}
}
//================================================================
// Methods for writing items of SQL user-defined types to the stream.
// These methods pass objects to the database as values of SQL
// Structured Types, Distinct Types, Constructed Types, and Locator
// Types. They decompose the Java object(s) and write leaf data
// items using the methods above.
//================================================================
/**
* Writes to the stream the data contained in the given
* <code>SQLData</code> object.
* When the <code>SQLData</code> object is <code>null</code>, this
* method writes an SQL <code>NULL</code> to the stream.
* Otherwise, it calls the <code>SQLData.writeSQL</code>
* method of the given object, which
* writes the object's attributes to the stream.
* <P>
* The implementation of the method <code>SQLData.writeSQ</code>
* calls the appropriate <code>SQLOutputImpl.writeXXX</code> method(s)
* for writing each of the object's attributes in order.
* The attributes must be read from an <code>SQLInput</code>
* input stream and written to an <code>SQLOutputImpl</code>
* output stream in the same order in which they were
* listed in the SQL definition of the user-defined type.
*
* @param x the object representing data of an SQL structured or
* distinct type
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeObject(SQLData x) throws SQLException {
/*
* Except for the types that are passed as objects
* this seems to be the only way for an object to
* get a null value for a field in a structure.
*
* Note: this means that the class defining SQLData
* will need to track if a field is SQL null for itself
*/
if (x == null) {
attribs.add(null);
} else {
/*
* We have to write out a SerialStruct that contains
* the name of this class otherwise we don't know
* what to re-instantiate during readSQL()
*/
attribs.add(new SerialStruct(x, map));
}
}
/**
* Writes a <code>Ref</code> object in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to a serializable <code>SerialRef</code> SQL <code>REF</code> value
* before returning it to the database.
*
* @param x an object representing an SQL <code>REF</code> value
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeRef(Ref x) throws SQLException {
if (x == null) {
attribs.add(null);
} else {
attribs.add(new SerialRef(x));
}
}
/**
* Writes a <code>Blob</code> object in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to a serializable <code>SerialBlob</code> SQL <code>BLOB</code> value
* before returning it to the database.
*
* @param x an object representing an SQL <code>BLOB</code> value
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeBlob(Blob x) throws SQLException {
if (x == null) {
attribs.add(null);
} else {
attribs.add(new SerialBlob(x));
}
}
/**
* Writes a <code>Clob</code> object in the Java programming language
* to this <code>SQLOutputImpl</code> object. The driver converts
* it to a serializable <code>SerialClob</code> SQL <code>CLOB</code> value
* before returning it to the database.
*
* @param x an object representing an SQL <code>CLOB</code> value
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeClob(Clob x) throws SQLException {
if (x == null) {
attribs.add(null);
} else {
attribs.add(new SerialClob(x));
}
}
/**
* Writes a <code>Struct</code> object in the Java
* programming language to this <code>SQLOutputImpl</code>
* object. The driver converts this value to an SQL structured type
* before returning it to the database.
* <P>
* This method should be used when an SQL structured type has been
* mapped to a <code>Struct</code> object in the Java programming
* language (the standard mapping). The method
* <code>writeObject</code> should be used if an SQL structured type
* has been custom mapped to a class in the Java programming language.
*
* @param x an object representing the attributes of an SQL structured type
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeStruct(Struct x) throws SQLException {
SerialStruct s = new SerialStruct(x,map);
attribs.add(s);
}
/**
* Writes an <code>Array</code> object in the Java
* programming language to this <code>SQLOutputImpl</code>
* object. The driver converts this value to a serializable
* <code>SerialArray</code> SQL <code>ARRAY</code>
* value before returning it to the database.
*
* @param x an object representing an SQL <code>ARRAY</code> value
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeArray(Array x) throws SQLException {
if (x == null) {
attribs.add(null);
} else {
attribs.add(new SerialArray(x, map));
}
}
/**
* Writes an <code>java.sql.Type.DATALINK</code> object in the Java
* programming language to this <code>SQLOutputImpl</code> object. The
* driver converts this value to a serializable <code>SerialDatalink</code>
* SQL <code>DATALINK</code> value before return it to the database.
*
* @param url an object representing a SQL <code>DATALINK</code> value
* @throws SQLException if the <code>SQLOutputImpl</code> object is in
* use by a <code>SQLData</code> object attempting to write the attribute
* values of a UDT to the database.
*/
@SuppressWarnings("unchecked")
public void writeURL(java.net.URL url) throws SQLException {
if (url == null) {
attribs.add(null);
} else {
attribs.add(new SerialDatalink(url));
}
}
/**
* Writes the next attribute to the stream as a <code>String</code>
* in the Java programming language. The driver converts this to a
* SQL <code>NCHAR</code> or
* <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
* (depending on the argument's
* size relative to the driver's limits on <code>NVARCHAR</code> values)
* when it sends it to the stream.
*
* @param x the value to pass to the database
* @exception SQLException if a database access error occurs
* @since 1.6
*/
@SuppressWarnings("unchecked")
public void writeNString(String x) throws SQLException {
attribs.add(x);
}
/**
* Writes an SQL <code>NCLOB</code> value to the stream.
*
* @param x a <code>NClob</code> object representing data of an SQL
* <code>NCLOB</code> value
*
* @exception SQLException if a database access error occurs
* @since 1.6
*/
@SuppressWarnings("unchecked")
public void writeNClob(NClob x) throws SQLException {
attribs.add(x);
}
/**
* Writes an SQL <code>ROWID</code> value to the stream.
*
* @param x a <code>RowId</code> object representing data of an SQL
* <code>ROWID</code> value
*
* @exception SQLException if a database access error occurs
* @since 1.6
*/
@SuppressWarnings("unchecked")
public void writeRowId(RowId x) throws SQLException {
attribs.add(x);
}
/**
* Writes an SQL <code>XML</code> value to the stream.
*
* @param x a <code>SQLXML</code> object representing data of an SQL
* <code>XML</code> value
*
* @exception SQLException if a database access error occurs
* @since 1.6
*/
@SuppressWarnings("unchecked")
public void writeSQLXML(SQLXML x) throws SQLException {
attribs.add(x);
}
}

View file

@ -0,0 +1,668 @@
/*
* Copyright (c) 2003, 2020, 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.serial;
import java.sql.*;
import java.io.*;
import java.util.Map;
import java.net.URL;
import java.util.Arrays;
/**
* A serialized version of an <code>Array</code>
* object, which is the mapping in the Java programming language of an SQL
* <code>ARRAY</code> value.
* <P>
* The <code>SerialArray</code> class provides a constructor for creating
* a <code>SerialArray</code> instance from an <code>Array</code> object,
* methods for getting the base type and the SQL name for the base type, and
* methods for copying all or part of a <code>SerialArray</code> object.
* <P>
*
* Note: In order for this class to function correctly, a connection to the
* data source
* must be available in order for the SQL <code>Array</code> object to be
* materialized (have all of its elements brought to the client server)
* if necessary. At this time, logical pointers to the data in the data source,
* such as locators, are not currently supported.
*
* <h2> Thread safety </h2>
*
* A SerialArray is not safe for use by multiple concurrent threads. If a
* SerialArray is to be used by more than one thread then access to the
* SerialArray should be controlled by appropriate synchronization.
*
* @since 1.5
*/
public class SerialArray implements Array, Serializable, Cloneable {
/**
* A serialized array in which each element is an <code>Object</code>
* in the Java programming language that represents an element
* in the SQL <code>ARRAY</code> value.
* @serial
*/
@SuppressWarnings("serial") // Not statically typed as Serializable
private Object[] elements;
/**
* The SQL type of the elements in this <code>SerialArray</code> object. The
* type is expressed as one of the constants from the class
* <code>java.sql.Types</code>.
* @serial
*/
private int baseType;
/**
* The type name used by the DBMS for the elements in the SQL <code>ARRAY</code>
* value that this <code>SerialArray</code> object represents.
* @serial
*/
private String baseTypeName;
/**
* The number of elements in this <code>SerialArray</code> object, which
* is also the number of elements in the SQL <code>ARRAY</code> value
* that this <code>SerialArray</code> object represents.
* @serial
*/
private int len;
/**
* Constructs a new <code>SerialArray</code> object from the given
* <code>Array</code> object, using the given type map for the custom
* mapping of each element when the elements are SQL UDTs.
* <P>
* This method does custom mapping if the array elements are a UDT
* and the given type map has an entry for that UDT.
* Custom mapping is recursive,
* meaning that if, for instance, an element of an SQL structured type
* is an SQL structured type that itself has an element that is an SQL
* structured type, each structured type that has a custom mapping will be
* mapped according to the given type map.
* <P>
* The new <code>SerialArray</code>
* object contains the same elements as the <code>Array</code> object
* from which it is built, except when the base type is the SQL type
* <code>STRUCT</code>, <code>ARRAY</code>, <code>BLOB</code>,
* <code>CLOB</code>, <code>DATALINK</code> or <code>JAVA_OBJECT</code>.
* In this case, each element in the new
* <code>SerialArray</code> object is the appropriate serialized form,
* that is, a <code>SerialStruct</code>, <code>SerialArray</code>,
* <code>SerialBlob</code>, <code>SerialClob</code>,
* <code>SerialDatalink</code>, or <code>SerialJavaObject</code> object.
* <P>
* Note: (1) The <code>Array</code> object from which a <code>SerialArray</code>
* object is created must have materialized the SQL <code>ARRAY</code> value's
* data on the client before it is passed to the constructor. Otherwise,
* the new <code>SerialArray</code> object will contain no data.
* <p>
* Note: (2) If the <code>Array</code> contains <code>java.sql.Types.JAVA_OBJECT</code>
* types, the <code>SerialJavaObject</code> constructor is called where checks
* are made to ensure this object is serializable.
* <p>
* Note: (3) The <code>Array</code> object supplied to this constructor cannot
* return <code>null</code> for any <code>Array.getArray()</code> methods.
* <code>SerialArray</code> cannot serialize null array values.
*
*
* @param array the <code>Array</code> object to be serialized
* @param map a <code>java.util.Map</code> object in which
* each entry consists of 1) a <code>String</code> object
* giving the fully qualified name of a UDT (an SQL structured type or
* distinct type) and 2) the
* <code>Class</code> object for the <code>SQLData</code> implementation
* that defines how the UDT is to be mapped. The <i>map</i>
* parameter does not have any effect for <code>Blob</code>,
* <code>Clob</code>, <code>DATALINK</code>, or
* <code>JAVA_OBJECT</code> types.
* @throws SerialException if an error occurs serializing the
* <code>Array</code> object
* @throws SQLException if a database access error occurs or if the
* <i>array</i> or the <i>map</i> values are <code>null</code>
*/
public SerialArray(Array array, Map<String,Class<?>> map)
throws SerialException, SQLException
{
if ((array == null) || (map == null)) {
throw new SQLException("Cannot instantiate a SerialArray " +
"object with null parameters");
}
if ((elements = (Object[])array.getArray()) == null) {
throw new SQLException("Invalid Array object. Calls to Array.getArray() " +
"return null value which cannot be serialized");
}
elements = (Object[])array.getArray(map);
baseType = array.getBaseType();
baseTypeName = array.getBaseTypeName();
len = elements.length;
switch (baseType) {
case java.sql.Types.STRUCT:
for (int i = 0; i < len; i++) {
elements[i] = new SerialStruct((Struct)elements[i], map);
}
break;
case java.sql.Types.ARRAY:
for (int i = 0; i < len; i++) {
elements[i] = new SerialArray((Array)elements[i], map);
}
break;
case java.sql.Types.BLOB:
for (int i = 0; i < len; i++) {
elements[i] = new SerialBlob((Blob)elements[i]);
}
break;
case java.sql.Types.CLOB:
for (int i = 0; i < len; i++) {
elements[i] = new SerialClob((Clob)elements[i]);
}
break;
case java.sql.Types.DATALINK:
for (int i = 0; i < len; i++) {
elements[i] = new SerialDatalink((URL)elements[i]);
}
break;
case java.sql.Types.JAVA_OBJECT:
for (int i = 0; i < len; i++) {
elements[i] = new SerialJavaObject(elements[i]);
}
}
}
/**
* This method frees the {@code SerialArray} object and releases the
* resources that it holds. The object is invalid once the {@code free}
* method is called. <p> If {@code free} is called multiple times, the
* subsequent calls to {@code free} are treated as a no-op. </P>
*
* @throws SQLException if an error occurs releasing the SerialArray's resources
* @since 1.6
*/
public void free() throws SQLException {
if (elements != null) {
elements = null;
baseTypeName= null;
}
}
/**
* Constructs a new <code>SerialArray</code> object from the given
* <code>Array</code> object.
* <P>
* This constructor does not do custom mapping. If the base type of the array
* is an SQL structured type and custom mapping is desired, the constructor
* <code>SerialArray(Array array, Map map)</code> should be used.
* <P>
* The new <code>SerialArray</code>
* object contains the same elements as the <code>Array</code> object
* from which it is built, except when the base type is the SQL type
* <code>BLOB</code>,
* <code>CLOB</code>, <code>DATALINK</code> or <code>JAVA_OBJECT</code>.
* In this case, each element in the new
* <code>SerialArray</code> object is the appropriate serialized form,
* that is, a <code>SerialBlob</code>, <code>SerialClob</code>,
* <code>SerialDatalink</code>, or <code>SerialJavaObject</code> object.
* <P>
* Note: (1) The <code>Array</code> object from which a <code>SerialArray</code>
* object is created must have materialized the SQL <code>ARRAY</code> value's
* data on the client before it is passed to the constructor. Otherwise,
* the new <code>SerialArray</code> object will contain no data.
* <p>
* Note: (2) The <code>Array</code> object supplied to this constructor cannot
* return <code>null</code> for any <code>Array.getArray()</code> methods.
* <code>SerialArray</code> cannot serialize <code>null</code> array values.
*
* @param array the <code>Array</code> object to be serialized
* @throws SerialException if an error occurs serializing the
* <code>Array</code> object
* @throws SQLException if a database access error occurs or the
* <i>array</i> parameter is <code>null</code>.
*/
public SerialArray(Array array) throws SerialException, SQLException {
if (array == null) {
throw new SQLException("Cannot instantiate a SerialArray " +
"object with a null Array object");
}
if ((elements = (Object[])array.getArray()) == null) {
throw new SQLException("Invalid Array object. Calls to Array.getArray() " +
"return null value which cannot be serialized");
}
//elements = (Object[])array.getArray();
baseType = array.getBaseType();
baseTypeName = array.getBaseTypeName();
len = elements.length;
switch (baseType) {
case java.sql.Types.BLOB:
for (int i = 0; i < len; i++) {
elements[i] = new SerialBlob((Blob)elements[i]);
}
break;
case java.sql.Types.CLOB:
for (int i = 0; i < len; i++) {
elements[i] = new SerialClob((Clob)elements[i]);
}
break;
case java.sql.Types.DATALINK:
for (int i = 0; i < len; i++) {
elements[i] = new SerialDatalink((URL)elements[i]);
}
break;
case java.sql.Types.JAVA_OBJECT:
for (int i = 0; i < len; i++) {
elements[i] = new SerialJavaObject(elements[i]);
}
break;
}
}
/**
* Returns a new array that is a copy of this <code>SerialArray</code>
* object.
*
* @return a copy of this <code>SerialArray</code> object as an
* <code>Object</code> in the Java programming language
* @throws SerialException if an error occurs;
* if {@code free} had previously been called on this object
*/
public Object getArray() throws SerialException {
isValid();
Object dst = new Object[len];
System.arraycopy((Object)elements, 0, dst, 0, len);
return dst;
}
/**
* Returns a new array that is a copy of this <code>SerialArray</code>
* object, using the given type map for the custom
* mapping of each element when the elements are SQL UDTs.
* <P>
* This method does custom mapping if the array elements are a UDT
* and the given type map has an entry for that UDT.
* Custom mapping is recursive,
* meaning that if, for instance, an element of an SQL structured type
* is an SQL structured type that itself has an element that is an SQL
* structured type, each structured type that has a custom mapping will be
* mapped according to the given type map.
*
* @param map a <code>java.util.Map</code> object in which
* each entry consists of 1) a <code>String</code> object
* giving the fully qualified name of a UDT and 2) the
* <code>Class</code> object for the <code>SQLData</code> implementation
* that defines how the UDT is to be mapped
* @return a copy of this <code>SerialArray</code> object as an
* <code>Object</code> in the Java programming language
* @throws SerialException if an error occurs;
* if {@code free} had previously been called on this object
*/
public Object getArray(Map<String, Class<?>> map) throws SerialException {
isValid();
Object dst[] = new Object[len];
System.arraycopy((Object)elements, 0, dst, 0, len);
return dst;
}
/**
* Returns a new array that is a copy of a slice
* of this <code>SerialArray</code> object, starting with the
* element at the given index and containing the given number
* of consecutive elements.
*
* @param index the index into this <code>SerialArray</code> object
* of the first element to be copied;
* the index of the first element is <code>0</code>
* @param count the number of consecutive elements to be copied, starting
* at the given index
* @return a copy of the designated elements in this <code>SerialArray</code>
* object as an <code>Object</code> in the Java programming language
* @throws SerialException if an error occurs;
* if {@code free} had previously been called on this object
*/
public Object getArray(long index, int count) throws SerialException {
isValid();
Object dst = new Object[count];
System.arraycopy((Object)elements, (int)index, dst, 0, count);
return dst;
}
/**
* Returns a new array that is a copy of a slice
* of this <code>SerialArray</code> object, starting with the
* element at the given index and containing the given number
* of consecutive elements.
* <P>
* This method does custom mapping if the array elements are a UDT
* and the given type map has an entry for that UDT.
* Custom mapping is recursive,
* meaning that if, for instance, an element of an SQL structured type
* is an SQL structured type that itself has an element that is an SQL
* structured type, each structured type that has a custom mapping will be
* mapped according to the given type map.
*
* @param index the index into this <code>SerialArray</code> object
* of the first element to be copied; the index of the
* first element in the array is <code>0</code>
* @param count the number of consecutive elements to be copied, starting
* at the given index
* @param map a <code>java.util.Map</code> object in which
* each entry consists of 1) a <code>String</code> object
* giving the fully qualified name of a UDT and 2) the
* <code>Class</code> object for the <code>SQLData</code> implementation
* that defines how the UDT is to be mapped
* @return a copy of the designated elements in this <code>SerialArray</code>
* object as an <code>Object</code> in the Java programming language
* @throws SerialException if an error occurs;
* if {@code free} had previously been called on this object
*/
public Object getArray(long index, int count, Map<String,Class<?>> map)
throws SerialException
{
isValid();
Object dst = new Object[count];
System.arraycopy((Object)elements, (int)index, dst, 0, count);
return dst;
}
/**
* Retrieves the SQL type of the elements in this <code>SerialArray</code>
* object. The <code>int</code> returned is one of the constants in the class
* <code>java.sql.Types</code>.
*
* @return one of the constants in <code>java.sql.Types</code>, indicating
* the SQL type of the elements in this <code>SerialArray</code> object
* @throws SerialException if an error occurs;
* if {@code free} had previously been called on this object
*/
public int getBaseType() throws SerialException {
isValid();
return baseType;
}
/**
* Retrieves the DBMS-specific type name for the elements in this
* <code>SerialArray</code> object.
*
* @return the SQL type name used by the DBMS for the base type of this
* <code>SerialArray</code> object
* @throws SerialException if an error occurs;
* if {@code free} had previously been called on this object
*/
public String getBaseTypeName() throws SerialException {
isValid();
return baseTypeName;
}
/**
* Retrieves a <code>ResultSet</code> object holding the elements of
* the subarray that starts at
* index <i>index</i> and contains up to <i>count</i> successive elements.
* This method uses the connection's type map to map the elements of
* the array if the map contains
* an entry for the base type. Otherwise, the standard mapping is used.
*
* @param index the index into this <code>SerialArray</code> object
* of the first element to be copied; the index of the
* first element in the array is <code>0</code>
* @param count the number of consecutive elements to be copied, starting
* at the given index
* @return a <code>ResultSet</code> object containing the designated
* elements in this <code>SerialArray</code> object, with a
* separate row for each element
* @throws SerialException if called with the cause set to
* {@code UnsupportedOperationException}
*/
public ResultSet getResultSet(long index, int count) throws SerialException {
SerialException se = new SerialException();
se.initCause(new UnsupportedOperationException());
throw se;
}
/**
*
* Retrieves a <code>ResultSet</code> object that contains all of
* the elements of the SQL <code>ARRAY</code>
* value represented by this <code>SerialArray</code> object. This method uses
* the specified map for type map customizations unless the base type of the
* array does not match a user-defined type (UDT) in <i>map</i>, in
* which case it uses the
* standard mapping. This version of the method <code>getResultSet</code>
* uses either the given type map or the standard mapping; it never uses the
* type map associated with the connection.
*
* @param map a <code>java.util.Map</code> object in which
* each entry consists of 1) a <code>String</code> object
* giving the fully qualified name of a UDT and 2) the
* <code>Class</code> object for the <code>SQLData</code> implementation
* that defines how the UDT is to be mapped
* @return a <code>ResultSet</code> object containing all of the
* elements in this <code>SerialArray</code> object, with a
* separate row for each element
* @throws SerialException if called with the cause set to
* {@code UnsupportedOperationException}
*/
public ResultSet getResultSet(Map<String, Class<?>> map)
throws SerialException
{
SerialException se = new SerialException();
se.initCause(new UnsupportedOperationException());
throw se;
}
/**
* Retrieves a <code>ResultSet</code> object that contains all of
* the elements in the <code>ARRAY</code> value that this
* <code>SerialArray</code> object represents.
* If appropriate, the elements of the array are mapped using the connection's
* type map; otherwise, the standard mapping is used.
*
* @return a <code>ResultSet</code> object containing all of the
* elements in this <code>SerialArray</code> object, with a
* separate row for each element
* @throws SerialException if called with the cause set to
* {@code UnsupportedOperationException}
*/
public ResultSet getResultSet() throws SerialException {
SerialException se = new SerialException();
se.initCause(new UnsupportedOperationException());
throw se;
}
/**
* Retrieves a result set holding the elements of the subarray that starts at
* Retrieves a <code>ResultSet</code> object that contains a subarray of the
* elements in this <code>SerialArray</code> object, starting at
* index <i>index</i> and containing up to <i>count</i> successive
* elements. This method uses
* the specified map for type map customizations unless the base type of the
* array does not match a user-defined type (UDT) in <i>map</i>, in
* which case it uses the
* standard mapping. This version of the method <code>getResultSet</code> uses
* either the given type map or the standard mapping; it never uses the type
* map associated with the connection.
*
* @param index the index into this <code>SerialArray</code> object
* of the first element to be copied; the index of the
* first element in the array is <code>0</code>
* @param count the number of consecutive elements to be copied, starting
* at the given index
* @param map a <code>java.util.Map</code> object in which
* each entry consists of 1) a <code>String</code> object
* giving the fully qualified name of a UDT and 2) the
* <code>Class</code> object for the <code>SQLData</code> implementation
* that defines how the UDT is to be mapped
* @return a <code>ResultSet</code> object containing the designated
* elements in this <code>SerialArray</code> object, with a
* separate row for each element
* @throws SerialException if called with the cause set to
* {@code UnsupportedOperationException}
*/
public ResultSet getResultSet(long index, int count,
Map<String,Class<?>> map)
throws SerialException
{
SerialException se = new SerialException();
se.initCause(new UnsupportedOperationException());
throw se;
}
/**
* Compares this SerialArray to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* SerialArray} object whose elements are identical to this object's elements
*
* @param obj The object to compare this {@code SerialArray} against
*
* @return {@code true} if the given object represents a {@code SerialArray}
* equivalent to this SerialArray, {@code false} otherwise
*
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof SerialArray) {
SerialArray sa = (SerialArray)obj;
return baseType == sa.baseType &&
baseTypeName.equals(sa.baseTypeName) &&
Arrays.equals(elements, sa.elements);
}
return false;
}
/**
* Returns a hash code for this SerialArray. The hash code for a
* {@code SerialArray} object is computed using the hash codes
* of the elements of the {@code SerialArray} object
*
* @return a hash code value for this object.
*/
public int hashCode() {
return (((31 + Arrays.hashCode(elements)) * 31 + len) * 31 +
baseType) * 31 + baseTypeName.hashCode();
}
/**
* Returns a clone of this {@code SerialArray}. The copy will contain a
* reference to a clone of the underlying objects array, not a reference
* to the original underlying object array of this {@code SerialArray} object.
*
* @return a clone of this SerialArray
*/
public Object clone() {
try {
SerialArray sa = (SerialArray) super.clone();
sa.elements = (elements != null) ? Arrays.copyOf(elements, len) : null;
return sa;
} catch (CloneNotSupportedException ex) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* readObject is called to restore the state of the {@code SerialArray} from
* a stream.
* @param s the {@code ObjectInputStream} to read from.
*
* @throws ClassNotFoundException if the class of a serialized object
* could not be found.
* @throws IOException if an I/O error occurs.
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
Object[] tmp = (Object[])fields.get("elements", null);
if (tmp == null)
throw new InvalidObjectException("elements is null and should not be!");
elements = tmp.clone();
len = fields.get("len", 0);
if(elements.length != len)
throw new InvalidObjectException("elements is not the expected size");
baseType = fields.get("baseType", 0);
baseTypeName = (String)fields.get("baseTypeName", null);
}
/**
* writeObject is called to save the state of the {@code SerialArray}
* to a stream.
* @param s the {@code ObjectOutputStream} to write to.
* @throws IOException if an I/O error occurs.
*/
private void writeObject(ObjectOutputStream s)
throws IOException {
ObjectOutputStream.PutField fields = s.putFields();
fields.put("elements", elements);
fields.put("len", len);
fields.put("baseType", baseType);
fields.put("baseTypeName", baseTypeName);
s.writeFields();
}
/**
* Check to see if this object had previously had its {@code free} method
* called
*
* @throws SerialException
*/
private void isValid() throws SerialException {
if (elements == null) {
throw new SerialException("Error: You cannot call a method on a "
+ "SerialArray instance once free() has been called.");
}
}
/**
* The identifier that assists in the serialization of this <code>SerialArray</code>
* object.
*/
static final long serialVersionUID = -8466174297270688520L;
}

View file

@ -0,0 +1,618 @@
/*
* Copyright (c) 2003, 2025, 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.serial;
import java.sql.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.Arrays;
/**
* A serialized mapping in the Java programming language of an SQL
* <code>BLOB</code> value.
* <P>
* The <code>SerialBlob</code> class provides a constructor for creating
* an instance from a <code>Blob</code> object. Note that the
* <code>Blob</code>
* object should have brought the SQL <code>BLOB</code> value's data over
* to the client before a <code>SerialBlob</code> object
* is constructed from it. The data of an SQL <code>BLOB</code> value can
* be materialized on the client as an array of bytes (using the method
* <code>Blob.getBytes</code>) or as a stream of uninterpreted bytes
* (using the method <code>Blob.getBinaryStream</code>).
* <P>
* <code>SerialBlob</code> methods make it possible to make a copy of a
* <code>SerialBlob</code> object as an array of bytes or as a stream.
* They also make it possible to locate a given pattern of bytes or a
* <code>Blob</code> object within a <code>SerialBlob</code> object
* and to update or truncate a <code>Blob</code> object.
*
* <h2> Thread safety </h2>
*
* <p> A SerialBlob is not safe for use by multiple concurrent threads. If a
* SerialBlob is to be used by more than one thread then access to the SerialBlob
* should be controlled by appropriate synchronization.
*
* @author Jonathan Bruce
* @since 1.5
*/
public class SerialBlob implements Blob, Serializable, Cloneable {
/**
* A serialized array of uninterpreted bytes representing the
* value of this <code>SerialBlob</code> object.
* @serial
*/
private byte[] buf;
/**
* @serial The internal representation of the <code>Blob</code> object on which this
* <code>SerialBlob</code> object is based.
*/
@SuppressWarnings("serial") // Not statically typed as Serializable; checked in writeObject
private Blob blob;
/**
* The number of bytes in this <code>SerialBlob</code> object's
* array of bytes.
* @serial
*/
private long len;
/**
* The original number of bytes in this <code>SerialBlob</code> object's
* array of bytes when it was first established.
* @serial
*/
private long origLen;
/**
* Constructs a <code>SerialBlob</code> object that is a serialized version of
* the given <code>byte</code> array.
* <p>
* The new <code>SerialBlob</code> object is initialized with the data from the
* <code>byte</code> array, thus allowing disconnected <code>RowSet</code>
* objects to establish serialized <code>Blob</code> objects without
* touching the data source.
*
* @param b the <code>byte</code> array containing the data for the
* <code>Blob</code> object to be serialized
* @throws SerialException if an error occurs during serialization
* @throws SQLException if a SQL errors occurs
*/
public SerialBlob(byte[] b)
throws SerialException, SQLException {
len = b.length;
buf = new byte[(int)len];
for(int i = 0; i < len; i++) {
buf[i] = b[i];
}
origLen = len;
}
/**
* Constructs a <code>SerialBlob</code> object that is a serialized
* version of the given <code>Blob</code> object.
* <P>
* The new <code>SerialBlob</code> object is initialized with the
* data from the <code>Blob</code> object; therefore, the
* <code>Blob</code> object should have previously brought the
* SQL <code>BLOB</code> value's data over to the client from
* the database. Otherwise, the new <code>SerialBlob</code> object
* will contain no data.
*
* @param blob the <code>Blob</code> object from which this
* <code>SerialBlob</code> object is to be constructed;
* cannot be null.
* @throws SerialException if an error occurs during serialization
* @throws SQLException if the <code>Blob</code> passed to this
* to this constructor is a <code>null</code>.
* @see java.sql.Blob
*/
public SerialBlob (Blob blob)
throws SerialException, SQLException {
if (blob == null) {
throw new SQLException(
"Cannot instantiate a SerialBlob object with a null Blob object");
}
len = blob.length();
buf = blob.getBytes(1, (int)len );
this.blob = blob;
origLen = len;
}
/**
* Copies the specified number of bytes, starting at the given
* position, from this <code>SerialBlob</code> object to
* another array of bytes.
* <P>
* Note that if the given number of bytes to be copied is larger than
* the length of this <code>SerialBlob</code> object's array of
* bytes, the given number will be shortened to the array's length.
*
* @param pos the ordinal position of the first byte in this
* <code>SerialBlob</code> object to be copied;
* numbering starts at <code>1</code>; must not be less
* than <code>1</code> and must be less than or equal
* to the length of this <code>SerialBlob</code> object
* @param length the number of bytes to be copied
* @return an array of bytes that is a copy of a region of this
* <code>SerialBlob</code> object, starting at the given
* position and containing the given number of consecutive bytes
* @throws SerialException if the given starting position is out of bounds;
* if {@code free} had previously been called on this object
*/
public byte[] getBytes(long pos, int length) throws SerialException {
isValid();
if (length > len) {
length = (int)len;
}
if (pos < 1 || len - pos < 0 ) {
throw new SerialException("Invalid arguments: position cannot be "
+ "less than 1 or greater than the length of the SerialBlob");
}
pos--; // correct pos to array index
byte[] b = new byte[length];
for (int i = 0; i < length; i++) {
b[i] = this.buf[(int)pos];
pos++;
}
return b;
}
/**
* Retrieves the number of bytes in this <code>SerialBlob</code>
* object's array of bytes.
*
* @return a <code>long</code> indicating the length in bytes of this
* <code>SerialBlob</code> object's array of bytes
* @throws SerialException if an error occurs;
* if {@code free} had previously been called on this object
*/
public long length() throws SerialException {
isValid();
return len;
}
/**
* Returns this <code>SerialBlob</code> object as an input stream.
* Unlike the related method, <code>setBinaryStream</code>,
* a stream is produced regardless of whether the <code>SerialBlob</code>
* was created with a <code>Blob</code> object or a <code>byte</code> array.
*
* @return a <code>java.io.InputStream</code> object that contains
* this <code>SerialBlob</code> object's array of bytes
* @throws SerialException if an error occurs;
* if {@code free} had previously been called on this object
* @see #setBinaryStream
*/
public java.io.InputStream getBinaryStream() throws SerialException {
isValid();
InputStream stream = new ByteArrayInputStream(buf);
return stream;
}
/**
* Returns the position in this <code>SerialBlob</code> object where
* the given pattern of bytes begins, starting the search at the
* specified position.
*
* @param pattern the pattern of bytes for which to search
* @param start the position of the byte in this
* <code>SerialBlob</code> object from which to begin
* the search; the first position is <code>1</code>;
* must not be less than <code>1</code> nor greater than
* the length of this <code>SerialBlob</code> object
* @return the position in this <code>SerialBlob</code> object
* where the given pattern begins, starting at the specified
* position; <code>-1</code> if the pattern is not found
* or the given starting position is out of bounds; position
* numbering for the return value starts at <code>1</code>
* @throws SerialException if an error occurs when serializing the blob;
* if {@code free} had previously been called on this object
* @throws SQLException if there is an error accessing the <code>BLOB</code>
* value from the database
*/
public long position(byte[] pattern, long start)
throws SerialException, SQLException {
isValid();
if (start < 1 || start > len) {
return -1;
}
int pos = (int)start-1; // internally Blobs are stored as arrays.
int i = 0;
long patlen = pattern.length;
while (pos < len) {
if (pattern[i] == buf[pos]) {
if (i + 1 == patlen) {
return (pos + 1) - (patlen - 1);
}
i++; pos++; // increment pos, and i
} else if (pattern[i] != buf[pos]) {
pos++; // increment pos only
}
}
return -1; // not found
}
/**
* Returns the position in this <code>SerialBlob</code> object where
* the given <code>Blob</code> object begins, starting the search at the
* specified position.
*
* @param pattern the <code>Blob</code> object for which to search;
* @param start the position of the byte in this
* <code>SerialBlob</code> object from which to begin
* the search; the first position is <code>1</code>;
* must not be less than <code>1</code> nor greater than
* the length of this <code>SerialBlob</code> object
* @return the position in this <code>SerialBlob</code> object
* where the given <code>Blob</code> object begins, starting
* at the specified position; <code>-1</code> if the pattern is
* not found or the given starting position is out of bounds;
* position numbering for the return value starts at <code>1</code>
* @throws SerialException if an error occurs when serializing the blob;
* if {@code free} had previously been called on this object
* @throws SQLException if there is an error accessing the <code>BLOB</code>
* value from the database
*/
public long position(Blob pattern, long start)
throws SerialException, SQLException {
isValid();
return position(pattern.getBytes(1, (int)(pattern.length())), start);
}
/**
* Writes the given array of bytes to the {@code BLOB} value that
* this {@code Blob} object represents, starting at position
* {@code pos}, and returns the number of bytes written.
*
* @param pos the position in the SQL {@code BLOB} value at which
* to start writing. The first position is {@code 1};
* must not be less than {@code 1} nor greater than
* the length+1 of this {@code SerialBlob} object.
* @param bytes the array of bytes to be written to the {@code BLOB}
* value that this {@code Blob} object represents
* @return the number of bytes written
* @throws SerialException if there is an error accessing the
* {@code BLOB} value; or if an invalid position is set;
* if {@code free} had previously been called on this object
* @throws SQLException if there is an error accessing the {@code BLOB}
* value from the database
* @see #getBytes
*/
public int setBytes(long pos, byte[] bytes)
throws SerialException, SQLException {
return setBytes(pos, bytes, 0, bytes.length);
}
/**
* Writes all or part of the given {@code byte} array to the
* {@code BLOB} value that this {@code Blob} object represents
* and returns the number of bytes written.
* Writing starts at position {@code pos} in the {@code BLOB}
* value; {@code length} bytes from the given byte array are written.
*
* @param pos the position in the {@code BLOB} object at which
* to start writing. The first position is {@code 1};
* must not be less than {@code 1} nor greater than
* the length+1 of this {@code SerialBlob} object.
* @param bytes the array of bytes to be written to the {@code BLOB}
* value
* @param offset the offset into the array {@code byte}s at which
* to start reading the bytes to be set. The first offset position is
* {@code 0}; must not be less than {@code 0} nor greater
* than the length of the array {@code byte}s
* @param length the number of bytes to be written to the
* {@code BLOB} value from the array of bytes {@code byte}s
*
* @return the number of bytes written
* @throws SerialException if there is an error accessing the
* {@code BLOB} value; if an invalid position is set; if an
* invalid offset value is set; or the combined values of the
* {@code length} and {@code offset} is greater than the length of
* {@code byte}s;
* if {@code free} had previously been called on this object
* @throws SQLException if there is an error accessing the {@code BLOB}
* value from the database.
* @see #getBytes
*/
public int setBytes(long pos, byte[] bytes, int offset, int length)
throws SerialException, SQLException {
isValid();
if (offset < 0 || offset > bytes.length) {
throw new SerialException("Invalid offset in byte array set");
}
if (length < 0) {
throw new SerialException("Invalid arguments: length cannot be "
+ "negative");
}
if (pos < 1 || pos > len + 1) {
throw new SerialException("Invalid position in BLOB object set");
}
if (length > bytes.length - offset) {
throw new SerialException("Invalid OffSet. Cannot have combined offset " +
"and length that is greater than the length of bytes");
}
if (pos - 1 + length > Integer.MAX_VALUE) {
throw new SerialException("Invalid length. Cannot have combined pos " +
"and length that is greater than Integer.MAX_VALUE");
}
pos--; // correct to array indexing
if (pos + length > len) {
len = pos + length;
byte[] newbuf = new byte[(int)len];
System.arraycopy(buf, 0, newbuf, 0, (int)pos);
buf = newbuf;
}
System.arraycopy(bytes, offset, buf, (int)pos, length);
return length;
}
/**
* Retrieves a stream that can be used to write to the <code>BLOB</code>
* value that this <code>Blob</code> object represents. The stream begins
* at position <code>pos</code>. This method forwards the
* <code>setBinaryStream()</code> call to the underlying <code>Blob</code> in
* the event that this <code>SerialBlob</code> object is instantiated with a
* <code>Blob</code>. If this <code>SerialBlob</code> is instantiated with
* a <code>byte</code> array, a <code>SerialException</code> is thrown.
*
* @param pos the position in the <code>BLOB</code> value at which
* to start writing
* @return a <code>java.io.OutputStream</code> object to which data can
* be written
* @throws SQLException if there is an error accessing the
* <code>BLOB</code> value
* @throws SerialException if the SerialBlob in not instantiated with a
* <code>Blob</code> object that supports <code>setBinaryStream()</code>;
* if {@code free} had previously been called on this object
* @see #getBinaryStream
*/
public java.io.OutputStream setBinaryStream(long pos)
throws SerialException, SQLException {
isValid();
if (this.blob != null) {
return this.blob.setBinaryStream(pos);
} else {
throw new SerialException("Unsupported operation. SerialBlob cannot " +
"return a writable binary stream, unless instantiated with a Blob object " +
"that provides a setBinaryStream() implementation");
}
}
/**
* Truncates the <code>BLOB</code> value that this <code>Blob</code>
* object represents to be <code>len</code> bytes in length.
*
* @param length the length, in bytes, to which the <code>BLOB</code>
* value that this <code>Blob</code> object represents should be
* truncated
* @throws SerialException if there is an error accessing the Blob value;
* or the length to truncate is greater that the SerialBlob length;
* if {@code free} had previously been called on this object
*/
public void truncate(long length) throws SerialException {
isValid();
if (length > len) {
throw new SerialException(
"Length more than what can be truncated");
} else if((int)length == 0) {
buf = new byte[0];
len = length;
} else {
len = length;
buf = this.getBytes(1, (int)len);
}
}
/**
* Returns an
* <code>InputStream</code> object that contains a partial
* {@code Blob} value, starting with the byte specified by pos, which is
* length bytes in length.
*
* @param pos the offset to the first byte of the partial value to be
* retrieved. The first byte in the {@code Blob} is at position 1
* @param length the length in bytes of the partial value to be retrieved
* @return
* <code>InputStream</code> through which the partial {@code Blob} value can
* be read.
* @throws SQLException if pos is less than 1 or if pos is greater than the
* number of bytes in the {@code Blob} or if pos + length is greater than
* the number of bytes in the {@code Blob}
* @throws SerialException if the {@code free} method had been previously
* called on this object
*
* @since 1.6
*/
public InputStream getBinaryStream(long pos, long length) throws SQLException {
isValid();
if (pos < 1 || pos > this.length()) {
throw new SerialException("Invalid position in BLOB object set");
}
if (length < 1 || length > len - pos + 1) {
throw new SerialException(
"length is < 1 or pos + length > total number of bytes");
}
return new ByteArrayInputStream(buf, (int) pos - 1, (int) length);
}
/**
* This method frees the {@code SerialBlob} object and releases the
* resources that it holds. The object is invalid once the {@code free}
* method is called. <p> If {@code free} is called multiple times, the
* subsequent calls to {@code free} are treated as a no-op. </P>
*
* @throws SQLException if an error occurs releasing the Blob's resources
* @since 1.6
*/
public void free() throws SQLException {
if (buf != null) {
buf = null;
if (blob != null) {
blob.free();
}
blob = null;
}
}
/**
* Compares this SerialBlob to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* SerialBlob} object that represents the same sequence of bytes as this
* object.
*
* @param obj The object to compare this {@code SerialBlob} against
*
* @return {@code true} if the given object represents a {@code SerialBlob}
* equivalent to this SerialBlob, {@code false} otherwise
*
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof SerialBlob) {
SerialBlob sb = (SerialBlob)obj;
if (this.len == sb.len) {
return Arrays.equals(buf, sb.buf);
}
}
return false;
}
/**
* Returns a hash code for this {@code SerialBlob}.
* @return a hash code value for this object.
*/
public int hashCode() {
return ((31 + Arrays.hashCode(buf)) * 31 + (int)len) * 31 + (int)origLen;
}
/**
* Returns a clone of this {@code SerialBlob}. The copy will contain a
* reference to a clone of the internal byte array, not a reference
* to the original internal byte array of this {@code SerialBlob} object.
* The underlying {@code Blob} object will be set to null.
*
* @return a clone of this SerialBlob
*/
public Object clone() {
try {
SerialBlob sb = (SerialBlob) super.clone();
sb.buf = (buf != null) ? Arrays.copyOf(buf, (int)len) : null;
sb.blob = null;
return sb;
} catch (CloneNotSupportedException ex) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* readObject is called to restore the state of the SerialBlob from
* a stream.
* @param s the {@code ObjectInputStream} to read from.
*
* @throws ClassNotFoundException if the class of a serialized object
* could not be found.
* @throws IOException if an I/O error occurs.
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
byte[] tmp = (byte[])fields.get("buf", null);
if (tmp == null)
throw new InvalidObjectException("buf is null and should not be!");
buf = tmp.clone();
len = fields.get("len", 0L);
if (buf.length != len)
throw new InvalidObjectException("buf is not the expected size");
origLen = fields.get("origLen", 0L);
blob = (Blob) fields.get("blob", null);
}
/**
* writeObject is called to save the state of the SerialBlob
* to a stream.
* @param s the {@code ObjectOutputStream} to write to.
* @throws IOException if an I/O error occurs.
*/
private void writeObject(ObjectOutputStream s)
throws IOException {
ObjectOutputStream.PutField fields = s.putFields();
fields.put("buf", buf);
fields.put("len", len);
fields.put("origLen", origLen);
// Note: this check to see if it is an instance of Serializable
// is for backwards compatibility
fields.put("blob", blob instanceof Serializable ? blob : null);
s.writeFields();
}
/**
* Check to see if this object had previously had its {@code free} method
* called
*
* @throws SerialException
*/
private void isValid() throws SerialException {
if (buf == null) {
throw new SerialException("Error: You cannot call a method on a " +
"SerialBlob instance once free() has been called.");
}
}
/**
* The identifier that assists in the serialization of this
* {@code SerialBlob} object.
*/
static final long serialVersionUID = -8144641928112860441L;
}

View file

@ -0,0 +1,709 @@
/*
* Copyright (c) 2003, 2025, 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.serial;
import java.sql.*;
import java.io.*;
import java.util.Arrays;
/**
* A serialized mapping in the Java programming language of an SQL
* <code>CLOB</code> value.
* <P>
* The <code>SerialClob</code> class provides a constructor for creating
* an instance from a <code>Clob</code> object. Note that the <code>Clob</code>
* object should have brought the SQL <code>CLOB</code> value's data over
* to the client before a <code>SerialClob</code> object
* is constructed from it. The data of an SQL <code>CLOB</code> value can
* be materialized on the client as a stream of Unicode characters.
* <P>
* <code>SerialClob</code> methods make it possible to get a substring
* from a <code>SerialClob</code> object or to locate the start of
* a pattern of characters.
*
* <h2> Thread safety </h2>
*
* <p> A SerialClob is not safe for use by multiple concurrent threads. If a
* SerialClob is to be used by more than one thread then access to the SerialClob
* should be controlled by appropriate synchronization.
*
* @author Jonathan Bruce
* @since 1.5
*/
public class SerialClob implements Clob, Serializable, Cloneable {
/**
* A serialized array of characters containing the data of the SQL
* <code>CLOB</code> value that this <code>SerialClob</code> object
* represents.
*
* @serial
*/
private char buf[];
/**
* @serial Internal Clob representation if SerialClob is initialized with a
* Clob. Null if SerialClob is initialized with a char[].
*/
@SuppressWarnings("serial") // Not statically typed as Serializable; checked in writeObject
private Clob clob;
/**
* The length in characters of this <code>SerialClob</code> object's
* internal array of characters.
*
* @serial
*/
private long len;
/**
* The original length in characters of this <code>SerialClob</code>
* object's internal array of characters.
*
* @serial
*/
private long origLen;
/**
* Constructs a <code>SerialClob</code> object that is a serialized version of
* the given <code>char</code> array.
* <p>
* The new <code>SerialClob</code> object is initialized with the data from the
* <code>char</code> array, thus allowing disconnected <code>RowSet</code>
* objects to establish a serialized <code>Clob</code> object without touching
* the data source.
*
* @param ch the char array representing the <code>Clob</code> object to be
* serialized
* @throws SerialException if an error occurs during serialization
* @throws SQLException if a SQL error occurs
*/
public SerialClob(char ch[]) throws SerialException, SQLException {
// %%% JMB. Agreed. Add code here to throw a SQLException if no
// support is available for locatorsUpdateCopy=false
// Serializing locators is not supported.
len = ch.length;
buf = new char[(int)len];
for (int i = 0; i < len ; i++){
buf[i] = ch[i];
}
origLen = len;
clob = null;
}
/**
* Constructs a <code>SerialClob</code> object that is a serialized
* version of the given <code>Clob</code> object.
* <P>
* The new <code>SerialClob</code> object is initialized with the
* data from the <code>Clob</code> object; therefore, the
* <code>Clob</code> object should have previously brought the
* SQL <code>CLOB</code> value's data over to the client from
* the database. Otherwise, the new <code>SerialClob</code> object
* object will contain no data.
* <p>
* Note: The <code>Clob</code> object supplied to this constructor must
* return non-null for both the <code>Clob.getCharacterStream()</code>
* and <code>Clob.getAsciiStream</code> methods. This <code>SerialClob</code>
* constructor cannot serialize a <code>Clob</code> object in this instance
* and will throw an <code>SQLException</code> object.
*
* @param clob the <code>Clob</code> object from which this
* <code>SerialClob</code> object is to be constructed; cannot be null
* @throws SerialException if an error occurs during serialization
* @throws SQLException if a SQL error occurs in capturing the CLOB;
* if the <code>Clob</code> object is a null; or if either of the
* <code>Clob.getCharacterStream()</code> and <code>Clob.getAsciiStream()</code>
* methods on the <code>Clob</code> returns a null
* @see java.sql.Clob
*/
public SerialClob(Clob clob) throws SerialException, SQLException {
if (clob == null) {
throw new SQLException("Cannot instantiate a SerialClob " +
"object with a null Clob object");
}
len = clob.length();
this.clob = clob;
buf = new char[(int)len];
int read = 0;
int offset = 0;
try (Reader charStream = clob.getCharacterStream()) {
if (charStream == null) {
throw new SQLException("Invalid Clob object. The call to getCharacterStream " +
"returned null which cannot be serialized.");
}
// Note: get an ASCII stream in order to null-check it,
// even though we don't do anything with it.
try (InputStream asciiStream = clob.getAsciiStream()) {
if (asciiStream == null) {
throw new SQLException("Invalid Clob object. The call to getAsciiStream " +
"returned null which cannot be serialized.");
}
}
try (Reader reader = new BufferedReader(charStream)) {
do {
read = reader.read(buf, offset, (int)(len - offset));
offset += read;
} while (read > 0);
}
} catch (java.io.IOException ex) {
throw new SerialException("SerialClob: " + ex.getMessage());
}
origLen = len;
}
/**
* Retrieves the number of characters in this <code>SerialClob</code>
* object's array of characters.
*
* @return a <code>long</code> indicating the length in characters of this
* <code>SerialClob</code> object's array of character
* @throws SerialException if an error occurs;
* if {@code free} had previously been called on this object
*/
public long length() throws SerialException {
isValid();
return len;
}
/**
* Returns this <code>SerialClob</code> object's data as a stream
* of Unicode characters. Unlike the related method, <code>getAsciiStream</code>,
* a stream is produced regardless of whether the <code>SerialClob</code> object
* was created with a <code>Clob</code> object or a <code>char</code> array.
*
* @return a <code>java.io.Reader</code> object containing this
* <code>SerialClob</code> object's data
* @throws SerialException if an error occurs;
* if {@code free} had previously been called on this object
*/
public java.io.Reader getCharacterStream() throws SerialException {
isValid();
return (java.io.Reader) new CharArrayReader(buf);
}
/**
* Retrieves the <code>CLOB</code> value designated by this <code>SerialClob</code>
* object as an ascii stream. This method forwards the <code>getAsciiStream</code>
* call to the underlying <code>Clob</code> object in the event that this
* <code>SerialClob</code> object is instantiated with a <code>Clob</code>
* object. If this <code>SerialClob</code> object is instantiated with
* a <code>char</code> array, a <code>SerialException</code> object is thrown.
*
* @return a <code>java.io.InputStream</code> object containing
* this <code>SerialClob</code> object's data
* @throws SerialException if this {@code SerialClob} object was not
* instantiated with a <code>Clob</code> object;
* if {@code free} had previously been called on this object
* @throws SQLException if there is an error accessing the
* <code>CLOB</code> value represented by the <code>Clob</code> object
* that was used to create this <code>SerialClob</code> object
*/
public java.io.InputStream getAsciiStream() throws SerialException, SQLException {
isValid();
if (this.clob != null) {
return this.clob.getAsciiStream();
} else {
throw new SerialException("Unsupported operation. SerialClob cannot " +
"return the CLOB value as an ascii stream, unless instantiated " +
"with a fully implemented Clob object.");
}
}
/**
* Returns a copy of the substring contained in this
* <code>SerialClob</code> object, starting at the given position
* and continuing for the specified number or characters.
*
* @param pos the position of the first character in the substring
* to be copied; the first character of the
* <code>SerialClob</code> object is at position
* <code>1</code>; must not be less than <code>1</code>,
* and the sum of the starting position and the length
* of the substring must be less than the length of this
* <code>SerialClob</code> object
* @param length the number of characters in the substring to be
* returned; must not be greater than the length of
* this <code>SerialClob</code> object, and the
* sum of the starting position and the length
* of the substring must be less than the length of this
* <code>SerialClob</code> object
* @return a <code>String</code> object containing a substring of
* this <code>SerialClob</code> object beginning at the
* given position and containing the specified number of
* consecutive characters
* @throws SerialException if either of the arguments is out of bounds;
* if {@code free} had previously been called on this object
*/
public String getSubString(long pos, int length) throws SerialException {
isValid();
if (pos < 1 || pos > this.length()) {
throw new SerialException("Invalid position in SerialClob object set");
}
if ((pos-1) + length > this.length()) {
throw new SerialException("Invalid position and substring length");
}
try {
return new String(buf, (int)pos - 1, length);
} catch (StringIndexOutOfBoundsException e) {
throw new SerialException("StringIndexOutOfBoundsException: " +
e.getMessage());
}
}
/**
* Returns the position in this <code>SerialClob</code> object
* where the given <code>String</code> object begins, starting
* the search at the specified position. This method returns
* <code>-1</code> if the pattern is not found.
*
* @param searchStr the <code>String</code> object for which to
* search
* @param start the position in this <code>SerialClob</code> object
* at which to start the search; the first position is
* <code>1</code>; must not be less than <code>1</code> nor
* greater than the length of this <code>SerialClob</code> object
* @return the position at which the given <code>String</code> object
* begins, starting the search at the specified position;
* <code>-1</code> if the given <code>String</code> object is
* not found or the starting position is out of bounds; position
* numbering for the return value starts at <code>1</code>
* @throws SerialException if the {@code free} method had been
* previously called on this object
* @throws SQLException if there is an error accessing the Clob value
* from the database.
*/
public long position(String searchStr, long start)
throws SerialException, SQLException {
isValid();
if (start < 1 || start > len) {
return -1;
}
char pattern[] = searchStr.toCharArray();
int pos = (int)start-1;
int i = 0;
long patlen = pattern.length;
while (pos < len) {
if (pattern[i] == buf[pos]) {
if (i + 1 == patlen) {
return (pos + 1) - (patlen - 1);
}
i++; pos++; // increment pos, and i
} else if (pattern[i] != buf[pos]) {
pos++; // increment pos only
}
}
return -1; // not found
}
/**
* Returns the position in this <code>SerialClob</code> object
* where the given <code>Clob</code> signature begins, starting
* the search at the specified position. This method returns
* <code>-1</code> if the pattern is not found.
*
* @param searchStr the <code>Clob</code> object for which to search
* @param start the position in this <code>SerialClob</code> object
* at which to begin the search; the first position is
* <code>1</code>; must not be less than <code>1</code> nor
* greater than the length of this <code>SerialClob</code> object
* @return the position at which the given <code>Clob</code>
* object begins in this <code>SerialClob</code> object,
* at or after the specified starting position
* @throws SerialException if an error occurs locating the Clob signature;
* if the {@code free} method had been previously called on this object
* @throws SQLException if there is an error accessing the Clob value
* from the database
*/
public long position(Clob searchStr, long start)
throws SerialException, SQLException {
isValid();
return position(searchStr.getSubString(1,(int)searchStr.length()), start);
}
/**
* Writes the given Java {@code String} to the {@code CLOB}
* value that this {@code SerialClob} object represents, at the position
* {@code pos}.
*
* @param pos the position at which to start writing to the {@code CLOB}
* value that this {@code SerialClob} object represents; the first
* position is {@code 1}; must not be less than {@code 1} nor
* greater than the length+1 of this {@code SerialClob} object
* @param str the string to be written to the {@code CLOB}
* value that this {@code SerialClob} object represents
* @return the number of characters written
* @throws SerialException if there is an error accessing the
* {@code CLOB} value; if an invalid position is set;
* if the {@code free} method had been previously called on this object
*/
public int setString(long pos, String str) throws SerialException {
return (setString(pos, str, 0, str.length()));
}
/**
* Writes {@code len} characters of {@code str}, starting
* at character {@code offset}, to the {@code CLOB} value
* that this {@code Clob} represents.
*
* @param pos the position at which to start writing to the {@code CLOB}
* value that this {@code SerialClob} object represents; the first
* position is {@code 1}; must not be less than {@code 1} nor
* greater than the length+1 of this {@code SerialClob} object
* @param str the string to be written to the {@code CLOB}
* value that this {@code Clob} object represents
* @param offset the offset into {@code str} to start reading
* the characters to be written
* @param length the number of characters to be written
* @return the number of characters written
* @throws SerialException if there is an error accessing the
* {@code CLOB} value; if an invalid position is set; if an
* invalid offset value is set; or the combined values of the
* {@code length} and {@code offset} is greater than the length of
* {@code str};
* if the {@code free} method had been previously called on this object
*/
public int setString(long pos, String str, int offset, int length)
throws SerialException {
isValid();
if (offset < 0 || offset > str.length()) {
throw new SerialException("Invalid offset in String object set");
}
if (length < 0) {
throw new SerialException("Invalid arguments: length cannot be "
+ "negative");
}
if (pos < 1 || pos > len + 1) {
throw new SerialException("Invalid position in Clob object set");
}
if (length > str.length() - offset) {
// need check to ensure length + offset !> str.length
throw new SerialException("Invalid OffSet. Cannot have combined offset " +
" and length that is greater than the length of str");
}
if (pos - 1 + length > Integer.MAX_VALUE) {
throw new SerialException("Invalid length. Cannot have combined pos " +
"and length that is greater than Integer.MAX_VALUE");
}
pos--; //values in the array are at position one less
if (pos + length > len) {
len = pos + length;
char[] newbuf = new char[(int)len];
System.arraycopy(buf, 0, newbuf, 0, (int)pos);
buf = newbuf;
}
String temp = str.substring(offset, offset + length);
char cPattern[] = temp.toCharArray();
System.arraycopy(cPattern, 0, buf, (int)pos, length);
return length;
}
/**
* Retrieves a stream to be used to write Ascii characters to the
* <code>CLOB</code> value that this <code>SerialClob</code> object represents,
* starting at position <code>pos</code>. This method forwards the
* <code>setAsciiStream()</code> call to the underlying <code>Clob</code> object in
* the event that this <code>SerialClob</code> object is instantiated with a
* <code>Clob</code> object. If this <code>SerialClob</code> object is instantiated
* with a <code>char</code> array, a <code>SerialException</code> object is thrown.
*
* @param pos the position at which to start writing to the
* <code>CLOB</code> object
* @return the stream to which ASCII encoded characters can be written
* @throws SerialException if SerialClob is not instantiated with a
* Clob object;
* if the {@code free} method had been previously called on this object
* @throws SQLException if there is an error accessing the
* <code>CLOB</code> value
* @see #getAsciiStream
*/
public java.io.OutputStream setAsciiStream(long pos)
throws SerialException, SQLException {
isValid();
if (this.clob != null) {
return this.clob.setAsciiStream(pos);
} else {
throw new SerialException("Unsupported operation. SerialClob cannot " +
"return a writable ascii stream\n unless instantiated with a Clob object " +
"that has a setAsciiStream() implementation");
}
}
/**
* Retrieves a stream to be used to write a stream of Unicode characters
* to the <code>CLOB</code> value that this <code>SerialClob</code> object
* represents, at position <code>pos</code>. This method forwards the
* <code>setCharacterStream()</code> call to the underlying <code>Clob</code>
* object in the event that this <code>SerialClob</code> object is instantiated with a
* <code>Clob</code> object. If this <code>SerialClob</code> object is instantiated with
* a <code>char</code> array, a <code>SerialException</code> is thrown.
*
* @param pos the position at which to start writing to the
* <code>CLOB</code> value
*
* @return a stream to which Unicode encoded characters can be written
* @throws SerialException if the SerialClob is not instantiated with
* a Clob object;
* if the {@code free} method had been previously called on this object
* @throws SQLException if there is an error accessing the
* <code>CLOB</code> value
* @see #getCharacterStream
*/
public java.io.Writer setCharacterStream(long pos)
throws SerialException, SQLException {
isValid();
if (this.clob != null) {
return this.clob.setCharacterStream(pos);
} else {
throw new SerialException("Unsupported operation. SerialClob cannot " +
"return a writable character stream\n unless instantiated with a Clob object " +
"that has a setCharacterStream implementation");
}
}
/**
* Truncates the <code>CLOB</code> value that this <code>SerialClob</code>
* object represents so that it has a length of <code>len</code>
* characters.
* <p>
* Truncating a <code>SerialClob</code> object to length 0 has the effect of
* clearing its contents.
*
* @param length the length, in bytes, to which the <code>CLOB</code>
* value should be truncated
* @throws SerialException if there is an error accessing the
* <code>CLOB</code> value;
* if the {@code free} method had been previously called on this object
*/
public void truncate(long length) throws SerialException {
isValid();
if (length > len) {
throw new SerialException
("Length more than what can be truncated");
} else {
len = length;
// re-size the buffer
if (len == 0) {
buf = new char[] {};
} else {
buf = (this.getSubString(1, (int)len)).toCharArray();
}
}
}
/**
* Returns a {@code Reader} object that contains a partial
* {@code SerialClob} value, starting
* with the character specified by pos, which is length characters in length.
*
* @param pos the offset to the first character of the partial value to
* be retrieved. The first character in the {@code SerialClob} is at position 1.
* @param length the length in characters of the partial value to be retrieved.
* @return {@code Reader} through which the partial {@code SerialClob}
* value can be read.
* @throws SQLException if pos is less than 1 or if pos is greater than the
* number of characters in the {@code SerialClob} or if pos + length
* is greater than the number of characters in the {@code SerialClob};
* @throws SerialException if the {@code free} method had been previously
* called on this object
* @since 1.6
*/
public Reader getCharacterStream(long pos, long length) throws SQLException {
isValid();
if (pos < 1 || pos > len) {
throw new SerialException("Invalid position in Clob object set");
}
if ((pos-1) + length > len) {
throw new SerialException("Invalid position and substring length");
}
if (length <= 0) {
throw new SerialException("Invalid length specified");
}
return new CharArrayReader(buf, (int)pos, (int)length);
}
/**
* This method frees the {@code SerialClob} object and releases the
* resources that it holds.
* The object is invalid once the {@code free} method is called.
* <p>
* If {@code free} is called multiple times, the subsequent
* calls to {@code free} are treated as a no-op.
* </P>
* @throws SQLException if an error occurs releasing
* the Clob's resources
* @since 1.6
*/
public void free() throws SQLException {
if (buf != null) {
buf = null;
if (clob != null) {
clob.free();
}
clob = null;
}
}
/**
* Compares this SerialClob to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* SerialClob} object that represents the same sequence of characters as this
* object.
*
* @param obj The object to compare this {@code SerialClob} against
*
* @return {@code true} if the given object represents a {@code SerialClob}
* equivalent to this SerialClob, {@code false} otherwise
*
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof SerialClob) {
SerialClob sc = (SerialClob)obj;
if (this.len == sc.len) {
return Arrays.equals(buf, sc.buf);
}
}
return false;
}
/**
* Returns a hash code for this {@code SerialClob}.
* @return a hash code value for this object.
*/
public int hashCode() {
return ((31 + Arrays.hashCode(buf)) * 31 + (int)len) * 31 + (int)origLen;
}
/**
* Returns a clone of this {@code SerialClob}. The copy will contain a
* reference to a clone of the internal character array, not a reference
* to the original internal character array of this {@code SerialClob} object.
* The underlying {@code Clob} object will be set to null.
*
* @return a clone of this SerialClob
*/
public Object clone() {
try {
SerialClob sc = (SerialClob) super.clone();
sc.buf = (buf != null) ? Arrays.copyOf(buf, (int)len) : null;
sc.clob = null;
return sc;
} catch (CloneNotSupportedException ex) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* readObject is called to restore the state of the SerialClob from
* a stream.
* @param s the {@code ObjectInputStream} to read from.
*
* @throws ClassNotFoundException if the class of a serialized object
* could not be found.
* @throws IOException if an I/O error occurs.
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
char[] tmp = (char[])fields.get("buf", null);
if (tmp == null)
throw new InvalidObjectException("buf is null and should not be!");
buf = tmp.clone();
len = fields.get("len", 0L);
if (buf.length != len)
throw new InvalidObjectException("buf is not the expected size");
origLen = fields.get("origLen", 0L);
clob = (Clob) fields.get("clob", null);
}
/**
* writeObject is called to save the state of the SerialClob
* to a stream.
* @param s the {@code ObjectOutputStream} to write to.
* @throws IOException if an I/O error occurs.
*/
private void writeObject(ObjectOutputStream s)
throws IOException {
ObjectOutputStream.PutField fields = s.putFields();
fields.put("buf", buf);
fields.put("len", len);
fields.put("origLen", origLen);
// Note: this check to see if it is an instance of Serializable
// is for backwards compatibility
fields.put("clob", clob instanceof Serializable ? clob : null);
s.writeFields();
}
/**
* Check to see if this object had previously had its {@code free} method
* called
*
* @throws SerialException
*/
private void isValid() throws SerialException {
if (buf == null) {
throw new SerialException("Error: You cannot call a method on a "
+ "SerialClob instance once free() has been called.");
}
}
/**
* The identifier that assists in the serialization of this {@code SerialClob}
* object.
*/
static final long serialVersionUID = -1662519690087375313L;
}

View file

@ -0,0 +1,173 @@
/*
* Copyright (c) 2003, 2022, 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.serial;
import java.sql.*;
import java.io.*;
import java.net.URL;
/**
* A serialized mapping in the Java programming language of an SQL
* <code>DATALINK</code> value. A <code>DATALINK</code> value
* references a file outside of the underlying data source that the
* data source manages.
* <P>
* <code>RowSet</code> implementations can use the method <code>RowSet.getURL</code>
* to retrieve a <code>java.net.URL</code> object, which can be used
* to manipulate the external data.
* <pre>
* java.net.URL url = rowset.getURL(1);
* </pre>
*
* <h2> Thread safety </h2>
*
* A SerialDatalink is not safe for use by multiple concurrent threads. If a
* SerialDatalink is to be used by more than one thread then access to the
* SerialDatalink should be controlled by appropriate synchronization.
*
* @since 1.5
*/
public class SerialDatalink implements Serializable, Cloneable {
/**
* The extracted URL field retrieved from the DATALINK field.
* @serial
*/
private URL url;
/**
* The SQL type of the elements in this <code>SerialDatalink</code>
* object. The type is expressed as one of the constants from the
* class <code>java.sql.Types</code>.
* @serial
*/
private int baseType;
/**
* The type name used by the DBMS for the elements in the SQL
* <code>DATALINK</code> value that this SerialDatalink object
* represents.
* @serial
*/
private String baseTypeName;
/**
* Constructs a new <code>SerialDatalink</code> object from the given
* <code>java.net.URL</code> object.
*
* @param url the {@code URL} to create the {@code SerialDataLink} from
* @throws SerialException if url parameter is a null
*/
public SerialDatalink(URL url) throws SerialException {
if (url == null) {
throw new SerialException("Cannot serialize empty URL instance");
}
this.url = url;
}
/**
* Returns a new URL that is a copy of this <code>SerialDatalink</code>
* object.
*
* @return a copy of this <code>SerialDatalink</code> object as a
* <code>URL</code> object in the Java programming language.
* @throws SerialException if the <code>URL</code> object cannot be de-serialized
*/
@SuppressWarnings("deprecation")
public URL getDatalink() throws SerialException {
URL aURL = null;
try {
aURL = new URL((this.url).toString());
} catch (java.net.MalformedURLException e) {
throw new SerialException("MalformedURLException: " + e.getMessage());
}
return aURL;
}
/**
* Compares this {@code SerialDatalink} to the specified object.
* The result is {@code true} if and only if the argument is not
* {@code null} and is a {@code SerialDatalink} object whose URL is
* identical to this object's URL
*
* @param obj The object to compare this {@code SerialDatalink} against
*
* @return {@code true} if the given object represents a {@code SerialDatalink}
* equivalent to this SerialDatalink, {@code false} otherwise
*
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof SerialDatalink) {
SerialDatalink sdl = (SerialDatalink) obj;
return url.equals(sdl.url);
}
return false;
}
/**
* Returns a hash code for this {@code SerialDatalink}. The hash code for a
* {@code SerialDatalink} object is taken as the hash code of
* the {@code URL} it stores
*
* @return a hash code value for this object.
*/
public int hashCode() {
return 31 + url.hashCode();
}
/**
* Returns a clone of this {@code SerialDatalink}.
*
* @return a clone of this SerialDatalink
*/
public Object clone() {
try {
SerialDatalink sdl = (SerialDatalink) super.clone();
return sdl;
} catch (CloneNotSupportedException ex) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* readObject and writeObject are called to restore the state
* of the {@code SerialDatalink}
* from a stream. Note: we leverage the default Serialized form
*/
/**
* The identifier that assists in the serialization of this
* {@code SerialDatalink} object.
*/
static final long serialVersionUID = 2826907821828733626L;
}

View file

@ -0,0 +1,57 @@
/*
* 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.serial;
import java.sql.SQLException;
/**
* Indicates and an error with the serialization or de-serialization of
* SQL types such as <code>BLOB, CLOB, STRUCT or ARRAY</code> in
* addition to SQL types such as <code>DATALINK and JAVAOBJECT</code>
*
* @since 1.5
*/
public class SerialException extends java.sql.SQLException {
/**
* Creates a new <code>SerialException</code> without a
* message.
*/
public SerialException() {
}
/**
* Creates a new <code>SerialException</code> with the
* specified message.
*
* @param msg the detail message
*/
public SerialException(String msg) {
super(msg);
}
static final long serialVersionUID = -489794565168592690L;
}

View file

@ -0,0 +1,266 @@
/*
* Copyright (c) 2003, 2025, 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.serial;
import java.io.*;
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.Vector;
import javax.sql.rowset.RowSetWarning;
/**
* A serializable mapping in the Java programming language of an SQL
* <code>JAVA_OBJECT</code> value. Assuming the Java object
* implements the <code>Serializable</code> interface, this class simply wraps the
* serialization process.
* <P>
* If however, the serialization is not possible because
* the Java object is not immediately serializable, this class will
* attempt to serialize all non-static members to permit the object
* state to be serialized.
* Static or transient fields cannot be serialized; an attempt to serialize
* them will result in a <code>SerialException</code> object being thrown.
*
* <h2> Thread safety </h2>
*
* A SerialJavaObject is not safe for use by multiple concurrent threads. If a
* SerialJavaObject is to be used by more than one thread then access to the
* SerialJavaObject should be controlled by appropriate synchronization.
*
* @author Jonathan Bruce
* @since 1.5
*/
public class SerialJavaObject implements Serializable, Cloneable {
/**
* @serial Placeholder for object to be serialized.
*/
@SuppressWarnings("serial") // Not statically typed as Serializable
private Object obj;
/**
* Placeholder for all fields in the <code>JavaObject</code> being serialized.
*/
private transient Field[] fields;
/**
* Constructor for <code>SerialJavaObject</code> helper class.
*
* @param obj the Java <code>Object</code> to be serialized
* @throws SerialException if the object is found not to be serializable
*/
public SerialJavaObject(Object obj) throws SerialException {
// if any static fields are found, an exception
// should be thrown
// get Class. Object instance should always be available
Class<?> c = obj.getClass();
// determine if object implements Serializable i/f
if (!(obj instanceof java.io.Serializable)) {
setWarning(new RowSetWarning("Warning, the object passed to the constructor does not implement Serializable"));
}
// can only determine public fields (obviously). If
// any of these are static, this should invalidate
// the action of attempting to persist these fields
// in a serialized form
fields = c.getFields();
if (hasStaticFields(fields)) {
throw new SerialException("Located static fields in " +
"object instance. Cannot serialize");
}
this.obj = obj;
}
/**
* Returns an <code>Object</code> that is a copy of this <code>SerialJavaObject</code>
* object.
*
* @return a copy of this <code>SerialJavaObject</code> object as an
* <code>Object</code> in the Java programming language
* @throws SerialException if the instance is corrupt
*/
public Object getObject() throws SerialException {
return this.obj;
}
/**
* Returns an array of <code>Field</code> objects that contains each
* field of the object that this helper class is serializing.
*
* @return an array of <code>Field</code> objects
* @throws SerialException if an error is encountered accessing
* the serialized object
* @see Class#getFields
*/
public Field[] getFields() throws SerialException {
if (fields != null) {
Class<?> c = this.obj.getClass();
return c.getFields();
} else {
throw new SerialException("SerialJavaObject does not contain" +
" a serialized object instance");
}
}
/**
* The identifier that assists in the serialization of this
* <code>SerialJavaObject</code> object.
*/
static final long serialVersionUID = -1465795139032831023L;
/**
* @serial A container for the warnings issued on this <code>SerialJavaObject</code>
* object. When there are multiple warnings, each warning is chained to the
* previous warning.
*/
Vector<RowSetWarning> chain;
/**
* Compares this SerialJavaObject to the specified object.
* The result is {@code true} if and only if the argument
* is not {@code null} and is a {@code SerialJavaObject}
* object that is identical to this object
*
* @param o The object to compare this {@code SerialJavaObject} against
*
* @return {@code true} if the given object represents a {@code SerialJavaObject}
* equivalent to this SerialJavaObject, {@code false} otherwise
*
*/
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof SerialJavaObject) {
SerialJavaObject sjo = (SerialJavaObject) o;
return obj.equals(sjo.obj);
}
return false;
}
/**
* Returns a hash code for this SerialJavaObject. The hash code for a
* {@code SerialJavaObject} object is taken as the hash code of
* the {@code Object} it stores
*
* @return a hash code value for this object.
*/
public int hashCode() {
return 31 + obj.hashCode();
}
/**
* Returns a clone of this {@code SerialJavaObject}.
*
* @return a clone of this SerialJavaObject
*/
public Object clone() {
try {
SerialJavaObject sjo = (SerialJavaObject) super.clone();
sjo.fields = Arrays.copyOf(fields, fields.length);
if (chain != null)
sjo.chain = new Vector<>(chain);
return sjo;
} catch (CloneNotSupportedException ex) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* Registers the given warning.
*/
private void setWarning(RowSetWarning e) {
if (chain == null) {
chain = new Vector<>();
}
chain.add(e);
}
/**
* readObject is called to restore the state of the {@code SerialJavaObject}
* from a stream.
* @param s the {@code ObjectInputStream} to read from.
*
* @throws ClassNotFoundException if the class of a serialized object
* could not be found.
* @throws IOException if an I/O error occurs.
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields1 = s.readFields();
@SuppressWarnings("unchecked")
Vector<RowSetWarning> tmp = (Vector<RowSetWarning>)fields1.get("chain", null);
if (tmp != null)
chain = new Vector<>(tmp);
obj = fields1.get("obj", null);
if (obj != null) {
fields = obj.getClass().getFields();
if(hasStaticFields(fields))
throw new IOException("Located static fields in " +
"object instance. Cannot serialize");
} else {
throw new IOException("Object cannot be null!");
}
}
/**
* writeObject is called to save the state of the {@code SerialJavaObject}
* to a stream.
* @param s the {@code ObjectOutputStream} to write to.
* @throws IOException if an I/O error occurs.
*/
private void writeObject(ObjectOutputStream s)
throws IOException {
ObjectOutputStream.PutField fields = s.putFields();
fields.put("obj", obj);
fields.put("chain", chain);
s.writeFields();
}
/*
* Check to see if there are any Static Fields in this object
*/
private static boolean hasStaticFields(Field[] fields) {
for (Field field : fields) {
if ( field.getModifiers() == Modifier.STATIC) {
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,267 @@
/*
* Copyright (c) 2003, 2025, 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.serial;
import java.sql.*;
import java.io.*;
import java.util.*;
/**
* A serialized mapping of a <code>Ref</code> object, which is the mapping in the
* Java programming language of an SQL <code>REF</code> value.
* <p>
* The <code>SerialRef</code> class provides a constructor for
* creating a <code>SerialRef</code> instance from a <code>Ref</code>
* object and provides methods for getting and setting the <code>Ref</code> object.
*
* <h2> Thread safety </h2>
*
* A SerialRef is not safe for use by multiple concurrent threads. If a
* SerialRef is to be used by more than one thread then access to the SerialRef
* should be controlled by appropriate synchronization.
*
* @since 1.5
*/
public class SerialRef implements Ref, Serializable, Cloneable {
/**
* String containing the base type name.
* @serial
*/
private String baseTypeName;
/**
* @serial This will store the type <code>Ref</code> as an <code>Object</code>.
*/
@SuppressWarnings("serial") // Not statically typed as Serializable
private Object object;
/**
* @serial Private copy of the Ref reference.
*/
@SuppressWarnings("serial") // Not statically typed as Serializable; checked in writeObject
private Ref reference;
/**
* Constructs a <code>SerialRef</code> object from the given <code>Ref</code>
* object.
*
* @param ref a Ref object; cannot be <code>null</code>
* @throws SQLException if a database access occurs; if <code>ref</code>
* is <code>null</code>; or if the <code>Ref</code> object returns a
* <code>null</code> value base type name.
* @throws SerialException if an error occurs serializing the <code>Ref</code>
* object
*/
public SerialRef(Ref ref) throws SerialException, SQLException {
if (ref == null) {
throw new SQLException("Cannot instantiate a SerialRef object " +
"with a null Ref object");
}
reference = ref;
object = ref;
if (ref.getBaseTypeName() == null) {
throw new SQLException("Cannot instantiate a SerialRef object " +
"that returns a null base type name");
} else {
baseTypeName = ref.getBaseTypeName();
}
}
/**
* Returns a string describing the base type name of the <code>Ref</code>.
*
* @return a string of the base type name of the Ref
* @throws SerialException in no Ref object has been set
*/
public String getBaseTypeName() throws SerialException {
return baseTypeName;
}
/**
* Returns an <code>Object</code> representing the SQL structured type
* to which this <code>SerialRef</code> object refers. The attributes
* of the structured type are mapped according to the given type map.
*
* @param map a <code>java.util.Map</code> object containing zero or
* more entries, with each entry consisting of 1) a <code>String</code>
* giving the fully qualified name of a UDT and 2) the
* <code>Class</code> object for the <code>SQLData</code> implementation
* that defines how the UDT is to be mapped
* @return an object instance resolved from the Ref reference and mapped
* according to the supplied type map
* @throws SerialException if an error is encountered in the reference
* resolution
*/
public Object getObject(java.util.Map<String,Class<?>> map)
throws SerialException
{
map = new Hashtable<String, Class<?>>(map);
if (object != null) {
return map.get(object);
} else {
throw new SerialException("The object is not set");
}
}
/**
* Returns an <code>Object</code> representing the SQL structured type
* to which this <code>SerialRef</code> object refers.
*
* @return an object instance resolved from the Ref reference
* @throws SerialException if an error is encountered in the reference
* resolution
*/
public Object getObject() throws SerialException {
if (reference != null) {
try {
return reference.getObject();
} catch (SQLException e) {
throw new SerialException("SQLException: " + e.getMessage());
}
}
if (object != null) {
return object;
}
throw new SerialException("The object is not set");
}
/**
* Sets the SQL structured type that this <code>SerialRef</code> object
* references to the given <code>Object</code> object.
*
* @param obj an <code>Object</code> representing the SQL structured type
* to be referenced
* @throws SerialException if an error is encountered generating the
* the structured type referenced by this <code>SerialRef</code> object
*/
public void setObject(Object obj) throws SerialException {
try {
reference.setObject(obj);
} catch (SQLException e) {
throw new SerialException("SQLException: " + e.getMessage());
}
object = obj;
}
/**
* Compares this SerialRef to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* SerialRef} object that represents the same object as this
* object.
*
* @param obj The object to compare this {@code SerialRef} against
*
* @return {@code true} if the given object represents a {@code SerialRef}
* equivalent to this SerialRef, {@code false} otherwise
*
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if(obj instanceof SerialRef) {
SerialRef ref = (SerialRef)obj;
return baseTypeName.equals(ref.baseTypeName) &&
object.equals(ref.object);
}
return false;
}
/**
* Returns a hash code for this {@code SerialRef}.
* @return a hash code value for this object.
*/
public int hashCode() {
return (31 + object.hashCode()) * 31 + baseTypeName.hashCode();
}
/**
* Returns a clone of this {@code SerialRef}.
* The underlying {@code Ref} object will be set to null.
*
* @return a clone of this SerialRef
*/
public Object clone() {
try {
SerialRef ref = (SerialRef) super.clone();
ref.reference = null;
return ref;
} catch (CloneNotSupportedException ex) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* readObject is called to restore the state of the SerialRef from
* a stream.
* @param s the {@code ObjectInputStream} to read from.
*
* @throws ClassNotFoundException if the class of a serialized object
* could not be found.
* @throws IOException if an I/O error occurs.
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
object = fields.get("object", null);
baseTypeName = (String) fields.get("baseTypeName", null);
reference = (Ref) fields.get("reference", null);
}
/**
* writeObject is called to save the state of the SerialRef
* to a stream.
* @param s the {@code ObjectOutputStream} to write to.
* @throws IOException if an I/O error occurs.
*/
private void writeObject(ObjectOutputStream s)
throws IOException {
ObjectOutputStream.PutField fields = s.putFields();
fields.put("baseTypeName", baseTypeName);
fields.put("object", object);
// Note: this check to see if it is an instance of Serializable
// is for backwards compatibility
fields.put("reference", reference instanceof Serializable ? reference : null);
s.writeFields();
}
/**
* The identifier that assists in the serialization of this <code>SerialRef</code>
* object.
*/
static final long serialVersionUID = -4727123500609662274L;
}

View file

@ -0,0 +1,356 @@
/*
* Copyright (c) 2003, 2020, 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.serial;
import java.sql.*;
import javax.sql.*;
import java.io.*;
import java.math.*;
import java.util.Arrays;
import java.util.Map;
import java.util.Vector;
import javax.sql.rowset.*;
/**
* A serialized mapping in the Java programming language of an SQL
* structured type. Each attribute that is not already serialized
* is mapped to a serialized form, and if an attribute is itself
* a structured type, each of its attributes that is not already
* serialized is mapped to a serialized form.
* <P>
* In addition, the structured type is custom mapped to a class in the
* Java programming language if there is such a mapping, as are
* its attributes, if appropriate.
* <P>
* The <code>SerialStruct</code> class provides a constructor for creating
* an instance from a <code>Struct</code> object, a method for retrieving
* the SQL type name of the SQL structured type in the database, and methods
* for retrieving its attribute values.
*
* <h2> Thread safety </h2>
*
* A SerialStruct is not safe for use by multiple concurrent threads. If a
* SerialStruct is to be used by more than one thread then access to the
* SerialStruct should be controlled by appropriate synchronization.
*
* @since 1.5
*/
public class SerialStruct implements Struct, Serializable, Cloneable {
/**
* The SQL type name for the structured type that this
* <code>SerialStruct</code> object represents. This is the name
* used in the SQL definition of the SQL structured type.
*
* @serial
*/
private String SQLTypeName;
/**
* An array of <code>Object</code> instances in which each
* element is an attribute of the SQL structured type that this
* <code>SerialStruct</code> object represents. The attributes are
* ordered according to their order in the definition of the
* SQL structured type.
*
* @serial
*/
@SuppressWarnings("serial") // Not statically typed as Serializable
private Object attribs[];
/**
* Constructs a <code>SerialStruct</code> object from the given
* <code>Struct</code> object, using the given <code>java.util.Map</code>
* object for custom mapping the SQL structured type or any of its
* attributes that are SQL structured types.
*
* @param in an instance of {@code Struct}
* @param map a <code>java.util.Map</code> object in which
* each entry consists of 1) a <code>String</code> object
* giving the fully qualified name of a UDT and 2) the
* <code>Class</code> object for the <code>SQLData</code> implementation
* that defines how the UDT is to be mapped
* @throws SerialException if an error occurs
* @see java.sql.Struct
*/
public SerialStruct(Struct in, Map<String,Class<?>> map)
throws SerialException
{
try {
// get the type name
SQLTypeName = in.getSQLTypeName();
System.out.println("SQLTypeName: " + SQLTypeName);
// get the attributes of the struct
attribs = in.getAttributes(map);
/*
* the array may contain further Structs
* and/or classes that have been mapped,
* other types that we have to serialize
*/
mapToSerial(map);
} catch (SQLException e) {
throw new SerialException(e.getMessage());
}
}
/**
* Constructs a <code>SerialStruct</code> object from the
* given <code>SQLData</code> object, using the given type
* map to custom map it to a class in the Java programming
* language. The type map gives the SQL type and the class
* to which it is mapped. The <code>SQLData</code> object
* defines the class to which the SQL type will be mapped.
*
* @param in an instance of the <code>SQLData</code> class
* that defines the mapping of the SQL structured
* type to one or more objects in the Java programming language
* @param map a <code>java.util.Map</code> object in which
* each entry consists of 1) a <code>String</code> object
* giving the fully qualified name of a UDT and 2) the
* <code>Class</code> object for the <code>SQLData</code> implementation
* that defines how the UDT is to be mapped
* @throws SerialException if an error occurs
*/
public SerialStruct(SQLData in, Map<String,Class<?>> map)
throws SerialException
{
try {
//set the type name
SQLTypeName = in.getSQLTypeName();
Vector<Object> tmp = new Vector<>();
in.writeSQL(new SQLOutputImpl(tmp, map));
attribs = tmp.toArray();
} catch (SQLException e) {
throw new SerialException(e.getMessage());
}
}
/**
* Retrieves the SQL type name for this <code>SerialStruct</code>
* object. This is the name used in the SQL definition of the
* structured type
*
* @return a <code>String</code> object representing the SQL
* type name for the SQL structured type that this
* <code>SerialStruct</code> object represents
* @throws SerialException if an error occurs
*/
public String getSQLTypeName() throws SerialException {
return SQLTypeName;
}
/**
* Retrieves an array of <code>Object</code> values containing the
* attributes of the SQL structured type that this
* <code>SerialStruct</code> object represents.
*
* @return an array of <code>Object</code> values, with each
* element being an attribute of the SQL structured type
* that this <code>SerialStruct</code> object represents
* @throws SerialException if an error occurs
*/
public Object[] getAttributes() throws SerialException {
Object[] val = this.attribs;
return (val == null) ? null : Arrays.copyOf(val, val.length);
}
/**
* Retrieves the attributes for the SQL structured type that
* this <code>SerialStruct</code> represents as an array of
* <code>Object</code> values, using the given type map for
* custom mapping if appropriate.
*
* @param map a <code>java.util.Map</code> object in which
* each entry consists of 1) a <code>String</code> object
* giving the fully qualified name of a UDT and 2) the
* <code>Class</code> object for the <code>SQLData</code> implementation
* that defines how the UDT is to be mapped
* @return an array of <code>Object</code> values, with each
* element being an attribute of the SQL structured
* type that this <code>SerialStruct</code> object
* represents
* @throws SerialException if an error occurs
*/
public Object[] getAttributes(Map<String,Class<?>> map)
throws SerialException
{
Object[] val = this.attribs;
return (val == null) ? null : Arrays.copyOf(val, val.length);
}
/**
* Maps attributes of an SQL structured type that are not
* serialized to a serialized form, using the given type map
* for custom mapping when appropriate. The following types
* in the Java programming language are mapped to their
* serialized forms: <code>Struct</code>, <code>SQLData</code>,
* <code>Ref</code>, <code>Blob</code>, <code>Clob</code>, and
* <code>Array</code>.
* <P>
* This method is called internally and is not used by an
* application programmer.
*
* @param map a <code>java.util.Map</code> object in which
* each entry consists of 1) a <code>String</code> object
* giving the fully qualified name of a UDT and 2) the
* <code>Class</code> object for the <code>SQLData</code> implementation
* that defines how the UDT is to be mapped
* @throws SerialException if an error occurs
*/
private void mapToSerial(Map<String,Class<?>> map) throws SerialException {
try {
for (int i = 0; i < attribs.length; i++) {
if (attribs[i] instanceof Struct) {
attribs[i] = new SerialStruct((Struct)attribs[i], map);
} else if (attribs[i] instanceof SQLData) {
attribs[i] = new SerialStruct((SQLData)attribs[i], map);
} else if (attribs[i] instanceof Blob) {
attribs[i] = new SerialBlob((Blob)attribs[i]);
} else if (attribs[i] instanceof Clob) {
attribs[i] = new SerialClob((Clob)attribs[i]);
} else if (attribs[i] instanceof Ref) {
attribs[i] = new SerialRef((Ref)attribs[i]);
} else if (attribs[i] instanceof java.sql.Array) {
attribs[i] = new SerialArray((java.sql.Array)attribs[i], map);
}
}
} catch (SQLException e) {
throw new SerialException(e.getMessage());
}
return;
}
/**
* Compares this SerialStruct to the specified object. The result is
* {@code true} if and only if the argument is not {@code null} and is a
* {@code SerialStruct} object whose attributes are identical to this
* object's attributes
*
* @param obj The object to compare this {@code SerialStruct} against
*
* @return {@code true} if the given object represents a {@code SerialStruct}
* equivalent to this SerialStruct, {@code false} otherwise
*
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof SerialStruct) {
SerialStruct ss = (SerialStruct)obj;
return SQLTypeName.equals(ss.SQLTypeName) &&
Arrays.equals(attribs, ss.attribs);
}
return false;
}
/**
* Returns a hash code for this {@code SerialStruct}. The hash code for a
* {@code SerialStruct} object is computed using the hash codes
* of the attributes of the {@code SerialStruct} object and its
* {@code SQLTypeName}
*
* @return a hash code value for this object.
*/
public int hashCode() {
return ((31 + Arrays.hashCode(attribs)) * 31) * 31
+ SQLTypeName.hashCode();
}
/**
* Returns a clone of this {@code SerialStruct}. The copy will contain a
* reference to a clone of the underlying attribs array, not a reference
* to the original underlying attribs array of this {@code SerialStruct} object.
*
* @return a clone of this SerialStruct
*/
public Object clone() {
try {
SerialStruct ss = (SerialStruct) super.clone();
ss.attribs = Arrays.copyOf(attribs, attribs.length);
return ss;
} catch (CloneNotSupportedException ex) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* readObject is called to restore the state of the {@code SerialStruct} from
* a stream.
* @param s the {@code ObjectInputStream} to read from.
*
* @throws ClassNotFoundException if the class of a serialized object
* could not be found.
* @throws IOException if an I/O error occurs.
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
Object[] tmp = (Object[])fields.get("attribs", null);
attribs = tmp == null ? null : tmp.clone();
SQLTypeName = (String)fields.get("SQLTypeName", null);
}
/**
* writeObject is called to save the state of the {@code SerialStruct}
* to a stream.
* @param s the {@code ObjectOutputStream} to write to.
* @throws IOException if an I/O error occurs.
*/
private void writeObject(ObjectOutputStream s)
throws IOException {
ObjectOutputStream.PutField fields = s.putFields();
fields.put("attribs", attribs);
fields.put("SQLTypeName", SQLTypeName);
s.writeFields();
}
/**
* The identifier that assists in the serialization of this
* <code>SerialStruct</code> object.
*/
static final long serialVersionUID = -8322445504027483372L;
}

View file

@ -0,0 +1,229 @@
/*
* Copyright (c) 2003, 2023, 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.
*/
/**
* Provides utility classes to allow serializable mappings between SQL types
* and data types in the Java programming language.
* <p> Standard JDBC {@code RowSet} implementations may use these utility
* classes to
* assist in the serialization of disconnected {@code RowSet} objects.
* This is useful
* when transmitting a disconnected {@code RowSet} object over the wire to
* a different VM or across layers within an application.<br>
* </p>
*
* <h2>1.0 SerialArray</h2>
* A serializable mapping in the Java programming language of an SQL ARRAY
* value. <br>
* <br>
* The {@code SerialArray} class provides a constructor for creating a {@code SerialArray}
* instance from an Array object, methods for getting the base type and
* the SQL name for the base type, and methods for copying all or part of a
* {@code SerialArray} object. <br>
*
* <h2>2.0 SerialBlob</h2>
* A serializable mapping in the Java programming language of an SQL BLOB
* value. <br>
* <br>
* The {@code SerialBlob} class provides a constructor for creating an instance
* from a Blob object. Note that the Blob object should have brought the SQL
* BLOB value's data over to the client before a {@code SerialBlob} object
* is constructed from it. The data of an SQL BLOB value can be materialized
* on the client as an array of bytes (using the method {@code Blob.getBytes})
* or as a stream of uninterpreted bytes (using the method {@code Blob.getBinaryStream}).
* <br>
* <br>
* {@code SerialBlob} methods make it possible to make a copy of a {@code SerialBlob}
* object as an array of bytes or as a stream. They also make it possible
* to locate a given pattern of bytes or a {@code Blob} object within a {@code SerialBlob}
* object. <br>
*
* <h2>3.0 SerialClob</h2>
* A serializable mapping in the Java programming language of an SQL CLOB
* value. <br>
* <br>
* The {@code SerialClob} class provides a constructor for creating an instance
* from a {@code Clob} object. Note that the {@code Clob} object should have
* brought the SQL CLOB value's data over to the client before a {@code SerialClob}
* object is constructed from it. The data of an SQL CLOB value can be
* materialized on the client as a stream of Unicode characters. <br>
* <br>
* {@code SerialClob} methods make it possible to get a substring from a
* {@code SerialClob} object or to locate the start of a pattern of characters.
* <br>
*
* <h2>5.0 SerialDatalink</h2>
* A serializable mapping in the Java programming language of an SQL DATALINK
* value. A DATALINK value references a file outside of the underlying data source
* that the originating data source manages. <br>
* <br>
* {@code RowSet} implementations can use the method {@code RowSet.getURL()} to retrieve
* a {@code java.net.URL} object, which can be used to manipulate the external data.
* <br>
* <PRE>
* java.net.URL url = rowset.getURL(1);
* </PRE>
*
* <h2>6.0 SerialJavaObject</h2>
* A serializable mapping in the Java programming language of an SQL JAVA_OBJECT
* value. Assuming the Java object instance implements the Serializable interface,
* this simply wraps the serialization process. <br>
* <br>
* If however, the serialization is not possible in the case where the Java
* object is not immediately serializable, this class will attempt to serialize
* all non static members to permit the object instance state to be serialized.
* Static or transient fields cannot be serialized and attempting to do so
* will result in a {@code SerialException} being thrown. <br>
*
* <h2>7.0 SerialRef</h2>
* A serializable mapping between the SQL REF type and the Java programming
* language. <br>
* <br>
* The {@code SerialRef} class provides a constructor for creating a {@code SerialRef}
* instance from a {@code Ref} type and provides methods for getting
* and setting the {@code Ref} object type. <br>
*
* <h2>8.0 SerialStruct</h2>
* A serializable mapping in the Java programming language of an SQL structured
* type. Each attribute that is not already serializable is mapped to a serializable
* form, and if an attribute is itself a structured type, each of its attributes
* that is not already serializable is mapped to a serializable form. <br>
* <br>
* In addition, if a {@code Map} object is passed to one of the constructors or
* to the method {@code getAttributes}, the structured type is custom mapped
* according to the mapping specified in the {@code Map} object.
* <br>
* The {@code SerialStruct} class provides a constructor for creating an
* instance from a {@code Struct} object, a method for retrieving the SQL
* type name of the SQL structured type in the database, and methods for retrieving
* its attribute values. <br>
*
* <h2>9.0 SQLInputImpl</h2>
* An input stream used for custom mapping user-defined types (UDTs). An
* {@code SQLInputImpl} object is an input stream that contains a stream of
* values that are
* the attributes of a UDT. This class is used by the driver behind the scenes
* when the method {@code getObject} is called on an SQL structured or distinct
* type that has a custom mapping; a programmer never invokes {@code SQLInputImpl}
* methods directly. <br>
* <br>
* The {@code SQLInputImpl} class provides a set of reader methods
* analogous to the {@code ResultSet} getter methods. These methods make it
* possible to read the values in an {@code SQLInputImpl} object. The method
* {@code wasNull} is used to determine whether the last value read was SQL NULL.
* <br>
* <br>
* When a constructor or getter method that takes a {@code Map} object is called,
* the JDBC driver calls the method
* {@code SQLData.getSQLType} to determine the SQL type of the UDT being custom
* mapped. The driver creates an instance of {@code SQLInputImpl}, populating it with
* the attributes of the UDT. The driver then passes the input stream to the
* method {@code SQLData.readSQL}, which in turn calls the {@code SQLInputImpl}
* methods to read the attributes from the input stream. <br>
*
* <h2>10.0 SQLOutputImpl</h2>
* The output stream for writing the attributes of a custom mapped user-defined
* type (UDT) back to the database. The driver uses this interface internally,
* and its methods are never directly invoked by an application programmer.
* <br>
* <br>
* When an application calls the method {@code PreparedStatement.setObject}, the
* driver checks to see whether the value to be written is a UDT with a custom
* mapping. If it is, there will be an entry in a type map containing the Class
* object for the class that implements {@code SQLData} for this UDT. If the
* value to be written is an instance of {@code SQLData}, the driver will
* create an instance of {@code SQLOutputImpl} and pass it to the method
* {@code SQLData.writeSQL}.
* The method {@code writeSQL} in turn calls the appropriate {@code SQLOutputImpl}
* writer methods to write data from the {@code SQLData} object to the
* {@code SQLOutputImpl}
* output stream as the representation of an SQL user-defined type.
*
* <h2>Custom Mapping</h2>
* The JDBC API provides mechanisms for mapping an SQL structured type or DISTINCT
* type to the Java programming language. Typically, a structured type is mapped
* to a class, and its attributes are mapped to fields in the class.
* (A DISTINCT type can thought of as having one attribute.) However, there are
* many other possibilities, and there may be any number of different mappings.
* <P>
* A programmer defines the mapping by implementing the interface {@code SQLData}.
* For example, if an SQL structured type named AUTHORS has the attributes NAME,
* TITLE, and PUBLISHER, it could be mapped to a Java class named Authors. The
* Authors class could have the fields name, title, and publisher, to which the
* attributes of AUTHORS are mapped. In such a case, the implementation of
* {@code SQLData} could look like the following:
* <PRE>
* public class Authors implements SQLData {
* public String name;
* public String title;
* public String publisher;
*
* private String sql_type;
* public String getSQLTypeName() {
* return sql_type;
* }
*
* public void readSQL(SQLInput stream, String type)
* throws SQLException {
* sql_type = type;
* name = stream.readString();
* title = stream.readString();
* publisher = stream.readString();
* }
*
* public void writeSQL(SQLOutput stream) throws SQLException {
* stream.writeString(name);
* stream.writeString(title);
* stream.writeString(publisher);
* }
* }
* </PRE>
*
* A {@code java.util.Map} object is used to associate the SQL structured
* type with its mapping to the class {@code Authors}. The following code fragment shows
* how a {@code Map} object might be created and given an entry associating
* {@code AUTHORS} and {@code Authors}.
* <PRE>
* java.util.Map map = new java.util.HashMap();
* map.put("SCHEMA_NAME.AUTHORS", Class.forName("Authors");
* </PRE>
*
* The {@code Map} object <i>map</i> now contains an entry with the
* fully qualified name of the SQL structured type and the {@code Class}
* object for the class {@code Authors}. It can be passed to a method
* to tell the driver how to map {@code AUTHORS} to {@code Authors}.
* <P>
* For a disconnected {@code RowSet} object, custom mapping can be done
* only when a {@code Map} object is passed to the method or constructor
* that will be doing the custom mapping. The situation is different for
* connected {@code RowSet} objects because they maintain a connection
* with the data source. A method that does custom mapping and is called by
* a disconnected {@code RowSet} object may use the {@code Map}
* object that is associated with the {@code Connection} object being
* used. So, in other words, if no map is specified, the connection's type
* map can be used by default.
* @since 1.5
*/
package javax.sql.rowset.serial;

View file

@ -0,0 +1,865 @@
/*
* Copyright (c) 2003, 2025, 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 javax.naming.*;
/**
* 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.
*
* <h2>1.0 Overview</h2>
* 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>
* <h2>2.0 Registering <code>SyncProvider</code> Implementations</h2>
* <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
* @since 1.5
*/
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";
/**
* 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 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 = System.getProperty("rowset.properties");
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";
try {
InputStream in = SyncFactory.class.getModule().getResourceAsStream(ROWSET_PROPERTIES);
if (in == null) {
throw new SyncFactoryException("Resource " + ROWSET_PROPERTIES + " not found");
}
try (in) {
properties.load(in);
}
} catch (IOException e) {
SyncFactoryException sfe = new SyncFactoryException();
sfe.initCause(e);
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 = System.getProperty(ROWSET_SYNC_PROVIDER);
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 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();
}
// 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);
@SuppressWarnings("deprecation")
Object result = c.newInstance();
return (SyncProvider)result;
} catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) {
throw new SyncFactoryException("IllegalAccessException: " + 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.
*
* @param logger A Logger object instance
* @throws NullPointerException if the logger is null
*/
public static void setLogger(Logger logger) {
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.
*
* @param logger a Logger object instance
* @param level a Level object instance indicating the degree of logging
* required
* @throws NullPointerException if the logger is null
*/
public static void setLogger(Logger logger, Level level) {
// singleton
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
*
* @param ctx a valid JNDI context
* @throws SyncFactoryException if the supplied JNDI context is null
*/
public static synchronized void setJNDIContext(javax.naming.Context ctx)
throws SyncFactoryException {
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;
}
}

View file

@ -0,0 +1,59 @@
/*
* 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
* @since 1.5
*/
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;
}

View file

@ -0,0 +1,424 @@
/*
* Copyright (c) 2003, 2019, 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.
*
* <h2>1.0 Naming Convention for Implementations</h2>
* 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>
* Vendors should refer to the reference implementation synchronization
* providers for additional guidance on how to implement a new
* <code>SyncProvider</code> implementation.
*
* <h2>2.0 How a <code>RowSet</code> Object Gets Its Provider</h2>
*
* 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>.
*
* <h2>3.0 Violations and Synchronization Issues</h2>
* 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>.
*
* <h2>4.0 Updatable SQL VIEWs</h2>
* 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>.
*
* <h2>5.0 <code>SyncProvider</code> Constants</h2>
* 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 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
* @since 1.5
*/
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;
}

View file

@ -0,0 +1,166 @@
/*
* Copyright (c) 2003, 2025, 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
* @since 1.5
*/
public class SyncProviderException extends java.sql.SQLException {
/**
* @serial 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.
*/
@SuppressWarnings("serial") // Not statically typed as Serializable
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;
}

View file

@ -0,0 +1,377 @@
/*
* 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
* @since 1.5
*/
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;
}

View file

@ -0,0 +1,85 @@
/*
* 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.
*
* @since 1.5
*/
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;
}

View file

@ -0,0 +1,76 @@
/*
* 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.
*
* @since 1.5
*/
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;
}

View file

@ -0,0 +1,76 @@
/*
* 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.
*
* @since 1.5
*/
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;
}

View file

@ -0,0 +1,481 @@
/*
* Copyright (c) 2003, 2023, 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.
*/
/**
* The standard classes and interfaces that a third party vendor has to
* use in its implementation of a synchronization provider. These classes and
* interfaces are referred to as the Service Provider Interface (SPI). To make it possible
* for a {@code RowSet} object to use an implementation, the vendor must register
* it with the {@code SyncFactory} singleton. (See the class comment for
* {@code SyncProvider} for a full explanation of the registration process and
* the naming convention to be used.)
*
* <h2>Table of Contents</h2>
* <ul>
* <li><a href="#pkgspec">1.0 Package Specification</a>
* <li><a href="#arch">2.0 Service Provider Architecture</a>
* <li><a href="#impl">3.0 Implementer's Guide</a>
* <li><a href="#resolving">4.0 Resolving Synchronization Conflicts</a>
* <li><a href="#relspec">5.0 Related Specifications</a>
* <li><a href="#reldocs">6.0 Related Documentation</a>
* </ul>
*
* <h3><a id="pkgspec">1.0 Package Specification</a></h3>
* <P>
* The following classes and interfaces make up the {@code javax.sql.rowset.spi}
* package:
* <UL>
* <LI>{@code SyncFactory}
* <LI>{@code SyncProvider}
* <LI>{@code SyncFactoryException}
* <LI>{@code SyncProviderException}
* <LI>{@code SyncResolver}
* <LI>{@code XmlReader}
* <LI>{@code XmlWriter}
* <LI>{@code TransactionalWriter}
* </UL>
* The following interfaces, in the {@code javax.sql} package, are also part of the SPI:
* <UL>
* <LI>{@code RowSetReader}
* <LI>{@code RowSetWriter}
* </UL>
* <P>
* A {@code SyncProvider} implementation provides a disconnected {@code RowSet}
* object with the mechanisms for reading data into it and for writing data that has been
* modified in it
* back to the underlying data source. A <i>reader</i>, a {@code RowSetReader} or
* {@code XMLReader} object, reads data into a {@code RowSet} object when the
* {@code CachedRowSet} methods {@code execute} or {@code populate}
* are called. A <i>writer</i>, a {@code RowSetWriter} or {@code XMLWriter}
* object, writes changes back to the underlying data source when the
* {@code CachedRowSet} method {@code acceptChanges} is called.
* <P>
* The process of writing changes in a {@code RowSet} object to its data source
* is known as <i>synchronization</i>. The {@code SyncProvider} implementation that a
* {@code RowSet} object is using determines the level of synchronization that the
* {@code RowSet} object's writer uses. The various levels of synchronization are
* referred to as <i>grades</i>.
* <P>
* The lower grades of synchronization are
* known as <i>optimistic</i> concurrency levels because they optimistically
* assume that there will be no conflicts or very few conflicts. A conflict exists when
* the same data modified in the {@code RowSet} object has also been modified
* in the data source. Using the optimistic concurrency model means that if there
* is a conflict, modifications to either the data source or the {@code RowSet}
* object will be lost.
* <P>
* Higher grades of synchronization are called <i>pessimistic</i> because they assume
* that others will be accessing the data source and making modifications. These
* grades set varying levels of locks to increase the chances that no conflicts
* occur.
* <P>
* The lowest level of synchronization is simply writing any changes made to the
* {@code RowSet} object to its underlying data source. The writer does
* nothing to check for conflicts.
* If there is a conflict and the data
* source values are overwritten, the changes other parties have made by to the data
* source are lost.
* <P>
* The {@code RIXMLProvider} implementation uses the lowest level
* of synchronization and just writes {@code RowSet} changes to the data source.
*
* <P>
* For the next level up, the
* writer checks to see if there are any conflicts, and if there are,
* it does not write anything to the data source. The problem with this concurrency
* level is that if another party has modified the corresponding data in the data source
* since the {@code RowSet} object got its data,
* the changes made to the {@code RowSet} object are lost. The
* {@code RIOptimisticProvider} implementation uses this level of synchronization.
* <P>
* At higher levels of synchronization, referred to as pessimistic concurrency,
* the writer take steps to avoid conflicts by setting locks. Setting locks
* can vary from setting a lock on a single row to setting a lock on a table
* or the entire data source. The level of synchronization is therefore a tradeoff
* between the ability of users to access the data source concurrently and the ability
* of the writer to keep the data in the {@code RowSet} object and its data source
* synchronized.
* <P>
* It is a requirement that all disconnected {@code RowSet} objects
* ({@code CachedRowSet}, {@code FilteredRowSet}, {@code JoinRowSet},
* and {@code WebRowSet} objects) obtain their {@code SyncProvider} objects
* from the {@code SyncFactory} mechanism.
* <P>
* The reference implementation (RI) provides two synchronization providers.
* <UL>
* <LI><b>{@code RIOptimisticProvider}</b> <br>
* The default provider that the {@code SyncFactory} instance will
* supply to a disconnected {@code RowSet} object when no provider
* implementation is specified.<BR>
* This synchronization provider uses an optimistic concurrency model,
* assuming that there will be few conflicts among users
* who are accessing the same data in a database. It avoids
* using locks; rather, it checks to see if there is a conflict
* before trying to synchronize the {@code RowSet} object and the
* data source. If there is a conflict, it does nothing, meaning that
* changes to the {@code RowSet} object are not persisted to the data
* source.
* <LI><B>{@code RIXMLProvider}</B> <BR>
* A synchronization provider that can be used with a
* {@code WebRowSet} object, which is a rowset that can be written
* in XML format or read from XML format. The
* {@code RIXMLProvider} implementation does no checking at all for
* conflicts and simply writes any updated data in the
* {@code WebRowSet} object to the underlying data source.
* {@code WebRowSet} objects use this provider when they are
* dealing with XML data.
* </UL>
*
* These {@code SyncProvider} implementations
* are bundled with the reference implementation, which makes them always available to
* {@code RowSet} implementations.
* {@code SyncProvider} implementations make themselves available by being
* registered with the {@code SyncFactory} singleton. When a {@code RowSet}
* object requests a provider, by specifying it in the constructor or as an argument to the
* {@code CachedRowSet} method {@code setSyncProvider},
* the {@code SyncFactory} singleton
* checks to see if the requested provider has been registered with it.
* If it has, the {@code SyncFactory} creates an instance of it and passes it to the
* requesting {@code RowSet} object.
* If the {@code SyncProvider} implementation that is specified has not been registered,
* the {@code SyncFactory} singleton causes a {@code SyncFactoryException} object
* to be thrown. If no provider is specified,
* the {@code SyncFactory} singleton will create an instance of the default
* provider implementation, {@code RIOptimisticProvider},
* and pass it to the requesting {@code RowSet} object.
*
* <P>
* If a {@code WebRowSet} object does not specify a provider in its constructor, the
* {@code SyncFactory} will give it an instance of {@code RIOptimisticProvider}.
* However, the constructor for {@code WebRowSet} is implemented to set the provider
* to the {@code RIXMLProvider}, which reads and writes a {@code RowSet} object
* in XML format.
* <P>
* See the <a href="SyncProvider.html">SyncProvider</a> class
* specification for further details.
* <p>
* Vendors may develop a {@code SyncProvider} implementation with any one of the possible
* levels of synchronization, thus giving {@code RowSet} objects a choice of
* synchronization mechanisms.
*
* <h3><a id="arch">2.0 Service Provider Interface Architecture</a></h3>
* <b>2.1 Overview</b>
* <p>
* The Service Provider Interface provides a pluggable mechanism by which
* {@code SyncProvider} implementations can be registered and then generated when
* required. The lazy reference mechanism employed by the {@code SyncFactory} limits
* unnecessary resource consumption by not creating an instance until it is
* required by a disconnected
* {@code RowSet} object. The {@code SyncFactory} class also provides
* a standard API to configure logging options and streams that <b>may</b> be provided
* by a particular {@code SyncProvider} implementation.
* <p>
* <b>2.2 Registering with the {@code SyncFactory}</b>
* <p>
* A third party {@code SyncProvider} implementation must be registered with the
* {@code SyncFactory} in order for a disconnected {@code RowSet} object
* to obtain it and thereby use its {@code javax.sql.RowSetReader} and
* {@code javax.sql.RowSetWriter}
* implementations. The following registration mechanisms are available to all
* {@code SyncProvider} implementations:
* <ul>
* <li><b>System properties</b> - Properties set at the command line. These
* properties are set at run time and apply system-wide per invocation of the Java
* application. See the section <a href="#reldocs">"Related Documentation"</a>
* further related information.
*
* <li><b>Property Files</b> - Properties specified in a standard property file.
* This can be specified using a System Property or by modifying a standard
* property file located in the platform run-time. The
* reference implementation of this technology includes a standard property
* file than can be edited to add additional {@code SyncProvider} objects.
*
* <li><b>JNDI Context</b> - Available providers can be registered on a JNDI
* context. The {@code SyncFactory} will attempt to load {@code SyncProvider}
* objects bound to the context and register them with the factory. This
* context must be supplied to the {@code SyncFactory} for the mechanism to
* function correctly.
* </ul>
* <p>
* Details on how to specify the system properties or properties in a property file
* and how to configure the JNDI Context are explained in detail in the
* <a href="SyncFactory.html">{@code SyncFactory}</a> class description.
* <p>
* <b>2.3 SyncFactory Provider Instance Generation Policies</b>
* <p>
* The {@code SyncFactory} generates a requested {@code SyncProvider}
* object if the provider has been correctly registered. The
* following policies are adhered to when either a disconnected {@code RowSet} object
* is instantiated with a specified {@code SyncProvider} implementation or is
* reconfigured at runtime with an alternative {@code SyncProvider} object.
* <ul>
* <li> If a {@code SyncProvider} object is specified and the {@code SyncFactory}
* contains <i>no</i> reference to the provider, a {@code SyncFactoryException} is
* thrown.
*
* <li> If a {@code SyncProvider} object is specified and the {@code SyncFactory}
* contains a reference to the provider, the requested provider is supplied.
*
* <li> If no {@code SyncProvider} object is specified, the reference
* implementation provider {@code RIOptimisticProvider} is supplied.
* </ul>
* <p>
* These policies are explored in more detail in the <a href="SyncFactory.html">
* {@code SyncFactory}</a> class.
*
* <h3><a id="impl">3.0 SyncProvider Implementer's Guide</a></h3>
*
* <b>3.1 Requirements</b>
* <p>
* A compliant {@code SyncProvider} implementation that is fully pluggable
* into the {@code SyncFactory} <b>must</b> extend and implement all
* abstract methods in the <a href="SyncProvider.html">{@code SyncProvider}</a>
* class. In addition, an implementation <b>must</b> determine the
* grade, locking and updatable view capabilities defined in the
* {@code SyncProvider} class definition. One or more of the
* {@code SyncProvider} description criteria <b>must</b> be supported. It
* is expected that vendor implementations will offer a range of grade, locking, and
* updatable view capabilities.
* <p>
* Furthermore, the {@code SyncProvider} naming convention <b>must</b> be followed as
* detailed in the <a href="SyncProvider.html">{@code SyncProvider}</a> class
* description.
* <p>
* <b>3.2 Grades</b>
* <p>
* JSR 114 defines a set of grades to describe the quality of synchronization
* a {@code SyncProvider} object can offer a disconnected {@code RowSet}
* object. These grades are listed from the lowest quality of service to the highest.
* <ul>
* <li><b>GRADE_NONE</b> - No synchronization with the originating data source is
* provided. A {@code SyncProvider} implementation returning this grade will simply
* attempt to write any data that has changed in the {@code RowSet} object to the
*underlying data source, overwriting whatever is there. No attempt is made to compare
* original values with current values to see if there is a conflict. The
* {@code RIXMLProvider} is implemented with this grade.
*
* <li><b>GRADE_CHECK_MODIFIED_AT_COMMIT</b> - A low grade of optimistic synchronization.
* A {@code SyncProvider} implementation returning this grade
* will check for conflicts in rows that have changed between the last synchronization
* and the current synchronization under way. Any changes in the originating data source
* that have been modified will not be reflected in the disconnected {@code RowSet}
* object. If there are no conflicts, changes in the {@code RowSet} object will be
* written to the data source. If there are conflicts, no changes are written.
* The {@code RIOptimisticProvider} implementation uses this grade.
*
* <li><b>GRADE_CHECK_ALL_AT_COMMIT</b> - A high grade of optimistic synchronization.
* A {@code SyncProvider} implementation returning this grade
* will check all rows, including rows that have not changed in the disconnected
* {@code RowSet} object. In this way, any changes to rows in the underlying
* data source will be reflected in the disconnected {@code RowSet} object
* when the synchronization finishes successfully.
*
* <li><b>GRADE_LOCK_WHEN_MODIFIED</b> - A pessimistic grade of synchronization.
* {@code SyncProvider} implementations returning this grade will lock
* the row in the originating data source that corresponds to the row being changed
* in the {@code RowSet} object to reduce the possibility of other
* processes modifying the same data in the data source.
*
* <li><b>GRADE_LOCK_WHEN_LOADED</b> - A higher pessimistic synchronization grade.
* A {@code SyncProvider} implementation returning this grade will lock
* the entire view and/or table affected by the original query used to
* populate a {@code RowSet} object.
* </ul>
* <p>
* <b>3.3 Locks</b>
* <p>
* JSR 114 defines a set of constants that specify whether any locks have been
* placed on a {@code RowSet} object's underlying data source and, if so,
* on which constructs the locks are placed. These locks will remain on the data
* source while the {@code RowSet} object is disconnected from the data source.
* <P>
* These constants <b>should</b> be considered complementary to the
* grade constants. The default setting for the majority of grade settings requires
* that no data source locks remain when a {@code RowSet} object is disconnected
* from its data source.
* The grades {@code GRADE_LOCK_WHEN_MODIFIED} and
* {@code GRADE_LOCK_WHEN_LOADED} allow a disconnected {@code RowSet} object
* to have a fine-grained control over the degree of locking.
* <ul>
* <li><b>DATASOURCE_NO_LOCK</b> - No locks remain on the originating data source.
* This is the default lock setting for all {@code SyncProvider} implementations
* unless otherwise directed by a {@code RowSet} object.
*
* <li><b>DATASOURCE_ROW_LOCK</b> - A lock is placed on the rows that are touched by
* the original SQL query used to populate the {@code RowSet} object.
*
* <li><b>DATASOURCE_TABLE_LOCK</b> - A lock is placed on all tables that are touched
* by the query that was used to populate the {@code RowSet} object.
*
* <li><b>DATASOURCE_DB_LOCK</b>
* A lock is placed on the entire data source that is used by the {@code RowSet}
* object.
* </ul>
* <p>
* <b>3.4 Updatable Views</b>
* <p>
* A {@code RowSet} object may be populated with data from an SQL {@code VIEW}.
* The following constants indicate whether a {@code SyncProvider} object can
* update data in the table or tables from which the {@code VIEW} was derived.
* <ul>
* <li><b>UPDATABLE_VIEW_SYNC</b>
* Indicates that a {@code SyncProvider} implementation supports synchronization
* to the table or tables from which the SQL {@code VIEW} used to populate
* a {@code RowSet} object is derived.
*
* <li><b>NONUPDATABLE_VIEW_SYNC</b>
* Indicates that a {@code SyncProvider} implementation does <b>not</b> support
* synchronization to the table or tables from which the SQL {@code VIEW}
* used to populate a {@code RowSet} object is derived.
* </ul>
* <p>
* <b>3.5 Usage of {@code SyncProvider} Grading and Locking</b>
* <p>
* In the example below, the reference {@code CachedRowSetImpl} implementation
* reconfigures its current {@code SyncProvider} object by calling the
* {@code setSyncProvider} method.<br>
*
* <PRE>
* CachedRowSetImpl crs = new CachedRowSetImpl();
* crs.setSyncProvider("com.foo.bar.HASyncProvider");
* </PRE>
* An application can retrieve the {@code SyncProvider} object currently in use
* by a disconnected {@code RowSet} object. It can also retrieve the
* grade of synchronization with which the provider was implemented and the degree of
* locking currently in use. In addition, an application has the flexibility to set
* the degree of locking to be used, which can increase the possibilities for successful
* synchronization. These operation are shown in the following code fragment.
* <PRE>
* SyncProvider sync = crs.getSyncProvider();
*
* switch (sync.getProviderGrade()) {
* case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT
* //A high grade of optimistic synchronization
* break;
* case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT
* //A low grade of optimistic synchronization
* break;
* case: SyncProvider.GRADE_LOCK_WHEN_LOADED
* // A pessimistic synchronization grade
* break;
* case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED
* // A pessimistic synchronization grade
* break;
* case: SyncProvider.GRADE_NONE
* // No synchronization with the originating data source provided
* break;
* }
*
* switch (sync.getDataSourceLock() {
* case: SyncProvider.DATASOURCE_DB_LOCK
* // A lock is placed on the entire datasource that is used by the
* // {@code RowSet} object
* break;
*
* case: SyncProvider.DATASOURCE_NO_LOCK
* // No locks remain on the originating data source.
* break;
*
* case: SyncProvider.DATASOURCE_ROW_LOCK
* // A lock is placed on the rows that are touched by the original
* // SQL statement used to populate
* // the RowSet object that is using the SyncProvider
* break;
*
* case: DATASOURCE_TABLE_LOCK
* // A lock is placed on all tables that are touched by the original
* // SQL statement used to populated
* // the RowSet object that is using the SyncProvider
* break;
*
* </PRE>
* It is also possible using the static utility method in the
* {@code SyncFactory} class to determine the list of {@code SyncProvider}
* implementations currently registered with the {@code SyncFactory}.
*
* <pre>
* Enumeration e = SyncFactory.getRegisteredProviders();
* </pre>
*
*
* <h3><a id="resolving">4.0 Resolving Synchronization Conflicts</a></h3>
*
* The interface {@code SyncResolver} provides a way for an application to
* decide manually what to do when a conflict occurs. When the {@code CachedRowSet}
* method {@code acceptChanges} finishes and has detected one or more conflicts,
* it throws a {@code SyncProviderException} object. An application can
* catch the exception and
* have it retrieve a {@code SyncResolver} object by calling the method
* {@code SyncProviderException.getSyncResolver()}.
* <P>
* A {@code SyncResolver} object, which is a special kind of
* {@code CachedRowSet} object or
* a {@code JdbcRowSet} object that has implemented the {@code SyncResolver}
* interface, examines the conflicts row by row. It is a duplicate of the
* {@code RowSet} object being synchronized except that it contains only the data
* from the data source this is causing a conflict. All of the other column values are
* set to {@code null}. To navigate from one conflict value to another, a
* {@code SyncResolver} object provides the methods {@code nextConflict} and
* {@code previousConflict}.
* <P>
* The {@code SyncResolver} interface also
* provides methods for doing the following:
* <UL>
* <LI>finding out whether the conflict involved an update, a delete, or an insert
* <LI>getting the value in the data source that caused the conflict
* <LI>setting the value that should be in the data source if it needs to be changed
* or setting the value that should be in the {@code RowSet} object if it needs
* to be changed
* </UL>
* <P>
* When the {@code CachedRowSet} method {@code acceptChanges} is called, it
* delegates to the {@code RowSet} object's {@code SyncProvider} object.
* How the writer provided by that {@code SyncProvider} object is implemented
* determines what level (grade) of checking for conflicts will be done. After all
* checking for conflicts is completed and one or more conflicts has been found, the method
* {@code acceptChanges} throws a {@code SyncProviderException} object. The
* application can catch the exception and use it to obtain a {@code SyncResolver} object.
* <P>
* The application can then use {@code SyncResolver} methods to get information
* about each conflict and decide what to do. If the application logic or the user
* decides that a value in the {@code RowSet} object should be the one to
* persist, the application or user can overwrite the data source value with it.
* <P>
* The comment for the {@code SyncResolver} interface has more detail.
*
* <h3><a id="relspec">5.0 Related Specifications</a></h3>
* <ul>
* <li><a href="http://docs.oracle.com/javase/jndi/tutorial/index.html">JNDI</a>
* <li><a href="{@docRoot}/java.logging/java/util/logging/package-summary.html">Java Logging
* APIs</a>
* </ul>
* <h3><a id="reldocs">6.0 Related Documentation</a></h3>
* <ul>
* <li><a href="http://docs.oracle.com/javase/tutorial/jdbc/">DataSource for JDBC
* Connections</a>
* </ul>
* @since 1.5
*/
package javax.sql.rowset.spi;

View file

@ -0,0 +1,162 @@
<?xml version="1.0"?>
<!--
Copyright (c) 2003, 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.
-->
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://standards.iso.org/iso/9075/2002/12/sqlxml"
xmlns:sqlxml="http://standards.iso.org/iso/9075/2002/12/sqlxml">
<xsd:annotation>
<xsd:documentation>
ISO/IEC 9075-14:2003 (SQL/XML)
This document contains definitions of types and
annotations as specified in ISO/IEC 9075-14:2003.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType name="kindKeyword">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="PREDEFINED"/>
<xsd:enumeration value="DOMAIN"/>
<xsd:enumeration value="ROW"/>
<xsd:enumeration value="DISTINCT"/>
<xsd:enumeration value="ARRAY"/>
<xsd:enumeration value="MULTISET"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="typeKeyword">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="CHAR"/>
<xsd:enumeration value="VARCHAR"/>
<xsd:enumeration value="CLOB"/>
<xsd:enumeration value="BLOB"/>
<xsd:enumeration value="NUMERIC"/>
<xsd:enumeration value="DECIMAL"/>
<xsd:enumeration value="INTEGER"/>
<xsd:enumeration value="SMALLINT"/>
<xsd:enumeration value="BIGINT"/>
<xsd:enumeration value="FLOAT"/>
<xsd:enumeration value="REAL"/>
<xsd:enumeration value="DOUBLE PRECISION"/>
<xsd:enumeration value="BOOLEAN"/>
<xsd:enumeration value="DATE"/>
<xsd:enumeration value="TIME"/>
<xsd:enumeration value="TIME WITH TIME ZONE"/>
<xsd:enumeration value="TIMESTAMP"/>
<xsd:enumeration value="TIMESTAMP WITH TIME ZONE"/>
<xsd:enumeration value="INTERVAL YEAR"/>
<xsd:enumeration value="INTERVAL YEAR TO MONTH"/>
<xsd:enumeration value="INTERVAL MONTH"/>
<xsd:enumeration value="INTERVAL DAY"/>
<xsd:enumeration value="INTERVAL DAY TO HOUR"/>
<xsd:enumeration value="INTERVAL DAY TO MINUTE"/>
<xsd:enumeration value="INTERVAL DAY TO SECOND"/>
<xsd:enumeration value="INTERVAL HOUR"/>
<xsd:enumeration value="INTERVAL HOUR TO MINUTE"/>
<xsd:enumeration value="INTERVAL HOUR TO SECOND"/>
<xsd:enumeration value="INTERVAL MINUTE"/>
<xsd:enumeration value="INTERVAL MINUTE TO SECOND"/>
<xsd:enumeration value="INTERVAL SECOND"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="fieldType">
<xsd:attribute name="name" type="xsd:string"/>
<xsd:attribute name="mappedType" type="xsd:string"/>
</xsd:complexType>
<xsd:element name="sqltype">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="field" type="sqlxml:fieldType"
minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="kind"
type="sqlxml:kindKeyword"/>
<xsd:attribute name="name"
type="sqlxml:typeKeyword" use="optional"/>
<xsd:attribute name="length" type="xsd:integer"
use="optional"/>
<xsd:attribute name="maxLength" type="xsd:integer"
use="optional"/>
<xsd:attribute name="characterSetName" type="xsd:string"
use="optional"/>
<xsd:attribute name="collation" type="xsd:string"
use="optional"/>
<xsd:attribute name="precision" type="xsd:integer"
use="optional"/>
<xsd:attribute name="scale" type="xsd:integer"
use="optional"/>
<xsd:attribute name="maxExponent" type="xsd:integer"
use="optional"/>
<xsd:attribute name="minExponent" type="xsd:integer"
use="optional"/>
<xsd:attribute name="userPrecision" type="xsd:integer"
use="optional"/>
<xsd:attribute name="leadingPrecision" type="xsd:integer"
use="optional"/>
<xsd:attribute name="maxElements" type="xsd:integer"
use="optional"/>
<xsd:attribute name="catalogName" type="xsd:string"
use="optional"/>
<xsd:attribute name="schemaName" type="xsd:string"
use="optional"/>
<xsd:attribute name="domainName" type="xsd:string"
use="optional"/>
<xsd:attribute name="typeName" type="xsd:string"
use="optional"/>
<xsd:attribute name="mappedType" type="xsd:string"
use="optional"/>
<xsd:attribute name="mappedElementType" type="xsd:string"
use="optional"/>
<xsd:attribute name="final" type="xsd:boolean"
use="optional"/>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="objectType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="CATALOG" />
<xsd:enumeration value="SCHEMA" />
<xsd:enumeration value="BASE TABLE" />
<xsd:enumeration value="VIEWED TABLE" />
<xsd:enumeration value="CHARACTER SET" />
<xsd:enumeration value="COLLATION" />
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="sqlname">
<xsd:complexType>
<xsd:attribute name="type" type="sqlxml:objectType"
use="required" />
<xsd:attribute name="catalogName" type="xsd:string" />
<xsd:attribute name="schemaName" type="xsd:string" />
<xsd:attribute name="localName" type="xsd:string" />
</xsd:complexType>
</xsd:element>
</xsd:schema>

View file

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2003, 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.
-->
<!-- WebRowSet XML Schema by Jonathan Bruce (Sun Microsystems Inc.) -->
<xs:schema targetNamespace="http://java.sun.com/xml/ns/jdbc" xmlns:wrs="http://java.sun.com/xml/ns/jdbc" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="webRowSet">
<xs:complexType>
<xs:sequence>
<xs:element ref="wrs:properties"/>
<xs:element ref="wrs:metadata"/>
<xs:element ref="wrs:data"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="columnValue" type="xs:anyType"/>
<xs:element name="updateValue" type="xs:anyType"/>
<xs:element name="properties">
<xs:complexType>
<xs:sequence>
<xs:element name="command" type="xs:string"/>
<xs:element name="concurrency" type="xs:string"/>
<xs:element name="datasource" type="xs:string"/>
<xs:element name="escape-processing" type="xs:string"/>
<xs:element name="fetch-direction" type="xs:string"/>
<xs:element name="fetch-size" type="xs:string"/>
<xs:element name="isolation-level" type="xs:string"/>
<xs:element name="key-columns">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="column" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="map">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="type" type="xs:string"/>
<xs:element name="class" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="max-field-size" type="xs:string"/>
<xs:element name="max-rows" type="xs:string"/>
<xs:element name="query-timeout" type="xs:string"/>
<xs:element name="read-only" type="xs:string"/>
<xs:element name="rowset-type" type="xs:string"/>
<xs:element name="show-deleted" type="xs:string"/>
<xs:element name="table-name" type="xs:string"/>
<xs:element name="url" type="xs:string"/>
<xs:element name="sync-provider">
<xs:complexType>
<xs:sequence>
<xs:element name="sync-provider-name" type="xs:string"/>
<xs:element name="sync-provider-vendor" type="xs:string"/>
<xs:element name="sync-provider-version" type="xs:string"/>
<xs:element name="sync-provider-grade" type="xs:string"/>
<xs:element name="data-source-lock" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="metadata">
<xs:complexType>
<xs:sequence>
<xs:element name="column-count" type="xs:string"/>
<xs:choice>
<xs:element name="column-definition" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="column-index" type="xs:string"/>
<xs:element name="auto-increment" type="xs:string"/>
<xs:element name="case-sensitive" type="xs:string"/>
<xs:element name="currency" type="xs:string"/>
<xs:element name="nullable" type="xs:string"/>
<xs:element name="signed" type="xs:string"/>
<xs:element name="searchable" type="xs:string"/>
<xs:element name="column-display-size" type="xs:string"/>
<xs:element name="column-label" type="xs:string"/>
<xs:element name="column-name" type="xs:string"/>
<xs:element name="schema-name" type="xs:string"/>
<xs:element name="column-precision" type="xs:string"/>
<xs:element name="column-scale" type="xs:string"/>
<xs:element name="table-name" type="xs:string"/>
<xs:element name="catalog-name" type="xs:string"/>
<xs:element name="column-type" type="xs:string"/>
<xs:element name="column-type-name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="data">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="currentRow" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element ref="wrs:columnValue"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="insertRow" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="wrs:columnValue"/>
<xs:element ref="wrs:updateValue"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="deleteRow" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element ref="wrs:columnValue"/>
<xs:element ref="wrs:updateValue"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="modifyRow" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element ref="wrs:columnValue"/>
<xs:element ref="wrs:updateValue"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2014, 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.
*/
/**
* Defines the JDBC RowSet API.
*
* @uses javax.sql.rowset.RowSetFactory
*
* @moduleGraph
* @since 9
*/
module java.sql.rowset {
requires transitive java.logging;
requires transitive java.naming;
requires transitive java.sql;
exports javax.sql.rowset;
exports javax.sql.rowset.serial;
exports javax.sql.rowset.spi;
uses javax.sql.rowset.RowSetFactory;
}