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.fukurou.util;
017    
018    import java.awt.Rectangle;
019    import java.awt.Robot;
020    import java.awt.image.BufferedImage;
021    import java.awt.AWTException;
022    import javax.imageio.ImageIO;
023    
024    import java.awt.Toolkit;
025    import java.awt.datatransfer.Clipboard;
026    import java.awt.datatransfer.DataFlavor;
027    import java.awt.datatransfer.StringSelection;
028    import java.awt.datatransfer.FlavorListener;
029    import java.awt.datatransfer.FlavorEvent;
030    import java.awt.datatransfer.UnsupportedFlavorException;
031    import java.io.IOException;
032    import java.io.File;
033    
034    /**
035     * DisplayCapture.java は、画面イメージをキャプチャして、ファイルに書きå?すためã?クラスですã?
036     *
037     * 基本çš?�ª使ã�?–¹は、main メソãƒ?ƒ‰から立ち上げて、クリãƒ??ボã?ドã?状態を監視しますã?
038     * クリãƒ??ボã?ドにã€?GUI:画面ID xxxxx.jsp" 形式ã?æ–?­—が書き込まれると、flavorsChanged イベントが
039     * 発生して、画面をã?ファイルに書きå?すå?ç�?�Œ実行されますã?
040     * エンジンの機è?と連動すれã?、画面IDã‚?ƒ•ァイル名をクリãƒ??ボã?ド経由でこã?アプリケーションに
041     * 渡すことで、画面操作を行うã�?�‘で、è?動的に画面キャプチャを行うことが可能ですã?
042     *
043     * エンジンでは、jsp/indexc.jsp に、この機è?がçµ?�¿込まれてã�?‚‹ため、gf\BAT\displayCapture の
044     * DisplayCapture.bat を起動後ã?アプリケーションをã?jsp/indexc.jsp で呼び出せã?、è?動的に
045     * 画面のキャプチャを開始できますã?
046     * キャプチャは、å?画面のみですã?で、IEを最大にåº?�’て操作してくださいã€?
047     * またã??¢Prnt Scrn?£ボタンにも対応してã�?�¾すã?で、操作中ã‚??ãƒ??アãƒ??等ã?非è?動化の
048     * 画面キャプチャもã?手動で取得できますã?
049     *
050     * 起動時の引数に応じて、å?ç�?‚’制御することが可能ですã?
051     *
052     * 書きå?すフォルãƒ??、BASE_DIR でæŒ?®šしますã?
053     *  すべてのキャプチャ画像ã?、ã?ースフォルãƒ?にé›?´?�—て保存しますã?
054     *  キャプチャ画像ã?æƒ??は、å?力されるファイル名に反映されますã?ファイル名ã?形式も?’種類ありã?
055     *  キャプチャé ?�¨、画面IDé ?�ŒæŒ?®šできますã?
056     *  初期値は、Java起動時のフォルãƒ?�«なりますã?
057     *
058     * 書きå?すファイル名ã?初期形式ã?、firstID の設定により異なりますã?
059     *   firstID ã‚?gui に設定したå?å�?
060     *      ベã?スフォルãƒ?�§フォルãƒ?‚’作æ?しã?そã?中に、画面ID_JSPファイル名_連番.画像形å¼?ファイルを作æ?しますã?
061     *      画面ID 単位に、画面のキャプチャを整ç�??使用したã�??合に便利ですã?
062     *      ファイルのタイãƒ?‚¹タンãƒ?作æ?時刻)で並び替えを行えば、キャプチャé ?�«並び替えできますã?
063     *   firstID ã‚?seq に設定したå?å�?
064     *      ベã?スフォルãƒ?�§フォルãƒ?‚’作æ?しã?そã?中にã€??番_画面ID_JSPファイルå�?画像形å¼?ファイルを作æ?しますã?
065     *      ファイルは、キャプチャされたé?番に、画面IDも混在して作æ?されますã?つまりã?ファイル名ã?é ?•ªに
066     *      再生すれば、リンクã‚?»–ã?シスãƒ?ƒ との連携などで、画面が行き来してもã?作業のé ?•ªにキャプチャできて
067     *      ã�?‚‹事になりますã?
068     *
069     * こã?クラスは、これらを実現するために利用してã�?‚‹、static メソãƒ?ƒ‰をいくつか持ってã�?�¾すã?
070     *   BufferedImage doCapture()
071     *      画面イメージをキャプチャしますã?これは、å?画面ですã?
072     *   void saveImage( File saveFile, BufferedImage img, String imgType )
073     *      æŒ?®šã?ファイルに、画面イメージを書きå?しますã?
074     *      imgType に、画像ã?種é¡?png|gif|jpg)を指定しまã�?初期値:png)ã€?
075     *   String getClipboard()
076     *      現在のクリãƒ??ボã?ドã?値を取りå?しますã?ここでは、文字å?のみ取り出すことが可能ですã?
077     *      こã?メソãƒ?ƒ‰の特徴çš?�ªところは、PrintScreenなどのæ–?­—å?以外ã?値をクリãƒ??ボã?ドにセãƒ?ƒˆ
078     *      した場合にã€?GUI:PRINT SCREEN.img" とã�?�†æ–?­—å?を返すところですã?つまりã?そã?場合ã?ã€?
079     *      全画面のキャプチャが行われるとã�?�†事ですã?
080     *   void setClipboard( String txt )
081     *      クリãƒ??ボã?ドに、文字å?をセãƒ?ƒˆしますã?
082     *
083     * こã?クラスが実è£?�—てã�?‚‹ FlavorListener は、クリãƒ??ボã?ドã?"値"の更新には追従してã�?�¾せんã€?
084     * å†?ƒ¨の Transferable オブジェクトが変更されたå?合に、flavorsChanged メソãƒ?ƒ‰が呼び出されますã?
085     * つまりã?ä¸?º¦セãƒ?ƒˆされた文字型ãƒ??タは、取りå?した後ã?別のTransferable オブジェクトに変更して
086     * おかなã�?�¨、次のæ–?­—å?の変更が拾えなくなりますã?またã?こã?別のTransferableオブジェクトã?
087     * 設定で、å?び、イベントが発生するã?で、そのままでは、無限ループになってしまã�?�¾すã?
088     * そこで、少し、トリãƒ?‚­ーなのですが、setClipboard( String ) すると、å?びイベントが呼び出され
089     * なã�?‚ˆã�?�«、取得した文字å?の先é?がã?"GUI:" で始まるå?合ã?み、å?設定するよã�?�«してã�?�¾すã?
090     *
091     * Usage: java org.opengion.fukurou.util.DisplayCapture
092     *                   [BASE_DIR] [firstID(seq|gui)] [imageFormat(png|gif|jpg)] [startCnt(100)]
093     *
094     *     args[0]  BASE_DIR    : キャプチャファイルをセーブするã?ースとなるディレクトリ(初期値:起動フォルãƒ?
095     *     args[1]  firstID     : キャプチャ画像をセーブするファイル方式をæŒ?®šしまã�?初期値:seq)
096     *                            gui (画面ID_JSPファイル名_連番.画像形å¼?
097     *                            seq (連番_画面ID_JSPファイルå�?画像形å¼?
098     *     args[2]  imageFormat : 作æ?するイメージの形式ã?png|gif|jpg のどれか(初期値:png)
099     *     args[3]  startCnt    : セーブファイル名をユニã?クにするためのカウンãƒ?初期値:100)
100     *
101     * こã?実è£??同期化されませんã€?
102     *
103     * @og.rev 5.1.7.0 (2010/06/01) 新規追åŠ?
104     * @og.rev 5.2.1.0 (2010/10/01) 実用性を重視した改修
105     *
106     * @version  5.0
107     * @author   Kazuhiko Hasegawa
108     * @since    JDK6.0,
109     */
110    public final class DisplayCapture implements FlavorListener {
111            private static final Clipboard CLIP_BOARD = Toolkit.getDefaultToolkit().getSystemClipboard();
112            private static final Rectangle SCRN_SIZE  = new Rectangle( Toolkit.getDefaultToolkit().getScreenSize() );
113    
114            private File    baseDir         = new File(".");                // セーブするã?ースãƒ?‚£レクトリ
115            private String  firstID         = "seq";                                // 保存時のファイル名ã?形å¼?seq|gui)
116            private String  imgType         = "png" ;                               // 画像形å¼?png|gif|jpg)
117            private int             cnt                     = 100;                                  // ユニã?ク番号(セーブファイル名に付ä¸?
118    
119            /**
120             * キャプチャファイルをセーブするã?ースとなるディレクトリを設定しまã�?初期値:java実行フォルãƒ?ã€?
121             *
122             * クラスのå†?ƒ¨çš?�«は、Java の実行フォルãƒ? new File(".") ) がå?期å?ですã?
123             *
124             * @param       bsDir   セーブするã?ースãƒ?‚£レクトリ
125             * @throws RuntimeException セーブフォルãƒ?�Œ作æ?できなかったå?å�?
126             */
127            public void setBaseDir( final String bsDir ) {
128                    if( bsDir != null && bsDir.length() > 0 ) {
129                            baseDir = new File( bsDir );
130    
131                            // ベã?スフォルãƒ??作æ?。å?期å?は起動フォルãƒ?�ªので、å¿?�š存在する(はã�?
132                            if( !baseDir.exists() && !baseDir.mkdirs() ) {
133                                    String errMsg = "ERROR:セーブフォルãƒ?�Œ作æ?できませんでしたã€? + baseDir.getAbsolutePath()  ;
134                                    throw new RuntimeException( errMsg );
135                            }
136                    }
137            }
138    
139            /**
140             * キャプチャ画像をセーブするファイル方式をæŒ?®šしまã�?初期値:seq)ã€?
141             *
142             *    seq (連番_画面ID_JSPファイルå�?画像形å¼?
143             *    gui (画面ID_JSPファイル名_連番.画像形å¼?
144             *
145             * 初期値は、seq ですã?
146             *
147             * @param       firstID セーブするファイル方å¼?seq|gui)
148             * @throws RuntimeException ファイル方式ã?æŒ?®šが間違ってã�?�Ÿ場å�?
149             */
150            public void setFirstID( final String firstID ) {
151                    if( firstID != null ) {
152                            if( firstID.matches( "seq|gui" ) ) {
153                                    this.firstID = firstID;
154                            }
155                            else {
156                                    String errMsg = "ERROR:firstID 属æ?はã€?seq|gui)でお願いしますã?firstID=[" + firstID + "]" ;
157                                    throw new RuntimeException( errMsg );
158                            }
159                    }
160            }
161    
162            /**
163             * キャプチャ画像をセーブする画像形式をæŒ?®šしまã�?初期値:png)ã€?
164             *
165             * キャプチャされたイメージをセーブするときã?画像形式をæŒ?®šできますã?
166             * ここでは、png , gif ,jpg を指定できますã?
167             *
168             * 初期値は、png 形式ですã?
169             *
170             * @param       imgType セーブする画像形å¼?png|gif|jpg)
171             */
172            public void setImageType( final String imgType ) {
173                    if( imgType != null && imgType.matches( "png|gif|jpg" ) ) {
174                            this.imgType = imgType;
175                    }
176            }
177    
178            /**
179             * キャプチャ画像をセーブするファイル名ã?先é?に付けるé?番の開始数(初期値:100)ã€?
180             *
181             * キャプチャされたイメージをセーブするときã?画面IDとJSPファイル名だけでは、前回å?ã‚?
182             * 上書きしてしまã�?�Ÿめã?ファイル名ã?先é?に連番を付与してã�?�¾すã?
183             * ここでは、その連番の開始番号を指定できますã?
184             *
185             * 初期値はã€?00 ですã?
186             *
187             * @param       startCnt        連番の開始数(初期値:100)
188             */
189            public void setStartCnt( final String startCnt ) {
190                    if( startCnt != null && startCnt.length() > 0 ) {
191                            cnt = Integer.parseInt( startCnt );
192                    }
193            }
194    
195            /**
196             * 全画面の画像イメージ(キャプチャ画åƒ?を取得しますã?
197             *
198             * java.awt.Toolkit で、å?画面のスクリーンサイズを取得し、java.awt.Robot の
199             * createScreenCapture( Rectangle ) メソãƒ?ƒ‰で、BufferedImage を取得してã�?�¾すã?
200             *
201             * @return      全画面の画像イメージ
202             * @throws RuntimeException AWTException が発生したå?å�?
203             */
204            public static BufferedImage doCapture() {
205                    BufferedImage img = null;
206                    try{
207                            Robot robo = new Robot();
208                            img = robo.createScreenCapture( SCRN_SIZE );
209                    }
210                    catch( AWTException ex ) {
211    //                      ex.printStackTrace();
212                            String errMsg = "ERROR:画像イメージ(キャプチャ画åƒ?が取得できませんでしたã€? ;
213                            setClipboard( errMsg );
214                            throw new RuntimeException( errMsg,ex );
215                    }
216                    catch( Throwable th ) {
217                            String errMsg = "ERROR:" + th.getLocalizedMessage() ;
218                            setClipboard( errMsg );
219                            throw new RuntimeException( errMsg,th );
220                    }
221    
222                    return img;
223            }
224    
225            /**
226             * キャプチャ画像をファイルにセーブしますã?
227             *
228             * ここでは、単純に、引数そã?ままで、ImageIO.write( BufferedImage,String,File ) してã�?�¾すã?
229             * saveFile のãƒ?‚£レクトリ存在チェãƒ?‚¯ã‚??ファイル名ã?拡張å­?png,gif,jpgなど)の修正ã€?
230             * imgType の形式チェãƒ?‚¯などは、行ってã�?�¾せんã€?
231             * それらã?処ç�??、事前に、調整しておいてくださいã€?
232             *
233             * @param       img     セーブする画像イメージ
234             * @param       imgType セーブする画像形å¼?png|gif|jpg)
235             * @param       saveFile        セーブする画像ファイルオブジェクãƒ?
236             * @throws RuntimeException IOException が発生したå?å�?
237             * @see  javax.imageio.ImageIO#write( java.awt.image.RenderedImage , String , java.io.File )
238             */
239            public static void saveImage( final BufferedImage img , final String imgType , final File saveFile ) {
240                    try{
241                            ImageIO.write( img,imgType,saveFile );
242                    }
243                    catch( IOException ex ) {
244    //                      ex.printStackTrace();
245                            String errMsg = "ERROR:キャプチャ画像をファイルにセーブできませんでしたã€? + saveFile.getAbsolutePath()  ;
246                            setClipboard( errMsg );
247                            throw new RuntimeException( errMsg,ex );
248                    }
249                    catch( Throwable th ) {
250                            String errMsg = "ERROR:" + th.getLocalizedMessage() ;
251                            setClipboard( errMsg );
252                            throw new RuntimeException( errMsg,th );
253                    }
254            }
255    
256            /**
257             * シスãƒ?ƒ のクリãƒ??ボã?ドã?æ–?­—å?を取得しますã?
258             *
259             * Toolkit.getDefaultToolkit().getSystemClipboard() で取得された  Clipboard オブジェクトかã‚?
260             * æ–?­—å?æƒ??(DataFlavor.stringFlavor)を取得しますã?
261             * æ–?­—å?æƒ??が取得できなã�??合ã?(UnsupportedFlavorException が発生したå?å�? 例えばã€?
262             * PrntScrn ボタンが押されたå?合などは、文字å?としてã€?GUI:PRINT SCREEN.img" を返しますã?
263             * これは、文字å?が返せなã�??合でもã?クリãƒ??ボã?ドに書き込まれたイベントで、å?画面のキャプチャã‚?
264             * 取得するためã?、特殊なコマンドに相当しますã?
265             *
266             * @return      クリãƒ??ボã?ドã?æ–?­—å?
267             * @throws RuntimeException IOException が発生したå?å�?
268             * @see  java.awt.datatransfer.Clipboard#getData( DataFlavor )
269             */
270            public static String getClipboard() {
271                    String strClip = null;
272    
273                    // 方法として、Transferable を取得後ã?getTransferData する事もできるã€?
274            //      Transferable data = CLIP_BOARD.getContents(null);
275    
276                    try {
277                            // クリãƒ??ボã?ドã?値を取å¾?
278            //              strClip = (String)data.getTransferData(DataFlavor.stringFlavor);
279                            strClip = (String)CLIP_BOARD.getData( DataFlavor.stringFlavor );
280                    }
281                    catch( UnsupportedFlavorException ex ) {
282                            // PrintScreen が押されたå?合ã?
283                            strClip = "GUI:PRINT SCREEN.img" ;              // 形式をGUI:画面ID xxxxx.jsp 形式に合わす為
284                    }
285                    catch( IOException ex ) {
286    //                      ex.printStackTrace();
287                            String errMsg = "ERROR:クリãƒ??ボã?ドã?値を取得できませんでしたã€? ;
288                            setClipboard( errMsg );
289                            throw new RuntimeException( errMsg,ex );
290                    }
291                    catch( Throwable th ) {
292                            String errMsg = "ERROR:" + th.getLocalizedMessage() ;
293                            setClipboard( errMsg );
294                            throw new RuntimeException( errMsg,th );
295                    }
296    
297                    return strClip;
298            }
299    
300            /**
301             * シスãƒ?ƒ のクリãƒ??ボã?ドにæ–?­—å?を書き込みますã?
302             *
303             * シスãƒ?ƒ の Clipboard オブジェクトに、StringSelection ã‚?セãƒ?ƒˆしますã?
304             * 通常であれば、単純に、クリãƒ??ボã?ド経由でãƒ??タのã‚?‚Š取りをするだけã?機構ですがã€?
305             * FlavorListener を実è£?�—てã�?‚‹関係上ã?flavorsChanged が発生しますã?
306             * こã?イベントにつã�?�¦はã€?flavorsChanged( FlavorEvent ) を参照くださいã€?
307             *
308             * @param       txt     クリãƒ??ボã?ドに書き込ã‚?–‡字å?
309             * @see  java.awt.datatransfer.StringSelection
310             * @see  java.awt.datatransfer.Clipboard#setContents( Transferable , ClipboardOwner )
311             */
312            public static void setClipboard( final String txt ) {
313                    StringSelection strSel = new StringSelection( txt );
314                    CLIP_BOARD.setContents( strSel, null );
315            }
316    
317            /**
318             * リスナã?対象の Clipboard で使用可能な DataFlavor が変更されたときに呼び出されますã?
319             *
320             * これは、FlavorListener の イベントã?実è£?�§すã?
321             * DataFlavor が変更されたときであり、そのãƒ??タのå†?®¹が書き換えられた場合には、イベントが
322             * 発生しませんã€?
323             * そã?ため、データを取りå?したあとで、Transferable をå?セãƒ?ƒˆする処ç�?‚’行ってã�?�¾すã?
324             *
325             * クリãƒ??ボã?ドで使用可能なä¸??の DataFlavors の変更によるもã?でなã�??余å?な通知もありますã?
326             * さらに、イベントを発生させるために、Transferable をセãƒ?ƒˆする処ç�? #setClipboard(String) )ã‚?
327             * 実行してもã?同様にイベントが発生しますã?
328             *
329             * ここでは、取得したクリãƒ??ボã?ドã?æ–?­—å?がã?"GUI:" の場合ã?み処ç�?�—てã�?�¾すã?
330             * これにより、取得後ã? Transferable の再セãƒ?ƒˆ時ã?æ–?­—å?はã€?GUI:" を削除してã�?�¾すã?
331             *
332             * こã?メソãƒ?ƒ‰では、画面キャプチャを取得し、クリãƒ??ボã?ドã?æ–?­—å?から、画面ID とJSPファイル名を
333             * 抜き出しã?セーブするä¸??の処ç�?‚’行ってã�?�¾すã?
334             *
335             * @param       fe      イベントソース
336             * @see  java.awt.datatransfer.FlavorListener#flavorsChanged( FlavorEvent )
337             */
338            @Override
339            public void flavorsChanged( final FlavorEvent fe )  {
340                    String txt = getClipboard();
341    
342                    // クリãƒ??ボã?ドã?値をクリアしたときã?イベントã?、拾わなã�?�Ÿめã?
343                    if( txt != null && txt.length() > 0 && txt.startsWith( "GUI:" ) ) {
344                            System.out.println( cnt + ":� + txt + "� );
345                            BufferedImage img = doCapture();
346    
347                            File saveFile = makeSaveFile( txt );
348    
349                            saveImage( img,imgType,saveFile );
350    
351                            // クリãƒ??ボã?ドã?Flavorを置換しますã?(Windwosからセãƒ?ƒˆされた時にイベントを発生させるためã€?
352                            // 先é?の GUI: を取り除くã?イベントã?無限ループを防ぐ意味ã€?
353                            setClipboard( txt.substring( 4 ) );
354                    }
355            }
356    
357            /**
358             * キャプチャ画像を書きå?すファイルオブジェクトを作æ?しますã?
359             *
360             * 引数はã€?GUI:画面ID xxxxx.jsp" 形式を想定した文字å?ですã?
361             *
362             * ファイル名にはã€?¼’種類ありますã?
363             *   firstID ã‚?seq に設定したå?å�?
364             *      ベã?スフォルãƒ?�§フォルãƒ?‚’作æ?しã?そã?中にã€??番_画面ID_JSPファイルå�?画像形å¼?ファイルを作æ?しますã?
365             *      ファイルは、キャプチャされたé?番に、画面IDも混在して作æ?されますã?つまりã?ファイル名ã?é ?•ªに
366             *      再生すれば、リンクã‚?»–ã?シスãƒ?ƒ との連携などで、画面が行き来してもã?作業のé ?•ªにキャプチャできて
367             *      ã�?‚‹事になりますã?
368             *   firstID ã‚?gui に設定したå?å�?
369             *      ベã?スフォルãƒ?�§フォルãƒ?‚’作æ?しã?そã?中に、画面ID_JSPファイル名_連番.画像形å¼?ファイルを作æ?しますã?
370             *      画面ID 単位に、画面のキャプチャを整ç�??使用したã�??合に便利ですã?
371             *      ファイルのタイãƒ?‚¹タンãƒ?作æ?時刻)で並び替えを行えば、キャプチャé ?�«並び替えできますã?
372             *
373             * こã?メソãƒ?ƒ‰で、フォルãƒ??存在チェãƒ?‚¯、およã?、無ければ作æ?(mkdirs)も行いますã?
374             *
375             * @param       txt     ファイル名ã?å…?�¨なる文字å?("GUI:画面ID xxxxx.jsp" 形å¼?
376             *
377             * @return      書きå?すファイルオブジェクãƒ?
378             */
379            private File makeSaveFile( final String txt ) {
380                    int spc = txt.indexOf( ' ' );                                                   // "GUI:画面ID xxxxx.jsp" をスペã?スでåˆ?›¢
381                    String gui = txt.substring( 4,spc );                                    //      画面ID の部åˆ??みåˆ?‚Š出すã?
382                    String jsp = txt.substring( spc+1,txt.length()-4 );             //             xxxxx の部åˆ??みåˆ?‚Š出すã?
383    
384                    String saveFile = null;
385                    if( "seq".equalsIgnoreCase( firstID ) ) {
386                            saveFile = cnt++ + "_" + gui + "_" + jsp + "." + imgType ;
387                    }
388                    else if( "gui".equalsIgnoreCase( firstID ) ) {
389                            saveFile = gui + "_" + jsp + "_" + cnt++ + "." + imgType ;
390                    }
391                    else {          // 5.5.2.6 (2012/05/25) findbugs対å¿?
392                            saveFile = cnt++ + "_" + gui + "_" + jsp + "." + imgType ;              // seqかguiしかなã�?�Œ、経路として、å?期å?(seq)を設定しておくã€?
393                    }
394    
395                    File svf = new File( baseDir,saveFile );
396                    // セーブフォルãƒ??作æ?ã€?
397                    File parent = svf.getParentFile();
398                    if( !parent.exists() && !parent.mkdirs() ) {
399                            String errMsg = "ERROR:セーブフォルãƒ?�Œ作æ?できませんでしたã€? + parent.getAbsolutePath()  ;
400                            setClipboard( errMsg );
401                            throw new RuntimeException( errMsg );
402                    }
403    
404                    // セーブファイルの存在チェãƒ?‚¯。上書き禁止にしておきますã?
405                    if( svf.exists() ) {
406                            String errMsg = "ERROR:セーブファイルがすでに作æ?されてã�?�¾すã?" + svf.getAbsolutePath()  ;
407                            setClipboard( errMsg );
408                            throw new RuntimeException( errMsg );
409                    }
410    
411                    return svf;
412            }
413    
414            /**
415             * DisplayCapture.java は、画面イメージをキャプチャする、メインメソãƒ?ƒ‰ですã?
416             *
417             * Javaアプリケーションとして実行すると、無限å?ç�?�«入りますã?
418             * å†?ƒ¨çš?�«は、flavorsChanged イベンãƒ?によるクリãƒ??ボã?ドã?監視を行いますã?
419             * クリãƒ??ボã?ドにã€?GUI:画面ID xxxxx.jsp" 形式ã?æ–?­—が書き込まれると、画面キャプチャをã?
420             * ファイルに書きå?すå?ç�?�Œ実行されますã?
421             * 書きå?すファイル名ã?初期形式ã?、firstID の設定により異なりますã?
422             *   firstID ã‚?seq に設定したå?å�?
423             *      ベã?スフォルãƒ?�§フォルãƒ?‚’作æ?しã?そã?中にã€??番_画面ID_JSPファイルå�?画像形å¼?ファイルを作æ?しますã?
424             *      ファイルは、キャプチャされたé?番に、画面IDも混在して作æ?されますã?つまりã?ファイル名ã?é ?•ªに
425             *      再生すれば、リンクã‚?»–ã?シスãƒ?ƒ との連携などで、画面が行き来してもã?作業のé ?•ªにキャプチャできて
426             *      ã�?‚‹事になりますã?
427             *   firstID ã‚?gui に設定したå?å�?
428             *      ベã?スフォルãƒ?�§フォルãƒ?‚’作æ?しã?そã?中に、画面ID_JSPファイル名_連番.画像形å¼?ファイルを作æ?しますã?
429             *      画面ID 単位に、画面のキャプチャを整ç�??使用したã�??合に便利ですã?
430             *      ファイルのタイãƒ?‚¹タンãƒ?作æ?時刻)で並び替えを行えば、キャプチャé ?�«並び替えできますã?
431             *
432             * Usage: java org.opengion.fukurou.util.DisplayCapture
433             *                   [BASE_DIR] [firstID(seq|gui)] [imageFormat(png|gif|jpg)] [startCnt(100)]
434             *
435             *     args[0]  BASE_DIR    : キャプチャファイルをセーブするã?ースとなるディレクトリ(初期値:起動フォルãƒ?
436             *     args[1]  firstID     : キャプチャ画像をセーブするファイル方式をæŒ?®šしまã�?初期値:seq)
437             *                            seq (連番_画面ID_JSPファイルå�?画像形å¼?
438             *                            gui (画面ID_JSPファイル名_連番.画像形å¼?
439             *     args[2]  imageFormat : 作æ?するイメージの形式ã?png|gif|jpg のどれか(初期値:png)
440             *     args[3]  startCnt    : セーブファイル名をユニã?クにするためのカウンãƒ?初期値:100)
441             *
442             * @param       args    引数 [BASE_DIR] [firstID(seq|gui)] [imageFormat(png|gif|jpg)] [startCnt(100)]
443             */
444            public static void main( final String[] args ) {
445                    System.out.println( "DisplayCapture を起動しましたã€? );
446    
447                    DisplayCapture dispCap = new DisplayCapture();
448    
449                    if( args.length > 0 ) { dispCap.setBaseDir(   args[0] ); }
450                    if( args.length > 1 ) { dispCap.setFirstID(   args[1] ); }
451                    if( args.length > 2 ) { dispCap.setImageType( args[2] ); }
452                    if( args.length > 3 ) { dispCap.setStartCnt(  args[3] ); }
453    
454                    // クリãƒ??ボã?ドã?値をクリア(FlavorEvent を起こさせるため)
455                    DisplayCapture.setClipboard( null );
456    
457                    // FlavorListener を登録しますã?(自åˆ??身のオブジェクãƒ?
458                    CLIP_BOARD.addFlavorListener( dispCap );
459    
460                    // FlavorEvent で処ç�?�•せるので、ずっとスレãƒ?ƒ‰をSleepさせておけばよいã€?
461                    while( true ) {
462                            try {
463                                    Thread.sleep( 100000 );
464                            }
465                            catch( InterruptedException ex ) {}
466                    }
467            }
468    }