View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs.provider.zip;
18  
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  import org.apache.commons.vfs.FileName;
22  import org.apache.commons.vfs.FileObject;
23  import org.apache.commons.vfs.FileSystem;
24  import org.apache.commons.vfs.FileSystemException;
25  import org.apache.commons.vfs.FileSystemOptions;
26  import org.apache.commons.vfs.Selectors;
27  import org.apache.commons.vfs.VfsLog;
28  import org.apache.commons.vfs.provider.AbstractFileSystem;
29  import org.apache.commons.vfs.provider.UriParser;
30  
31  import java.io.File;
32  import java.io.IOException;
33  import java.util.ArrayList;
34  import java.util.Collection;
35  import java.util.Enumeration;
36  import java.util.List;
37  import java.util.zip.ZipEntry;
38  import java.util.zip.ZipFile;
39  
40  /***
41   * A read-only file system for Zip/Jar files.
42   *
43   * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
44   * @version $Revision: 484648 $ $Date: 2006-12-08 17:18:36 +0100 (Fr, 08 Dez 2006) $
45   */
46  public class ZipFileSystem
47      extends AbstractFileSystem
48      implements FileSystem
49  {
50      private final static Log log = LogFactory.getLog(ZipFileSystem.class);
51  
52      private final File file;
53      private ZipFile zipFile;
54  
55      public ZipFileSystem(final FileName rootName,
56                           final FileObject parentLayer,
57                           final FileSystemOptions fileSystemOptions)
58          throws FileSystemException
59      {
60          super(rootName, parentLayer, fileSystemOptions);
61  
62          // Make a local copy of the file
63          file = parentLayer.getFileSystem().replicateFile(parentLayer, Selectors.SELECT_SELF);
64  
65          // Open the Zip file
66          if (!file.exists())
67          {
68              // Don't need to do anything
69              zipFile = null;
70              return;
71          }
72  
73          // zipFile = createZipFile(this.file);
74      }
75  
76      public void init() throws FileSystemException
77      {
78          super.init();
79  
80          try
81          {
82              // Build the index
83              List strongRef = new ArrayList(100);
84              Enumeration entries = getZipFile().entries();
85              while (entries.hasMoreElements())
86              {
87                  ZipEntry entry = (ZipEntry) entries.nextElement();
88                  FileName name = getFileSystemManager().resolveName(getRootName(), UriParser.encode(entry.getName()));
89  
90                  // Create the file
91                  ZipFileObject fileObj;
92                  if (entry.isDirectory() && getFileFromCache(name) != null)
93                  {
94                      fileObj = (ZipFileObject) getFileFromCache(name);
95                      fileObj.setZipEntry(entry);
96                      continue;
97                  }
98  
99                  fileObj = createZipFileObject(name, entry);
100                 putFileToCache(fileObj);
101                 strongRef.add(fileObj);
102                 fileObj.holdObject(strongRef);
103 
104                 // Make sure all ancestors exist
105                 // TODO - create these on demand
106                 ZipFileObject parent = null;
107                 for (FileName parentName = name.getParent();
108                      parentName != null;
109                      fileObj = parent, parentName = parentName.getParent())
110                 {
111                     // Locate the parent
112                     parent = (ZipFileObject) getFileFromCache(parentName);
113                     if (parent == null)
114                     {
115                         parent = createZipFileObject(parentName, null);
116                         putFileToCache(parent);
117                         strongRef.add(parent);
118                         parent.holdObject(strongRef);
119                     }
120 
121                     // Attach child to parent
122                     parent.attachChild(fileObj.getName());
123                 }
124             }
125         }
126         finally
127         {
128             closeCommunicationLink();
129         }
130     }
131 
132     protected ZipFile getZipFile() throws FileSystemException
133     {
134         if (zipFile == null && this.file.exists())
135         {
136             ZipFile zipFile = createZipFile(this.file);
137 
138             this.zipFile = zipFile;
139         }
140 
141         return zipFile;
142     }
143 
144     protected ZipFileObject createZipFileObject(final FileName name,
145                                                 final ZipEntry entry) throws FileSystemException
146     {
147         return new ZipFileObject(name, entry, this, true);
148     }
149 
150     protected ZipFile createZipFile(final File file) throws FileSystemException
151     {
152         try
153         {
154             return new ZipFile(file);
155         }
156         catch (IOException ioe)
157         {
158             throw new FileSystemException("vfs.provider.zip/open-zip-file.error", file, ioe);
159         }
160     }
161 
162     protected void doCloseCommunicationLink()
163     {
164         // Release the zip file
165         try
166         {
167             if (zipFile != null)
168             {
169                 zipFile.close();
170                 zipFile = null;
171             }
172         }
173         catch (final IOException e)
174         {
175             // getLogger().warn("vfs.provider.zip/close-zip-file.error :" + file, e);
176             VfsLog.warn(getLogger(), log, "vfs.provider.zip/close-zip-file.error :" + file, e);
177         }
178     }
179 
180     /***
181      * Returns the capabilities of this file system.
182      */
183     protected void addCapabilities(final Collection caps)
184     {
185         caps.addAll(ZipFileProvider.capabilities);
186     }
187 
188     /***
189      * Creates a file object.
190      */
191     protected FileObject createFile(final FileName name) throws FileSystemException
192     {
193         // This is only called for files which do not exist in the Zip file
194         return new ZipFileObject(name, null, this, false);
195     }
196 
197     /***
198      * will be called after all file-objects closed their streams.
199     protected void notifyAllStreamsClosed()
200     {
201         closeCommunicationLink();
202     }
203 	 */
204 }