    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" ) != -1 ){
    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                        if( osName.indexOf( "Windows" ) >= 0 ){
    132                                // 4.3.0.0 (2008/07/18) Windoesのtaskkillを利用してsoffice.binのタスクを強制終了します。
    133                                new ProcessBuilder( "cmd.exe","/c","taskkill","/F","/IM","soffice.bin" ).start().waitFor();
    134                        }
    135                        else{
    136                                // 4.3.0.0 (2008/07/24) Windowsではない場合はkillallコマンド
    137                                new ProcessBuilder( "killall","-9","-w","soffice.bin" ).start().waitFor();
    138                        }
    139
    140                        // 4.3.0.0 (2008/07/22) 設定ファイル(SOfficeProcessでディレクトリを設定)を全削除します。
    141                        FileUtil.deleteFiles( new File( SOfficeProcess.ENV_DIR ) );
    142                }
    143//              catch( Exception ex ) {
    144//                      ex.printStackTrace();
    145//              }
    146                catch( IOException ex ) {
    147                        ex.printStackTrace();
    148                }
    149                catch( InterruptedException ex ) {
    150                        ex.printStackTrace();
    151                }
    152                catch( RuntimeException ex ) {
    153                        ex.printStackTrace();
    154                }
    155        }
    156
    157        /**
    158         * 現在の状態を文字列で返します。
    159         *
    160         * @return  現在の状態
    161         */
    162        public static String information() {
    163                return pp.toString();
    164        }
    165
    166        /**
    167         * ProcessPool は、AbstractObjectPool を継承した オブジェクトプールです。
    168         *
    169         * OpenOfficeのプロセスをプールします。
    170         *
    171         * @version  4.0
    172         * @author   Hiroki Nakamura
    173         * @since    JDK5.0,
    174         */
    175        protected static class ProcessPool extends AbstractObjectPool<SOfficeProcess> {
    176                // 環境ファイル作成の識別用
    177                private int count = 0;
    178
    179                /**
    180                 * 初期処理を行います。
    181                 */
    182                protected ProcessPool() {
    183                        init( 0, HybsSystem.sysInt( "REPORT_MAX_PROCESS_COUNT")
    184                                        , true, HybsSystem.sysInt( "REPORT_PROCESS_ALIVE" ) );
    185                }
    186
    187                /**
    188                 * soffieのプロセスオブジェクトを作成します。
    189                 *
    190                 * @og.rev 4.3.5.0 (2009/02/01) Exception ではなく、RuntimeException に変更
    191                 * @og.rev 5.1.7.0 (2010/06/01) TCP接続対応
    192                 *
    193                 * @return OpenOfficeのプロセス
    194                 */
    195                protected SOfficeProcess createInstance() {
    196                        SOfficeProcess soffice = null;
    197                        try {
    198                                // 5.1.7.0 (2010/06/01) TCP接続対応
    199//                              soffice = new SOfficeProcess( "env_" + count );
    200                                if( "TCP".equalsIgnoreCase( HybsSystem.sys( "REPORT_OOO_CONN_TYPE" ) ) ) {
    201                                        soffice = new SOfficeProcessTcp( "env_" + count, HybsSystem.sysInt( "REPORT_OOO_MIN_PORT" ) );
    202                                }
    203                                else {
    204                                        soffice = new SOfficeProcess( "env_" + count );
    205                                }
    206                                soffice.bootstrap();
    207
    208                                count++;
    209                        }
    210//                      catch( Exception ex ) {
    211                        catch( RuntimeException ex ) {
    212                                System.out.println( "[ERROR]OOo:Failed to Connect Soffice! " + ex.getMessage() );
    213                        }
    214                        return soffice;
    215                }
    216
    217                /**
    218                 * オブジェクトプールから削除するときに呼ばれます。
    219                 * このメソッドで各オブジェクトごとの終了処理を行います。
    220                 *
    221                 * @param soffice OpenOfficeのプロセス
    222                 */
    223                protected void objectFinal( final SOfficeProcess soffice ) {
    224                        soffice.close();
    225                }
    226        }
    227}
    228