4 * License : The MIT License
5 * Copyright(c) 2008 olyutorskii
8 package jp.sourceforge.jindolf.archiver;
10 import java.io.BufferedOutputStream;
11 import java.io.BufferedWriter;
13 import java.io.FileOutputStream;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.io.OutputStream;
17 import java.io.OutputStreamWriter;
18 import java.io.Writer;
19 import java.text.MessageFormat;
20 import java.util.List;
21 import java.util.Properties;
22 import jp.sourceforge.jindolf.corelib.LandDef;
23 import jp.sourceforge.jindolf.parser.DecodeException;
24 import jp.sourceforge.jindolf.parser.HtmlParseException;
29 public final class JinArchiver{
32 public static final String GENERATOR;
35 private static final Class<?> SELF_KLASS;
37 private static final Package SELF_PACKAGE;
39 private static final String TITLE;
41 private static final String VERSION;
44 private static final String RES_VERDEF = "resources/version.properties";
48 SELF_KLASS = JinArchiver.class;
49 SELF_PACKAGE = SELF_KLASS.getPackage();
51 Properties verProp = loadVersionDefinition(SELF_KLASS);
52 TITLE = getPackageInfo(verProp, "pkg-title.", "Unknown");
53 VERSION = getPackageInfo(verProp, "pkg-version.", "0");
54 GENERATOR = TITLE + " " + VERSION;
61 private JinArchiver(){
67 * リソース上のパッケージ定義プロパティをロードする。
68 * MANIFEST.MFが参照できない実行環境での代替品。
69 * @param klass パッケージを構成する任意のクラス
72 private static Properties loadVersionDefinition(Class<?> klass){
73 Properties result = new Properties();
75 InputStream istream = klass.getResourceAsStream(RES_VERDEF);
78 }catch(IOException e){
83 }catch(IOException e){
93 * このクラスのパッケージのパッケージ情報を取得する。
94 * MANIFEST.MFが参照できない実行環境での代替品。
97 * @param defValue 見つからなかった場合のデフォルト値
100 private static String getPackageInfo(Properties prop,
103 return getPackageInfo(prop, SELF_PACKAGE, prefix, defValue);
107 * リソース上のプロパティからパッケージ情報を取得する。
108 * MANIFEST.MFが参照できない実行環境での代替品。
110 * @param pkg 任意のパッケージ
112 * @param defValue デフォルト値
113 * @return 見つからなかった場合のパッケージ情報
115 private static String getPackageInfo(Properties prop,
119 String propName = prefix + pkg.getName();
120 String result = prop.getProperty(propName, defValue);
125 * System.err.println()のWrapper。
128 private static void errprintln(CharSequence text){
129 System.err.println(text);
135 * @param code プロセスコード。
137 private static void exit(int code){
146 private static void helpMessage(){
148 "\n" + GENERATOR + " 人狼BBS アーカイブ作成ツール\n\n"
149 +"-h, -help, -?\n\tヘルプメッセージ\n"
152 +"-outdir 出力ディレクトリ\n"
153 +"-stdout\n\t標準出力へ出力\n\n"
154 +"※ -outdir と -stdout は排他指定\n"
157 String landList = LandUtils.getLandList();
158 errprintln("利用可能な国識別子は " + landList + "\n");
165 * @param args オプション文字列
167 private static void parseOption(String[] args){
168 if(args.length <= 0){
174 LandDef landDef = null;
176 String outdir = null;
177 boolean stdout = false;
179 for(int pos = 0; pos < args.length; pos++){
180 String arg = args[pos];
182 if( ! arg.startsWith("-") ){
183 errprintln("不正なオプションです。 " + arg);
188 if(arg.equals("-h") || arg.equals("-help") || arg.equals("-?")){
194 if(arg.equals("-stdout")){
200 if(++pos >= args.length){
202 "オプション " + arg + " に引数がありません。");
207 String val = args[pos];
208 if(arg.equals("-land")){
209 landDef = LandUtils.getLandDef(val);
211 errprintln("不正な国識別子です。 " + val);
215 }else if(arg.equals("-vid")){
216 vid = Integer.parseInt(val);
218 errprintln("不正な村番号です。 " + vid);
222 }else if(arg.equals("-outdir")){
226 errprintln("不正なオプションです。 " + arg);
234 "-land オプションで国識別子を指定してください。");
241 "-vid オプションで村番号を指定してください。");
246 if( (outdir == null && stdout == false)
247 || (outdir != null && stdout == true) ){
249 "-outdir か -stdout のどちらか一方を指定してください。");
256 writer = getFileWriter(outdir, landDef, vid);
258 writer = getStdOutWriter();
261 writer = ValidateTask.wrapValidator(writer);
264 dump(writer, landDef, vid);
265 }catch(IOException e){
266 abortWithException(e);
267 }catch(DecodeException e){
268 abortWithException(e);
269 }catch(HtmlParseException e){
270 abortWithException(e);
280 private static void abortWithException(Exception e){
281 e.printStackTrace(System.err);
282 errprintln("処理を続行できません。");
288 * 主処理。人狼サーバからXHTMLを読み込み。XMLで出力。
292 * @throws IOException 入出力エラー
293 * @throws DecodeException デコードエラー
294 * @throws HtmlParseException パースエラー
296 public static void dump(Writer writer, LandDef landDef, int vid)
297 throws IOException, DecodeException, HtmlParseException{
298 List<PeriodResource> resourceList =
299 HttpAccess.loadResourceList(landDef, vid);
300 VillageData village = new VillageData(resourceList);
302 Builder.fillVillageData(village);
303 XmlUtils.dumpVillageData(writer, village);
312 public static Writer getStdOutWriter(){
313 OutputStream ostream;
314 ostream = new BufferedOutputStream(System.out);
317 writer = new OutputStreamWriter(ostream, "UTF-8");
318 writer = new BufferedWriter(writer, 4 * 1024);
319 }catch(IOException e){
330 * @param outdir 出力ディレクトリ
335 public static Writer getFileWriter(String outdir,
338 File outFile = new File(outdir);
339 if( ! outFile.exists() ){
341 outdir + " が存在しません。");
345 if( ! outFile.isDirectory() ){
347 outdir + " はディレクトリではありません。");
351 if( ! outFile.canWrite() ){
353 outdir + " に書き込めません。");
357 String fname = MessageFormat.format(
358 "jin_{0}_{1,number,#00000}.xml", landDef.getLandId(), vid);
359 File xmlFile = new File(outFile, fname);
362 created = xmlFile.createNewFile();
363 }catch(IOException e){
365 xmlFile.getName() + " が作成できません。");
371 fname + " が既に" + outdir + "に存在します。");
376 xmlFile.setReadable(true);
377 xmlFile.setWritable(true);
378 xmlFile.setExecutable(false, false);
382 OutputStream ostream;
383 ostream = new FileOutputStream(xmlFile);
384 ostream = new BufferedOutputStream(ostream, 4 * 1024);
385 writer = new OutputStreamWriter(ostream, "UTF-8");
386 writer = new BufferedWriter(writer, 4 * 1024);
387 }catch(IOException e){
389 xmlFile.getName() + " に書き込めません。");
401 public static void main(String[] args){