KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > jdbc > ClientDriver


1 /*
2
3    Derby - Class org.apache.derby.jdbc.ClientDriver
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20 */

21
22 package org.apache.derby.jdbc;
23
24 import java.util.Enumeration JavaDoc;
25 import java.util.Properties JavaDoc;
26 import java.sql.SQLException JavaDoc;
27 import org.apache.derby.client.am.Configuration;
28 import org.apache.derby.client.am.SqlException;
29 import org.apache.derby.client.am.Utils;
30 import org.apache.derby.client.am.Version;
31 import org.apache.derby.client.am.ClientJDBCObjectFactory;
32 import org.apache.derby.client.am.ClientMessageId;
33 import org.apache.derby.client.net.ClientJDBCObjectFactoryImpl;
34 import org.apache.derby.shared.common.reference.Attribute;
35 import org.apache.derby.shared.common.reference.SQLState;
36 import org.apache.derby.shared.common.reference.MessageId;
37
38
39 public class ClientDriver implements java.sql.Driver JavaDoc {
40     private transient int traceFileSuffixIndex_ = 0;
41
42     private final static int DERBY_REMOTE_PROTOCOL = 1;
43     
44     private static ClientJDBCObjectFactory factoryObject = null;
45
46     static private SQLException JavaDoc exceptionsOnLoadDriver__ = null;
47     // Keep track of the registere driver so that we can deregister it if we're a stored proc.
48
static private ClientDriver registeredDriver__ = null;
49
50     static {
51         // This may possibly hit the race-condition bug of java 1.1.
52
// The Configuration static clause should execute before the following line does.
53
if (Configuration.exceptionsOnLoadResources != null) {
54             exceptionsOnLoadDriver__ =
55                     Utils.accumulateSQLException(
56                             Configuration.exceptionsOnLoadResources.getSQLException(),
57                             exceptionsOnLoadDriver__);
58         }
59         try {
60             registeredDriver__ = new ClientDriver();
61             java.sql.DriverManager.registerDriver(registeredDriver__);
62         } catch (java.sql.SQLException JavaDoc e) {
63             // A null log writer is passed, because jdbc 1 sql exceptions are automatically traced
64
exceptionsOnLoadDriver__ =
65                     new SqlException(null,
66                         new ClientMessageId(SQLState.JDBC_DRIVER_REGISTER)).getSQLException();
67             exceptionsOnLoadDriver__.setNextException(e);
68         }
69     }
70
71     public ClientDriver() {
72     }
73
74     public java.sql.Connection JavaDoc connect(String JavaDoc url,
75                                        java.util.Properties JavaDoc properties) throws java.sql.SQLException JavaDoc {
76         org.apache.derby.client.net.NetConnection conn;
77         try {
78             if (exceptionsOnLoadDriver__ != null) {
79                 throw exceptionsOnLoadDriver__;
80             }
81
82             if (properties == null) {
83                 properties = new java.util.Properties JavaDoc();
84             }
85
86             java.util.StringTokenizer JavaDoc urlTokenizer =
87                     new java.util.StringTokenizer JavaDoc(url, "/:= \t\n\r\f", true);
88
89             int protocol = tokenizeProtocol(url, urlTokenizer);
90             if (protocol == 0) {
91                 return null; // unrecognized database URL prefix.
92
}
93
94             String JavaDoc slashOrNull = null;
95             if (protocol == DERBY_REMOTE_PROTOCOL) {
96                 try {
97                     slashOrNull = urlTokenizer.nextToken(":/");
98                 } catch (java.util.NoSuchElementException JavaDoc e) {
99                     // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
100
throw new SqlException(null,
101                         new ClientMessageId(SQLState.MALFORMED_URL),
102                         url, e);
103                 }
104             }
105             String JavaDoc server = tokenizeServerName(urlTokenizer, url); // "/server"
106
int port = tokenizeOptionalPortNumber(urlTokenizer, url); // "[:port]/"
107
if (port == 0) {
108                 port = ClientDataSource.propertyDefault_portNumber;
109             }
110
111             // database is the database name and attributes. This will be
112
// sent to network server as the databaseName
113
String JavaDoc database = tokenizeDatabase(urlTokenizer, url); // "database"
114
java.util.Properties JavaDoc augmentedProperties = tokenizeURLProperties(url, properties);
115             database = appendDatabaseAttributes(database,augmentedProperties);
116
117             int traceLevel;
118             try {
119                 traceLevel = ClientDataSource.getTraceLevel(augmentedProperties);
120             } catch (java.lang.NumberFormatException JavaDoc e) {
121                 // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
122
throw new SqlException(null,
123                     new ClientMessageId(SQLState.TRACELEVEL_FORMAT_INVALID), e);
124             }
125
126             // Jdbc 1 connections will write driver trace info on a
127
// driver-wide basis using the jdbc 1 driver manager log writer.
128
// This log writer may be narrowed to the connection-level
129
// This log writer will be passed to the agent constructor.
130
org.apache.derby.client.am.LogWriter dncLogWriter =
131                     ClientDataSource.computeDncLogWriterForNewConnection(java.sql.DriverManager.getLogWriter(),
132                             ClientDataSource.getTraceDirectory(augmentedProperties),
133                             ClientDataSource.getTraceFile(augmentedProperties),
134                             ClientDataSource.getTraceFileAppend(augmentedProperties),
135                             traceLevel,
136                             "_driver",
137                             traceFileSuffixIndex_++);
138             
139             
140             conn = (org.apache.derby.client.net.NetConnection)getFactory().
141                     newNetConnection((org.apache.derby.client.net.NetLogWriter)
142                     dncLogWriter,
143                     java.sql.DriverManager.getLoginTimeout(),
144                     server,
145                     port,
146                     database,
147                     augmentedProperties);
148         } catch(SqlException se) {
149             throw se.getSQLException();
150         }
151         
152         if(conn.isConnectionNull())
153             return null;
154         
155         return conn;
156     }
157
158     /**
159      * Append attributes to the database name except for user/password
160      * which are sent as part of the protocol.
161      * Other attributes will be sent to the server with the database name
162      * Assumes augmentedProperties is not null
163      *
164      * @param database - Short database name
165      * @param augmentedProperties - Set of properties to append as attributes
166      * @return databaseName + attributes (e.g. mydb;create=true)
167      */

168     private String JavaDoc appendDatabaseAttributes(String JavaDoc database, Properties JavaDoc augmentedProperties) {
169     
170         StringBuffer JavaDoc longDatabase = new StringBuffer JavaDoc(database);
171         for (Enumeration JavaDoc keys = augmentedProperties.keys(); keys.hasMoreElements() ;)
172         {
173             String JavaDoc key = (String JavaDoc) keys.nextElement();
174             if (key.equals(Attribute.USERNAME_ATTR) ||
175                 key.equals(Attribute.PASSWORD_ATTR))
176                 continue;
177             longDatabase.append(";" + key + "=" + augmentedProperties.getProperty(key));
178         }
179         return longDatabase.toString();
180     }
181
182     public boolean acceptsURL(String JavaDoc url) throws java.sql.SQLException JavaDoc {
183         try
184         {
185             java.util.StringTokenizer JavaDoc urlTokenizer =
186                     new java.util.StringTokenizer JavaDoc(url, "/:=; \t\n\r\f", true);
187             int protocol = tokenizeProtocol(url, urlTokenizer);
188             return protocol != 0;
189         }
190         catch ( SqlException se )
191         {
192             throw se.getSQLException();
193         }
194     }
195
196     public java.sql.DriverPropertyInfo JavaDoc[] getPropertyInfo(String JavaDoc url,
197                                                          java.util.Properties JavaDoc properties) throws java.sql.SQLException JavaDoc {
198         java.sql.DriverPropertyInfo JavaDoc driverPropertyInfo[] = new java.sql.DriverPropertyInfo JavaDoc[2];
199
200         // If there are no properties set already,
201
// then create a dummy properties just to make the calls go thru.
202
if (properties == null) {
203             properties = new java.util.Properties JavaDoc();
204         }
205
206         driverPropertyInfo[0] =
207                 new java.sql.DriverPropertyInfo JavaDoc(Attribute.USERNAME_ATTR,
208                         properties.getProperty(Attribute.USERNAME_ATTR, ClientDataSource.propertyDefault_user));
209
210         driverPropertyInfo[1] =
211                 new java.sql.DriverPropertyInfo JavaDoc(Attribute.PASSWORD_ATTR,
212                         properties.getProperty(Attribute.PASSWORD_ATTR));
213
214         driverPropertyInfo[0].description =
215             SqlException.getMessageUtil().getTextMessage(
216                 MessageId.CONN_USERNAME_DESCRIPTION);
217         driverPropertyInfo[1].description =
218             SqlException.getMessageUtil().getTextMessage(
219                 MessageId.CONN_PASSWORD_DESCRIPTION);
220
221         driverPropertyInfo[0].required = true;
222         driverPropertyInfo[1].required = false; // depending on the security mechanism
223

224         return driverPropertyInfo;
225     }
226
227     public int getMajorVersion() {
228         return Version.getMajorVersion();
229     }
230
231     public int getMinorVersion() {
232         return Version.getMinorVersion();
233     }
234
235     public boolean jdbcCompliant() {
236         return Configuration.jdbcCompliant;
237     }
238
239     // ----------------helper methods---------------------------------------------
240

241     // Tokenize one of the following:
242
// "jdbc:derby:"
243
// and return 0 if the protcol is unrecognized
244
// return DERBY_PROTOCOL for "jdbc:derby"
245
private static int tokenizeProtocol(String JavaDoc url, java.util.StringTokenizer JavaDoc urlTokenizer) throws SqlException {
246         // Is this condition necessary, StringTokenizer constructor may do this for us
247
if (url == null) {
248             return 0;
249         }
250
251         if (urlTokenizer == null) {
252             return 0;
253         }
254
255         try {
256             String JavaDoc jdbc = urlTokenizer.nextToken(":");
257             if (!jdbc.equals("jdbc")) {
258                 return 0;
259             }
260             if (!urlTokenizer.nextToken(":").equals(":")) {
261                 return 0; // Skip over the first colon in jdbc:derby:
262
}
263             String JavaDoc dbname = urlTokenizer.nextToken(":");
264             int protocol = 0;
265             if (dbname.equals("derby") && (url.indexOf("derby://") != -1)) {
266                 // For Derby AS need to check for // since jdbc:derby: is also the
267
// embedded prefix
268
protocol = DERBY_REMOTE_PROTOCOL;
269             } else {
270                 return 0;
271             }
272
273             if (!urlTokenizer.nextToken(":").equals(":")) {
274                 return 0; // Skip over the second colon in jdbc:derby:
275
}
276
277             return protocol;
278         } catch (java.util.NoSuchElementException JavaDoc e) {
279             return 0;
280         }
281     }
282
283     // tokenize "/server" from URL jdbc:derby://server:port/
284
// returns server name
285
private static String JavaDoc tokenizeServerName(java.util.StringTokenizer JavaDoc urlTokenizer,
286                                              String JavaDoc url) throws SqlException {
287         try {
288             if (!urlTokenizer.nextToken("/").equals("/"))
289             // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
290
{
291                 throw new SqlException(null,
292                     new ClientMessageId(SQLState.MALFORMED_URL), url);
293             }
294             return urlTokenizer.nextToken("/:");
295         } catch (java.util.NoSuchElementException JavaDoc e) {
296             // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
297
throw new SqlException(null,
298                     new ClientMessageId(SQLState.MALFORMED_URL), url);
299         }
300     }
301
302     // tokenize "[:portNumber]/" from URL jdbc:derby://server[:port]/
303
// returns the portNumber or zero if portNumber is not specified.
304
private static int tokenizeOptionalPortNumber(java.util.StringTokenizer JavaDoc urlTokenizer,
305                                                   String JavaDoc url) throws SqlException {
306         try {
307             String JavaDoc firstToken = urlTokenizer.nextToken(":/");
308             if (firstToken.equals(":")) {
309                 String JavaDoc port = urlTokenizer.nextToken("/");
310                 if (!urlTokenizer.nextToken("/").equals("/")) {
311                     // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
312
throw new SqlException(null,
313                         new ClientMessageId(SQLState.MALFORMED_URL), url);
314                 }
315                 return Integer.parseInt(port);
316             } else if (firstToken.equals("/")) {
317                 return 0;
318             } else {
319                 // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
320
throw new SqlException(null,
321                     new ClientMessageId(SQLState.MALFORMED_URL), url);
322             }
323         } catch (java.util.NoSuchElementException JavaDoc e) {
324             // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
325
throw new SqlException(null,
326                 new ClientMessageId(SQLState.MALFORMED_URL), url, e);
327         }
328     }
329
330     //return database name
331
private static String JavaDoc tokenizeDatabase(java.util.StringTokenizer JavaDoc urlTokenizer,
332                                            String JavaDoc url) throws SqlException {
333         try {
334             // DERBY-618 - database name can contain spaces in the path
335
String JavaDoc databaseName = urlTokenizer.nextToken("\t\n\r\f;");
336             return databaseName;
337         } catch (java.util.NoSuchElementException JavaDoc e) {
338             // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
339
throw new SqlException(null,
340                 new ClientMessageId(SQLState.MALFORMED_URL), url, e);
341         }
342     }
343
344     private static java.util.Properties JavaDoc tokenizeURLProperties(String JavaDoc url,
345                                                               java.util.Properties JavaDoc properties)
346             throws SqlException {
347         String JavaDoc attributeString = null;
348         int attributeIndex = -1;
349
350         if ((url != null) &&
351                 ((attributeIndex = url.indexOf(";")) != -1)) {
352             attributeString = url.substring(attributeIndex);
353         }
354         return ClientDataSource.tokenizeAttributes(attributeString, properties);
355     }
356     
357     /**
358      *This method returns an Implementation
359      *of ClientJDBCObjectFactory depending on
360      *VM under use
361      *Currently it returns either
362      *ClientJDBCObjectFactoryImpl
363      *(or)
364      *ClientJDBCObjectFactoryImpl40
365      */

366     
367     public static ClientJDBCObjectFactory getFactory() {
368         if(factoryObject!=null)
369             return factoryObject;
370         if(Configuration.supportsJDBC40()) {
371             factoryObject = createJDBC40FactoryImpl();
372         } else {
373             factoryObject = createDefaultFactoryImpl();
374         }
375         return factoryObject;
376     }
377     
378     /**
379      *Returns an instance of the ClientJDBCObjectFactoryImpl class
380      */

381     private static ClientJDBCObjectFactory createDefaultFactoryImpl() {
382         return new ClientJDBCObjectFactoryImpl();
383     }
384     
385     /**
386      *Returns an instance of the ClientJDBCObjectFactoryImpl40 class
387      *If a ClassNotFoundException occurs then it returns an
388      *instance of ClientJDBCObjectFactoryImpl
389      *
390      *If a future version of JDBC comes then
391      *a similar method would be added say createJDBCXXFactoryImpl
392      *in which if the class is not found then it would
393      *return the lower version thus having a sort of cascading effect
394      *until it gets a valid instance
395      */

396     
397     private static ClientJDBCObjectFactory createJDBC40FactoryImpl() {
398         final String JavaDoc factoryName =
399                 "org.apache.derby.client.net.ClientJDBCObjectFactoryImpl40";
400         try {
401             return (ClientJDBCObjectFactory)
402             Class.forName(factoryName).newInstance();
403         } catch (ClassNotFoundException JavaDoc cnfe) {
404             return createDefaultFactoryImpl();
405         } catch (InstantiationException JavaDoc ie) {
406             return createDefaultFactoryImpl();
407         } catch (IllegalAccessException JavaDoc iae) {
408             return createDefaultFactoryImpl();
409         }
410     }
411 }
412
413
414
415
Popular Tags