Smart CODE
生成済みコードに関するオンラインガイド

Web ページの取り込み。既製の例題を使った学習


概要

これまでは、従来のプログラムを作成し、アプリケーションコードをインタフェースから分離しておくための手法を説明してきました。 

次の 2 つの例題は、アプリケーションの範囲を拡張し、ローカルマシンにあるファイルにアクセスして使用するのと同様に、インターネット上やローカルイントラネット内など外部にあるリソースを簡単に使用する方法を示しています。 

以下の例題では、HTML リソース、すなわち Web サーバーから使用できる URL だけを使用しています。しかし、この手法は、株価からイメージや映画まで、インターネット上で公開されているあらゆるデータを取り込むためにも使用できます。また、サーバーがサーチエンジンやオンライン翻訳サービスなどの書式に基づいた照会メカニズムを提供している場合は、もちろんプログラムでやり取りすることが可能です。Web サーバーとやり取りを行い、情報にアクセスすることは、Web ブラウザの専門分野ではありません。 

以下の例題では URL 接続アプリケーションが作成されます。インタフェースには 3 つのテキストフィールドがあり、ファイアウォールがある場合はプロキシホストとプロキシポートを設定することができます。さらに当然ながら、取り込む URL に入ることができます。 

「Fetch」ボタンにはスマートコールバックが設定されます。このボタンを押すと、適切な Web サーバーに接続され、URL がダウンロードされます。 

最初の例題で、受信した URL を処理するために提供したルーチンは、それを加工せずにテキストウィジェットに単純にドロップします。2 番目の例題では、受信した HTML の構文解析を行い、リンクだけを表示します。 

例題を実行する前に必要な作業と知識

環境変数、ほか

通常どおり、パスには必ず $XDROOT/bin を指定します。

例題を使用した作業を始める前に設定が必要な変数は、以下のものです。

XDROOT
LM_LICENSE_FILE

例題を準備する

手順 1 新しいディレクトリを作成し、ここでは仮に htmlfetch という名前を付けます。
手順 2 htmlfetch ディレクトリに移動します。
手順 3 xdreplay スクリプトの $XDROOT/src/examples/sc/fetch.vcr を使用して、xdesigner を実行します。次のように指定します。
$ xdreplay -f $XDROOT/src/examples/sc/fetch.vcr xdesigner

これを実行すると、アプリケーション例題が作成され、コードが生成され、記述しておいたコールバックの標準バージョンが適切な箇所にコピーされて、プログラムを構築するための呼び出しが行われます。 

例題を実行する

まず、環境変数が設定されていることを確認します。問題がある場合は、正しく設定されているかチェックします。
$ ls $XDROOT

次のように入力してアプリケーション例題を実行します。
$ ./untitled

プログラムのサイズを変更し、アクセスしたときに、テキストデータ領域が HTML を表示するために十分な大きさになるようにします。

ファイアウォールが存在する場合、Web ブラウザ用にプロキシを設定するときと同様に、「プロキシ・ホスト」フィールドにプロキシの名前を設定し、「プロキシ・ポート」フィールドにポート番号を設定する必要があります。 

URL を取り込んで処理するには、次の例のように、「URL」フィールドに完全な URL を入力します。

http://www.ist.co.uk/index.html

次に、「Fetch」ボタンを押します。 

生の HTML がテキストウィジェット内に格納されます。

例題の説明

インタフェースを作成する

手順 1 アプリケーションシェル、フォーム、ボタンを各 1 つずつ、テキストフィールドを 3 つ、テキストウィジェットを 1 つ作成します。
手順 1a 3 つのテキストフィールドを区別するために、Proxy、Port、URL を表すラベルを 3 つ追加することもできます。 
手順 1b 配置エディタを使用して、フォームを設定し、ダイアログのサイズを変更したときに、テキストウィジェットが拡大するようにすることもできます。このテキストウィジェットに HTML をはめ込みます。 
手順 2 3 つのテキストフィールドに proxyport、および url という名前を付けます。さらにテキストウィジェットに data という名前を付けます。 
手順 3 最初のテキストフィールドをクリックし、次に Shift キーを押しながらほかのテキストフィールドとテキストウィジェットをクリックして、それらを選択します。 
手順 4 ツールバーから、「新規グループに追加」を選択します。グループエディタが表示されたら、それを閉じます。 
手順 5 ボタンを選択して、「コールバック」ダイアログを開き、コールバックに doit_callback という名前を付けます。「スマートコード」のチェックボックスをオンにして、「スタイル」オプションメニューから「インターネット」を選択します。次に「グループ」ボタンを押し、グループエディタでそのグループが選択されていることを確認してから、「適用」ボタンを押します。 
手順 6 この時点で、「カスタマイズ」ボタンが有効になります。このボタンを押して、「カスタマイズ 」ダイアログにアクセスします。このダイアログが表示されたら次の処理を行います。 
手順 7a 「プロキシ・ホスト」にmyProxy という関数を設定します。
手順 7b 「プロキシ・ポート」に myPort という関数を設定します。
手順 7c 「URL」に myURL という関数を設定します。
手順 7d カスタム・データ・ハンドラ」領域で、「受信 (URL の内容)」フィールドに myData という独自の関数を設定します。 
手順 8 これらの変更を適用し、「カスタマイズ」ダイアログを閉じます。次に、「コールバック」ダイアログで「追加」ボタンを押します。 

「コールバック」ダイアログを閉じます。 

手順 9 メニューバーの「生成」メニューから「生成」を選択し、「コード生成」ダイアログを開きます。言語に C を選択していること、ディレクトリの指定が正しいこと、およびスタブを生成するためのトグルがオンに なっていることを確認します。

 「生成」ボタンを押します。 

Access 関数

前述の例では、インターネット用のプロパティには定数値を設定していました。実際のプログラムでは、プロキシおよびポートの使用法や接続するサーバーなどの情報を文字列としてハードコードすることはまれです。これらが機能するようにすると、スタブの getter および setter が callout ディレクトリに 1 組生成され、インターネットの接続層によって使用されます。 

getter および setter を使用して、これらの関数を通常どおりインタフェースのテキストフィールドにハードコードすることができます。 

プロキシホスト
static char * myHost_value = (char*)0;

char *
get_myHost ( AnyGroup_t* ingroup)
{
        mygroup_t * group = (mygroup_t*)ingroup;

        myHost_value = SC_GET(Value,group->proxy);

        return myHost_value;
}

プロキシポート
static char * myPort_value = (char*)0;

char *
get_myPort ( AnyGroup_t* ingroup)
{
        mygroup_t * group = (mygroup_t*)ingroup;

        myPort_value = SC_GET(Value,group->port);

        return myPort_value;
}

URL
static char * myURL_value = (char*)0;

char *
get_myURL ( AnyGroup_t* ingroup)
{
        mygroup_t * group = (mygroup_t*)ingroup;

        myURL_value = SC_GET(Value,group->url);

        return myURL_value;
}

URL データを処理する

「カスタマイズ」ダイアログで、デフォルトのデータハンドラを無効にし、受信データをユーザーが完全に制御できるようにします。 

次のアクセスを可能にするためのスタブが生成されます。

  • グループ 
  • 受信する URL の MIME 型 
  • データ長 (わかっている場合) 
  • InputStream としての URL そのもの
  • int
    myData ( sc_data_t * data )
    {
            mygroup_t * group = (mygroup_t*)data->group;
            char      * type  = data->content_type; /* MIME 型 */
            InputStream i     = (InputStream) data->data;
            int         len   = data->content_length;
    
            /* コードをここに追加します */
    
            return 0;
    }
    
    
    追加するコードは、非常に単純です。 
            DataInputStream di = openDataInputStream( i);
            char * buf         = (*di->readAll)( di, &len);
    
            SC_SET(Value,group->data, buf);
    
            (*di->closeStream)( di);
    
    

    注意