OSDN Git Service

パッケージ移動
[mikutoga/Pmd2XML.git] / src / main / java / jp / sfjp / mikutoga / pmd2xml / Pmd2Xml.java
1 /*
2  * pmd 2 xml converter main entry
3  *
4  * License : The MIT License
5  * Copyright(c) 2010 MikuToga Partners
6  */
7
8 package jp.sfjp.mikutoga.pmd2xml;
9
10 import java.io.BufferedInputStream;
11 import java.io.BufferedOutputStream;
12 import java.io.File;
13 import java.io.FileInputStream;
14 import java.io.FileNotFoundException;
15 import java.io.FileOutputStream;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
19 import java.io.PrintStream;
20 import java.nio.channels.FileChannel;
21 import java.util.Properties;
22 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
23 import jp.sfjp.mikutoga.pmd.IllegalPmdDataException;
24 import jp.sourceforge.mikutoga.xml.TogaXmlException;
25 import org.xml.sax.SAXException;
26
27 /**
28  * PMDモデルファイルとXMLとの間で変換を行うアプリケーション。
29  */
30 public final class Pmd2Xml {
31
32     /** 正常系。 */
33     public static final int EXIT_OK     = 0;
34     /** ファイル入出力に起因するエラー。 */
35     public static final int EXIT_FILE   = 1;
36     /** XMLフォーマットに起因するエラー。 */
37     public static final int EXIT_XML    = 2;
38     /** PMDフォーマットに起因するエラー。 */
39     public static final int EXIT_PMD    = 3;
40     /** 実行環境に起因するエラー。 */
41     public static final int EXIT_JREVER = 4;
42     /** オプション指定に起因するエラー。 */
43     public static final int EXIT_OPT    = 5;
44     /** 内部エラー。 */
45     public static final int EXIT_INTERN = 6;
46
47     /** アプリ名。 */
48     public static final String APPNAME;
49     /** バージョン識別子。 */
50     public static final String APPVER;
51     /** ライセンス種別。 */
52     public static final String APPLICENSE;
53
54     private static final Class<?> THISCLASS;
55
56     private static final PrintStream ERROUT = System.err;
57
58     static{
59         THISCLASS = Pmd2Xml.class;
60         InputStream ver =
61                 THISCLASS.getResourceAsStream("resources/version.properties");
62         Properties verProps = new Properties();
63         try{
64             try{
65                 verProps.load(ver);
66             }finally{
67                 ver.close();
68             }
69         }catch(IOException e){
70             throw new ExceptionInInitializerError(e);
71         }
72
73         APPNAME    = verProps.getProperty("app.name");
74         APPVER     = verProps.getProperty("app.version");
75         APPLICENSE = verProps.getProperty("app.license");
76
77         new Pmd2Xml().hashCode();
78     }
79
80
81     /**
82      * ダミーコンストラクタ。
83      */
84     private Pmd2Xml(){
85         super();
86         assert this.getClass().equals(THISCLASS);
87         return;
88     }
89
90
91     /**
92      * VMを終了させる。
93      * @param code 終了コード
94      */
95     private static void exit(int code){
96         System.exit(code);
97         return;
98     }
99
100     /**
101      * 標準エラー出力へ例外情報出力。
102      * @param ex 例外
103      * @param dumpStack スタックトレースを出力するならtrue
104      */
105     private static void errPrintln(Throwable ex, boolean dumpStack){
106         String text = ex.toString();
107         ERROUT.println(text);
108
109         if(dumpStack){
110             ex.printStackTrace(ERROUT);
111         }
112
113         return;
114     }
115
116     /**
117      * 標準エラー出力へ例外情報出力。
118      * @param ex 例外
119      */
120     private static void errPrintln(Throwable ex){
121         errPrintln(ex, false);
122         return;
123     }
124
125     /**
126      * 共通エラーメッセージを出力する。
127      * @param text 個別メッセージ
128      */
129     private static void errMsg(String text){
130         ERROUT.println("ERROR:");
131         ERROUT.println(text);
132         ERROUT.println("(-h for help)");
133         return;
134     }
135
136     /**
137      * 入出力エラー処理。
138      * 例外を出力してVM終了する。
139      * @param ex 例外
140      */
141     private static void ioError(Throwable ex){
142         errPrintln(ex);
143         exit(EXIT_FILE);
144     }
145
146     /**
147      * XML構文エラー処理。
148      * 例外を出力してVM終了する。
149      * @param ex 例外
150      */
151     private static void xmlError(Throwable ex){
152         errPrintln(ex);
153         exit(EXIT_XML);
154     }
155
156     /**
157      * PMDファイルフォーマットエラー処理。
158      * 例外を出力してVM終了する。
159      * @param ex 例外
160      */
161     private static void pmdError(Throwable ex){
162         errPrintln(ex, true);
163         exit(EXIT_PMD);
164     }
165
166     /**
167      * 内部エラー処理。
168      * 例外を出力してVM終了する。
169      * @param ex 例外
170      */
171     private static void internalError(Throwable ex){
172         errPrintln(ex, true);
173         exit(EXIT_INTERN);
174     }
175
176     /**
177      * JREのバージョン判定を行う。
178      * 不適切ならVMごと終了。
179      */
180     private static void checkJRE(){
181         Package jrePackage = java.lang.Object.class.getPackage();
182         if( ! jrePackage.isCompatibleWith("1.6")){
183             ERROUT.println("You need JRE 1.6 or later.");
184             exit(EXIT_JREVER);
185         }
186         return;
187     }
188
189     /**
190      * ヘルプメッセージを出力してVMを終了させる。
191      */
192     private static void putHelp(){
193         StringBuilder appInfo = new StringBuilder();
194         String indent = "  ";
195
196         appInfo.append(APPNAME).append(' ').append(APPVER)
197                .append('\n');
198         appInfo.append(indent)
199                .append("License").append(" : ").append(APPLICENSE)
200                .append('\n');
201         appInfo.append(indent)
202                .append("http://mikutoga.sourceforge.jp/")
203                .append('\n');
204
205         ERROUT.println(appInfo.toString());
206         ERROUT.println(OptSwitch.getConsoleHelp());
207
208         return;
209     }
210
211     /**
212      * ファイルサイズを0に切り詰める。
213      * @param file ファイル
214      * @throws IOException 入出力エラー
215      */
216     private static void trunc(File file) throws IOException{
217         if( ! file.exists() ) return;
218         if( ! file.isFile() ) return;
219
220         if(file.length() <= 0L) return;
221
222         FileOutputStream foStream = new FileOutputStream(file);
223         try{
224             FileChannel channnel = foStream.getChannel();
225             try{
226                 channnel.truncate(0L);
227             }finally{
228                 channnel.close();
229             }
230         }finally{
231             foStream.close();
232         }
233
234         return;
235     }
236
237     /**
238      * 入力ストリームを準備する。
239      * @param fileName 入力ファイル名
240      * @return 入力ストリーム
241      */
242     private static InputStream openInfile(String fileName){
243         File inFile = new File(fileName);
244
245         if( (! inFile.exists()) || (! inFile.isFile()) ){
246             String absPath = inFile.getAbsolutePath();
247             errMsg("Can't find input file:" + absPath);
248             exit(EXIT_FILE);
249         }
250
251         InputStream is = null;
252         try{
253             is = new FileInputStream(inFile);
254         }catch(FileNotFoundException e){
255             ioError(e);
256             assert false;
257         }
258
259         is = new BufferedInputStream(is);
260
261         return is;
262     }
263
264     /**
265      * 出力ストリームを準備する。
266      * @param fileName 出力ファイル名
267      * @param overWrite 頭から上書きして良ければtrue
268      * @return 出力ストリーム
269      */
270     private static OutputStream openOutfile(String fileName,
271                                             boolean overWrite) {
272         File outFile = new File(fileName);
273
274         if(outFile.exists()){
275             String absPath = outFile.getAbsolutePath();
276             if( ! outFile.isFile() ){
277                 String msg = absPath + " is not file.";
278                 errMsg(msg);
279                 exit(EXIT_FILE);
280             }else if( ! overWrite ){
281                 String msg =
282                           absPath + " already exists.\n"
283                         + "If you want to overwrite, use -f.";
284                 errMsg(msg);
285                 exit(EXIT_FILE);
286             }
287         }
288
289         try{
290             trunc(outFile);
291         }catch(IOException e){
292             ioError(e);
293         }
294
295         OutputStream os = null;
296         try{
297             os = new FileOutputStream(outFile);
298         }catch(FileNotFoundException e){
299             ioError(e);
300             assert false;
301         }
302
303         os = new BufferedOutputStream(os);
304
305         return os;
306     }
307
308     /**
309      * Mainエントリ。
310      * @param args コマンドパラメータ
311      */
312     public static void main(String[] args){
313         checkJRE();
314
315         Pmd2XmlConv converter = new Pmd2XmlConv();
316
317         OptInfo optInfo;
318         try{
319             optInfo = OptInfo.parseOption(args);
320         }catch(CmdLineException e){
321             String optErrMsg = e.getLocalizedMessage();
322             errMsg(optErrMsg);
323             exit(EXIT_OPT);
324             return;
325         }
326
327         if(optInfo.needHelp()){
328             putHelp();
329             exit(EXIT_OK);
330         }
331
332         String inputFile = optInfo.getInFilename();
333         String outputFile = optInfo.getOutFilename();
334         boolean overwrite = optInfo.overwriteMode();
335
336         InputStream  is = openInfile(inputFile);
337         OutputStream os = openOutfile(outputFile, overwrite);
338
339         converter.setInType(optInfo.getInFileType());
340         converter.setOutType(optInfo.getOutFileType());
341
342         converter.setNewline(optInfo.getNewline());
343         converter.setGenerator(optInfo.getGenerator());
344
345         try{
346             converter.convert(is, os);
347         }catch(IOException e){
348             ioError(e);
349         }catch(IllegalPmdDataException e){
350             internalError(e);
351         }catch(MmdFormatException e){
352             pmdError(e);
353         }catch(TogaXmlException e){
354             xmlError(e);
355         }catch(SAXException e){
356             xmlError(e);
357         }
358
359         try{
360             is.close();
361             try{
362                 os.close();
363             }catch(IOException e){
364                 ioError(e);
365             }
366         }catch(IOException e){
367             ioError(e);
368         }
369
370         exit(EXIT_OK);
371
372         return;
373     }
374
375 }