EMMA Coverage Report (generated Wed Jun 28 22:15:27 PDT 2006)
[all classes][org.apache.derby.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [ClientDriver.java]

nameclass, %method, %block, %line, %
ClientDriver.java100% (1/1)93%  (13/14)59%  (288/486)66%  (73/111)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ClientDriver100% (1/1)93%  (13/14)59%  (288/486)66%  (73/111)
<static initializer> 100% (1/1)50%  (14/28)64%  (7/11)
ClientDriver (): void 100% (1/1)100% (6/6)100% (3/3)
acceptsURL (String): boolean 100% (1/1)100% (17/17)100% (3/3)
appendDatabaseAttributes (String, Properties): String 100% (1/1)100% (45/45)100% (7/7)
connect (String, Properties): Connection 100% (1/1)78%  (96/123)80%  (24/30)
getMajorVersion (): int 100% (1/1)100% (2/2)100% (1/1)
getMinorVersion (): int 100% (1/1)100% (2/2)100% (1/1)
getPropertyInfo (String, Properties): DriverPropertyInfo [] 0%   (0/1)0%   (0/54)0%   (0/10)
jdbcCompliant (): boolean 100% (1/1)100% (2/2)100% (1/1)
tokenizeDatabase (StringTokenizer, String): String 100% (1/1)29%  (6/21)50%  (2/4)
tokenizeOptionalPortNumber (StringTokenizer, String): int 100% (1/1)31%  (21/68)45%  (5/11)
tokenizeProtocol (String, StringTokenizer): int 100% (1/1)78%  (46/59)63%  (12/19)
tokenizeServerName (StringTokenizer, String): String 100% (1/1)26%  (10/38)40%  (2/5)
tokenizeURLProperties (String, Properties): Properties 100% (1/1)100% (21/21)100% (5/5)

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 
21package org.apache.derby.jdbc;
22 
23import java.util.Enumeration;
24import java.util.Properties;
25import java.sql.SQLException;
26import org.apache.derby.client.am.Configuration;
27import org.apache.derby.client.am.SqlException;
28import org.apache.derby.client.am.Utils;
29import org.apache.derby.client.am.Version;
30import org.apache.derby.client.am.ClientJDBCObjectFactory;
31import org.apache.derby.client.am.ClientMessageId;
32import org.apache.derby.client.net.ClientJDBCObjectFactoryImpl;
33import org.apache.derby.shared.common.reference.Attribute;
34import org.apache.derby.shared.common.reference.SQLState;
35import org.apache.derby.shared.common.reference.MessageId;
36 
37 
38public class ClientDriver implements java.sql.Driver {
39    private transient int traceFileSuffixIndex_ = 0;
40 
41    private final static int DERBY_REMOTE_PROTOCOL = 1;
42    
43    private static ClientJDBCObjectFactory factoryObject = null;
44 
45    static private SQLException exceptionsOnLoadDriver__ = null;
46    // Keep track of the registere driver so that we can deregister it if we're a stored proc.
47    static private ClientDriver registeredDriver__ = null;
48 
49    static {
50        // This may possibly hit the race-condition bug of java 1.1.
51        // The Configuration static clause should execute before the following line does.
52        if (Configuration.exceptionsOnLoadResources != null) {
53            exceptionsOnLoadDriver__ =
54                    Utils.accumulateSQLException(
55                            Configuration.exceptionsOnLoadResources.getSQLException(),
56                            exceptionsOnLoadDriver__);
57        }
58        try {
59            registeredDriver__ = new ClientDriver();
60            java.sql.DriverManager.registerDriver(registeredDriver__);
61        } catch (java.sql.SQLException e) {
62            // A null log writer is passed, because jdbc 1 sql exceptions are automatically traced
63            exceptionsOnLoadDriver__ =
64                    new SqlException(null, 
65                        new ClientMessageId(SQLState.JDBC_DRIVER_REGISTER)).getSQLException();
66            exceptionsOnLoadDriver__.setNextException(e);
67        }
68    }
69 
70    public ClientDriver() {
71    }
72 
73    public java.sql.Connection connect(String url,
74                                       java.util.Properties properties) throws java.sql.SQLException {
75        org.apache.derby.client.net.NetConnection conn;
76        try {    
77            if (exceptionsOnLoadDriver__ != null) {
78                throw exceptionsOnLoadDriver__;
79            }
80 
81            if (properties == null) {
82                properties = new java.util.Properties();
83            }
84 
85            java.util.StringTokenizer urlTokenizer =
86                    new java.util.StringTokenizer(url, "/:= \t\n\r\f", true);
87 
88            int protocol = tokenizeProtocol(url, urlTokenizer);
89            if (protocol == 0) {
90                return null; // unrecognized database URL prefix.
91            }
92 
93            String slashOrNull = null;
94            if (protocol == DERBY_REMOTE_PROTOCOL) {
95                try {
96                    slashOrNull = urlTokenizer.nextToken(":/");
97                } catch (java.util.NoSuchElementException e) {
98                    // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
99                    throw new SqlException(null, 
100                        new ClientMessageId(SQLState.MALFORMED_URL),
101                        url, e);
102                }
103            }
104            String server = tokenizeServerName(urlTokenizer, url);    // "/server"
105            int port = tokenizeOptionalPortNumber(urlTokenizer, url); // "[:port]/"
106            if (port == 0) {
107                port = ClientDataSource.propertyDefault_portNumber;
108            }
109 
110            // database is the database name and attributes.  This will be
111            // sent to network server as the databaseName
112            String database = tokenizeDatabase(urlTokenizer, url); // "database"
113            java.util.Properties augmentedProperties = tokenizeURLProperties(url, properties);
114            database = appendDatabaseAttributes(database,augmentedProperties);
115 
116            int traceLevel;
117            try {
118                traceLevel = ClientDataSource.getTraceLevel(augmentedProperties);
119            } catch (java.lang.NumberFormatException e) {
120                // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
121                throw new SqlException(null, 
122                    new ClientMessageId(SQLState.TRACELEVEL_FORMAT_INVALID), e);
123            }
124 
125            // Jdbc 1 connections will write driver trace info on a
126            // driver-wide basis using the jdbc 1 driver manager log writer.
127            // This log writer may be narrowed to the connection-level
128            // This log writer will be passed to the agent constructor.
129            org.apache.derby.client.am.LogWriter dncLogWriter =
130                    ClientDataSource.computeDncLogWriterForNewConnection(java.sql.DriverManager.getLogWriter(),
131                            ClientDataSource.getTraceDirectory(augmentedProperties),
132                            ClientDataSource.getTraceFile(augmentedProperties),
133                            ClientDataSource.getTraceFileAppend(augmentedProperties),
134                            traceLevel,
135                            "_driver",
136                            traceFileSuffixIndex_++);
137            
138            
139            conn = (org.apache.derby.client.net.NetConnection)getFactory().
140                    newNetConnection((org.apache.derby.client.net.NetLogWriter) 
141                    dncLogWriter,
142                    java.sql.DriverManager.getLoginTimeout(),
143                    server,
144                    port,
145                    database,
146                    augmentedProperties);
147        } catch(SqlException se) {
148            throw se.getSQLException();
149        }
150        
151        if(conn.isConnectionNull())
152            return null;
153        
154        return conn;
155    }
156 
157    /**
158     * Append attributes to the database name except for user/password 
159     * which are sent as part of the protocol.
160     * Other attributes will  be sent to the server with the database name
161     * Assumes augmentedProperties is not null
162     * 
163         * @param database - Short database name
164         * @param augmentedProperties - Set of properties to append as attributes
165         * @return databaseName + attributes (e.g. mydb;create=true) 
166         */
167        private String appendDatabaseAttributes(String database, Properties augmentedProperties) {
168        
169                StringBuffer longDatabase = new StringBuffer(database);
170                for (Enumeration keys = augmentedProperties.keys(); keys.hasMoreElements() ;)
171                {
172                        String key = (String) keys.nextElement();
173                        if (key.equals(Attribute.USERNAME_ATTR) || 
174                                key.equals(Attribute.PASSWORD_ATTR))
175                                continue;
176                        longDatabase.append(";" + key + "=" + augmentedProperties.getProperty(key));
177                }
178                return longDatabase.toString();
179        }
180 
181        public boolean acceptsURL(String url) throws java.sql.SQLException {
182        try
183        {
184            java.util.StringTokenizer urlTokenizer = 
185                    new java.util.StringTokenizer(url, "/:=; \t\n\r\f", true);
186            int protocol = tokenizeProtocol(url, urlTokenizer);
187            return protocol != 0;
188        }
189        catch ( SqlException se )
190        {
191            throw se.getSQLException();
192        }
193    }
194 
195    public java.sql.DriverPropertyInfo[] getPropertyInfo(String url,
196                                                         java.util.Properties properties) throws java.sql.SQLException {
197        java.sql.DriverPropertyInfo driverPropertyInfo[] = new java.sql.DriverPropertyInfo[2];
198 
199        // If there are no properties set already,
200        // then create a dummy properties just to make the calls go thru.
201        if (properties == null) {
202            properties = new java.util.Properties();
203        }
204 
205        driverPropertyInfo[0] =
206                new java.sql.DriverPropertyInfo(Attribute.USERNAME_ATTR,
207                        properties.getProperty(Attribute.USERNAME_ATTR, ClientDataSource.propertyDefault_user));
208 
209        driverPropertyInfo[1] =
210                new java.sql.DriverPropertyInfo(Attribute.PASSWORD_ATTR,
211                        properties.getProperty(Attribute.PASSWORD_ATTR));
212 
213        driverPropertyInfo[0].description =
214            SqlException.getMessageUtil().getTextMessage(
215                MessageId.CONN_USERNAME_DESCRIPTION);
216        driverPropertyInfo[1].description =
217            SqlException.getMessageUtil().getTextMessage(
218                MessageId.CONN_PASSWORD_DESCRIPTION);
219 
220        driverPropertyInfo[0].required = true;
221        driverPropertyInfo[1].required = false; // depending on the security mechanism
222 
223        return driverPropertyInfo;
224    }
225 
226    public int getMajorVersion() {
227        return Version.getMajorVersion();
228    }
229 
230    public int getMinorVersion() {
231        return Version.getMinorVersion();
232    }
233 
234    public boolean jdbcCompliant() {
235        return Configuration.jdbcCompliant;
236    }
237 
238    // ----------------helper methods---------------------------------------------
239 
240    // Tokenize one of the following:
241    //  "jdbc:derby:"
242    // and return 0 if the protcol is unrecognized
243    // return DERBY_PROTOCOL for "jdbc:derby"
244    private static int tokenizeProtocol(String url, java.util.StringTokenizer urlTokenizer) throws SqlException {
245        // Is this condition necessary, StringTokenizer constructor may do this for us
246        if (url == null) {
247            return 0;
248        }
249 
250        if (urlTokenizer == null) {
251            return 0;
252        }
253 
254        try {
255            String jdbc = urlTokenizer.nextToken(":");
256            if (!jdbc.equals("jdbc")) {
257                return 0;
258            }
259            if (!urlTokenizer.nextToken(":").equals(":")) {
260                return 0; // Skip over the first colon in jdbc:derby:
261            }
262            String dbname = urlTokenizer.nextToken(":");
263            int protocol = 0;
264            if (dbname.equals("derby") && (url.indexOf("derby://") != -1)) {
265                // For Derby AS need to check for // since jdbc:derby: is also the
266                // embedded prefix
267                protocol = DERBY_REMOTE_PROTOCOL;
268            } else {
269                return 0;
270            }
271 
272            if (!urlTokenizer.nextToken(":").equals(":")) {
273                return 0; // Skip over the second colon in jdbc:derby:
274            }
275 
276            return protocol;
277        } catch (java.util.NoSuchElementException e) {
278            return 0;
279        }
280    }
281 
282    // tokenize "/server" from URL jdbc:derby://server:port/
283    // returns server name
284    private static String tokenizeServerName(java.util.StringTokenizer urlTokenizer,
285                                             String url) throws SqlException {
286        try {
287            if (!urlTokenizer.nextToken("/").equals("/"))
288            // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
289            {
290                throw new SqlException(null, 
291                    new ClientMessageId(SQLState.MALFORMED_URL), url);
292            }
293            return urlTokenizer.nextToken("/:");
294        } catch (java.util.NoSuchElementException e) {
295            // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
296                throw new SqlException(null, 
297                    new ClientMessageId(SQLState.MALFORMED_URL), url);
298        }
299    }
300 
301    // tokenize "[:portNumber]/" from URL jdbc:derby://server[:port]/
302    // returns the portNumber or zero if portNumber is not specified.
303    private static int tokenizeOptionalPortNumber(java.util.StringTokenizer urlTokenizer,
304                                                  String url) throws SqlException {
305        try {
306            String firstToken = urlTokenizer.nextToken(":/");
307            if (firstToken.equals(":")) {
308                String port = urlTokenizer.nextToken("/");
309                if (!urlTokenizer.nextToken("/").equals("/")) {
310                    // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
311                    throw new SqlException(null, 
312                        new ClientMessageId(SQLState.MALFORMED_URL), url);
313                }
314                return Integer.parseInt(port);
315            } else if (firstToken.equals("/")) {
316                return 0;
317            } else {
318                // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
319                throw new SqlException(null, 
320                    new ClientMessageId(SQLState.MALFORMED_URL), url);
321            }
322        } catch (java.util.NoSuchElementException e) {
323            // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
324            throw new SqlException(null, 
325                new ClientMessageId(SQLState.MALFORMED_URL), url, e);
326        }
327    }
328 
329    //return database name
330    private static String tokenizeDatabase(java.util.StringTokenizer urlTokenizer,
331                                           String url) throws SqlException {
332        try {
333                // DERBY-618 - database name can contain spaces in the path
334            String databaseName = urlTokenizer.nextToken("\t\n\r\f;");
335            return databaseName;
336        } catch (java.util.NoSuchElementException e) {
337            // A null log writer is passed, because jdbc 1 sqlexceptions are automatically traced
338            throw new SqlException(null, 
339                new ClientMessageId(SQLState.MALFORMED_URL), url, e);
340        }
341    }
342 
343    private static java.util.Properties tokenizeURLProperties(String url,
344                                                              java.util.Properties properties)
345            throws SqlException {
346        String attributeString = null;
347        int attributeIndex = -1;
348 
349        if ((url != null) &&
350                ((attributeIndex = url.indexOf(";")) != -1)) {
351            attributeString = url.substring(attributeIndex);
352        }
353        return ClientDataSource.tokenizeAttributes(attributeString, properties);
354    }
355    
356    /**
357     *This method returns an Implementation
358     *of ClientJDBCObjectFactory depending on
359     *VM under use
360     *Currently it returns either
361     *ClientJDBCObjectFactoryImpl
362     *(or)
363     *ClientJDBCObjectFactoryImpl40
364     */
365    
366    public static ClientJDBCObjectFactory getFactory() {
367        if(factoryObject!=null)
368            return factoryObject;
369        if(Configuration.supportsJDBC40()) {
370            factoryObject = createJDBC40FactoryImpl();
371        } else {
372            factoryObject = createDefaultFactoryImpl();
373        }
374        return factoryObject;
375    }
376    
377    /**
378     *Returns an instance of the ClientJDBCObjectFactoryImpl class
379     */
380    private static ClientJDBCObjectFactory createDefaultFactoryImpl() {
381        return  new ClientJDBCObjectFactoryImpl();
382    }
383    
384    /**
385     *Returns an instance of the ClientJDBCObjectFactoryImpl40 class
386     *If a ClassNotFoundException occurs then it returns an
387     *instance of ClientJDBCObjectFactoryImpl
388     *
389     *If a future version of JDBC comes then
390     *a similar method would be added say createJDBCXXFactoryImpl
391     *in which if  the class is not found then it would
392     *return the lower version thus having a sort of cascading effect
393     *until it gets a valid instance
394     */
395    
396    private static ClientJDBCObjectFactory createJDBC40FactoryImpl() {
397        final String factoryName =
398                "org.apache.derby.client.net.ClientJDBCObjectFactoryImpl40";
399        try {
400            return (ClientJDBCObjectFactory)
401            Class.forName(factoryName).newInstance();
402        } catch (ClassNotFoundException cnfe) {
403            return createDefaultFactoryImpl();
404        } catch (InstantiationException ie) {
405            return createDefaultFactoryImpl();
406        } catch (IllegalAccessException iae) {
407            return createDefaultFactoryImpl();
408        }
409    }
410}
411 
412 
413 

[all classes][org.apache.derby.jdbc]
EMMA 2.0.5312 (C) Vladimir Roubtsov