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 + -
显示快捷键?