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.IOException;
019    import java.net.InetSocketAddress;
020    import java.net.Socket;
021    
022    import org.opengion.hayabusa.common.HybsSystemException;
023    
024    /**
025     * OpenOfficeのプロセスを表すクラスです?
026     *
027     * こ?クラスでは、TCPによりプロセスに接続を行います?
028     * 基本?は、パイプ名による接?{@link SOfficeProcess})を利用すべきですが?
029     * x64環??4Bit版?Javaを起動した?合?パイプ接続では、UnsatisfiedLinkErrorが発生します?
030     * こ?ような場合では、TCP接続を利用することで、上記エラーを回避することができます?
031     *
032     * @version  4.0
033     * @author   Hiroki Nakamura
034     * @since    JDK5.0,
035     */
036    public final class SOfficeProcessTcp extends SOfficeProcess {
037    
038            private static final boolean[] ports    = new boolean[512];
039            private static final Object lock                = new Object();
040    
041            private final int initPort;
042            private final int thisPort;
043    
044            /**
045             * コンストラクタです?
046             *
047             * @param       id                      プロセスID
048             * @param       initPort        初期ポ??
049             */
050            protected SOfficeProcessTcp( final String id, final int initPort ) {
051                    super( id );
052    
053                    this.initPort = initPort;
054                    this.thisPort = getThisPort();
055            }
056    
057            /**
058             * TCP接続?ート番号を取得します?
059             *
060             * @return TCP接続?ート番号
061             */
062            private int getThisPort() {
063                    try {
064                            Thread.sleep( 100 ); // ?後すぐにopenされると、?ートチェ?で引っかかるた?00msWAIT
065                    }
066                    catch( InterruptedException ex ) {
067                            // ここの Exception は、無視します?
068                    }
069    
070                    int port = -1;
071                    synchronized( lock ) {
072                            for( int i=0; i<ports.length; i++ ) {
073                                    if( !ports[i] ) {
074                                            if( checkPort( initPort + i ) ) {
075    //                                              System.out.println( "port=" + ( initPort + i ) + "を使用済みにマ?クしました? );
076                                                    ports[i] = true;
077    //                                              System.out.println( "port=" + ( initPort + i ) + "を使用します?" );
078                                                    port = initPort + i;
079                                                    break;
080                                            }
081    //                                      else {
082    //                                              System.out.println( "port=" + ( initPort + i ) + "は使用中のためスキ??します?" );
083    //                                      }
084                                    }
085                            }
086                    }
087                    if( port < 0 ) {
088                            throw new HybsSystemException( "TCP接続?ートを取得することができません" );
089                    }
090    
091                    return port;
092            }
093    
094            /**
095             * 引数のポ?トが使用中かど?を調べます?
096             *
097             * @param port ポ?ト番号
098             *
099             * @return      使用中かど?
100             */
101            private boolean checkPort( final int port ) {
102                    boolean flg = false;
103                    Socket sk = null;
104                    try {
105                            sk = new Socket();
106                            sk.connect( new InetSocketAddress( "localhost", port ) );
107                    }
108                    catch( IOException ex ) {
109                            flg = true;
110                    }
111                    finally {
112                            try {
113    //                              sk.close();
114                                    if( sk != null ) { sk.close(); }        // 5.5.2.6 (2012/05/25) findbugs対?
115                            }
116                            catch( IOException ex ) {
117                                    ex.printStackTrace();
118                            }
119                    }
120                    return flg;
121            }
122    
123            /**
124             * Pipe名をキーにOpenOfficeのプロセスに接続するため???を生成します?
125             * ※TCP接続?場合?キーのPipe名?無視され???管?れるポ?ト番号?より
126             *   接続?ートを取得します?
127             *
128             * @param key Pipe?無視されま?
129             *
130             * @return 接続文字?
131             */
132            @Override
133            protected String getConnParam( final String key ) {
134                    System.out.println( "[INFO]OOo:TCP Connection Start,port=" + thisPort );
135    //              return "uno:socket,host=localhost,tcpNoDelay=1,port=" + String.valueOf( thisPort ) + ";urp;StarOffice.ComponentContext";
136                    return "uno:socket,host=localhost,tcpNoDelay=1,port=" + thisPort + ";urp;StarOffice.ComponentContext";
137            }
138    
139            /**
140             * Pipe名をキーにOpenOfficeのプロセスを生成するため?パラメーター??を生成します?
141             * ※TCP接続?場合?キーのPipe名?無視され???管?れるポ?ト番号?より
142             *   接続?ートを取得します?
143             *
144             * @param key Pipe?無視されま?
145             *
146             * @return プロセス生?パラメーター
147             */
148            @Override
149            protected String getProcParam( final String key ) {
150    //              return "-accept=socket,host=localhost,port=" + String.valueOf( thisPort ) + ";urp;";
151                    return "-accept=socket,host=localhost,port=" + thisPort + ";urp;";
152            }
153    
154            /**
155             * プロセスを終?ます?
156             * また?同時に環?定用のファイルも削除します?
157             * ここでは、?ロセスを終?ると同時に、そのプロセスのポ?ト番号を開放し?
158             * 次に起動されるプロセスで利用できるようにします?
159             */
160            @Override
161            public void close() {
162                    super.close();
163                    synchronized( lock ) {
164                            ports[thisPort-initPort] = false;
165                    }
166    //              System.out.println( "[INFO]OOo:TCP Connection End(Release),port=" + String.valueOf( thisPort ) );
167                    System.out.println( "[INFO]OOo:TCP Connection End(Release),port=" + thisPort );
168            }
169    }
170