⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tdscore.java

📁 jtds的源码 是你学习java的好东西
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
                case 1: // Set OLE transaction ID
                    if (oleTranID != null) {
                        out.write((short)oleTranID.length);
                        out.write(oleTranID);
                    } else {
                        // Delist the connection from all transactions.
                        out.write((short)0);
                    }
                    break;
            }
            out.flush();
            endOfResponse = false;
            endOfResults  = true;
        } catch (IOException ioe) {
            connection.setClosed();
            throw Support.linkException(
                    new SQLException(
                            Messages.get(
                                    "error.generic.ioerror", ioe.getMessage()),
                            "08S01"),
                    ioe);
        } finally {
            if (mutex != null) {
                mutex.release();
            }
        }

        byte[] tmAddress = null;
        if (getMoreResults() && getNextRow()) {
            if (rowData.length == 1) {
                Object x = rowData[0];
                if (x instanceof byte[]) {
                    tmAddress = (byte[])x;
                }
            }
        }

        clearResponseQueue();
        messages.checkErrors();
        return tmAddress;
    }

    /**
     * Obtain the counts from a batch of SQL updates.
     * <p/>
     * If an error occurs Sybase will continue processing a batch consisting of
     * TDS_LANGUAGE records whilst SQL Server will usually stop after the first
     * error except when the error is caused by a duplicate key.
     * Sybase will also stop after the first error when executing RPC calls.
     * Care is taken to ensure that <code>SQLException</code>s are chained
     * because there could be several errors reported in a batch.
     *
     * @param counts the <code>ArrayList</code> containing the update counts
     * @param sqlEx  any previous <code>SQLException</code>(s) encountered
     * @return updated <code>SQLException</code> or <code>null</code> if no
     *         error has yet occured
     */
    SQLException getBatchCounts(ArrayList counts, SQLException sqlEx) {
        Integer lastCount = JtdsStatement.SUCCESS_NO_INFO;

        try {
            checkOpen();
            while (!endOfResponse) {
                nextToken();
                if (currentToken.isResultSet()) {
                    // Serious error, statement must not return a result set
                    throw new SQLException(
                            Messages.get("error.statement.batchnocount"),
                            "07000");
                }
                //
                // Analyse type of end token and try to extract correct
                // update count when calling stored procs.
                //
                switch (currentToken.token) {
                    case TDS_DONE_TOKEN:
                        if ((currentToken.status & DONE_ERROR) != 0
                                || lastCount == JtdsStatement.EXECUTE_FAILED) {
                            counts.add(JtdsStatement.EXECUTE_FAILED);
                        } else {
                            if (currentToken.isUpdateCount()) {
                                counts.add(new Integer(currentToken.updateCount));
                            } else {
                                counts.add(lastCount);
                            }
                        }
                        lastCount = JtdsStatement.SUCCESS_NO_INFO;
                        break;
                    case TDS_DONEINPROC_TOKEN:
                        if ((currentToken.status & DONE_ERROR) != 0) {
                            lastCount = JtdsStatement.EXECUTE_FAILED;
                        } else if (currentToken.isUpdateCount()) {
                            lastCount = new Integer(currentToken.updateCount);
                        }
                        break;
                    case TDS_DONEPROC_TOKEN:
                        if ((currentToken.status & DONE_ERROR) != 0
                                || lastCount == JtdsStatement.EXECUTE_FAILED) {
                            counts.add(JtdsStatement.EXECUTE_FAILED);
                        } else {
                            counts.add(lastCount);
                        }
                        lastCount = JtdsStatement.SUCCESS_NO_INFO;
                        break;
                }
            }
            //
            // Check for any exceptions
            //
            messages.checkErrors();

        } catch (SQLException e) {
            //
            // Chain all exceptions
            //
            if (sqlEx != null) {
                sqlEx.setNextException(e);
            } else {
                sqlEx = e;
            }
        } finally {
            while (!endOfResponse) {
                // Flush rest of response
                try {
                    nextToken();
                } catch (SQLException ex) {
                    // Chain any exceptions to the BatchUpdateException
                    if (sqlEx != null) {
                        sqlEx.setNextException(ex);
                    } else {
                        sqlEx = ex;
                    }
                }
            }
        }

        return sqlEx;
    }

// ---------------------- Private Methods from here ---------------------

    /**
     * Write a TDS login packet string. Text followed by padding followed
     * by a byte sized length.
     */
    private void putLoginString(String txt, int len)
        throws IOException {
        byte[] tmp = Support.encodeString(connection.getCharset(), txt);
        out.write(tmp, 0, len);
        out.write((byte) (tmp.length < len ? tmp.length : len));
    }

    /**
     * Send the SQL Server 2000 pre login packet.
     * <p>Packet contains; netlib version, ssl mode, instance
     * and process ID.
     * @param instance
     * @param forceEncryption
     * @throws IOException
     */
    private void sendPreLoginPacket(String instance, boolean forceEncryption)
            throws IOException {
        out.setPacketType(PRELOGIN_PKT);
        // Write Netlib pointer
        out.write((short)0);
        out.write((short)21);
        out.write((byte)6);
        // Write Encrypt flag pointer
        out.write((short)1);
        out.write((short)27);
        out.write((byte)1);
        // Write Instance name pointer
        out.write((short)2);
        out.write((short)28);
        out.write((byte)(instance.length()+1));
        // Write process ID pointer
        out.write((short)3);
        out.write((short)(28+instance.length()+1));
        out.write((byte)4);
        // Write terminator
        out.write((byte)0xFF);
        // Write fake net lib ID 8.341.0
        out.write(new byte[]{0x08, 0x00, 0x01, 0x55, 0x00, 0x00});
        // Write force encryption flag
        out.write((byte)(forceEncryption? 1: 0));
        // Write instance name
        out.writeAscii(instance);
        out.write((byte)0);
        // Write dummy process ID
        out.write(new byte[]{0x01, 0x02, 0x00, 0x00});
        //
        out.flush();
    }

    /**
     * Process the pre login acknowledgement from the server.
     * <p>Packet contains; server version no, SSL mode, instance name
     * and process id.
     * <p>Server returns the following values for SSL mode:
     * <ol>
     * <ll>0 = Certificate installed encrypt login packet only.
     * <li>1 = Certificate installed client requests force encryption.
     * <li>2 = No certificate no encryption possible.
     * <li>3 = Server requests force encryption.
     * </ol>
     * @return The server side SSL mode.
     * @throws IOException
     */
    private int readPreLoginPacket() throws IOException {
        byte list[][] = new byte[8][];
        byte data[][] = new byte[8][];
        int recordCount = 0;

        byte record[] = new byte[5];
        // Read entry pointers
        record[0] = (byte)in.read();
        while ((record[0] & 0xFF) != 0xFF) {
            if (recordCount == list.length) {
                throw new IOException("Pre Login packet has more than 8 entries");
            }
            // Read record
            in.read(record, 1, 4);
            list[recordCount++] = record;
            record = new byte[5];
            record[0] = (byte)in.read();
        }
        // Read entry data
        for (int i = 0; i < recordCount; i++) {
            byte value[] = new byte[(byte)list[i][4]];
            in.read(value);
            data[i] = value;
        }
        if (Logger.isActive()) {
            // Diagnostic dump
            Logger.println("PreLogin server response");
            for (int i = 0; i < recordCount; i++) {
                Logger.println("Record " + i+ " = " +
                        Support.toHex(data[i]));
            }
        }
        if (recordCount > 1) {
            return data[1][0]; // This is the server side SSL mode
        } else {
            // Response too short to include SSL mode!
            return SSL_NO_ENCRYPT;
        }
    }

    /**
     * TDS 4.2 Login Packet.
     *
     * @param serverName server host name
     * @param user       user name
     * @param password   user password
     * @param charset    required server character set
     * @param appName    application name
     * @param progName   program name
     * @param wsid       workstation ID
     * @param language   server language for messages
     * @param packetSize required network packet size
     * @throws IOException if an I/O error occurs
     */
    private void send42LoginPkt(final String serverName,
                                final String user,
                                final String password,
                                final String charset,
                                final String appName,
                                final String progName,
                                final String wsid,
                                final String language,
                                final int packetSize)
        throws IOException {
        final byte[] empty = new byte[0];

        out.setPacketType(LOGIN_PKT);
        putLoginString(wsid, 30);           // Host name
        putLoginString(user, 30);           // user name
        putLoginString(password, 30);       // password
        putLoginString("00000123", 30);     // hostproc (offset 93 0x5d)

        out.write((byte) 3); // type of int2
        out.write((byte) 1); // type of int4
        out.write((byte) 6); // type of char
        out.write((byte) 10);// type of flt
        out.write((byte) 9); // type of date
        out.write((byte) 1); // notify of use db
        out.write((byte) 1); // disallow dump/load and bulk insert
        out.write((byte) 0); // sql interface type
        out.write((byte) 0); // type of network connection

        out.write(empty, 0, 7);

        putLoginString(appName, 30);  // appname
        putLoginString(serverName, 30); // server name

        out.write((byte)0); // remote passwords
        out.write((byte)password.length());
        byte[] tmp = Support.encodeString(connection.getCharset(), password);
        out.write(tmp, 0, 253);
        out.write((byte) (tmp.length + 2));

        out.write((byte) 4);  // tds version
        out.write((byte) 2);

        out.write((byte) 0);
        out.write((byte) 0);
        putLoginString(progName, 10); // prog name

        out.write((byte) 6);  // prog version
        out.write((byte) 0);
        out.write((byte) 0);
        out.write((byte) 0);

        out.write((byte) 0);  // auto convert short
        out.write((byte) 0x0D); // type of flt4
        out.write((byte) 0x11); // type of date4

        putLoginString(language, 30);  // language

        out.write((byte) 1);  // notify on lang change
        out.write((short) 0);  // security label hierachy
        out.write((byte) 0);  // security encrypted
        out.write(empty, 0, 8);  // security components
        out.write((short) 0);  // security spare

        putLoginString(charset, 30); // Character set

        out.write((byte) 1);  // notify on charset change
        putLoginString(String.valueOf(packetSize), 6); // length of tds packets

        out.write(empty, 0, 8);  // pad out to a longword

        out.flush(); // Send the packet
        endOfResponse = false;
    }

    /**
     * TDS 5.0 Login Packet.
     * <P>
     * @param serverName server host name
     * @par

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -