Source Code Cross Referenced for ConnectionFactoryImpl.java in  » Database-JDBC-Connection-Pool » postgresql » org » postgresql » core » v3 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database JDBC Connection Pool » postgresql » org.postgresql.core.v3 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*-------------------------------------------------------------------------
002:         *
003:         * Copyright (c) 2003-2005, PostgreSQL Global Development Group
004:         * Copyright (c) 2004, Open Cloud Limited.
005:         *
006:         * IDENTIFICATION
007:         *   $PostgreSQL: pgjdbc/org/postgresql/core/v3/ConnectionFactoryImpl.java,v 1.13 2007/02/28 06:11:00 jurka Exp $
008:         *
009:         *-------------------------------------------------------------------------
010:         */
011:        package org.postgresql.core.v3;
012:
013:        import java.util.Properties;
014:
015:        import java.sql.*;
016:        import java.io.IOException;
017:        import java.net.ConnectException;
018:
019:        import org.postgresql.Driver;
020:        import org.postgresql.core.*;
021:        import org.postgresql.util.PSQLException;
022:        import org.postgresql.util.PSQLState;
023:        import org.postgresql.util.PSQLWarning;
024:        import org.postgresql.util.ServerErrorMessage;
025:        import org.postgresql.util.UnixCrypt;
026:        import org.postgresql.util.MD5Digest;
027:        import org.postgresql.util.GT;
028:
029:        /**
030:         * ConnectionFactory implementation for version 3 (7.4+) connections.
031:         *
032:         * @author Oliver Jowett (oliver@opencloud.com), based on the previous implementation
033:         */
034:        public class ConnectionFactoryImpl extends ConnectionFactory {
035:            private static final int AUTH_REQ_OK = 0;
036:            private static final int AUTH_REQ_KRB4 = 1;
037:            private static final int AUTH_REQ_KRB5 = 2;
038:            private static final int AUTH_REQ_PASSWORD = 3;
039:            private static final int AUTH_REQ_CRYPT = 4;
040:            private static final int AUTH_REQ_MD5 = 5;
041:            private static final int AUTH_REQ_SCM = 6;
042:
043:            /** Marker exception; thrown when we want to fall back to using V2. */
044:            private static class UnsupportedProtocolException extends
045:                    IOException {
046:            }
047:
048:            public ProtocolConnection openConnectionImpl(String host, int port,
049:                    String user, String database, Properties info, Logger logger)
050:                    throws SQLException {
051:                // Extract interesting values from the info properties:
052:                //  - the SSL setting
053:                boolean requireSSL = (info.getProperty("ssl") != null);
054:                boolean trySSL = requireSSL; // XXX temporary until we revisit the ssl property values
055:
056:                // NOTE: To simplify this code, it is assumed that if we are
057:                // using the V3 protocol, then the database is at least 7.4.  That
058:                // eliminates the need to check database versions and maintain
059:                // backward-compatible code here.
060:                //
061:                // Change by Chris Smith <cdsmith@twu.net>
062:
063:                if (logger.logDebug())
064:                    logger
065:                            .debug("Trying to establish a protocol version 3 connection to "
066:                                    + host + ":" + port);
067:
068:                if (!Driver.sslEnabled()) {
069:                    if (requireSSL)
070:                        throw new PSQLException(GT
071:                                .tr("The driver does not support SSL."),
072:                                PSQLState.CONNECTION_FAILURE);
073:                    trySSL = false;
074:                }
075:
076:                //
077:                // Establish a connection.
078:                //
079:
080:                PGStream newStream = null;
081:                try {
082:                    newStream = new PGStream(host, port);
083:
084:                    // Construct and send an ssl startup packet if requested.
085:                    if (trySSL)
086:                        newStream = enableSSL(newStream, requireSSL, info,
087:                                logger);
088:
089:                    // Construct and send a startup packet.
090:                    String[][] params = { { "user", user },
091:                            { "database", database },
092:                            { "client_encoding", "UNICODE" },
093:                            { "DateStyle", "ISO" } };
094:
095:                    sendStartupPacket(newStream, params, logger);
096:
097:                    // Do authentication (until AuthenticationOk).
098:                    doAuthentication(newStream, user, info
099:                            .getProperty("password"), logger);
100:
101:                    // Do final startup.
102:                    ProtocolConnectionImpl protoConnection = new ProtocolConnectionImpl(
103:                            newStream, user, database, info, logger);
104:                    readStartupMessages(newStream, protoConnection, logger);
105:
106:                    // And we're done.
107:                    return protoConnection;
108:                } catch (UnsupportedProtocolException upe) {
109:                    // Swallow this and return null so ConnectionFactory tries the next protocol.
110:                    if (logger.logDebug())
111:                        logger
112:                                .debug("Protocol not supported, abandoning connection.");
113:                    try {
114:                        newStream.close();
115:                    } catch (IOException e) {
116:                    }
117:                    return null;
118:                } catch (ConnectException cex) {
119:                    // Added by Peter Mount <peter@retep.org.uk>
120:                    // ConnectException is thrown when the connection cannot be made.
121:                    // we trap this an return a more meaningful message for the end user
122:                    throw new PSQLException(
123:                            GT
124:                                    .tr("Connection refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections."),
125:                            PSQLState.CONNECTION_REJECTED, cex);
126:                } catch (IOException ioe) {
127:                    if (newStream != null) {
128:                        try {
129:                            newStream.close();
130:                        } catch (IOException e) {
131:                        }
132:                    }
133:                    throw new PSQLException(GT
134:                            .tr("The connection attempt failed."),
135:                            PSQLState.CONNECTION_UNABLE_TO_CONNECT, ioe);
136:                } catch (SQLException se) {
137:                    if (newStream != null) {
138:                        try {
139:                            newStream.close();
140:                        } catch (IOException e) {
141:                        }
142:                    }
143:                    throw se;
144:                }
145:            }
146:
147:            private PGStream enableSSL(PGStream pgStream, boolean requireSSL,
148:                    Properties info, Logger logger) throws IOException,
149:                    SQLException {
150:                if (logger.logDebug())
151:                    logger.debug(" FE=> SSLRequest");
152:
153:                // Send SSL request packet
154:                pgStream.SendInteger4(8);
155:                pgStream.SendInteger2(1234);
156:                pgStream.SendInteger2(5679);
157:                pgStream.flush();
158:
159:                // Now get the response from the backend, one of N, E, S.
160:                int beresp = pgStream.ReceiveChar();
161:                switch (beresp) {
162:                case 'E':
163:                    if (logger.logDebug())
164:                        logger.debug(" <=BE SSLError");
165:
166:                    // Server doesn't even know about the SSL handshake protocol
167:                    if (requireSSL)
168:                        throw new PSQLException(GT
169:                                .tr("The server does not support SSL."),
170:                                PSQLState.CONNECTION_FAILURE);
171:
172:                    // We have to reconnect to continue.
173:                    pgStream.close();
174:                    return new PGStream(pgStream.getHost(), pgStream.getPort());
175:
176:                case 'N':
177:                    if (logger.logDebug())
178:                        logger.debug(" <=BE SSLRefused");
179:
180:                    // Server does not support ssl
181:                    if (requireSSL)
182:                        throw new PSQLException(GT
183:                                .tr("The server does not support SSL."),
184:                                PSQLState.CONNECTION_FAILURE);
185:
186:                    return pgStream;
187:
188:                case 'S':
189:                    if (logger.logDebug())
190:                        logger.debug(" <=BE SSLOk");
191:
192:                    // Server supports ssl
193:                    Driver.makeSSL(pgStream, info, logger);
194:                    return pgStream;
195:
196:                default:
197:                    throw new PSQLException(
198:                            GT
199:                                    .tr("An error occured while setting up the SSL connection."),
200:                            PSQLState.CONNECTION_FAILURE);
201:                }
202:            }
203:
204:            private void sendStartupPacket(PGStream pgStream,
205:                    String[][] params, Logger logger) throws IOException {
206:                if (logger.logDebug()) {
207:                    String details = "";
208:                    for (int i = 0; i < params.length; ++i) {
209:                        if (i != 0)
210:                            details += ", ";
211:                        details += params[i][0] + "=" + params[i][1];
212:                    }
213:                    logger.debug(" FE=> StartupPacket(" + details + ")");
214:                }
215:
216:                /*
217:                 * Precalculate message length and encode params.
218:                 */
219:                int length = 4 + 4;
220:                byte[][] encodedParams = new byte[params.length * 2][];
221:                for (int i = 0; i < params.length; ++i) {
222:                    encodedParams[i * 2] = params[i][0].getBytes("US-ASCII");
223:                    encodedParams[i * 2 + 1] = params[i][1]
224:                            .getBytes("US-ASCII");
225:                    length += encodedParams[i * 2].length + 1
226:                            + encodedParams[i * 2 + 1].length + 1;
227:                }
228:
229:                length += 1; // Terminating \0
230:
231:                /*
232:                 * Send the startup message.
233:                 */
234:                pgStream.SendInteger4(length);
235:                pgStream.SendInteger2(3); // protocol major
236:                pgStream.SendInteger2(0); // protocol minor
237:                for (int i = 0; i < encodedParams.length; ++i) {
238:                    pgStream.Send(encodedParams[i]);
239:                    pgStream.SendChar(0);
240:                }
241:
242:                pgStream.SendChar(0);
243:                pgStream.flush();
244:            }
245:
246:            private void doAuthentication(PGStream pgStream, String user,
247:                    String password, Logger logger) throws IOException,
248:                    SQLException {
249:                // Now get the response from the backend, either an error message
250:                // or an authentication request
251:
252:                while (true) {
253:                    int beresp = pgStream.ReceiveChar();
254:
255:                    switch (beresp) {
256:                    case 'E':
257:                        // An error occured, so pass the error message to the
258:                        // user.
259:                        //
260:                        // The most common one to be thrown here is:
261:                        // "User authentication failed"
262:                        //
263:                        int l_elen = pgStream.ReceiveInteger4();
264:                        if (l_elen > 30000) {
265:                            // if the error length is > than 30000 we assume this is really a v2 protocol
266:                            // server, so trigger fallback.
267:                            throw new UnsupportedProtocolException();
268:                        }
269:
270:                        ServerErrorMessage errorMsg = new ServerErrorMessage(
271:                                pgStream.ReceiveString(l_elen - 4), logger
272:                                        .getLogLevel());
273:                        if (logger.logDebug())
274:                            logger
275:                                    .debug(" <=BE ErrorMessage(" + errorMsg
276:                                            + ")");
277:                        throw new PSQLException(errorMsg);
278:
279:                    case 'R':
280:                        // Authentication request.
281:                        // Get the message length
282:                        int l_msgLen = pgStream.ReceiveInteger4();
283:
284:                        // Get the type of request
285:                        int areq = pgStream.ReceiveInteger4();
286:
287:                        // Process the request.
288:                        switch (areq) {
289:                        case AUTH_REQ_CRYPT: {
290:                            byte[] rst = new byte[2];
291:                            rst[0] = (byte) pgStream.ReceiveChar();
292:                            rst[1] = (byte) pgStream.ReceiveChar();
293:                            String salt = new String(rst, 0, 2, "US-ASCII");
294:
295:                            if (logger.logDebug())
296:                                logger
297:                                        .debug(" <=BE AuthenticationReqCrypt(salt='"
298:                                                + salt + "')");
299:
300:                            if (password == null)
301:                                throw new PSQLException(
302:                                        GT
303:                                                .tr("The server requested password-based authentication, but no password was provided."),
304:                                        PSQLState.CONNECTION_REJECTED);
305:
306:                            String result = UnixCrypt.crypt(salt, password);
307:                            byte[] encodedResult = result.getBytes("US-ASCII");
308:
309:                            if (logger.logDebug())
310:                                logger.debug(" FE=> Password(crypt='" + result
311:                                        + "')");
312:
313:                            pgStream.SendChar('p');
314:                            pgStream.SendInteger4(4 + encodedResult.length + 1);
315:                            pgStream.Send(encodedResult);
316:                            pgStream.SendChar(0);
317:                            pgStream.flush();
318:
319:                            break;
320:                        }
321:
322:                        case AUTH_REQ_MD5: {
323:                            byte[] md5Salt = pgStream.Receive(4);
324:                            if (logger.logDebug()) {
325:                                logger.debug(" <=BE AuthenticationReqMD5(salt="
326:                                        + Utils.toHexString(md5Salt) + ")");
327:                            }
328:
329:                            if (password == null)
330:                                throw new PSQLException(
331:                                        GT
332:                                                .tr("The server requested password-based authentication, but no password was provided."),
333:                                        PSQLState.CONNECTION_REJECTED);
334:
335:                            byte[] digest = MD5Digest.encode(user, password,
336:                                    md5Salt);
337:
338:                            if (logger.logDebug()) {
339:                                logger.debug(" FE=> Password(md5digest="
340:                                        + new String(digest, "US-ASCII") + ")");
341:                            }
342:
343:                            pgStream.SendChar('p');
344:                            pgStream.SendInteger4(4 + digest.length + 1);
345:                            pgStream.Send(digest);
346:                            pgStream.SendChar(0);
347:                            pgStream.flush();
348:
349:                            break;
350:                        }
351:
352:                        case AUTH_REQ_PASSWORD: {
353:                            if (logger.logDebug()) {
354:                                logger.debug(" <=BE AuthenticationReqPassword");
355:                                logger
356:                                        .debug(" FE=> Password(password=<not shown>)");
357:                            }
358:
359:                            if (password == null)
360:                                throw new PSQLException(
361:                                        GT
362:                                                .tr("The server requested password-based authentication, but no password was provided."),
363:                                        PSQLState.CONNECTION_REJECTED);
364:
365:                            byte[] encodedPassword = password
366:                                    .getBytes("US-ASCII");
367:
368:                            pgStream.SendChar('p');
369:                            pgStream
370:                                    .SendInteger4(4 + encodedPassword.length + 1);
371:                            pgStream.Send(encodedPassword);
372:                            pgStream.SendChar(0);
373:                            pgStream.flush();
374:
375:                            break;
376:                        }
377:
378:                        case AUTH_REQ_OK:
379:                            if (logger.logDebug())
380:                                logger.debug(" <=BE AuthenticationOk");
381:
382:                            return; // We're done.
383:
384:                        default:
385:                            if (logger.logDebug())
386:                                logger
387:                                        .debug(" <=BE AuthenticationReq (unsupported type "
388:                                                + ((int) areq) + ")");
389:
390:                            throw new PSQLException(
391:                                    GT
392:                                            .tr(
393:                                                    "The authentication type {0} is not supported. Check that you have configured the pg_hba.conf file to include the client''s IP address or subnet, and that it is using an authentication scheme supported by the driver.",
394:                                                    new Integer(areq)),
395:                                    PSQLState.CONNECTION_REJECTED);
396:                        }
397:
398:                        break;
399:
400:                    default:
401:                        throw new PSQLException(GT
402:                                .tr("Protocol error.  Session setup failed."),
403:                                PSQLState.CONNECTION_UNABLE_TO_CONNECT);
404:                    }
405:                }
406:            }
407:
408:            private void readStartupMessages(PGStream pgStream,
409:                    ProtocolConnectionImpl protoConnection, Logger logger)
410:                    throws IOException, SQLException {
411:                while (true) {
412:                    int beresp = pgStream.ReceiveChar();
413:                    switch (beresp) {
414:                    case 'Z':
415:                        // Ready For Query; we're done.
416:                        if (pgStream.ReceiveInteger4() != 5)
417:                            throw new IOException(
418:                                    "unexpected length of ReadyForQuery packet");
419:
420:                        char tStatus = (char) pgStream.ReceiveChar();
421:                        if (logger.logDebug())
422:                            logger
423:                                    .debug(" <=BE ReadyForQuery(" + tStatus
424:                                            + ")");
425:
426:                        // Update connection state.
427:                        switch (tStatus) {
428:                        case 'I':
429:                            protoConnection
430:                                    .setTransactionState(ProtocolConnection.TRANSACTION_IDLE);
431:                            break;
432:                        case 'T':
433:                            protoConnection
434:                                    .setTransactionState(ProtocolConnection.TRANSACTION_OPEN);
435:                            break;
436:                        case 'E':
437:                            protoConnection
438:                                    .setTransactionState(ProtocolConnection.TRANSACTION_FAILED);
439:                            break;
440:                        default:
441:                            // Huh?
442:                            break;
443:                        }
444:
445:                        return;
446:
447:                    case 'K':
448:                        // BackendKeyData
449:                        int l_msgLen = pgStream.ReceiveInteger4();
450:                        if (l_msgLen != 12)
451:                            throw new PSQLException(
452:                                    GT
453:                                            .tr("Protocol error.  Session setup failed."),
454:                                    PSQLState.CONNECTION_UNABLE_TO_CONNECT);
455:
456:                        int pid = pgStream.ReceiveInteger4();
457:                        int ckey = pgStream.ReceiveInteger4();
458:
459:                        if (logger.logDebug())
460:                            logger.debug(" <=BE BackendKeyData(pid=" + pid
461:                                    + ",ckey=" + ckey + ")");
462:
463:                        protoConnection.setBackendKeyData(pid, ckey);
464:                        break;
465:
466:                    case 'E':
467:                        // Error
468:                        int l_elen = pgStream.ReceiveInteger4();
469:                        ServerErrorMessage l_errorMsg = new ServerErrorMessage(
470:                                pgStream.ReceiveString(l_elen - 4), logger
471:                                        .getLogLevel());
472:
473:                        if (logger.logDebug())
474:                            logger.debug(" <=BE ErrorMessage(" + l_errorMsg
475:                                    + ")");
476:
477:                        throw new PSQLException(l_errorMsg);
478:
479:                    case 'N':
480:                        // Warning
481:                        int l_nlen = pgStream.ReceiveInteger4();
482:                        ServerErrorMessage l_warnMsg = new ServerErrorMessage(
483:                                pgStream.ReceiveString(l_nlen - 4), logger
484:                                        .getLogLevel());
485:
486:                        if (logger.logDebug())
487:                            logger.debug(" <=BE NoticeResponse(" + l_warnMsg
488:                                    + ")");
489:
490:                        protoConnection.addWarning(new PSQLWarning(l_warnMsg));
491:                        break;
492:
493:                    case 'S':
494:                        // ParameterStatus
495:                        int l_len = pgStream.ReceiveInteger4();
496:                        String name = pgStream.ReceiveString();
497:                        String value = pgStream.ReceiveString();
498:
499:                        if (logger.logDebug())
500:                            logger.debug(" <=BE ParameterStatus(" + name
501:                                    + " = " + value + ")");
502:
503:                        if (name.equals("server_version"))
504:                            protoConnection.setServerVersion(value);
505:                        else if (name.equals("client_encoding")) {
506:                            if (!value.equals("UNICODE"))
507:                                throw new PSQLException(
508:                                        GT
509:                                                .tr("Protocol error.  Session setup failed."),
510:                                        PSQLState.CONNECTION_UNABLE_TO_CONNECT);
511:                            pgStream.setEncoding(Encoding
512:                                    .getDatabaseEncoding("UNICODE"));
513:                        } else if (name.equals("standard_conforming_strings")) {
514:                            if (value.equals("on"))
515:                                protoConnection
516:                                        .setStandardConformingStrings(true);
517:                            else if (value.equals("off"))
518:                                protoConnection
519:                                        .setStandardConformingStrings(false);
520:                            else
521:                                throw new PSQLException(
522:                                        GT
523:                                                .tr("Protocol error.  Session setup failed."),
524:                                        PSQLState.CONNECTION_UNABLE_TO_CONNECT);
525:                        }
526:
527:                        break;
528:
529:                    default:
530:                        if (logger.logDebug())
531:                            logger.debug("invalid message type="
532:                                    + (char) beresp);
533:                        throw new PSQLException(GT
534:                                .tr("Protocol error.  Session setup failed."),
535:                                PSQLState.CONNECTION_UNABLE_TO_CONNECT);
536:                    }
537:                }
538:            }
539:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.