View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors. 
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   *
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  
25  package org.modeshape.sequencer.zip;
26  
27  import java.io.ByteArrayOutputStream;
28  import java.io.File;
29  import java.io.InputStream;
30  import java.util.zip.ZipEntry;
31  import java.util.zip.ZipInputStream;
32  import org.modeshape.graph.JcrLexicon;
33  import org.modeshape.graph.JcrNtLexicon;
34  import org.modeshape.graph.ModeShapeLexicon;
35  import org.modeshape.graph.property.BinaryFactory;
36  import org.modeshape.graph.property.DateTimeFactory;
37  import org.modeshape.graph.property.Name;
38  import org.modeshape.graph.property.NameFactory;
39  import org.modeshape.graph.property.Path;
40  import org.modeshape.graph.property.PathFactory;
41  import org.modeshape.graph.sequencer.SequencerOutput;
42  import org.modeshape.graph.sequencer.StreamSequencer;
43  import org.modeshape.graph.sequencer.StreamSequencerContext;
44  
45  /**
46   * A sequencer that processes and extract the files and folders from ZIP archive files.
47   */
48  public class ZipSequencer implements StreamSequencer {
49  
50      /**
51       * {@inheritDoc}
52       * 
53       * @see org.modeshape.graph.sequencer.StreamSequencer#sequence(java.io.InputStream,
54       *      org.modeshape.graph.sequencer.SequencerOutput, org.modeshape.graph.sequencer.StreamSequencerContext)
55       */
56      public void sequence( InputStream stream,
57                            SequencerOutput output,
58                            StreamSequencerContext context ) {
59          BinaryFactory binaryFactory = context.getValueFactories().getBinaryFactory();
60          DateTimeFactory dateFactory = context.getValueFactories().getDateFactory();
61          PathFactory pathFactory = context.getValueFactories().getPathFactory();
62          NameFactory nameFactory = context.getValueFactories().getNameFactory();
63  
64          // Figure out the name of the archive file ...
65          Path pathToArchiveFile = context.getInputPath();
66          Name zipFileName = null;
67          if (pathToArchiveFile != null && !pathToArchiveFile.isRoot()) {
68              // Remove the 'jcr:content' node (of type 'nt:resource'), if it is there ...
69              if (pathToArchiveFile.getLastSegment().getName().equals(JcrLexicon.CONTENT)) pathToArchiveFile = pathToArchiveFile.getParent();
70              if (!pathToArchiveFile.isRoot()) zipFileName = pathToArchiveFile.getLastSegment().getName();
71          }
72          if (zipFileName == null) {
73              zipFileName = ZipLexicon.CONTENT;
74          }
75  
76          ZipInputStream in = null;
77          try {
78              in = new ZipInputStream(stream);
79              ZipEntry entry = in.getNextEntry();
80              byte[] buf = new byte[1024];
81  
82              // Create top-level node
83              Path zipPath = pathFactory.createRelativePath(zipFileName);
84              output.setProperty(zipPath, JcrLexicon.PRIMARY_TYPE, ZipLexicon.CONTENT);
85              while (entry != null) {
86                  Path entryPath = zipPath;
87                  String entryName = entry.getName();
88                  for (String segment : entryName.split(File.separator)) {
89                      entryPath = pathFactory.create(entryPath, nameFactory.create(segment));
90                  }
91  
92                  if (entry.isDirectory()) { // If entry is directory, create nt:folder node
93                      output.setProperty(entryPath, JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.FOLDER);
94                  } else { // If entry is File, create nt:file
95                      output.setProperty(entryPath, JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.FILE);
96  
97                      Path contentPath = pathFactory.create(entryPath, JcrLexicon.CONTENT);
98                      output.setProperty(contentPath, JcrLexicon.PRIMARY_TYPE, ModeShapeLexicon.RESOURCE);
99                      int n;
100                     ByteArrayOutputStream baout = new ByteArrayOutputStream();
101                     while ((n = in.read(buf, 0, 1024)) > -1) {
102                         baout.write(buf, 0, n);
103                     }
104                     byte[] bytes = baout.toByteArray();
105                     output.setProperty(contentPath, JcrLexicon.DATA, binaryFactory.create(bytes));
106                     // all other nt:file properties should be generated by other sequencers (mimetype, encoding,...) but we'll
107                     // default them here
108                     output.setProperty(contentPath, JcrLexicon.ENCODED, "binary");
109                     output.setProperty(contentPath, JcrLexicon.LAST_MODIFIED, dateFactory.create(entry.getTime()).toString());
110                     output.setProperty(contentPath, JcrLexicon.MIMETYPE, "application/octet-stream");
111 
112                 }
113                 in.closeEntry();
114                 entry = in.getNextEntry();
115             }
116         } catch (Exception e) {
117             String location = context.getValueFactories().getStringFactory().create(context.getInputPath());
118             context.getProblems().addError(e, ZipI18n.errorReadingZipFile, location, e.getMessage());
119         } finally {
120             if (in != null) {
121                 try {
122                     in.close();
123                 } catch (Exception e) {
124                     String location = context.getValueFactories().getStringFactory().create(context.getInputPath());
125                     context.getProblems().addError(e, ZipI18n.errorClosingZipFile, location, e.getMessage());
126                 }
127             }
128         }
129     }
130 }