OSDN Git Service

改行コード指定
[jindolf/JinArchiver.git] / src / main / java / jp / sourceforge / jindolf / archiver / ZipUtils.java
1 /*
2  * ZIP utils
3  *
4  * License : The MIT License
5  * Copyright(c) 2008 olyutorskii
6  */
7
8 package jp.sourceforge.jindolf.archiver;
9
10 import java.io.File;
11 import java.io.IOException;
12 import java.io.InputStream;
13 import java.io.Writer;
14 import java.net.MalformedURLException;
15 import java.net.URI;
16 import java.net.URISyntaxException;
17 import java.net.URL;
18 import java.util.Enumeration;
19 import java.util.Iterator;
20 import java.util.LinkedList;
21 import java.util.List;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24 import java.util.zip.ZipEntry;
25 import java.util.zip.ZipFile;
26 import jp.sourceforge.jindolf.parser.DecodeException;
27 import jp.sourceforge.jindolf.parser.HtmlParseException;
28
29 /**
30  * ZIPアーカイブされた生XHTML情報へのアクセス諸々。
31  */
32 public final class ZipUtils{
33
34     /**
35      * 隠れコンストラクタ。
36      */
37     private ZipUtils(){
38         super();
39         return;
40     }
41
42
43     /**
44      * ZIPファイルに格納された村一覧を抽出する。
45      * 各日のロードはまだ行われない。
46      * @param zipFile ZIPファイル
47      * @return 村一覧
48      * @throws IOException 入力エラー
49      */
50     public static List<VillageData> getVillageDataList(ZipFile zipFile)
51             throws IOException{
52         List<VillageData> result = new LinkedList<VillageData>();
53
54         List<ZipEntry> logList = getDownloadLogList(zipFile);
55         for(ZipEntry entry : logList){
56             VillageData villageData =
57                 getVillageDataFromLogEntry(zipFile, entry);
58             result.add(villageData);
59         }
60
61         return result;
62     }
63
64     /**
65      * ZIPファイルからダウンロードログファイルの一覧を取得する。
66      * ダウンロードログファイルは必ず「download.log」の名前を持つ。
67      * @param file ZIPファイル
68      * @return ログファイル一覧
69      */
70     public static List<ZipEntry> getDownloadLogList(ZipFile file){
71         List<ZipEntry> result = new LinkedList<ZipEntry>();
72
73         Enumeration<? extends ZipEntry> list = file.entries();
74         while(list.hasMoreElements()){
75             ZipEntry entry = list.nextElement();
76             String name = entry.getName();
77             if(name.endsWith("/download.log" )){
78                 result.add(entry);
79             }
80         }
81
82         return result;
83     }
84
85     /**
86      * ログファイルを表すZIPエントリから村情報を抽出する。
87      * @param zipFile ZIPファイル
88      * @param logEntry ログファイルのZIPエントリ
89      * @return 村情報
90      * @throws IOException 入力エラー
91      */
92     public static VillageData getVillageDataFromLogEntry(
93             ZipFile zipFile, ZipEntry logEntry)
94             throws IOException{
95         InputStream istream = zipFile.getInputStream(logEntry);
96         List<PeriodResource> list =
97                 FileArchive.parseDownloadLog(istream);
98         istream.close();
99
100         String baseName = logEntry.getName().replaceAll("/[^/]+$", "/");
101         for(PeriodResource resource : list){
102             modifyResourceUrl(zipFile, baseName, resource);
103         }
104
105         VillageData villageData = new VillageData(list);
106         return villageData;
107     }
108
109     /**
110      * ログ記録に書かれたXHTMLファイル名を実際にアクセス可能なURLに修正する。
111      * @param zipFile ZIPファイル
112      * @param entryBase ファイル名のベース
113      * @param resource リソース情報
114      * @return 引数と同じ物
115      */
116     public static PeriodResource modifyResourceUrl(ZipFile zipFile,
117                                            String entryBase,
118                                            PeriodResource resource ){
119         String fileName;
120         try{
121             URL resUrl = resource.getResourceUrl();
122             URI resUri = resUrl.toURI();
123             File file = new File(resUri);
124             fileName = file.getName();
125         }catch(URISyntaxException e){
126             throw new IllegalArgumentException(e);
127         }
128
129         String zipUri = new File(zipFile.getName()).toURI().toString();
130
131         String urlText = "jar:" + zipUri + "!/" + entryBase + fileName;
132
133         URL zipResource;
134         try{
135             zipResource = new URL(urlText);
136         }catch(MalformedURLException e){
137             throw new IllegalArgumentException(e);
138         }
139
140         resource.setResourceUrl(zipResource);
141
142         return resource;
143     }
144
145     /**
146      * 村番号から村情報を得る。
147      * @param zipFile ZIPファイル
148      * @param vid 村番号
149      * @return 村情報
150      * @throws IOException 入力エラー
151      */
152     public static VillageData getVillageData(ZipFile zipFile, int vid)
153             throws IOException{
154         ZipEntry entry = getDownloadLogEntry(zipFile, vid);
155         VillageData result = getVillageDataFromLogEntry(zipFile, entry);
156         return result;
157     }
158
159     /**
160      * 村番号から該当するログファイルエントリを取得する。
161      * @param file ZIPファイル
162      * @param vid 村番号
163      * @return ログファイルのZIPエントリ。見つからなければnull。
164      */
165     public static ZipEntry getDownloadLogEntry(ZipFile file, int vid){
166         Pattern entryPattern =
167                 Pattern.compile("jin_[^_]+_([0-9]+)/download.log$");
168
169         Enumeration<? extends ZipEntry> list = file.entries();
170         while(list.hasMoreElements()){
171             ZipEntry entry = list.nextElement();
172             String name = entry.getName();
173             Matcher matcher = entryPattern.matcher(name);
174             if(matcher.find()){
175                 String vnum = matcher.group(1);
176                 if(vid == Integer.parseInt(vnum)) return entry;
177             }
178         }
179         return null;
180     }
181
182     /**
183      * ZIPファイル中の指定した村番号の村をXML出力する。
184      * @param zipFile ZIPファイル
185      * @param vid 村番号
186      * @param writer 出力先
187      * @throws IOException 入出力エラー
188      * @throws DecodeException デコードエラー
189      * @throws HtmlParseException パースエラー
190      */
191     public static void dumpZipVid(ZipFile zipFile, int vid, Writer writer)
192             throws IOException, DecodeException, HtmlParseException{
193         VillageData data = getVillageData(zipFile, vid);
194         Builder.fillVillageData(data);
195         XmlUtils.dumpVillageData(writer, data);
196
197         return;
198     }
199
200     /**
201      * ZIPファイル中の全村をXML出力する。
202      * @param zipFile ZIPファイル
203      * @throws IOException 入出力エラー
204      * @throws DecodeException デコードエラー
205      * @throws HtmlParseException パースエラー
206      */
207     public static void dumpZipAll(ZipFile zipFile)
208             throws IOException, DecodeException, HtmlParseException{
209         List<VillageData> villageDataList;
210         villageDataList = ZipUtils.getVillageDataList(zipFile);
211         Iterator<VillageData> it = villageDataList.iterator();
212         while(it.hasNext()){
213             VillageData villageData = it.next();
214             Builder.fillVillageData(villageData);
215             Writer writer = XmlUtils.createFileWriter(villageData);
216             XmlUtils.dumpVillageData(writer, villageData);
217             writer.close();
218             it.remove();
219         }
220
221         return;
222     }
223
224 }