Tuesday, November 25, 2014

Alfresco 5.0とSolr 4を手動インストールしてみた(Alfresco 5.0.b以降)

こんにちは。大谷です。

以前、「Alfresco4.2をインストールしてみよう(手動インストール編)」という記事を書いたのですが、先ごろリリースされたAlfresco Community 5.0.bで構成に大きな変更があったので、改めて手動インストールの方法を紹介しようと思います。

※ なお、インストーラを利用したインストールは以前と変わっていませんので、「Alfresco4.0をインストールしてみよう(インストーラ編)」を参照してください。インストーラを使うとウィザードに沿っていくつかの設定項目を入力するだけでAlfrescoがインストールできますので、てっとり早く試してみたい場合はインストーラの利用をお勧めします。

「大きな変更」とはSolr 4への対応のことで、これまでの手順に加えてSolr 4のセットアップが新たに必要になりました。これまでは検索エンジンとしてLuceneを使ったインストール手順を紹介していましたが、Alfresco Community 5.0.bからはLuceneをサポートしなくなっています。なお、本記事では以下のような構成を想定しています。
  • OS : Windows
  • Java : JDK7
  • Alfresco : Alfresco Community 5.0.b
  • アプリケーションサーバ : Tomcat 7
  • RDBMS : MySQL Community Server 5.6
  • Solr 4はAlfrescoと同じTomcatインスタンス上にデプロイ
  • Alfresco - Solr間は非SSL通信


JDKのインストール


  1. こちらのサイトからJDK7をダウンロードします。Alfresco 5.0ではJDK7が必要になります。
  2. ダウンロードしたファイルを実行し、JDKをインストールします。


Tomcatのインストール


  1. Alfresco用のディレクトリを作成します。ここでは、Cドライブ直下にalfresco50bというディレクトリを作成し、以下ではALF_HOMEと表記します(ALF_HOME = C:/alfresco50b)。
  2. Apache TomcatのサイトからTomcat 7をダウンロードします。
  3. ダウンロードしたファイルをALF_HOMEに展開します。展開するとALF_HOME以下にapache-tomcat-<バージョン番号>という名前のディレクトリが作成されますので、このディレクトリをTOMCAT_HOMEと表記します(TOMCAT_HOME = C:/alfresco50b/apache-tomcat-7.0.xx)。


MySQLのインストール


  1. MySQL Developer ZoneからMySQL Community Server 5.6をダウンロードし、インストールします。また、後ほど利用するMySQL Connector/J 5.1(JDBCドライバ)をここからダウンロードします。


Tomcatの設定


  1. Alfresco Community Editionのダウンロードサイトにアクセスし、Alfresco 5.0.b Community -> alfresco-community-5.0.b.zipをダウンロードします。
  2. ダウンロードしたファイルを適当なディレクトリに展開します。このうち、alf_data, amps, bin, solr4ディレクトリをALF_HOMEにコピーし、web_serverディレクトリの中身をTOMCAT_HOMEにコピーします(webapps等既存フォルダへのファイル追加も行われます)。
  3. JDBCドライバをTomcatのクラスパスに配置します。先ほどダウンロードしたMySQL Connector/Jを展開し、mysql-connector-java-5.1.xx-bin.jarを<TOMCAT_HOME>/libにコピーします。
  4. Tomcatの設定を変更します。<TOMCAT_HOME>/conf/catalina.properties のshared.loaderプロパティを以下のように変更します。
  5. shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar
  6. <TOMCAT_HOME>/conf/server.xml の8080番ポートのConnector設定を以下のように変更します。AJPを利用する場合は8009番についてもURIEncoding設定を追加します。
  7. <Connector port="8080" protocol="HTTP/1.1" URIEncoding="UTF-8"
               connectionTimeout="20000"
               redirectPort="8443" />
  8. <TOMCAT_HOME>/bin/catalina.bat に以下の行を追加してJVMの設定を変更します。JRE_HOMEや最大/最小ヒープサイズ等はPCの設定・スペックに応じて変更してください。alfresco.homeは<ALF_HOME>のパスを指定します。
  9. set JRE_HOME=C:\Program Files\Java\jdk1.7.0_xx\jre
    set JAVA_OPTS=-Xms1024m -Xmx2048m -XX:MaxPermSize=512m -server -Dalfresco.home=C:/alfresco50b -Dcom.sun.management.jmxremote
  10. <ALF_HOME>/solr4/context.xml を <TOMCAT_HOME>/conf/Catalina/localhost/solr4.xml にリネーム/コピーし、環境変数の値を環境に応じて設定します。
  11. <Environment name="solr/home"        type="java.lang.String" value="C:/alfresco50b/solr4" override="true"/>
    <Environment name="solr/model/dir"   type="java.lang.String" value="C:/alfresco50b/alf_data/solr4/model" override="true"/>
    <Environment name="solr/content/dir" type="java.lang.String" value="C:/alfresco50b/alf_data/solr4/content" override="true"/>


データベースの作成


Alfrescoはコンテンツのメタデータをデータベースで管理し、コンテンツのファイル実体をファイルシステムで管理します。データベースについてはAlfrescoが起動時に必要なテーブルを自動生成するため、まずはデータベース(とユーザ)を作成しておくだけで構いません。
  1. コマンドプロンプトで以下のコマンドを実行し、MySQLにログインします。
  2. mysql -u root -p
  3. 以下のコマンドでMySQLにAlfresco用のデータベースを作成します。この例では、データベース名をalfrescoとし、ユーザ名/パスワードもalfresco/alfrescoとなります。
  4. create database alfresco default character set utf8 collate utf8_bin;
    grant all on alfresco.* to 'alfresco'@'localhost' identified by 'alfresco' with grant option;


Solrの設定


  1. <ALF_HOME>/solr4/workspace-SpacesStore/conf/solrcore.properties と <ALF_HOME>/solr4/archive-SpacesStore/conf/solrcore.properties のdata.dir.rootプロパティ(インデックス格納先)とalfresco.secureCommsプロパティ(SSL通信か否か)を以下のように変更します。パスは環境に応じて変更してください。
  2. data.dir.root=C:/alfresco50b/alf_data/solr4/index
    alfresco.secureComms=none


外部ツールのインストール


次に、Alfrescoが利用する外部ツールのインストールを行います。ここではLibreOffice, ImageMagick, Ghostscript, SWFTools(pdf2swf)について説明します。この4つのツールの用途は以下のとおりですので、必要に応じてインストール、設定を行ってください。
  • LibreOffice : Alfrescoでファイルフォーマット変換を行う際に使います。PDF変換機能などを利用する場合に設定する必要があります。(手元の環境では少し古い4.1.0.4を利用)
  • ImageMagick : コンテンツのサムネイルやプレビューを生成する際に使います。(手元の環境では6.8.6.9を利用)
  • Ghostscript : ImageMagickが間接的に利用します。(手元の環境では9.10を利用)
  • SWFTools : 一部コンテンツのプレビューを生成する際に使います。(手元の環境では0.9.0を利用)


Alfrescoの設定


続いて、Alfrescoの設定を行います。大きく分けると、データベース接続設定、ファイルシステムの設定、外部ツール連携設定の3つがあります。
  1. <TOMCAT_HOME>/shared/classes/alfresco-global.properties.sample をalfresco-global.propertiesにリネームします。以下のプロパティ設定は全てalfresco-global.propertiesに行います。
  2. データベース接続設定、ファイルシステムの設定について、以下のように設定します(全てデフォルトでコメントアウトされているので、コメントアウトを外して環境に合わせて設定変更してください)。
  3. #
    # Sample custom content and index data location
    #
    dir.root=C:/alfresco50b/alf_data
    
    #
    # Sample database connection properties
    #
    db.username=alfresco
    db.password=alfresco
    
    #
    # MySQL connection
    #
    db.driver=org.gjt.mm.mysql.Driver
    db.url=jdbc:mysql://localhost/alfresco?useUnicode=yes&characterEncoding=UTF-8
  4. 検索エンジンとしてSolr 4を使い、Alfrescoとの通信を非SSL化するために以下の設定を追記します。
  5. index.subsystem.name=solr4
    solr.secureComms=none
  6. 外部ツールとの連携について、環境に合わせて以下のように設定します(コメントアウトされているものもあるので適宜コメントアウトを外すなりして設定変更してください)。
  7. ooo.exe=C:/Program Files (x86)/LibreOffice 4/program/soffice
    ooo.enabled=true
    img.root=C:/Program Files/ImageMagick-6.8.6-Q16
    img.exe=${img.root}/convert.exe
    img.gslib=C:/Program Files/gs/gs9.10/lib
    swf.exe=c:/SWFTools/pdf2swf.exe


Alfrescoの初回起動と追加の設定


最後に、一度Alfrescoを起動してWARファイルを展開し、その展開されたファイルの設定を修正します。
  1. <TOMCAT_HOME>/bin/startup.bat を実行してAlfrescoを起動します。
  2. コンソールの出力内容(もしくはalfresco.logやcatalina.out)をチェックします。初回起動時はデータベースにテーブルを追加する作業やwarファイルを展開する作業がありますので時間がかかりますが、最終的にはExceptionが断続的に出力される状態となります(一部SSL通信の設定が残っているため)
  3. <TOMCAT_HOME>/bin/shutdown.bat を実行してAlfrescoを停止します。
  4. <TOMCAT_HOME>/webapps/alfresco/WEB-INF/web.xml を編集し、SSL設定に関する以下の箇所をコメントアウトします。
  5. <security-constraint>
       <web-resource-collection>
          <web-resource-name>SOLR</web-resource-name>
          <url-pattern>/service/api/solr/*</url-pattern>
       </web-resource-collection>
    
       <auth-constraint>
          <role-name>repoclient</role-name>
       </auth-constraint>
    
       <user-data-constraint>
          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
       </user-data-constraint>
    </security-constraint>
    
    <security-constraint>
       <web-resource-collection>
          <web-resource-name>SOLR</web-resource-name>
          <url-pattern>/s/api/solr/*</url-pattern>
       </web-resource-collection>
    
       <auth-constraint>
          <role-name>repoclient</role-name>
       </auth-constraint>
    
       <user-data-constraint>
          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
       </user-data-constraint>
    </security-constraint>
    
    <security-constraint>
       <web-resource-collection>
          <web-resource-name>SOLR</web-resource-name>
          <url-pattern>/wcservice/api/solr/*</url-pattern>
       </web-resource-collection>
    
       <auth-constraint>
          <role-name>repoclient</role-name>
       </auth-constraint>
    
       <user-data-constraint>
          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
       </user-data-constraint>
    </security-constraint>
    
    <security-constraint>
       <web-resource-collection>
          <web-resource-name>SOLR</web-resource-name>
          <url-pattern>/wcs/api/solr/*</url-pattern>
       </web-resource-collection>
    
       <auth-constraint>
          <role-name>repoclient</role-name>
       </auth-constraint>
    
       <user-data-constraint>
          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
       </user-data-constraint>
    </security-constraint>
    
    <login-config>
       <auth-method>CLIENT-CERT</auth-method>
       <realm-name>Repository</realm-name>
    </login-config>
    
    <security-role>
      <role-name>repoclient</role-name>
    </security-role>
  6. <TOMCAT_HOME>/webapps/solr4/WEB-INF/web.xml を編集し、SSL設定に関する以下の箇所をコメントアウトします。
  7. <security-constraint>
        <web-resource-collection>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>repository</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    
    <login-config>
        <auth-method>CLIENT-CERT</auth-method>
        <realm-name>Solr</realm-name>
    </login-config>
    
    <security-role>
       <role-name>repository</role-name>
    </security-role>


動作確認


以上で設定は完了です。Alfrescoを起動して動作確認してみましょう。

  1. <TOMCAT_HOME>/bin/startup.bat を実行してAlfrescoを起動します。
  2. コンソールの出力内容(もしくはalfresco.logやcatalina.out)をチェックします。正常に起動すると、コンソールもしくはログに"Server startup in xxxxxx ms"と表示されます。
  3. 、ブラウザで http://localhost:8080/share にアクセスします。管理者ユーザのデフォルトユーザ名/パスワードは、admin/adminになりますのでそれを入力します。

  4. ログインに成功し、ユーザダッシュボード画面が表示されたら動作確認完了です!

  5. 念のため、Solrにもアクセスしてみましょう。URLは http://localhost:8080/solr4 です。以下の画面が表示されたらOKです。

以上がAlfresco 5.0(5.0.b以降)をインストールする手順となります。本番環境構築の際には、Solr 4の別建てやAlfresco - Solr間のSSL化など、さらに考慮する必要のある事項がありますが、本質的にはこの手順でいけると思います。

Alfresco 5.0の新機能については本ブログの記事「Alfresco 5.0.bの機能紹介」をチェックしてみてください。また、基本的な使い方については「Alfresco 4.2の使い方 - ユーザ管理・グループ管理」、「Alfresco 4.2の使い方 - リポジトリとサイトの準備をしよう」あたりが参考になるかと思いますので是非ご一読ください。

Tuesday, November 18, 2014

Alfrescoでリアルタイムウイルススキャンを実装する


こんにちは。おおたにです。

今回は、Alfrescoでファイルアップロード時にウイルススキャンを行うようなカスタムモジュールを作ってみたいと思います。想定している環境は、以下のとおりです。Alfrescoについては、多分このままもしくは多少の修正で5.0.xでも動くと思います。
  • Alfresco : Alfresco Community Edition 4.2.f
  • OS : CentOS 6系
  • ウイルススキャンツール : Clam AntiVirus


準備


まずは、AlfrescoとClam AntiVirusをインストールします。AlfrescoのインストールはAlfresco4.0をインストールしてみよう(インストーラ編)Alfresco4.2をインストールしてみよう(手動インストール編)あたりを参考にしてください。

次に、Clam AntiVirusをインストールします。CentOSへのインストールはこちらの記事が参考になります。基本的にはファイルアップロードのタイミングでスキャンコマンドを実行するだけなので、自動起動や定期実行の設定は必要ありません。clamscanコマンドがパス指定なしで実行できるようになっていればOKです。


カスタムモジュールの開発


では、早速コードを見てみましょう。今回作ったコード/設定ファイルは以下の4つになります。なお、サンプルコードはこちらからダウンロードすることができます。
  • VirusScanActionExecuter.java : ウイルススキャン処理の実装
  • VirusDetectException.java : ウイルス検知時に投げるException
  • VirusScan.java : OnContentUpdatePolicyを利用したコンテンツ実体更新フック
  • alfresco-virusscan-sample-context.xml :VirusScanActionExecuterとVirusScanのSpring bean定義ファイル

VirusScanActionExecuter.java

ウイルススキャン処理を、ActionExecuterとして実装します。ActionExecuterとして実装するとActionServiceから名前を指定するだけで処理をキックできるため、Alfresco内での再利用性が高まります。具体的には、ActionExecuterAbstractBaseのexecuteImplに処理を実装します。

public class VirusScanActionExecuter extends ActionExecuterAbstractBase {
...
    @Override
    protected void executeImpl(Action action, NodeRef nodeRef) {
        String fileName = (String) fileFolderService.getFileInfo(nodeRef).getName();
        LOGGER.debug("Virus scan start : " + fileName);

        // Output content to temporary file
        ContentReader contentReader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
        File targetFile = null;
        try {
            targetFile = TempFileProvider.createTempFile(contentReader.getContentInputStream(), "virusscan_", ".bin");
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        // Execute virus scan
        Map<String, String> properties = new HashMap<String, String>();
        properties.put("target", targetFile.getAbsolutePath());
        ExecutionResult result = virusScanCommand.execute(properties);

        // Check result and delete infected file.
        int exitValue = result.getExitValue();
        if (exitValue == 0) {
            LOGGER.debug("Virus not detected : " + fileName);
        } else if (exitValue == 1) {
            fileFolderService.delete(nodeRef);
            throw new VirusDetectException("Virus detected and cleaned up : " + fileName);
        } else {
            LOGGER.error("Unable to scan : " + result);
        }
    }
...
}

VirusScan.java

OnContentUpdatePolicyを利用して、コンテンツ実体更新時(正確にはそのトランザクションのコミット時)にウイルススキャン処理をキックします。

public class VirusScan extends TransactionListenerAdapter implements OnContentUpdatePolicy, InitializingBean {
...
    @Override
    public void onContentUpdate(NodeRef nodeRef, boolean newContent) {
        if (!nodeService.getType(nodeRef).equals(ContentModel.TYPE_CONTENT) || nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT) == null) {
            return;
        }
        AlfrescoTransactionSupport.bindListener(this);
        AlfrescoTransactionSupport.bindResource(NODE_KEY, nodeRef);
    }

    @Override
    public void beforeCommit(boolean readOnly)
    {
        final NodeRef nodeRef = AlfrescoTransactionSupport.getResource(NODE_KEY);
        String fileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);

        LOGGER.debug("beforeCommit start : " + fileName + ", readonly : " + readOnly);
        actionService.executeAction(actionService.createAction("virus-scan-action"), nodeRef);
        LOGGER.debug("beforeCommit end : " + fileName);
    }
}

alfresco-virusscan-sample-context.xml

上記2つの実装をSpring beanとして定義します。VirusScanActionExecuterはvirus-scan-actionという名前で登録し、Java APIやJavaScript API、REST APIからこの名前でウイルススキャン処理を実行できるようになります。

コマンドの中身はLinux用になっているのでOSに応じて変更もしくはOSごとに指定してください。

<bean id="virus-scan-action" class="jp.aegif.alfresco.sample.action.executer.VirusScanActionExecuter" parent="action-executer">
   <property name="contentService">
      <ref bean="ContentService" />
   </property>
   <property name="fileFolderService">
      <ref bean="FileFolderService" />
   </property>
   <property name="virusScanCommand">
      <bean class="org.alfresco.util.exec.RuntimeExec">
         <property name="commandsAndArguments">
            <map>
               <entry key=".*">
                  <list>
                     <value>clamscan</value>
                     <value>--stdout</value>
                     <value>--no-summary</value>
                     <value>${target}</value>
                  </list>
               </entry>
            </map>
         </property>
      </bean>
   </property>
</bean>


テストしてみよう


では、カスタムモジュールを適用し、ウイルススキャン機能をテストしてみましょう。

JavaクラスファイルはalfrescoVirusScanSample.jarなどにパッケージングして<tomcat_dir>/webapps/alfresco/WEB-INF/lib/にコピーし、alfresco-virusscan-sample-context.xmlは<tomcat_dir>/shared/classes/alfresco/extension/にコピーします。もちろんAlfrescoを再起動する必要があります。

そして、クライアントPCはリアルタイムスキャンが無効になっていることを確認します。クラ イアントPCにリアルタイムスキャンが設定されていると、テスト用のウイルスファイルが自動除去されてしまってテストができません。そして、テスト用のウイルスファイルをこちらからダウンロードしておきます。

Alfrescoが起動したら、Alfrescoにログインして先ほどのテスト用ウイルスファイルをアップロードします。以下のようにアップロードに失敗し、ウイルスが検知された旨が表示されればOKです。




さらに、catalina.out等のログにはVirusDetectExceptionが出力されているはずです。

ERROR [extensions.webscripts.AbstractRuntime] [http-bio-8080-exec-19] Exception from executeScript - redirecting to status template error: 10120029 Virus detected and cleaned up : eicar.com.txt
 jp.aegif.alfresco.sample.action.executer.VirusDetectException: 10120029 Virus detected and cleaned up : eicar.com.txt
 at jp.aegif.alfresco.sample.action.executer.VirusScanActionExecuter.executeImpl(VirusScanActionExecuter.java:68)
 ...

まとめ


テストはうまくいきましたでしょうか?以上でウイルススキャンを行うカスタムモジュールの基本的な部分ができたかと思います。実際に利用するにあたっては、さらに以下のようなことを考慮する必要があるかもしれません。
  • 1トランザクションで複数のファイル(ノード)が作成されるような場合には対応していない
    • ウイルススキャンアクション呼び出し部分に工夫が必要
  • clamscanはパフォーマンスが良くない
    • ウイルス定義を予めメモリに展開しておくclamdscanの利用
    • Clam AntiVirus以外のウイルススキャンツールの利用
  • ファイルアップロード時ではなく、アクションメニューから手動で実行したい
    • ウイルススキャンをActionExecuterとして実装しているので簡単に実現できます(何人かが既に実装して公開しています) 

Wednesday, November 12, 2014

Alfresco 5.0.bの機能紹介

こんにちは、かわべです。先日会社の人たちとサバイバルゲームをしました。初体験だったのですがとても楽しかったですし、もっと痛いのかと思いきや顔も体もちゃんと防護されているので意外と平気でした。「痛くないので撃たれたのかどうかよくわかりません」とスタッフさんに言ったら、「それは相手も同じなので、なるべく顔を狙ってあげてください」と笑顔で言われたのが印象的です。(ゲームの終盤になっても狙った場所を打てるような余裕は生まれませんでしたが…)

さて、本日はAlfresco 5.0.bでの追加機能について紹介します。Alfresco 5.0.bがリリースされたのは2014年10月なので少し遅くなってしまいましたが、気にせずいきましょう。記事を作成するにあたってはMac OS X 10.9.5にインストーラを利用してインストールしたAlfresco Community Edition 5.0.bを使用しています。

5.0.aがリリースされた際にも当ブログで新機能の紹介を行い、その際に4.2系と比較して主に「検索」と「プレビュー」が強化されたという風にご紹介しました。5.0.bではこの2点のさらなる強化が見られます。まずはこちらから確認していきましょう。

検索機能の強化(サジェスト、スペルチェック)

5.0.bにおける最大の変化として、インストーラに同梱されるSolrのバージョンが4系になりました(5.0.aの段階ではSolr1.4でした)。Solrのバージョンが上がったことによって、5.0.aで実装された検索フィルタはより高速になり、さらに管理者によって設定を変更・追加できるようになりました。

検索結果右上の「検索マネージャ」をクリックすると、フィルタの管理画面に移動できます。



新規フィルタの作成画面はこんな感じです。フィルタ対象を細かく指定できるようになっています。



検索結果に対してフィルタを適用する場合にはURLが変わるので、よく使う検索条件をブックマークして使用することもできます。

入力途中での予測検索の性能も向上しました。5.0.aと比較するとスマートな表示となっています。



検索結果から続けて検索を行う場合に、入力途中の単語と一致する言葉を存在するコンテンツの名前や内容からサジェストする機能も追加されました。



検索結果が見つからないワードで検索した場合には、自動的に置換したワードで検索をする機能も備わりました。

 

検索結果でのプレビュー

検索結果のページから移動することなく文書をプレビューすることが可能になりました。検索結果のサムネイルをクリックするとプレビュー画面が立ち上がります。このプレビュー画面内での検索もできます。



検索結果に対するアクション実行機能の実装と合わせて、検索がより使いやすくなりました。

その他に追加された機能も少し見てみましょう。

 

アクティビティの記録

ユーザのアクティビティとして「プレビュー」と「ダウンロード」も記録され、ダッシュレットに表示されるようになりました。これまでと比較すると件数が増えてしまうため、類似アクティビティは纏めて折りたたみ表示されるようになりました。


新しいサイトダッシュレット

サイトの利用状況の分析に役立つ2つの新しいダッシュレットが追加されました。サイトのファイルの種類、特定の期間のコントリビュータの内訳をわかりやすいグラフで表示してくれます。今後はこのような分析機能もより強化されていくようなので、こちらも期待です。


 

注意点

便利になった5.0.bですが、削除された機能もいくつかあります。Alfresco Explorerクライアント(いわゆるShareでない旧UI画面)はこのバージョンから利用できなくなりました。
また、当記事で触れたように検索機能が強化されたのですが、インデックスシステムとしてluceneを利用するとこれらの機能を完全に利用することはできません。
詳しくはリリースノートをご覧ください。

 

まとめ

これまでのバージョンを知っている方も知らない方も、ぜひAlfresco 5.0.bをインストールしてこれらの機能を試してみてください。また、今後のAlfresco勉強会でも5.0.bを題材とする回があると思いますので、もっと知りたい方はぜひご参加ください。