2 * vmd to xml converter main entry
4 * License : The MIT License
5 * Copyright(c) 2011 MikuToga Partners
8 package jp.sfjp.mikutoga.vmd2xml;
10 import java.io.BufferedOutputStream;
12 import java.io.FileNotFoundException;
13 import java.io.FileOutputStream;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.io.OutputStream;
17 import java.io.PrintStream;
18 import java.nio.channels.FileChannel;
19 import java.text.MessageFormat;
20 import java.util.Properties;
21 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
22 import jp.sfjp.mikutoga.vmd.IllegalVmdDataException;
23 import jp.sfjp.mikutoga.xml.TogaXmlException;
24 import org.xml.sax.InputSource;
25 import org.xml.sax.SAXException;
29 * VMDモーションファイルとXMLとの間で変換を行うアプリケーション。
31 public final class Vmd2Xml {
34 public static final int EXIT_OK = 0;
36 public static final int EXIT_INTERR = 1;
38 public static final int EXIT_ENVERR = 2;
39 /** オプション指定に起因するエラー。 */
40 public static final int EXIT_OPTERR = 3;
41 /** ファイル入出力に起因するエラー。 */
42 public static final int EXIT_IOERR = 4;
43 /** XMLフォーマットに起因するエラー。 */
44 public static final int EXIT_XMLERR = 5;
45 /** VMDフォーマットに起因するエラー。 */
46 public static final int EXIT_VMDERR = 7;
49 public static final String APPNAME;
51 public static final String APPVER;
53 public static final String APPLICENSE;
55 public static final String APPURL;
57 public static final String GENERATOR;
59 private static final Class<?> THISCLASS;
60 private static final String RES_VER = "resources/version.properties";
62 private static final PrintStream ERROUT = System.err;
63 private static final String MSG_ERR = "ERROR:\n{0}\n(-h for help)";
64 private static final String MSG_HELP =
66 + "\u0020\u0020License\u0020:\u0020{2}\n"
67 + "\u0020\u0020{3}\n";
68 private static final String MSG_NOINFILE = "Can''t find input file: {0}";
69 private static final String MSG_ABNFILE = "{0} is not file.";
70 private static final String MSG_OWOUTFILE =
71 "{0} already exists.\n"
72 + "If you want to overwrite, use -f.";
74 private static final String MSG_OLDJRE = "You need JRE {0} or later.";
75 private static final String REQUIRED_JRE = "1.8";
78 THISCLASS = Vmd2Xml.class;
79 InputStream ver = THISCLASS.getResourceAsStream(RES_VER);
80 Properties verProps = new Properties();
87 }catch(IOException e){
88 throw new ExceptionInInitializerError(e);
91 APPNAME = verProps.getProperty("app.name");
92 APPVER = verProps.getProperty("app.version");
93 APPLICENSE = verProps.getProperty("app.license");
94 APPURL = verProps.getProperty("app.url");
96 GENERATOR = APPNAME + ' ' + APPVER;
98 new Vmd2Xml().hashCode();
107 assert this.getClass().equals(THISCLASS);
115 * @see java.lang.System#exit(int)
117 private static void exit(int code){
120 throw new AssertionError();
125 * @param text 個別メッセージ
127 private static void errMsg(String text){
128 String msg = MessageFormat.format(MSG_ERR, text);
136 * @param dumpStack スタックトレースを出力するならtrue
138 private static void thPrintln(Throwable ex, boolean dumpStack){
140 ex.printStackTrace(ERROUT);
142 String text = ex.toString();
143 ERROUT.println(text);
153 private static void thPrintln(Throwable ex){
154 thPrintln(ex, false);
163 private static void ioError(IOException ex){
173 private static void xmlError(Throwable ex){
179 * VMDファイルフォーマットエラー処理。
183 private static void vmdError(MmdFormatException ex){
193 private static void internalError(Throwable ex){
202 private static void checkJRE(){
203 Package jrePackage = java.lang.Object.class.getPackage();
204 if( ! jrePackage.isCompatibleWith(REQUIRED_JRE)){
205 String msg = MessageFormat.format(MSG_OLDJRE, REQUIRED_JRE);
215 private static void putHelp(){
217 MessageFormat.format(MSG_HELP,
218 APPNAME, APPVER, APPLICENSE, APPURL);
220 ERROUT.println(OptSwitch.getConsoleHelp());
226 * <p>ファイルが存在しなければなにもしない。
227 * <p>通常ファイルでなければなにもしない。
229 * @throws IOException 入出力エラー
231 private static void trunc(File file) throws IOException{
232 if( ! file.exists() ) return;
233 if( ! file.isFile() ) return;
235 if(file.length() <= 0L) return;
237 FileOutputStream foStream = new FileOutputStream(file);
239 FileChannel channnel = foStream.getChannel();
241 channnel.truncate(0L);
254 * <p>入力ファイルが通常ファイルとして存在しなければエラー終了。
255 * @param optInfo オプション情報
258 private static InputSource openInfile(OptInfo optInfo){
259 String fileName = optInfo.getInFilename();
260 File inFile = new File(fileName);
262 if( (! inFile.exists()) || (! inFile.isFile()) ){
263 String absPath = inFile.getAbsolutePath();
264 String msg = MessageFormat.format(MSG_NOINFILE, absPath);
269 InputSource source = XmlInputUtil.fileToSource(inFile);
276 * <p>出力ファイルが通常ファイルでない場合はエラー終了。
277 * <p>既存の出力ファイルに上書き指示が伴っていなければエラー終了。
278 * @param optInfo オプション情報
281 private static OutputStream openOutfile(OptInfo optInfo) {
282 String outputFile = optInfo.getOutFilename();
283 boolean overwrite = optInfo.overwriteMode();
285 File outFile = new File(outputFile);
287 if(outFile.exists()){
288 String absPath = outFile.getAbsolutePath();
289 if( ! outFile.isFile() ){
290 String msg = MessageFormat.format(MSG_ABNFILE, absPath);
293 }else if( ! overwrite ){
294 String msg = MessageFormat.format(MSG_OWOUTFILE, absPath);
302 }catch(IOException e){
308 os = new FileOutputStream(outFile);
309 }catch(FileNotFoundException e){
312 throw new AssertionError(e);
315 os = new BufferedOutputStream(os);
321 * オプション情報に従いコンバータを生成する。
322 * @param optInfo オプション情報
325 private static Vmd2XmlConv buildConverter(OptInfo optInfo){
326 Vmd2XmlConv converter = new Vmd2XmlConv();
328 converter.setInType (optInfo.getInFileType());
329 converter.setOutType(optInfo.getOutFileType());
331 converter.setNewline(optInfo.getNewline());
332 converter.setGenerator(optInfo.getGenerator());
333 converter.setQuaterniomMode(optInfo.isQuaterniomMode());
339 * 実際のコンバート作業と異常系処理を行う。
340 * <p>異常系が起きた場合、このメソッドは制御を戻さない。
341 * @param converter コンバータ
342 * @param source 入力ソース
343 * @param ostream 出力ストリーム
345 private static void doConvert(Vmd2XmlConv converter,
347 OutputStream ostream ){
349 converter.convert(source, ostream);
350 }catch(IOException e){
352 }catch(IllegalVmdDataException e){
354 }catch(MmdFormatException e){
356 }catch(TogaXmlException e){
358 }catch(SAXException e){
366 * コマンドライン文字列をオプション情報としてパースする。
367 * <p>異常系が起きた場合、このメソッドは制御を戻さない。
368 * @param args コマンドライン文字列群
371 private static OptInfo parseOption(String[] args){
375 optInfo = OptInfo.parseOption(args);
376 }catch(CmdLineException e){
377 String optErrMsg = e.getLocalizedMessage();
382 throw new AssertionError(e);
390 * @param args コマンドパラメータ
392 public static void main(String[] args){
395 OptInfo optInfo = parseOption(args);
396 if(optInfo.needHelp()){
401 Vmd2XmlConv converter = buildConverter(optInfo);
402 InputSource source = openInfile(optInfo);
403 OutputStream ostream = openOutfile(optInfo);
405 doConvert(converter, source, ostream);
409 }catch(IOException e){