OSDN Git Service

JRE version-checking modified.
[mikutoga/Pmd2XML.git] / src / main / java / jp / sfjp / mikutoga / pmd2xml / Pmd2Xml.java
index c4c4c07..05ba75d 100644 (file)
@@ -7,10 +7,8 @@
 
 package jp.sfjp.mikutoga.pmd2xml;
 
-import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -18,10 +16,12 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.nio.channels.FileChannel;
+import java.text.MessageFormat;
 import java.util.Properties;
-import jp.sourceforge.mikutoga.parser.MmdFormatException;
-import jp.sourceforge.mikutoga.pmd.IllegalPmdDataException;
-import jp.sourceforge.mikutoga.xml.TogaXmlException;
+import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
+import jp.sfjp.mikutoga.pmd.IllegalPmdDataException;
+import jp.sfjp.mikutoga.xml.TogaXmlException;
+import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
 /**
@@ -31,18 +31,18 @@ public final class Pmd2Xml {
 
     /** 正常系。 */
     public static final int EXIT_OK     = 0;
+    /** 内部エラー。 */
+    public static final int EXIT_INTERR = 1;
+    /** 実行環境に起因するエラー。 */
+    public static final int EXIT_ENVERR = 2;
+    /** オプション指定に起因するエラー。 */
+    public static final int EXIT_OPTERR = 3;
     /** ファイル入出力に起因するエラー。 */
-    public static final int EXIT_FILE   = 1;
+    public static final int EXIT_IOERR  = 4;
     /** XMLフォーマットに起因するエラー。 */
-    public static final int EXIT_XML    = 2;
+    public static final int EXIT_XMLERR = 5;
     /** PMDフォーマットに起因するエラー。 */
-    public static final int EXIT_PMD    = 3;
-    /** 実行環境に起因するエラー。 */
-    public static final int EXIT_JREVER = 4;
-    /** オプション指定に起因するエラー。 */
-    public static final int EXIT_OPT    = 5;
-    /** 内部エラー。 */
-    public static final int EXIT_INTERN = 6;
+    public static final int EXIT_PMDERR = 6;
 
     /** アプリ名。 */
     public static final String APPNAME;
@@ -50,15 +50,32 @@ public final class Pmd2Xml {
     public static final String APPVER;
     /** ライセンス種別。 */
     public static final String APPLICENSE;
+    /** 開発元URL。 */
+    public static final String APPURL;
+    /** ジェネレータ名。 */
+    public static final String GENERATOR;
 
     private static final Class<?> THISCLASS;
+    private static final String RES_VER = "resources/version.properties";
 
     private static final PrintStream ERROUT = System.err;
+    private static final String MSG_ERR = "ERROR:\n{0}\n(-h for help)";
+    private static final String MSG_HELP =
+              "{0} {1}\n"
+            + "\u0020\u0020License\u0020:\u0020{2}\n"
+            + "\u0020\u0020{3}\n";
+    private static final String MSG_NOINFILE = "Can't find input file:{0}";
+    private static final String MSG_ABNFILE = "{0} is not file.";
+    private static final String MSG_OWOUTFILE =
+              "{0} already exists.\n"
+            + "If you want to overwrite, use -f.";
+
+    private static final String MSG_OLDJRE = "You need JRE {0} or later.";
+    private static final String REQUIRED_JRE = "1.8";
 
     static{
         THISCLASS = Pmd2Xml.class;
-        InputStream ver =
-                THISCLASS.getResourceAsStream("resources/version.properties");
+        InputStream ver = THISCLASS.getResourceAsStream(RES_VER);
         Properties verProps = new Properties();
         try{
             try{
@@ -73,6 +90,9 @@ public final class Pmd2Xml {
         APPNAME    = verProps.getProperty("app.name");
         APPVER     = verProps.getProperty("app.version");
         APPLICENSE = verProps.getProperty("app.license");
+        APPURL     = verProps.getProperty("app.url");
+
+        GENERATOR = APPNAME + ' ' + APPVER;
 
         new Pmd2Xml().hashCode();
     }
@@ -91,9 +111,21 @@ public final class Pmd2Xml {
     /**
      * VMを終了させる。
      * @param code 終了コード
+     * @see java.lang.System#exit(int)
      */
     private static void exit(int code){
         System.exit(code);
+        assert false;
+        throw new AssertionError();
+    }
+
+    /**
+     * 共通エラーメッセージを出力する。
+     * @param text 個別メッセージ
+     */
+    private static void errMsg(String text){
+        String msg = MessageFormat.format(MSG_ERR, text);
+        ERROUT.println(msg);
         return;
     }
 
@@ -102,12 +134,12 @@ public final class Pmd2Xml {
      * @param ex 例外
      * @param dumpStack スタックトレースを出力するならtrue
      */
-    private static void errPrintln(Throwable ex, boolean dumpStack){
-        String text = ex.toString();
-        ERROUT.println(text);
-
+    private static void thPrintln(Throwable ex, boolean dumpStack){
         if(dumpStack){
             ex.printStackTrace(ERROUT);
+        }else{
+            String text = ex.toString();
+            ERROUT.println(text);
         }
 
         return;
@@ -117,19 +149,8 @@ public final class Pmd2Xml {
      * 標準エラー出力へ例外情報出力。
      * @param ex 例外
      */
-    private static void errPrintln(Throwable ex){
-        errPrintln(ex, false);
-        return;
-    }
-
-    /**
-     * 共通エラーメッセージを出力する。
-     * @param text 個別メッセージ
-     */
-    private static void errMsg(String text){
-        ERROUT.println("ERROR:");
-        ERROUT.println(text);
-        ERROUT.println("(-h for help)");
+    private static void thPrintln(Throwable ex){
+        thPrintln(ex, false);
         return;
     }
 
@@ -138,9 +159,9 @@ public final class Pmd2Xml {
      * 例外を出力してVM終了する。
      * @param ex 例外
      */
-    private static void ioError(Throwable ex){
-        errPrintln(ex);
-        exit(EXIT_FILE);
+    private static void ioError(IOException ex){
+        thPrintln(ex);
+        exit(EXIT_IOERR);
     }
 
     /**
@@ -149,8 +170,8 @@ public final class Pmd2Xml {
      * @param ex 例外
      */
     private static void xmlError(Throwable ex){
-        errPrintln(ex);
-        exit(EXIT_XML);
+        thPrintln(ex);
+        exit(EXIT_XMLERR);
     }
 
     /**
@@ -158,9 +179,9 @@ public final class Pmd2Xml {
      * 例外を出力してVM終了する。
      * @param ex 例外
      */
-    private static void pmdError(Throwable ex){
-        errPrintln(ex, true);
-        exit(EXIT_PMD);
+    private static void pmdError(MmdFormatException ex){
+        thPrintln(ex, true);
+        exit(EXIT_PMDERR);
     }
 
     /**
@@ -169,8 +190,8 @@ public final class Pmd2Xml {
      * @param ex 例外
      */
     private static void internalError(Throwable ex){
-        errPrintln(ex, true);
-        exit(EXIT_INTERN);
+        thPrintln(ex, true);
+        exit(EXIT_INTERR);
     }
 
     /**
@@ -179,37 +200,30 @@ public final class Pmd2Xml {
      */
     private static void checkJRE(){
         Package jrePackage = java.lang.Object.class.getPackage();
-        if( ! jrePackage.isCompatibleWith("1.6")){
-            ERROUT.println("You need JRE 1.6 or later.");
-            exit(EXIT_JREVER);
+        if( ! jrePackage.isCompatibleWith(REQUIRED_JRE)){
+            String msg = MessageFormat.format(MSG_OLDJRE, REQUIRED_JRE);
+            ERROUT.println(msg);
+            exit(EXIT_ENVERR);
         }
         return;
     }
 
     /**
-     * ã\83\98ã\83«ã\83\97ã\83¡ã\83\83ã\82»ã\83¼ã\82¸ã\82\92å\87ºå\8a\9bã\81\97ã\81¦VMã\82\92çµ\82äº\86ã\81\95ã\81\9bる。
+     * ã\83\98ã\83«ã\83\97ã\83¡ã\83\83ã\82»ã\83¼ã\82¸ã\82\92å\87ºå\8a\9bã\81\99る。
      */
     private static void putHelp(){
-        StringBuilder appInfo = new StringBuilder();
-        String indent = "  ";
-
-        appInfo.append(APPNAME).append(' ').append(APPVER)
-               .append('\n');
-        appInfo.append(indent)
-               .append("License").append(" : ").append(APPLICENSE)
-               .append('\n');
-        appInfo.append(indent)
-               .append("http://mikutoga.sourceforge.jp/")
-               .append('\n');
-
-        ERROUT.println(appInfo.toString());
+        String msg =
+                MessageFormat.format(MSG_HELP,
+                APPNAME, APPVER, APPLICENSE, APPURL);
+        ERROUT.println(msg);
         ERROUT.println(OptSwitch.getConsoleHelp());
-
         return;
     }
 
     /**
      * ファイルサイズを0に切り詰める。
+     * <p>ファイルが存在しなければなにもしない。
+     * <p>通常ファイルでなければなにもしない。
      * @param file ファイル
      * @throws IOException 入出力エラー
      */
@@ -217,65 +231,68 @@ public final class Pmd2Xml {
         if( ! file.exists() ) return;
         if( ! file.isFile() ) return;
 
-        FileOutputStream foStream = new FileOutputStream(file);
-        FileChannel channnel = foStream.getChannel();
-        channnel.truncate(0);
+        if(file.length() <= 0L) return;
 
-        channnel.close();
-        foStream.close();
+        FileOutputStream foStream = new FileOutputStream(file);
+        try{
+            FileChannel channnel = foStream.getChannel();
+            try{
+                channnel.truncate(0L);
+            }finally{
+                channnel.close();
+            }
+        }finally{
+            foStream.close();
+        }
 
         return;
     }
 
     /**
-     * 入力ストリームを準備する。
-     * @param fileName 入力ファイル名
-     * @return 入力ストリーム
+     * 入力ソースを準備する。
+     * <p>入力ファイルが通常ファイルとして存在しなければエラー終了。
+     * @param optInfo オプション情報
+     * @return 入力ソース
      */
-    private static InputStream openInfile(String fileName){
+    private static InputSource openInfile(OptInfo optInfo){
+        String fileName = optInfo.getInFilename();
         File inFile = new File(fileName);
 
         if( (! inFile.exists()) || (! inFile.isFile()) ){
             String absPath = inFile.getAbsolutePath();
-            errMsg("Can't find input file:" + absPath);
-            exit(EXIT_FILE);
+            String msg = MessageFormat.format(MSG_NOINFILE, absPath);
+            errMsg(msg);
+            exit(EXIT_IOERR);
         }
 
-        InputStream is = null;
-        try{
-            is = new FileInputStream(inFile);
-        }catch(FileNotFoundException e){
-            ioError(e);
-            assert false;
-        }
-
-        is = new BufferedInputStream(is);
+        InputSource source = XmlInputUtil.fileToSource(inFile);
 
-        return is;
+        return source;
     }
 
     /**
      * 出力ストリームを準備する。
-     * @param fileName 出力ファイル名
-     * @param overWrite 頭から上書きして良ければtrue
+     * <p>出力ファイルが通常ファイルでない場合はエラー終了。
+     * <p>既存の出力ファイルに上書き指示が伴っていなければエラー終了。
+     * @param optInfo オプション情報
      * @return 出力ストリーム
      */
-    private static OutputStream openOutfile(String fileName,
-                                            boolean overWrite) {
-        File outFile = new File(fileName);
+    private static OutputStream openOutfile(OptInfo optInfo){
+        String outputFile = optInfo.getOutFilename();
+        boolean overwrite = optInfo.overwriteMode();
+
+        File outFile = new File(outputFile);
 
         if(outFile.exists()){
             String absPath = outFile.getAbsolutePath();
             if( ! outFile.isFile() ){
-                String msg = absPath + " is not file.";
+                String msg = MessageFormat.format(MSG_ABNFILE, absPath);
                 errMsg(msg);
-                exit(EXIT_FILE);
-            }else if( ! overWrite ){
-                String msg =
-                          absPath + " already exists.\n"
-                        + "If you want to overwrite, use -f.";
+                exit(EXIT_IOERR);
+            }else if( ! overwrite ){
+                String msg = MessageFormat.format(MSG_OWOUTFILE, absPath);
                 errMsg(msg);
-                exit(EXIT_FILE);
+                exit(EXIT_IOERR);
             }
         }
 
@@ -285,12 +302,13 @@ public final class Pmd2Xml {
             ioError(e);
         }
 
-        OutputStream os = null;
+        OutputStream os;
         try{
             os = new FileOutputStream(outFile);
         }catch(FileNotFoundException e){
             ioError(e);
             assert false;
+            throw new AssertionError(e);
         }
 
         os = new BufferedOutputStream(os);
@@ -299,44 +317,34 @@ public final class Pmd2Xml {
     }
 
     /**
-     * Mainエントリ。
-     * @param args コマンドパラメータ
+     * オプション情報に従いコンバータを生成する。
+     * @param optInfo オプション情報
+     * @return コンバータ
      */
-    public static void main(String[] args){
-        checkJRE();
-
+    private static Pmd2XmlConv buildConverter(OptInfo optInfo){
         Pmd2XmlConv converter = new Pmd2XmlConv();
 
-        OptInfo optInfo;
-        try{
-            optInfo = OptInfo.parseOption(args);
-        }catch(CmdLineException e){
-            String optErrMsg = e.getLocalizedMessage();
-            errMsg(optErrMsg);
-            exit(EXIT_OPT);
-            return;
-        }
-
-        if(optInfo.needHelp()){
-            putHelp();
-            exit(EXIT_OK);
-        }
-
-        String inputFile = optInfo.getInFilename();
-        String outputFile = optInfo.getOutFilename();
-        boolean overwrite = optInfo.overwriteMode();
-
-        InputStream  is = openInfile(inputFile);
-        OutputStream os = openOutfile(outputFile, overwrite);
-
-        converter.setInType(optInfo.getInFileType());
+        converter.setInType (optInfo.getInFileType());
         converter.setOutType(optInfo.getOutFileType());
 
         converter.setNewline(optInfo.getNewline());
         converter.setGenerator(optInfo.getGenerator());
 
+        return converter;
+    }
+
+    /**
+     * 実際のコンバート作業と異常系処理を行う。
+     * <p>異常系が起きた場合、このメソッドは制御を戻さない。
+     * @param converter コンバータ
+     * @param source 入力ソース
+     * @param ostream 出力ストリーム
+     */
+    private static void doConvert(Pmd2XmlConv converter,
+                                   InputSource source,
+                                   OutputStream ostream ){
         try{
-            converter.convert(is, os);
+            converter.convert(source, ostream);
         }catch(IOException e){
             ioError(e);
         }catch(IllegalPmdDataException e){
@@ -349,13 +357,53 @@ public final class Pmd2Xml {
             xmlError(e);
         }
 
+        return;
+    }
+
+    /**
+     * コマンドライン文字列をオプション情報としてパースする。
+     * <p>異常系が起きた場合、このメソッドは制御を戻さない。
+     * @param args コマンドライン文字列群
+     * @return オプション情報
+     */
+    private static OptInfo parseOption(String[] args){
+        OptInfo optInfo;
+
         try{
-            is.close();
-            try{
-                os.close();
-            }catch(IOException e){
-                ioError(e);
-            }
+            optInfo = OptInfo.parseOption(args);
+        }catch(CmdLineException e){
+            String optErrMsg = e.getLocalizedMessage();
+            errMsg(optErrMsg);
+            exit(EXIT_OPTERR);
+
+            assert false;
+            throw new AssertionError(e);
+        }
+
+        return optInfo;
+    }
+
+    /**
+     * Mainエントリ。
+     * @param args コマンドパラメータ
+     */
+    public static void main(String[] args){
+        checkJRE();
+
+        OptInfo optInfo = parseOption(args);
+        if(optInfo.needHelp()){
+            putHelp();
+            exit(EXIT_OK);
+        }
+
+        Pmd2XmlConv converter = buildConverter(optInfo);
+        InputSource source = openInfile(optInfo);
+        OutputStream ostream = openOutfile(optInfo);
+
+        doConvert(converter, source, ostream);
+
+        try{
+            ostream.close();
         }catch(IOException e){
             ioError(e);
         }