Instance: use getInstance()
[nikiroo-utils.git] / src / be / nikiroo / fanfix / supported / Epub.java
CommitLineData
08fe2e33
NR
1package be.nikiroo.fanfix.supported;
2
08fe2e33 3import java.io.File;
08fe2e33
NR
4import java.io.IOException;
5import java.io.InputStream;
7445f856 6import java.net.URISyntaxException;
08fe2e33 7import java.net.URL;
778d8d85 8import java.net.URLDecoder;
68686a37 9import java.util.ArrayList;
08fe2e33
NR
10import java.util.zip.ZipEntry;
11import java.util.zip.ZipInputStream;
12
7445f856
NR
13import org.jsoup.nodes.Document;
14
08fe2e33 15import be.nikiroo.fanfix.Instance;
68686a37 16import be.nikiroo.fanfix.data.MetaData;
08fe2e33 17import be.nikiroo.utils.IOUtils;
16a81ef7 18import be.nikiroo.utils.Image;
b7afbe42 19import be.nikiroo.utils.StringUtils;
8d59ce07 20import be.nikiroo.utils.streams.MarkableFileInputStream;
08fe2e33
NR
21
22/**
23 * Support class for EPUB files created with this program (as we need some
24 * metadata available in those we create).
25 *
26 * @author niki
27 */
68686a37 28class Epub extends InfoText {
7445f856 29 private MetaData meta;
2aac79c7 30 private File tmpDir;
b7afbe42 31 private String desc;
08fe2e33 32
68686a37
NR
33 private URL fakeSource;
34 private InputStream fakeIn;
08fe2e33 35
7445f856 36 public File getSourceFileOriginal() {
298d405a 37 return super.getSourceFile();
08fe2e33
NR
38 }
39
40 @Override
7445f856
NR
41 protected File getSourceFile() {
42 try {
43 return new File(fakeSource.toURI());
44 } catch (URISyntaxException e) {
d66deb8d
NR
45 Instance.getInstance().getTraceHandler()
46 .error(new IOException("Cannot get the source file from the info-text URL", e));
08fe2e33
NR
47 }
48
49 return null;
50 }
51
52 @Override
7445f856 53 protected InputStream getInput() {
298d405a
NR
54 if (fakeIn != null) {
55 try {
56 fakeIn.reset();
57 } catch (IOException e) {
d66deb8d 58 Instance.getInstance().getTraceHandler().error(new IOException("Cannot reset the Epub Text stream", e));
298d405a
NR
59 }
60
61 return fakeIn;
62 }
63
64 return null;
08fe2e33
NR
65 }
66
67 @Override
7445f856
NR
68 protected boolean supports(URL url) {
69 return url.getPath().toLowerCase().endsWith(".epub");
70 }
08fe2e33 71
7445f856
NR
72 @Override
73 protected MetaData getMeta() throws IOException {
74 return meta;
08fe2e33
NR
75 }
76
77 @Override
7445f856
NR
78 protected Document loadDocument(URL source) throws IOException {
79 super.loadDocument(source); // prepares super.getSourceFile() and
80 // super.getInput()
81
82 InputStream in = super.getInput();
83 ZipInputStream zipIn = null;
84 try {
85 zipIn = new ZipInputStream(in);
d66deb8d 86 tmpDir = Instance.getInstance().getTempFiles().createTempDir("fanfic-reader-parser");
7445f856
NR
87 File tmp = new File(tmpDir, "file.txt");
88 File tmpInfo = new File(tmpDir, "file.info");
89
90 fakeSource = tmp.toURI().toURL();
91 Image cover = null;
92
93 String url;
94 try {
95 url = getSource().toURI().toURL().toString();
96 } catch (URISyntaxException e1) {
97 url = getSource().toString();
98 }
99 String title = null;
100 String author = null;
101
102 for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn
103 .getNextEntry()) {
104 if (!entry.isDirectory()
105 && entry.getName().startsWith(getDataPrefix())) {
106 String entryLName = entry.getName().toLowerCase();
107
108 boolean imageEntry = false;
8d59ce07 109 for (String ext : bsImages.getImageExt(false)) {
7445f856
NR
110 if (entryLName.endsWith(ext)) {
111 imageEntry = true;
112 }
08fe2e33 113 }
08fe2e33 114
7445f856
NR
115 if (entry.getName().equals(getDataPrefix() + "version")) {
116 // Nothing to do for now ("first"
117 // version is 3.0)
118 } else if (entryLName.endsWith(".info")) {
119 // Info file
120 IOUtils.write(zipIn, tmpInfo);
121 } else if (imageEntry) {
122 // Cover
123 if (getCover()) {
124 try {
125 cover = new Image(zipIn);
126 } catch (Exception e) {
d66deb8d 127 Instance.getInstance().getTraceHandler().error(e);
7445f856 128 }
08fe2e33 129 }
7445f856
NR
130 } else if (entry.getName().equals(getDataPrefix() + "URL")) {
131 String[] descArray = StringUtils
132 .unhtml(IOUtils.readSmallStream(zipIn)).trim()
133 .split("\n");
134 if (descArray.length > 0) {
135 url = descArray[0].trim();
136 }
137 } else if (entry.getName().equals(
138 getDataPrefix() + "SUMMARY")) {
139 String[] descArray = StringUtils
140 .unhtml(IOUtils.readSmallStream(zipIn)).trim()
141 .split("\n");
142 int skip = 0;
143 if (descArray.length > 1) {
144 title = descArray[0].trim();
145 skip = 1;
146 if (descArray.length > 2
147 && descArray[1].startsWith("©")) {
148 author = descArray[1].substring(1).trim();
149 skip = 2;
150 }
151 }
152 this.desc = "";
153 for (int i = skip; i < descArray.length; i++) {
154 this.desc += descArray[i].trim() + "\n";
b7afbe42 155 }
b7afbe42 156
7445f856
NR
157 this.desc = this.desc.trim();
158 } else {
159 // Hopefully the data file
160 IOUtils.write(zipIn, tmp);
161 }
08fe2e33
NR
162 }
163 }
08fe2e33 164
7445f856
NR
165 if (requireInfo() && (!tmp.exists() || !tmpInfo.exists())) {
166 throw new IOException(
167 "file not supported (maybe not created with this program or corrupt)");
168 }
68686a37 169
7445f856 170 if (tmp.exists()) {
67837328 171 this.fakeIn = new MarkableFileInputStream(tmp);
68686a37 172 }
7445f856
NR
173
174 if (tmpInfo.exists()) {
175 meta = InfoReader.readMeta(tmpInfo, true);
7445f856
NR
176 tmpInfo.delete();
177 } else {
178 if (title == null || title.isEmpty()) {
179 title = getSourceFileOriginal().getName();
180 if (title.toLowerCase().endsWith(".cbz")) {
181 title = title.substring(0, title.length() - 4);
182 }
183 title = URLDecoder.decode(title, "UTF-8").trim();
778d8d85 184 }
778d8d85 185
7445f856
NR
186 meta = new MetaData();
187 meta.setLang("en");
188 meta.setTags(new ArrayList<String>());
727108fe 189 meta.setSource(getType().getSourceName());
7445f856
NR
190 meta.setUuid(url);
191 meta.setUrl(url);
192 meta.setTitle(title);
193 meta.setAuthor(author);
194 meta.setImageDocument(isImagesDocumentByDefault());
195 }
bb7021f2
NR
196
197 if (meta.getCover() == null) {
198 if (cover != null) {
199 meta.setCover(cover);
200 } else {
bb7021f2
NR
201 meta.setCover(InfoReader
202 .getCoverByName(getSourceFileOriginal().toURI()
203 .toURL()));
204 }
205 }
7445f856
NR
206 } finally {
207 if (zipIn != null) {
208 zipIn.close();
209 }
210 if (in != null) {
211 in.close();
212 }
08fe2e33 213 }
7445f856
NR
214
215 return null;
08fe2e33
NR
216 }
217
218 @Override
0ffa4754 219 protected void close() {
2aac79c7
NR
220 if (tmpDir != null) {
221 IOUtils.deltree(tmpDir);
08fe2e33
NR
222 }
223
2aac79c7 224 tmpDir = null;
dea63313 225
68686a37 226 super.close();
08fe2e33
NR
227 }
228
229 protected String getDataPrefix() {
230 return "DATA/";
231 }
232
233 protected boolean requireInfo() {
234 return true;
235 }
236
237 protected boolean getCover() {
238 return true;
239 }
e4fa48a0
NR
240
241 protected boolean isImagesDocumentByDefault() {
242 return false;
243 }
08fe2e33 244}