1 //
2 // Copyright 1998 CDS Networks, Inc., Medford Oregon
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // 1. Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // 3. All advertising materials mentioning features or use of this software
14 // must display the following acknowledgement:
15 // This product includes software developed by CDS Networks, Inc.
16 // 4. The name of CDS Networks, Inc. may not be used to endorse or promote
17 // products derived from this software without specific prior
18 // written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY CDS NETWORKS, INC. ``AS IS'' AND
21 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 // ARE DISCLAIMED. IN NO EVENT SHALL CDS NETWORKS, INC. BE LIABLE
24 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 // SUCH DAMAGE.
31 //
32
33
34
35 package com.internetcds.jdbc.tds;
36
37
38 import java.sql.*;
39 import java.util.*;
40 import com.internetcds.jdbc.tds.TdsException;
41
42
43
44 /***
45 * <P>The Java SQL framework allows for multiple database drivers.
46 *
47 * <P>Each driver should supply a class that implements
48 * the Driver interface.
49 *
50 * <P>The DriverManager will try to load as many drivers as it can
51 * find and then for any given connection request, it will ask each
52 * driver in turn to try to connect to the target URL.
53 *
54 * <P>It is strongly recommended that each Driver class should be
55 * small and standalone so that the Driver class can be loaded and
56 * queried without bringing in vast quantities of supporting code.
57 *
58 * <P>When a Driver class is loaded, it should create an instance of
59 * itself and register it with the DriverManager. This means that a
60 * user can load and register a driver by doing
61 * Class.forName("foo.bah.Driver").
62 *
63 * @author Craig Spannring
64 * @author Igor Petrovski
65 * @version $Id: Driver.html,v 1.1 2003/05/12 16:19:44 sinisa Exp $
66 *
67 * @see DriverManager
68 * @see Connection
69 */
70 public class Driver implements java.sql.Driver
71 {
72 public static final String cvsVersion = "$Id: Driver.html,v 1.1 2003/05/12 16:19:44 sinisa Exp $";
73
74
75 //
76 // Register ourselves with the DriverManager
77 //
78 static
79 {
80 try {
81 java.sql.DriverManager.registerDriver(new Driver());
82 }
83 catch (SQLException E) {
84 E.printStackTrace();
85 }
86 }
87
88
89 static final boolean debug = false;
90 static final String oldSQLServerUrlPrefix = "jdbc:freetds://";
91 static final String newSQLServerUrlPrefix = "jdbc:freetds:sqlserver://";
92 static final String sybaseUrlPrefix = "jdbc:freetds:sybase://";
93 static final String defaultSQLServerPort = "1433";
94 static final String defaultSybasePort = "7100";
95
96
97
98 private boolean isValidHostname(String host)
99 {
100 return true; // XXX
101 }
102
103 /***
104 * Parses the properties specified in <i>url</i> and adds them to
105 * <i>result</i>.
106 *
107 * @return true if the URL could be parsed successfully.
108 */
109 protected boolean parseUrl(String url, Properties result)
110 {
111 String tmpUrl = url;
112 int serverType = -1;
113
114 if (tmpUrl.startsWith(oldSQLServerUrlPrefix) ||
115 tmpUrl.startsWith(newSQLServerUrlPrefix) ||
116 tmpUrl.startsWith(sybaseUrlPrefix))
117 {
118 if (tmpUrl.startsWith(oldSQLServerUrlPrefix))
119 {
120 serverType = Tds.SQLSERVER;
121 tmpUrl = tmpUrl.substring(oldSQLServerUrlPrefix.length());
122 }
123 else if (tmpUrl.startsWith(newSQLServerUrlPrefix))
124 {
125 serverType = Tds.SQLSERVER;
126 tmpUrl = tmpUrl.substring(newSQLServerUrlPrefix.length());
127 }
128 else if (tmpUrl.startsWith(sybaseUrlPrefix))
129 {
130 serverType = Tds.SYBASE;
131 tmpUrl = url.substring(sybaseUrlPrefix.length());
132 }
133
134
135 try
136 {
137 StringTokenizer tokenizer = new StringTokenizer(tmpUrl, ":/;",
138 true);
139 String tmp;
140 String host = null;
141 String port = (serverType==Tds.SYBASE
142 ? defaultSybasePort
143 : defaultSQLServerPort);
144 String database = null;
145 // String tdsVer = "42";
146 //Sinisa
147 String tdsVer = "7.0";
148
149 // Get the hostname
150 host = tokenizer.nextToken();
151
152
153 // Find the port if it has one.
154 tmp = tokenizer.nextToken();
155 if (tmp.equals(":"))
156 {
157 port = tokenizer.nextToken();
158 // Skip the '/' character
159 tmp = tokenizer.nextToken();
160 }
161
162 if (tmp.equals("/"))
163 {
164 // find the database name
165 database = tokenizer.nextToken();
166 if (tokenizer.hasMoreTokens())
167 tmp = tokenizer.nextToken();
168 }
169
170
171 // XXX The next loop is a bit too permisive.
172 while (tmp.equals(";"))
173 {
174 // Extract the additional attribute.
175 String extra = tokenizer.nextToken();
176 StringTokenizer tok2 = new StringTokenizer(extra, "=", false);
177 String key = tok2.nextToken().toUpperCase();
178 if (tok2.hasMoreTokens())
179 {
180 result.put(key, tok2.nextToken());
181 }
182
183 if (tokenizer.hasMoreTokens())
184 {
185 tmp = tokenizer.nextToken();
186 }
187 else
188 {
189 break;
190 }
191 }
192
193 // if there are anymore tokens then don't recognoze this URL
194 if ((! tokenizer.hasMoreTokens())
195 && isValidHostname(host)
196 && database!=null)
197 {
198 result.put("HOST", host);
199 result.put("SERVERTYPE", "" + serverType);
200 result.put("PORT", port);
201 result.put("DBNAME", database);
202 }
203 else
204 {
205 return false;
206 }
207 }
208 catch (NoSuchElementException e)
209 {
210 return false;
211 }
212 }
213 else
214 {
215 return false;
216 }
217
218 return true;
219 }
220
221
222 /***
223 * Construct a new driver and register it with DriverManager
224 *
225 * @exception SQLException
226 */
227 public Driver() throws SQLException
228 {
229 }
230
231
232 /***
233 * Try to make a database connection to the given URL. The driver
234 * should return "null" if it realizes it is the wrong kind of
235 * driver to connect to the given URL. This will be common, as
236 * when the JDBC driverManager is asked to connect to a given URL,
237 * it passes the URL to each loaded driver in turn.
238 *
239 * <p>The driver should raise an SQLException if it is the right driver
240 * to connect to the given URL, but has trouble connecting to the
241 * database.
242 *
243 * <p>The java.util.Properties argument can be used to pass arbitrary
244 * string tag/value pairs as connection arguments.
245 *
246 * This driver handles URLs of the form:
247 * <PRE>
248 * jdbc:freetds://servername/database
249 * jdbc:freetds://servername:port/database
250 * jdbc:freetds:sqlserver://servername/database
251 * jdbc:freetds:sqlserver://servername:port/database
252 * jdbc:freetds:sybase://servername/database
253 * jdbc:freetds:sybase://servername:port/database
254 * </PRE>
255 * <p>
256 *
257 * <table><thead>Recognized Properties</thead>
258 * <tbody>
259 * <tr><td>PROGNAME<td>Send this name to server to identify the program</tr>
260 * <tr><td>APPNAME<td>Send this name to server to identify the app</tr>
261 * </tbody>
262 * </table>
263 *
264 * @param url the URL of the database to connect to
265 * @param info a list of arbitrary tag/value pairs as connection
266 * arguments
267 * @return a connection to the URL or null if it isnt us
268 * @exception SQLException if a database access error occurs
269 * @see java.sql.Driver#connect
270 */
271 public java.sql.Connection connect(String Url, Properties info)
272 throws SQLException
273 {
274 java.sql.Connection result = null;
275
276 if (!parseUrl(Url, info))
277 {
278 return null;
279 }
280 else
281 {
282 try
283 {
284 result = Constructors.newConnection(info);
285 }
286 catch(NumberFormatException e)
287 {
288 throw new SQLException("NumberFormatException converting port number");
289 }
290 catch(com.internetcds.jdbc.tds.TdsException e)
291 {
292 throw new SQLException(e.getMessage());
293 }
294 }
295 return result;
296 }
297
298 /***
299 * Returns true if the driver thinks it can open a connection to the
300 * given URL. Typically, drivers will return true if they understand
301 * the subprotocol specified in the URL and false if they don't. This
302 * driver's protocols start with jdbc:freetds:
303 *
304 * This driver handles URLs of the form:
305 * <PRE>
306 * jdbc:freetds://host:port/database
307 * </PRE>
308 * or
309 * <PRE>
310 * jdbc:freetds://host/database
311 * </PRE>
312 * <PRE>
313 * jdbc:freetds:sqlserver://host:port/database
314 * </PRE>
315 * or
316 * <PRE>
317 * jdbc:freetds:sqlserver://host/database
318 * </PRE>
319 * <PRE>
320 * jdbc:freetds:sybase://host:port/database
321 * </PRE>
322 * or
323 * <PRE>
324 * jdbc:freetds:sybase://host/database
325 * </PRE>
326 *
327 * @see java.sql.Driver#acceptsURL
328 * @param url the URL of the driver
329 * @return true if this driver accepts the given URL
330 * @exception SQLException if a database-access error occurs
331 */
332 public boolean acceptsURL(String url) throws SQLException
333 {
334 boolean result = parseUrl(url, new Properties());
335 return result;
336 }
337
338 /***
339 * <p>The getPropertyInfo method is intended to allow a generic GUI tool to
340 * discover what properties it should prompt a human for in order to get
341 * enough information to connect to a database. Note that depending on
342 * the values the human has supplied so far, additional values may become
343 * necessary, so it may be necessary to iterate though several calls
344 * to getPropertyInfo.
345 *
346 * @param url The URL of the database to connect to.
347 * @param info A proposed list of tag/value pairs that will be sent on
348 * connect open.
349 * @return An array of DriverPropertyInfo objects describing possible
350 * properties. This array may be an empty array if no properties
351 * are required.
352 * @exception SQLException if a database-access error occurs.
353 */
354 public DriverPropertyInfo[] getPropertyInfo(String Url, Properties Info)
355 throws SQLException
356 {
357 DriverPropertyInfo result[] = new DriverPropertyInfo[0];
358
359 return result;
360 }
361
362 /***
363 * Gets the drivers major version number
364 *
365 * @return the drivers major version number
366 */
367 public int getMajorVersion()
368 {
369 return DriverVersion.getDriverMajorVersion();
370 }
371
372
373 /***
374 * Get the driver's minor version number. Initially this should be 0.
375 */
376 public int getMinorVersion()
377 {
378 return DriverVersion.getDriverMinorVersion();
379 }
380
381
382 /***
383 * Report whether the Driver is a genuine JDBC COMPLIANT (tm) driver.
384 * A driver may only report "true" here if it passes the JDBC compliance
385 * tests, otherwise it is required to return false.
386 *
387 * JDBC compliance requires full support for the JDBC API and full support
388 * for SQL 92 Entry Level. It is expected that JDBC compliant drivers will
389 * be available for all the major commercial databases.
390 *
391 * This method is not intended to encourage the development of non-JDBC
392 * compliant drivers, but is a recognition of the fact that some vendors
393 * are interested in using the JDBC API and framework for lightweight
394 * databases that do not support full database functionality, or for
395 * special databases such as document information retrieval where a SQL
396 * implementation may not be feasible.
397 */
398 public boolean jdbcCompliant()
399 {
400 // :-( MS SQLServer 6.5 doesn't provide what JDBC wants.
401 // See DatabaseMetaData.nullPlusNonNullIsNull() for more details.
402 // XXX Need to check if Sybase could be jdbcCompliant
403 return false;
404 }
405
406 }
This page automatically generated by Maven