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