    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.hayabusa.report2;
    017
    018import java.io.File;
    019import java.io.IOException;
    020
    021import org.opengion.fukurou.util.AbstractObjectPool;
    022import org.opengion.fukurou.util.Cleanable;
    023import org.opengion.fukurou.util.FileUtil;
    024import org.opengion.hayabusa.common.HybsSystem;
    025import org.opengion.hayabusa.common.SystemManager;
    026
    027/**
    028 * Sofficeのプロセスを管理するファクトリクラスです。
    029 * プロセスプールの実装は、AbstractObjectPoolを継承して実装されています。
    030 *
    031 * プロセスの初期生成数は0です。最大生成数は、システムリソースのREPORT_MAX_PROCESS_COUNTで
    032 * 定義されます。また、生存時間は、REPORT_PROCESS_ALIVEで定義されています。
    033 *
    034 * プロセスを全て終了するには、clearメソッドを呼び出します。
    035 * clearメソッドは、Cleanableインターフェースの実装として組み込まれ、SytemManagerに登録されるため、
    036 * Tomcat終了時に、自動的にプロセスが終了されます。
    037 * 但し、貸し出し中(処理中)のプロセスは、AbstractObjecgPoolの実装から、終了されないため、別の方法で
    038 * 明示的にkillする必要があります
    039 *
    040 * @version  4.0
    041 * @author   Hiroki Nakamura
    042 * @since    JDK5.0,
    043 */
    044public final class ProcessFactory {
    045
    046        /**
    047         * プロセスプール
    048         */
    049        private static ProcessPool pp = new ProcessPool() ;
    050
    051        /** Cleanable インターフェースによる初期化処理 */
    052        static {
    053                Cleanable clr = new Cleanable() {
    054                        public void clear() {
    055                                ProcessFactory.clear();
    056                        }
    057                };
    058                SystemManager.addCleanable( clr );
    059
    060                // 5.2.2.0 (2010/11/01) 循環参照解消のため、SystemManager から移動
    061                Cleanable clr2 = new Cleanable() {
    062                        public void clear() {
    063                                ProcessFactory.kill();
    064                        }
    065                };
    066                SystemManager.addCleanable( clr2 , true );      // コンテキスト終了時のみ呼び出す
    067        }
    068
    069        /**
    070         * デフォルトコンストラクターをprivateにして、
    071         * オブジェクトの生成をさせないようにする。
    072         */
    073        private ProcessFactory() {
    074        }
    075
    076        /**
    077         * OpenOfficeのプロセスを生成します。
    078         *
    079         * @return      sofficeのプロセス
    080         */
    081        public static SOfficeProcess newInstance() {
    082                return pp.newInstance();
    083        }
    084
    085        /**
    086         * OpenOfficeのプロセスをリリースします。
    087         *
    088         * @param  soffice SOfficeProcessオブジェクト
    089         */
    090        public static void release( final SOfficeProcess soffice ) {
    091                pp.release( soffice );
    092        }
    093
    094        /**
    095         * OpenOfficeのプロセスをクローズします。
    096         *
    097         * @param   soffice SOfficeProcessオブジェクト
    098         */
    099        public static void remove( final SOfficeProcess soffice ) {
    100                pp.remove( soffice );
    101        }
    102
    103        /**
    104         * プールされているOpenOfficeのプロセスを全てクローズします。
    105         */
    106        public static void clear() {
    107                pp.clear();
    108        }
    109
    110        /**
    111         * 全てのsoffice.binプロセスをKILLします。
    112         * アプリケーションの終了処理で実行します。
    113         * OS名がWindowsを含む場合はtaskkill、それ以外の場合はkillallします。
    114         * 又、プロセス終了後にコピーされた設定ファイルを削除します。
    115         *
    116         * @og.rev 4.3.0.0 (2008/07/18) 追加
    117         * @og.rev 4.3.0.0 (2008/07/22) 設定ファイルの削除を追加
    118         * @og.rev 4.3.5.0 (2009/02/01) Exception をそれぞれのExceptionに分けて捕らえる。
    119         */
    120        public static void kill() {
    121                try {
    122                        final String osName = HybsSystem.sys( "OS_INFO" ); //System.getProperty("os.name");
    123                        if( osName.indexOf( "Windows" ) >= 0 ){
    124                                // 4.3.0.0 (2008/07/18) Windoesのtaskkillを利用してsoffice.binのタスクを強制終了します。
    125                                new ProcessBuilder( "cmd.exe","/c","taskkill","/F","/IM","soffice.bin" ).start().waitFor();
    126                        }
    127                        else{
    128                                // 4.3.0.0 (2008/07/24) Windowsではない場合はkillallコマンド
    129                                new ProcessBuilder( "killall","-9","-w","soffice.bin" ).start().waitFor();
    130                        }
    131
    132                        // 4.3.0.0 (2008/07/22) 設定ファイル(SOfficeProcessでディレクトリを設定)を全削除します。
    133                        FileUtil.deleteFiles( new File( SOfficeProcess.ENV_DIR ) );
    134                }
    135                catch( IOException ex ) {
    136                        ex.printStackTrace();
    137                }
    138                catch( InterruptedException ex ) {
    139                        ex.printStackTrace();
    140                }
    141                catch( RuntimeException ex ) {
    142                        ex.printStackTrace();
    143                }
    144        }
    145
    146        /**
    147         * 現在の状態を文字列で返します。
    148         *
    149         * @return  現在の状態
    150         */
    151        public static String information() {
    152                return pp.toString();
    153        }
    154
    155        /**
    156         * ProcessPool は、AbstractObjectPool を継承した オブジェクトプールです。
    157         *
    158         * OpenOfficeのプロセスをプールします。
    159         *
    160         * @version  4.0
    161         * @author   Hiroki Nakamura
    162         * @since    JDK5.0,
    163         */
    164        protected static class ProcessPool extends AbstractObjectPool<SOfficeProcess> {
    165                // 環境ファイル作成の識別用
    166                private int count = 0;
    167
    168                /**
    169                 * 初期処理を行います。
    170                 */
    171                protected ProcessPool() {
    172                        init( 0, HybsSystem.sysInt( "REPORT_MAX_PROCESS_COUNT")
    173                                        , true, HybsSystem.sysInt( "REPORT_PROCESS_ALIVE" ) );
    174                }
    175
    176                /**
    177                 * soffieのプロセスオブジェクトを作成します。
    178                 *
    179                 * @og.rev 4.3.5.0 (2009/02/01) Exception ではなく、RuntimeException に変更
    180                 * @og.rev 5.1.7.0 (2010/06/01) TCP接続対応
    181                 *
    182                 * @return OpenOfficeのプロセス
    183                 */
    184                protected SOfficeProcess createInstance() {
    185                        SOfficeProcess soffice = null;
    186                        try {
    187                                // 5.1.7.0 (2010/06/01) TCP接続対応
    188                                if( "TCP".equalsIgnoreCase( HybsSystem.sys( "REPORT_OOO_CONN_TYPE" ) ) ) {
    189                                        soffice = new SOfficeProcessTcp( "env_" + count, HybsSystem.sysInt( "REPORT_OOO_MIN_PORT" ) );
    190                                }
    191                                else {
    192                                        soffice = new SOfficeProcess( "env_" + count );
    193                                }
    194                                soffice.bootstrap();
    195
    196                                count++;
    197                        }
    198                        catch( RuntimeException ex ) {
    199                                System.out.println( "[ERROR]OOo:Failed to Connect Soffice! " + ex.getMessage() );
    200                        }
    201                        return soffice;
    202                }
    203
    204                /**
    205                 * オブジェクトプールから削除するときに呼ばれます。
    206                 * このメソッドで各オブジェクトごとの終了処理を行います。
    207                 *
    208                 * @param soffice OpenOfficeのプロセス
    209                 */
    210                protected void objectFinal( final SOfficeProcess soffice ) {
    211                        soffice.close();
    212                }
    213        }
    214}
    215