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  
18  package org.apache.commons.vfs2.provider.zip;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.nio.charset.StandardCharsets;
24  
25  import org.apache.commons.io.FileUtils;
26  import org.apache.commons.io.IOUtils;
27  import org.apache.commons.lang3.SystemUtils;
28  import org.apache.commons.vfs2.FileObject;
29  import org.apache.commons.vfs2.FileSystemException;
30  import org.apache.commons.vfs2.FileSystemManager;
31  import org.apache.commons.vfs2.VFS;
32  import org.junit.Assert;
33  import org.junit.Assume;
34  import org.junit.Before;
35  import org.junit.Test;
36  
37  /**
38   * Tests https://issues.apache.org/jira/browse/VFS-291
39   */
40  public class FileLockTestCase {
41  
42      private FileSystemManager manager;
43      private File newZipFile;
44  
45      private String zipFileUri;
46  
47      private void assertDelete() {
48          // We do not use newZipFile in the Assert message to avoid touching it before calling delete().
49          Assert.assertTrue("Could not delete file", newZipFile.delete());
50      }
51  
52      private void readAndAssert(final InputStream inputStream) throws IOException {
53          final String string = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
54          Assert.assertNotNull(string);
55          Assert.assertEquals("This is a test file.", string);
56      }
57  
58      private void resolveAndOpenCloseContent() throws FileSystemException {
59          try (final FileObject zipFileObject = manager.resolveFile(zipFileUri)) {
60              zipFileObject.getContent().close();
61          }
62      }
63  
64      private void resolveAndOpenCloseInputStream() throws IOException, FileSystemException {
65          try (final FileObject zipFileObject = manager.resolveFile(zipFileUri)) {
66              zipFileObject.getContent().getInputStream().close();
67          }
68      }
69  
70      private void resolveAndOpenReadCloseInputStream() throws IOException, FileSystemException {
71          try (final FileObject zipFileObject = manager.resolveFile(zipFileUri)) {
72              try (InputStream inputStream = zipFileObject.getContent().getInputStream()) {
73                  readAndAssert(inputStream);
74              }
75          }
76      }
77  
78      @Before
79      public void setup() throws IOException {
80          final File zipFile = new File("src/test/resources/test-data/test.zip");
81          newZipFile = File.createTempFile(getClass().getSimpleName(), ".zip");
82          newZipFile.deleteOnExit();
83          FileUtils.copyFile(zipFile, newZipFile);
84          zipFileUri = "zip:file:" + newZipFile.getAbsolutePath() + "!/read-tests/file1.txt";
85          manager = VFS.getManager();
86      }
87  
88      @Test
89      public void testCannotDeleteWhileStreaming() throws Exception {
90          try (final FileObject zipFileObject = manager.resolveFile(zipFileUri)) {
91              try (InputStream inputStream = zipFileObject.getContent().getInputStream()) {
92                  if (SystemUtils.IS_OS_WINDOWS) {
93                      // We do not use newZipFile in the Assert message to avoid touching it before calling delete().
94                      Assert.assertFalse("Could not delete file", newZipFile.delete());
95                  }
96              }
97          }
98          assertDelete();
99      }
100 
101     @Test
102     public void testCannotDeleteWhileStreaming2() throws Exception {
103         Assume.assumeTrue(SystemUtils.IS_OS_WINDOWS);
104         try (final FileObject zipFileObject = manager.resolveFile(zipFileUri)) {
105             try (InputStream inputStream = zipFileObject.getContent().getInputStream()) {
106                 // We do not use newZipFile in the Assert message to avoid touching it before calling delete().
107                 Assert.assertFalse("Could not delete file", newZipFile.delete());
108             }
109         }
110     }
111 
112     @Test
113     public void testReadClosedFileObject() throws Exception {
114         final FileObject zipFileObjectRef;
115         try (final FileObject zipFileObject = manager.resolveFile(zipFileUri)) {
116             zipFileObjectRef = zipFileObject;
117             try (final InputStream inputStream = zipFileObject.getContent().getInputStream()) {
118                 readAndAssert(inputStream);
119             }
120         }
121         try (final InputStream inputStream = zipFileObjectRef.getContent().getInputStream()) {
122             readAndAssert(inputStream);
123         } finally {
124             zipFileObjectRef.close();
125         }
126         assertDelete();
127     }
128 
129     @Test
130     public void testResolveAndOpenCloseContent() throws Exception {
131         resolveAndOpenCloseContent();
132         assertDelete();
133     }
134 
135     @Test
136     public void testResolveAndOpenCloseContent3() throws Exception {
137         resolveAndOpenCloseContent();
138         resolveAndOpenCloseContent();
139         resolveAndOpenCloseContent();
140 
141         assertDelete();
142     }
143 
144     /**
145      * This test checks whether we can modify an underlying Zip file after we have performed IO operations on files
146      * within it, but although we no longer have any FileObjects explicitly open.
147      *
148      * @throws Exception
149      */
150     @Test
151     public void testResolveAndOpenCloseInputStream() throws Exception {
152         resolveAndOpenCloseInputStream();
153         assertDelete();
154     }
155 
156     @Test
157     public void testResolveAndOpenCloseInputStream3() throws Exception {
158         resolveAndOpenCloseInputStream();
159         resolveAndOpenCloseInputStream();
160         resolveAndOpenCloseInputStream();
161 
162         assertDelete();
163     }
164 
165     @Test
166     public void testResolveAndOpenReadCloseInputStream() throws Exception {
167         resolveAndOpenReadCloseInputStream();
168         assertDelete();
169     }
170 
171     @Test
172     public void testResolveAndOpenReadCloseInputStream3() throws Exception {
173         resolveAndOpenReadCloseInputStream();
174         resolveAndOpenReadCloseInputStream();
175         resolveAndOpenReadCloseInputStream();
176         assertDelete();
177     }
178 
179     @Test
180     public void testResolveOpenCloseNestedInputStreams() throws Exception {
181         try (final FileObject zipFileObject = manager.resolveFile(zipFileUri)) {
182             try (final FileObject zipFileObject2 = manager.resolveFile(zipFileUri)) {
183                 zipFileObject2.getContent().getInputStream().close();
184             }
185             zipFileObject.getContent().getInputStream().close();
186         }
187         assertDelete();
188     }
189 
190 }