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.util.Map;
020    import java.util.HashMap;
021    import java.util.Locale;
022    
023    import org.opengion.fukurou.util.FileUtil;
024    import org.opengion.fukurou.util.StringUtil;
025    import org.opengion.hayabusa.common.HybsSystem;
026    import org.opengion.hayabusa.common.HybsSystemException;
027    
028    import com.sun.star.beans.PropertyValue;
029    import com.sun.star.frame.XComponentLoader;
030    import com.sun.star.frame.XController;
031    import com.sun.star.frame.XDispatchHelper;
032    import com.sun.star.frame.XDispatchProvider;
033    import com.sun.star.frame.XModel;
034    import com.sun.star.frame.XStorable;
035    import com.sun.star.io.IOException;
036    import com.sun.star.lang.EventObject;
037    import com.sun.star.lang.IllegalArgumentException;
038    import com.sun.star.lang.XComponent;
039    import com.sun.star.uno.Exception;
040    import com.sun.star.uno.UnoRuntime;
041    import com.sun.star.util.CloseVetoException;
042    import com.sun.star.util.XCloseable;
043    import com.sun.star.view.PrintJobEvent;
044    import com.sun.star.view.PrintableState;
045    import com.sun.star.view.XPrintJobBroadcaster;
046    import com.sun.star.view.XPrintJobListener;
047    import com.sun.star.view.XPrintable;
048    
049    /**
050     * OpenOfficeを利用して様ã?な形式ã?ファイルを読み込み、å?力ã?印刷を行うための変換クラスですã?
051     *
052     * 変換を行うことのできる入出力ã?フォーマット以下ã?通りですã?
053     *
054     * [対応フォーマッãƒ?
055     *  入力[Calc(ODS)   ,Excel(XLS)     ] â‡?出力[Calc(ODS)   ,Excel(XLS)     ,PDF]
056     *  入力[Writer(ODT) ,Word(DOC)      ] â‡?出力[Writer(ODT) ,Word(DOC)      ,PDF]
057     *  入力[Impress(ODP),PowerPoint(PPT)] â‡?出力[Impress(ODP),PowerPoint(PPT),PDF]
058     *  入力[ * 上記ã?全て               ] â‡?印刷
059     *
060     * 変換を行うには、以下ã?2通りの方法がありますã?
061     * (1)簡易的な変換メソãƒ?ƒ‰を利用する場å�?
062     *   {@link #convert(String, String)}を利用して、変換を行いますã?
063     *   こã?場合ã?出力形式ã?、å?力ファイルの拡張子に従って自動的に決定されますã?
064     *   こã?ため、印刷処ç�?�ªどを行う場合ã?ã€?2)の方法で出力して下さã�??
065     * (2)段階的に書くメソãƒ?ƒ‰を呼び出して変換する場å�?
066     *   オブジェクトを生æ?した後ã?{@link #open()}ã€?(å�?¨®変換メソãƒ?ƒ‰)、{@link #clone()}ã‚?
067     *   é ?•ªに呼び出して変換を行いますã?
068     *   こã?場合ã?出力形式ã?、それに対応するメソãƒ?ƒ‰を呼び出ることで決定されますã?
069     *
070     *   またã?変換を行うための、各種メソãƒ?ƒ‰は、例外としてThrowableを投げるように定義されてã�?�¾すã?
071     *   こã?クラスを利用する場合ã?、このThrowableをcatchしã?catch句で、å¿?�š{@link #close( boolean )}にã€?
072     *   "true"(エラー発生時のクローズ処ç�?を指定して、終äº??ç�?‚’行って下さã�??
073     *   (これを行わなã�??合ã?OpenOfficeの不要なプロセスが残ってしまã�?�¯能性がありまã�?
074     *
075     * またã?出力ファイルが既に存在する場合ã?出力ファイルはä¸?—¦削除された後ã?処ç�?�•れますã?
076     * なおã?入力ファイルと出力ファイルが同じå?合ã?何も処ç�?�•れませんã€?例外も発行されません)
077     *
078     * 入力ファイルをã?カンマ区åˆ?‚Šでè¤?•°æŒ?®šしたå?合ã?è¤?•°の入力ファイルをã?ージして出力しますã?
079     * ※1 現状は、ファイルのマã?ジは、å?力ファイルがExcelまたã?Calcの場合ã?み対応してã�?�¾すã?
080     *
081     * @og.group 帳票シスãƒ?ƒ 
082     *
083     * @version  4.0
084     * @author   Hiroki.Nakamura
085     * @since    JDK1.6
086     */
087    public class DocConverter_OOO {
088    
089            final private boolean                   isOnline;                       // オンライン処ç�?�‹どã�?�‹(オンライン処ç�??場合ã?プロセスはファクトリクラス経由で生æ?されまã�?
090            final private String[]                  mergeFile;
091    
092            private String                                  inputName;
093            private String                                  origName;
094    
095    //      private XComponent                              doc;
096            private XComponent                              xComp;                          // 5.1.8.0 (2010/07/01) メソãƒ?ƒ‰と重なる変数名ã?変更
097            private SOfficeProcess                  soffice;
098    
099            // 入力ã?出力ã?拡張子とこれに対応するフィルターå�?
100    //      static final private HashMap<String,String> filterMap     = new HashMap<String,String>();
101            static final private Map<String,String> filterMap = new HashMap<String,String>();
102            static {
103                    filterMap.put( "ods_ods", "calc8" );
104                    filterMap.put( "xls_ods", "calc8" );
105                    filterMap.put( "ods_xls", "MS Excel 97" );
106                    filterMap.put( "xls_xls", "MS Excel 97" );
107                    filterMap.put( "ods_pdf", "calc_pdf_Export" );
108                    filterMap.put( "xls_pdf", "calc_pdf_Export" );
109                    filterMap.put( "odt_odt", "writer8" );
110                    filterMap.put( "doc_odt", "writer8" );
111                    filterMap.put( "odt_doc", "MS Word 97" );
112                    filterMap.put( "doc_doc", "MS Word 97" );
113                    filterMap.put( "odt_pdf", "writer_pdf_Export" );
114                    filterMap.put( "doc_pdf", "writer_pdf_Export" );
115                    filterMap.put( "odp_odp", "impress8" );
116                    filterMap.put( "ppt_odp", "impress8" );
117                    filterMap.put( "odp_ppt", "MS PowerPoint 97" );
118                    filterMap.put( "ppt_ppt", "MS PowerPoint 97" );
119                    filterMap.put( "odp_pdf", "impress_pdf_Export" );
120                    filterMap.put( "ppt_pdf", "impress_pdf_Export" );
121            };
122    
123            /**
124             * コンストラクタですã?
125             *
126             * #DocConverter(input, true)と同じですã?
127             *
128             * @param input ファイルä¸?¦§(カンマ区åˆ?‚Š)
129             * @see #DocConverter_OOO(String[])
130             */
131            public DocConverter_OOO( final String input ) {
132                    this( StringUtil.csv2Array( input ), true );
133            }
134    
135            /**
136             * コンストラクタですã?
137             *
138             * #DocConverter(input, true)と同じですã?
139             *
140             * @param input ファイルä¸?¦§(配å?)
141             * @see #DocConverter_OOO(String[], boolean)
142             */
143            public DocConverter_OOO( final String input[] ) {
144                    this( input, true );
145            }
146    
147            /**
148             * コンストラクタですã?
149             *
150             * isOnline(isOl)がtrueにæŒ?®šされた場合ã?soffice.binのプロセスをファクトリークラス経由で生æ?しã?
151             * キャãƒ?‚·ュしますã?
152             * ä½?�—、シスãƒ?ƒ リソースが読み込まれなã�?‚ˆã�?�ª、バãƒ?ƒ�ファイルから起動したå?合ã?、この方法ã?
153             * 利用できなã�?�Ÿめã?isOnlineをfalseにæŒ?®šするå¿?¦�がありますã?
154             *
155             * @param input ファイルä¸?¦§(配å?)
156             * @param isOl オンライン(Web環å¢?�§の使用)かどã�?�‹
157             */
158            public DocConverter_OOO( final String input[], final boolean isOl ) {
159                    if( input == null || input.length == 0 || input[0].length() == 0 ) {
160                            throw new HybsSystemException( "入力ファイルが指定されてã�?�¾せんã€? );
161                    }
162                    File inFile = new File( input[0] );
163                    if( !inFile.exists() ) {
164                            throw new HybsSystemException( "入力ファイルが存在しませんã€?file=" + input[0] + "]" );
165                    }
166                    isOnline = isOl;
167                    inputName = input[0];
168                    origName = input[0];
169    
170                    if( input.length == 1 ) {
171                            mergeFile = null;
172                    }
173                    else {
174                            if( !"xls".equals( getSuffix( input[0] ) ) && !"ods".equals( getSuffix( input[0] ) ) ) {
175                                    throw new HybsSystemException( "ファイルのマã?ジを行う場合ã?入力ファイルは、Excelまたã?Cacl形式であるå¿?¦�がありますã?" );
176                            }
177    
178                            mergeFile = new String[input.length-1];
179                            for( int i=0; i<mergeFile.length; i++ ) {
180                                    if( input[i+1].length() == 0 || !( new File( input[i+1] ) ).exists() ) {
181                                            throw new HybsSystemException( "マã?ジファイルが指定されてã�?�ªã�?�‹、またã?存在しませんã€?file=" + input[i+1] + "]" );
182                                    }
183                                    if( inputName.equals( input[i] + 1 ) ) {
184                                            throw new HybsSystemException( "マã?ジファイルに入力ファイルと同じファイルが指定されてますã?[file=" + input[i+1] + "]" );
185                                    }
186                                    if( !"xls".equals( getSuffix( input[i+1] ) ) && !"ods".equals( getSuffix( input[i+1] ) ) ) {
187                                            throw new HybsSystemException( "ファイルのマã?ジを行う場合ã?マã?ジファイルは、Excelまたã?Cacl形式であるå¿?¦�がありますã?" );
188                                    }
189                                    mergeFile[i] = input[i+1];
190                            }
191                    }
192            }
193    
194            /**
195             * SOficeのコンポã?ネントを起動しますã?
196             *
197             * 正常に処ç�?�Œ終äº?�—たå?合ã?ã€?close()を発行し、終äº??ç�?‚’行って下さã�??
198             * またã?例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
199             *
200             * @og.rev 5.1.7.0 (2010/06/01) マã?ジ処ç�?¯¾å¿?
201             *
202             * @throws Throwable 何らかã?エラーが発生したå?合ã?
203             * @see #close()
204             * @see #close(boolean)
205             */
206            public void open() throws Throwable {
207                    // プロセスの取å¾?
208                    if( soffice == null ) {
209                            if( isOnline ) {
210                                    soffice = ProcessFactory.newInstance();
211                            }
212                            else {
213                                    soffice = new SOfficeProcess( "docconverter.class" );
214                                    soffice.bootstrap();
215                            }
216    
217                            // マã?ジする場合ã?、ã?ージ対象のファイルをテンポラリにコピã?する(readOnly回避のため)
218                            // ãƒ?ƒ³プレーãƒ?無é¡?として上げると、シートコピã?先として特定できなくなるたã‚?
219                            if( mergeFile != null ) {
220                                    File origFile = new File( origName );
221                                    inputName = soffice.getTempPath() + System.currentTimeMillis() + "_" + origFile.getName();
222                                    FileUtil.copy( origFile, new File( inputName ) );
223                            }
224                    }
225    
226    //              PropertyValue[] calcProps = new PropertyValue[1];
227    //              calcProps[0] = new PropertyValue();
228    //              calcProps[0].Name = "Hidden";
229    //              calcProps[0].Value = true;
230    //
231    //              String url = "file:///" + inputName.replace( '\\', '/' );
232    //
233    //              @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告ã?抑止。キャストをはずすと、旧3.1 では、エラーになるã?
234    //              XComponentLoader cloader = (XComponentLoader) UnoRuntime.queryInterface( XComponentLoader.class, soffice.getDesktop() );
235    //              try {
236    //                      doc = cloader.loadComponentFromURL( url, "_default", 0, calcProps );
237    //              }
238    //              catch( IOException ex ) {
239    //                      throw new HybsSystemException( "OpenOfficeの立ち上げ時にエラーが発生しました(入出力エラー)ã€?, ex );
240    //              }
241    //              catch( IllegalArgumentException ex ) {
242    //                      throw new HybsSystemException( "OpenOfficeの立ち上げ時にエラーが発生しました(パラメーター不正)ã€?, ex );
243    //              }
244    
245                    // 5.1.7.0 (2010/06/01) マã?ジ処ç�?¯¾å¿?
246                    xComp = getComponent( inputName, ( mergeFile == null ? true : false ), false );
247    
248                    if( mergeFile != null ) {
249                            for( int i=0; i<mergeFile.length; i++ ) {
250                                    merge( mergeFile[i] );
251                            }
252                    }
253            }
254    
255            /**
256             * ドキュメントコンポã?ネントを取得しますã?
257             *
258             * @param       input                   ファイルå�?
259             * @param       isHidden                éš?�—属æ?[true/false]
260             * @param       isAsTemplate    OpenOffice上ã?Template属æ?[true/false]
261             *
262             * @return      ドキュメントコンポã?ネンãƒ?
263             */
264            @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告ã?抑止。キャストをはずすと、旧3.1 では、エラーになるã?
265            private XComponent getComponent( final String input, final boolean isHidden, final boolean isAsTemplate ) {
266                    PropertyValue[] calcProps = new PropertyValue[2];
267                    calcProps[0] = new PropertyValue();
268                    calcProps[0].Name = "Hidden";
269                    calcProps[0].Value = isHidden;
270                    calcProps[1] = new PropertyValue();
271                    calcProps[1].Name = "AsTemplate";
272                    calcProps[1].Value = isAsTemplate;
273    
274                    String url = "file:///" + input.replace( '\\', '/' );
275    
276                    XComponent rtnDoc;
277                    XComponentLoader cloader = (XComponentLoader) UnoRuntime.queryInterface( XComponentLoader.class, soffice.getDesktop() );
278                    try {
279                            rtnDoc = cloader.loadComponentFromURL( url, "_blank", 0, calcProps );
280                    }
281                    catch( IOException ex ) {
282                            throw new HybsSystemException( "OpenOfficeの立ち上げ時にエラーが発生しました(入出力エラー)ã€?, ex );
283                    }
284                    catch( IllegalArgumentException ex ) {
285                            throw new HybsSystemException( "OpenOfficeの立ち上げ時にエラーが発生しました(パラメーター不正)ã€?, ex );
286                    }
287                    return rtnDoc;
288            }
289    
290            /**
291             * ドキュメンãƒ?xls,ods)のマã?ジを行いますã?
292             *
293             * @param mergeInputName マã?ジ対象のファイルå�?
294             */
295            @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告ã?抑止。キャストをはずすと、旧3.1 では、エラーになるã?
296            private void merge( final String mergeInputName ) {
297                    // マã?ジする副ファイルは、テンプレーãƒ?無é¡?として上げã‚?readOnly回避のため)
298                    XComponent subDoc = getComponent( mergeInputName, false, true );
299    
300                    XDispatchProvider dispatchProvider
301                            = (XDispatchProvider)UnoRuntime.queryInterface( XDispatchProvider.class
302                                    ,((XController)UnoRuntime.queryInterface( XController.class
303                                            ,((XModel)UnoRuntime.queryInterface( XModel.class
304                                                    ,subDoc
305                                            )).getCurrentController()
306                                    )).getFrame()
307                            );
308    
309                    XDispatchHelper xDispatchHelper = soffice.getDispatcher();
310                    xDispatchHelper.executeDispatch(dispatchProvider, ".uno:TableSelectAll", "", 0, new PropertyValue[0]);
311    
312                    String title = ( new File( inputName ).getName() );
313                    title = ( title ).substring( 0, title.indexOf( '.' ) );
314    
315                    PropertyValue[] moveProps = new PropertyValue[3];
316                    moveProps[0] = new PropertyValue();
317                    moveProps[0].Name = "DocName";
318                    moveProps[0].Value = title;
319                    moveProps[1] = new PropertyValue();
320                    moveProps[1].Name = "Index";
321                    moveProps[1].Value = 32767;
322                    moveProps[2] = new PropertyValue();
323                    moveProps[2].Name = "Copy";
324                    moveProps[2].Value = true;
325                    xDispatchHelper.executeDispatch(dispatchProvider, ".uno:Move", "", 0, moveProps);
326    
327                    // シートリンク方式ã?場合ã?、CalcをHiddenの状態で実行できるがã?画像などのオブジェクトがリンクされなã�?�Ÿめã?
328                    // 採用見é?りã?ã€?
329    //              XSpreadsheets mainSp = ( (XSpreadsheetDocument)UnoRuntime.queryInterface( XSpreadsheetDocument.class, xComp ) ).getSheets();
330    //              String[] mainSheetNames = mainSp.getElementNames();
331    //
332    //              XSpreadsheets subSp = ( (XSpreadsheetDocument)UnoRuntime.queryInterface( XSpreadsheetDocument.class, subDoc ) ).getSheets();
333    //              String[] subSheetNames = subSp.getElementNames();
334    //              for( int i=0; i<1; i++ ) {
335    //                      XSpreadsheet newSp = insertSheet( mainSp, subSheetNames[i], 0, (short)(mainSheetNames.length + i) );
336    //                      XSheetLinkable mainLink = (XSheetLinkable) UnoRuntime.queryInterface( XSheetLinkable.class, newSp );
337    //                      mainLink.link( "file:///" + mergeInputName.replace( '\\', '/' ), subSheetNames[i], "", "", com.sun.star.sheet.SheetLinkMode.NORMAL );
338    //                      mainLink.setLinkMode( com.sun.star.sheet.SheetLinkMode.NONE );
339    //              }
340    
341                    closeComponent( subDoc );
342            }
343    
344    //      /**
345    //       * スプレãƒ?ƒ‰シートオブジェクトに対して、シートを新規に追åŠ?�—ますã?
346    //       * 追åŠ?�™るシート名が既に存在する場合ã?シート名のサフィãƒ?‚¯スとして1,2...の連番を付加しますã?
347    //       *
348    //       * @param sheets
349    //       * @param sheetName
350    //       * @param suffix
351    //       * @param index
352    //       * @return 追åŠ?‚·ートã?シートオブジェクãƒ?
353    //       */
354    //      private XSpreadsheet insertSheet( final XSpreadsheets sheets, final String sheetName, final int suffix, final short index ) {
355    //              String sn = sheetName + ( suffix == 0 ? "" : String.valueOf( suffix ) );
356    //              try {
357    //                      sheets.insertNewByName( sn, index );
358    //              }
359    //              catch ( com.sun.star.uno.RuntimeException ex ) {
360    //                      if( suffix < 256 ) {
361    //                              return insertSheet( sheets, sheetName, suffix+1, index );
362    //                      }
363    //                      else {
364    //                              throw new HybsSystemException( "シートã?追åŠ?�«失敗しました", ex );
365    //                      }
366    //              }
367    //
368    //              XSpreadsheet insSheet = null;
369    //              try {
370    //                      insSheet = (XSpreadsheet)UnoRuntime.queryInterface( XSpreadsheet.class, sheets.getByName( sn ) );
371    //              }
372    //              catch( NoSuchElementException ex ) {
373    //                      throw new HybsSystemException( "追åŠ?�—たシートにアクセスできませんã€?, ex );
374    //              }
375    //              catch( WrappedTargetException ex ) {
376    //                      throw new HybsSystemException( "追åŠ?�—たシートにアクセスできませんã€?, ex );
377    //              }
378    //              return insSheet;
379    //      }
380    
381            /**
382             * Calcコンポã?ネントをクローズしますã?
383             *
384             * こã?クローズ処ç�??、å?ç�?�Œ正常終äº?�—たå?合に呼び出しするå¿?¦�がありますã?
385             * 例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
386             *
387             * こã?メソãƒ?ƒ‰は#close(false)と同じですã?
388             *
389             * @throws Throwable 何らかã?エラーが発生したå?合ã?
390             * @see #close(boolean)
391             */
392            public void close() throws Throwable  {
393                    close( false );
394            }
395    
396            /**
397             * Calcコンポã?ネントをクローズしますã?
398             *
399             * 引数のisErrがtrueの場合ã?こã?変換オブジェクトで生æ?されたã?ロセスは強制çš?�«破æ£?�•れますã?
400             * falseの場合ã?、ã?ロセスは、ファクトリクラスを経由して、キャãƒ?‚·ュに戻されますã?
401             * (バッチå?ç�??場合ã?、いずれの場合も、ã?ロセスは強制çš?�«破æ£?�•れまã�?
402             *
403             * 起動から変換、クローズまでの書くå?ç�?�§例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
404             *
405             * #close(false)は#close()と同じであるためã€??常利用することはありませんã€?
406             *
407             * @og.rev 4.2.4.1 (2008/07/07 ) 終äº??ç�?‚’60回で終わるよã�?�«修正
408             * @og.rev 4.3.0.0 (2008/07/15 ) ↑ã?6秒しかå¾?�£てã�?�ªかったã?でã€?0秒å¾?�¤ように修正
409             *
410             * @param       isErr   trueの場合ã?こã?変換オブジェクトで生æ?されたã?ロセスは強制çš?�«破æ£?�•れますã?
411             */
412            @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告ã?抑止。キャストをはずすと、旧3.1 では、エラーになるã?
413            public void close( final boolean isErr ) {
414                    if( xComp != null ) {
415                            closeComponent( xComp );
416                    }
417    
418                    if( soffice != null ) {
419                            if( isOnline ) {
420                                    if( isErr ) {
421                                            ProcessFactory.remove( soffice );
422                                    }
423                                    else {
424                                            ProcessFactory.release( soffice );
425                                    }
426                            }
427                            else {
428                                    soffice.close();
429                            }
430                    }
431    
432                    // マã?ジした場合ã?、テンポラリにコピã?したファイルを削除
433                    if( mergeFile != null ) {
434                            if( ! ( new File( inputName ) ).delete() ) {
435                                    System.err.println( "ãƒ?ƒ³ポラリにコピã?したファイルを削除できませんでしたã€?" + inputName + "]" );
436                            }
437                    }
438            }
439    
440            /**
441             * ドキュメントコンポã?ネントをクローズしますã?
442             *
443             * @param comp ドキュメントコンポã?ネンãƒ?
444             */
445            @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告ã?抑止。キャストをはずすと、旧3.1 では、エラーになるã?
446            private void closeComponent( final XComponent comp ) {
447                    XCloseable closeable = null;
448                    for( int i = 0;; ++i ) {
449                            try {
450                                    closeable = (XCloseable) UnoRuntime.queryInterface( XCloseable.class, comp );
451                                    closeable.close( true );
452                                    break;
453                            }
454                            catch( CloseVetoException ex ) {
455                                    // 4.2.4.1 (2008/07/07 )
456                                    // 4.3.4.4 (2009/01/01)
457                                    if( i == 600 ) { throw new HybsSystemException( "sofficeプロセスに接続できませんã€?, ex ); }
458                                    try {
459                                            Thread.sleep( 100 );
460                                    }
461                                    catch( InterruptedException ex2 ) {
462    //                                      throw new HybsSystemException( ex2 );
463                                    }
464                            }
465                    }
466            }
467    
468            /**
469             * 印刷を行いますã?
470             *
471             * 正常に処ç�?�Œ終äº?�—たå?合ã?ã€?close()を発行し、終äº??ç�?‚’行って下さã�??
472             * またã?例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
473             *
474             * @og.rev 4.3.0.0 (2008/07/16) スプã?ルが終わるまでwaitしã?さらにプリンタ発行ã?状況を監視し、正常終äº?�‹どã�?�‹を判断
475             * @og.rev 4.3.7.3 (2009/06/22) 存在しなã�??リンターを指定したå?合ã?エラーハンドリングを追åŠ?
476             * @og.rev 5.1.2.0 (2010/01/01) CentOS等ã?、OS_INFOがLinux UNKNOWNとなるためã?判定条件を変更
477             *
478             * @param       printer プリンターå�?
479             * @throws Throwable 何らかã?エラーが発生したå?合ã?
480             */
481            public void print( final String printer ) throws Throwable {
482                    if( xComp == null ) { throw new HybsSystemException( "初めにã€?open()を実行して下さã�? ); }
483    
484                    if( printer == null || printer.length() == 0 ) {
485                            throw new HybsSystemException( "プリンターが指定されてã�?�¾せんã€? );
486                    }
487    
488                    @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告ã?抑止。キャストをはずすと、旧3.1 では、エラーになるã?
489                    XPrintable xprintable = (XPrintable) UnoRuntime.queryInterface( XPrintable.class, xComp );
490                    @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告ã?抑止。キャストをはずすと、旧3.1 では、エラーになるã?
491                    XPrintJobBroadcaster selection = (XPrintJobBroadcaster) UnoRuntime.queryInterface(XPrintJobBroadcaster.class, xprintable);
492                    MyPrintJobListener listener = new MyPrintJobListener ();
493                    selection.addPrintJobListener( listener );
494    
495                    PropertyValue[] tmpProps = new PropertyValue[1];
496                    tmpProps[0] = new PropertyValue();
497                    tmpProps[0].Name = "Name";
498                    // 5.1.2.0 (2010/01/01) CentOS等ã?、OS_INFOがLinux UNKNOWNとなるためã?判定条件を変更
499                    // OSがLinuxの場合ã?、ã?リンタ名称の前後に"<",">"を付加
500    //              tmpProps[0].Value = "Linux".equals( HybsSystem.sys( "OS_INFO" ) ) ? "<" + printer + ">" : printer;
501                    tmpProps[0].Value = "LINUX".indexOf( HybsSystem.sys( "OS_INFO" ).toUpperCase( Locale.JAPAN ) ) >= 0 ? "<" + printer + ">" : printer;
502    
503                    // 4.3.4.4 (2009/01/01)
504                    try {
505                            xprintable.setPrinter( tmpProps );
506                    }
507                    catch ( IllegalArgumentException ex ) {
508                            throw new HybsSystemException( "印刷時にエラーが発生しましたã€?, ex );
509                    }
510    
511                    // 4.3.7.3 (2009/06/22) 存在しなã�??リンタを指定したå?合ã?、PropertyValueに
512                    // ãƒ?ƒ•ォルトã?リンターがå?るためã?引数の値と合è?してã�?‚‹かで正しく設定されたかを確èª?
513                    String curPrinter = null;
514                    PropertyValue[] chkProps = xprintable.getPrinter();
515                    for( int i=0; i<chkProps.length; i++ ) {
516                            if( "Name".equals( chkProps[i].Name) ) {
517                                    curPrinter = (String)chkProps[i].Value;
518                                    break;
519                            }
520                    }
521                    if( !(printer.equalsIgnoreCase( curPrinter ) ) ) {
522                            String errMsg = "プリンター[" + printer + "]を発行å?にæŒ?®šできませんでしたã€? + HybsSystem.CR
523                                                            + "存在しなã�??リンタ名がæŒ?®šされてã�?‚‹可能性がありますã?";
524                            throw new HybsSystemException( errMsg );
525                    }
526    
527                    // 4.3.0.0 (2008/07/16)
528                    PropertyValue[] printProps = new PropertyValue[1];
529                    printProps[0] = new PropertyValue();
530                    printProps[0].Name = "Wait";
531                    printProps[0].Value = true;
532    
533                    // 4.3.4.4 (2009/01/01)
534                    try {
535                            xprintable.print( printProps );
536                    }
537                    catch ( IllegalArgumentException ex ) {
538                            throw new HybsSystemException( "印刷時にエラーが発生しましたã€?, ex );
539                    }
540    
541                    // 4.3.0.0 (2008/07/16)
542                    if( listener.getStatus() == null
543                                    || ( listener.getStatus() != PrintableState.JOB_COMPLETED && listener.getStatus() != PrintableState.JOB_SPOOLED ) ){
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 class MyPrintJobListener implements XPrintJobListener {
554                    private PrintableState status = null;
555    
556                    @Override
557                    public void printJobEvent( final PrintJobEvent event ) {
558                            status = event.State;
559                    }
560    
561                    @Override
562                    public void disposing( final EventObject event ) {
563                            // 何もありませんã€?PMD エラー回避)
564                    }
565    
566                    public PrintableState getStatus() {
567                            return status;
568                    }
569            }
570    
571            /**
572             * PDF出力を行いますã?
573             *
574             * 入力形式で未対応ã?場å�?形式ã?入力ファイルの拡張子で判別)、例外が発行されますã?
575             *
576             * 正常に処ç�?�Œ終äº?�—たå?合ã?ã€?close()を発行し、終äº??ç�?‚’行って下さã�??
577             * またã?例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
578             *
579             * @param       outputName      出力ファイルå�?
580             * @param       pdfPasswd       PDFパスワーãƒ?
581             * @throws Throwable 何らかã?エラーが発生したå?合ã?
582             */
583            public void pdf( final String outputName, final String pdfPasswd ) throws Throwable  {
584                    savePdf( outputName, getFilterName( getSuffix( inputName ), "pdf" ), pdfPasswd );
585            }
586    
587            /**
588             * Calc(ods)出力を行いますã?
589             *
590             * 入力形式で未対応ã?場å�?形式ã?入力ファイルの拡張子で判別)、例外が発行されますã?
591             *
592             * 正常に処ç�?�Œ終äº?�—たå?合ã?ã€?close()を発行し、終äº??ç�?‚’行って下さã�??
593             * またã?例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
594             *
595             * @param       outputName      出力ファイルå�?
596             * @throws Throwable 何らかã?エラーが発生したå?合ã?
597             */
598            public void ods( final String outputName ) throws Throwable  {
599                    saveDoc( outputName, getFilterName( getSuffix( inputName ), "ods" ) );
600            }
601    
602            /**
603             * Excel(xls)出力を行いますã?
604             *
605             * 入力形式で未対応ã?場å�?形式ã?入力ファイルの拡張子で判別)、例外が発行されますã?
606             *
607             * 正常に処ç�?�Œ終äº?�—たå?合ã?ã€?close()を発行し、終äº??ç�?‚’行って下さã�??
608             * またã?例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
609             *
610             * @param       outputName      出力ファイルå�?
611             * @throws Throwable 何らかã?エラーが発生したå?合ã?
612             */
613            public void xls( final String outputName ) throws Throwable {
614                    saveDoc( outputName, getFilterName( getSuffix( inputName ), "xls" ) );
615            }
616    
617            /**
618             * Writer(ods)出力を行いますã?
619             *
620             * 入力形式で未対応ã?場å�?形式ã?入力ファイルの拡張子で判別)、例外が発行されますã?
621             *
622             * 正常に処ç�?�Œ終äº?�—たå?合ã?ã€?close()を発行し、終äº??ç�?‚’行って下さã�??
623             * またã?例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
624             *
625             * @param       outputName      出力ファイルå�?
626             * @throws Throwable 何らかã?エラーが発生したå?合ã?
627             */
628            public void odt( final String outputName ) throws Throwable {
629                    saveDoc( outputName, getFilterName( getSuffix( inputName ), "odt" ) );
630            }
631    
632            /**
633             * Word(doc)出力を行いますã?
634             *
635             * 入力形式で未対応ã?場å�?形式ã?入力ファイルの拡張子で判別)、例外が発行されますã?
636             *
637             * 正常に処ç�?�Œ終äº?�—たå?合ã?ã€?close()を発行し、終äº??ç�?‚’行って下さã�??
638             * またã?例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
639             *
640             * @param       outputName      出力ファイルå�?
641             * @throws Throwable 何らかã?エラーが発生したå?合ã?
642             */
643            public void doc( final String outputName ) throws Throwable {
644                    saveDoc( outputName, getFilterName( getSuffix( inputName ), "doc" ) );
645            }
646    
647            /**
648             * Impress(odp)出力を行いますã?
649             *
650             * 入力形式で未対応ã?場å�?形式ã?入力ファイルの拡張子で判別)、例外が発行されますã?
651             *
652             * 正常に処ç�?�Œ終äº?�—たå?合ã?ã€?close()を発行し、終äº??ç�?‚’行って下さã�??
653             * またã?例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
654             *
655             * @param       outputName      出力ファイルå�?
656             * @throws Throwable 何らかã?エラーが発生したå?合ã?
657             */
658            public void odp( final String outputName ) throws Throwable {
659                    saveDoc( outputName, getFilterName( getSuffix( inputName ), "odp" ) );
660            }
661    
662            /**
663             * PowerPoint(ppt)出力を行いますã?
664             *
665             * 入力形式で未対応ã?場å�?形式ã?入力ファイルの拡張子で判別)、例外が発行されますã?
666             *
667             * 正常に処ç�?�Œ終äº?�—たå?合ã?ã€?close()を発行し、終äº??ç�?‚’行って下さã�??
668             * またã?例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
669             *
670             * @param       outputName      出力ファイルå�?
671             * @throws Throwable 何らかã?エラーが発生したå?合ã?
672             */
673            public void ppt( final String outputName ) throws Throwable {
674                    saveDoc( outputName, getFilterName( getSuffix( inputName ), "ppt" ) );
675            }
676    
677            /**
678             * 出力ファイルから出力形式を自動判別しã?変換を行いますã?
679             *
680             * 入出力形式で未対応ã?場å�?形式ã?入出力ファイルの拡張子で判別)、例外が発行されますã?
681             *
682             * 正常に処ç�?�Œ終äº?�—たå?合ã?ã€?close()を発行し、終äº??ç�?‚’行って下さã�??
683             * またã?例外が発生したå?合ã?ã€?close(true)を発行し、終äº??ç�?‚’行って下さã�??
684             *
685             * @param       outputName      出力ファイルå�?
686             * @throws Throwable 何らかã?エラーが発生したå?合ã?
687             */
688            public void auto( final String outputName ) throws Throwable {
689                    String outSuffix = getSuffix( outputName );
690                    if( "pdf".equalsIgnoreCase( outSuffix ) ) {
691                            savePdf( outputName, getFilterName( getSuffix( inputName ), outSuffix ), null );
692                    }
693                    else {
694                            saveDoc( outputName, getFilterName( getSuffix( inputName ), outSuffix ) );
695                    }
696            }
697    
698            /**
699             * フィルター名をæŒ?®šして、各種ファイル形式に出力を行いますã?
700             *
701             * @param       outputName      出力ファイルå�?
702             * @param       filter          フィルターå�?
703             */
704            private void saveDoc(  final String outputName, final String filter ) {
705                    if( xComp == null ) { throw new HybsSystemException( "初めにã€?open()を実行して下さã�? ); }
706                    if( !checkOutput( outputName ) ){ return; }
707    
708                    PropertyValue[] storeProps = new PropertyValue[1];
709                    storeProps[0] = new PropertyValue();
710                    storeProps[0].Name = "FilterName";
711                    storeProps[0].Value = filter;
712    
713                    String url = "file:///" + outputName.replace( '\\', '/' );
714                    @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告ã?抑止。キャストをはずすと、旧3.1 では、エラーになるã?
715                    XStorable xstorable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xComp );
716                    try {
717                            xstorable.storeAsURL( url, storeProps );
718                    }
719                    catch ( Throwable th ) {
720                            throw new HybsSystemException( "ファイルへの変換時にエラーが発生しましたã€?filter=" + filter + "]", th );
721                    }
722            }
723    
724            /**
725             * フィルターを指定してPDF出力を行いますã?
726             *
727             * @param       outputName      出力ファイルå�?
728             * @param       filter          フィルターå�?
729             * @param       pdfPasswd       PDFパスワーãƒ?
730             */
731            private void savePdf( final String outputName, final String filter, final String pdfPasswd ) {
732                    if( xComp == null ) { throw new HybsSystemException( "初めにã€?open()を実行して下さã�? ); }
733                    if( !checkOutput( outputName ) ){ return; }
734    
735                    PropertyValue[] storeProps;
736                    if( pdfPasswd == null || pdfPasswd.length() == 0 ) {
737                            storeProps = new PropertyValue[1];
738                            storeProps[0] = new PropertyValue();
739                            storeProps[0].Name = "FilterName";
740                            storeProps[0].Value = filter;
741                    }
742                    // 帳票要求テーブルでPDFパスワードが設定されてã�?‚‹場å�?
743                    else {
744                            PropertyValue[] filterProps = new PropertyValue[2];
745                            filterProps[0] = new PropertyValue();
746                            filterProps[0].Name = "EncryptFile";
747                            filterProps[0].Value = true;
748                            filterProps[1] = new PropertyValue();
749                            filterProps[1].Name = "DocumentOpenPassword";
750                            filterProps[1].Value = pdfPasswd;
751    
752                            storeProps = new PropertyValue[2];
753                            storeProps[0] = new PropertyValue();
754                            storeProps[0].Name = "FilterName";
755                            storeProps[0].Value = "calc_pdf_Export";
756                            storeProps[1] = new PropertyValue();
757                            storeProps[1].Name = "FilterData";
758                            storeProps[1].Value = filterProps;
759                    }
760    
761                    String url = "file:///" + outputName.replace( '\\', '/' );
762                    @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なキャスト警告ã?抑止。キャストをはずすと、旧3.1 では、エラーになるã?
763                    XStorable xstorable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xComp );
764                    try {
765                            xstorable.storeToURL( url, storeProps );
766                    }
767                    catch ( Throwable th ) {
768                            throw new HybsSystemException( "PDFファイルへの変換時にエラーが発生しましたã€?filter=" + filter + "]", th );
769                    }
770            }
771    
772            /**
773             * 出力ファイルのチェãƒ?‚¯を行いますã?
774             *
775             * @param       outputName      出力ファイルå�?
776             *
777             * @return      処ç�?¯¾象かどã�?�‹(入力ファイルと出力ファイルが同じå?合ã?、falseが返りまã�?
778             */
779            private boolean checkOutput( final String outputName ) {
780                    if( outputName == null || outputName.length() == 0 ) {
781                            throw new HybsSystemException( "出力ファイルが指定されてã�?�¾せんã€? );
782                    }
783    
784                    File inFile = new File( inputName );
785                    File outFile = new File( outputName );
786    
787                    if( outFile.exists() ) {
788                            if( inFile.getAbsoluteFile().equals( outFile.getAbsoluteFile() ) ) {
789                                    // 入力と出力が同じファイルの場合な何もしなã�?
790                                    return false;
791                            }
792                            else if( !outFile.delete() ) {
793                                    throw new HybsSystemException( "出力å?の既存ファイルが削除できませんã€?file=" + outputName + "]" );
794                            }
795                    }
796                    return true;
797            }
798    
799            /**
800             * 入出力ã?形å¼?拡張å­?からフィルター名を取得しますã?
801             *
802             * @param       inSuffix        入力拡張å­?
803             * @param       outSuffix       出力拡張å­?
804             *
805             * @return      フィルターå�?
806             */
807            private static String getFilterName( final String inSuffix, final String outSuffix ) {
808                    String filterName = filterMap.get( inSuffix + "_" + outSuffix );
809                    if( filterName == null ) {
810                            String errMsg = "入力形式ã?出力形式ã?、以下ã?対応表に基づきã?設定して下さã�??" + HybsSystem.CR
811                                                            + "入力[Calc(ods)   ,Excel(xls)     ] â‡?出力[Calc(ods)   ,Excel(xls)     ,PDF]" + HybsSystem.CR
812                                                            + "入力[Writer(odt) ,Word(doc)      ] â‡?出力[Writer(odt) ,Word(doc)      ,PDF]" + HybsSystem.CR
813                                                            + "入力[Impress(odp),PowerPoint(ppt)] â‡?出力[Impress(odp),PowerPoint(ppt),PDF]" + HybsSystem.CR;
814                            throw new HybsSystemException( errMsg );
815                    }
816                    return filterName;
817            }
818    
819            /**
820             * ファイル名から拡張å­?小文å­?を求めますã?
821             *
822             * @param       fileName        ファイルå�?
823             *
824             * @return      拡張å­?小文å­?
825             */
826            private static String getSuffix( final String fileName ) {
827                    String suffix = null;
828                    if( fileName != null ) {
829    //                      int sufIdx = fileName.lastIndexOf( "." );
830                            int sufIdx = fileName.lastIndexOf( '.' );
831                            if( sufIdx >= 0 ) {
832                                    suffix = fileName.substring( sufIdx + 1 ).toLowerCase( Locale.JAPAN );
833                            }
834                    }
835                    return suffix;
836            }
837    
838            /**
839             * ドキュメントã?変換を行うための簡易メソãƒ?ƒ‰ですã?
840             *
841             * 変換方法ã?、å?力ファイルの拡張子により自動的に決定されますã?
842             *
843             * @param       inputFile       入力ファイルå�?
844             * @param       outputFile      出力ファイルå�?
845             * @see #convert(String[], String, boolean)
846             */
847            public static final void convert( final String inputFile, final String outputFile ) {
848                    convert( StringUtil.csv2Array( inputFile ), outputFile );
849            }
850    
851            /**
852             * ドキュメントã?変換を行うための簡易メソãƒ?ƒ‰ですã?
853             *
854             * 変換方法ã?、å?力ファイルの拡張子により自動的に決定されますã?
855             *
856             * @param       inputFile       入力ファイル名é?åˆ?
857             * @param       outputFile      出力ファイルå�?
858             * @see #convert(String[], String, boolean)
859             */
860            public static final void convert( final String[] inputFile, final String outputFile ) {
861                    convert( inputFile, outputFile, true );
862            }
863    
864            /**
865             * ドキュメントã?変換を行うための簡易メソãƒ?ƒ‰ですã?
866             *
867             * 変換方法ã?、å?力ファイルの拡張子により自動的に決定されますã?
868             *
869             * isOnlineがtrueにæŒ?®šされた場合ã?soffice.binのプロセスをファクトリークラス経由で生æ?しã?
870             * キャãƒ?‚·ュしますã?
871             * ä½?�—、シスãƒ?ƒ リソースが読み込まれなã�?‚ˆã�?�ª、バãƒ?ƒ�ファイルから起動したå?合ã?、この方法ã?
872             * 利用できなã�?�Ÿめã?isOnlineをfalseにæŒ?®šするå¿?¦�がありますã?
873             *
874             * @param       inputFile       入力ファイル名é?åˆ?
875             * @param       outputFile      出力ファイルå�?
876             * @param       isOnline        オンライン(Web環å¢?�§の使用)かどã�?�‹
877             */
878            public static final void convert( final String inputFile[], final String outputFile, final boolean isOnline ) {
879                    DocConverter_OOO dc = new DocConverter_OOO( inputFile, isOnline );
880                    try {
881                            dc.open();
882                            dc.auto( outputFile );
883                            dc.close();
884                    }
885                    catch ( Throwable th ) {
886                            dc.close( true );
887                            throw new HybsSystemException( th );
888                    }
889            }
890    
891            /**
892             * ドキュメントã?変換を行いますã?
893             *
894             * 変換方法ã?、å?力ファイルの拡張子により自動的に決定されますã?
895             *
896             * @og.rev 4.3.1.1 (2008/08/23) mkdirs の戻りå?判å®?
897             *
898             * @param       args    コマンド引数配å?
899             * @throws Exception 何らかã?エラーが発生したときã?
900             */
901            public static void main( final String[] args ) throws Exception {
902                    if( args.length < 2 ) {
903                            System.out.println( "usage : OdsConverter [inputFile or inputDir] [outputDir]" );
904                            return;
905                    }
906    
907                    File input = new File( args[0] );
908                    File output = new File( args[1] );
909    
910                    // 4.3.1.1 (2008/08/23) mkdirs の戻りå?判å®?
911                    if( output.mkdirs() ) {
912                            System.err.println( args[1] + " の ãƒ?‚£レクトリ作æ?に失敗しましたã€? );
913                    }
914    
915                    if( input.isDirectory() ) {
916                            File[] inputFiles = input.listFiles();
917                            for( int i = 0; i<inputFiles.length; i++ ) {
918                                    String inputFile = inputFiles[i].getAbsolutePath();
919                                    String outputFile = output.getAbsolutePath() + File.separator + inputFiles[i].getName().replace( ".xls", ".ods" );
920                                    convert( StringUtil.csv2Array( inputFile ), outputFile, false );
921                            }
922                    }
923                    else {
924                            String inputFile = input.getAbsolutePath();
925                            String outputFile = output.getAbsolutePath() + File.separator + input.getName().replace( ".xls", ".ods" );
926                            convert( StringUtil.csv2Array( inputFile ), outputFile, false );
927                    }
928            }
929    }