1 | /* |
2 | |
3 | Derby - Class org.apache.derby.jdbc.Driver20 |
4 | |
5 | Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | 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, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.jdbc; |
22 | |
23 | import org.apache.derby.iapi.reference.Attribute; |
24 | import org.apache.derby.iapi.reference.MessageId; |
25 | import org.apache.derby.iapi.reference.Property; |
26 | import org.apache.derby.iapi.reference.SQLState; |
27 | |
28 | import org.apache.derby.impl.jdbc.EmbedConnection; |
29 | |
30 | import org.apache.derby.iapi.services.sanity.SanityManager; |
31 | import org.apache.derby.iapi.error.StandardException; |
32 | import org.apache.derby.iapi.sql.ResultSet; |
33 | import org.apache.derby.iapi.jdbc.BrokeredConnection; |
34 | import org.apache.derby.iapi.jdbc.BrokeredConnectionControl; |
35 | import org.apache.derby.iapi.services.i18n.MessageService; |
36 | import org.apache.derby.iapi.services.monitor.Monitor; |
37 | import org.apache.derby.iapi.services.io.FormatableProperties; |
38 | |
39 | import org.apache.derby.impl.jdbc.*; |
40 | |
41 | import java.sql.Connection; |
42 | import java.sql.SQLException; |
43 | import java.sql.Driver; |
44 | import java.sql.DriverManager; |
45 | import java.sql.DriverPropertyInfo; |
46 | |
47 | import java.util.Properties; |
48 | |
49 | /** |
50 | This class extends the local JDBC driver in order to determine at JBMS |
51 | boot-up if the JVM that runs us does support JDBC 2.0. If it is the case |
52 | then we will load the appropriate class(es) that have JDBC 2.0 new public |
53 | methods and sql types. |
54 | */ |
55 | |
56 | public class Driver20 extends InternalDriver implements Driver { |
57 | |
58 | private static final String[] BOOLEAN_CHOICES = {"false", "true"}; |
59 | |
60 | private Class antiGCDriverManager; |
61 | |
62 | /* |
63 | ** Methods from ModuleControl |
64 | */ |
65 | |
66 | public void boot(boolean create, Properties properties) throws StandardException { |
67 | |
68 | super.boot(create, properties); |
69 | |
70 | // Register with the driver manager |
71 | try { |
72 | DriverManager.registerDriver(this); |
73 | |
74 | // hold onto the driver manager to avoid it being garbage collected. |
75 | // make sure the class is loaded by using .class |
76 | antiGCDriverManager = java.sql.DriverManager.class; |
77 | |
78 | } catch (SQLException e) { |
79 | throw StandardException.newException(SQLState.JDBC_DRIVER_REGISTER, e); |
80 | } |
81 | } |
82 | |
83 | public void stop() { |
84 | |
85 | super.stop(); |
86 | |
87 | try { |
88 | DriverManager.deregisterDriver(this); |
89 | } catch (SQLException sqle) { |
90 | // just do nothing |
91 | } |
92 | } |
93 | |
94 | /** |
95 | * Get a new nested connection. |
96 | * |
97 | * @param conn The EmbedConnection. |
98 | * |
99 | * @return A nested connection object. |
100 | * |
101 | */ |
102 | public Connection getNewNestedConnection(EmbedConnection conn) |
103 | { |
104 | return new EmbedConnection(conn); |
105 | } |
106 | |
107 | /* |
108 | Methods to be overloaded in sub-implementations such as |
109 | a tracing driver. |
110 | */ |
111 | public EmbedConnection getNewEmbedConnection(String url, Properties info) |
112 | throws SQLException |
113 | { |
114 | // make a new local connection with a new transaction resource |
115 | return new EmbedConnection(this, url, info); |
116 | } |
117 | |
118 | /** |
119 | @exception SQLException if fails to create statement |
120 | */ |
121 | public java.sql.PreparedStatement |
122 | newEmbedPreparedStatement (EmbedConnection conn, |
123 | String stmt, |
124 | boolean forMetaData, |
125 | int resultSetType, |
126 | int resultSetConcurrency, |
127 | int resultSetHoldability, |
128 | int autoGeneratedKeys, |
129 | int[] columnIndexes, |
130 | String[] columnNames) |
131 | throws SQLException |
132 | { |
133 | return new EmbedPreparedStatement20(conn, stmt, forMetaData, |
134 | resultSetType, resultSetConcurrency, resultSetHoldability, |
135 | autoGeneratedKeys, columnIndexes, columnNames); |
136 | } |
137 | |
138 | /** |
139 | @exception SQLException if fails to create statement |
140 | */ |
141 | public java.sql.CallableStatement newEmbedCallableStatement( |
142 | EmbedConnection conn, |
143 | String stmt, |
144 | int resultSetType, |
145 | int resultSetConcurrency, |
146 | int resultSetHoldability) |
147 | throws SQLException |
148 | { |
149 | return new EmbedCallableStatement20(conn, stmt, |
150 | resultSetType, resultSetConcurrency, resultSetHoldability); |
151 | } |
152 | |
153 | public org.apache.derby.impl.jdbc.EmbedResultSet |
154 | newEmbedResultSet(EmbedConnection conn, ResultSet results, boolean forMetaData, org.apache.derby.impl.jdbc.EmbedStatement statement, boolean isAtomic) |
155 | throws SQLException |
156 | { |
157 | return new EmbedResultSet20(conn, results, forMetaData, statement, |
158 | isAtomic); |
159 | } |
160 | public BrokeredConnection newBrokeredConnection(BrokeredConnectionControl control) { |
161 | |
162 | return new BrokeredConnection(control); |
163 | } |
164 | /** |
165 | * <p>The getPropertyInfo method is intended to allow a generic GUI tool to |
166 | * discover what properties it should prompt a human for in order to get |
167 | * enough information to connect to a database. Note that depending on |
168 | * the values the human has supplied so far, additional values may become |
169 | * necessary, so it may be necessary to iterate though several calls |
170 | * to getPropertyInfo. |
171 | * |
172 | * @param url The URL of the database to connect to. |
173 | * @param info A proposed list of tag/value pairs that will be sent on |
174 | * connect open. |
175 | * @return An array of DriverPropertyInfo objects describing possible |
176 | * properties. This array may be an empty array if no properties |
177 | * are required. |
178 | * @exception SQLException if a database-access error occurs. |
179 | */ |
180 | public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { |
181 | |
182 | // RESOLVE other properties should be added into this method in the future ... |
183 | |
184 | if (info != null) { |
185 | if (Boolean.valueOf(info.getProperty(Attribute.SHUTDOWN_ATTR)).booleanValue()) { |
186 | |
187 | // no other options possible when shutdown is set to be true |
188 | return new DriverPropertyInfo[0]; |
189 | } |
190 | } |
191 | |
192 | // at this point we have databaseName, |
193 | |
194 | String dbname = InternalDriver.getDatabaseName(url, info); |
195 | |
196 | // convert the ;name=value attributes in the URL into |
197 | // properties. |
198 | FormatableProperties finfo = getAttributes(url, info); |
199 | info = null; // ensure we don't use this reference directly again. |
200 | boolean encryptDB = Boolean.valueOf(finfo.getProperty(Attribute.DATA_ENCRYPTION)).booleanValue(); |
201 | String encryptpassword = finfo.getProperty(Attribute.BOOT_PASSWORD); |
202 | |
203 | if (dbname.length() == 0 || (encryptDB = true && encryptpassword == null)) { |
204 | |
205 | // with no database name we can have shutdown or a database name |
206 | |
207 | // In future, if any new attribute info needs to be included in this |
208 | // method, it just has to be added to either string or boolean or secret array |
209 | // depending on whether it accepts string or boolean or secret(ie passwords) value. |
210 | |
211 | String[][] connStringAttributes = { |
212 | {Attribute.DBNAME_ATTR, MessageId.CONN_DATABASE_IDENTITY}, |
213 | {Attribute.CRYPTO_PROVIDER, MessageId.CONN_CRYPTO_PROVIDER}, |
214 | {Attribute.CRYPTO_ALGORITHM, MessageId.CONN_CRYPTO_ALGORITHM}, |
215 | {Attribute.CRYPTO_KEY_LENGTH, MessageId.CONN_CRYPTO_KEY_LENGTH}, |
216 | {Attribute.CRYPTO_EXTERNAL_KEY, MessageId.CONN_CRYPTO_EXTERNAL_KEY}, |
217 | {Attribute.TERRITORY, MessageId.CONN_LOCALE}, |
218 | {Attribute.USERNAME_ATTR, MessageId.CONN_USERNAME_ATTR}, |
219 | {Attribute.LOG_DEVICE, MessageId.CONN_LOG_DEVICE}, |
220 | {Attribute.ROLL_FORWARD_RECOVERY_FROM, MessageId.CONN_ROLL_FORWARD_RECOVERY_FROM}, |
221 | {Attribute.CREATE_FROM, MessageId.CONN_CREATE_FROM}, |
222 | {Attribute.RESTORE_FROM, MessageId.CONN_RESTORE_FROM}, |
223 | }; |
224 | |
225 | String[][] connBooleanAttributes = { |
226 | {Attribute.SHUTDOWN_ATTR, MessageId.CONN_SHUT_DOWN_CLOUDSCAPE}, |
227 | {Attribute.CREATE_ATTR, MessageId.CONN_CREATE_DATABASE}, |
228 | {Attribute.DATA_ENCRYPTION, MessageId.CONN_DATA_ENCRYPTION}, |
229 | {Attribute.UPGRADE_ATTR, MessageId.CONN_UPGRADE_DATABASE}, |
230 | }; |
231 | |
232 | String[][] connStringSecretAttributes = { |
233 | {Attribute.BOOT_PASSWORD, MessageId.CONN_BOOT_PASSWORD}, |
234 | {Attribute.PASSWORD_ATTR, MessageId.CONN_PASSWORD_ATTR}, |
235 | }; |
236 | |
237 | |
238 | DriverPropertyInfo[] optionsNoDB = new DriverPropertyInfo[connStringAttributes.length+ |
239 | connBooleanAttributes.length+ |
240 | connStringSecretAttributes.length]; |
241 | |
242 | int attrIndex = 0; |
243 | for( int i = 0; i < connStringAttributes.length; i++, attrIndex++ ) |
244 | { |
245 | optionsNoDB[attrIndex] = new DriverPropertyInfo(connStringAttributes[i][0], |
246 | finfo.getProperty(connStringAttributes[i][0])); |
247 | optionsNoDB[attrIndex].description = MessageService.getTextMessage(connStringAttributes[i][1]); |
248 | } |
249 | |
250 | optionsNoDB[0].choices = Monitor.getMonitor().getServiceList(Property.DATABASE_MODULE); |
251 | // since database name is not stored in FormatableProperties, we |
252 | // assign here explicitly |
253 | optionsNoDB[0].value = dbname; |
254 | |
255 | for( int i = 0; i < connStringSecretAttributes.length; i++, attrIndex++ ) |
256 | { |
257 | optionsNoDB[attrIndex] = new DriverPropertyInfo(connStringSecretAttributes[i][0], |
258 | (finfo.getProperty(connStringSecretAttributes[i][0]) == null? "" : "****")); |
259 | optionsNoDB[attrIndex].description = MessageService.getTextMessage(connStringSecretAttributes[i][1]); |
260 | } |
261 | |
262 | for( int i = 0; i < connBooleanAttributes.length; i++, attrIndex++ ) |
263 | { |
264 | optionsNoDB[attrIndex] = new DriverPropertyInfo(connBooleanAttributes[i][0], |
265 | Boolean.valueOf(finfo == null? "" : finfo.getProperty(connBooleanAttributes[i][0])).toString()); |
266 | optionsNoDB[attrIndex].description = MessageService.getTextMessage(connBooleanAttributes[i][1]); |
267 | optionsNoDB[attrIndex].choices = BOOLEAN_CHOICES; |
268 | } |
269 | |
270 | return optionsNoDB; |
271 | } |
272 | |
273 | return new DriverPropertyInfo[0]; |
274 | } |
275 | } |