OSDN Git Service

130128版スキーマ対応
[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.sourceforge.mikutoga.parser.MmdFormatException;
23 import jp.sourceforge.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         FileOutputStream foStream = new FileOutputStream(file);
221         FileChannel channnel = foStream.getChannel();
222         channnel.truncate(0);
223
224         channnel.close();
225         foStream.close();
226
227         return;
228     }
229
230     /**
231      * 入力ストリームを準備する。
232      * @param fileName 入力ファイル名
233      * @return 入力ストリーム
234      */
235     private static InputStream openInfile(String fileName){
236         File inFile = new File(fileName);
237
238         if( (! inFile.exists()) || (! inFile.isFile()) ){
239             String absPath = inFile.getAbsolutePath();
240             errMsg("Can't find input file:" + absPath);
241             exit(EXIT_FILE);
242         }
243
244         InputStream is = null;
245         try{
246             is = new FileInputStream(inFile);
247         }catch(FileNotFoundException e){
248             ioError(e);
249             assert false;
250         }
251
252         is = new BufferedInputStream(is);
253
254         return is;
255     }
256
257     /**
258      * 出力ストリームを準備する。
259      * @param fileName 出力ファイル名
260      * @param overWrite 頭から上書きして良ければtrue
261      * @return 出力ストリーム
262      */
263     private static OutputStream openOutfile(String fileName,
264                                             boolean overWrite) {
265         File outFile = new File(fileName);
266
267         if(outFile.exists()){
268             String absPath = outFile.getAbsolutePath();
269             if( ! outFile.isFile() ){
270                 String msg = absPath + " is not file.";
271                 errMsg(msg);
272                 exit(EXIT_FILE);
273             }else if( ! overWrite ){
274                 String msg =
275                           absPath + " already exists.\n"
276                         + "If you want to overwrite, use -f.";
277                 errMsg(msg);
278                 exit(EXIT_FILE);
279             }
280         }
281
282         try{
283             trunc(outFile);
284         }catch(IOException e){
285             ioError(e);
286         }
287
288         OutputStream os = null;
289         try{
290             os = new FileOutputStream(outFile);
291         }catch(FileNotFoundException e){
292             ioError(e);
293             assert false;
294         }
295
296         os = new BufferedOutputStream(os);
297
298         return os;
299     }
300
301     /**
302      * Mainエントリ。
303      * @param args コマンドパラメータ
304      */
305     public static void main(String[] args){
306         checkJRE();
307
308         Pmd2XmlConv converter = new Pmd2XmlConv();
309
310         OptInfo optInfo;
311         try{
312             optInfo = OptInfo.parseOption(args);
313         }catch(CmdLineException e){
314             String optErrMsg = e.getLocalizedMessage();
315             errMsg(optErrMsg);
316             exit(EXIT_OPT);
317             return;
318         }
319
320         if(optInfo.needHelp()){
321             putHelp();
322             exit(EXIT_OK);
323         }
324
325         String inputFile = optInfo.getInFilename();
326         String outputFile = optInfo.getOutFilename();
327         boolean overwrite = optInfo.overwriteMode();
328
329         InputStream  is = openInfile(inputFile);
330         OutputStream os = openOutfile(outputFile, overwrite);
331
332         converter.setInType(optInfo.getInFileType());
333         converter.setOutType(optInfo.getOutFileType());
334
335         converter.setNewline(optInfo.getNewline());
336         converter.setGenerator(optInfo.getGenerator());
337
338         try{
339             converter.convert(is, os);
340         }catch(IOException e){
341             ioError(e);
342         }catch(IllegalPmdDataException e){
343             internalError(e);
344         }catch(MmdFormatException e){
345             pmdError(e);
346         }catch(TogaXmlException e){
347             xmlError(e);
348         }catch(SAXException e){
349             xmlError(e);
350         }
351
352         try{
353             is.close();
354             try{
355                 os.close();
356             }catch(IOException e){
357                 ioError(e);
358             }
359         }catch(IOException e){
360             ioError(e);
361         }
362
363         exit(EXIT_OK);
364
365         return;
366     }
367
368 }