忍者ブログ
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10]

DATE : 2017/12/12 (Tue)
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。


DATE : 2009/11/05 (Thu)

11月1日に「北陸アンカンファレンス2009」に行ってきました。「アンカンファレンス」とは、セッションの内容が事前に決まっておらず、参加者が自由に発表や議題を持ち込んでセッションを開くというスタイルのカンファレンスです。

どのようなセッションが開かれるのかわからず、高度な内容が多そうで初めは発表する気はありませんでした。しかしアンカンファレンスという参加者が自由に発表を持ち込む形式であること、また部屋2つ(当日は3つに増えました)で並行してセッションが開かれると言うことで、奮起して発表を持ち込みました。

とにかくバラエティに富んだセッションが多くて面白かったです。テーマが絞られていないので、本当に何が出てくるのかわからない。IT系のものもあればそうでないものもある、制作したものを発表している方もいれば、ツールの使い方を発表している方、iPhoneにインストールしているアプリを紹介している方もいれば、ディスプレイモニタの解体ショーを実演している方もいる。午前11時から午後5時までの長丁場だったにもかかわらず、どのセッションに参加するかとても悩ましく、時間があっという間に過ぎていきました。自分がふだん情報収集していても気付かない情報が大量にあって、刺激的で見聞がとても広がりました。久々にHudsonに本腰を入れたくなったり、jetpackにも興味を持ちました。非常に勉強熱心な方を見て、ライバル心にも似た気持ちが燃え上がったりもしました。

自分自身の発表「スクリプトからiTunesを操作する(Windowsで)」も、ところどころ詰まりながらもなんとか終えることができました。セッションへ参加された皆さんは熱心な表情でお聞くださりとてもありがたく、楽しかったです。このような機会があれば、またネタを持ち込んで発表したいと思いました。

以下、当日に思ったことをつらづらと書き連ねます。

  • 自分自身の発表資料は、前日の夜遅くまでOpenOffice.org Impressで作成していました。ところが、当日の発表の中にはテキストエディタ中の文字を大きく表示させてスライド代わりにされている方もいました。発表したくなったら空いている時間に自分のセッションを入れても良いという点もアンカンファレンスの魅力なので、テキストエディタを使って即席で資料を作って発表したり、ホワイトボードを使ってアドリブで発表してしまうというのも十分にアリだと感じました。むしろ、それぐらい肩から力を抜いて参加した方が自分自身よかったのかもしれません(;´∀`)本当は、発表ネタを2つ3つ用意していたのですが、1個目のスライド作りだけで力尽きてしまったので……。

  • 1セッション15分でセッション間が途切れなく進むので、実際に発表できる目安は10分ほどでした。ところが自分自身内容を詰め込みすぎて15分の発表資料になってしまい、セッション中は余裕がなく慌ただしく進めざるを得なくなってしまいました。次はもう少し時間に余裕を見て発表資料をまとめようと思いました。
  • 1セッション15分で、並行してセッションが別々の部屋で3つあるため、15分ごとに移動することもたびたびありました。ノートPCの電源の確保が大変でしたし、移動の際には荷物を素早く片付けなければなりませんでした。そのため、アンカンファレンスにはネットブックなどの電源効率が良くて持ち運びしやすいノートPCが必須だと感じました。(;´∀`)いちおう自分はネットブックを持っていったのでなんとかなりました。

一参加者として、北陸アンカンファレンス2009はとても楽しく、刺激的な会となりました。このようなイベントがまたあれば、ぜひ参加して、発表したいと思います。

参考文献

PR

DATE : 2009/06/21 (Sun)

Mapから値を取り出すと同時にオートアンボクシングを使用する場合は、nullが出てくる可能性を考えなければなりません。

Mapからboolean値を取り出してif文で条件分岐をさせるコードを書いたら、NullPointerExceptionが発生してしまいました。NullPointerExceptionが発生した箇所は下記の通りです。

private void function(String key, Map<String, Boolean> map) {
    ...
    if (map.get(key)) {    // NullPointerException発生
        ....
    }
    ...
}

初めは、MapがnullだったためNullPointerExceptionが発生したのかと思いました。しかし動作を調べてみても、Mapにはきちんとインスタンスが割り当てられていました。

実は、NullPointerExceptionが発生していたのは、ラッパークラスのBooleanオブジェクトからプリミティブ値のboolean型へと変換を行うオートアンボクシングの部分でした。NullPointerExceptionが発生した箇所の処理を細かく見ていくと、以下のようになります。

  1. 「map.get(key)」でBooleanオブジェクトを取り出す。
  2. if文の評価にはプリミティブ値のboolean値が必要。
  3. そのため、取り出されたBooleanオブジェクトをプリミティブ値のboolean値にオートアンボクシングする。

問題だったのは、Mapから取り出したBooleanオブジェクトがnullになっていたことでした。キーに対応づく値がMapに存在しなかったためです。nullオブジェクトをアンボクシングしようとすると、NullPointerExceptionが発生します。だから上記の箇所でNullPointerExceptionが発生していたのです。

こういう場合、オートアンボクシングでNullPointerExceptionが発生しないようにするには、Mapから値を取り出す際にはオートアンボクシングせず、取り出した値がnullではないか確かめるほうが安全です。

(;^ω^)問題が発生した書き方だとコードがやけにすっきりするので、nullのことをつい忘れてしまいました。

参考文献


DATE : 2009/02/15 (Sun)

Skype 4.0以上ではsecondaryオプションを付けることで、Skypeがすでに立ち上がっている状態でもさらにSkypeを追加して起動できます。しかし「Skypeがすでに立ち上がっている状態」というのが曲者で、単純に次のようなバッチスクリプトを書いてもSkypeは1つ目のものしか起動しません。なお、本記事ではSkypeは「C:\Program Files\Skype」にインストールされているものとします。その他のフォルダにインストールされている場合は、SKYPE_EXE_DIR変数を、Skype.exeのあるフォルダに書き換えてください。

setlocal
set SKYPE_EXE_DIR="C:\Program Files\Skype\Phone"
start /d %SKYPE_EXE_DIR% Skype.exe
start /d %SKYPE_EXE_DIR% Skype.exe /secondary
endlocal

そこで、1つ目のSkypeを起動したあとにスクリプトの実行をしばらく待機させて、1つ目のSkypeが起動しきってから2つ目のSkypeを立ち上げるようにしました。ただし、指定した時間分待機するようなコマンドはコマンドプロンプトには存在しません。そこで代わりにpingコマンドを使用しました。

setlocal
set SKYPE_EXE_DIR="C:\Program Files\Skype\Phone"
set PAUSE_SEC=60
start /d %SKYPE_EXE_DIR% Skype.exe
REM 1つ目のSkypeの起動を待つため待機
ping -n %PAUSE_SEC% localhost
start /d %SKYPE_EXE_DIR% Skype.exe /secondary
endlocal

このバッチスクリプトをスタートアップに入れておけば、Windowsの起動時にSkypeを同時に2つ立ち上げることができます。なお、上のバッチファイルでは1つ目のSkypeを立ち上げた後に60秒待機してから2つ目のSkypeの起動を行っています。お使いの環境によっては、それが長すぎたり短すぎたりすることもあるので、PAUSE_SEC変数の部分をほどよい秒数に調節してください。

参考文献


DATE : 2008/11/22 (Sat)

Firefox 拡張で、特定の URL が読み込まれた際に他のページへ飛ばすには、nsIWebProgressListener インタフェースを実装したオブジェクトを作ります。

function MyListener() {

}

MyListener.prototype = {

    /*
     * nsIWebProgressListener の実装
     */
        
    QueryInterface : function(aIID) {
        if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
                aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
                aIID.equals(Components.interfaces.nsISupports)) {
            return this;
        }
        
        throw Components.results.NS_NOINSTANCE;
    },
    
    onStateChange : function(aWebProgress, aRequest, aFlag, aStatus) {

    },
    
    onLocationChange : function(aProgress, aRequest, aURI) {

    },
    
    onProgressChange : function(aProgress, aRequest, aCurSelfProgress,
                                 aMaxSelfProgress, aCurTotalProgress,
                                 aMaxTotalProgress) {

    },
    
    onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {

    },
    
    onSecurityChange : function(aWebProgress, aRequest, aState) {

    }
}

nsIWebProgressListener インタフェースを実装したオブジェクトは、ページへのリクエストを監視できます。ページへのリクエストが発生すると onStateChange メソッドが呼ばれるので、このメソッド内に、移動したいページの URL へのリクエストを監視するコードを書きます。

    onStateChange : function(aWebProgress, aRequest, aFlag, aStatus) {
        var url = aRequest.name;

        if (aFlag & Components.interfaces.nsIWebProgressListener.STATE_START) {
            // url のページへのリクエストが発生した際に到達する
        }
    },

リクエストされた URL を取得するには、引数 aRequest の型である nsIRequest の name プロパティを使用します。また、リクエストの開始かどうかは、引数 aFlag のビット列を見ることでわかります。

引数 aRequest の name プロパティの中身が予期していた URL と同じであれば、別のページへ飛ばすようなコードを書きます。ここで、SOURCE_URL は別ページへ飛ばす対象となる URL、DESTINATION_URL は、移動先の URL を表します。

    onStateChange : function(aWebProgress, aRequest, aFlag, aStatus) {
        var url = aRequest.name;

        if (aFlag & Components.interfaces.nsIWebProgressListener.STATE_START) {
            if (url == SOURCE_URL) {
                aWebProgress.DOMWindow.location.replace(DESTINATION_URL);
            }
        }
    },

nsIWebProgress 型である引数 aWebProgress から、現在のページを表示している nsIDOMWindow 型のオブジェクトを取得し、そのページの場所を表す Location オブジェクトを使用して、移動先のページに置き換えます。Location オブジェクトでは、assign メソッドを使用してページを置き換える方法もありますが、上記のコードでは replace メソッドを使用しました。assing メソッドでは置き換えた元のページが履歴に残りますが、replace では残りません。

現在のページの URL は、 nsIDOMWindow 型のオブジェクトから取得した Location オブジェクトを使用しても取得できますが、今回はその方法が使えません。Location オブジェクトの表す URL はすでに読み込みが完了した後のページのものなので、上記のコードで新しくリクエストされた URL を Location オブジェクトから取得しようとしても、現在表示されているページの URL が取得されてしまいます。replace メソッドを使用してページを置き換えると新しいリクエストが発生するので、無限ループになる場合もあります。そのため、リクエストされた URL を使用する際には、必ず引数 aRequest の name プロパティから取得するようにしてください。

(;^ω^)これで長時間つまりました。

あとは、このリスナーオブジェクトを Firefox に登録します。

var myListener = new MyListener();

function load() {
    gBrowser.addProgressListener(
        myListener,
        Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
}

function unload() {
    gBrowser.removeProgressListener(myListener);
}

window.addEventListener("load", load, false);
window.addEventListener("unload", unload, false);

参考文献


DATE : 2008/10/19 (Sun)

Hudson では、Java 以外の言語で作られたプロジェクトの継続的インテグレーションを行うことができます。特に、テスト結果のログを JUnit 形式の XML で出力できる場合、テスト結果の管理もできるので便利です。本記事では、JSUnit を用いてユニットテストを行っている JavaScript プロジェクトを Hudson で管理させる方法について記します。JavaScript プロジェクトは、すでに Hudson に登録できている状態だとします。本記事で使用した Hudson のバージョンは 1.255 で、使用したブラウザは Firefox 3.0.3、JSUnit は 2.2alpha11 です。標準の状態では、Firefox 3 で JSUnit は動きません。その場合は、「JSUnit を Firefox 3 で動作させるメモ」を参考にしてください。

本記事では、実行用のコードが main フォルダ、ユニットテスト用のコードが test フォルダに分けて配置されていることを前提にしています。また、JSUnit 本体は test フォルダに収められているとします。

常用している Firefox プロファイルでテストを行う場合

JSUnit の実行に開発専用のプロファイルを用いず、常用しているプロファイルを使用している場合は、JSUnit 付属の build.xml が使用できます。しかし、JSUnit から出力されるログの形式は JSUnit 独自の形式なので、Hudson でテスト結果を管理するには JUnit 形式のものに変換しなければなりません。そこで、Billy Reisinger 氏が作成されたXSLTを使用して、変換を行います。「JSUnit XML to JUnit XML」から「jsunit_to_junit.xsl」をダウンロードして、テスト用フォルダに配置します。

JSUnit Server から standalone_test を実行した後、JSUnit 形式のログファイルを JUnit 形式に変換する Ant スクリプトは次の通りです。なお、以下のスクリプトでテスト環境の設定を行うため、JSUnit 付属の build.xml の設定を行う必要はありません。また、複数のブラウザでユニットテストを行う場合は、JSUnit 付属の build.xml を呼び出す部分のスクリプトを修正してください。hudson.WORKSPACE プロパティは、Hudson から提供される環境変数で、Hudson の上のプロジェクトのワークスペースフォルダを表します。以下の Ant スクリプトでは、ログファイルを test/logs に名前で出力します。この Ant スクリプトは、「Ant の呼び出し」→「高度な設定」→「ビルドファイル」にそのファイルのパスを指定するだけで使えます。

<?xml version="1.0" encoding="utf-8"?>

<project name="JSUnitForHudson" default="test" basedir=".">
  <description>
    Hudson 上で JSUnit によるユニットテストを行う。
  </description>
  <property environment="hudson"/>

  <!-- プロジェクトのホームディレクトリ -->
  <property name="home"
            location="${hudson.WORKSPACE}/sample"/>
  <!-- テスト対象のページ -->
  <property name="testPage"
            location="${home}/test/testsuite.html"/>
  <!-- JSUnit の動作するポート番号 -->
  <property name="jsunitPort"
            value="8090"/>
  <!-- Firefox のパス -->
  <property name="firefox"
            location="C:\Program Files\Mozilla Firefox\firefox.exe"/>
  <!-- JSUnit のホームディレクトリ -->
  <property name="jsunitHome"
            location="${home}/test/jsunit"/>
  <!-- ログを出力するディレクトリ -->
  <property name="logsDirectory"
            location="${home}/test/logs"/>
  <!-- JSUnit 形式のログファイルを JUnit 形式のログファイルに変換する XSLT -->
  <property name="logTransrator"
            location="${home}/test/jsunit_to_junit.xsl"/>

  <!-- TestRunner -->
  <property name="testRunner"
            location="${jsunitHome}/testRunner.html"/>
  <!-- JSUnit Server を起動する build.xml -->
  <property name="buildScript"
            location="${jsunitHome}/build.xml"/>

  <target name="test">
    <mkdir dir="${logsDirectory}"/>
    <delete includeemptydirs="true">
      <fileset dir="${logsDirectory}" includes="**/*"/>
    </delete>
    <makeurl file="${testRunner}" property="testRunnerURL"/>
    <ant antfile="${buildScript}" dir="${jsunitHome}" target="standalone_test">
      <property name="browserFileNames" value="${firefox}"/>
      <property name="port" value="${jsunitPort}"/>
      <property name="logsdirectory" location="${logsDirectory}"/>
      <property name="url" value="${testRunnerURL}?testPage=${testPage}"/>
    </ant>
    <xslt basedir="${logsDirectory}" destdir="${logsDirectory}"
          style="${logTransrator}">
      <mapper type="glob" from="JSTEST-*.xml" to="JSTEST-*.junit.xml" />
    </xslt>
  </target>
</project>

あとは、「ビルド後の処理」の「JUnitテスト結果の集計」にチェックを入れ、「テスト結果 XML」に出力されるログファイルのパターンを記述すれば完了です。「<ログが出力されるフォルダ>/JSTEST-*.junit.xml」を指定してください。

専用のプロファイルを用いる場合(Windows 向け)

JSUnit 専用のプロファイルを作る

専用のプロファイルを用いる場合は、まず JSUnit 専用のプロファイルを作成することをおすすめします。Firefox 3 の場合、常用以外のプロファイルで起動する場合、プロファイル名以外に「-no-remote」オプションを付けて起動しなければなりません。しかし、すでにそのプロファイルで Firefox 3 が立ち上がっている場合、「-no-remote」オプションを付けると、すでに Firefox 3 が立ち上がっていることを示すメッセージが表示され、新たに起動できません。そのため、テスト実行時のみに起動し、テストが終われば終了できる JSUnit 専用のプロファイルが必要となります。ここでは、そのプロファイル名が「jsunit」であると仮定して話を進めます。

JSUnit でテスト終了時に Firefox を自動的に閉じる設定を行っている場合は、Firefox の再起動時に、前回終了時に読み込んでいたページを復元するか聞かれる場合があります。そのため、「about:config」から次の設定を全て false に設定します。

  • browser.sessionstore.resume_from_crash
  • browser.sessionstore.enabled

Ant スクリプトから専用のプロファイルの Firefox を起動

JSUnit 付属の build.xml では、コマンドラインオプションを付けて Firefox を起動できません。そこで、バッチファイルを用意し、オプションを付けて Firefox を起動する Ant スクリプトを呼び出すようにします。バッチファイル単体でも起動は可能ですが、起動するコマンドの前に他の文が含まれていると、うまく動作しない場合があるためです。

Ant スクリプトは次のようになります。JSUnit のログを JUnit 形式のログに変換するため、Billy Reisinger 氏が作成されたXSLTを「JSUnit XML to JUnit XML」からダウンロード(jsunit_to_junit.xsl)して、テスト用フォルダに配置しておいてください。

テスト終了時に Firefox を強制終了させている点に注意してください。通常では、ユニットテスト終了時に JSUnit Server が Firefox を終了させるのですが、バッチファイルやスクリプトなどから Firefox を起動した場合は JSUnit Server から終了できません。そこで Ant スクリプトから、テストに使用した Firefox を終了させています。Ant スクリプトからはテストに使用した Firefox のプロセス番号を入手できないので、Firefox のウィンドウのタイトルから、終了する Firefox を特定しています。そのため、テスト以外の用途の Firefox も巻き込まれて終了されてしまう場合があります。これを防ぐ場合は、closeFirefoxAfterTestRuns プロパティを false に設定してください。ただし、テストに使用した Firefox も手動で閉じる必要があります。

複数のブラウザでユニットテストを行う場合は、Ant スクリプト中の、JSUnit 付属の build.xml を呼び出す部分を修正してください。hudson.WORKSPACE プロパティは、Hudson から提供される環境変数で、Hudson の上のプロジェクトのワークスペースフォルダを表します。以下の Ant スクリプトでは、ログファイルを test/logs に名前で出力します。この Ant スクリプトは、「Ant の呼び出し」→「高度な設定」→「ビルドファイル」にそのファイルのパスを指定するだけで使えます。

<?xml version="1.0" encoding="utf-8"?>

<project name="JSUnitForHudson" default="test" basedir=".">
  <description>
    Hudson 上で JSUnit によるユニットテストを行う。
  </description>
  <property environment="hudson"/>

  <!-- プロジェクトのホームディレクトリ -->
  <property name="home"
            location="${hudson.WORKSPACE}/trunk"/>
  <!-- テスト対象のページ -->
  <property name="testSuite"
            location="${home}/test/TestSuite.html"/>
  <!-- JSUnit の動作するポート番号 -->
  <property name="jsunitPort"
            value="9091"/>
  <!-- Firefox を起動するバッチファイル -->
  <property name="firefox"
            location="${home}/test/hudson_firefox.bat"/>
  <!-- JSUnit のホームディレクトリ -->
  <property name="jsunitHome"
            location="${home}/test/jsunit"/>
  <!-- ログを出力するディレクトリ -->
  <property name="logsDirectory"
            location="${home}/test/logs"/>
  <!-- JSUnit 形式のログファイルを JUnit 形式のログファイルに変換する XSLT -->
  <property name="logTransrator"
            location="${home}/test/jsunit_to_junit.xsl"/>
  <!-- テスト終了後に Firefox を終了するかどうか。                        -->
  <!-- ウィンドウのタイトルが ${closingFirefoxTitle} のみのものを終了する -->
  <property name="closeFirefoxAfterTestRuns"
            value="true"/>

  <!-- TestRunner -->
  <property name="testRunner"
            location="${jsunitHome}/testRunner.html"/>
  <!-- JSUnit Server を起動する build.xml -->
  <property name="buildScript"
            location="${jsunitHome}/build.xml"/>
  <!-- 終了させる Firefox の、ウィンドウのタイトル -->
  <property name="closingFirefoxTitle"
            value="Mozilla Firefox"/>

  <target name="test">
    <mkdir dir="${logsDirectory}"/>
    <delete includeemptydirs="true">
      <fileset dir="${logsDirectory}" includes="**/*"/>
    </delete>
    <makeurl file="${testRunner}" property="testRunnerURL"/>
    <ant antfile="${buildScript}" dir="${jsunitHome}" target="standalone_test">
      <property name="browserFileNames" value="${firefox}"/>
      <property name="port" value="${jsunitPort}"/>
      <property name="logsdirectory" location="${logsDirectory}"/>
      <property name="url" value="${testRunnerURL}"/>
    </ant>
    <xslt basedir="${logsDirectory}" destdir="${logsDirectory}"
          style="${logTransrator}">
      <mapper type="glob" from="JSTEST-*.xml" to="JSTEST-*.junit.xml" />
    </xslt>
    <antcall target="_closeFirefox"/>
  </target>

  <target name="_closeFirefox" if="closeFirefoxAfterTestRuns">
    <exec executable="TASKKILL" osfamily="Windows">
      <arg value="/IM"/>
      <arg value="firefox.exe"/>
      <arg value="/FI"/>
      <arg value="WINDOWTITLE eq ${closingFirefoxTitle}"/>
      <arg value="/F"/>
    </exec>
  </target>
</project>

Firefox を起動する Ant スクリプトを、呼び出すバッチファイル(hudson_firefox.bat)は次の通りです。Firefox を起動する Ant スクリプトの名前は hudson_firefox.xml としています。

ant -f hudson_firefox.xml
REM Firefox を起動するためのバッチファイル jsunit\build.xml から呼ばれる。
REM 他の文が含まれているとそこで動作が止まってしまうため、本バッチファイルでは
REM ant スクリプトを起動する。
REM 本コメントが ant の実行より上にあると、ant が実行されない場合がある。

Firefox を起動する Ant スクリプト(hudson_firefox.xml)は、次の通りです。各プロパティは、各自の環境に合わせて設定してください。

TestRunner の URL を Ant スクリプト内で生成している点に注意してください。JUnit Server で TestRunner の URL が生成されて、Firefox を起動するバッチファイルにその URL に渡されるのが本来の流れなのですが、「&」や「=」はバッチファイルの引数として使用できません。そのため、Ant スクリプトで URL を生成しています。

<?xml version="1.0" encoding="utf-8"?>

<project name="launchFirefox" default="test" basedir=".">
  <description>
    Firefox を専用のプロファイルで起動してユニットテストを行う。
    hudson_firefox.bat から呼び出される。
  </description>
  <import file="build.xml"/>

  <!-- Firefox のパス -->
  <property name="firefox_exe"
            location="C:\Program Files\Mozilla Firefox\firefox.exe"/>
  <!-- テストを実行する Firefox プロファイル -->
  <property name="profileName"
            value="jsunit"/>

  <target name="test">
    <makeurl file="${testRunner}" property="testRunnerURL"/>
    <exec executable="${firefox_exe}">
      <arg value="-no-remote"/>
      <arg value="-P"/>
      <arg value="${profileName}"/>
      <arg value="${testRunnerURL}?testPage=${testSuite}&amp;autoRun=true&amp;submitResults=localhost:${jsunitPort}/jsunit/acceptor"/>
    </exec>
  </target>
</project>

あとは、「ビルド後の処理」の「JUnitテスト結果の集計」にチェックを入れ、「テスト結果 XML」に出力されるログファイルのパターンを記述すれば完了です。「<ログが出力されるフォルダ>/JSTEST-*.junit.xml」を指定してください。

参考文献

忍者ブログ [PR]
ブログ内検索
最近の状況
リンク
カレンダー
11 2017/12 01
S M T W T F S
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
使用許諾
最新コメント
(08/15)
(05/04)
(03/06)
(03/04)
(09/25)
最新トラックバック
T/O
(11/05)
ブログ内検索
最近の状況
リンク
カレンダー
11 2017/12 01
S M T W T F S
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
使用許諾
最新コメント
(08/15)
(05/04)
(03/06)
(03/04)
(09/25)
最新トラックバック
T/O
(11/05)