Source code: org/apache/derby/jdbc/ClientDriver.java
1 /*
2
3 Derby - Class org.apache.derby.jdbc.ClientDriver
4
5 Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where 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.client.am.Configuration;
24 import org.apache.derby.client.am.ResourceUtilities;
25 import org.apache.derby.client.am.SqlException;
26 import org.apache.derby.client.am.Utils;
27 import org.apache.derby.client.am.Version;
28 import org.apache.derby.client.resources.ResourceKeys;
29
30
31 public class ClientDriver implements java.sql.Driver {
32 private transient int traceFileSuffixIndex_ = 0;
33
34 private final static int DERBY_REMOTE_PROTOCOL = 1;
35
36 static private SqlException exceptionsOnLoadDriver__ = null;
37 // Keep track of the registere driver so that we can deregister it if we're a stored proc.
38 static private ClientDriver registeredDriver__ = null;
39
40 static {
41 // This may possibly hit the race-condition bug of java 1.1.
42 // The Configuration static clause should execute before the following line does.
43 if (Configuration.exceptionsOnLoadResources != null) {
44 exceptionsOnLoadDriver__ =
45 Utils.accumulateSQLException(Configuration.exceptionsOnLoadResources,
46 exceptionsOnLoadDriver__);
47 }
48 try {
49 registeredDriver__ = new ClientDriver();
50 java.sql.DriverManager.registerDriver(registeredDriver__);
51 } catch (java.sql.SQLException e) {
52 // A null log writer is passed, because jdbc 1 sql exceptions are automatically traced
53 exceptionsOnLoadDriver__ =
54 new SqlException(null, "Error occurred while trying to register Dnc driver with JDBC 1 Driver Manager");
55 exceptionsOnLoadDriver__.setNextException(e);
56 }
57 }
58
59 public ClientDriver() {
60 }
61
62 public java.sql.Connection connect(String url,
63 java.util.Properties properties) throws java.sql.SQLException {
64 if (exceptionsOnLoadDriver__ != null) {
65 throw exceptionsOnLoadDriver__;
66 }
67
68 if (properties == null) {
69 properties = new java.util.Properties();
70 }
71
72 java.util.StringTokenizer urlTokenizer =
73 new java.util.StringTokenizer(url, "/:= \t\n\r\f", true);
74
75 int protocol = tokenizeProtocol(url, urlTokenizer);
76 if (protocol == 0) {
77 return null; // unrecognized database URL prefix.
78 }
79
80 String slashOrNull = null;
81 if (protocol == DERBY_REMOTE_PROTOCOL) {
82 try {
83 slashOrNull = urlTokenizer.nextToken(":/");
84 } catch (java.util.NoSuchElementException e) {
85 // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
86 throw new SqlException(null, e, "Invalid database url syntax: " + url);
87 }
88 }
89 String server = tokenizeServerName(urlTokenizer, url); // "/server"
90 int port = tokenizeOptionalPortNumber(urlTokenizer, url); // "[:port]/"
91 if (port == 0) {
92 port = ClientDataSource.propertyDefault_portNumber;
93 }
94
95 // longDatabase is the databaseName and attributes. This will be
96 // sent to network server as the databaseName
97 String database = tokenizeDatabase(urlTokenizer, url); // "database"
98 java.util.Properties augmentedProperties = tokenizeURLProperties(url, properties);
99
100
101 int traceLevel;
102 try {
103 traceLevel = ClientDataSource.getTraceLevel(augmentedProperties);
104 } catch (java.lang.NumberFormatException e) {
105 // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
106 throw new SqlException(null, e, "trouble reading traceLevel connection property");
107 }
108
109 // Jdbc 1 connections will write driver trace info on a
110 // driver-wide basis using the jdbc 1 driver manager log writer.
111 // This log writer may be narrowed to the connection-level
112 // This log writer will be passed to the agent constructor.
113 org.apache.derby.client.am.LogWriter dncLogWriter =
114 ClientDataSource.computeDncLogWriterForNewConnection(java.sql.DriverManager.getLogWriter(),
115 ClientDataSource.getTraceDirectory(augmentedProperties),
116 ClientDataSource.getTraceFile(augmentedProperties),
117 ClientDataSource.getTraceFileAppend(augmentedProperties),
118 traceLevel,
119 "_driver",
120 traceFileSuffixIndex_++);
121
122 org.apache.derby.client.net.NetConnection conn =
123 new org.apache.derby.client.net.NetConnection((org.apache.derby.client.net.NetLogWriter) dncLogWriter,
124 java.sql.DriverManager.getLoginTimeout(),
125 server,
126 port,
127 database,
128 augmentedProperties);
129 return conn;
130 }
131
132 public boolean acceptsURL(String url) throws java.sql.SQLException {
133 java.util.StringTokenizer urlTokenizer = new java.util.StringTokenizer(url, "/:=; \t\n\r\f", true);
134 int protocol = tokenizeProtocol(url, urlTokenizer);
135 return protocol != 0;
136 }
137
138 public java.sql.DriverPropertyInfo[] getPropertyInfo(String url,
139 java.util.Properties properties) throws java.sql.SQLException {
140 java.sql.DriverPropertyInfo driverPropertyInfo[] = new java.sql.DriverPropertyInfo[2];
141
142 // If there are no properties set already,
143 // then create a dummy properties just to make the calls go thru.
144 if (properties == null) {
145 properties = new java.util.Properties();
146 }
147
148 driverPropertyInfo[0] =
149 new java.sql.DriverPropertyInfo(ClientDataSource.propertyKey_user,
150 properties.getProperty(ClientDataSource.propertyKey_user, ClientDataSource.propertyDefault_user));
151
152 driverPropertyInfo[1] =
153 new java.sql.DriverPropertyInfo(ClientDataSource.propertyKey_password,
154 properties.getProperty(ClientDataSource.propertyKey_password));
155
156 driverPropertyInfo[0].description =
157 ResourceUtilities.getResource(ResourceKeys.propertyDescription__user);
158 driverPropertyInfo[1].description =
159 ResourceUtilities.getResource(ResourceKeys.propertyDescription__password);
160
161 driverPropertyInfo[0].required = true;
162 driverPropertyInfo[1].required = false; // depending on the security mechanism
163
164 return driverPropertyInfo;
165 }
166
167 public int getMajorVersion() {
168 return Version.getMajorVersion();
169 }
170
171 public int getMinorVersion() {
172 return Version.getMinorVersion();
173 }
174
175 public boolean jdbcCompliant() {
176 return Configuration.jdbcCompliant;
177 }
178
179 // ----------------helper methods---------------------------------------------
180
181 // Tokenize one of the following:
182 // "jdbc:derby:"
183 // and return 0 if the protcol is unrecognized
184 // return DERBY_PROTOCOL for "jdbc:derby"
185 private static int tokenizeProtocol(String url, java.util.StringTokenizer urlTokenizer) throws SqlException {
186 // Is this condition necessary, StringTokenizer constructor may do this for us
187 if (url == null) {
188 return 0;
189 }
190
191 if (urlTokenizer == null) {
192 return 0;
193 }
194
195 try {
196 String jdbc = urlTokenizer.nextToken(":");
197 if (!jdbc.equals("jdbc")) {
198 return 0;
199 }
200 if (!urlTokenizer.nextToken(":").equals(":")) {
201 return 0; // Skip over the first colon in jdbc:derby:
202 }
203 String dbname = urlTokenizer.nextToken(":");
204 int protocol = 0;
205 if (dbname.equals("derby") && (url.indexOf("derby://") != -1)) {
206 // For Derby AS need to check for // since jdbc:derby: is also the
207 // embedded prefix
208 protocol = DERBY_REMOTE_PROTOCOL;
209 } else {
210 return 0;
211 }
212
213 if (!urlTokenizer.nextToken(":").equals(":")) {
214 return 0; // Skip over the second colon in jdbc:derby:
215 }
216
217 return protocol;
218 } catch (java.util.NoSuchElementException e) {
219 return 0;
220 }
221 }
222
223 // tokenize "/server" from URL jdbc:derby://server:port/
224 // returns server name
225 private static String tokenizeServerName(java.util.StringTokenizer urlTokenizer,
226 String url) throws SqlException {
227 try {
228 if (!urlTokenizer.nextToken("/").equals("/"))
229 // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
230 {
231 throw new SqlException(null, "Invalid database url syntax: " + url);
232 }
233 return urlTokenizer.nextToken("/:");
234 } catch (java.util.NoSuchElementException e) {
235 // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
236 throw new SqlException(null, e, "Invalid database url syntax: " + url);
237 }
238 }
239
240 // tokenize "[:portNumber]/" from URL jdbc:derby://server[:port]/
241 // returns the portNumber or zero if portNumber is not specified.
242 private static int tokenizeOptionalPortNumber(java.util.StringTokenizer urlTokenizer,
243 String url) throws SqlException {
244 try {
245 String firstToken = urlTokenizer.nextToken(":/");
246 if (firstToken.equals(":")) {
247 String port = urlTokenizer.nextToken("/");
248 if (!urlTokenizer.nextToken("/").equals("/")) {
249 // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
250 throw new SqlException(null, "Invalid database url syntax: " + url);
251 }
252 return Integer.parseInt(port);
253 } else if (firstToken.equals("/")) {
254 return 0;
255 } else {
256 // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
257 throw new SqlException(null, "Invalid database url syntax: " + url);
258 }
259 } catch (java.util.NoSuchElementException e) {
260 // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
261 throw new SqlException(null, e, "Invalid database url syntax: " + url);
262 }
263 }
264
265 //return database name and attributes
266 private static String tokenizeDatabase(java.util.StringTokenizer urlTokenizer,
267 String url) throws SqlException {
268 try {
269 String databaseName = urlTokenizer.nextToken(" \t\n\r\f");
270 return databaseName;
271 } catch (java.util.NoSuchElementException e) {
272 // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
273 throw new SqlException(null, e, "Invalid database url syntax: " + url);
274 }
275 }
276
277 private static java.util.Properties tokenizeURLProperties(String url,
278 java.util.Properties properties)
279 throws SqlException {
280 String attributeString = null;
281 int attributeIndex = -1;
282
283 if ((url != null) &&
284 ((attributeIndex = url.indexOf(";")) != -1)) {
285 attributeString = url.substring(attributeIndex);
286 }
287 return ClientDataSource.tokenizeAttributes(attributeString, properties);
288 }
289
290
291 }
292
293
294