1 package ch
.cyberduck
.core
.s3
;
4 * Copyright (c) 2002-2013 David Kocher. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * Bug fixes, suggestions and comments should be sent to feedback@cyberduck.ch
20 import ch
.cyberduck
.core
.AbstractTestCase
;
21 import ch
.cyberduck
.core
.AttributedList
;
22 import ch
.cyberduck
.core
.Credentials
;
23 import ch
.cyberduck
.core
.DisabledCancelCallback
;
24 import ch
.cyberduck
.core
.DisabledHostKeyCallback
;
25 import ch
.cyberduck
.core
.DisabledListProgressListener
;
26 import ch
.cyberduck
.core
.DisabledLoginCallback
;
27 import ch
.cyberduck
.core
.DisabledPasswordStore
;
28 import ch
.cyberduck
.core
.DisabledTranscriptListener
;
29 import ch
.cyberduck
.core
.Host
;
30 import ch
.cyberduck
.core
.Path
;
31 import ch
.cyberduck
.core
.PathAttributes
;
32 import ch
.cyberduck
.core
.Protocol
;
33 import ch
.cyberduck
.core
.ProtocolFactory
;
34 import ch
.cyberduck
.core
.exception
.BackgroundException
;
35 import ch
.cyberduck
.core
.exception
.NotfoundException
;
36 import ch
.cyberduck
.core
.features
.Delete
;
37 import ch
.cyberduck
.core
.preferences
.PreferencesFactory
;
38 import ch
.cyberduck
.core
.shared
.DefaultHomeFinderService
;
40 import org
.jets3t
.service
.Jets3tProperties
;
41 import org
.junit
.Ignore
;
42 import org
.junit
.Test
;
44 import java
.util
.Arrays
;
45 import java
.util
.EnumSet
;
46 import java
.util
.List
;
47 import java
.util
.UUID
;
49 import static org
.junit
.Assert
.*;
54 public class S3ObjectListServiceTest
extends AbstractTestCase
{
57 public void testList() throws Exception
{
58 final S3Session session
= new S3Session(
59 new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(),
61 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
63 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
64 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
65 final Path container
= new Path("test.cyberduck.ch", EnumSet
.of(Path
.Type
.volume
));
66 container
.attributes().setRegion("us-east-1");
67 final List
<Path
> list
= new S3ObjectListService(session
).list(container
, new DisabledListProgressListener());
68 assertFalse(list
.isEmpty());
70 assertEquals(container
, p
.getParent());
71 assertEquals("us-east-1", p
.attributes().getRegion());
73 assertNotNull(p
.attributes().getModificationDate());
74 assertNotNull(p
.attributes().getSize());
75 assertNotNull(p
.attributes().getETag());
76 assertNotNull(p
.attributes().getStorageClass());
83 public void tetsEmptyPlaceholder() throws Exception
{
84 final S3Session session
= new S3Session(
85 new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(),
87 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
89 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
90 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
91 final Path container
= new Path("test.cyberduck.ch", EnumSet
.of(Path
.Type
.volume
));
92 final List
<Path
> list
= new S3ObjectListService(session
).list(new Path(container
, "empty", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.placeholder
)),
93 new DisabledListProgressListener());
94 assertTrue(list
.isEmpty());
98 @Test(expected
= NotfoundException
.class)
99 public void testListNotfound() throws Exception
{
100 final S3Session session
= new S3Session(
101 new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(),
103 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
105 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
106 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
107 final Path container
= new Path("notfound.cyberduck.ch", EnumSet
.of(Path
.Type
.volume
));
108 new S3ObjectListService(session
).list(container
, new DisabledListProgressListener());
114 public void testListCnameAnonymous() throws Exception
{
115 final Host host
= new Host(new S3Protocol(), "dist.springframework.org", new Credentials(
116 PreferencesFactory
.get().getProperty("connection.login.anon.name"), null
118 final S3Session session
= new S3Session(host
);
119 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
120 final AttributedList
<Path
> list
121 = new S3ObjectListService(session
).list(new Path("/dist.springframework.org", EnumSet
.of(Path
.Type
.directory
)),
122 new DisabledListProgressListener());
123 assertFalse(list
.isEmpty());
124 assertTrue(list
.contains(new Path("/dist.springframework.org/release", EnumSet
.of(Path
.Type
.directory
))));
125 assertTrue(list
.contains(new Path("/dist.springframework.org/milestone", EnumSet
.of(Path
.Type
.directory
))));
126 assertTrue(list
.contains(new Path("/dist.springframework.org/snapshot", EnumSet
.of(Path
.Type
.directory
))));
127 assertTrue(list
.contains(new Path("/dist.springframework.org/robots.txt", EnumSet
.of(Path
.Type
.file
))));
132 public void testListBuckenameAnonymous() throws Exception
{
133 final Host host
= new Host(new S3Protocol(), "dist.springframework.org.s3.amazonaws.com", new Credentials(
134 PreferencesFactory
.get().getProperty("connection.login.anon.name"), null
136 final S3Session session
= new S3Session(host
);
137 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
138 final AttributedList
<Path
> list
139 = new S3ObjectListService(session
).list(new Path("/dist.springframework.org", EnumSet
.of(Path
.Type
.directory
)),
140 new DisabledListProgressListener());
141 assertFalse(list
.isEmpty());
142 assertTrue(list
.contains(new Path("/dist.springframework.org/release", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.placeholder
))));
143 assertTrue(list
.contains(new Path("/dist.springframework.org/milestone", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.placeholder
))));
144 assertTrue(list
.contains(new Path("/dist.springframework.org/snapshot", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.placeholder
))));
145 assertTrue(list
.contains(new Path("/dist.springframework.org/robots.txt", EnumSet
.of(Path
.Type
.file
))));
150 public void testListDefaultPath() throws Exception
{
151 final Host host
= new Host(new S3Protocol(), "dist.springframework.org.s3.amazonaws.com", new Credentials(
152 PreferencesFactory
.get().getProperty("connection.login.anon.name"), null
154 host
.setDefaultPath("/dist.springframework.org/release");
155 final S3Session session
= new S3Session(host
);
156 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
157 assertEquals(new Path("/dist.springframework.org/release", EnumSet
.of(Path
.Type
.directory
)), new DefaultHomeFinderService(session
).find());
158 final AttributedList
<Path
> list
159 = new S3ObjectListService(session
).list(new DefaultHomeFinderService(session
).find(), new DisabledListProgressListener());
160 assertFalse(list
.isEmpty());
161 assertTrue(list
.contains(new Path("/dist.springframework.org/release/SWF", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.placeholder
))));
166 public void testListVersioning() throws Exception
{
167 final S3Session session
= new S3Session(
168 new Host(ProtocolFactory
.forName(Protocol
.Type
.s3
.name()), ProtocolFactory
.forName(Protocol
.Type
.s3
.name()).getDefaultHostname(),
170 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
172 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
173 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
174 final AttributedList
<Path
> list
= new S3ObjectListService(session
).list(new Path("versioning.test.cyberduck.ch",
175 EnumSet
.of(Path
.Type
.directory
, Path
.Type
.volume
)),
176 new DisabledListProgressListener());
177 final PathAttributes att
= new PathAttributes();
178 assertTrue(list
.contains(new Path("/versioning.test.cyberduck.ch/test", EnumSet
.of(Path
.Type
.file
), att
)));
179 att
.setVersionId("xtgd1iPdpb1L0c87oe.3KVul2rcxRyqh");
180 assertTrue(list
.contains(new Path("/versioning.test.cyberduck.ch/test", EnumSet
.of(Path
.Type
.file
), att
)));
185 public void testListPlaceholder() throws Exception
{
186 final S3Session session
= new S3Session(
187 new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(),
189 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
191 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
192 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
193 final Path container
= new Path("test.cyberduck.ch", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.volume
));
194 container
.attributes().setRegion("us-east-1");
195 final Path placeholder
= new Path(container
, UUID
.randomUUID().toString(), EnumSet
.of(Path
.Type
.directory
));
196 new S3DirectoryFeature(session
).mkdir(placeholder
);
197 placeholder
.setType(EnumSet
.of(Path
.Type
.directory
, Path
.Type
.placeholder
));
198 final AttributedList
<Path
> list
= new S3ObjectListService(session
).list(placeholder
, new DisabledListProgressListener());
199 assertTrue(list
.isEmpty());
200 new S3DefaultDeleteFeature(session
).delete(Arrays
.asList(placeholder
), new DisabledLoginCallback(), new Delete
.Callback() {
202 public void delete(final Path file
) {
209 public void testListAWS4SignatureFrankfurt() throws Exception
{
210 final S3Session session
= new S3Session(
211 new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(),
213 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
216 public S3Protocol
.AuthenticationHeaderSignatureVersion
getSignatureVersion() {
217 return S3Protocol
.AuthenticationHeaderSignatureVersion
.AWS4HMACSHA256
;
221 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
222 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
223 final Path container
= new Path("cyberduck-frankfurt", EnumSet
.of(Path
.Type
.volume
));
224 final AttributedList
<Path
> list
= new S3ObjectListService(session
).list(container
, new DisabledListProgressListener());
229 public void testListAWS2AutoSwitchAWS4SignatureFrankfurt() throws Exception
{
230 final S3Session session
= new S3Session(
231 new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(),
233 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
236 public S3Protocol
.AuthenticationHeaderSignatureVersion
getSignatureVersion() {
237 return S3Protocol
.AuthenticationHeaderSignatureVersion
.AWS2
;
240 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
241 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
242 final Path container
= new Path("cyberduck-frankfurt", EnumSet
.of(Path
.Type
.volume
));
243 final AttributedList
<Path
> list
= new S3ObjectListService(session
).list(container
, new DisabledListProgressListener());
247 @Test(expected
= BackgroundException
.class)
248 public void testAccessPathStyleBucketEuCentral() throws Exception
{
249 final S3Session session
= new S3Session(
250 new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(),
252 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
255 public S3Protocol
.AuthenticationHeaderSignatureVersion
getSignatureVersion() {
256 return S3Protocol
.AuthenticationHeaderSignatureVersion
.AWS4HMACSHA256
;
260 protected Jets3tProperties
configure() {
261 final Jets3tProperties properties
= super.configure();
262 properties
.setProperty("s3service.disable-dns-buckets", String
.valueOf(true));
266 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
267 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
268 final Path container
= new Path("cyberduck-frankfurt", EnumSet
.of(Path
.Type
.volume
));
270 final AttributedList
<Path
> list
= new S3ObjectListService(session
).list(container
, new DisabledListProgressListener());
272 catch(BackgroundException e
) {
273 assertEquals("Listing directory cyberduck-frankfurt failed.", e
.getMessage());
274 assertEquals("Received redirect response HTTP/1.1 301 Moved Permanently but no location header.", e
.getDetail());