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