Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetReader.java
40948 views
1
/*
2
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package com.sun.rowset.internal;
27
28
import java.sql.*;
29
import javax.sql.*;
30
import javax.naming.*;
31
import java.io.*;
32
import java.lang.reflect.*;
33
34
import com.sun.rowset.*;
35
import javax.sql.rowset.*;
36
import javax.sql.rowset.spi.*;
37
38
/**
39
* The facility called by the <code>RIOptimisticProvider</code> object
40
* internally to read data into it. The calling <code>RowSet</code> object
41
* must have implemented the <code>RowSetInternal</code> interface
42
* and have the standard <code>CachedRowSetReader</code> object set as its
43
* reader.
44
* <P>
45
* This implementation always reads all rows of the data source,
46
* and it assumes that the <code>command</code> property for the caller
47
* is set with a query that is appropriate for execution by a
48
* <code>PreparedStatement</code> object.
49
* <P>
50
* Typically the <code>SyncFactory</code> manages the <code>RowSetReader</code> and
51
* the <code>RowSetWriter</code> implementations using <code>SyncProvider</code> objects.
52
* Standard JDBC RowSet implementations provide an object instance of this
53
* reader by invoking the <code>SyncProvider.getRowSetReader()</code> method.
54
*
55
* @author Jonathan Bruce
56
* @see javax.sql.rowset.spi.SyncProvider
57
* @see javax.sql.rowset.spi.SyncFactory
58
* @see javax.sql.rowset.spi.SyncFactoryException
59
*/
60
public class CachedRowSetReader implements RowSetReader, Serializable {
61
62
/**
63
* The field that keeps track of whether the writer associated with
64
* this <code>CachedRowSetReader</code> object's rowset has been called since
65
* the rowset was populated.
66
* <P>
67
* When this <code>CachedRowSetReader</code> object reads data into
68
* its rowset, it sets the field <code>writerCalls</code> to 0.
69
* When the writer associated with the rowset is called to write
70
* data back to the underlying data source, its <code>writeData</code>
71
* method calls the method <code>CachedRowSetReader.reset</code>,
72
* which increments <code>writerCalls</code> and returns <code>true</code>
73
* if <code>writerCalls</code> is 1. Thus, <code>writerCalls</code> equals
74
* 1 after the first call to <code>writeData</code> that occurs
75
* after the rowset has had data read into it.
76
*
77
* @serial
78
*/
79
private int writerCalls = 0;
80
81
private boolean userCon = false;
82
83
private int startPosition;
84
85
private JdbcRowSetResourceBundle resBundle;
86
87
public CachedRowSetReader() {
88
try {
89
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
90
} catch(IOException ioe) {
91
throw new RuntimeException(ioe);
92
}
93
}
94
95
96
/**
97
* Reads data from a data source and populates the given
98
* <code>RowSet</code> object with that data.
99
* This method is called by the rowset internally when
100
* the application invokes the method <code>execute</code>
101
* to read a new set of rows.
102
* <P>
103
* After clearing the rowset of its contents, if any, and setting
104
* the number of writer calls to <code>0</code>, this reader calls
105
* its <code>connect</code> method to make
106
* a connection to the rowset's data source. Depending on which
107
* of the rowset's properties have been set, the <code>connect</code>
108
* method will use a <code>DataSource</code> object or the
109
* <code>DriverManager</code> facility to make a connection to the
110
* data source.
111
* <P>
112
* Once the connection to the data source is made, this reader
113
* executes the query in the calling <code>CachedRowSet</code> object's
114
* <code>command</code> property. Then it calls the rowset's
115
* <code>populate</code> method, which reads data from the
116
* <code>ResultSet</code> object produced by executing the rowset's
117
* command. The rowset is then populated with this data.
118
* <P>
119
* This method's final act is to close the connection it made, thus
120
* leaving the rowset disconnected from its data source.
121
*
122
* @param caller a <code>RowSet</code> object that has implemented
123
* the <code>RowSetInternal</code> interface and had
124
* this <code>CachedRowSetReader</code> object set as
125
* its reader
126
* @throws SQLException if there is a database access error, there is a
127
* problem making the connection, or the command property has not
128
* been set
129
*/
130
public void readData(RowSetInternal caller) throws SQLException
131
{
132
Connection con = null;
133
try {
134
CachedRowSet crs = (CachedRowSet)caller;
135
136
// Get rid of the current contents of the rowset.
137
138
/**
139
* Checking added to verify whether page size has been set or not.
140
* If set then do not close the object as certain parameters need
141
* to be maintained.
142
*/
143
144
if(crs.getPageSize() == 0 && crs.size() >0 ) {
145
// When page size is not set,
146
// crs.size() will show the total no of rows.
147
crs.close();
148
}
149
150
writerCalls = 0;
151
152
// Get a connection. This reader assumes that the necessary
153
// properties have been set on the caller to let it supply a
154
// connection.
155
userCon = false;
156
157
con = this.connect(caller);
158
159
// Check our assumptions.
160
if (con == null || crs.getCommand() == null)
161
throw new SQLException(resBundle.handleGetObject("crsreader.connecterr").toString());
162
163
try {
164
con.setTransactionIsolation(crs.getTransactionIsolation());
165
} catch (Exception ex) {
166
;
167
}
168
// Use JDBC to read the data.
169
PreparedStatement pstmt = con.prepareStatement(crs.getCommand());
170
// Pass any input parameters to JDBC.
171
172
decodeParams(caller.getParams(), pstmt);
173
try {
174
pstmt.setMaxRows(crs.getMaxRows());
175
pstmt.setMaxFieldSize(crs.getMaxFieldSize());
176
pstmt.setEscapeProcessing(crs.getEscapeProcessing());
177
pstmt.setQueryTimeout(crs.getQueryTimeout());
178
} catch (Exception ex) {
179
/*
180
* drivers may not support the above - esp. older
181
* drivers being used by the bridge..
182
*/
183
throw new SQLException(ex.getMessage());
184
}
185
186
if(crs.getCommand().toLowerCase().indexOf("select") != -1) {
187
// can be (crs.getCommand()).indexOf("select")) == 0
188
// because we will be getting resultset when
189
// it may be the case that some false select query with
190
// select coming in between instead of first.
191
192
// if ((crs.getCommand()).indexOf("?")) does not return -1
193
// implies a Prepared Statement like query exists.
194
195
ResultSet rs = pstmt.executeQuery();
196
if(crs.getPageSize() == 0){
197
crs.populate(rs);
198
}
199
else {
200
/**
201
* If page size has been set then create a ResultSet object that is scrollable using a
202
* PreparedStatement handle.Also call the populate(ResultSet,int) function to populate
203
* a page of data as specified by the page size.
204
*/
205
pstmt = con.prepareStatement(crs.getCommand(),ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
206
decodeParams(caller.getParams(), pstmt);
207
try {
208
pstmt.setMaxRows(crs.getMaxRows());
209
pstmt.setMaxFieldSize(crs.getMaxFieldSize());
210
pstmt.setEscapeProcessing(crs.getEscapeProcessing());
211
pstmt.setQueryTimeout(crs.getQueryTimeout());
212
} catch (Exception ex) {
213
/*
214
* drivers may not support the above - esp. older
215
* drivers being used by the bridge..
216
*/
217
throw new SQLException(ex.getMessage());
218
}
219
rs = pstmt.executeQuery();
220
crs.populate(rs,startPosition);
221
}
222
rs.close();
223
} else {
224
pstmt.executeUpdate();
225
}
226
227
// Get the data.
228
pstmt.close();
229
try {
230
con.commit();
231
} catch (SQLException ex) {
232
;
233
}
234
// only close connections we created...
235
if (getCloseConnection() == true)
236
con.close();
237
}
238
catch (SQLException ex) {
239
// Throw an exception if reading fails for any reason.
240
throw ex;
241
} finally {
242
try {
243
// only close connections we created...
244
if (con != null && getCloseConnection() == true) {
245
try {
246
if (!con.getAutoCommit()) {
247
con.rollback();
248
}
249
} catch (Exception dummy) {
250
/*
251
* not an error condition, we're closing anyway, but
252
* we'd like to clean up any locks if we can since
253
* it is not clear the connection pool will clean
254
* these connections in a timely manner
255
*/
256
}
257
con.close();
258
con = null;
259
}
260
} catch (SQLException e) {
261
// will get exception if something already went wrong, but don't
262
// override that exception with this one
263
}
264
}
265
}
266
267
/**
268
* Checks to see if the writer associated with this reader needs
269
* to reset its state. The writer will need to initialize its state
270
* if new contents have been read since the writer was last called.
271
* This method is called by the writer that was registered with
272
* this reader when components were being wired together.
273
*
274
* @return <code>true</code> if writer associated with this reader needs
275
* to reset the values of its fields; <code>false</code> otherwise
276
* @throws SQLException if an access error occurs
277
*/
278
public boolean reset() throws SQLException {
279
writerCalls++;
280
return writerCalls == 1;
281
}
282
283
/**
284
* Establishes a connection with the data source for the given
285
* <code>RowSet</code> object. If the rowset's <code>dataSourceName</code>
286
* property has been set, this method uses the JNDI API to retrieve the
287
* <code>DataSource</code> object that it can use to make the connection.
288
* If the url, username, and password properties have been set, this
289
* method uses the <code>DriverManager.getConnection</code> method to
290
* make the connection.
291
* <P>
292
* This method is used internally by the reader and writer associated with
293
* the calling <code>RowSet</code> object; an application never calls it
294
* directly.
295
*
296
* @param caller a <code>RowSet</code> object that has implemented
297
* the <code>RowSetInternal</code> interface and had
298
* this <code>CachedRowSetReader</code> object set as
299
* its reader
300
* @return a <code>Connection</code> object that represents a connection
301
* to the caller's data source
302
* @throws SQLException if an access error occurs
303
*/
304
public Connection connect(RowSetInternal caller) throws SQLException {
305
306
// Get a JDBC connection.
307
if (caller.getConnection() != null) {
308
// A connection was passed to execute(), so use it.
309
// As we are using a connection the user gave us we
310
// won't close it.
311
userCon = true;
312
return caller.getConnection();
313
}
314
else if (((RowSet)caller).getDataSourceName() != null) {
315
// Connect using JNDI.
316
try {
317
Context ctx = new InitialContext();
318
DataSource ds = (DataSource)ctx.lookup
319
(((RowSet)caller).getDataSourceName());
320
321
// Check for username, password,
322
// if it exists try getting a Connection handle through them
323
// else try without these
324
// else throw SQLException
325
326
if(((RowSet)caller).getUsername() != null) {
327
return ds.getConnection(((RowSet)caller).getUsername(),
328
((RowSet)caller).getPassword());
329
} else {
330
return ds.getConnection();
331
}
332
}
333
catch (javax.naming.NamingException ex) {
334
SQLException sqlEx = new SQLException(resBundle.handleGetObject("crsreader.connect").toString());
335
sqlEx.initCause(ex);
336
throw sqlEx;
337
}
338
} else if (((RowSet)caller).getUrl() != null) {
339
// Connect using the driver manager.
340
return DriverManager.getConnection(((RowSet)caller).getUrl(),
341
((RowSet)caller).getUsername(),
342
((RowSet)caller).getPassword());
343
}
344
else {
345
return null;
346
}
347
}
348
349
/**
350
* Sets the parameter placeholders
351
* in the rowset's command (the given <code>PreparedStatement</code>
352
* object) with the parameters in the given array.
353
* This method, called internally by the method
354
* <code>CachedRowSetReader.readData</code>, reads each parameter, and
355
* based on its type, determines the correct
356
* <code>PreparedStatement.setXXX</code> method to use for setting
357
* that parameter.
358
*
359
* @param params an array of parameters to be used with the given
360
* <code>PreparedStatement</code> object
361
* @param pstmt the <code>PreparedStatement</code> object that is the
362
* command for the calling rowset and into which
363
* the given parameters are to be set
364
* @throws SQLException if an access error occurs
365
*/
366
@SuppressWarnings("deprecation")
367
private void decodeParams(Object[] params,
368
PreparedStatement pstmt) throws SQLException {
369
// There is a corresponding decodeParams in JdbcRowSetImpl
370
// which does the same as this method. This is a design flaw.
371
// Update the JdbcRowSetImpl.decodeParams when you update
372
// this method.
373
374
// Adding the same comments to JdbcRowSetImpl.decodeParams.
375
376
int arraySize;
377
Object[] param = null;
378
379
for (int i=0; i < params.length; i++) {
380
if (params[i] instanceof Object[]) {
381
param = (Object[])params[i];
382
383
if (param.length == 2) {
384
if (param[0] == null) {
385
pstmt.setNull(i + 1, ((Integer)param[1]).intValue());
386
continue;
387
}
388
389
if (param[0] instanceof java.sql.Date ||
390
param[0] instanceof java.sql.Time ||
391
param[0] instanceof java.sql.Timestamp) {
392
System.err.println(resBundle.handleGetObject("crsreader.datedetected").toString());
393
if (param[1] instanceof java.util.Calendar) {
394
System.err.println(resBundle.handleGetObject("crsreader.caldetected").toString());
395
pstmt.setDate(i + 1, (java.sql.Date)param[0],
396
(java.util.Calendar)param[1]);
397
continue;
398
}
399
else {
400
throw new SQLException(resBundle.handleGetObject("crsreader.paramtype").toString());
401
}
402
}
403
404
if (param[0] instanceof Reader) {
405
pstmt.setCharacterStream(i + 1, (Reader)param[0],
406
((Integer)param[1]).intValue());
407
continue;
408
}
409
410
/*
411
* What's left should be setObject(int, Object, scale)
412
*/
413
if (param[1] instanceof Integer) {
414
pstmt.setObject(i + 1, param[0], ((Integer)param[1]).intValue());
415
continue;
416
}
417
418
} else if (param.length == 3) {
419
420
if (param[0] == null) {
421
pstmt.setNull(i + 1, ((Integer)param[1]).intValue(),
422
(String)param[2]);
423
continue;
424
}
425
426
if (param[0] instanceof java.io.InputStream) {
427
switch (((Integer)param[2]).intValue()) {
428
case CachedRowSetImpl.UNICODE_STREAM_PARAM:
429
pstmt.setUnicodeStream(i + 1,
430
(java.io.InputStream)param[0],
431
((Integer)param[1]).intValue());
432
break;
433
case CachedRowSetImpl.BINARY_STREAM_PARAM:
434
pstmt.setBinaryStream(i + 1,
435
(java.io.InputStream)param[0],
436
((Integer)param[1]).intValue());
437
break;
438
case CachedRowSetImpl.ASCII_STREAM_PARAM:
439
pstmt.setAsciiStream(i + 1,
440
(java.io.InputStream)param[0],
441
((Integer)param[1]).intValue());
442
break;
443
default:
444
throw new SQLException(resBundle.handleGetObject("crsreader.paramtype").toString());
445
}
446
}
447
448
/*
449
* no point at looking at the first element now;
450
* what's left must be the setObject() cases.
451
*/
452
if (param[1] instanceof Integer && param[2] instanceof Integer) {
453
pstmt.setObject(i + 1, param[0], ((Integer)param[1]).intValue(),
454
((Integer)param[2]).intValue());
455
continue;
456
}
457
458
throw new SQLException(resBundle.handleGetObject("crsreader.paramtype").toString());
459
460
} else {
461
// common case - this catches all SQL92 types
462
pstmt.setObject(i + 1, params[i]);
463
continue;
464
}
465
} else {
466
// Try to get all the params to be set here
467
pstmt.setObject(i + 1, params[i]);
468
469
}
470
}
471
}
472
473
/**
474
* Assists in determining whether the current connection was created by this
475
* CachedRowSet to ensure incorrect connections are not prematurely terminated.
476
*
477
* @return a boolean giving the status of whether the connection has been closed.
478
*/
479
protected boolean getCloseConnection() {
480
if (userCon == true)
481
return false;
482
483
return true;
484
}
485
486
/**
487
* This sets the start position in the ResultSet from where to begin. This is
488
* called by the Reader in the CachedRowSetImpl to set the position on the page
489
* to begin populating from.
490
* @param pos integer indicating the position in the <code>ResultSet</code> to begin
491
* populating from.
492
*/
493
public void setStartPosition(int pos){
494
startPosition = pos;
495
}
496
497
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
498
// Default state initialization happens here
499
ois.defaultReadObject();
500
// Initialization of Res Bundle happens here .
501
try {
502
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
503
} catch(IOException ioe) {
504
throw new RuntimeException(ioe);
505
}
506
507
}
508
509
static final long serialVersionUID =5049738185801363801L;
510
}
511
512