View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.transport.file;
20  
21  import java.io.File;
22  import java.io.FileNotFoundException;
23  import java.net.URI;
24  import java.nio.charset.StandardCharsets;
25  
26  import org.eclipse.aether.DefaultRepositorySystemSession;
27  import org.eclipse.aether.internal.test.util.TestFileUtils;
28  import org.eclipse.aether.internal.test.util.TestUtils;
29  import org.eclipse.aether.repository.RemoteRepository;
30  import org.eclipse.aether.spi.connector.transport.GetTask;
31  import org.eclipse.aether.spi.connector.transport.PeekTask;
32  import org.eclipse.aether.spi.connector.transport.PutTask;
33  import org.eclipse.aether.spi.connector.transport.Transporter;
34  import org.eclipse.aether.spi.connector.transport.TransporterFactory;
35  import org.eclipse.aether.transfer.NoTransporterException;
36  import org.eclipse.aether.transfer.TransferCancelledException;
37  import org.junit.jupiter.api.AfterEach;
38  import org.junit.jupiter.api.BeforeEach;
39  import org.junit.jupiter.api.Test;
40  
41  import static org.junit.jupiter.api.Assertions.*;
42  
43  /**
44   */
45  public class FileTransporterTest {
46  
47      private DefaultRepositorySystemSession session;
48  
49      private TransporterFactory factory;
50  
51      private Transporter transporter;
52  
53      private File repoDir;
54  
55      private RemoteRepository newRepo(String url) {
56          return new RemoteRepository.Builder("test", "default", url).build();
57      }
58  
59      private void newTransporter(String url) throws Exception {
60          if (transporter != null) {
61              transporter.close();
62              transporter = null;
63          }
64          transporter = factory.newInstance(session, newRepo(url));
65      }
66  
67      @BeforeEach
68      void setUp() throws Exception {
69          session = TestUtils.newSession();
70          factory = new FileTransporterFactory();
71          repoDir = TestFileUtils.createTempDir();
72          TestFileUtils.writeString(new File(repoDir, "file.txt"), "test");
73          TestFileUtils.writeString(new File(repoDir, "empty.txt"), "");
74          TestFileUtils.writeString(new File(repoDir, "some space.txt"), "space");
75          newTransporter(repoDir.toURI().toString());
76      }
77  
78      @AfterEach
79      void tearDown() {
80          if (transporter != null) {
81              transporter.close();
82              transporter = null;
83          }
84          factory = null;
85          session = null;
86      }
87  
88      @Test
89      void testClassify() {
90          assertEquals(Transporter.ERROR_OTHER, transporter.classify(new FileNotFoundException()));
91          assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(new ResourceNotFoundException("test")));
92      }
93  
94      @Test
95      void testPeek() throws Exception {
96          transporter.peek(new PeekTask(URI.create("file.txt")));
97      }
98  
99      @Test
100     void testPeek_NotFound() throws Exception {
101         try {
102             transporter.peek(new PeekTask(URI.create("missing.txt")));
103             fail("Expected error");
104         } catch (ResourceNotFoundException e) {
105             assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(e));
106         }
107     }
108 
109     @Test
110     void testPeek_Closed() throws Exception {
111         transporter.close();
112         try {
113             transporter.peek(new PeekTask(URI.create("missing.txt")));
114             fail("Expected error");
115         } catch (IllegalStateException e) {
116             assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
117         }
118     }
119 
120     @Test
121     void testGet_ToMemory() throws Exception {
122         RecordingTransportListener listener = new RecordingTransportListener();
123         GetTask task = new GetTask(URI.create("file.txt")).setListener(listener);
124         transporter.get(task);
125         assertEquals("test", task.getDataString());
126         assertEquals(0L, listener.dataOffset);
127         assertEquals(4L, listener.dataLength);
128         assertEquals(1, listener.startedCount);
129         assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
130         assertEquals(task.getDataString(), new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
131     }
132 
133     @Test
134     void testGet_ToFile() throws Exception {
135         File file = TestFileUtils.createTempFile("failure");
136         RecordingTransportListener listener = new RecordingTransportListener();
137         GetTask task = new GetTask(URI.create("file.txt")).setDataFile(file).setListener(listener);
138         transporter.get(task);
139         assertEquals("test", TestFileUtils.readString(file));
140         assertEquals(0L, listener.dataOffset);
141         assertEquals(4L, listener.dataLength);
142         assertEquals(1, listener.startedCount);
143         assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
144         assertEquals("test", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
145     }
146 
147     @Test
148     void testGet_EmptyResource() throws Exception {
149         File file = TestFileUtils.createTempFile("failure");
150         RecordingTransportListener listener = new RecordingTransportListener();
151         GetTask task = new GetTask(URI.create("empty.txt")).setDataFile(file).setListener(listener);
152         transporter.get(task);
153         assertEquals("", TestFileUtils.readString(file));
154         assertEquals(0L, listener.dataOffset);
155         assertEquals(0L, listener.dataLength);
156         assertEquals(1, listener.startedCount);
157         assertEquals(0, listener.progressedCount);
158         assertEquals("", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
159     }
160 
161     @Test
162     void testGet_EncodedResourcePath() throws Exception {
163         GetTask task = new GetTask(URI.create("some%20space.txt"));
164         transporter.get(task);
165         assertEquals("space", task.getDataString());
166     }
167 
168     @Test
169     void testGet_Fragment() throws Exception {
170         GetTask task = new GetTask(URI.create("file.txt#ignored"));
171         transporter.get(task);
172         assertEquals("test", task.getDataString());
173     }
174 
175     @Test
176     void testGet_Query() throws Exception {
177         GetTask task = new GetTask(URI.create("file.txt?ignored"));
178         transporter.get(task);
179         assertEquals("test", task.getDataString());
180     }
181 
182     @Test
183     void testGet_FileHandleLeak() throws Exception {
184         for (int i = 0; i < 100; i++) {
185             File file = TestFileUtils.createTempFile("failure");
186             transporter.get(new GetTask(URI.create("file.txt")).setDataFile(file));
187             assertTrue(file.delete(), i + ", " + file.getAbsolutePath());
188         }
189     }
190 
191     @Test
192     void testGet_NotFound() throws Exception {
193         try {
194             transporter.get(new GetTask(URI.create("missing.txt")));
195             fail("Expected error");
196         } catch (ResourceNotFoundException e) {
197             assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(e));
198         }
199     }
200 
201     @Test
202     void testGet_Closed() throws Exception {
203         transporter.close();
204         try {
205             transporter.get(new GetTask(URI.create("file.txt")));
206             fail("Expected error");
207         } catch (IllegalStateException e) {
208             assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
209         }
210     }
211 
212     @Test
213     void testGet_StartCancelled() throws Exception {
214         RecordingTransportListener listener = new RecordingTransportListener();
215         listener.cancelStart = true;
216         GetTask task = new GetTask(URI.create("file.txt")).setListener(listener);
217         try {
218             transporter.get(task);
219             fail("Expected error");
220         } catch (TransferCancelledException e) {
221             assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
222         }
223         assertEquals(0L, listener.dataOffset);
224         assertEquals(4L, listener.dataLength);
225         assertEquals(1, listener.startedCount);
226         assertEquals(0, listener.progressedCount);
227     }
228 
229     @Test
230     void testGet_ProgressCancelled() throws Exception {
231         RecordingTransportListener listener = new RecordingTransportListener();
232         listener.cancelProgress = true;
233         GetTask task = new GetTask(URI.create("file.txt")).setListener(listener);
234         try {
235             transporter.get(task);
236             fail("Expected error");
237         } catch (TransferCancelledException e) {
238             assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
239         }
240         assertEquals(0L, listener.dataOffset);
241         assertEquals(4L, listener.dataLength);
242         assertEquals(1, listener.startedCount);
243         assertEquals(1, listener.progressedCount);
244     }
245 
246     @Test
247     void testPut_FromMemory() throws Exception {
248         RecordingTransportListener listener = new RecordingTransportListener();
249         PutTask task = new PutTask(URI.create("file.txt")).setListener(listener).setDataString("upload");
250         transporter.put(task);
251         assertEquals(0L, listener.dataOffset);
252         assertEquals(6L, listener.dataLength);
253         assertEquals(1, listener.startedCount);
254         assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
255         assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
256     }
257 
258     @Test
259     void testPut_FromFile() throws Exception {
260         File file = TestFileUtils.createTempFile("upload");
261         RecordingTransportListener listener = new RecordingTransportListener();
262         PutTask task = new PutTask(URI.create("file.txt")).setListener(listener).setDataFile(file);
263         transporter.put(task);
264         assertEquals(0L, listener.dataOffset);
265         assertEquals(6L, listener.dataLength);
266         assertEquals(1, listener.startedCount);
267         assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
268         assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
269     }
270 
271     @Test
272     void testPut_EmptyResource() throws Exception {
273         RecordingTransportListener listener = new RecordingTransportListener();
274         PutTask task = new PutTask(URI.create("file.txt")).setListener(listener);
275         transporter.put(task);
276         assertEquals(0L, listener.dataOffset);
277         assertEquals(0L, listener.dataLength);
278         assertEquals(1, listener.startedCount);
279         assertEquals(0, listener.progressedCount);
280         assertEquals("", TestFileUtils.readString(new File(repoDir, "file.txt")));
281     }
282 
283     @Test
284     void testPut_NonExistentParentDir() throws Exception {
285         RecordingTransportListener listener = new RecordingTransportListener();
286         PutTask task = new PutTask(URI.create("dir/sub/dir/file.txt"))
287                 .setListener(listener)
288                 .setDataString("upload");
289         transporter.put(task);
290         assertEquals(0L, listener.dataOffset);
291         assertEquals(6L, listener.dataLength);
292         assertEquals(1, listener.startedCount);
293         assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
294         assertEquals("upload", TestFileUtils.readString(new File(repoDir, "dir/sub/dir/file.txt")));
295     }
296 
297     @Test
298     void testPut_EncodedResourcePath() throws Exception {
299         RecordingTransportListener listener = new RecordingTransportListener();
300         PutTask task = new PutTask(URI.create("some%20space.txt"))
301                 .setListener(listener)
302                 .setDataString("OK");
303         transporter.put(task);
304         assertEquals(0L, listener.dataOffset);
305         assertEquals(2L, listener.dataLength);
306         assertEquals(1, listener.startedCount);
307         assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
308         assertEquals("OK", TestFileUtils.readString(new File(repoDir, "some space.txt")));
309     }
310 
311     @Test
312     void testPut_FileHandleLeak() throws Exception {
313         for (int i = 0; i < 100; i++) {
314             File src = TestFileUtils.createTempFile("upload");
315             File dst = new File(repoDir, "file.txt");
316             transporter.put(new PutTask(URI.create("file.txt")).setDataFile(src));
317             assertTrue(src.delete(), i + ", " + src.getAbsolutePath());
318             assertTrue(dst.delete(), i + ", " + dst.getAbsolutePath());
319         }
320     }
321 
322     @Test
323     void testPut_Closed() throws Exception {
324         transporter.close();
325         try {
326             transporter.put(new PutTask(URI.create("missing.txt")));
327             fail("Expected error");
328         } catch (IllegalStateException e) {
329             assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
330         }
331     }
332 
333     @Test
334     void testPut_StartCancelled() throws Exception {
335         RecordingTransportListener listener = new RecordingTransportListener();
336         listener.cancelStart = true;
337         PutTask task = new PutTask(URI.create("file.txt")).setListener(listener).setDataString("upload");
338         try {
339             transporter.put(task);
340             fail("Expected error");
341         } catch (TransferCancelledException e) {
342             assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
343         }
344         assertEquals(0L, listener.dataOffset);
345         assertEquals(6L, listener.dataLength);
346         assertEquals(1, listener.startedCount);
347         assertEquals(0, listener.progressedCount);
348         assertFalse(new File(repoDir, "file.txt").exists());
349     }
350 
351     @Test
352     void testPut_ProgressCancelled() throws Exception {
353         RecordingTransportListener listener = new RecordingTransportListener();
354         listener.cancelProgress = true;
355         PutTask task = new PutTask(URI.create("file.txt")).setListener(listener).setDataString("upload");
356         try {
357             transporter.put(task);
358             fail("Expected error");
359         } catch (TransferCancelledException e) {
360             assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
361         }
362         assertEquals(0L, listener.dataOffset);
363         assertEquals(6L, listener.dataLength);
364         assertEquals(1, listener.startedCount);
365         assertEquals(1, listener.progressedCount);
366         assertFalse(new File(repoDir, "file.txt").exists());
367     }
368 
369     @Test
370     void testInit_BadProtocol() {
371         assertThrows(NoTransporterException.class, () -> newTransporter("bad:/void"));
372     }
373 
374     @Test
375     void testInit_CaseInsensitiveProtocol() throws Exception {
376         newTransporter("file:/void");
377         newTransporter("FILE:/void");
378         newTransporter("File:/void");
379     }
380 
381     @Test
382     void testInit_OpaqueUrl() throws Exception {
383         testInit("file:repository", "repository");
384     }
385 
386     @Test
387     void testInit_OpaqueUrlTrailingSlash() throws Exception {
388         testInit("file:repository/", "repository");
389     }
390 
391     @Test
392     void testInit_OpaqueUrlSpaces() throws Exception {
393         testInit("file:repo%20space", "repo space");
394     }
395 
396     @Test
397     void testInit_OpaqueUrlSpacesDecoded() throws Exception {
398         testInit("file:repo space", "repo space");
399     }
400 
401     @Test
402     void testInit_HierarchicalUrl() throws Exception {
403         testInit("file:/repository", "/repository");
404     }
405 
406     @Test
407     void testInit_HierarchicalUrlTrailingSlash() throws Exception {
408         testInit("file:/repository/", "/repository");
409     }
410 
411     @Test
412     void testInit_HierarchicalUrlSpaces() throws Exception {
413         testInit("file:/repo%20space", "/repo space");
414     }
415 
416     @Test
417     void testInit_HierarchicalUrlSpacesDecoded() throws Exception {
418         testInit("file:/repo space", "/repo space");
419     }
420 
421     @Test
422     void testInit_HierarchicalUrlRoot() throws Exception {
423         testInit("file:/", "/");
424     }
425 
426     @Test
427     void testInit_HierarchicalUrlHostNoPath() throws Exception {
428         testInit("file://host/", "/");
429     }
430 
431     @Test
432     void testInit_HierarchicalUrlHostPath() throws Exception {
433         testInit("file://host/dir", "/dir");
434     }
435 
436     private void testInit(String base, String expected) throws Exception {
437         newTransporter(base);
438         File exp = new File(expected).getAbsoluteFile();
439         assertEquals(exp, ((FileTransporter) transporter).getBasedir());
440     }
441 }