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