001package org.eclipse.aether.transport.file;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 * 
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 * 
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import static org.junit.Assert.*;
023
024import java.io.File;
025import java.io.FileNotFoundException;
026import java.net.URI;
027import java.nio.charset.StandardCharsets;
028
029import org.eclipse.aether.DefaultRepositorySystemSession;
030import org.eclipse.aether.internal.test.util.TestFileUtils;
031import org.eclipse.aether.internal.test.util.TestLoggerFactory;
032import org.eclipse.aether.internal.test.util.TestUtils;
033import org.eclipse.aether.repository.RemoteRepository;
034import org.eclipse.aether.spi.connector.transport.GetTask;
035import org.eclipse.aether.spi.connector.transport.PeekTask;
036import org.eclipse.aether.spi.connector.transport.PutTask;
037import org.eclipse.aether.spi.connector.transport.Transporter;
038import org.eclipse.aether.spi.connector.transport.TransporterFactory;
039import org.eclipse.aether.transfer.NoTransporterException;
040import org.eclipse.aether.transfer.TransferCancelledException;
041import org.junit.After;
042import org.junit.Before;
043import org.junit.Test;
044
045/**
046 */
047public class FileTransporterTest
048{
049
050    private DefaultRepositorySystemSession session;
051
052    private TransporterFactory factory;
053
054    private Transporter transporter;
055
056    private File repoDir;
057
058    private RemoteRepository newRepo( String url )
059    {
060        return new RemoteRepository.Builder( "test", "default", url ).build();
061    }
062
063    private void newTransporter( String url )
064        throws Exception
065    {
066        if ( transporter != null )
067        {
068            transporter.close();
069            transporter = null;
070        }
071        transporter = factory.newInstance( session, newRepo( url ) );
072    }
073
074    @Before
075    public void setUp()
076        throws Exception
077    {
078        session = TestUtils.newSession();
079        factory = new FileTransporterFactory( new TestLoggerFactory() );
080        repoDir = TestFileUtils.createTempDir();
081        TestFileUtils.writeString( new File( repoDir, "file.txt" ), "test" );
082        TestFileUtils.writeString( new File( repoDir, "empty.txt" ), "" );
083        TestFileUtils.writeString( new File( repoDir, "some space.txt" ), "space" );
084        newTransporter( repoDir.toURI().toString() );
085    }
086
087    @After
088    public void tearDown()
089    {
090        if ( transporter != null )
091        {
092            transporter.close();
093            transporter = null;
094        }
095        factory = null;
096        session = null;
097    }
098
099    @Test
100    public void testClassify()
101        throws Exception
102    {
103        assertEquals( Transporter.ERROR_OTHER, transporter.classify( new FileNotFoundException() ) );
104        assertEquals( Transporter.ERROR_NOT_FOUND, transporter.classify( new ResourceNotFoundException( "test" ) ) );
105    }
106
107    @Test
108    public void testPeek()
109        throws Exception
110    {
111        transporter.peek( new PeekTask( URI.create( "file.txt" ) ) );
112    }
113
114    @Test
115    public void testPeek_NotFound()
116        throws Exception
117    {
118        try
119        {
120            transporter.peek( new PeekTask( URI.create( "missing.txt" ) ) );
121            fail( "Expected error" );
122        }
123        catch ( ResourceNotFoundException e )
124        {
125            assertEquals( Transporter.ERROR_NOT_FOUND, transporter.classify( e ) );
126        }
127    }
128
129    @Test
130    public void testPeek_Closed()
131        throws Exception
132    {
133        transporter.close();
134        try
135        {
136            transporter.peek( new PeekTask( URI.create( "missing.txt" ) ) );
137            fail( "Expected error" );
138        }
139        catch ( IllegalStateException e )
140        {
141            assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) );
142        }
143    }
144
145    @Test
146    public void testGet_ToMemory()
147        throws Exception
148    {
149        RecordingTransportListener listener = new RecordingTransportListener();
150        GetTask task = new GetTask( URI.create( "file.txt" ) ).setListener( listener );
151        transporter.get( task );
152        assertEquals( "test", task.getDataString() );
153        assertEquals( 0L, listener.dataOffset );
154        assertEquals( 4L, listener.dataLength );
155        assertEquals( 1, listener.startedCount );
156        assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 );
157        assertEquals( task.getDataString(), new String( listener.baos.toByteArray(), StandardCharsets.UTF_8 ) );
158    }
159
160    @Test
161    public void testGet_ToFile()
162        throws Exception
163    {
164        File file = TestFileUtils.createTempFile( "failure" );
165        RecordingTransportListener listener = new RecordingTransportListener();
166        GetTask task = new GetTask( URI.create( "file.txt" ) ).setDataFile( file ).setListener( listener );
167        transporter.get( task );
168        assertEquals( "test", TestFileUtils.readString( file ) );
169        assertEquals( 0L, listener.dataOffset );
170        assertEquals( 4L, listener.dataLength );
171        assertEquals( 1, listener.startedCount );
172        assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 );
173        assertEquals( "test", new String( listener.baos.toByteArray(), StandardCharsets.UTF_8 ) );
174    }
175
176    @Test
177    public void testGet_EmptyResource()
178        throws Exception
179    {
180        File file = TestFileUtils.createTempFile( "failure" );
181        RecordingTransportListener listener = new RecordingTransportListener();
182        GetTask task = new GetTask( URI.create( "empty.txt" ) ).setDataFile( file ).setListener( listener );
183        transporter.get( task );
184        assertEquals( "", TestFileUtils.readString( file ) );
185        assertEquals( 0L, listener.dataOffset );
186        assertEquals( 0L, listener.dataLength );
187        assertEquals( 1, listener.startedCount );
188        assertEquals( 0, listener.progressedCount );
189        assertEquals( "", new String( listener.baos.toByteArray(), StandardCharsets.UTF_8 ) );
190    }
191
192    @Test
193    public void testGet_EncodedResourcePath()
194        throws Exception
195    {
196        GetTask task = new GetTask( URI.create( "some%20space.txt" ) );
197        transporter.get( task );
198        assertEquals( "space", task.getDataString() );
199    }
200
201    @Test
202    public void testGet_Fragment()
203        throws Exception
204    {
205        GetTask task = new GetTask( URI.create( "file.txt#ignored" ) );
206        transporter.get( task );
207        assertEquals( "test", task.getDataString() );
208    }
209
210    @Test
211    public void testGet_Query()
212        throws Exception
213    {
214        GetTask task = new GetTask( URI.create( "file.txt?ignored" ) );
215        transporter.get( task );
216        assertEquals( "test", task.getDataString() );
217    }
218
219    @Test
220    public void testGet_FileHandleLeak()
221        throws Exception
222    {
223        for ( int i = 0; i < 100; i++ )
224        {
225            File file = TestFileUtils.createTempFile( "failure" );
226            transporter.get( new GetTask( URI.create( "file.txt" ) ).setDataFile( file ) );
227            assertTrue( i + ", " + file.getAbsolutePath(), file.delete() );
228        }
229    }
230
231    @Test
232    public void testGet_NotFound()
233        throws Exception
234    {
235        try
236        {
237            transporter.get( new GetTask( URI.create( "missing.txt" ) ) );
238            fail( "Expected error" );
239        }
240        catch ( ResourceNotFoundException e )
241        {
242            assertEquals( Transporter.ERROR_NOT_FOUND, transporter.classify( e ) );
243        }
244    }
245
246    @Test
247    public void testGet_Closed()
248        throws Exception
249    {
250        transporter.close();
251        try
252        {
253            transporter.get( new GetTask( URI.create( "file.txt" ) ) );
254            fail( "Expected error" );
255        }
256        catch ( IllegalStateException e )
257        {
258            assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) );
259        }
260    }
261
262    @Test
263    public void testGet_StartCancelled()
264        throws Exception
265    {
266        RecordingTransportListener listener = new RecordingTransportListener();
267        listener.cancelStart = true;
268        GetTask task = new GetTask( URI.create( "file.txt" ) ).setListener( listener );
269        try
270        {
271            transporter.get( task );
272            fail( "Expected error" );
273        }
274        catch ( TransferCancelledException e )
275        {
276            assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) );
277        }
278        assertEquals( 0L, listener.dataOffset );
279        assertEquals( 4L, listener.dataLength );
280        assertEquals( 1, listener.startedCount );
281        assertEquals( 0, listener.progressedCount );
282    }
283
284    @Test
285    public void testGet_ProgressCancelled()
286        throws Exception
287    {
288        RecordingTransportListener listener = new RecordingTransportListener();
289        listener.cancelProgress = true;
290        GetTask task = new GetTask( URI.create( "file.txt" ) ).setListener( listener );
291        try
292        {
293            transporter.get( task );
294            fail( "Expected error" );
295        }
296        catch ( TransferCancelledException e )
297        {
298            assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) );
299        }
300        assertEquals( 0L, listener.dataOffset );
301        assertEquals( 4L, listener.dataLength );
302        assertEquals( 1, listener.startedCount );
303        assertEquals( 1, listener.progressedCount );
304    }
305
306    @Test
307    public void testPut_FromMemory()
308        throws Exception
309    {
310        RecordingTransportListener listener = new RecordingTransportListener();
311        PutTask task = new PutTask( URI.create( "file.txt" ) ).setListener( listener ).setDataString( "upload" );
312        transporter.put( task );
313        assertEquals( 0L, listener.dataOffset );
314        assertEquals( 6L, listener.dataLength );
315        assertEquals( 1, listener.startedCount );
316        assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 );
317        assertEquals( "upload", TestFileUtils.readString( new File( repoDir, "file.txt" ) ) );
318    }
319
320    @Test
321    public void testPut_FromFile()
322        throws Exception
323    {
324        File file = TestFileUtils.createTempFile( "upload" );
325        RecordingTransportListener listener = new RecordingTransportListener();
326        PutTask task = new PutTask( URI.create( "file.txt" ) ).setListener( listener ).setDataFile( file );
327        transporter.put( task );
328        assertEquals( 0L, listener.dataOffset );
329        assertEquals( 6L, listener.dataLength );
330        assertEquals( 1, listener.startedCount );
331        assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 );
332        assertEquals( "upload", TestFileUtils.readString( new File( repoDir, "file.txt" ) ) );
333    }
334
335    @Test
336    public void testPut_EmptyResource()
337        throws Exception
338    {
339        RecordingTransportListener listener = new RecordingTransportListener();
340        PutTask task = new PutTask( URI.create( "file.txt" ) ).setListener( listener );
341        transporter.put( task );
342        assertEquals( 0L, listener.dataOffset );
343        assertEquals( 0L, listener.dataLength );
344        assertEquals( 1, listener.startedCount );
345        assertEquals( 0, listener.progressedCount );
346        assertEquals( "", TestFileUtils.readString( new File( repoDir, "file.txt" ) ) );
347    }
348
349    @Test
350    public void testPut_NonExistentParentDir()
351        throws Exception
352    {
353        RecordingTransportListener listener = new RecordingTransportListener();
354        PutTask task =
355            new PutTask( URI.create( "dir/sub/dir/file.txt" ) ).setListener( listener ).setDataString( "upload" );
356        transporter.put( task );
357        assertEquals( 0L, listener.dataOffset );
358        assertEquals( 6L, listener.dataLength );
359        assertEquals( 1, listener.startedCount );
360        assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 );
361        assertEquals( "upload", TestFileUtils.readString( new File( repoDir, "dir/sub/dir/file.txt" ) ) );
362    }
363
364    @Test
365    public void testPut_EncodedResourcePath()
366        throws Exception
367    {
368        RecordingTransportListener listener = new RecordingTransportListener();
369        PutTask task = new PutTask( URI.create( "some%20space.txt" ) ).setListener( listener ).setDataString( "OK" );
370        transporter.put( task );
371        assertEquals( 0L, listener.dataOffset );
372        assertEquals( 2L, listener.dataLength );
373        assertEquals( 1, listener.startedCount );
374        assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 );
375        assertEquals( "OK", TestFileUtils.readString( new File( repoDir, "some space.txt" ) ) );
376    }
377
378    @Test
379    public void testPut_FileHandleLeak()
380        throws Exception
381    {
382        for ( int i = 0; i < 100; i++ )
383        {
384            File src = TestFileUtils.createTempFile( "upload" );
385            File dst = new File( repoDir, "file.txt" );
386            transporter.put( new PutTask( URI.create( "file.txt" ) ).setDataFile( src ) );
387            assertTrue( i + ", " + src.getAbsolutePath(), src.delete() );
388            assertTrue( i + ", " + dst.getAbsolutePath(), dst.delete() );
389        }
390    }
391
392    @Test
393    public void testPut_Closed()
394        throws Exception
395    {
396        transporter.close();
397        try
398        {
399            transporter.put( new PutTask( URI.create( "missing.txt" ) ) );
400            fail( "Expected error" );
401        }
402        catch ( IllegalStateException e )
403        {
404            assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) );
405        }
406    }
407
408    @Test
409    public void testPut_StartCancelled()
410        throws Exception
411    {
412        RecordingTransportListener listener = new RecordingTransportListener();
413        listener.cancelStart = true;
414        PutTask task = new PutTask( URI.create( "file.txt" ) ).setListener( listener ).setDataString( "upload" );
415        try
416        {
417            transporter.put( task );
418            fail( "Expected error" );
419        }
420        catch ( TransferCancelledException e )
421        {
422            assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) );
423        }
424        assertEquals( 0L, listener.dataOffset );
425        assertEquals( 6L, listener.dataLength );
426        assertEquals( 1, listener.startedCount );
427        assertEquals( 0, listener.progressedCount );
428        assertFalse( new File( repoDir, "file.txt" ).exists() );
429    }
430
431    @Test
432    public void testPut_ProgressCancelled()
433        throws Exception
434    {
435        RecordingTransportListener listener = new RecordingTransportListener();
436        listener.cancelProgress = true;
437        PutTask task = new PutTask( URI.create( "file.txt" ) ).setListener( listener ).setDataString( "upload" );
438        try
439        {
440            transporter.put( task );
441            fail( "Expected error" );
442        }
443        catch ( TransferCancelledException e )
444        {
445            assertEquals( Transporter.ERROR_OTHER, transporter.classify( e ) );
446        }
447        assertEquals( 0L, listener.dataOffset );
448        assertEquals( 6L, listener.dataLength );
449        assertEquals( 1, listener.startedCount );
450        assertEquals( 1, listener.progressedCount );
451        assertFalse( new File( repoDir, "file.txt" ).exists() );
452    }
453
454    @Test( expected = NoTransporterException.class )
455    public void testInit_BadProtocol()
456        throws Exception
457    {
458        newTransporter( "bad:/void" );
459    }
460
461    @Test
462    public void testInit_CaseInsensitiveProtocol()
463        throws Exception
464    {
465        newTransporter( "file:/void" );
466        newTransporter( "FILE:/void" );
467        newTransporter( "File:/void" );
468    }
469
470    @Test
471    public void testInit_OpaqueUrl()
472        throws Exception
473    {
474        testInit( "file:repository", "repository" );
475    }
476
477    @Test
478    public void testInit_OpaqueUrlTrailingSlash()
479        throws Exception
480    {
481        testInit( "file:repository/", "repository" );
482    }
483
484    @Test
485    public void testInit_OpaqueUrlSpaces()
486        throws Exception
487    {
488        testInit( "file:repo%20space", "repo space" );
489    }
490
491    @Test
492    public void testInit_OpaqueUrlSpacesDecoded()
493        throws Exception
494    {
495        testInit( "file:repo space", "repo space" );
496    }
497
498    @Test
499    public void testInit_HierarchicalUrl()
500        throws Exception
501    {
502        testInit( "file:/repository", "/repository" );
503    }
504
505    @Test
506    public void testInit_HierarchicalUrlTrailingSlash()
507        throws Exception
508    {
509        testInit( "file:/repository/", "/repository" );
510    }
511
512    @Test
513    public void testInit_HierarchicalUrlSpaces()
514        throws Exception
515    {
516        testInit( "file:/repo%20space", "/repo space" );
517    }
518
519    @Test
520    public void testInit_HierarchicalUrlSpacesDecoded()
521        throws Exception
522    {
523        testInit( "file:/repo space", "/repo space" );
524    }
525
526    @Test
527    public void testInit_HierarchicalUrlRoot()
528        throws Exception
529    {
530        testInit( "file:/", "/" );
531    }
532
533    @Test
534    public void testInit_HierarchicalUrlHostNoPath()
535        throws Exception
536    {
537        testInit( "file://host/", "/" );
538    }
539
540    @Test
541    public void testInit_HierarchicalUrlHostPath()
542        throws Exception
543    {
544        testInit( "file://host/dir", "/dir" );
545    }
546
547    private void testInit( String base, String expected )
548        throws Exception
549    {
550        newTransporter( base );
551        File exp = new File( expected ).getAbsoluteFile();
552        assertEquals( exp, ( (FileTransporter) transporter ).getBasedir() );
553    }
554
555}