OSDN Git Service

572be515b4ca3ed242175f248028186a2e08aee5
[charactermanaj/CharacterManaJ.git] / src / charactermanaj / model / io / CharacterDataZipFileWriter.java
1 package charactermanaj.model.io;\r
2 \r
3 import java.io.File;\r
4 import java.io.IOException;\r
5 import java.io.OutputStream;\r
6 import java.io.UnsupportedEncodingException;\r
7 import java.nio.charset.Charset;\r
8 import java.nio.charset.CharsetEncoder;\r
9 import java.nio.charset.CodingErrorAction;\r
10 \r
11 import org.apache.tools.zip.ZipEntry;\r
12 import org.apache.tools.zip.ZipOutputStream;\r
13 \r
14 import charactermanaj.model.AppConfig;\r
15 \r
16 \r
17 public class CharacterDataZipFileWriter extends AbstractCharacterDataArchivedFileWriter {\r
18 \r
19         /**\r
20          * Zipストリーム\r
21          */\r
22         protected ZipOutputStream zipOutStm;\r
23         \r
24         /**\r
25          * ファイル名のエンコーディング\r
26          */\r
27         protected CharsetEncoder enc;\r
28         \r
29         /**\r
30          * ルートコンテンツへのプレフィックス\r
31          */\r
32         protected String rootPrefix = "";\r
33 \r
34 \r
35         public CharacterDataZipFileWriter(File outFile) throws IOException {\r
36                 super(outFile);\r
37 \r
38                 AppConfig appConfig = AppConfig.getInstance();\r
39                 String zipNameEncoding = appConfig.getZipNameEncoding();\r
40                 \r
41                 // コンストラクタにストリームではなくファイル名を指定することで、\r
42                 // 内部でランダムアクセスファイルを使うようになるためヘッダのCRCチェックの書き込み等で有利\r
43                 this.zipOutStm = new ZipOutputStream(tmpFile);\r
44                 \r
45                 // ファイル名の文字コードを設定する.\r
46                 // (JDKの標準のZipOutputStreamはUTF-8になるが、一般的にはMS932が多いため、Apache Antのものを借用し指定する.)\r
47                 this.enc = Charset.forName(zipNameEncoding).newEncoder();\r
48                 zipOutStm.setEncoding(zipNameEncoding);\r
49                 enc.onUnmappableCharacter(CodingErrorAction.REPORT);\r
50 \r
51                 // zipの場合、根本に1つフォルダをたてておく.\r
52                 // 一般的なフォルダ圧縮したものと体裁をそろえるため.\r
53                 String fname = outFile.getName();\r
54                 int extpos = fname.lastIndexOf('.');\r
55                 if (extpos > 0) { // ドットで始まる名前の場合は無視\r
56                         fname = fname.substring(0, extpos);\r
57                 }\r
58                 setRootPrefix(fname);\r
59         }\r
60 \r
61         public void setRootPrefix(String rootPrefix) {\r
62                 if (rootPrefix == null || rootPrefix.trim().equals("/")) {\r
63                         rootPrefix = "";\r
64                 }\r
65                 if (rootPrefix.length() > 0 && !rootPrefix.endsWith("/")) {\r
66                         rootPrefix += "/";\r
67                 }\r
68                 this.rootPrefix = rootPrefix.trim();\r
69         }\r
70         \r
71         public String getRootPrefix() {\r
72                 return rootPrefix;\r
73         }\r
74 \r
75         @Override\r
76         protected void closeEntry() throws IOException {\r
77                 zipOutStm.closeEntry();\r
78         }\r
79         \r
80         @Override\r
81         protected OutputStream getOutputStream() throws IOException {\r
82                 return zipOutStm;\r
83         }\r
84         \r
85         @Override\r
86         protected void putNextEntry(String name, long lastModified)\r
87                         throws IOException {\r
88 \r
89                  // ルートプレフィックスをすべてのエントリの登録時に付与する.\r
90                 String fname = rootPrefix + name;\r
91                 \r
92                 // ファイル名がキャラクターセットに合致するか?\r
93                 checkName(fname);\r
94 \r
95                 // Zipエントリの登録\r
96                 ZipEntry entry = new ZipEntry(fname);\r
97                 if (lastModified > 0) {\r
98                         entry.setTime(lastModified);\r
99                 }\r
100                 zipOutStm.putNextEntry(entry);\r
101         }\r
102         \r
103         protected void internalClose() throws IOException {\r
104                 zipOutStm.close();\r
105         }\r
106         \r
107         /**\r
108          * ファイル名がエンコーディング可能であるかチェックする.<br>\r
109          * @param name チェックする名前\r
110          * @throws IOException ファイル名が不正である場合\r
111          * @throws UnsupportedEncodingException ファイル名がエンコーディングできない場合\r
112          */\r
113         protected void checkName(String name) throws UnsupportedEncodingException, IOException {\r
114                 if (name == null || name.length() == 0) {\r
115                         throw new IOException("missing entry name");\r
116                 }\r
117                 if (!enc.canEncode(name)) {\r
118                         throw new UnsupportedEncodingException("file name encoding error.: " + name);\r
119                 }\r
120         }\r
121 }\r