Wednesday, April 24, 2013

Alfrescoでcron的なスケジュール処理を行う時の注意点

こんにちは。

溶連菌(≠人喰いバクテリア)感染症のおおたにです。喉の痛みと下がらない熱で結構苦しいです。
さて、今日はAlfrescoでスケジュール処理を定義したり、そのスケジュールを変更したりするときに気を付けるポイントを紹介しようと思います。

まず、Alfrescoにはcronよろしく指定されたタイミングでジョブを実行する仕組みを持っています。Quartzというオープンソースのジョブスケジューラを使っており、例えば、非同期のインデックス生成であるとか、日次のインデックスバックアップ処理であるとか、LDAP連携時のユーザ情報同期処理などがこの仕組みで動いています。これらの処理の実施タイミングについては、やはりcronと同様の表現で指定します。

index.backup.cronExpression=0 0 3 * * ?

上の例は、webapps/alfresco/WEB-INF/classes/alfresco/repository.propertiesで定義されているインデックスバックアップの実行スケジュールです。これを毎月3日0時0分と読んだ方は注意が必要です。多分このように読んだ方は、Linuxのcron式のフォーマットに従って読んだのだと思います。
Linuxでは「<分> <時> <日> <月> <曜日> <年(オプション)>」ですが、Quartzでは以下のとおり、1桁目が秒となってります。

  <秒> <分> <時> <日> <月> <曜日> <年(オプション)>

なので、先ほどの例は月次処理ではなく、毎日3時0分に開始する日次処理ということになります。詳しくはScheduled Actions - alfrescowikiを参照してください(すいません英語です)。

今回はcron式のフォーマットについての注意点を紹介しましたが、機会があれば、スケジュールジョブの実装方法についても紹介したいと思います。

Wednesday, April 17, 2013

Alfresco4.2をインストールしてみよう(手動インストール編)

こんにちは。大谷です。

以前、Alfresco4.0をインストールしてみよう(手動インストール編)という記事を書いたのですが、現在の最新版が4.2.cで、必要なJDKやTomcatの要件も変わってきているので、改めてインストールの方法を紹介しようと思います。相変わらずですが、OSはWindowsを想定しており、構成はTomcat/MySQLとしています。なお、インストーラを利用したインストールは以前と変わっていませんので、Alfresco4.0をインストールしてみよう(インストーラ編)を参照してください。


JDKをインストールする


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


Tomcatを準備する


  1. Alfresco用のディレクトリを作成します。ここでは、Cドライブ直下にalfresco42cというディレクトリを作成し、以下ではALF_HOMEと表記します(ALF_HOME = c:/alfresco42c)。
  2. cd c:/
    mkdir alfresco42c
  3. Apache TomcatのサイトからTomcatをダウンロードします。本記事では、Alfresco 4.2.cのインストーラに同梱されているTomcatと同じバージョンである7.0.30を利用します。
  4. ダウンロードしたファイルをALF_HOMEに展開します。展開するとALF_HOME以下にapache-tomcat-<バージョン番号>という名前のディレクトリが作成されますので、このディレクトリをTOMCAT_HOMEと表記します(TOMCAT_HOME = c:/alfresco42c/apache-tomcat-7.0.30)。


MySQLを準備する


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


AlfrescoをTomcatにデプロイする


  1. Alfresco Community Editionのダウンロードサイトにアクセスし、"Custom Installs & Optional Modules"のリンクからalfresco-community-4.2.c.zipをダウンロードします。
  2. ダウンロードしたファイルを適当なディレクトリに展開します。このうち、bin, licenses, web-serverディレクトリの中身をAlfrescoのディレクトリにコピーします。
    • bin/* -> <ALF_HOME>/bin
    • licenses/* -> <ALF_HOME>/licenses
    • web-server/* -> <TOMCAT_HOME>
    ALF_HOME、TOMCAT_HOME以下は次のようになります。
     c:\alfresco42c のディレクトリ
    
    [.]                    [..]                   [apache-tomcat-7.0.30] [bin]                  [licenses]
     c:\alfresco42c\apache-tomcat-7.0.30 のディレクトリ
    
    [.]             [..]            [bin]           [conf]          [endorsed]      [lib]           LICENSE
    [logs]          NOTICE          RELEASE-NOTES   RUNNING.txt     [shared]        [temp]          [webapps]
    [work]
  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番ポートの設定を以下のように変更します。
  7.     <Connector port="8080" protocol="HTTP/1.1" URIEncoding="UTF-8"
                   connectionTimeout="20000" 
                   redirectPort="8443" />
  8. JVMのヒープサイズを設定します。<TOMCAT_HOME>/bin/catalina.batに以下の行を追加します。JRE_HOMEや最大/最小ヒープサイズ等はPCの設定・スペックに応じて変更してください。
  9. set JRE_HOME=C:\Program Files\Java\jdk1.7.0_0xx\jre
    set JAVA_OPTS=-Xms1024m -Xmx2048m -Xss1024k -XX:MaxPermSize=256m -XX:NewSize=256m -server -Dcom.sun.management.jmxremote


データベースを設定する


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;
  5. Alfrescoが上記データベースを使用するように設定ファイルを変更します。<TOMCAT_HOME>/shared/classes/alfresco-global.properties.sampleをalfresco-global.propertiesにリネームし、テキストエディタで開いて以下のように変更します(コメントアウトされている場合はそのコメントアウトを外し、環境に合うように設定を変更してください)。
  6. #
    # 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

  7. 引き続きalfresco-global.propertiesを編集し、dir.rootプロパティを設定します。dir.rootはコンテンツ実体やインデックス情報を格納するディレクトリを指定するプロパティですが、<ALF_HOME>/alf_dataあたりを設定しておくと無難です。
  8. dir.root=c:/alfresco42c/alf_data


その他の設定を行う


最後に、その他のツールとの連携設定を行います。ここではOpenOffice/LibreOffice、ImageMagick、SWFTools(pdf2swf)について説明します。この3つのツールの用途は以下のとおりですので、必要に応じてインストール、設定を行ってください。
  • OpenOffice/LibreOffice : Alfrescoでファイルフォーマット変換を行う際に使います。PDF変換機能などを利用する場合に設定する必要があります。
  • ImageMagick : コンテンツのサムネイルやプレビューを生成する際に使います。
  • SWFTools : コンテンツのプレビューを生成する際に使います。
  1. それぞれのサイト(OpenOffice.orgもしくはLibreOfficeImageMagickSWFTools)からツールをダウンロードし、インストールします。次に、alfresco-global.propertiesをテキストエディタで開き、以下のプロパティを設定します。
    • ooo.exeはOpenOffice実行ファイルのパスを指定します。
    • img.rootはImageMagickのインストール先、img.dynはライブラリディレクトリ、img.exeは実行ファイルパスを指定します。Linuxの場合はimg.rootを設定するだけで動くかもしれません。
    • swf.exeはSWFToolsに入っているpdf2swfの実行ファイルパスを指定します。
    ooo.exe=C:/Program Files (x86)/OpenOffice.org 3/program/soffice
    ooo.enabled=true
    img.root=C:/alfresco/ImageMagick-6.7.3-7
    img.dyn=${img.root}
    img.exe=${img.root}/convert.exe
    swf.exe=C:/alfresco/SWFTools/pdf2swf.exe
    なお、筆者手元の環境は、OpenOffice 3.3.0、ImageMagick 6.7.3-7-Q16、SWFTools 0.9.0となっています(ちょっと古めのリリースを利用しています)。


Alfrescoを起動して動作確認する


以上で設定は終わりです。最後にAlfrescoを起動して動作確認を行います。
  1. <TOMCAT_HOME>/bin/startup.batを実行し、コンソールの出力内容(もしくはalfresco.logやcatalina.out)をチェックします。初回起動時はデータベースにテーブルを追加する作業やwarファイルを展開する作業がありますので時間がかかります。
  2. 起動が正常終了すると、コンソールもしくはログに"Server startup in xxxxxx ms"と表示されます。
  3. 正常に起動したら、ブラウザからAlfrescoにアクセスしてみましょう。http://localhost:8080/shareにアクセスします。管理者ユーザのデフォルトユーザ名/パスワードは、admin/adminになりますのでそれを入力します。
  4. 正常にログインし、ダッシュボード画面が表示されたらめでたく動作確認完了です!
以上がAlfrescoを手動インストールする手順になります。Alfrescoを実際に使ってみるにあたっては、弊社Webサイトからダウンロードできるユーザガイド等が役立つと思いますので是非参考にしてみてください。

Wednesday, April 10, 2013

CMIS: What are Secondary object types?

The main advantage of ECM servers over file servers is the ability to have metadata about the documents, and the ability to define what metadata should exist, on what kind of document.

For instance, an ECM administrator might decide that pictures should have a height and a width metadata, while bills should have a price metadata. In CMIS parlance, pictures and bills are called "primary types".

Most ECM servers also have a "secondary type" concept. Secondary types are more transverse, and can be applied to documents of any primary type. For instance, "Confidentiality" can be applied to images as well as bills. A document can only have one primary type, but can have several secondary types.
A few examples: Versionability, effectivity, geographic details, audio details, ...

Forgotten in CMIS 1.0, secondary types are now part of the CMIS 1.1 standard, which should be official soon.

Example with Alfresco

In Alfresco, a secondary type is called an "aspect". You can easily add aspects to any document. There are predefined aspects, but you can also define custom aspects.

For instance, let's say we manage field observation reports, and each observation report has a latitude and longitude. So, let's add the predefined "Geographic" secondary type to a document. In the document's details page, click on "Manage Aspects":


 Then add the "Geographic" aspect:




The latitude and longitude are now part of the document's metadata properties:


Looks nice in the Alfresco client, but how is it via CMIS?

The CMIS 1.1 standard is not official yet, so unfortunately in Alfresco 4.2.0, secondary type properties can not yet be seen in the CMIS properties:


Instead, you have to get them via the CMIS extensions, which is a mechanism for vendor-specific tricks:


Actually, there is an open source Java library that makes it easy to retrieve them from there. But I would suggest waiting for CMIS 1.1, you will then be able to use secondary type properties easily, in a way that will work on all ECM servers.

Nicolas Raoul

Alfrescoでユーザごとの使用容量を制限したい! -クオータの自動設定とか-

こんにちは。

 4月から娘が転園する関係で慣らし保育だったりとか自身が風邪引いたりとか(会社でも流行ってます)でてんやわんやのおおたにです。
 弊社は幸い業務内容によっては自宅やコワーキングスペースでの作業が認められているため、それらを駆使しつつ何とか仕事をこなしています。まあ慣らし保育だと通常よりも早い時間に迎えに行かなくてはならないのでそこは有休をうまく使ったりして乗り切っています。

 さて、今回はAlfrescoのクオータ設定についてのお話しです。Alfrescoではユーザごとにクオータを設定することができます(現時点での最新版Alfresco 4.2.cにて確認)。ただし、デフォルトのクオータサイズを指定してユーザ作成時に自動設定するようなことはできず、ユーザごとに手動で設定する必要があります(もしくは一括でクオータを設定するようなスクリプトを流すなど)。



 そこで今回は、クオータを自動設定するための方法を紹介したいと思います。前提条件としては、Alfrescoの開発環境が整っていることです。詳しくはここあたりを参照してみてください。

 開発内容自体は大したことは無くて、以下のクラス1個と定義ファイル1個を作るだけです。UserQuotaPolicyクラスはビルド後jarファイル等にしてクラスパス(<alf_dir>/tomcat/webapps/alfresco/WEB-INF/lib/)にコピーします。

jp.aegif.sample.UserQuotaPolicy
public class UserQuotaPolicy implements NodeServicePolicies.OnCreateNodePolicy
{
    private PolicyComponent policyComponent;
    private NodeService nodeService;
    private ContentUsageService contentUsageService;

    public void setPolicyComponent(PolicyComponent policyComponent) {
        this.policyComponent = policyComponent;
    }
    public void setNodeService(NodeService nodeService) {
        this.nodeService = nodeService;
    }
    public void setContentUsageService(ContentUsageService contentUsageService) {
        this.contentUsageService = contentUsageService;
    }

    public void init() {
        policyComponent.bindClassBehaviour(
            NodeServicePolicies.OnCreateNodePolicy.QNAME, ContentModel.TYPE_PERSON,
            new JavaBehaviour(this, "onCreateNode", Behaviour.NotificationFrequency.TRANSACTION_COMMIT));
    }

    @Override
    public void onCreateNode(ChildAssociationRef childAssociationRef) {
        String userName = (String)nodeService.getProperty(childAssociationRef.getChildRef(), ContentModel.PROP_USERNAME);
        long currentUserQuota = contentUsageService.getUserQuota(userName);
        if (currentUserQuota < 0) {
            contentUsageService.setUserQuota(userName, 524288000L);
        }
    }
}

<alf_dir>/tomcat/shared/classes/alfresco/extension/user-quota-context.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
    <bean id="defaultUserQuota" class="jp.aegif.sample.UserQuotaPolicy" init-method="init">
        <property name="policyComponent">
            <ref bean="policyComponent" />
        </property>
        <property name="nodeService">
            <ref bean="nodeService" />
        </property>
        <property name="contentUsageService">
            <ref bean="contentUsageImpl" />
        </property>
    </bean>
</beans>

 UserQuotaPolicyクラスではPolicyという仕組を利用しており、ノード作成時にそのノードタイプがcm:personノード(ユーザの情報を保持するノードタイプ)であった場合に、クオータを設定する処理を自動実行します。Policyは今回利用したOnCreateNodePolicy以外にもたくさん定義されているので、何らかの処理の際に独自の処理を挿入するようなカスタマイズを行う時にはよくお世話になります。とても重宝する拡張ポイントですので、是非覚えておいてください。

 あとは、定義ファイルを指定のディレクトリにコピーし、Alfrescoを再起動するだけです。早速ユーザを追加し、クオータが自動設定されていることを確認してみてください。今回の例ではクオータを決め打ちで500MBとしていますが、この値を定義ファイルから指定できるようにするとより便利になるので、そちらも是非チャレンジしてみてください。

Thursday, April 4, 2013

How to get the HTTPS headers?

Long-time sniffers remember tracking HTTP headers down the wire using Ethereal (now Wireshark), but this has become impossible in environments where everything is encrypted (HTTPS).

In such environments, tracking headers means monitoring either directly within the server process (difficult in clouds), or within the client process (typically a browser).

Recently I had to reverse-engineer the convoluted authentication to the CMIS endpoint of a Sharepoint server. Below is my tale, and the tools I tried (spoiler: only the last one did the job).

Contestant 1: Chrome Developer Tools

In Chrome, I start Incognito mode (CTRL-SHIFT-N) to make sure no saved passwords/cookies interfere, fire up the Developer Tools (CTRL-SHIFT-I), select "Network" to see the requests, and launch the request.

As seen in the screenshot below, Chrome shows the conversation between client and server. Something sounds fishy: Only 2 requests, and the last one is marked as "canceled" even though download succeded... let's try another tool!



Contestant 2: Firefox Web Console

In Firefox, I start Private Browsing mode (CTRL-SHIFT-P), fire up the Web Console (CTRL-SHIFT-K), unselect everything but "Net", and launch the request.

Firefox wins over Chrome by showing the right number of requests (four):


Now to the job: Getting the HTTPS headers!
I click on a request, and something awful happens: a totally unusable window appears, displaying what I need (request headers and response headers), but preventing me from copy-pasting it.

Mouse selection goes crazy, and copying everything results in an unusable long string containing everything aggregated without spaces [1]. Not to mention the inexact timestamp [2], the content that does not scale with the window [3], and the weird titles font style [4].


Fine if you just want to see the headers, but real hackers want to script-parse and diff the headers, right? Next!


Winner: Httpfox

In Firefox, after having installed the Httpfox extension, I start Private Browsing, fire up Httpfox (SHIFT-F2), press "Start", and launch the request.
The lower part shows the headers, and copying them is accessible via the context menu... perfect!



Conclusion: Httpfox is the easiest way to get HTTPS headers.
If you know any other convenient tool, please let us know in the comments!
Nicolas Raoul