Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SAP Sybase SQL Anywhere 16.0 » SQL Anywhere サーバ プログラミング » JDBC サポート

 

JDBC コールバック

SQL Anywhere JDBC ドライバでは、2 つの非同期コールバックをサポートしています。1 つは SQL MESSAGE 文を処理し、もう 1 つはファイル転送要求を検証します。これは、SQL Anywhere ODBC ドライバでサポートされているコールバックに似ています。

メッセージは、SQL MESSAGE 文を使用してクライアントアプリケーションからデータベースサーバに送信できます。実行時間が長いデータベースサーバ文によってメッセージも生成できます。

メッセージハンドラルーチンを作成して、これらのメッセージを捕捉できます。次に、メッセージハンドラのコールバックルーチンの例を示します。



class T_message_handler implements sybase.jdbc4.sqlanywhere.ASAMessageHandler
{
    private final int MSG_INFO      = 0x80 | 0;
    private final int MSG_WARNING   = 0x80 | 1;
    private final int MSG_ACTION    = 0x80 | 2;
    private final int MSG_STATUS    = 0x80 | 3;
    T_message_handler()
    {
    }

    public SQLException messageHandler(SQLException sqe)
    {
        String msg_type = "unknown";
        
        switch( sqe.getErrorCode() ) {
            case MSG_INFO:      msg_type = "INFO   ";   break;
            case MSG_WARNING:   msg_type = "WARNING";   break;
            case MSG_ACTION:    msg_type = "ACTION ";   break;
            case MSG_STATUS:    msg_type = "STATUS ";   break;
        }
        
        System.out.println( msg_type + ": " + sqe.getMessage() );
        return sqe;
    }
}

クライアントファイル転送要求を検証できます。転送を許可する前に、JDBC ドライバは検証コールバックが存在する場合は、それを呼び出します。ストアドプロシージャからなどの間接文の実行中にクライアントのデータ転送が要求された場合、JDBC ドライバはクライアントアプリケーションで検証コールバックが登録されていないかぎり転送を許可しません。どのような状況で検証の呼び出しが行われるかについては、以下でより詳しく説明します。次に、ファイル転送検証のコールバックルーチンの例を示します。



class T_filetrans_callback implements sybase.jdbc4.sqlanywhere.SAValidateFileTransferCallback
{
    T_filetrans_callback()
    {
    }
    
    public int callback(String filename, int is_write)
    {
        System.out.println( "File transfer granted for file " + filename +                          
                            " with an is_write value of " + is_write );                         
        return( 1 ); // 0 to disallow, non-zero to allow
    }
}

filename 引数は、読み込みまたは書き込み対象のファイルの名前です。is_write パラメータは、読み込み (クライアントからサーバへの転送) が要求された場合は 0、書き込みが要求された場合は 0 以外の値になります。ファイル転送が許可されない場合、コールバック関数は 0 を返します。それ以外の場合は 0 以外の値を返します。

データのセキュリティ上、サーバはファイル転送を要求している文の実行元を追跡します。サーバは、文がクライアントアプリケーションから直接受信されたものかどうかを判断します。クライアントからデータ転送を開始する際に、サーバは文の実行元に関する情報をクライアントソフトウェアに送信します。クライアント側では、クライアントアプリケーションから直接送信された文を実行するためにデータ転送が要求されている場合にかぎり、JDBC ドライバはデータの転送を無条件で許可します。それ以外の場合は、上述の検証コールバックがアプリケーションで登録されていることが必要です。登録されていない場合、転送は拒否されて文が失敗し、エラーが発生します。データベース内に既存しているストアドプロシージャがクライアントの文で呼び出された場合、ストアドプロシージャそのものの実行はクライアントの文で開始されたものと見なされません。ただし、クライアントアプリケーションでテンポラリストアドプロシージャを明示的に作成してストアドプロシージャを実行した場合、そのプロシージャはクライアントによって開始されたものとしてサーバは処理します。同様に、クライアントアプリケーションでバッチ文を実行する場合も、バッチ文はクライアントアプリケーションによって直接実行されるものと見なされます。

次のサンプル Java アプリケーションは、SQL Anywhere JDBC 4.0 ドライバでサポートされているコールバックの使用を示しています。クラスパスにファイル %SQLANY16%\java\sajdbc4.jar を入れる必要があります。



import java.io.*;
import java.sql.*;
import java.util.*;

public class callback
{
    public static void main (String args[]) throws IOException
    {
        Connection          con = null;
        Statement           stmt;

        System.out.println ( "Starting... " );
        con = connect();
        if( con == null )
        {
            return; // exception should already have been reported
        }
        System.out.println ( "Connected... " );
        try
        {
            // create and register message handler callback
            T_message_handler message_worker = new T_message_handler();
            ((sybase.jdbc4.sqlanywhere.IConnection)con).setASAMessageHandler( message_worker );
            
            // create and register validate file transfer callback
            T_filetrans_callback filetran_worker = new T_filetrans_callback();
            ((sybase.jdbc4.sqlanywhere.IConnection)con).setSAValidateFileTransferCallback( filetran_worker );
            
            stmt = con.createStatement();
            
            // execute message statements to force message handler to be called
            stmt.execute( "MESSAGE 'this is an info   message' TYPE INFO TO CLIENT" );
            stmt.execute( "MESSAGE 'this is an action message' TYPE ACTION TO CLIENT" );
            stmt.execute( "MESSAGE 'this is a warning message' TYPE WARNING TO CLIENT" );
            stmt.execute( "MESSAGE 'this is a status  message' TYPE STATUS TO CLIENT" );
            
            System.out.println( "\n==================\n" );
            
            stmt.execute( "set temporary option allow_read_client_file='on'" );
            try
            {
                stmt.execute( "drop procedure read_client_file_test" );
            }
            catch( SQLException dummy )
            {
                // ignore exception if procedure does not exist
            }
            // create procedure that will force file transfer callback to be called
            stmt.execute( "create procedure read_client_file_test()" +
                          "begin" +
                          "    declare v long binary;" +
                          "    set v = read_client_file('sample.txt');" +
                          "end" );
            
            // call procedure to force validate file transfer callback to be called
            try
            {
                stmt.execute( "call read_client_file_test()" );
            }
            catch( SQLException filetrans_exception )
            {
                // Note: Since the file transfer callback returns 1,  
                // do not expect a SQL exception to be thrown
                System.out.println( "SQLException: " +
                                    filetrans_exception.getMessage() );
            }
            stmt.close();
            con.close();
            System.out.println( "Disconnected" );
        }
        catch( SQLException sqe )
        {
            printExceptions(sqe);
        }
    }
   
    private static Connection connect()
    {
        Connection  connection;
        
        System.out.println( "Using jdbc4 driver"  );
        try
        {
            connection = DriverManager.getConnection(
                    "jdbc:sqlanywhere:uid=DBA;pwd=sql" );
        }
        catch( Exception e )
        {
            System.err.println( "Error! Could not connect" );
            System.err.println( e.getMessage() );
            printExceptions( (SQLException)e );
            connection = null;
        }
        return connection;
    }

    static private void printExceptions(SQLException sqe)
    {
        while (sqe != null)
        {

            System.out.println("Unexpected exception : " +
                "SqlState: " + sqe.getSQLState()  +
                " " + sqe.toString() +
                ", ErrorCode: " + sqe.getErrorCode());
            System.out.println( "==================\n" );
            sqe = sqe.getNextException();
        }
    }
}
 参照