abstractjdbc1connection.java
来自「PostgreSQL7.4.6 for Linux」· Java 代码 · 共 1,864 行 · 第 1/4 页
JAVA
1,864 行
/*------------------------------------------------------------------------- * * AbstractJdbc1Connection.java * This class defines methods of the jdbc1 specification. This class is * extended by org.postgresql.jdbc2.AbstractJdbc2Connection which adds * the jdbc2 methods. The real Connection class (for jdbc1) is * org.postgresql.jdbc1.Jdbc1Connection * * Copyright (c) 2003, PostgreSQL Global Development Group * * IDENTIFICATION * $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.27.2.4 2004/08/11 06:56:00 jurka Exp $ * *------------------------------------------------------------------------- */package org.postgresql.jdbc1;import java.io.IOException;import java.net.ConnectException;import java.sql.*;import java.util.*;import org.postgresql.Driver;import org.postgresql.PGNotification;import org.postgresql.core.BaseConnection;import org.postgresql.core.BaseResultSet;import org.postgresql.core.BaseStatement;import org.postgresql.core.Encoding;import org.postgresql.core.PGStream;import org.postgresql.core.QueryExecutor;import org.postgresql.core.StartupPacket;import org.postgresql.fastpath.Fastpath;import org.postgresql.largeobject.LargeObjectManager;import org.postgresql.util.MD5Digest;import org.postgresql.util.PGobject;import org.postgresql.util.PSQLException;import org.postgresql.util.PSQLState;import org.postgresql.util.UnixCrypt;public abstract class AbstractJdbc1Connection implements BaseConnection{ // This is the network stream associated with this connection private PGStream pgStream; public PGStream getPGStream() { return pgStream; } protected String PG_HOST; protected int PG_PORT; protected String PG_USER; protected String PG_DATABASE; protected boolean PG_STATUS; protected String compatible; protected boolean useSSL; // The PID an cancellation key we get from the backend process protected int pid; protected int ckey; private Vector m_notifications; /* The encoding to use for this connection. */ private Encoding encoding = Encoding.defaultEncoding(); private String dbVersionNumber; public boolean CONNECTION_OK = true; public boolean CONNECTION_BAD = false; public boolean autoCommit = true; public boolean readOnly = false; public Driver this_driver; private String this_url; private String cursor = null; // The positioned update cursor name private int PGProtocolVersionMajor = 2; private int PGProtocolVersionMinor = 0; public int getPGProtocolVersionMajor() { return PGProtocolVersionMajor; } public int getPGProtocolVersionMinor() { return PGProtocolVersionMinor; } private static final int AUTH_REQ_OK = 0; private static final int AUTH_REQ_KRB4 = 1; private static final int AUTH_REQ_KRB5 = 2; private static final int AUTH_REQ_PASSWORD = 3; private static final int AUTH_REQ_CRYPT = 4; private static final int AUTH_REQ_MD5 = 5; private static final int AUTH_REQ_SCM = 6; // These are used to cache oids, PGTypes and SQLTypes private static Hashtable sqlTypeCache = new Hashtable(); // oid -> SQLType private static Hashtable pgTypeCache = new Hashtable(); // oid -> PGType private static Hashtable typeOidCache = new Hashtable(); //PGType -> oid // Now handle notices as warnings, so things like "show" now work public SQLWarning firstWarning = null; /* * Cache of the current isolation level */ private int isolationLevel = Connection.TRANSACTION_READ_COMMITTED; public abstract Statement createStatement() throws SQLException; public abstract DatabaseMetaData getMetaData() throws SQLException; /* * This method actually opens the connection. It is called by Driver. * * @param host the hostname of the database back end * @param port the port number of the postmaster process * @param info a Properties[] thing of the user and password * @param database the database to connect to * @param url the URL of the connection * @param d the Driver instantation of the connection * @exception SQLException if a database access error occurs */ public void openConnection(String host, int port, Properties info, String database, String url, Driver d) throws SQLException { firstWarning = null; // Throw an exception if the user or password properties are missing // This occasionally occurs when the client uses the properties version // of getConnection(), and is a common question on the email lists if (info.getProperty("user") == null) throw new PSQLException("postgresql.con.user", PSQLState.CONNECTION_REJECTED); this_driver = (Driver)d; this_url = url; PG_DATABASE = database; PG_USER = info.getProperty("user"); String password = info.getProperty("password", ""); PG_PORT = port; PG_HOST = host; PG_STATUS = CONNECTION_BAD; if (info.getProperty("ssl") != null && Driver.sslEnabled()) { useSSL = true; } else { useSSL = false; } if (info.getProperty("compatible") == null) { compatible = d.getMajorVersion() + "." + d.getMinorVersion(); } else { compatible = info.getProperty("compatible"); } //Read loglevel arg and set the loglevel based on this value //in addition to setting the log level enable output to //standard out if no other printwriter is set String l_logLevelProp = info.getProperty("loglevel", "0"); int l_logLevel = 0; try { l_logLevel = Integer.parseInt(l_logLevelProp); if (l_logLevel > Driver.DEBUG || l_logLevel < Driver.INFO) { l_logLevel = 0; } } catch (Exception l_e) { //invalid value for loglevel ignore } if (l_logLevel > 0) { Driver.setLogLevel(l_logLevel); enableDriverManagerLogging(); } //Print out the driver version number if (Driver.logInfo) Driver.info(Driver.getVersion()); if (Driver.logDebug) { Driver.debug(" ssl = " + useSSL); Driver.debug(" compatible = " + compatible); Driver.debug(" loglevel = " + l_logLevel); } // Now make the initial connection try { pgStream = new PGStream(host, port); } catch (ConnectException cex) { // Added by Peter Mount <peter@retep.org.uk> // ConnectException is thrown when the connection cannot be made. // we trap this an return a more meaningful message for the end user throw new PSQLException ("postgresql.con.refused", PSQLState.CONNECTION_REJECTED); } catch (IOException e) { throw new PSQLException ("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } try { //Now do the protocol work if (haveMinimumCompatibleVersion("7.4")) { openConnectionV3(host,port,info,database,url,d,password); } else { openConnectionV2(host,port,info,database,url,d,password); } } catch (SQLException sqle) { // if we fail to completely establish a connection, // close down the socket to not leak resources. try { pgStream.close(); } catch (IOException ioe) { } throw sqle; } } private void openConnectionV3(String p_host, int p_port, Properties p_info, String p_database, String p_url, Driver p_d, String p_password) throws SQLException { PGProtocolVersionMajor = 3; if (Driver.logDebug) Driver.debug("Using Protocol Version3"); // Now we need to construct and send an ssl startup packet try { if (useSSL) { if (Driver.logDebug) Driver.debug("Asking server if it supports ssl"); pgStream.SendInteger(8,4); pgStream.SendInteger(80877103,4); // now flush the ssl packets to the backend pgStream.flush(); // Now get the response from the backend, either an error message // or an authentication request int beresp = pgStream.ReceiveChar(); if (Driver.logDebug) Driver.debug("Server response was (S=Yes,N=No): "+(char)beresp); switch (beresp) { case 'E': // An error occured, so pass the error message to the // user. // // The most common one to be thrown here is: // "User authentication failed" // throw new PSQLException("postgresql.con.misc", PSQLState.CONNECTION_REJECTED, pgStream.ReceiveString(encoding)); case 'N': // Server does not support ssl throw new PSQLException("postgresql.con.sslnotsupported", PSQLState.CONNECTION_FAILURE); case 'S': // Server supports ssl if (Driver.logDebug) Driver.debug("server does support ssl"); Driver.makeSSL(pgStream); break; default: throw new PSQLException("postgresql.con.sslfail", PSQLState.CONNECTION_FAILURE); } } } catch (IOException e) { throw new PSQLException("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } // Now we need to construct and send a startup packet try { new StartupPacket(PGProtocolVersionMajor, PGProtocolVersionMinor, PG_USER, p_database).writeTo(pgStream); // now flush the startup packets to the backend pgStream.flush(); // Now get the response from the backend, either an error message // or an authentication request int areq = -1; // must have a value here do { int beresp = pgStream.ReceiveChar(); String salt = null; byte [] md5Salt = new byte[4]; switch (beresp) { case 'E': // An error occured, so pass the error message to the // user. // // The most common one to be thrown here is: // "User authentication failed" // int l_elen = pgStream.ReceiveIntegerR(4); if (l_elen > 30000) { //if the error length is > than 30000 we assume this is really a v2 protocol //server so try again with a v2 connection //need to create a new connection and try again pgStream.close(); try { pgStream = new PGStream(p_host, p_port); } catch (ConnectException cex) { // Added by Peter Mount <peter@retep.org.uk> // ConnectException is thrown when the connection cannot be made. // we trap this an return a more meaningful message for the end user throw new PSQLException ("postgresql.con.refused", PSQLState.CONNECTION_REJECTED); } catch (IOException e) { throw new PSQLException ("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } openConnectionV2(p_host, p_port, p_info, p_database, p_url, p_d, p_password); return; } throw new PSQLException("postgresql.con.misc", PSQLState.CONNECTION_REJECTED, PSQLException.parseServerError(encoding.decode(pgStream.Receive(l_elen-4)))); case 'R': // Get the message length int l_msgLen = pgStream.ReceiveIntegerR(4); // Get the type of request areq = pgStream.ReceiveIntegerR(4); // Get the crypt password salt if there is one if (areq == AUTH_REQ_CRYPT) { byte[] rst = new byte[2]; rst[0] = (byte)pgStream.ReceiveChar(); rst[1] = (byte)pgStream.ReceiveChar(); salt = new String(rst, 0, 2); if (Driver.logDebug) Driver.debug("Crypt salt=" + salt); } // Or get the md5 password salt if there is one if (areq == AUTH_REQ_MD5) { md5Salt[0] = (byte)pgStream.ReceiveChar(); md5Salt[1] = (byte)pgStream.ReceiveChar(); md5Salt[2] = (byte)pgStream.ReceiveChar(); md5Salt[3] = (byte)pgStream.ReceiveChar(); if (Driver.logDebug) { String md5SaltString = ""; for (int i=0; i<md5Salt.length; i++) { md5SaltString += " " + md5Salt[i]; } Driver.debug("MD5 salt=" + md5SaltString); } } // now send the auth packet switch (areq) { case AUTH_REQ_OK: break; case AUTH_REQ_KRB4: if (Driver.logDebug) Driver.debug("postgresql: KRB4"); throw new PSQLException("postgresql.con.kerb4", PSQLState.CONNECTION_REJECTED); case AUTH_REQ_KRB5: if (Driver.logDebug) Driver.debug("postgresql: KRB5"); throw new PSQLException("postgresql.con.kerb5", PSQLState.CONNECTION_REJECTED); case AUTH_REQ_SCM: if (Driver.logDebug) Driver.debug("postgresql: SCM"); throw new PSQLException("postgresql.con.scm", PSQLState.CONNECTION_REJECTED); case AUTH_REQ_PASSWORD: if (Driver.logDebug) Driver.debug("postgresql: PASSWORD"); pgStream.SendChar('p'); pgStream.SendInteger(5 + p_password.length(), 4); pgStream.Send(p_password.getBytes()); pgStream.SendChar(0); pgStream.flush(); break; case AUTH_REQ_CRYPT: if (Driver.logDebug) Driver.debug("postgresql: CRYPT"); String crypted = UnixCrypt.crypt(salt, p_password); pgStream.SendChar('p'); pgStream.SendInteger(5 + crypted.length(), 4); pgStream.Send(crypted.getBytes()); pgStream.SendChar(0); pgStream.flush(); break; case AUTH_REQ_MD5: if (Driver.logDebug) Driver.debug("postgresql: MD5"); byte[] digest = MD5Digest.encode(PG_USER, p_password, md5Salt); pgStream.SendChar('p'); pgStream.SendInteger(5 + digest.length, 4); pgStream.Send(digest); pgStream.SendChar(0); pgStream.flush(); break; default: throw new PSQLException("postgresql.con.auth", PSQLState.CONNECTION_REJECTED, new Integer(areq)); } break; default: throw new PSQLException("postgresql.con.authfail", PSQLState.CONNECTION_REJECTED); } } while (areq != AUTH_REQ_OK); } catch (IOException e) { throw new PSQLException("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } int beresp; do { beresp = pgStream.ReceiveChar(); switch (beresp) { case 'Z': //ready for query break; case 'K': int l_msgLen = pgStream.ReceiveIntegerR(4); if (l_msgLen != 12) throw new PSQLException("postgresql.con.setup", PSQLState.CONNECTION_UNABLE_TO_CONNECT); pid = pgStream.ReceiveIntegerR(4); ckey = pgStream.ReceiveIntegerR(4); break; case 'E': int l_elen = pgStream.ReceiveIntegerR(4); throw new PSQLException("postgresql.con.backend", PSQLState.CONNECTION_UNABLE_TO_CONNECT, PSQLException.parseServerError(encoding.decode(pgStream.Receive(l_elen-4)))); case 'N': int l_nlen = pgStream.ReceiveIntegerR(4); PSQLException notify = PSQLException.parseServerError(encoding.decode(pgStream.Receive(l_nlen-4))); addWarning(notify.getMessage()); break; case 'S':
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?