1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.exorcist.core.zip;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.util.Enumeration;
21 import java.util.logging.Logger;
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
27 import net.sf.exorcist.api.ContentException;
28 import net.sf.exorcist.api.ContentExporter;
29 import net.sf.exorcist.api.ContentState;
30
31 /***
32 * Exporter plugin for the Exorcist content state file format.
33 * This plugin can be used to extract the content saved in an
34 * Exorcist content state file.
35 */
36 public class ZipExporter extends ZipBase implements ContentExporter {
37
38 /*** Static logger instance. */
39 private static final Logger logger =
40 Logger.getLogger(ZipExporter.class.getName());
41
42 /*** The attachment file name pattern. */
43 private static final Pattern DATA_PATTERN = Pattern.compile(
44 DATA + "/([0-9a-f]{2})/([0-9a-f]{2})/(//1//2[0-9a-f]{36})");
45
46 /***
47 * Reads the content state file and fills the given {@link ContentState}
48 * instance with the contents of the file.
49 *
50 * @param state the content state to be filled from the state file
51 * @throws ContentException if the content state file could not be read
52 * @see ContentExporter#exportContent(ContentState)
53 */
54 public void exportContent(ContentState state) throws ContentException {
55 ZipFile zip = null;
56 try {
57 logger.info("Reading content state file " + getZipfile());
58 zip = new ZipFile(getZipfile());
59
60 logger.fine("Reading " + CONTENT_XML + " from " + getZipfile());
61 ZipEntry entry = zip.getEntry(CONTENT_XML);
62 if (entry == null) {
63 throw new ContentException(
64 "No " + CONTENT_XML + " found inside " + getZipfile());
65 }
66 InputStream xml = zip.getInputStream(entry);
67 try {
68 state.setContent(xml);
69 } finally {
70 try { xml.close(); } catch (Exception e) {}
71 }
72
73 Enumeration entries = zip.entries();
74 while (entries.hasMoreElements()) {
75 entry = (ZipEntry) entries.nextElement();
76 Matcher matcher = DATA_PATTERN.matcher(entry.getName());
77 if (matcher.matches()) {
78 logger.fine(
79 "Reading attachment " + matcher.group(3)
80 + " from " + getZipfile());
81 InputStream data = zip.getInputStream(entry);
82 try {
83 String hash = state.addAttachment(data);
84 if (!hash.equals(matcher.group(3))) {
85 throw new ContentException(
86 "Invalid attachment in " + getZipfile());
87 }
88 } finally {
89 try { data.close(); } catch (Exception e) {}
90 }
91 }
92 }
93 } catch (IOException e) {
94 throw new ContentException(
95 "Error reading the content state file " + getZipfile(), e);
96 } finally {
97 logger.fine("Closing content state file " + getZipfile());
98 try { zip.close(); } catch (Exception e) {}
99 }
100 }
101
102 }