1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 package com.sun.star.comp.sdbc;
22 
23 import org.apache.openoffice.comp.sdbc.dbtools.comphelper.CompHelper;
24 import org.apache.openoffice.comp.sdbc.dbtools.comphelper.PropertySet;
25 import org.apache.openoffice.comp.sdbc.dbtools.comphelper.PropertySetAdapter.PropertyGetter;
26 import org.apache.openoffice.comp.sdbc.dbtools.comphelper.PropertySetAdapter.PropertySetter;
27 import org.apache.openoffice.comp.sdbc.dbtools.util.PropertyIds;
28 import org.apache.openoffice.comp.sdbc.dbtools.util.Resources;
29 
30 import com.sun.star.beans.PropertyVetoException;
31 import com.sun.star.comp.sdbc.ConnectionLog.ObjectType;
32 import com.sun.star.lang.IllegalArgumentException;
33 import com.sun.star.lang.WrappedTargetException;
34 import com.sun.star.logging.LogLevel;
35 import com.sun.star.sdbc.ResultSetConcurrency;
36 import com.sun.star.sdbc.ResultSetType;
37 import com.sun.star.sdbc.SQLException;
38 import com.sun.star.sdbc.SQLWarning;
39 import com.sun.star.sdbc.XCloseable;
40 import com.sun.star.sdbc.XGeneratedResultSet;
41 import com.sun.star.sdbc.XMultipleResults;
42 import com.sun.star.sdbc.XResultSet;
43 import com.sun.star.sdbc.XStatement;
44 import com.sun.star.sdbc.XWarningsSupplier;
45 import com.sun.star.uno.Any;
46 import com.sun.star.uno.Type;
47 import com.sun.star.util.XCancellable;
48 
49 public abstract class JavaSQLStatementBase extends PropertySet
50         implements XGeneratedResultSet, XMultipleResults, XCloseable, XCancellable, XWarningsSupplier {
51 
52     protected JavaSQLConnection connection;
53     protected ConnectionLog logger;
54     protected java.sql.Statement jdbcStatement;
55     protected boolean escapeProcessing = true;
56     protected int resultSetType = ResultSetType.FORWARD_ONLY;
57     protected int resultSetConcurrency = ResultSetConcurrency.READ_ONLY;
58     protected String sqlStatement = "";
59     protected XStatement generatedStatement;
60 
JavaSQLStatementBase(JavaSQLConnection connection)61     public JavaSQLStatementBase(JavaSQLConnection connection) {
62         this.connection = connection;
63         this.logger = new ConnectionLog(connection.getLogger(), ObjectType.STATEMENT);
64         registerProperties();
65     }
66 
getStatementObjectId()67     public int getStatementObjectId() {
68         return logger.getObjectId();
69     }
70 
71     // XComponent
72 
73     @Override
postDisposing()74     protected synchronized void postDisposing() {
75         super.postDisposing();
76         logger.log(LogLevel.FINE, Resources.STR_LOG_CLOSING_STATEMENT);
77         if (jdbcStatement != null) {
78             try {
79                 jdbcStatement.close();
80             } catch (java.sql.SQLException sqlException) {
81                 logger.log(LogLevel.WARNING, sqlException);
82             }
83         }
84         CompHelper.disposeComponent(generatedStatement);
85     }
86 
createStatement()87     protected abstract void createStatement() throws SQLException;
88 
89     // XPropertySet
90 
registerProperties()91     private void registerProperties() {
92         registerProperty(PropertyIds.CURSORNAME.name, PropertyIds.CURSORNAME.id, Type.STRING, (short)0,
93                 new PropertyGetter() {
94                     @Override
95                     public Object getValue() throws WrappedTargetException {
96                         return getCursorName();
97                     }
98                 },
99                 new PropertySetter() {
100                     @Override
101                     public void setValue(Object value) throws PropertyVetoException, IllegalArgumentException, WrappedTargetException {
102                         setCursorName((String)value);
103                     }
104                 }
105         );
106         registerProperty(PropertyIds.ESCAPEPROCESSING.name, PropertyIds.ESCAPEPROCESSING.id, Type.BOOLEAN, (short)0,
107                 new PropertyGetter() {
108                     @Override
109                     public Object getValue() throws WrappedTargetException {
110                         return getEscapeProcessing();
111                     }
112                 },
113                 new PropertySetter() {
114                     @Override
115                     public void setValue(Object value) throws PropertyVetoException, IllegalArgumentException, WrappedTargetException {
116                         setEscapeProcessing((boolean)value);
117                     }
118                 }
119         );
120         registerProperty(PropertyIds.FETCHDIRECTION.name, PropertyIds.FETCHDIRECTION.id, Type.LONG, (short)0,
121                 new PropertyGetter() {
122                     @Override
123                     public Object getValue() throws WrappedTargetException {
124                         return getFetchDirection();
125                     }
126                 },
127                 new PropertySetter() {
128                     @Override
129                     public void setValue(Object value) throws PropertyVetoException, IllegalArgumentException, WrappedTargetException {
130                         setFetchDirection((int)value);
131                     }
132                 }
133         );
134         registerProperty(PropertyIds.FETCHSIZE.name, PropertyIds.FETCHSIZE.id, Type.LONG, (short)0,
135                 new PropertyGetter() {
136                     @Override
137                     public Object getValue() throws WrappedTargetException {
138                         return getFetchSize();
139                     }
140                 },
141                 new PropertySetter() {
142                     @Override
143                     public void setValue(Object value) throws PropertyVetoException, IllegalArgumentException, WrappedTargetException {
144                         setFetchSize((int)value);
145                     }
146                 }
147         );
148         registerProperty(PropertyIds.MAXFIELDSIZE.name, PropertyIds.MAXFIELDSIZE.id, Type.LONG, (short)0,
149                 new PropertyGetter() {
150                     @Override
151                     public Object getValue() throws WrappedTargetException {
152                         return getMaxFieldSize();
153                     }
154                 },
155                 new PropertySetter() {
156                     @Override
157                     public void setValue(Object value) throws PropertyVetoException, IllegalArgumentException, WrappedTargetException {
158                         setMaxFieldSize((int)value);
159                     }
160                 }
161         );
162         registerProperty(PropertyIds.MAXROWS.name, PropertyIds.MAXROWS.id, Type.LONG, (short)0,
163                 new PropertyGetter() {
164                     @Override
165                     public Object getValue() throws WrappedTargetException {
166                         return getMaxRows();
167                     }
168                 },
169                 new PropertySetter() {
170                     @Override
171                     public void setValue(Object value) throws PropertyVetoException, IllegalArgumentException, WrappedTargetException {
172                         setMaxRows((int)value);
173                     }
174                 }
175         );
176         registerProperty(PropertyIds.QUERYTIMEOUT.name, PropertyIds.QUERYTIMEOUT.id, Type.LONG, (short)0,
177                 new PropertyGetter() {
178                     @Override
179                     public Object getValue() throws WrappedTargetException {
180                         return getQueryTimeOut();
181                     }
182                 },
183                 new PropertySetter() {
184                     @Override
185                     public void setValue(Object value) throws WrappedTargetException{
186                         setQueryTimeOut((int)value);
187                     }
188                 }
189         );
190         registerProperty(PropertyIds.RESULTSETCONCURRENCY.name, PropertyIds.RESULTSETCONCURRENCY.id, Type.LONG, (short)0,
191                 new PropertyGetter() {
192                     @Override
193                     public Object getValue() throws WrappedTargetException {
194                         return getResultSetConcurrency();
195                     }
196                 },
197                 new PropertySetter() {
198                     @Override
199                     public void setValue(Object value) throws PropertyVetoException, IllegalArgumentException, WrappedTargetException {
200                         setResultSetConcurrency((int)value);
201                     }
202                 }
203         );
204         registerProperty(PropertyIds.RESULTSETTYPE.name, PropertyIds.RESULTSETTYPE.id, Type.LONG, (short)0,
205                 new PropertyGetter() {
206                     @Override
207                     public Object getValue() throws WrappedTargetException {
208                         return getResultSetType();
209                     }
210                 },
211                 new PropertySetter() {
212                     @Override
213                     public void setValue(Object value) throws PropertyVetoException, IllegalArgumentException, WrappedTargetException {
214                         setResultSetType((int)value);
215                     }
216                 }
217         );
218     }
219 
getCursorName()220     private String getCursorName() throws WrappedTargetException {
221         try {
222             createStatement();
223             // FIXME: C++'s jdbcStatement.getCursorName() doesn't exist in JDBC. We always return a blank string.
224             return "";
225         } catch (SQLException exception) {
226             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
227         }
228     }
229 
setCursorName(String value)230     private synchronized void setCursorName(String value) throws WrappedTargetException {
231         try {
232             createStatement();
233             jdbcStatement.setCursorName(value);
234         } catch (java.sql.SQLException | SQLException exception) {
235             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
236         }
237     }
238 
getEscapeProcessing()239     private boolean getEscapeProcessing() throws WrappedTargetException {
240         try {
241             createStatement();
242             return escapeProcessing;
243         } catch (SQLException exception) {
244             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
245         }
246     }
247 
setEscapeProcessing(boolean value)248     private synchronized void setEscapeProcessing(boolean value) throws WrappedTargetException {
249         escapeProcessing = value;
250         try {
251             createStatement();
252             logger.log(LogLevel.FINE, Resources.STR_LOG_SET_ESCAPE_PROCESSING, value);
253             jdbcStatement.setEscapeProcessing(value);
254         } catch (java.sql.SQLException | SQLException exception) {
255             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
256         }
257     }
258 
getFetchDirection()259     private int getFetchDirection() throws WrappedTargetException {
260         try {
261             createStatement();
262             return jdbcStatement.getFetchDirection();
263         } catch (java.sql.SQLException | SQLException exception) {
264             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
265         }
266     }
267 
setFetchDirection(int value)268     private synchronized void setFetchDirection(int value) throws WrappedTargetException {
269         try {
270             createStatement();
271             logger.log(LogLevel.FINER, Resources.STR_LOG_FETCH_DIRECTION, value);
272             jdbcStatement.setFetchDirection(value);
273         } catch (java.sql.SQLException | SQLException exception) {
274             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
275         }
276     }
277 
getFetchSize()278     private int getFetchSize() throws WrappedTargetException {
279         try {
280             createStatement();
281             return jdbcStatement.getFetchSize();
282         } catch (java.sql.SQLException | SQLException exception) {
283             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
284         }
285     }
286 
setFetchSize(int value)287     private synchronized void setFetchSize(int value) throws WrappedTargetException {
288         try {
289             createStatement();
290             logger.log(LogLevel.FINER, Resources.STR_LOG_FETCH_SIZE, value);
291             jdbcStatement.setFetchSize(value);
292         } catch (java.sql.SQLException | SQLException exception) {
293             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
294         }
295     }
296 
getMaxFieldSize()297     private int getMaxFieldSize() throws WrappedTargetException {
298         try {
299             createStatement();
300             return jdbcStatement.getMaxFieldSize();
301         } catch (java.sql.SQLException | SQLException exception) {
302             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
303         }
304     }
305 
setMaxFieldSize(int value)306     private synchronized void setMaxFieldSize(int value) throws WrappedTargetException {
307         try {
308             createStatement();
309             jdbcStatement.setMaxFieldSize(value);
310         } catch (java.sql.SQLException | SQLException exception) {
311             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
312         }
313     }
314 
getMaxRows()315     private int getMaxRows() throws WrappedTargetException {
316         try {
317             createStatement();
318             return jdbcStatement.getMaxRows();
319         } catch (java.sql.SQLException | SQLException exception) {
320             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
321         }
322     }
323 
setMaxRows(int value)324     private synchronized void setMaxRows(int value) throws WrappedTargetException {
325         try {
326             createStatement();
327             jdbcStatement.setMaxRows(value);
328         } catch (java.sql.SQLException | SQLException exception) {
329             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
330         }
331     }
332 
getQueryTimeOut()333     private int getQueryTimeOut() throws WrappedTargetException {
334         try {
335             createStatement();
336             return jdbcStatement.getQueryTimeout();
337         } catch (java.sql.SQLException | SQLException exception) {
338             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
339         }
340     }
341 
setQueryTimeOut(int value)342     private synchronized void setQueryTimeOut(int value) throws WrappedTargetException {
343         try {
344             createStatement();
345             jdbcStatement.setQueryTimeout(value);
346         } catch (java.sql.SQLException | SQLException exception) {
347             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
348         }
349     }
350 
getResultSetConcurrency()351     private int getResultSetConcurrency() throws WrappedTargetException {
352         try {
353             createStatement();
354             return jdbcStatement.getResultSetConcurrency();
355         } catch (java.sql.SQLException | SQLException exception) {
356             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
357         }
358     }
359 
setResultSetConcurrency(int value)360     private synchronized void setResultSetConcurrency(int value) throws WrappedTargetException {
361         checkDisposed();
362         try {
363             logger.log(LogLevel.FINE, Resources.STR_LOG_RESULT_SET_CONCURRENCY, value);
364             resultSetConcurrency = value;
365             jdbcStatement.close();
366         } catch (java.sql.SQLException exception) {
367             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
368         } finally {
369             jdbcStatement = null;
370         }
371     }
372 
getResultSetType()373     private int getResultSetType() throws WrappedTargetException {
374         try {
375             createStatement();
376             return jdbcStatement.getResultSetType();
377         } catch (java.sql.SQLException | SQLException exception) {
378             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
379         }
380     }
381 
setResultSetType(int value)382     private synchronized void setResultSetType(int value) throws WrappedTargetException {
383         checkDisposed();
384         try {
385             logger.log(LogLevel.FINE, Resources.STR_LOG_RESULT_SET_TYPE, value);
386             resultSetType = value;
387             jdbcStatement.close();
388         } catch (java.sql.SQLException exception) {
389             throw new WrappedTargetException("SQL error", this, Tools.toUnoException(this, exception));
390         } finally {
391             jdbcStatement = null;
392         }
393     }
394 
395     // XCancellable
396 
397     @Override
cancel()398     public void cancel() {
399         try {
400             createStatement();
401             jdbcStatement.cancel();
402         } catch (SQLException sqlException) {
403             logger.log(LogLevel.SEVERE, sqlException);
404         } catch (java.sql.SQLException jdbcException) {
405             logger.log(LogLevel.SEVERE, jdbcException);
406         }
407     }
408 
409     // XCloseable
410 
411     @Override
close()412     public synchronized void close() throws SQLException {
413         checkDisposed();
414         dispose();
415     }
416 
417     // XWarningsSupplier
418 
419     @Override
clearWarnings()420     public synchronized void clearWarnings() throws SQLException {
421         try {
422             createStatement();
423             jdbcStatement.clearWarnings();
424         } catch (java.sql.SQLException sqlException) {
425             throw Tools.toUnoException(this, sqlException);
426         }
427     }
428 
429     @Override
getWarnings()430     public synchronized Object getWarnings() throws SQLException {
431         try {
432             createStatement();
433             java.sql.SQLWarning javaWarning = jdbcStatement.getWarnings();
434             if (javaWarning != null) {
435                 java.lang.Throwable nextException = javaWarning.getCause();
436                 SQLWarning warning = new SQLWarning(javaWarning.getMessage());
437                 warning.Context = this;
438                 warning.SQLState = javaWarning.getSQLState();
439                 warning.ErrorCode = javaWarning.getErrorCode();
440                 warning.NextException = nextException != null ? Tools.toUnoException(this, nextException) : Any.VOID;
441                 return warning;
442             }
443             return Any.VOID;
444         } catch (java.sql.SQLException sqlException) {
445             throw Tools.toUnoException(this, sqlException);
446         }
447     }
448 
449     // XGeneratedResultSet
450 
451     @Override
getGeneratedValues()452     public synchronized com.sun.star.sdbc.XResultSet getGeneratedValues() throws SQLException {
453         logger.log(LogLevel.FINE, Resources.STR_LOG_GENERATED_VALUES);
454         createStatement();
455         java.sql.ResultSet jdbcResultSet = null;
456         try {
457             jdbcResultSet = jdbcStatement.getGeneratedKeys();
458         } catch (java.sql.SQLException jdbcException) {
459         }
460 
461         XResultSet resultSet = null;
462         if (jdbcResultSet != null) {
463             resultSet = new JavaSQLResultSet(jdbcResultSet, connection, this);
464         } else {
465             if (connection != null && connection.isAutoRetrievingEnabled()) {
466                 String statement = connection.getTransformedGeneratedStatement(sqlStatement);
467                 if (!statement.isEmpty()) {
468                     logger.log(LogLevel.FINER, Resources.STR_LOG_GENERATED_VALUES_FALLBACK, statement);
469                     CompHelper.disposeComponent(generatedStatement);
470                     generatedStatement = connection.createStatement();
471                     resultSet = generatedStatement.executeQuery(statement);
472                 }
473             }
474         }
475         return resultSet;
476     }
477 
478     // XMultipleResults
479 
480     @Override
getMoreResults()481     public boolean getMoreResults() throws SQLException {
482         try {
483             createStatement();
484             return jdbcStatement.getMoreResults();
485         } catch (java.sql.SQLException sqlException) {
486             throw Tools.toUnoException(this, sqlException);
487         }
488     }
489 
490     @Override
getResultSet()491     public XResultSet getResultSet() throws SQLException {
492         try {
493             createStatement();
494             java.sql.ResultSet jdbcResultSet = jdbcStatement.getResultSet();
495             if (jdbcResultSet != null) {
496                 return new JavaSQLResultSet(jdbcResultSet, connection, this);
497             } else {
498                 return null;
499             }
500         } catch (java.sql.SQLException sqlException) {
501             throw Tools.toUnoException(this, sqlException);
502         }
503     }
504 
505     @Override
getUpdateCount()506     public int getUpdateCount() throws SQLException {
507         try {
508             createStatement();
509             int count = jdbcStatement.getUpdateCount();
510             logger.log(LogLevel.FINER, Resources.STR_LOG_UPDATE_COUNT, count);
511             return count;
512         } catch (java.sql.SQLException sqlException) {
513             throw Tools.toUnoException(this, sqlException);
514         }
515     }
516 }
517