OSDN Git Service

09442dc933122a57df727ae9e72c72afca9c1de5
[jindolf/JinArchiver.git] / src / main / java / jp / sourceforge / jindolf / archiver / JinArchiver.java
1 /*
2  * main entry
3  *
4  * License : The MIT License
5  * Copyright(c) 2008 olyutorskii
6  */
7
8 package jp.sourceforge.jindolf.archiver;
9
10 import java.io.BufferedOutputStream;
11 import java.io.BufferedReader;
12 import java.io.BufferedWriter;
13 import java.io.File;
14 import java.io.FileOutputStream;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.io.OutputStream;
18 import java.io.OutputStreamWriter;
19 import java.io.Reader;
20 import java.io.Writer;
21 import java.text.MessageFormat;
22 import java.util.List;
23 import java.util.Properties;
24 import javax.xml.validation.Validator;
25 import jp.sourceforge.jindolf.corelib.LandDef;
26 import jp.sourceforge.jindolf.parser.DecodeException;
27 import jp.sourceforge.jindolf.parser.HtmlParseException;
28 import org.xml.sax.SAXException;
29
30 /**
31  * メインエントリ。
32  */
33 public final class JinArchiver{
34
35     /** Generator. */
36     public static final String GENERATOR;
37
38     /** このClass。 */
39     private static final Class<?> SELF_KLASS;
40     /** このPackage。 */
41     private static final Package  SELF_PACKAGE;
42     /** タイトル。 */
43     private static final String TITLE;
44     /** バージョン。 */
45     private static final String VERSION;
46
47     /** バージョン定義リソース。 */
48     private static final String RES_VERDEF = "resources/version.properties";
49
50
51     static{
52         SELF_KLASS   = JinArchiver.class;
53         SELF_PACKAGE = SELF_KLASS.getPackage();
54
55         Properties verProp = loadVersionDefinition(SELF_KLASS);
56         TITLE   = getPackageInfo(verProp, "pkg-title.",   "Unknown");
57         VERSION = getPackageInfo(verProp, "pkg-version.", "0");
58         GENERATOR = TITLE + " " + VERSION;
59     }
60
61
62     /**
63      * 隠しコンストラクタ。
64      */
65     private JinArchiver(){
66         assert false;
67         throw new AssertionError();
68     }
69
70
71     /**
72      * リソース上のパッケージ定義プロパティをロードする。
73      * MANIFEST.MFが参照できない実行環境での代替品。
74      * @param klass パッケージを構成する任意のクラス
75      * @return プロパティ
76      */
77     private static Properties loadVersionDefinition(Class<?> klass){
78         Properties result = new Properties();
79
80         InputStream istream = klass.getResourceAsStream(RES_VERDEF);
81
82         try{
83             try{
84                 result.load(istream);
85             }finally{
86                 istream.close();
87             }
88         }catch(IOException e){
89             // NOTHING
90         }
91
92         return result;
93     }
94
95     /**
96      * リソース上のプロパティから
97      * このクラスのパッケージのパッケージ情報を取得する。
98      * MANIFEST.MFが参照できない実行環境での代替品。
99      * @param prop プロパティ
100      * @param prefix 接頭辞
101      * @param defValue 見つからなかった場合のデフォルト値
102      * @return パッケージ情報
103      */
104     private static String getPackageInfo(Properties prop,
105                                           String prefix,
106                                           String defValue){
107         return getPackageInfo(prop, SELF_PACKAGE, prefix, defValue);
108     }
109
110     /**
111      * リソース上のプロパティからパッケージ情報を取得する。
112      * MANIFEST.MFが参照できない実行環境での代替品。
113      * @param prop プロパティ
114      * @param pkg 任意のパッケージ
115      * @param prefix 接頭辞
116      * @param defValue デフォルト値
117      * @return 見つからなかった場合のパッケージ情報
118      */
119     private static String getPackageInfo(Properties prop,
120                                           Package pkg,
121                                           String prefix,
122                                           String defValue){
123         String propName = prefix + pkg.getName();
124         String result = prop.getProperty(propName, defValue);
125         return result;
126     }
127
128     /**
129      * System.err.println()のWrapper。
130      * @param text 出力テキスト
131      */
132     private static void errprintln(CharSequence text){
133         System.err.println(text);
134         return;
135     }
136
137     /**
138      * プログラムの終了。
139      * @param code プロセスコード。
140      */
141     private static void exit(int code){
142         System.exit(code);
143         assert false;
144         return;
145     }
146
147     /**
148      * ヘルプメッセージ出力。
149      */
150     private static void helpMessage(){
151         String msg = OptArg.getHelpMessage(GENERATOR);
152         errprintln(msg);
153         return;
154     }
155
156     /**
157      * オプション文字列を解析する。
158      * @param optInfo オプション情報
159      */
160     private static void dumpOut(OptInfo optInfo){
161
162         String outdir   = optInfo.getOutdir();
163         LandDef landDef = optInfo.getLandDef();
164         int vid         = optInfo.getVid();
165
166         Writer writer;
167         if(outdir != null){
168             writer = getFileWriter(outdir, landDef, vid);
169         }else{
170             writer = getStdOutWriter();
171         }
172
173         SnifWriter snifWriter = new SnifWriter(writer);
174         Reader reader = snifWriter.getSnifReader();
175
176         writer = new BufferedWriter(snifWriter);
177         reader = new BufferedReader(reader);
178
179         Validator validator;
180         try{
181             validator = XmlUtils.createValidator();
182         }catch(SAXException e){
183             abortWithException(e, "処理を続行できません。");
184             return;
185         }
186
187         VillageData villageData;
188         try{
189             villageData = load(landDef, vid);
190         }catch(IOException e){
191             abortWithException(e);
192             return;
193         }catch(DecodeException e){
194             abortWithException(e);
195             return;
196         }catch(HtmlParseException e){
197             abortWithException(e);
198             return;
199         }
200
201         ValidateTask valTask = new ValidateTask(reader, validator);
202         DumpXmlTask dumpTask = new DumpXmlTask(villageData, writer);
203
204         ProdCons taskman = new ProdCons(dumpTask, valTask);
205         try{
206             taskman.submit();
207         }catch(InterruptedException e){
208             abortWithException(e);
209         }
210
211         if(taskman.hasError()){
212             Throwable cause = taskman.getCause();
213             String desc = taskman.getErrDescription();
214             abortWithException(cause, desc);
215             assert false;
216         }
217
218         return;
219     }
220
221     /**
222      * 例外によるアプリ終了。
223      * @param e 例外
224      */
225     private static void abortWithException(Throwable e){
226         abortWithException(e, "処理を続行できません。");
227         exit(1);
228         return;
229     }
230
231     /**
232      * 例外によるアプリ終了。
233      * @param e 例外
234      * @param desc 詳細テキスト
235      */
236     private static void abortWithException(Throwable e, String desc){
237         e.printStackTrace(System.err);
238         errprintln(desc);
239         exit(1);
240         return;
241     }
242
243     /**
244      * 主処理。人狼サーバからXHTMLを読み込み。XMLで出力。
245      * @param landDef 国情報
246      * @param vid 村番号
247      * @return 村情報
248      * @throws IOException 入出力エラー
249      * @throws DecodeException デコードエラー
250      * @throws HtmlParseException パースエラー
251      */
252     public static VillageData load(LandDef landDef, int vid)
253             throws IOException, DecodeException, HtmlParseException{
254         List<PeriodResource> resourceList =
255                 HttpAccess.loadResourceList(landDef, vid);
256         VillageData villageData = new VillageData(resourceList);
257
258         Builder.fillVillageData(villageData);
259
260         return villageData;
261     }
262
263     /**
264      * 標準出力への出力先を得る。
265      * @return 出力先
266      */
267     public static Writer getStdOutWriter(){
268         OutputStream ostream;
269         ostream = new BufferedOutputStream(System.out);
270         Writer writer;
271         try{
272             writer = new OutputStreamWriter(ostream, "UTF-8");
273             writer = new BufferedWriter(writer, 4 * 1024);
274         }catch(IOException e){
275             errprintln(
276                     "標準出力に書き込めません。");
277             exit(1);
278             return null;
279         }
280         return writer;
281     }
282
283     /**
284      * ローカルファイルへの出力先を得る。
285      * @param outdir 出力ディレクトリ
286      * @param landDef 国情報
287      * @param vid 村番号
288      * @return 出力先
289      */
290     public static Writer getFileWriter(String outdir,
291                                          LandDef landDef,
292                                          int vid ){
293         File outFile = new File(outdir);
294         if( ! outFile.exists() ){
295             errprintln(
296                     outdir + " が存在しません。");
297             exit(1);
298             return null;
299         }
300         if( ! outFile.isDirectory() ){
301             errprintln(
302                     outdir + " はディレクトリではありません。");
303             exit(1);
304             return null;
305         }
306         if( ! outFile.canWrite() ){
307             errprintln(
308                     outdir + " に書き込めません。");
309             exit(1);
310             return null;
311         }
312         String fname = MessageFormat.format(
313             "jin_{0}_{1,number,#00000}.xml", landDef.getLandId(), vid);
314         File xmlFile = new File(outFile, fname);
315         boolean created;
316         try{
317             created = xmlFile.createNewFile();
318         }catch(IOException e){
319             errprintln(
320                     xmlFile.getName() + " が作成できません。");
321             exit(1);
322             return null;
323         }
324         if( ! created ){
325             errprintln(
326                     fname + " が既に" + outdir + "に存在します。");
327             exit(1);
328             return null;
329         }
330         /* JRE 1.6 only
331         xmlFile.setReadable(true);
332         xmlFile.setWritable(true);
333         xmlFile.setExecutable(false, false);
334         */
335         Writer writer;
336         try{
337             OutputStream ostream;
338             ostream = new FileOutputStream(xmlFile);
339             ostream = new BufferedOutputStream(ostream, 4 * 1024);
340             writer = new OutputStreamWriter(ostream, "UTF-8");
341             writer = new BufferedWriter(writer, 4 * 1024);
342         }catch(IOException e){
343             errprintln(
344                     xmlFile.getName() + " に書き込めません。");
345             exit(1);
346             return null;
347         }
348
349         return writer;
350     }
351
352     /**
353      * スタートアップエントリ。
354      * @param args 引数
355      */
356     public static void main(String[] args){
357         OptInfo optInfo = OptInfo.parseOptInfo(args);
358
359         if(optInfo.isHelp()){
360             helpMessage();
361             exit(0);
362             assert false;
363             return;
364         }
365
366         if(optInfo.hasError()){
367             String errMsg = optInfo.getErrMsg();
368             errprintln(errMsg);
369             exit(1);
370             assert false;
371             return;
372         }
373
374         dumpOut(optInfo);
375
376         exit(0);
377         assert false;
378
379         return;
380     }
381
382 }