-
Notifications
You must be signed in to change notification settings - Fork 5.8k
/
Copy pathBaseRowSet.java
4450 lines (4231 loc) · 211 KB
/
BaseRowSet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* 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;
import java.sql.*;
import javax.sql.*;
import java.util.*;
import java.io.*;
import java.math.*;
import java.io.Serializable;
import javax.sql.rowset.serial.*;
/**
* An abstract class providing a <code>RowSet</code> object with its basic functionality.
* The basic functions include having properties and sending event notifications,
* which all JavaBeans components must implement.
*
* <h2>1.0 Overview</h2>
* The <code>BaseRowSet</code> class provides the core functionality
* for all <code>RowSet</code> implementations,
* and all standard implementations <b>may</b> use this class in combination with
* one or more <code>RowSet</code> interfaces in order to provide a standard
* vendor-specific implementation. To clarify, all implementations must implement
* at least one of the <code>RowSet</code> interfaces (<code>JdbcRowSet</code>,
* <code>CachedRowSet</code>, <code>JoinRowSet</code>, <code>FilteredRowSet</code>,
* or <code>WebRowSet</code>). This means that any implementation that extends
* the <code>BaseRowSet</code> class must also implement one of the <code>RowSet</code>
* interfaces.
* <p>
* The <code>BaseRowSet</code> class provides the following:
*
* <UL>
* <LI><b>Properties</b>
* <ul>
* <li>Fields for storing current properties
* <li>Methods for getting and setting properties
* </ul>
*
* <LI><b>Event notification</b>
*
* <LI><b>A complete set of setter methods</b> for setting the parameters in a
* <code>RowSet</code> object's command
*
* <LI> <b>Streams</b>
* <ul>
* <li>Fields for storing stream instances
* <li>Constants for indicating the type of a stream
* </ul>
* </UL>
*
* <h2>2.0 Setting Properties</h2>
* All rowsets maintain a set of properties, which will usually be set using
* a tool. The number and kinds of properties a rowset has will vary,
* depending on what the <code>RowSet</code> implementation does and how it gets
* its data. For example,
* rowsets that get their data from a <code>ResultSet</code> object need to
* set the properties that are required for making a database connection.
* If a <code>RowSet</code> object uses the <code>DriverManager</code> facility to make a
* connection, it needs to set a property for the JDBC URL that identifies the
* appropriate driver, and it needs to set the properties that give the
* user name and password.
* If, on the other hand, the rowset uses a <code>DataSource</code> object
* to make the connection, which is the preferred method, it does not need to
* set the property for the JDBC URL. Instead, it needs to set the property
* for the logical name of the data source along with the properties for
* the user name and password.
* <P>
* NOTE: In order to use a <code>DataSource</code> object for making a
* connection, the <code>DataSource</code> object must have been registered
* with a naming service that uses the Java Naming and Directory
* Interface (JNDI) API. This registration
* is usually done by a person acting in the capacity of a system administrator.
*
* <h2>3.0 Setting the Command and Its Parameters</h2>
* When a rowset gets its data from a relational database, it executes a command (a query)
* that produces a <code>ResultSet</code> object. This query is the command that is set
* for the <code>RowSet</code> object's command property. The rowset populates itself with data by reading the
* data from the <code>ResultSet</code> object into itself. If the query
* contains placeholders for values to be set, the <code>BaseRowSet</code> setter methods
* are used to set these values. All setter methods allow these values to be set
* to <code>null</code> if required.
* <P>
* The following code fragment illustrates how the
* <code>CachedRowSet</code>
* object <code>crs</code> might have its command property set. Note that if a
* tool is used to set properties, this is the code that the tool would use.
* <PRE>{@code
* crs.setCommand("SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS" +
* "WHERE CREDIT_LIMIT > ? AND REGION = ?");
* }</PRE>
* <P>
* In this example, the values for <code>CREDIT_LIMIT</code> and
* <code>REGION</code> are placeholder parameters, which are indicated with a
* question mark (?). The first question mark is placeholder parameter number
* <code>1</code>, the second question mark is placeholder parameter number
* <code>2</code>, and so on. Any placeholder parameters must be set with
* values before the query can be executed. To set these
* placeholder parameters, the <code>BaseRowSet</code> class provides a set of setter
* methods, similar to those provided by the <code>PreparedStatement</code>
* interface, for setting values of each data type. A <code>RowSet</code> object stores the
* parameter values internally, and its <code>execute</code> method uses them internally
* to set values for the placeholder parameters
* before it sends the command to the DBMS to be executed.
* <P>
* The following code fragment demonstrates
* setting the two parameters in the query from the previous example.
* <PRE>{@code
* crs.setInt(1, 5000);
* crs.setString(2, "West");
* }</PRE>
* If the <code>execute</code> method is called at this point, the query
* sent to the DBMS will be:
* <PRE>{@code
* "SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS" +
* "WHERE CREDIT_LIMIT > 5000 AND REGION = 'West'"
* }</PRE>
* NOTE: Setting <code>Array</code>, <code>Clob</code>, <code>Blob</code> and
* <code>Ref</code> objects as a command parameter, stores these values as
* <code>SerialArray</code>, <code>SerialClob</code>, <code>SerialBlob</code>
* and <code>SerialRef</code> objects respectively.
*
* <h2>4.0 Handling of Parameters Behind the Scenes</h2>
*
* NOTE: The <code>BaseRowSet</code> class provides two kinds of setter methods,
* those that set properties and those that set placeholder parameters. The setter
* methods discussed in this section are those that set placeholder parameters.
* <P>
* The placeholder parameters set with the <code>BaseRowSet</code> setter methods
* are stored as objects in an internal <code>Hashtable</code> object.
* Primitives are stored as their <code>Object</code> type. For example, <code>byte</code>
* is stored as <code>Byte</code> object, and <code>int</code> is stored as
* an <code>Integer</code> object.
* When the method <code>execute</code> is called, the values in the
* <code>Hashtable</code> object are substituted for the appropriate placeholder
* parameters in the command.
* <P>
* A call to the method <code>getParams</code> returns the values stored in the
* <code>Hashtable</code> object as an array of <code>Object</code> instances.
* An element in this array may be a simple <code>Object</code> instance or an
* array (which is a type of <code>Object</code>). The particular setter method used
* determines whether an element in this array is an <code>Object</code> or an array.
* <P>
* The majority of methods for setting placeholder parameters take two parameters,
* with the first parameter
* indicating which placeholder parameter is to be set, and the second parameter
* giving the value to be set. Methods such as <code>setInt</code>,
* <code>setString</code>, <code>setBoolean</code>, and <code>setLong</code> fall into
* this category. After these methods have been called, a call to the method
* <code>getParams</code> will return an array with the values that have been set. Each
* element in the array is an <code>Object</code> instance representing the
* values that have been set. The order of these values in the array is determined by the
* <code>int</code> (the first parameter) passed to the setter method. The values in the
* array are the values (the second parameter) passed to the setter method.
* In other words, the first element in the array is the value
* to be set for the first placeholder parameter in the <code>RowSet</code> object's
* command. The second element is the value to
* be set for the second placeholder parameter, and so on.
* <P>
* Several setter methods send the driver and DBMS information beyond the value to be set.
* When the method <code>getParams</code> is called after one of these setter methods has
* been used, the elements in the array will themselves be arrays to accommodate the
* additional information. In this category, the method <code>setNull</code> is a special case
* because one version takes only
* two parameters (<code>setNull(int parameterIndex, int SqlType)</code>). Nevertheless,
* it requires
* an array to contain the information that will be passed to the driver and DBMS. The first
* element in this array is the value to be set, which is <code>null</code>, and the
* second element is the <code>int</code> supplied for <i>sqlType</i>, which
* indicates the type of SQL value that is being set to <code>null</code>. This information
* is needed by some DBMSs and is therefore required in order to ensure that applications
* are portable.
* The other version is intended to be used when the value to be set to <code>null</code>
* is a user-defined type. It takes three parameters
* (<code>setNull(int parameterIndex, int sqlType, String typeName)</code>) and also
* requires an array to contain the information to be passed to the driver and DBMS.
* The first two elements in this array are the same as for the first version of
* <code>setNull</code>. The third element, <i>typeName</i>, gives the SQL name of
* the user-defined type. As is true with the other setter methods, the number of the
* placeholder parameter to be set is indicated by an element's position in the array
* returned by <code>getParams</code>. So, for example, if the parameter
* supplied to <code>setNull</code> is <code>2</code>, the second element in the array
* returned by <code>getParams</code> will be an array of two or three elements.
* <P>
* Some methods, such as <code>setObject</code> and <code>setDate</code> have versions
* that take more than two parameters, with the extra parameters giving information
* to the driver or the DBMS. For example, the methods <code>setDate</code>,
* <code>setTime</code>, and <code>setTimestamp</code> can take a <code>Calendar</code>
* object as their third parameter. If the DBMS does not store time zone information,
* the driver uses the <code>Calendar</code> object to construct the <code>Date</code>,
* <code>Time</code>, or <code>Timestamp</code> object being set. As is true with other
* methods that provide additional information, the element in the array returned
* by <code>getParams</code> is an array instead of a simple <code>Object</code> instance.
* <P>
* The methods <code>setAsciiStream</code>, <code>setBinaryStream</code>,
* <code>setCharacterStream</code>, and <code>setUnicodeStream</code> (which is
* deprecated, so applications should use <code>getCharacterStream</code> instead)
* take three parameters, so for them, the element in the array returned by
* <code>getParams</code> is also an array. What is different about these setter
* methods is that in addition to the information provided by parameters, the array contains
* one of the <code>BaseRowSet</code> constants indicating the type of stream being set.
* <p>
* NOTE: The method <code>getParams</code> is called internally by
* <code>RowSet</code> implementations extending this class; it is not normally called by an
* application programmer directly.
*
* <h2>5.0 Event Notification</h2>
* The <code>BaseRowSet</code> class provides the event notification
* mechanism for rowsets. It contains the field
* <code>listeners</code>, methods for adding and removing listeners, and
* methods for notifying listeners of changes.
* <P>
* A listener is an object that has implemented the <code>RowSetListener</code> interface.
* If it has been added to a <code>RowSet</code> object's list of listeners, it will be notified
* when an event occurs on that <code>RowSet</code> object. Each listener's
* implementation of the <code>RowSetListener</code> methods defines what that object
* will do when it is notified that an event has occurred.
* <P>
* There are three possible events for a <code>RowSet</code> object:
* <OL>
* <LI>the cursor moves
* <LI>an individual row is changed (updated, deleted, or inserted)
* <LI>the contents of the entire <code>RowSet</code> object are changed
* </OL>
* <P>
* The <code>BaseRowSet</code> method used for the notification indicates the
* type of event that has occurred. For example, the method
* <code>notifyRowChanged</code> indicates that a row has been updated,
* deleted, or inserted. Each of the notification methods creates a
* <code>RowSetEvent</code> object, which is supplied to the listener in order to
* identify the <code>RowSet</code> object on which the event occurred.
* What the listener does with this information, which may be nothing, depends on how it was
* implemented.
*
* <h2>6.0 Default Behavior</h2>
* A default <code>BaseRowSet</code> object is initialized with many starting values.
*
* The following is true of a default <code>RowSet</code> instance that extends
* the <code>BaseRowSet</code> class:
* <UL>
* <LI>Has a scrollable cursor and does not show changes
* made by others.
* <LI>Is updatable.
* <LI>Does not show rows that have been deleted.
* <LI>Has no time limit for how long a driver may take to
* execute the <code>RowSet</code> object's command.
* <LI>Has no limit for the number of rows it may contain.
* <LI>Has no limit for the number of bytes a column may contain. NOTE: This
* limit applies only to columns that hold values of the
* following types: <code>BINARY</code>, <code>VARBINARY</code>,
* <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
* and <code>LONGVARCHAR</code>.
* <LI>Will not see uncommitted data (make "dirty" reads).
* <LI>Has escape processing turned on.
* <LI>Has its connection's type map set to <code>null</code>.
* <LI>Has an empty <code>Vector</code> object for storing the values set
* for the placeholder parameters in the <code>RowSet</code> object's command.
* </UL>
* <p>
* If other values are desired, an application must set the property values
* explicitly. For example, the following line of code sets the maximum number
* of rows for the <code>CachedRowSet</code> object <i>crs</i> to 500.
* <PRE>
* crs.setMaxRows(500);
* </PRE>
* Methods implemented in extensions of this <code>BaseRowSet</code> class <b>must</b> throw an
* <code>SQLException</code> object for any violation of the defined assertions. Also, if the
* extending class overrides and reimplements any <code>BaseRowSet</code> method and encounters
* connectivity or underlying data source issues, that method <b>may</b> in addition throw an
* <code>SQLException</code> object for that reason.
*
* @since 1.5
*/
public abstract class BaseRowSet implements Serializable, Cloneable {
/**
* A constant indicating to a <code>RowSetReaderImpl</code> object
* that a given parameter is a Unicode stream. This
* <code>RowSetReaderImpl</code> object is provided as an extension of the
* <code>SyncProvider</code> abstract class defined in the
* <code>SyncFactory</code> static factory SPI mechanism.
*/
public static final int UNICODE_STREAM_PARAM = 0;
/**
* A constant indicating to a <code>RowSetReaderImpl</code> object
* that a given parameter is a binary stream. A
* <code>RowSetReaderImpl</code> object is provided as an extension of the
* <code>SyncProvider</code> abstract class defined in the
* <code>SyncFactory</code> static factory SPI mechanism.
*/
public static final int BINARY_STREAM_PARAM = 1;
/**
* A constant indicating to a <code>RowSetReaderImpl</code> object
* that a given parameter is an ASCII stream. A
* <code>RowSetReaderImpl</code> object is provided as an extension of the
* <code>SyncProvider</code> abstract class defined in the
* <code>SyncFactory</code> static factory SPI mechanism.
*/
public static final int ASCII_STREAM_PARAM = 2;
/**
* The <code>InputStream</code> object that will be
* returned by the method <code>getBinaryStream</code>, which is
* specified in the <code>ResultSet</code> interface.
* @serial
*/
@SuppressWarnings("serial") // Not statically typed as Serializable
protected java.io.InputStream binaryStream;
/**
* The <code>InputStream</code> object that will be
* returned by the method <code>getUnicodeStream</code>,
* which is specified in the <code>ResultSet</code> interface.
* @serial
*/
@SuppressWarnings("serial") // Not statically typed as Serializable
protected java.io.InputStream unicodeStream;
/**
* The <code>InputStream</code> object that will be
* returned by the method <code>getAsciiStream</code>,
* which is specified in the <code>ResultSet</code> interface.
* @serial
*/
@SuppressWarnings("serial") // Not statically typed as Serializable
protected java.io.InputStream asciiStream;
/**
* The <code>Reader</code> object that will be
* returned by the method <code>getCharacterStream</code>,
* which is specified in the <code>ResultSet</code> interface.
* @serial
*/
@SuppressWarnings("serial") // Not statically typed as Serializable
protected java.io.Reader charStream;
/**
* The query that will be sent to the DBMS for execution when the
* method <code>execute</code> is called.
* @serial
*/
private String command;
/**
* The JDBC URL the reader, writer, or both supply to the method
* <code>DriverManager.getConnection</code> when the
* <code>DriverManager</code> is used to get a connection.
* <P>
* The JDBC URL identifies the driver to be used to make the connection.
* This URL can be found in the documentation supplied by the driver
* vendor.
* @serial
*/
private String URL;
/**
* The logical name of the data source that the reader/writer should use
* in order to retrieve a <code>DataSource</code> object from a Java
* Directory and Naming Interface (JNDI) naming service.
* @serial
*/
private String dataSource;
/**
* The user name the reader, writer, or both supply to the method
* <code>DriverManager.getConnection</code> when the
* <code>DriverManager</code> is used to get a connection.
* @serial
*/
private transient String username;
/**
* The password the reader, writer, or both supply to the method
* <code>DriverManager.getConnection</code> when the
* <code>DriverManager</code> is used to get a connection.
* @serial
*/
private transient String password;
/**
* A constant indicating the type of this JDBC <code>RowSet</code>
* object. It must be one of the following <code>ResultSet</code>
* constants: <code>TYPE_FORWARD_ONLY</code>,
* <code>TYPE_SCROLL_INSENSITIVE</code>, or
* <code>TYPE_SCROLL_SENSITIVE</code>.
* @serial
*/
private int rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE;
/**
* A <code>boolean</code> indicating whether deleted rows are visible in this
* JDBC <code>RowSet</code> object .
* @serial
*/
private boolean showDeleted = false; // default is false
/**
* The maximum number of seconds the driver
* will wait for a command to execute. This limit applies while
* this JDBC <code>RowSet</code> object is connected to its data
* source, that is, while it is populating itself with
* data and while it is writing data back to the data source.
* @serial
*/
private int queryTimeout = 0; // default is no timeout
/**
* The maximum number of rows the reader should read.
* @serial
*/
private int maxRows = 0; // default is no limit
/**
* The maximum field size the reader should read.
* @serial
*/
private int maxFieldSize = 0; // default is no limit
/**
* A constant indicating the concurrency of this JDBC <code>RowSet</code>
* object. It must be one of the following <code>ResultSet</code>
* constants: <code>CONCUR_READ_ONLY</code> or
* <code>CONCUR_UPDATABLE</code>.
* @serial
*/
private int concurrency = ResultSet.CONCUR_UPDATABLE;
/**
* A <code>boolean</code> indicating whether this JDBC <code>RowSet</code>
* object is read-only. <code>true</code> indicates that it is read-only;
* <code>false</code> that it is writable.
* @serial
*/
private boolean readOnly;
/**
* A <code>boolean</code> indicating whether the reader for this
* JDBC <code>RowSet</code> object should perform escape processing.
* <code>true</code> means that escape processing is turned on;
* <code>false</code> that it is not. The default is <code>true</code>.
* @serial
*/
private boolean escapeProcessing = true;
/**
* A constant indicating the isolation level of the connection
* for this JDBC <code>RowSet</code> object . It must be one of
* the following <code>Connection</code> constants:
* <code>TRANSACTION_NONE</code>,
* <code>TRANSACTION_READ_UNCOMMITTED</code>,
* <code>TRANSACTION_READ_COMMITTED</code>,
* <code>TRANSACTION_REPEATABLE_READ</code> or
* <code>TRANSACTION_SERIALIZABLE</code>.
* @serial
*/
private int isolation;
/**
* A constant used as a hint to the driver that indicates the direction in
* which data from this JDBC <code>RowSet</code> object is going
* to be fetched. The following <code>ResultSet</code> constants are
* possible values:
* <code>FETCH_FORWARD</code>,
* <code>FETCH_REVERSE</code>,
* <code>FETCH_UNKNOWN</code>.
* <P>
* Unused at this time.
* @serial
*/
private int fetchDir = ResultSet.FETCH_FORWARD; // default fetch direction
/**
* A hint to the driver that indicates the expected number of rows
* in this JDBC <code>RowSet</code> object .
* <P>
* Unused at this time.
* @serial
*/
private int fetchSize = 0; // default fetchSize
/**
* The <code>java.util.Map</code> object that contains entries mapping
* SQL type names to classes in the Java programming language for the
* custom mapping of user-defined types.
* @serial
*/
@SuppressWarnings("serial") // Not statically typed as Serializable
private Map<String, Class<?>> map;
/**
* A <code>Vector</code> object that holds the list of listeners
* that have registered with this <code>RowSet</code> object.
* @serial
*/
private Vector<RowSetListener> listeners;
/**
* A <code>Vector</code> object that holds the parameters set
* for this <code>RowSet</code> object's current command.
* @serial
*/
private Hashtable<Integer, Object> params; // could be transient?
/**
* Constructs a new <code>BaseRowSet</code> object initialized with
* a default <code>Vector</code> object for its <code>listeners</code>
* field. The other default values with which it is initialized are listed
* in Section 6.0 of the class comment for this class.
*/
public BaseRowSet() {
// allocate the listeners collection
listeners = new Vector<RowSetListener>();
}
/**
* Performs the necessary internal configurations and initializations
* to allow any JDBC <code>RowSet</code> implementation to start using
* the standard facilities provided by a <code>BaseRowSet</code>
* instance. This method <b>should</b> be called after the <code>RowSet</code> object
* has been instantiated to correctly initialize all parameters. This method
* <b>should</b> never be called by an application, but is called from with
* a <code>RowSet</code> implementation extending this class.
*/
protected void initParams() {
params = new Hashtable<Integer, Object>();
}
//--------------------------------------------------------------------
// Events
//--------------------------------------------------------------------
/**
* The listener will be notified whenever an event occurs on this <code>RowSet</code>
* object.
* <P>
* A listener might, for example, be a table or graph that needs to
* be updated in order to accurately reflect the current state of
* the <code>RowSet</code> object.
* <p>
* <b>Note</b>: if the <code>RowSetListener</code> object is
* <code>null</code>, this method silently discards the <code>null</code>
* value and does not add a null reference to the set of listeners.
* <p>
* <b>Note</b>: if the listener is already set, and the new <code>RowSetListener</code>
* instance is added to the set of listeners already registered to receive
* event notifications from this <code>RowSet</code>.
*
* @param listener an object that has implemented the
* <code>javax.sql.RowSetListener</code> interface and wants to be notified
* of any events that occur on this <code>RowSet</code> object; May be
* null.
* @see #removeRowSetListener
*/
public void addRowSetListener(RowSetListener listener) {
listeners.add(listener);
}
/**
* Removes the designated object from this <code>RowSet</code> object's list of listeners.
* If the given argument is not a registered listener, this method
* does nothing.
*
* <b>Note</b>: if the <code>RowSetListener</code> object is
* <code>null</code>, this method silently discards the <code>null</code>
* value.
*
* @param listener a <code>RowSetListener</code> object that is on the list
* of listeners for this <code>RowSet</code> object
* @see #addRowSetListener
*/
public void removeRowSetListener(RowSetListener listener) {
listeners.remove(listener);
}
/**
* Determine if instance of this class extends the RowSet interface.
*/
private void checkforRowSetInterface() throws SQLException {
if ((this instanceof javax.sql.RowSet) == false) {
throw new SQLException("The class extending abstract class BaseRowSet " +
"must implement javax.sql.RowSet or one of it's sub-interfaces.");
}
}
/**
* Notifies all of the listeners registered with this
* <code>RowSet</code> object that its cursor has moved.
* <P>
* When an application calls a method to move the cursor,
* that method moves the cursor and then calls this method
* internally. An application <b>should</b> never invoke
* this method directly.
*
* @throws SQLException if the class extending the <code>BaseRowSet</code>
* abstract class does not implement the <code>RowSet</code> interface or
* one of it's sub-interfaces.
*/
protected void notifyCursorMoved() throws SQLException {
checkforRowSetInterface();
if (listeners.isEmpty() == false) {
RowSetEvent event = new RowSetEvent((RowSet)this);
for (RowSetListener rsl : listeners) {
rsl.cursorMoved(event);
}
}
}
/**
* Notifies all of the listeners registered with this <code>RowSet</code> object that
* one of its rows has changed.
* <P>
* When an application calls a method that changes a row, such as
* the <code>CachedRowSet</code> methods <code>insertRow</code>,
* <code>updateRow</code>, or <code>deleteRow</code>,
* that method calls <code>notifyRowChanged</code>
* internally. An application <b>should</b> never invoke
* this method directly.
*
* @throws SQLException if the class extending the <code>BaseRowSet</code>
* abstract class does not implement the <code>RowSet</code> interface or
* one of it's sub-interfaces.
*/
protected void notifyRowChanged() throws SQLException {
checkforRowSetInterface();
if (listeners.isEmpty() == false) {
RowSetEvent event = new RowSetEvent((RowSet)this);
for (RowSetListener rsl : listeners) {
rsl.rowChanged(event);
}
}
}
/**
* Notifies all of the listeners registered with this <code>RowSet</code>
* object that its entire contents have changed.
* <P>
* When an application calls methods that change the entire contents
* of the <code>RowSet</code> object, such as the <code>CachedRowSet</code> methods
* <code>execute</code>, <code>populate</code>, <code>restoreOriginal</code>,
* or <code>release</code>, that method calls <code>notifyRowSetChanged</code>
* internally (either directly or indirectly). An application <b>should</b>
* never invoke this method directly.
*
* @throws SQLException if the class extending the <code>BaseRowSet</code>
* abstract class does not implement the <code>RowSet</code> interface or
* one of it's sub-interfaces.
*/
protected void notifyRowSetChanged() throws SQLException {
checkforRowSetInterface();
if (listeners.isEmpty() == false) {
RowSetEvent event = new RowSetEvent((RowSet)this);
for (RowSetListener rsl : listeners) {
rsl.rowSetChanged(event);
}
}
}
/**
* Retrieves the SQL query that is the command for this
* <code>RowSet</code> object. The command property contains the query that
* will be executed to populate this <code>RowSet</code> object.
* <P>
* The SQL query returned by this method is used by <code>RowSet</code> methods
* such as <code>execute</code> and <code>populate</code>, which may be implemented
* by any class that extends the <code>BaseRowSet</code> abstract class and
* implements one or more of the standard JSR-114 <code>RowSet</code>
* interfaces.
* <P>
* The command is used by the <code>RowSet</code> object's
* reader to obtain a <code>ResultSet</code> object. The reader then
* reads the data from the <code>ResultSet</code> object and uses it to
* to populate this <code>RowSet</code> object.
* <P>
* The default value for the <code>command</code> property is <code>null</code>.
*
* @return the <code>String</code> that is the value for this
* <code>RowSet</code> object's <code>command</code> property;
* may be <code>null</code>
* @see #setCommand
*/
public String getCommand() {
return command;
}
/**
* Sets this <code>RowSet</code> object's <code>command</code> property to
* the given <code>String</code> object and clears the parameters, if any,
* that were set for the previous command.
* <P>
* The <code>command</code> property may not be needed if the <code>RowSet</code>
* object gets its data from a source that does not support commands,
* such as a spreadsheet or other tabular file.
* Thus, this property is optional and may be <code>null</code>.
*
* @param cmd a <code>String</code> object containing an SQL query
* that will be set as this <code>RowSet</code> object's command
* property; may be <code>null</code> but may not be an empty string
* @throws SQLException if an empty string is provided as the command value
* @see #getCommand
*/
public void setCommand(String cmd) throws SQLException {
// cmd equal to null or
// cmd with length 0 (implies url =="")
// are not independent events.
if(cmd == null) {
command = null;
} else if (cmd.length() == 0) {
throw new SQLException("Invalid command string detected. " +
"Cannot be of length less than 0");
} else {
// "unbind" any parameters from any previous command.
if(params == null){
throw new SQLException("Set initParams() before setCommand");
}
params.clear();
command = cmd;
}
}
/**
* Retrieves the JDBC URL that this <code>RowSet</code> object's
* <code>javax.sql.Reader</code> object uses to make a connection
* with a relational database using a JDBC technology-enabled driver.
*<P>
* The <code>Url</code> property will be <code>null</code> if the underlying data
* source is a non-SQL data source, such as a spreadsheet or an XML
* data source.
*
* @return a <code>String</code> object that contains the JDBC URL
* used to establish the connection for this <code>RowSet</code>
* object; may be <code>null</code> (default value) if not set
* @throws SQLException if an error occurs retrieving the URL value
* @see #setUrl
*/
public String getUrl() throws SQLException {
return URL;
}
/**
* Sets the Url property for this <code>RowSet</code> object
* to the given <code>String</code> object and sets the dataSource name
* property to <code>null</code>. The Url property is a
* JDBC URL that is used when
* the connection is created using a JDBC technology-enabled driver
* ("JDBC driver") and the <code>DriverManager</code>.
* The correct JDBC URL for the specific driver to be used can be found
* in the driver documentation. Although there are guidelines for how
* a JDBC URL is formed,
* a driver vendor can specify any <code>String</code> object except
* one with a length of <code>0</code> (an empty string).
* <P>
* Setting the Url property is optional if connections are established using
* a <code>DataSource</code> object instead of the <code>DriverManager</code>.
* The driver will use either the URL property or the
* dataSourceName property to create a connection, whichever was
* specified most recently. If an application uses a JDBC URL, it
* must load a JDBC driver that accepts the JDBC URL before it uses the
* <code>RowSet</code> object to connect to a database. The <code>RowSet</code>
* object will use the URL internally to create a database connection in order
* to read or write data.
*
* @param url a <code>String</code> object that contains the JDBC URL
* that will be used to establish the connection to a database for this
* <code>RowSet</code> object; may be <code>null</code> but must not
* be an empty string
* @throws SQLException if an error occurs setting the Url property or the
* parameter supplied is a string with a length of <code>0</code> (an
* empty string)
* @see #getUrl
*/
public void setUrl(String url) throws SQLException {
if(url == null) {
url = null;
} else if (url.length() < 1) {
throw new SQLException("Invalid url string detected. " +
"Cannot be of length less than 1");
} else {
URL = url;
}
dataSource = null;
}
/**
* Returns the logical name that when supplied to a naming service
* that uses the Java Naming and Directory Interface (JNDI) API, will
* retrieve a <code>javax.sql.DataSource</code> object. This
* <code>DataSource</code> object can be used to establish a connection
* to the data source that it represents.
* <P>
* Users should set either the url or the data source name property.
* The driver will use the property set most recently to establish a
* connection.
*
* @return a <code>String</code> object that identifies the
* <code>DataSource</code> object to be used for making a
* connection; if no logical name has been set, <code>null</code>
* is returned.
* @see #setDataSourceName
*/
public String getDataSourceName() {
return dataSource;
}
/**
* Sets the <code>DataSource</code> name property for this <code>RowSet</code>
* object to the given logical name and sets this <code>RowSet</code> object's
* Url property to <code>null</code>. The name must have been bound to a
* <code>DataSource</code> object in a JNDI naming service so that an
* application can do a lookup using that name to retrieve the
* <code>DataSource</code> object bound to it. The <code>DataSource</code>
* object can then be used to establish a connection to the data source it
* represents.
* <P>
* Users should set either the Url property or the dataSourceName property.
* If both properties are set, the driver will use the property set most recently.
*
* @param name a <code>String</code> object with the name that can be supplied
* to a naming service based on JNDI technology to retrieve the
* <code>DataSource</code> object that can be used to get a connection;
* may be <code>null</code> but must not be an empty string
* @throws SQLException if an empty string is provided as the <code>DataSource</code>
* name
* @see #getDataSourceName
*/
public void setDataSourceName(String name) throws SQLException {
if (name == null) {
dataSource = null;
} else if (name.isEmpty()) {
throw new SQLException("DataSource name cannot be empty string");
} else {
dataSource = name;
}
URL = null;
}
/**
* Returns the user name used to create a database connection. Because it
* is not serialized, the username property is set at runtime before
* calling the method <code>execute</code>.
*
* @return the <code>String</code> object containing the user name that
* is supplied to the data source to create a connection; may be
* <code>null</code> (default value) if not set
* @see #setUsername
*/
public String getUsername() {
return username;
}
/**
* Sets the username property for this <code>RowSet</code> object
* to the given user name. Because it
* is not serialized, the username property is set at run time before
* calling the method <code>execute</code>.
*
* @param name the <code>String</code> object containing the user name that
* is supplied to the data source to create a connection. It may be null.
* @see #getUsername
*/
public void setUsername(String name) {
if(name == null)
{
username = null;
} else {
username = name;
}
}
/**
* Returns the password used to create a database connection for this
* <code>RowSet</code> object. Because the password property is not
* serialized, it is set at run time before calling the method
* <code>execute</code>. The default value is <code>null</code>
*
* @return the <code>String</code> object that represents the password
* that must be supplied to the database to create a connection
* @see #setPassword
*/
public String getPassword() {
return password;
}
/**
* Sets the password used to create a database connection for this
* <code>RowSet</code> object to the given <code>String</code>
* object. Because the password property is not
* serialized, it is set at run time before calling the method
* <code>execute</code>.
*
* @param pass the <code>String</code> object that represents the password
* that is supplied to the database to create a connection. It may be
* null.
* @see #getPassword
*/
public void setPassword(String pass) {
if(pass == null)
{
password = null;
} else {
password = pass;
}
}
/**
* Sets the type for this <code>RowSet</code> object to the specified type.
* The default type is <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>.
*
* @param type one of the following constants:
* <code>ResultSet.TYPE_FORWARD_ONLY</code>,
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
* <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
* @throws SQLException if the parameter supplied is not one of the
* following constants:
* <code>ResultSet.TYPE_FORWARD_ONLY</code> or
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>
* <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
* @see #getConcurrency
* @see #getType
*/
public void setType(int type) throws SQLException {
if ((type != ResultSet.TYPE_FORWARD_ONLY) &&
(type != ResultSet.TYPE_SCROLL_INSENSITIVE) &&
(type != ResultSet.TYPE_SCROLL_SENSITIVE)) {
throw new SQLException("Invalid type of RowSet set. Must be either " +
"ResultSet.TYPE_FORWARD_ONLY or ResultSet.TYPE_SCROLL_INSENSITIVE " +
"or ResultSet.TYPE_SCROLL_SENSITIVE.");
}
this.rowSetType = type;
}
/**
* Returns the type of this <code>RowSet</code> object. The type is initially
* determined by the statement that created the <code>RowSet</code> object.
* The <code>RowSet</code> object can call the method
* <code>setType</code> at any time to change its
* type. The default is <code>TYPE_SCROLL_INSENSITIVE</code>.
*
* @return the type of this JDBC <code>RowSet</code>
* object, which must be one of the following:
* <code>ResultSet.TYPE_FORWARD_ONLY</code>,
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
* <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
* @throws SQLException if an error occurs getting the type of
* of this <code>RowSet</code> object
* @see #setType
*/
public int getType() throws SQLException {
return rowSetType;
}
/**
* Sets the concurrency for this <code>RowSet</code> object to
* the specified concurrency. The default concurrency for any <code>RowSet</code>
* object (connected or disconnected) is <code>ResultSet.CONCUR_UPDATABLE</code>,
* but this method may be called at any time to change the concurrency.
*
* @param concurrency one of the following constants:
* <code>ResultSet.CONCUR_READ_ONLY</code> or
* <code>ResultSet.CONCUR_UPDATABLE</code>
* @throws SQLException if the parameter supplied is not one of the
* following constants:
* <code>ResultSet.CONCUR_UPDATABLE</code> or
* <code>ResultSet.CONCUR_READ_ONLY</code>
* @see #getConcurrency
* @see #isReadOnly
*/