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 */ 016 package org.opengion.hayabusa.report2; 017 018 import java.io.File; 019 import java.io.IOException; 020 021 import org.opengion.fukurou.util.FileUtil; 022 import org.opengion.fukurou.util.StringUtil; 023 import org.opengion.hayabusa.common.HybsSystem; 024 import org.opengion.hayabusa.common.HybsSystemException; 025 026 import com.sun.star.bridge.UnoUrlResolver; 027 import com.sun.star.bridge.XUnoUrlResolver; 028 import com.sun.star.comp.helper.Bootstrap; 029 import com.sun.star.comp.helper.BootstrapException; 030 import com.sun.star.frame.XDesktop; 031 import com.sun.star.frame.XDispatchHelper; 032 import com.sun.star.lang.XMultiComponentFactory; 033 import com.sun.star.uno.UnoRuntime; 034 import com.sun.star.uno.XComponentContext; 035 036 /** 037 * OpenOfficeのプロセスを表すクラスです? 038 * 039 * bootstrap()メソ?が呼ばれたタイミングでsoffice.binのプロセスを生成します? 040 * soffice.binのプロセスを引数なしで実?た?合?通常は?ーザーで1プロセスしか 041 * 生?されな?め?-env:UserInstallationの引数を指定することで、仮想?別ユーザー 042 * として起動して?す? 043 * こ?"ユーザー"を表すキーは、コンストラクタの引数のidです? 044 * 045 * また?こ?仮想ユーザーで起動した?合?初回起動時にユーザー登録を?画面が立ち上がります? 046 * これを回避するため、デフォルト?環?ァイルを?ロセス生?前にコピ?することで、認証済みの 047 * 状態で立ち上がるよ?して?す? 048 * 049 * 起動した?ロセスとの通知は名前付きパイプで行われます?パイプ名は?env"+コンストラクタのidです? 050 * プロセス起動と、名前付きパイプでの接続?非同期で行われます? 051 * プロセス起動後?60秒経過しても接続できな??合?、BootstrapExceptionが発生します? 052 * 053 * @version 4.0 054 * @author Hiroki Nakamura 055 * @since JDK5.0, 056 */ 057 public class SOfficeProcess { 058 059 /** OOoのインスト?ル?レクトリ */ 060 public static final String OFFICE_HOME = 061 ( new File ( System.getenv( "OFFICE_HOME" ) ).getAbsolutePath() ) + File.separator; 062 063 /** 設定ファイルの雛形 */ 064 private static final String DEFAULT_ENV_PATH = 065 OFFICE_HOME + "env" + File.separator + "_default"; 066 067 /** soffice.binのパス */ 068 private static final String SOFFICE_BIN = 069 OFFICE_HOME + File.separator + "program" + File.separator + "soffice.bin"; 070 071 /** ローカルコン?ス?*/ 072 private static XComponentContext xLocalContext = null; 073 static { 074 try { 075 xLocalContext = Bootstrap.createInitialComponentContext( null ); 076 } 077 catch( Throwable th ) { 078 System.out.println( "[ERROR]OOo:Can't start LocalContext,Check OFFICE_HOME!" ); 079 th.printStackTrace(); 080 } 081 } 082 083 /** リモートデスクトップインスタンス */ 084 @SuppressWarnings("cast") // OpenOffice 3.2 での冗長なキャスト警告?抑止。キャストをはずすと、旧3.1 では、エラーになる? 085 private XDesktop desktop = null; 086 087 private XComponentContext remoteContext = null; 088 089 /** soffice.binのプロセス */ 090 private Process process = null; 091 092 /** 環?定?パス */ 093 // 5.1.7.0 (2010/06/01) ?サーバ?対応漏れ 094 // public static final String ENV_DIR = HybsSystem.url2dir( HybsSystem.sys( "FILE_URL" ) + "oooenv" ) + File.separator; 095 public static final String ENV_DIR = HybsSystem.url2dir( StringUtil.nval( HybsSystem.sys( "REPORT_FILE_URL" ) 096 , HybsSystem.sys( "FILE_URL" ) + "REPORT" + File.separator ) 097 + "oooenv" ) + File.separator; 098 private final String envPath; 099 100 /** 環?定ファイルのID */ 101 private final String envId; 102 103 /** 104 * コンストラクタです? 105 * 106 * @og.rev 4.3.0.0 (2008/07/15) 設定ファイルを各コン?ストごとに置くよ?変更 107 * @param id プロセスID 108 */ 109 protected SOfficeProcess( final String id ) { 110 envId = id; 111 // envPath = OFFICE_HOME + "env" + File.separator + envId; 112 envPath = ENV_DIR + envId; 113 } 114 115 /** 116 * OOoへの接続を行います? 117 * 118 * @og.rev 5.0.0.0 (2009/08/03) Linux対?パイプ名に":"が含まれて?と接続できな? 119 * @og.rev 5.1.7.0 (2010/06/01) TCP接続対? 120 * 121 * @throws Exception 122 */ 123 @SuppressWarnings("cast") // OpenOffice 3.2 での冗長なキャスト警告?抑止。キャストをはずすと、旧3.1 では、エラーになる? 124 protected void bootstrap() { 125 System.out.println( "[INFO]OOo:Starting soffice process,ENV-ID=" + envId ); 126 127 // check enviroment files, if no files, create from default files 128 checkEnv( envPath ); 129 130 // pipe name 131 // 4.3.3.6 (2008/11/15) マルチサーバ対応?同?ーバでの?実行時不?合?ため? 132 // 5.0.0.0 (2009/08/03) Linux対? 133 //String sPipeName = "uno" + envId; 134 String sPipeName = "uno" + "_" + HybsSystem.sys("HOST_URL").replace(':','_').replace('/','_') + "_" + envId; 135 136 // start office process 137 // 5.5.2.4 (2012/05/16) int priority は使われて???で、削除します? 138 // process = execOffice( envPath, sPipeName, 0 ); 139 process = execOffice( envPath, sPipeName ); 140 System.out.println( "[INFO]OOo:Invoke soffice.bin,ENV-ID=" + envId ); 141 142 // create a URL resolver 143 XUnoUrlResolver xUrlResolver = UnoUrlResolver.create( xLocalContext ); 144 145 // connection string 146 // 5.1.7.0 (2010/06/01) TCP接続対? 147 // String sConnect = "uno:pipe,name=" + sPipeName + ";urp;StarOffice.ComponentContext"; 148 String sConnect = getConnParam( sPipeName ); 149 150 // wait until office is started 151 // XComponentContext xContext = null; 152 try { 153 for( int i = 0;; ++i ) { 154 try { 155 Object context = xUrlResolver.resolve( sConnect ); 156 remoteContext = (XComponentContext) UnoRuntime.queryInterface( XComponentContext.class, context ); 157 if( remoteContext == null ) { throw new BootstrapException( "no component context!" ); } 158 break; 159 } 160 catch( com.sun.star.connection.NoConnectException ex ) { 161 System.out.println( "[INFO]OOo:Waiting for Connect soffice process,ENV-ID=" + envId ); 162 if( i == 60 ) { throw new BootstrapException( ex ); } 163 Thread.sleep( 1000 ); 164 } 165 } 166 167 // create desktop instance 168 XMultiComponentFactory componentFactory = remoteContext.getServiceManager(); 169 desktop = (XDesktop) UnoRuntime.queryInterface( XDesktop.class, componentFactory.createInstanceWithContext( "com.sun.star.frame.Desktop", remoteContext ) ); 170 } 171 catch ( Exception ex ) { 172 throw new HybsSystemException( "[ERROR] Can't create Desktop Instance", ex ); 173 } 174 175 System.out.println( "[INFO]OOo:Connected successful,ENV-ID=" + envId ); 176 } 177 178 /** 179 * Pipe名をキーにOpenOfficeのプロセスに接続するため???を生成します? 180 * 181 * @param key Pipe? 182 * 183 * @return 接続文字? 184 */ 185 protected String getConnParam( final String key ) { 186 return "uno:pipe,name=" + key + ";urp;StarOffice.ComponentContext"; 187 } 188 189 /** 190 * ?クトップインスタンスを返しま? 191 * 192 * @return ?クトップインスタンス 193 */ 194 public XDesktop getDesktop() { 195 return desktop; 196 } 197 198 /** 199 * プロセスを終?ます? 200 * また?同時に環?定用のファイルも削除します? 201 */ 202 public void close() { 203 process.destroy(); 204 FileUtil.deleteFiles( new File( envPath ) ); 205 System.out.println( "[INFO]OOo:Destroy process,ENV-ID=" + envId ); 206 } 207 208 /** 209 * soffice.binを起動します? 210 * 211 * @og.rev 5.1.7.0 (2010/06/01) TCP接続対? 212 * @og.rev 5.5.2.4 (2012/05/16) int priority は使われて???で、削除します? 213 * 214 * @param envPath String 215 * @param pipeName String 216 * 217 * @return soffice.binのプロセス 218 */ 219 // private Process execOffice( final String envPath, final String pipeName, final int priority ) { 220 private Process execOffice( final String envPath, final String pipeName ) { 221 String[] cmdArray = new String[11]; 222 cmdArray[0] = SOFFICE_BIN; 223 cmdArray[1] = "-nologo"; 224 cmdArray[2] = "-nodefault"; 225 cmdArray[3] = "-norestore"; 226 cmdArray[4] = "-nocrashreport"; 227 cmdArray[5] = "-nolockcheck"; 228 cmdArray[6] = "-minimized"; 229 cmdArray[7] = "-invisible"; 230 cmdArray[8] = "-headless"; 231 cmdArray[9] = "-env:UserInstallation=file:///" + ( envPath ).replace( '\\', '/' ); 232 // 5.1.7.0 (2010/06/01) TCP接続対? 233 // cmdArray[10] = "-accept=pipe,name=" + pipeName + ";urp;"; 234 cmdArray[10] = getProcParam( pipeName ); 235 236 Process process; 237 try { 238 process = Runtime.getRuntime().exec( cmdArray ); 239 } catch ( IOException ex ) { 240 throw new HybsSystemException( "[ERROR] Cant't exec soffice.bin", ex ); 241 } 242 // pipe( process.getInputStream(), System.out, "CO> " ); 243 // pipe( process.getErrorStream(), System.err, "CE> " ); 244 245 return process; 246 } 247 248 /** 249 * Pipe名をキーにOpenOfficeのプロセスを生成するため?パラメーター??を生成します? 250 * 251 * @param key Pipe? 252 * 253 * @return プロセス生?パラメーター 254 */ 255 protected String getProcParam( final String key ) { 256 return "-accept=pipe,name=" + key + ";urp;"; 257 } 258 259 /** 260 * OOoの環?定ファイルをコピ?します? 261 * 262 * @og.rev 4.3.0.0 (2008/07/24) OS依存を?てJavaでコピ?する 263 * 264 * @param envPath String 265 * @throws Exception 266 */ 267 private void checkEnv( final String envPath ) { 268 269 if( OFFICE_HOME == null || OFFICE_HOME.length() == 0 ) { 270 throw new HybsSystemException( "OFFICE_HOMEが設定されて??め?OpenOfficeを起動できません" ); 271 } 272 273 // File file = new File( envPath ); // ??ァイルが消えて?かった時のため、常にコピ? 274 // if( !file.exists() || !file.isDirectory() ) { 275 // String[] cmdArray = new String[7]; 276 // cmdArray[0] = "xcopy"; 277 // cmdArray[1] = "/e"; 278 // cmdArray[2] = "/q"; 279 // cmdArray[3] = "/y"; 280 // cmdArray[4] = "/i"; 281 // cmdArray[5] = DEFAULT_ENV_PATH; 282 // cmdArray[6] = envPath; 283 // 284 // Process proc = Runtime.getRuntime().exec( cmdArray ); 285 // proc.waitFor(); 286 287 // } 288 // 4.3.0.0 (2008/07/24) OS依存からFileUtilを使??変更 289 FileUtil.copyDirectry( DEFAULT_ENV_PATH, envPath ); 290 291 // 5.1.7.0 (2010/06/01) ファイルマ?ジ対? 292 if( ! ( new File( getTempPath() ) ).mkdirs() ) { 293 System.err.println( "ファイルマ?ジ時??ポラリフォル?作?できませんでした?" + getTempPath() + "]" ); 294 } 295 } 296 297 /** 298 * OpenOfficeのローカルコンポ?ネントコン?ストを返します? 299 * 300 * @og.rev 5.1.7.0 (2010/06/01) 新規作? 301 * 302 * @return ローカルコンポ?ネントコン?ス? 303 */ 304 @SuppressWarnings("cast") // OpenOffice 3.2 での冗長なキャスト警告?抑止。キャストをはずすと、旧3.1 では、エラーになる? 305 public XDispatchHelper getDispatcher() { 306 XMultiComponentFactory componentFactory = remoteContext.getServiceManager(); 307 XDispatchHelper dispatcher = null; 308 try { 309 dispatcher = (XDispatchHelper) UnoRuntime.queryInterface( XDispatchHelper.class, componentFactory.createInstanceWithContext( "com.sun.star.frame.DispatchHelper", remoteContext ) ); 310 } 311 catch( com.sun.star.uno.Exception ex ) { 312 throw new HybsSystemException( "?スパッチャーの取得に失敗しました?, ex ); 313 } 314 return dispatcher; 315 } 316 317 /** 318 * こ?プロセスに対して固有に使用できる?ファイルのパスを指定します? 319 * 320 * @og.rev 5.1.7.0 (2010/06/01) 新規作? 321 * 322 * @return ?ファイルのパス 323 */ 324 public String getTempPath() { 325 return envPath + File.separator + "temp" + File.separator; 326 } 327 } 328