OSDN Git Service

Ver8.5.2.0
[opengion/opengionV8.git] / uap / webapps / gf / src / org / opengion / hayabusa / report2 / DocConverter_OOO.java
1 /*
2  * Copyright (c) 2009 The openGion Project.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific language
14  * governing permissions and limitations under the License.
15  */
16 package org.opengion.hayabusa.report2;
17
18 import java.io.File;
19 import java.util.Map;
20 import java.util.HashMap;
21 import java.util.Locale;
22 // import java.util.List;                                                                               // 8.0.3.0 (2021/12/17) 【保留】
23 import java.nio.file.Files;                                                                             // 8.1.0.3 (2022/01/21)
24 import java.nio.file.Paths;                                                                             // 8.1.0.3 (2022/01/21)
25 import java.nio.file.Path;                                                                              // 8.1.0.3 (2022/01/21)
26 import java.nio.file.StandardCopyOption;                                                // 8.1.0.3 (2022/01/21)
27
28 // import org.opengion.fukurou.system.HybsConst;                                // 8.0.1.0 (2021/10/29)
29 // import org.opengion.fukurou.model.ExcelModel;                                // 8.0.3.0 (2021/12/17)【保留】
30 import org.opengion.fukurou.util.FileUtil;
31 import org.opengion.fukurou.util.StringUtil;
32 import org.opengion.hayabusa.common.HybsSystem;
33 import org.opengion.hayabusa.common.HybsSystemException;
34 import static org.opengion.fukurou.system.HybsConst.CR ;                // 6.1.0.0 (2014/12/26)
35 // import static org.opengion.fukurou.system.HybsConst.FS ;             // 8.0.3.0 (2021/12/17)
36
37 import com.sun.star.beans.PropertyValue;
38 import com.sun.star.frame.XComponentLoader;
39 import com.sun.star.frame.XController;
40 import com.sun.star.frame.XDispatchHelper;
41 import com.sun.star.frame.XDispatchProvider;
42 import com.sun.star.frame.XModel;
43 import com.sun.star.frame.XStorable;
44 import com.sun.star.io.IOException;
45 import com.sun.star.lang.EventObject;
46 import com.sun.star.lang.IllegalArgumentException;
47 import com.sun.star.lang.XComponent;
48 import com.sun.star.uno.UnoRuntime;
49 import com.sun.star.util.CloseVetoException;
50 import com.sun.star.util.XCloseable;
51 import com.sun.star.view.PrintJobEvent;
52 import com.sun.star.view.PrintableState;
53 import com.sun.star.view.XPrintJobBroadcaster;
54 import com.sun.star.view.XPrintJobListener;
55 import com.sun.star.view.XPrintable;
56
57 import com.sun.star.sheet.XCalculatable;                                                // 8.1.1.2 (2022/02/25)
58
59 /**
60  * OpenOfficeを利用して様々な形式のファイルを読み込み、出力・印刷を行うための変換クラスです。
61  *
62  * 変換を行うことのできる入出力のフォーマット以下の通りです。
63  *
64  * [対応フォーマット]
65  *  入力[Calc(ods)   ,Excel(xls)     ] ⇒ 出力[Calc(ods)   ,Excel(xls,xlsx)      ,PDF]
66  *  入力[Writer(odt) ,Word(doc)      ] ⇒ 出力[Writer(odt) ,Word(doc,docx)       ,PDF]
67  *  入力[Impress(odp),PowerPoint(ppt)] ⇒ 出力[Impress(odp),PowerPoint(ppt,pptx) ,PDF]
68  *  入力[ * 上記の全て               ] ⇒ 印刷
69  *
70  * ※ xlsx,docx,pptx は、MS 2007形式の為、LibreOffice のみ利用できます。
71  *
72  * 変換を行うには、以下の2通りの方法があります。
73  * <del>
74  * (1)簡易的な変換メソッドを利用する場合
75  *   #convert(String, String)を利用して、変換を行います。
76  *   この場合、出力形式は、出力ファイルの拡張子に従って自動的に決定されます。
77  *   このため、印刷処理などを行う場合は、(2)の方法で出力して下さい。
78  * </del>
79  * (2)段階的に各メソッドを呼び出して変換する場合
80  *   オブジェクトを生成した後、{@link #open()}、#(各種変換メソッド)、{@link #clone()}を
81  *   順番に呼び出して変換を行います。
82  *   この場合、出力形式は、それに対応するメソッドを呼び出すことで決定されます。
83  *
84  *   また、変換を行うための、各種メソッドは、例外としてThrowableを投げるように定義されています。
85  *   このクラスを利用する場合は、このThrowableをcatchし、catch句で、必ず{@link #close( boolean )}に、
86  *   "true"(エラー発生時のクローズ処理)を指定して、終了処理を行って下さい。
87  *   (これを行わない場合、OpenOfficeの不要なプロセスが残ってしまう可能性があります)
88  *
89  * また、出力ファイルが既に存在する場合、出力ファイルは一旦削除された後、処理されます。
90  * なお、入力ファイルと出力ファイルが同じ場合、何も処理されません。(例外も発行されません)
91  *
92  * 入力ファイルを、CSV形式で複数指定した場合、複数の入力ファイルをマージして出力します。
93  * ※1 現状は、ファイルのマージは、入力ファイルがExcelまたはCalcの場合のみ対応しています。
94  *
95  * ※ DocConverter は、クラウド対応されていません。変換時はローカルファイル間で行ってください。
96  *
97  * @og.group 帳票システム
98  *
99  * @version  4.0
100  * @author   Hiroki.Nakamura
101  * @since    JDK1.6
102  */
103 public class DocConverter_OOO {
104 //      // XLSX は、LibreOffice のみ実行可能なので、その判定用に使用する。
105 //      private static final String OFFICE_HOME = HybsConst.getenv( "OFFICE_HOME","NULL" );     // 8.0.1.0 (2021/10/29) 環境変数から取得
106
107         private final boolean                   isOnline;                       // オンライン処理かどうか(オンライン処理の場合、プロセスはファクトリクラス経由で生成されます)
108         private final String[]                  mergeFile;
109
110         private String                                  inputName;
111         private String                                  origName;
112
113         private XComponent                              xComp;                          // 5.1.8.0 (2010/07/01) メソッドと重なる変数名の変更
114         private SOfficeProcess                  soffice;
115
116         // 入力、出力の拡張子とこれに対応するフィルター名
117         // share¥registry¥calc.xcd 形式のファイル <node oor:name="****" 部分?
118
119         /** staticイニシャライザ後、読み取り専用にするので、ConcurrentHashMap を使用しません。 */
120         private static final Map<String,String> FILTER_MAP      = new HashMap<>();              // 6.4.1.1 (2016/01/16) filterMap → FILTER_MAP refactoring
121         static {
122                 // 8.1.0.3 (2022/01/21) ファイルの拡張子が同じ場合は、copyで対応する。
123         //      FILTER_MAP.put( "ods_ods", "calc8" );
124                 FILTER_MAP.put( "xls_ods", "calc8" );
125                 FILTER_MAP.put( "ods_xls", "MS Excel 97" );
126         //      FILTER_MAP.put( "xls_xls", "MS Excel 97" );
127                 FILTER_MAP.put( "ods_pdf", "calc_pdf_Export" );
128                 FILTER_MAP.put( "xls_pdf", "calc_pdf_Export" );
129         //      FILTER_MAP.put( "odt_odt", "writer8" );
130                 FILTER_MAP.put( "doc_odt", "writer8" );
131                 FILTER_MAP.put( "odt_doc", "MS Word 97" );
132         //      FILTER_MAP.put( "doc_doc", "MS Word 97" );
133                 FILTER_MAP.put( "odt_pdf", "writer_pdf_Export" );
134                 FILTER_MAP.put( "doc_pdf", "writer_pdf_Export" );
135         //      FILTER_MAP.put( "odp_odp", "impress8" );
136                 FILTER_MAP.put( "ppt_odp", "impress8" );
137                 FILTER_MAP.put( "odp_ppt", "MS PowerPoint 97" );
138         //      FILTER_MAP.put( "ppt_ppt", "MS PowerPoint 97" );
139                 FILTER_MAP.put( "odp_pdf", "impress_pdf_Export" );
140                 FILTER_MAP.put( "ppt_pdf", "impress_pdf_Export" );
141
142 //              if( OFFICE_HOME.contains( "LibreOffice" ) ) {                                           // 8.0.1.0 (2021/10/29) LibreOffice の時のみ使用可能
143         //              FILTER_MAP.put( "ods_xlsx", "Calc MS Excel 2007 XML" );                 // 8.0.1.0 (2021/10/29)
144         //              FILTER_MAP.put( "xls_xlsx", "Calc MS Excel 2007 XML" );                 // 8.0.1.0 (2021/10/29)
145
146                         FILTER_MAP.put( "ods_xlsx", "Calc Office Open XML" );                   // 8.0.1.0 (2021/10/29)
147                         FILTER_MAP.put( "xls_xlsx", "Calc Office Open XML" );                   // 8.0.1.0 (2021/10/29)
148
149                         // share¥registry¥writer.xcd
150                         FILTER_MAP.put( "odt_docx", "MS Word 2007 XML" );                               // 8.0.1.0 (2021/10/29)
151                         FILTER_MAP.put( "doc_docx", "MS Word 2007 XML" );                               // 8.0.1.0 (2021/10/29)
152                         // ※ writer_MS_Word_2007 は、failed: 0x81a(Error Area:Io Class:Parameter Code:26)
153
154                         // share¥registry¥impress.xcd
155                         FILTER_MAP.put( "odp_pptx", "Impress MS PowerPoint 2007 XML" ); // 8.0.1.0 (2021/10/29)
156                         FILTER_MAP.put( "ppt_pptx", "Impress MS PowerPoint 2007 XML" ); // 8.0.1.0 (2021/10/29)
157                         // ※ MS PowerPoint 2007 XML は、failed: 0x81a(Error Area:Io Class:Parameter Code:26)
158                         // ※ Office Open XML Presentation は、failed: 0x81a(Error Area:Io Class:Parameter Code:26)
159 //              }
160         };
161
162         /**
163          * コンストラクタです。
164          *
165          * #DocConverter(input, true)と同じです。
166          *
167          * @param input ファイル一覧(CSV形式)
168          * @see #DocConverter_OOO(String[])
169          */
170         public DocConverter_OOO( final String input ) {
171                 this( StringUtil.csv2Array( input ), true );
172         }
173
174         /**
175          * コンストラクタです。
176          *
177          * #DocConverter(input, true)と同じです。
178          *
179          * @param input ファイル一覧(配列)
180          * @see #DocConverter_OOO(String[], boolean)
181          */
182         public DocConverter_OOO( final String input[] ) {
183                 this( input, true );
184         }
185
186         /**
187          * コンストラクタです。
188          *
189          * isOnline(isOl)がtrueに指定された場合、soffice.binのプロセスをファクトリークラス経由で生成し、
190          * キャッシュします。
191          * 但し、システムリソースが読み込まれないような、バッチファイルから起動した場合は、この方法は
192          * 利用できないため、isOnlineをfalseに指定する必要があります。
193          *
194          * @param input ファイル一覧(配列)
195          * @param isOl オンライン(Web環境での使用)かどうか
196          */
197         public DocConverter_OOO( final String input[], final boolean isOl ) {
198                 if( input == null || input.length == 0 || input[0].isEmpty() ) {
199                         throw new HybsSystemException( "入力ファイルが指定されていません。" );
200                 }
201                 origName = input[0];
202                 final File inFile = new File( origName );
203                 if( !inFile.exists() ) {
204                         throw new HybsSystemException( "入力ファイルが存在しません。[file=" + input[0] + "]" );
205                 }
206                 isOnline  = isOl;
207                 inputName = origName;
208 //              origName  = input[0];
209
210                 if( input.length == 1 ) {
211                         mergeFile = null;
212                 }
213                 else {
214                         if( !"xls".equals( getSuffix( origName ) ) && !"ods".equals( getSuffix( origName ) ) ) {
215                                 throw new HybsSystemException( "ファイルのマージを行う場合、入力ファイルは、ExcelまたはCacl形式である必要があります。" );
216                         }
217
218                         mergeFile = new String[input.length-1];
219                         for( int i=0; i<mergeFile.length; i++ ) {
220                                 final String mrgFile = input[i+1];
221                                 if( mrgFile.isEmpty() || !( new File( mrgFile ) ).exists() ) {
222                                         throw new HybsSystemException( "マージファイルが指定されていないか、または存在しません。[file=" + mrgFile + "]" );
223                                 }
224                                 if( inputName.equals( mrgFile ) ) {
225                                         throw new HybsSystemException( "マージファイルに入力ファイルと同じファイルが指定されてます。[file=" + mrgFile + "]" );
226                                 }
227                                 if( !"xls".equals( getSuffix( mrgFile ) ) && !"ods".equals( getSuffix( mrgFile ) ) ) {
228                                         throw new HybsSystemException( "ファイルのマージを行う場合、マージファイルは、ExcelまたはCacl形式である必要があります。" );
229                                 }
230                                 mergeFile[i] = mrgFile;
231                         }
232                 }
233         }
234
235         /**
236          * SOficeのコンポーネントを起動します。
237          *
238          * 正常に処理が終了した場合は、#close()を発行し、終了処理を行って下さい。
239          * また、例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
240          *
241          * @og.rev 5.1.7.0 (2010/06/01) マージ処理対応
242          *
243          * @throws Throwable 何らかのエラーが発生した場合。
244          * @see #close()
245          * @see #close(boolean)
246          */
247         public void open() throws Throwable {
248                 // プロセスの取得
249                 if( soffice == null ) {
250                         if( isOnline ) {
251                                 soffice = ProcessFactory.newInstance();
252                         }
253                         else {
254                                 soffice = new SOfficeProcess( "docconverter.class" );
255                                 soffice.bootstrap();
256                         }
257
258                         // マージする場合は、マージ対象のファイルをテンポラリにコピーする(readOnly回避のため)
259                         // テンプレート(無題)として上げると、シートコピー先として特定できなくなるため
260                         if( mergeFile != null ) {
261                                 final File origFile = new File( origName );
262                                 inputName = soffice.getTempPath() + System.currentTimeMillis() + "_" + origFile.getName();
263                                 FileUtil.copy( origFile, new File( inputName ) );
264                         }
265                 }
266
267                 // 5.1.7.0 (2010/06/01) マージ処理対応
268                 xComp = getComponent( inputName, ( mergeFile == null ? true : false ), false );
269
270                 if( mergeFile != null ) {
271                         for( int i=0; i<mergeFile.length; i++ ) {
272                                 merge( mergeFile[i] );
273                         }
274                 }
275         }
276
277         /**
278          * ドキュメントコンポーネントを取得します。
279          *
280          * @param       input                   ファイル名
281          * @param       isHidden                隠し属性[true/false]
282          * @param       isAsTemplate    OpenOffice上のTemplate属性[true/false]
283          *
284          * @og.rev 8.1.0.2 (2022/01/14) odsフォーマットエラー時には、rtnDoc が null になる
285          * @og.rev 8.1.1.2 (2022/02/25) calcの計算式がLibreOfficeで実行されない対応
286          *
287          * @return      ドキュメントコンポーネント
288          */
289 //      @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告の抑止。キャストをはずすと、旧3.1 では、エラーになる。
290         private XComponent getComponent( final String input, final boolean isHidden, final boolean isAsTemplate ) {
291                 final PropertyValue[] calcProps = new PropertyValue[2];
292                 calcProps[0] = new PropertyValue();
293                 calcProps[0].Name = "Hidden";
294                 calcProps[0].Value = isHidden;
295                 calcProps[1] = new PropertyValue();
296                 calcProps[1].Name = "AsTemplate";
297                 calcProps[1].Value = isAsTemplate;
298
299                 final String url = "file:///" + input.replace( '\\', '/' );
300
301                 XComponent rtnDoc;
302 //              final XComponentLoader cloader = (XComponentLoader) UnoRuntime.queryInterface( XComponentLoader.class, soffice.getDesktop() );
303                 final XComponentLoader cloader = UnoRuntime.queryInterface( XComponentLoader.class, soffice.getDesktop() );
304                 try {
305                         rtnDoc = cloader.loadComponentFromURL( url, "_blank", 0, calcProps );
306
307                         // 8.1.1.2 (2022/02/25) calcの計算式がLibreOfficeで実行されない対応
308                         final XCalculatable calc = UnoRuntime.queryInterface(XCalculatable.class,rtnDoc);
309                 //      calc.enableAutomaticCalculation(true);
310                         calc.calculateAll();
311                 }
312                 catch( final IOException ex ) {
313                         throw new HybsSystemException( "OpenOfficeの立ち上げ時にエラーが発生しました(入出力エラー)。", ex );
314                 }
315                 catch( final IllegalArgumentException ex ) {
316                         throw new HybsSystemException( "OpenOfficeの立ち上げ時にエラーが発生しました(パラメーター不正)。", ex );
317                 }
318
319                 // 8.1.0.2 (2022/01/14)
320                 if( rtnDoc == null ) {
321                         final String errMsg = "OpenOffice[" + input + "]ファイルが不正です。" + CR
322                                                                 + "印刷範囲設定や、データにCTRL文字等が含まれていないかご確認ください。";
323                         throw new HybsSystemException( errMsg );
324                 }
325
326                 return rtnDoc;
327         }
328
329         /**
330          * ドキュメント(xls,ods)のマージを行います。
331          *
332          * @param mergeInputName マージ対象のファイル名
333          */
334 //      @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告の抑止。キャストをはずすと、旧3.1 では、エラーになる。
335         private void merge( final String mergeInputName ) {
336                 // マージする副ファイルは、テンプレート(無題)として上げる(readOnly回避のため)
337                 final XComponent subDoc = getComponent( mergeInputName, false, true );
338
339                 final XDispatchProvider dispatchProvider
340 //                      = (XDispatchProvider)UnoRuntime.queryInterface( XDispatchProvider.class
341                         = UnoRuntime.queryInterface( XDispatchProvider.class
342 //                              ,((XController)UnoRuntime.queryInterface( XController.class
343                                 ,(UnoRuntime.queryInterface( XController.class
344 //                                      ,((XModel)UnoRuntime.queryInterface( XModel.class
345                                         ,(UnoRuntime.queryInterface( XModel.class
346                                                 ,subDoc
347                                         )).getCurrentController()
348                                 )).getFrame()
349                         );
350
351                 final XDispatchHelper xDispatchHelper = soffice.getDispatcher();
352                 xDispatchHelper.executeDispatch(dispatchProvider, ".uno:TableSelectAll", "", 0, new PropertyValue[0]);
353
354                 String title = new File( inputName ).getName() ;
355                 title = title.substring( 0, title.indexOf( '.' ) );
356
357                 final PropertyValue[] moveProps = new PropertyValue[3];
358                 moveProps[0] = new PropertyValue();
359                 moveProps[0].Name = "DocName";
360                 moveProps[0].Value = title;
361                 moveProps[1] = new PropertyValue();
362                 moveProps[1].Name = "Index";
363                 moveProps[1].Value = 32767;
364                 moveProps[2] = new PropertyValue();
365                 moveProps[2].Name = "Copy";
366                 moveProps[2].Value = true;
367                 xDispatchHelper.executeDispatch(dispatchProvider, ".uno:Move", "", 0, moveProps);
368
369                 closeComponent( subDoc );
370         }
371
372         /**
373          * Calcコンポーネントをクローズします。
374          *
375          * このクローズ処理は、処理が正常終了した場合に呼び出しする必要があります。
376          * 例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
377          *
378          * このメソッドは#close(false)と同じです。
379          *
380          * @throws Throwable 何らかのエラーが発生した場合。
381          * @see #close(boolean)
382          */
383         public void close() throws Throwable {
384                 close( false );
385         }
386
387         /**
388          * Calcコンポーネントをクローズします。
389          *
390          * 引数のisErrがtrueの場合、この変換オブジェクトで生成されたプロセスは強制的に破棄されます。
391          * falseの場合は、プロセスは、ファクトリクラスを経由して、キャッシュに戻されます。
392          * (バッチ処理の場合は、いずれの場合も、プロセスは強制的に破棄されます)
393          *
394          * 起動から変換、クローズまでの書く処理で例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
395          *
396          * #close(false)は#close()と同じであるため、通常利用することはありません。
397          *
398          * @og.rev 4.2.4.1 (2008/07/07 ) 終了処理を60回で終わるように修正
399          * @og.rev 4.3.0.0 (2008/07/15 ) ↑は6秒しか待っていなかったので、60秒待つように修正
400          *
401          * @param       isErr   trueの場合、この変換オブジェクトで生成されたプロセスは強制的に破棄されます。
402          */
403 //      @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告の抑止。キャストをはずすと、旧3.1 では、エラーになる。
404         public void close( final boolean isErr ) {
405                 if( xComp != null ) {
406                         closeComponent( xComp );
407                 }
408
409                 if( soffice != null ) {
410                         if( isOnline ) {
411                                 if( isErr ) {
412                                         ProcessFactory.remove( soffice );
413                                 }
414                                 else {
415                                         ProcessFactory.release( soffice );
416                                 }
417                         }
418                         else {
419                                 soffice.close();
420                         }
421                 }
422
423                 // マージした場合は、テンポラリにコピーしたファイルを削除
424                 // 6.0.0.1 (2014/04/25) These nested if statements could be combined
425                 if( mergeFile != null && ! ( new File( inputName ) ).delete() ) {
426                         System.err.println( "テンポラリにコピーしたファイルを削除できませんでした。[" + inputName + "]" );
427                 }
428         }
429
430         /**
431          * ドキュメントコンポーネントをクローズします。
432          *
433          * @param comp ドキュメントコンポーネント
434          */
435 //      @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告の抑止。キャストをはずすと、旧3.1 では、エラーになる。
436         private void closeComponent( final XComponent comp ) {
437                 XCloseable closeable = null;
438                 for( int i=0;; ++i ) {
439                         try {
440 //                              closeable = (XCloseable) UnoRuntime.queryInterface( XCloseable.class, comp );
441                                 closeable = UnoRuntime.queryInterface( XCloseable.class, comp );
442                                 closeable.close( true );
443                                 break;
444                         }
445                         catch( final CloseVetoException ex ) {
446                                 // 4.2.4.1 (2008/07/07 )
447                                 // 4.3.4.4 (2009/01/01)
448                                 if( i == 600 ) { throw new HybsSystemException( "sofficeプロセスに接続できません。", ex ); }
449                                 try {
450                                         Thread.sleep( 100 );
451                                 }
452                                 catch( final InterruptedException ex2 ) {
453                         //              throw new HybsSystemException( ex2 );
454                                 }
455                         }
456                 }
457         }
458
459         /**
460          * 印刷を行います。
461          *
462          * 正常に処理が終了した場合は、#close()を発行し、終了処理を行って下さい。
463          * また、例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
464          *
465          * @og.rev 4.3.0.0 (2008/07/16) スプールが終わるまでwaitし、さらにプリンタ発行の状況を監視し、正常終了かどうかを判断
466          * @og.rev 4.3.7.3 (2009/06/22) 存在しないプリンターを指定した場合のエラーハンドリングを追加
467          * @og.rev 5.1.2.0 (2010/01/01) CentOS等は、OS_INFOがLinux UNKNOWNとなるため、判定条件を変更
468          *
469          * @param       printer プリンター名
470          * @throws Throwable 何らかのエラーが発生した場合。
471          */
472         public void print( final String printer ) throws Throwable {
473                 if( printer == null || printer.isEmpty() ) {
474                         throw new HybsSystemException( "プリンターが指定されていません。" );
475                 }
476
477         //      if( xComp == null ) { throw new HybsSystemException( "初めに、#open()を実行して下さい(1)" ); }
478 //              @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告の抑止。キャストをはずすと、旧3.1 では、エラーになる。
479 //              final XPrintable xprintable = (XPrintable) UnoRuntime.queryInterface( XPrintable.class, xComp );
480                 final XPrintable xprintable = UnoRuntime.queryInterface( XPrintable.class, xComp );
481 //              @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告の抑止。キャストをはずすと、旧3.1 では、エラーになる。
482 //              final XPrintJobBroadcaster selection = (XPrintJobBroadcaster) UnoRuntime.queryInterface(XPrintJobBroadcaster.class, xprintable);
483                 final XPrintJobBroadcaster selection = UnoRuntime.queryInterface(XPrintJobBroadcaster.class, xprintable);
484                 final MyPrintJobListener listener = new MyPrintJobListener();
485                 selection.addPrintJobListener( listener );
486
487                 final PropertyValue[] tmpProps = new PropertyValue[1];
488                 tmpProps[0] = new PropertyValue();
489                 tmpProps[0].Name = "Name";
490                 // 5.1.2.0 (2010/01/01) CentOS等は、OS_INFOがLinux UNKNOWNとなるため、判定条件を変更
491                 // OSがLinuxの場合は、プリンタ名称の前後に"<",">"を付加
492                 tmpProps[0].Value = "LINUX".indexOf( HybsSystem.sys( "OS_INFO" ).toUpperCase( Locale.JAPAN ) ) >= 0 ? "<" + printer + ">" : printer;
493
494                 // 4.3.4.4 (2009/01/01)
495                 try {
496                         xprintable.setPrinter( tmpProps );
497                 }
498                 catch( final IllegalArgumentException ex ) {
499                         throw new HybsSystemException( "印刷時にエラーが発生しました。", ex );
500                 }
501
502                 // 4.3.7.3 (2009/06/22) 存在しないプリンタを指定した場合は、PropertyValueに
503                 // デフォルトプリンターが入るため、引数の値と合致しているかで正しく設定されたかを確認
504                 String curPrinter = null;
505                 for( final PropertyValue chkProp : xprintable.getPrinter() ) {
506                         if( "Name".equals( chkProp.Name) ) {
507                                 curPrinter = (String)chkProp.Value;
508                                 break;
509                         }
510                 }
511
512 //              final PropertyValue[] chkProps = xprintable.getPrinter();
513 //              for( int i=0; i<chkProps.length; i++ ) {
514 //                      if( "Name".equals( chkProps[i].Name) ) {
515 //                              curPrinter = (String)chkProps[i].Value;
516 //                              break;
517 //                      }
518 //              }
519                 if( !(printer.equalsIgnoreCase( curPrinter ) ) ) {
520                         final String errMsg = "プリンター[" + printer + "]を発行先に指定できませんでした。" + CR
521                                                         + "存在しないプリンタ名が指定されている可能性があります。";
522                         throw new HybsSystemException( errMsg );
523                 }
524
525                 // 4.3.0.0 (2008/07/16)
526                 final PropertyValue[] printProps = new PropertyValue[1];
527                 printProps[0] = new PropertyValue();
528                 printProps[0].Name = "Wait";
529                 printProps[0].Value = true;
530
531                 // 4.3.4.4 (2009/01/01)
532                 try {
533                         xprintable.print( printProps );
534                 }
535                 catch( final IllegalArgumentException ex ) {
536                         throw new HybsSystemException( "印刷時にエラーが発生しました。", ex );
537                 }
538
539                 // 4.3.0.0 (2008/07/16)
540                 // 6.9.7.0 (2018/05/14) PMD Useless parentheses.
541 //              if( listener.getStatus() == null
542 //                              || listener.getStatus() != PrintableState.JOB_COMPLETED && listener.getStatus() != PrintableState.JOB_SPOOLED ) {
543                 if( listener.isError() ) {
544                         throw new HybsSystemException ( "Error Occured while spooling print job. Check Spooler-Service!!!");
545                 }
546         }
547
548         /**
549          * プリンタジョブの状況を監視するリスナーです。
550          *
551          * @author Hiroki.Nakamura
552          */
553         private static final class MyPrintJobListener implements XPrintJobListener {
554                 private PrintableState status   ;
555
556                 /**
557                  * PrintJobEventのステータスを内部変数にセットします。
558                  *
559                  * @param       event   PrintJobEventオブジェクト
560                  */
561                 @Override       // XPrintJobListener
562                 public void printJobEvent( final PrintJobEvent event ) {
563                         status = event.State;
564                 }
565
566                 /**
567                  * EventObjectの処理を実施します。(ここでは何も行いません。)
568                  *
569                  * @param       event   EventObjectオブジェクト
570                  */
571                 @Override       // XPrintJobListener
572                 public void disposing( final EventObject event ) {
573                         // 何もありません。(PMD エラー回避)
574                 }
575
576 //              /**
577 //               * PrintableStateオブジェクトを返します。
578 //               *
579 //               * @og.rev 8.0.3.0 (2021/12/17) Delete
580 //               *
581 //               * @return      PrintableStateオブジェクト
582 //               */
583 //              public PrintableState getStatus() {
584 //                      return status;
585 //              }
586
587                 /**
588                  * PrintableStateオブジェクトの状態を返します。
589                  *
590                  * statusが nullか、COMPLETEDでなく、SPOOLEDでない場合にエラーと判断します。
591                  *
592                  * @return      エラーの場合、true
593                  */
594                 public boolean isError() {
595                         return status == null || status != PrintableState.JOB_COMPLETED && status != PrintableState.JOB_SPOOLED ;
596                 }
597         }
598
599         /**
600          * Calc(ods)出力を行います。
601          *
602          * 入力形式で未対応の場合(形式は入力ファイルの拡張子で判別)、例外が発行されます。
603          *
604          * 正常に処理が終了した場合は、#close()を発行し、終了処理を行って下さい。
605          * また、例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
606          *
607          * @param       outputName      出力ファイル名
608          * @throws Throwable 何らかのエラーが発生した場合。
609          */
610 //      public void ods( final String outputName ) throws Throwable {
611 //      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "ods" ) );
612 //              saveDoc( outputName, getFilterName( inputName, "ods" ) );
613 //      }
614
615 //      /**
616 //       * Excel(xls)出力を行います。
617 //       *
618 //       * 入力形式で未対応の場合(形式は入力ファイルの拡張子で判別)、例外が発行されます。
619 //       *
620 //       * 正常に処理が終了した場合は、#close()を発行し、終了処理を行って下さい。
621 //       * また、例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
622 //       *
623 //       * @param       outputName      出力ファイル名
624 //       * @throws Throwable 何らかのエラーが発生した場合。
625 //       */
626 //      public void xls( final String outputName ) throws Throwable {
627 //      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "xls" ) );
628 //              saveDoc( outputName, getFilterName( inputName, "xls" ) );
629 //      }
630
631 //      /**
632 //       * Writer(ods)出力を行います。
633 //       *
634 //       * 入力形式で未対応の場合(形式は入力ファイルの拡張子で判別)、例外が発行されます。
635 //       *
636 //       * 正常に処理が終了した場合は、#close()を発行し、終了処理を行って下さい。
637 //       * また、例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
638 //       *
639 //       * @param       outputName      出力ファイル名
640 //       * @throws Throwable 何らかのエラーが発生した場合。
641 //       */
642 //      public void odt( final String outputName ) throws Throwable {
643 //      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "odt" ) );
644 //              saveDoc( outputName, getFilterName( inputName, "odt" ) );
645 //      }
646
647 //      /**
648 //       * Word(doc)出力を行います。
649 //       *
650 //       * 入力形式で未対応の場合(形式は入力ファイルの拡張子で判別)、例外が発行されます。
651 //       *
652 //       * 正常に処理が終了した場合は、#close()を発行し、終了処理を行って下さい。
653 //       * また、例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
654 //       *
655 //       * @param       outputName      出力ファイル名
656 //       * @throws Throwable 何らかのエラーが発生した場合。
657 //       */
658 //      public void doc( final String outputName ) throws Throwable {
659 //      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "doc" ) );
660 //              saveDoc( outputName, getFilterName( inputName, "doc" ) );
661 //      }
662
663 //      /**
664 //       * Impress(odp)出力を行います。
665 //       *
666 //       * 入力形式で未対応の場合(形式は入力ファイルの拡張子で判別)、例外が発行されます。
667 //       *
668 //       * 正常に処理が終了した場合は、#close()を発行し、終了処理を行って下さい。
669 //       * また、例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
670 //       *
671 //       * @param       outputName      出力ファイル名
672 //       * @throws Throwable 何らかのエラーが発生した場合。
673 //       */
674 //      public void odp( final String outputName ) throws Throwable {
675 //      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "odp" ) );
676 //              saveDoc( outputName, getFilterName( inputName, "odp" ) );
677 //      }
678
679 //      /**
680 //       * PowerPoint(ppt)出力を行います。
681 //       *
682 //       * 入力形式で未対応の場合(形式は入力ファイルの拡張子で判別)、例外が発行されます。
683 //       *
684 //       * 正常に処理が終了した場合は、#close()を発行し、終了処理を行って下さい。
685 //       * また、例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
686 //       *
687 //       * @param       outputName      出力ファイル名
688 //       * @throws Throwable 何らかのエラーが発生した場合。
689 //       */
690 //      public void ppt( final String outputName ) throws Throwable {
691 //      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "ppt" ) );
692 //              saveDoc( outputName, getFilterName( inputName, "ppt" ) );
693 //      }
694
695         /**
696          * PDF出力を行います。
697          *
698          * 入力形式で未対応の場合(形式は入力ファイルの拡張子で判別)、例外が発行されます。
699          *
700          * 正常に処理が終了した場合は、#close()を発行し、終了処理を行って下さい。
701          * また、例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
702          *
703          * @og.rev 8.1.0.3 (2022/01/21) checkOutputメソッドは呼出元で判定する。
704          *
705          * @param       outputName      出力ファイル名
706          * @param       pdfPasswd       PDFパスワード
707          * @throws Throwable 何らかのエラーが発生した場合。
708          */
709         public void pdf( final String outputName, final String pdfPasswd ) throws Throwable {
710                 if( !checkOutput( outputName ) ){ return; }                     // 8.1.0.3 (2022/01/21)
711
712         //      savePdf( outputName, getFilterName( getSuffix( inputName ), "pdf" ), pdfPasswd );
713                 savePdf( outputName, getFilterName( inputName, "pdf" ), pdfPasswd );
714         }
715
716         //      /**
717         //       * 【保留】Excel2007(xlsx)出力を行います。
718         //       *
719         //       * 入力形式で未対応の場合(形式は入力ファイルの拡張子で判別)、例外が発行されます。
720         //       *
721         //       * 正常に処理が終了した場合は、#close()を発行し、終了処理を行って下さい。
722         //       * また、例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
723         //       *
724         //       * @og.rev 8.0.3.0 (2021/12/17) ods→xlsx変換時のシート毎の行数
725         //       *
726         //       * @param       outputName      出力ファイル名
727         //       * @param       sheetRows       シート毎の行数List
728         //       * @throws Throwable 何らかのエラーが発生した場合。
729         //       */
730         //      public void xlsx( final String outputName,final List<Integer> sheetRows ) throws Throwable {
731         //              saveDoc( outputName, getFilterName( inputName, "xlsx" ) );
732         //
733         //              // 余分な行やカラムを除去(ただし、ものすごく遅い)
734         //              final File outputFile = new File( outputName );
735         //              final ExcelModel excel = new ExcelModel( outputFile , true );
736         //              excel.activeWorkbook( sheetRows );
737         //              excel.saveFile( outputFile );
738         //      }
739
740         /**
741          * 出力ファイルから出力形式を自動判別し、変換を行います。
742          *
743          * 入出力形式で未対応の場合(形式は入出力ファイルの拡張子で判別)、例外が発行されます。
744          *
745          * 正常に処理が終了した場合は、#close()を発行し、終了処理を行って下さい。
746          * また、例外が発生した場合は、#close(true)を発行し、終了処理を行って下さい。
747          *
748          * @og.rev 8.1.0.3 (2022/01/21) checkOutputメソッドは呼出元で判定する。
749          *
750          * @param       outputName      出力ファイル名
751          * @throws Throwable 何らかのエラーが発生した場合。
752          */
753         public void auto( final String outputName ) throws Throwable {
754                 if( !checkOutput( outputName ) ){ return; }                     // 8.1.0.3 (2022/01/21)
755
756                 final String outSuffix = getSuffix( outputName );
757                 if( "pdf".equalsIgnoreCase( outSuffix ) ) {
758 //                      savePdf( outputName, getFilterName( getSuffix( inputName ), outSuffix ), null );
759                         savePdf( outputName, getFilterName( inputName, outSuffix ), null );
760                 }
761                 else {
762 //                      saveDoc( outputName, getFilterName( getSuffix( inputName ), outSuffix ) );
763                         saveDoc( outputName, getFilterName( inputName, outSuffix ) );
764                 }
765         }
766
767         /**
768          * フィルター名を指定して、各種ファイル形式に出力を行います。
769          *
770          * @og.rev 8.1.0.3 (2022/01/21) checkOutputメソッドは呼出元で判定する。
771          *
772          * @param       outputName      出力ファイル名
773          * @param       filter          フィルター名
774          */
775         private void saveDoc( final String outputName, final String filter ) {
776 //              if( !checkOutput( outputName ) ){ return; }
777
778                 final PropertyValue[] storeProps = new PropertyValue[1];
779                 storeProps[0] = new PropertyValue();
780                 storeProps[0].Name = "FilterName";
781                 storeProps[0].Value = filter;
782
783                 final String url = "file:///" + outputName.replace( '\\', '/' );
784         //      if( xComp == null ) { throw new HybsSystemException( "初めに、#open()を実行して下さい(2)" ); }
785 //              @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告の抑止。キャストをはずすと、旧3.1 では、エラーになる。
786 //              final XStorable xstorable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xComp );
787                 final XStorable xstorable = UnoRuntime.queryInterface( XStorable.class, xComp );
788                 try {
789                         xstorable.storeAsURL( url, storeProps );
790                 }
791                 catch( final Throwable th ) {
792                         throw new HybsSystemException( "ファイルへの変換時にエラーが発生しました。[filter=" + filter + "]", th );
793                 }
794         }
795
796         /**
797          * フィルターを指定してPDF出力を行います。
798          *
799          * @og.rev 8.1.0.3 (2022/01/21) checkOutputメソッドは呼出元で判定する。
800          *
801          * @param       outputName      出力ファイル名
802          * @param       filter          フィルター名
803          * @param       pdfPasswd       PDFパスワード
804          */
805         private void savePdf( final String outputName, final String filter, final String pdfPasswd ) {
806 //              if( !checkOutput( outputName ) ){ return; }
807
808                 final PropertyValue[] storeProps;
809                 if( pdfPasswd == null || pdfPasswd.isEmpty() ) {
810                         storeProps = new PropertyValue[1];
811                         storeProps[0] = new PropertyValue();
812                         storeProps[0].Name = "FilterName";
813                         storeProps[0].Value = filter;
814                 }
815                 // 帳票要求テーブルでPDFパスワードが設定されている場合
816                 else {
817                         final PropertyValue[] filterProps = new PropertyValue[2];
818                         filterProps[0] = new PropertyValue();
819                         filterProps[0].Name = "EncryptFile";
820                         filterProps[0].Value = true;
821                         filterProps[1] = new PropertyValue();
822                         filterProps[1].Name = "DocumentOpenPassword";
823                         filterProps[1].Value = pdfPasswd;
824
825                         storeProps = new PropertyValue[2];
826                         storeProps[0] = new PropertyValue();
827                         storeProps[0].Name = "FilterName";
828                         storeProps[0].Value = "calc_pdf_Export";
829                         storeProps[1] = new PropertyValue();
830                         storeProps[1].Name = "FilterData";
831                         storeProps[1].Value = filterProps;
832                 }
833
834                 final String url = "file:///" + outputName.replace( '\\', '/' );
835         //      if( xComp == null ) { throw new HybsSystemException( "初めに、#open()を実行して下さい(3)" ); }
836 //              @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告の抑止。キャストをはずすと、旧3.1 では、エラーになる。
837 //              final XStorable xstorable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xComp );
838                 final XStorable xstorable = UnoRuntime.queryInterface( XStorable.class, xComp );
839                 try {
840                         xstorable.storeToURL( url, storeProps );
841                 }
842                 catch( final Throwable th ) {
843                         final String err = "PDFファイルへの変換時にエラーが発生しました。[filter=" + filter + "]"
844                                                         + " URL=" + url + " , storeProps=" + storeProps + " , xComp=" + xComp ;
845
846 //                      throw new HybsSystemException( "PDFファイルへの変換時にエラーが発生しました。[filter=" + filter + "]", th );
847                         throw new HybsSystemException( err, th );
848                 }
849         }
850
851         /**
852          * 出力ファイルのチェックを行います。
853          *
854          * @og.rev 8.1.0.3 (2022/01/21) ファイルの拡張子が同じ場合は、copyで対応する。
855          *
856          * @param       outputName      出力ファイル名
857          *
858          * @return      処理対象かどうか(入力ファイルと出力ファイルが同じ場合は、falseが返ります)
859          */
860         private boolean checkOutput( final String outputName ) {
861                 if( outputName == null || outputName.isEmpty() ) {
862                         throw new HybsSystemException( "出力ファイルが指定されていません。" );
863                 }
864
865                 try {
866                         // 8.1.0.3 (2022/01/21) 出力ファイルがあれば、無条件削除
867                         final Path outPath = Paths.get( outputName );
868                         if( Files.exists( outPath ) ) { Files.delete( outPath ); }
869 //                      if( Files.exists( outPath ) && !Files.deleteIfExists( outPath ) ) {
870 //                              throw new HybsSystemException( "出力先の既存ファイルが削除できません。[file=" + outputName + "]" );
871 //                      }
872
873                         // 8.1.0.3 (2022/01/21) 拡張子が同じなら、copyする。
874                         if( getSuffix( inputName ).equals( getSuffix( outputName ) ) ) {
875                                 final Path inPath = Paths.get( inputName );
876                                 Files.copy( inPath , outPath , StandardCopyOption.REPLACE_EXISTING );
877                                 return false;
878                         }
879                 }
880 //              catch( final IOException ex ) {         // 意味不明なエラーが出る。
881                 catch( final Throwable ex ) {
882                         throw new HybsSystemException( "ファイルコピーが失敗しました。[in=" + inputName + "],out=" + outputName + "]" ,ex );
883                 }
884
885                 return true;
886
887 //              if( outFile.exists() ) {
888 //                      if( inFile.getAbsoluteFile().equals( outFile.getAbsoluteFile() ) ) {
889 //                              // 入力と出力が同じファイルの場合な何もしない
890 //                              return false;
891 //                      }
892 //                      else if( !outFile.delete() ) {
893 //                              throw new HybsSystemException( "出力先の既存ファイルが削除できません。[file=" + outputName + "]" );
894 //                      }
895 //              }
896 //              return true;
897         }
898
899         /**
900          * 入出力の形式(拡張子)からフィルター名を取得します。
901          *
902          * 入力ファイル名からサフィックスを取り出して、FILTER_MAP からフィルター名を取り出します。
903          *
904          * @og.rev 8.0.1.0 (2021/10/29) メッセージ修正
905          *
906 //       * @param       inSuffix        入力拡張子
907          * @param       inputName       入力ファイル名
908          * @param       outSuffix       出力拡張子
909          *
910          * @return      フィルター名
911          */
912 //      private static String getFilterName( final String inSuffix, final String outSuffix ) {
913         private static String getFilterName( final String inputName, final String outSuffix ) {
914                 final String inSuffix = getSuffix( inputName );
915
916                 final String filterName = FILTER_MAP.get( inSuffix + "_" + outSuffix );
917                 if( filterName == null ) {
918                         final String errMsg = "入力ファイル=[" + inputName + "] , 出力形式=[" + outSuffix + "]" + CR
919                                                         + "入力形式、出力形式は、以下の対応表に基づき、設定して下さい。" + CR
920                                                         + "入力[Calc(ods)   ,Excel(xls)     ] ⇒ 出力[Calc(ods)   ,Excel(xls,xlsx)     ,PDF]" + CR
921                                                         + "入力[Writer(odt) ,Word(doc)      ] ⇒ 出力[Writer(odt) ,Word(doc,docx)      ,PDF]" + CR
922                                                         + "入力[Impress(odp),PowerPoint(ppt)] ⇒ 出力[Impress(odp),PowerPoint(ppt,pptx),PDF]" + CR
923                                                         + "xlsx,docx,pptx は、MS 2007形式の為、LibreOffice のみ利用できます。" + CR ;
924                         throw new HybsSystemException( errMsg );
925                 }
926                 return filterName;
927         }
928
929         /**
930          * ファイル名から拡張子(小文字)を求めます。
931          *
932          * @param       fileName        ファイル名
933          *
934          * @return      拡張子(小文字)…存在しない場合は、空文字列
935          */
936         private static String getSuffix( final String fileName ) {
937 //              String suffix = null;
938                 String suffix = "";
939                 if( fileName != null ) {
940                         final int sufIdx = fileName.lastIndexOf( '.' );
941                         if( sufIdx >= 0 ) {
942                                 suffix = fileName.substring( sufIdx + 1 ).toLowerCase( Locale.JAPAN );
943                         }
944                 }
945                 return suffix;
946         }
947
948 //      /**
949 //       * ドキュメントの変換を行うための簡易メソッドです。
950 //       *
951 //       * 変換方法は、出力ファイルの拡張子により自動的に決定されます。
952 //       *
953 //       * @og.rev 8.0.3.0 (2021/12/17) ファイル連結の簡易メソッドは、使用しません。
954 //       *
955 //       * @param       inputFile       入力ファイル名
956 //       * @param       outputFile      出力ファイル名
957 //       * @see #convert(String[], String, boolean)
958 //       */
959 //      public static final void convert( final String inputFile, final String outputFile ) {
960 ////            convert( StringUtil.csv2Array( inputFile ), outputFile );
961 //              convert( StringUtil.csv2Array( inputFile ), outputFile, true ); // 8.0.3.0 (2021/12/17)
962 //      }
963
964 //      /**
965 //       * ドキュメントの変換を行うための簡易メソッドです。
966 //       *
967 //       * 変換方法は、出力ファイルの拡張子により自動的に決定されます。
968 //       *
969 //       * @og.rev 8.0.3.0 (2021/12/17) ファイル連結の簡易メソッドは、使用しません。
970 //       *
971 //       * @param       inputFile       入力ファイル名配列
972 //       * @param       outputFile      出力ファイル名
973 //       * @see #convert(String[], String, boolean)
974 //       */
975 //      public static final void convert( final String[] inputFile, final String outputFile ) {
976 //              convert( inputFile, outputFile, true );
977 //      }
978
979         /**
980          * ドキュメントの変換を行うための簡易メソッドです。
981          *
982          * 変換方法は、出力ファイルの拡張子により自動的に決定されます。
983          *
984          * isOnlineがtrueに指定された場合、soffice.binのプロセスをファクトリークラス経由で生成し、
985          * キャッシュします。
986          * 但し、システムリソースが読み込まれないような、バッチファイルから起動した場合は、この方法は
987          * 利用できないため、isOnlineをfalseに指定する必要があります。
988          *
989          * @og.rev 8.0.3.0 (2021/12/17) ファイル連結の簡易メソッドは、使用しません。
990          *
991          * @param       inputFile       入力ファイル名配列
992          * @param       outputFile      出力ファイル名
993          * @param       isOnline        オンライン(Web環境での使用)かどうか
994          */
995         public static final void convert( final String inputFile[], final String outputFile, final boolean isOnline ) {
996                 final DocConverter_OOO dc = new DocConverter_OOO( inputFile, isOnline );
997                 try {
998                         dc.open();
999                         dc.auto( outputFile );
1000                         dc.close();
1001                 }
1002                 catch( final Throwable th ) {
1003                         dc.close( true );
1004                         throw new HybsSystemException( th );
1005                 }
1006         }
1007
1008         /**
1009          * ドキュメントの変換を行います。
1010          *
1011          * 変換方法は、出力ファイルの拡張子により自動的に決定されます。
1012          *
1013          * @og.rev 4.3.1.1 (2008/08/23) mkdirs の戻り値判定
1014          * @og.rev 6.3.9.1 (2015/11/27) A method/constructor shouldnt explicitly throw java.lang.Exception(PMD)。
1015          * @og.rev 8.0.3.0 (2021/12/17) ファイル連結の簡易メソッドは、使用しません。
1016          *
1017          * @param       args    コマンド引数配列
1018          */
1019         public static void main( final String[] args ) {
1020                 if( args.length < 2 ) {
1021                         System.out.println( "usage : OdsConverter [inputFile] [outputFile]" );
1022                         return;
1023                 }
1024
1025                 DocConverter_OOO.convert( new String[] {args[0]}, args[1], false );
1026
1027 //              final File input  = new File( args[0] );
1028 //              final File output = new File( args[1] );
1029 //
1030 //              // 4.3.1.1 (2008/08/23) mkdirs の戻り値判定
1031 //              if( outPath.mkdirs() ) {
1032 //                      System.err.println( args[1] + " の ディレクトリ作成に失敗しました。" );
1033 //              }
1034 //
1035 //              final String absPath = output.getAbsolutePath() + FS ;          // 8.0.3.0 (2021/12/17)
1036 //              if( input.isDirectory() ) {
1037 //                      final File[] inputFiles = input.listFiles();
1038 //                      // 6.3.9.0 (2015/11/06) null になっている可能性があるメソッドの戻り値を利用している(findbugs)
1039 //                      if( inputFiles != null ) {
1040 //                              for( final File file : inputFiles ) {
1041 //                                      final String inputFile = file.getAbsolutePath();
1042 ////                                    final String outputFile = output.getAbsolutePath() + File.separator + file.getName().replace( ".xls", ".ods" );
1043 //                                      final String outputFile = absPath + file.getName().replace( ".xls", ".ods" );
1044 //                                      convert( StringUtil.csv2Array( inputFile ), outputFile, false );
1045 //                              }
1046 //                      }
1047 //              }
1048 //              else {
1049 //                      final String inputFile = input.getAbsolutePath();
1050 ////                    final String outputFile = output.getAbsolutePath() + File.separator + input.getName().replace( ".xls", ".ods" );
1051 //                      final String outputFile = absPath + input.getName().replace( ".xls", ".ods" );
1052 //                      convert( StringUtil.csv2Array( inputFile ), outputFile, false );
1053 //              }
1054         }
1055 }