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.net.MalformedURLException;
21 import java.nio.channels.FileChannel;
22 import java.text.MessageFormat;
23 import java.util.Properties;
24 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
25 import jp.sfjp.mikutoga.vmd.IllegalVmdDataException;
26 import jp.sourceforge.mikutoga.xml.TogaXmlException;
27 import org.xml.sax.InputSource;
28 import org.xml.sax.SAXException;
32 * VMDモーションファイルとXMLとの間で変換を行うアプリケーション。
34 public final class Vmd2Xml {
37 public static final int EXIT_OK = 0;
39 public static final int EXIT_INTERR = 1;
41 public static final int EXIT_ENVERR = 2;
42 /** オプション指定に起因するエラー。 */
43 public static final int EXIT_OPTERR = 3;
44 /** ファイル入出力に起因するエラー。 */
45 public static final int EXIT_IOERR = 4;
46 /** XMLフォーマットに起因するエラー。 */
47 public static final int EXIT_XMLERR = 5;
48 /** VMDフォーマットに起因するエラー。 */
49 public static final int EXIT_VMDERR = 7;
52 public static final String APPNAME;
54 public static final String APPVER;
56 public static final String APPLICENSE;
58 public static final String APPURL;
60 public static final String GENERATOR;
62 private static final Class<?> THISCLASS;
63 private static final String RES_VER = "resources/version.properties";
65 private static final PrintStream ERROUT = System.err;
66 private static final String MSG_ERR = "ERROR:\n{0}\n(-h for help)";
67 private static final String MSG_HELP =
69 + "\u0020\u0020License\u0020:\u0020{2}\n"
70 + "\u0020\u0020{3}\n";
71 private static final String MSG_NOINFILE = "Can't find input file:{0}";
72 private static final String MSG_ABNFILE = "{0} is not file.";
73 private static final String MSG_OWOUTFILE =
74 "{0} already exists.\n"
75 + "If you want to overwrite, use -f.";
77 private static final String MSG_OLDJRE = "You need JRE {0} or later.";
78 private static final String REQUIRED_JRE = "1.6";
81 THISCLASS = Vmd2Xml.class;
82 InputStream ver = THISCLASS.getResourceAsStream(RES_VER);
83 Properties verProps = new Properties();
90 }catch(IOException e){
91 throw new ExceptionInInitializerError(e);
94 APPNAME = verProps.getProperty("app.name");
95 APPVER = verProps.getProperty("app.version");
96 APPLICENSE = verProps.getProperty("app.license");
97 APPURL = verProps.getProperty("app.url");
99 GENERATOR = APPNAME + ' ' + APPVER;
101 new Vmd2Xml().hashCode();
110 assert this.getClass().equals(THISCLASS);
118 * @see java.lang.System#exit(int)
120 private static void exit(int code){
123 throw new AssertionError();
128 * @param text 個別メッセージ
130 private static void errMsg(String text){
131 String msg = MessageFormat.format(MSG_ERR, text);
139 * @param dumpStack スタックトレースを出力するならtrue
141 private static void thPrintln(Throwable ex, boolean dumpStack){
143 ex.printStackTrace(ERROUT);
145 String text = ex.toString();
146 ERROUT.println(text);
156 private static void thPrintln(Throwable ex){
157 thPrintln(ex, false);
166 private static void ioError(IOException ex){
176 private static void xmlError(Throwable ex){
182 * VMDファイルフォーマットエラー処理。
186 private static void vmdError(MmdFormatException ex){
196 private static void internalError(Throwable ex){
205 private static void checkJRE(){
206 Package jrePackage = java.lang.Object.class.getPackage();
207 if( ! jrePackage.isCompatibleWith(REQUIRED_JRE)){
208 String msg = MessageFormat.format(MSG_OLDJRE, REQUIRED_JRE);
218 private static void putHelp(){
220 MessageFormat.format(MSG_HELP,
221 APPNAME, APPVER, APPLICENSE, APPURL);
223 ERROUT.println(OptSwitch.getConsoleHelp());
229 * <p>ファイルが存在しなければなにもしない。
230 * <p>通常ファイルでなければなにもしない。
232 * @throws IOException 入出力エラー
234 private static void trunc(File file) throws IOException{
235 if( ! file.exists() ) return;
236 if( ! file.isFile() ) return;
238 if(file.length() <= 0L) return;
240 FileOutputStream foStream = new FileOutputStream(file);
242 FileChannel channnel = foStream.getChannel();
244 channnel.truncate(0L);
257 * <p>入力ファイルが通常ファイルとして存在しなければエラー終了。
258 * @param optInfo オプション情報
261 private static InputSource openInfile(OptInfo optInfo){
262 String fileName = optInfo.getInFilename();
263 File inFile = new File(fileName);
265 if( (! inFile.exists()) || (! inFile.isFile()) ){
266 String absPath = inFile.getAbsolutePath();
267 String msg = MessageFormat.format(MSG_NOINFILE, absPath);
272 URI uri = inFile.toURI();
276 }catch(MalformedURLException e){
277 // File由来のURLでは起こりえない
279 throw new AssertionError(e);
281 String systemId = url.toString();
283 InputSource source = new InputSource(systemId);
290 * <p>出力ファイルが通常ファイルでない場合はエラー終了。
291 * <p>既存の出力ファイルに上書き指示が伴っていなければエラー終了。
292 * @param optInfo オプション情報
295 private static OutputStream openOutfile(OptInfo optInfo) {
296 String outputFile = optInfo.getOutFilename();
297 boolean overwrite = optInfo.overwriteMode();
299 File outFile = new File(outputFile);
301 if(outFile.exists()){
302 String absPath = outFile.getAbsolutePath();
303 if( ! outFile.isFile() ){
304 String msg = MessageFormat.format(MSG_ABNFILE, absPath);
307 }else if( ! overwrite ){
308 String msg = MessageFormat.format(MSG_OWOUTFILE, absPath);
316 }catch(IOException e){
322 os = new FileOutputStream(outFile);
323 }catch(FileNotFoundException e){
326 throw new AssertionError(e);
329 os = new BufferedOutputStream(os);
335 * オプション情報に従いコンバータを生成する。
336 * @param optInfo オプション情報
339 private static Vmd2XmlConv buildConverter(OptInfo optInfo){
340 Vmd2XmlConv converter = new Vmd2XmlConv();
342 converter.setInType (optInfo.getInFileType());
343 converter.setOutType(optInfo.getOutFileType());
345 converter.setNewline(optInfo.getNewline());
346 converter.setGenerator(optInfo.getGenerator());
347 converter.setQuaterniomMode(optInfo.isQuaterniomMode());
353 * 実際のコンバート作業と異常系処理を行う。
354 * <p>異常系が起きた場合、このメソッドは制御を戻さない。
355 * @param converter コンバータ
356 * @param source 入力ソース
357 * @param ostream 出力ストリーム
359 private static void doConvert(Vmd2XmlConv converter,
361 OutputStream ostream ){
363 converter.convert(source, ostream);
364 }catch(IOException e){
366 }catch(IllegalVmdDataException e){
368 }catch(MmdFormatException e){
370 }catch(TogaXmlException e){
372 }catch(SAXException e){
380 * コマンドライン文字列をオプション情報としてパースする。
381 * <p>異常系が起きた場合、このメソッドは制御を戻さない。
382 * @param args コマンドライン文字列群
385 private static OptInfo parseOption(String[] args){
389 optInfo = OptInfo.parseOption(args);
390 }catch(CmdLineException e){
391 String optErrMsg = e.getLocalizedMessage();
396 throw new AssertionError(e);
404 * @param args コマンドパラメータ
406 public static void main(String[] args){
409 OptInfo optInfo = parseOption(args);
410 if(optInfo.needHelp()){
415 Vmd2XmlConv converter = buildConverter(optInfo);
416 InputSource source = openInfile(optInfo);
417 OutputStream ostream = openOutfile(optInfo);
419 doConvert(converter, source, ostream);
423 }catch(IOException e){