Apache Tomcat 6.0.32 インストールメモ

すいません、完全に自分用のメモです(笑)。。

Redmine さんを家で動かす(JRuby on Rails 動作)ようになってからローカルサーバで Apache Tomcat が常時起動になりましたが、 そのバージョンが 6.0.32 に上がっていましたのでアップデートしてみました。 CentOS 5.5 でデーモン起動しています。

こういうの Redmine の wiki に書いておいているのですが、Tomcat アップデート中は Redmine みれないのでこちらに。。(笑)

IMG_0097

まずは動作環境。

$ uname -a
Linux localhost.localdomain 2.6.18-194.32.1.el5 #1 SMP Wed Jan 5 17:53:09 EST 2011 i686 i686 i386 GNU/Linux
$ java -version
java version "1.6.0_21"
Java(TM) SE Runtime Environment (build 1.6.0_21-b06)
Java HotSpot(TM) Server VM (build 17.0-b16, mixed mode)

いままで全然気が付かなかったのですが、Linux 版の Java はデフォルト Server VM モードであがるんですね。 Windows は Client VM がデフォルトであがるので、Linux でも Server VM 使うように昔から引数設定していましたが、、実は不要だったようです。

てなわけで Tomcat ダウンロードしてデーモン起動する jsvc をつくって入れるまで。 /opt/tomcat6 にいれています。 tomcat ユーザは作成のこと。

$ sudo /etc/init.d/tomcat6 stop
$ cd /opt
$ sudo wget http://ftp.jaist.ac.jp/pub/apache/tomcat/tomcat-6/v6.0.32/bin/apache-tomcat-6.0.32.tar.gz
$ sudo tar zxvf apache-tomcat-6.0.32.tar.gz
$ sudo mv apache-tomcat-6.0.32/ tomcat6/
$ sudo chown -R tomcat:tomcat tomcat6/
$ sudo cp /opt/tomcat6/bin/commons-daemon-native.tar.gz /root
$ sudo su - root
# cd
# tar zxvf commons-daemon-native.tar.gz
# cd commons-daemon-1.0.5-native-src/
# ./configure --with-java=/usr/java/default/
# make
# cp jsvc /opt/tomcat6/bin/
# chown tomcat:tomcat /opt/tomcat6/bin/jsvc
# /etc/init.d/tomcat6 start
# /etc/init.d/tomcat6 stop
# cd /opt/tomcat6/conf/Catalina/localhost/
# vi redmine.xml
# cp redmine.xml redmine.xml.org
# chown tomcat:tomcat *
# chmod 644 *
# /etc/init.d/tomcat6 start

ちなみに、redmine.xml はコンテキストルートと .war のパス設定のみ。

$ cat /opt/tomcat6/conf/Catalina/localhost/redmine.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/redmine" docBase="/home/apache/redmine/redmine.war" />

デーモン起動用の init.d シェル。

$ cat /etc/init.d/tomcat6
#!/bin/sh
#
# chkconfig: - 80 20
# description: jsvc

# Source function library.
. /etc/init.d/functions

JAVA_HOME=/usr/java/default
CATALINA_HOME=/opt/tomcat6
TOMCAT_USER=tomcat
TMP_DIR=/tmp
CATALINA_OPTS=
CLASSPATH=\
$JAVA_HOME/lib/tools.jar:\
$CATALINA_HOME/bin/commons-daemon.jar:\
$CATALINA_HOME/bin/bootstrap.jar
PIDFILE=/var/run/tomcat.pid
LOCKFILE=/var/lock/subsys/tomcat
DAEMON=$CATALINA_HOME/bin/jsvc

start(){
    #
    # Start Tomcat
    #

    echo -n "Starting tomcat6: "
    $DAEMON \
    -pidfile $PIDFILE \
    -user $TOMCAT_USER \
    -home $JAVA_HOME \
    -Dcatalina.home=$CATALINA_HOME \
    -Djava.io.tmpdir=$TMP_DIR \
    -outfile $CATALINA_HOME/logs/catalina.out \
    -errfile '&1' \
    $CATALINA_OPTS \
    -cp $CLASSPATH \
    org.apache.catalina.startup.Bootstrap

    #
    # To get a verbose JVM
    #-verbose \
    # To get a debug of jsvc.
    #-debug \
    RETVAL=$?
    if [ $RETVAL = 0 ]; then
        echo_success
        touch $LOCKFILE
    else
        echo_failure
    fi
    echo
}

stop(){
    #
    # Stop Tomcat
    #
    echo -n "Shutting down tomcat6: "
    $DAEMON \
    -stop \
    -pidfile $PIDFILE \
    org.apache.catalina.startup.Bootstrap
    RETVAL=$?
    if [ $RETVAL = 0 ]; then
        echo_success
        rm -f $PIDFILE $LOCKFILE
    else
        echo_failure
    fi
    echo
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    status)
        status $DAEMON
        RETVAL=$?
        ;;
    *)
        echo $"Usage: jsvc {start|stop|restart|status}"
        exit 1
        ;;
esac

Apache httpd と Apache Tomcat をつなぐ proxy_ajp.conf。

$ cat /etc/httpd/conf.d/proxy_ajp.conf

LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

#
# When loaded, the mod_proxy_ajp module adds support for
# proxying to an AJP/1.3 backend server (such as Tomcat).
# To proxy to an AJP backend, use the "ajp://" URI scheme;
# Tomcat is configured to listen on port 8009 for AJP requests
# by default.
#

#
# Uncomment the following lines to serve the ROOT webapp
# under the /tomcat/ location, and the jsp-examples webapp
# under the /examples/ location.
#
#ProxyPass /tomcat/ ajp://localhost:8009/
#ProxyPass /examples/ ajp://localhost:8009/jsp-examples/

ProxyPass /redmine ajp://localhost:8009/redmine

Tomcat と全然関係ないですが、fastladder を動かしている passenger.conf。

$ cat /etc/httpd/conf.d/passenger.conf
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15
PassengerRuby /usr/bin/ruby

<VirtualHost *:8081>
   ServerName localhost.localdomain
   DocumentRoot /opt/fastladder/public
   <Directory /opt/fastladder/public>
      AllowOverride all
      Options -MultiViews
   </Directory>
</VirtualHost>

さらに関係ないですが、Redmine とつないでいる subversion.conf。

$ cat /etc/httpd/conf.d/subversion.conf

LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule authz_svn_module   modules/mod_authz_svn.so

#
# Example configuration to enable HTTP access for a directory
# containing Subversion repositories, "/var/www/svn".  Each repository
# must be readable and writable by the 'apache' user.  Note that if
# SELinux is enabled, the repositories must be labelled with a context
# which httpd can write to; this will happen by default for
# directories created in /var/www.  Use "restorecon -R /var/www/svn"
# to label the repositories if upgrading from a previous release.
#

#
# To create a new repository "http://localhost/repos/stuff" using
# this configuration, run as root:
#
#   # cd /var/www/svn
#   # svnadmin create stuff
#   # chown -R apache.apache stuff
#

<VirtualHost *:8082>
   <Location />
      DAV svn
      SVNParentPath /home/apache/svn
      SVNListParentPath on
      DavDepthInfinity on
      Order deny,allow
      Deny from all
      Allow from 127.0.0.1
      Allow from 192.168.0.0/24
      AuthType Basic
      AuthName "Authorization Realm"
      AuthUserFile /home/apache/passwd/.htpasswd
      Require valid-user
   </Location>
</VirtualHost>

以上。

[tegaki]すいません、すいません。。[/tegaki]

Firefox 4.0 beta と WebGL

Linux 版の Firefox 4.0 も beta11 まできまして、だいぶ良い感じに動くようになってきました。 最初はテキストボックスのキー入力がやたら遅かったり、タブの描画がおかしかったりなかなかのベータ感だったのですが、もう常用しても大丈夫な感じです(といっても当然テスト用です)

Linux 版の Firefox ってちょっと特殊で GTK のテーマをそのまま持ってくるようにつくってあります。 なので4.0 で特徴的なウインドウフレームと閉じるの統合とか、オレンジ色の右上とかはまだありません。 この辺をどうするのか興味深いですね。 🙂

firefox10

そんな 4.0 の新機能の一つ WebGL、まだ Intel GPU 系が未対応のあるみたいですが、結構面白いです。 Chrome さんも 9.0 で標準 enable になってみたいですね。  Firefox 4.0 も beta9 だったか 10 だったかで標準 enable になったと思います。

Chrome 9.0 か Firefox 4.0 beta (+OpenGL 対応カード)を使っている方は以下のサイトでデモを楽しむことができます。

WebGL Experiments

WebGL is a new web technology that brings hardware-accelerated 3D graphics to the browser without installing additional software.To try these WebGL experiments with Google Chrome, please download and install it below.

一応、Chrome デモ用のサイトですが、ほとんどが Firefox 4.0 でも問題なく動作するようです。

webgl01

WebGL は JavaScript 経由で PC グラフィックカードの OpenGL ES API を呼び出すことができます。 ぱらっとみる限り 1:1 の薄いラッパーのようです。 たぶん OpenGL 知っている方ならすぐ描画できると思います。

OpenGL ES は iPhone とか Android 機でも使われている OpenGL のサブセットです。

webgl02

webgl03

サブセットとはいえ、プログラマルシェーダをカードに送り込んだりもできますので表現力があります。

既に JavaScript のフレームワークもいくつかでているようです。

GLGE WebGL Library/Framework

GLGE is a javascript library intended to ease the use of WebGL; which is basically a native browser javascript API giving direct access to openGL ES2, allowing for the use of hardware accelerated 2D/3D applications without having to download any plugins.

サイトにはなんだか市販ゲームのようなスクリーンショットもみえますね。 🙂

webgl04

対応ブラウザは今のところ Webkit 系と Gecko 系になると思いますので、全ブラウザ対応とはいきませんがワンポイントで対応していればすごくなる的な使い方はできるのではないかと思います。 たとえば、このサイトの右の kougaburari のところとか 対応していれば OpenGL で描画してみたりしてみたりですね!

速くなったとはいえまだまだ JavaScript に性能はくわれちゃうと思いますが、シェーダ含めてローカル資源を活用できるという意味で面白い技術です。 😀

Groovy と GUI アプリケーション

たまに作業の関係で OS ネイティブの GUI アプリケーションを作りたくなる時があります。 適当に自分用につくったコマンドラインベースのものが "ウケ” がよくて GUI に昇格させてみんなに使ってもらう、なんてときですね。 🙂

加えてぼくは普段 Linux を使っていますが、折角なのでたまに使う Windows でも同じもの動かしたいなんて要求が加わってくると使う環境は絞られてきて、、 GTK + スクリプト系言語とか Mono とか Java + Swing とかで、、いろいろやってみましたが一番簡単にランタイム環境を用意できて綺麗に動かせるのは Java + SWT ではないかと思います。

というわけで、SWT。

しかも SWT あまり分かっていないのに、これを Groovy の groovy-swt モジュールを使って呼び出してみました。 …分からないことだらけで大変(笑)

Groovy – GroovySWT

GroovySWT is a wrapper around SWT, the eclipse Standard Widget Toolkit. It allows you to easily write Eclipse SWT applications by using Groovy’s builder mechanism.

これが何かといえば、Groovy お得意の動的言語の機能をつかって、GUI のツリーを Groovy 記述で構築してしまおうというものです。

GUI コンポーネントを扱ったことがある方なら分かりますが、これらは親子関係とかいろいろ大変ですのでこれを解決しようという動きです。 XML 定義に Groovy の制御構文が使える、というイメージで扱うのがよさそうです。

ちなみに、GroovySWT のダウンロードですが、現在あろうことかリンクが切れていますのでリポジトリからダウンロードします。

Revision 21442: /trunk/groovy/modules/groovy-swt/dist

groovy-swt-0.5-examples.zip

groovy-swt-0.5-windows-all.jar

groovy-swt-0.5-without-swt.jar

without-swt のほうがうまいこと swt だけ除いてある jar になっていますので、Windows 以外の場合は without と各機種にあった swt をいっしょにクラスパスに通しておきます。

GroovySWT 0.5 時点での SWT 依存は 3.5 になっていましたので以下からダウンロードできます。(trunk のコミットコメントみると 3.5.1 でもよさそうな感じです)

Eclipse Project

swt-3.5-win32-win32-x86.zip
swt-3.5-win32-win32-x86_64.zip
swt-3.5-wpf-win32-x86.zip
swt-3.5-win32-wce_ppc-arm-j2se.zip
swt-3.5-win32-wce_ppc-arm-j2me.zip
swt-3.5-gtk-linux-x86.zip
swt-3.5-gtk-linux-x86_64.zip
swt-3.5-gtk-linux-ppc.zip
swt-3.5-motif-linux-x86.zip
swt-3.5-gtk-solaris-sparc.zip
swt-3.5-gtk-solaris-x86.zip
swt-3.5-motif-solaris-sparc.zip
swt-3.5-motif-hpux-ia64_32.zip
swt-3.5-photon-qnx-x86.zip
swt-3.5-motif-aix-ppc.zip
swt-3.5-cocoa-macosx.zip
swt-3.5-cocoa-macosx-x86_64.zip
swt-3.5-carbon-macosx.zip

各 OS の環境に合わせた x32 とか x64 とか使えばOKです。 Windows は WPF 版なんかが目を引きますね。 🙂

commons-logging-1.1.1.jar も動作時に class not found したので入れました。 swt.jar と groovy-swt-0.5.without-swt.jar とあとは Groovy の jar を入れれば準備OKです。

またこれを使ってプログラムかくにはクラスライブラリのソースコード必須です。 swt と groovy-swt のソースはダウンロードして jar にアタッチしておきましょう。(まずは groovy.swt.SwtBuilder からみると良さそうです。あとは SWT のコンポーネントソース見てプロパティ設定していきます)

ということでこの状態でから始めたのですが、、

[tegaki]どーやってもメニューが追加できない!![/tegaki]

サンプルもうまく動いていない模様。  ここの解明が疲れました。。

どうやら groovy-swt のライブラリに不具合があるようです(たぶん)。

これであっているかどうかな上にひどいコードですが、以下のようにパッチ。。(早く動かしたくて手抜きしたの図)

しかも diff 逆にとってしまったのはご愛嬌。。 + と – がさかさまです(笑)

Index: WidgetFactory.java
===================================================================
--- WidgetFactory.java    (revision 5)
+++ WidgetFactory.java    (revision 2)
@@ -119,19 +119,14 @@
                                 Object[] arguments = { parent, new Integer(style) };
                                 return constructor.newInstance(arguments);
                             }
+                            // lets try to find the constructor with 1
+                            // arguments
+                        } else if (types.length == 1
+                                && types[0].isAssignableFrom(parent.getClass())) {
+                            Object[] arguments = { parent };
+                            return constructor.newInstance(arguments);
                         }
                     }
-                    // lets try to find the constructor with 1
-                    // arguments
-                    for (int i = 0, size = constructors.length; i < size; i++) {
-                        Constructor constructor = constructors[i];
-                        Class[] types = constructor.getParameterTypes();
-                        if (types.length == 1
-                                && types[0].isAssignableFrom(parent.getClass())) {
-                            Object[] arguments = { parent };
-                            return constructor.newInstance(arguments);
-                        }
-                    }
                 }
             }
             return beanClass.newInstance();

SWT の org.eclipse.swt.widgets.Menu は 2引数コンストラクタがあって parent と style が設定できて、parent が Shell オブジェクトで style が SWT.BAR のときにメニューとしてはりつくと思うのですが、パッチ前の処理では 1引数コンストラクタを先に見つけてしまうため、style なしで new されてうまくメニューがでないという不具合のようです。(たぶん他の Widget は 2引数のコンストラクタが上のほうに定義されているのでしょう)

さて、そんなこんなで以下のつくったソースで動作させてみる。

変数定義の位置がおかしいとか大文字小文字が混在しているとかは気にしない方向で。  万が一動かしてみたい奇特な方がいらっしゃいましたら、画像のところはコメントアウトしてください。 🙂

import groovy.swt.SwtBuilder
import org.eclipse.swt.layout.GridData;
 
class Gonswt {
 
   def shell
   def sashForm1
   def builder
   def tab
 
   def run() {
      builder = new SwtBuilder()
      shell = builder.shell (text:'Groovy on SWT', size:[410, 600], location:[300,200]) {
         menu(style:"BAR") {
            menuItem("バインダー" , style:"CASCADE") {
               menu( style:"DROP_DOWN") {
                  menuItem(style:"PUSH", "&Open file")
                  menuSeparator()
                  menuItem(style:"PUSH", "E&xit"){
                     onEvent('Selection'){
                        shell.dispose()
                     }
                  }
               }   
            }
            menuItem("焼きそばん" , style:"CASCADE") {
            }
         }
         gridLayout()
         composite() {
            rowLayout()
            toolBar( style:"FLAT, WRAP, RIGHT") {
               toolItem(style:"push", "再チャレンジ") {
                  image( src:'resource/item1.png' )
               }
               toolItem(style:"push", "里に帰ろう") {
                  image( src:'resource/item2.png' )
               }
            }
         }
         composite(layoutData:gridData(horizontalSpan:3
            , horizontalAlignment:GridData.FILL
            , verticalAlignment:GridData.FILL
            , grabExcessHorizontalSpace:true
            , grabExcessVerticalSpace:true)) {
            fillLayout()
            sashForm1 = sashForm( style:"vertical") {
               tab = cTabFolder( id: 'myTabs', tabHeight:28, simple:false, style:"BORDER") {
                  fillLayout()
                  //gridData( style:'fill_both')
                  cTabItem( 'タイムマシーン', style:'none') {
                     table(linesVisible:true, headerVisible:true, style:"V_SCROLL") {
                        tableColumn("食べたい", width:80)
                        tableColumn("食べちゃいたい", width:60)
                        10.times {
                           tableItem(["", "ほげほげ"]) {
                              image:image( src:'resource/item3.png' )
                           }
                           tableItem(["", "もげもげ"]) {
                              image:image( src:'resource/item4.png' )
                           }
                           tableItem(["", "ほえほえ"]) {
                              image:image( src:'resource/item5.png' )
                           }
                        }
                     }
                  }
                  cTabItem( 'マンション', style:'none') {
                     text( style:'border, multi, v_scroll, h_scroll', 'Content for Tab1' ) 
                  }
                  cTabItem( 'ダイレクトショッピング', style:'none') {
                     text( style:'border, multi', 'Content for Tab2' ) 
                  }
               }
               composite( style:"none" ) {
                  fillLayout()
                  text( style: "border, multi, wrap")
                  }
            }
            // 2つの weight を決める
            sashForm1.weights = [90, 10]
            // デフォルト表示タブ
            tab.setSelection(0)
         }
         composite(style:"BORDER") {
            rowLayout()
            toolBar( style:"FLAT, WRAP, LEFT") {
               toolItem(style:"push", "ラーメンバー")
            }
         }
      }
 
      // fillLayout のときは縮められるので pack を false にする
      shell.doMainloop(false)
   }
 
   public static void main(String[] args) {
      new Gonswt().run();
   }
}

とりゃ、実行!

Linux 版。

groovy30

Windows 版。

groovy31

Mac 版。 は、残念ながら手元に機械がないのでできません(笑)

てなことで、いい感じでネイティブ描画されて同じように表示されているのが分かります。 可変ウインドウもばっちりです。 斜めタブは Eclipse でおなじみの CTabFolder 。

自分で使いそうな GUI 部品はだいたい入れてみて動いたので、この後は知恵と勇気でなんとかいけそうです。。 間違ってるかもですが。。

まぁ正直なところ SWTBuilder 使わなくても当然 Groovy からは SWT を直接呼べるのでそっちでもいいのですが、これはお遊びということで。 ちなみに、JFace の Builder もありますので、そちらを使えばコンポーネント・データバインディングを使うことができます。

一応描画ができるようになったので、あとはイベントリスナーとスレッド系の操作が分かればなにかつくれそうです。 Groovy でやると確かにお手軽感あります!

もうちょっとやってみます。 🙂