View Javadoc

1   /*
2    * Copyright 2005 Jukka Zitting <jz@yukatan.fi>
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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 }