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.system.ThrowUtil; // 6.4.2.0 (2016/01/29) 022import org.opengion.fukurou.util.AbstractObjectPool; 023import org.opengion.fukurou.util.Cleanable; 024import org.opengion.fukurou.util.FileUtil; 025import org.opengion.hayabusa.common.HybsSystem; 026import org.opengion.hayabusa.common.SystemManager; 027 028/** 029 * Sofficeのプロセスを管理するファクトリクラスです。 030 * プロセスプールの実装は、AbstractObjectPoolを継承して実装されています。 031 * 032 * プロセスの初期生成数は0です。最大生成数は、システムリソースのREPORT_MAX_PROCESS_COUNTで 033 * 定義されます。また、生存時間は、REPORT_PROCESS_ALIVEで定義されています。 034 * 035 * プロセスを全て終了するには、clearメソッドを呼び出します。 036 * clearメソッドは、Cleanableインターフェースの実装として組み込まれ、SytemManagerに登録されるため、 037 * Tomcat終了時に、自動的にプロセスが終了されます。 038 * 但し、貸し出し中(処理中)のプロセスは、AbstractObjecgPoolの実装から、終了されないため、別の方法で 039 * 明示的にkillする必要があります 040 * 041 * @version 4.0 042 * @author Hiroki Nakamura 043 * @since JDK5.0, 044 */ 045public final class ProcessFactory { 046 047 /** 048 * プロセスプール 049 */ 050 private static ProcessPool pp = new ProcessPool() ; 051 052 /** Cleanable インターフェースによる初期化処理 */ 053 static { 054 final Cleanable clr = new Cleanable() { 055 public void clear() { 056 ProcessFactory.clear(); 057 } 058 }; 059 SystemManager.addCleanable( clr ); 060 061 // 5.2.2.0 (2010/11/01) 循環参照解消のため、SystemManager から移動 062 final Cleanable clr2 = new Cleanable() { 063 /** 064 * 初期化(クリア)します。 065 * 主に、キャッシュクリアで利用します。 066 */ 067 public void clear() { 068// ProcessFactory.kill(); 069// kill(); // 8.5.4.2 (2024/01/12) PMD 7.0.0 UnnecessaryFullyQualifiedName 070 } 071 }; 072 SystemManager.addCleanable( clr2 , true ); // コンテキスト終了時のみ呼び出す 073 } 074 075 /** 076 * デフォルトコンストラクターをprivateにして、 077 * オブジェクトの生成をさせないようにする。 078 */ 079 private ProcessFactory() {} 080 081 /** 082 * OpenOfficeのプロセスを生成します。 083 * 084 * @return sofficeのプロセス 085 */ 086 public static SOfficeProcess newInstance() { 087 return pp.newInstance(); 088 } 089 090 /** 091 * OpenOfficeのプロセスをリリースします。 092 * 093 * @param soffice SOfficeProcessオブジェクト 094 */ 095 public static void release( final SOfficeProcess soffice ) { 096 pp.release( soffice ); 097 } 098 099 /** 100 * OpenOfficeのプロセスをクローズします。 101 * 102 * @param soffice SOfficeProcessオブジェクト 103 */ 104 public static void remove( final SOfficeProcess soffice ) { 105 pp.remove( soffice ); 106 } 107 108 /** 109 * プールされているOpenOfficeのプロセスを全てクローズします。 110 */ 111 public static void clear() { 112 pp.clear(); 113 } 114 115 /** 116 * 全てのsoffice.binプロセスをKILLします。 117 * アプリケーションの終了処理で実行します。 118 * OS名がWindowsを含む場合はtaskkill、それ以外の場合はkillallします。 119 * 又、プロセス終了後にコピーされた設定ファイルを削除します。 120 * 121 * @og.rev 4.3.0.0 (2008/07/18) 追加 122 * @og.rev 4.3.0.0 (2008/07/22) 設定ファイルの削除を追加 123 * @og.rev 4.3.5.0 (2009/02/01) Exception をそれぞれのExceptionに分けて捕らえる。 124 * @og.rev 6.4.2.0 (2016/01/29) ex.printStackTrace() を、ThrowUtil#ogStackTrace(Throwable) に置き換え。 125 */ 126 public static void kill() { 127 try { 128 final String osName = HybsSystem.sys( "OS_INFO" ); //System.getProperty("os.name"); 129 if( osName.indexOf( "Windows" ) >= 0 ){ 130 // 4.3.0.0 (2008/07/18) Windoesのtaskkillを利用してsoffice.binのタスクを強制終了します。 131 new ProcessBuilder( "cmd.exe","/c","taskkill","/F","/IM","soffice.bin" ).start().waitFor(); 132 } 133 else{ 134 // 4.3.0.0 (2008/07/24) Windowsではない場合はkillallコマンド 135 new ProcessBuilder( "killall","-9","-w","soffice.bin" ).start().waitFor(); 136 } 137 138 // 4.3.0.0 (2008/07/22) 設定ファイル(SOfficeProcessでディレクトリを設定)を全削除します。 139 FileUtil.deleteFiles( new File( SOfficeProcess.ENV_DIR ) ); 140 } 141 // 6.3.9.1 (2015/11/27) Exceptionをまとめます。 142 catch( final IOException | InterruptedException | RuntimeException ex ) { 143 System.err.println( ThrowUtil.ogStackTrace( ex ) ); // 6.4.2.0 (2016/01/29) 144 } 145 } 146 147 /** 148 * 現在の状態を文字列で返します。 149 * 150 * @return 現在の状態 151 * @og.rtnNotNull 152 */ 153 public static String information() { 154 return pp.toString(); 155 } 156 157 /** 158 * ProcessPool は、AbstractObjectPool を継承した オブジェクトプールです。 159 * 160 * OpenOfficeのプロセスをプールします。 161 * 162 * @version 4.0 163 * @author Hiroki Nakamura 164 * @since JDK5.0, 165 */ 166 protected static final class ProcessPool extends AbstractObjectPool<SOfficeProcess> { 167 // 環境ファイル作成の識別用 168 private int count ; 169 170 /** 171 * 初期処理を行います。 172 */ 173 protected ProcessPool() { 174 super(); // 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor 175 init( 0, HybsSystem.sysInt( "REPORT_MAX_PROCESS_COUNT") 176 , true, HybsSystem.sysInt( "REPORT_PROCESS_ALIVE" ) ); 177 } 178 179 /** 180 * soffieのプロセスオブジェクトを作成します。 181 * 182 * @og.rev 4.3.5.0 (2009/02/01) Exception ではなく、RuntimeException に変更 183 * @og.rev 5.1.7.0 (2010/06/01) TCP接続対応 184 * 185 * @return OpenOfficeのプロセス 186 */ 187 @Override 188 protected SOfficeProcess createInstance() { 189 SOfficeProcess soffice = null; 190 try { 191 // 5.1.7.0 (2010/06/01) TCP接続対応 192 if( "TCP".equalsIgnoreCase( HybsSystem.sys( "REPORT_OOO_CONN_TYPE" ) ) ) { 193 soffice = new SOfficeProcessTcp( "env_" + count, HybsSystem.sysInt( "REPORT_OOO_MIN_PORT" ) ); 194 } 195 else { 196 soffice = new SOfficeProcess( "env_" + count ); 197 } 198 soffice.bootstrap(); 199 200 count++; 201 } 202 catch( final RuntimeException ex ) { 203 System.out.println( "[ERROR]FACTORY:Failed to Connect Soffice! " + ex.getMessage() ); 204 } 205 return soffice; 206 } 207 208 /** 209 * オブジェクトプールから削除するときに呼ばれます。 210 * このメソッドで各オブジェクトごとの終了処理を行います。 211 * 212 * @param soffice OpenOfficeのプロセス 213 */ 214 @Override 215 protected void objectFinal( final SOfficeProcess soffice ) { 216 soffice.close(); 217 } 218 } 219}