@Override
    public DescriptiveUrlBag toUrl(final Path file) {
        final DescriptiveUrlBag list = new DescriptiveUrlBag();
        if(new HostPreferences(session.getHost()).getBoolean("s3.bucket.virtualhost.disable")) {
            list.addAll(new DefaultUrlProvider(session.getHost()).toUrl(file));
        }
        else {
            list.add(this.toUrl(file, session.getHost().getProtocol().getScheme(), session.getHost().getPort()));
            list.add(this.toUrl(file, Scheme.http, 80));
            if(StringUtils.isNotBlank(session.getHost().getWebURL())) {
                // Only include when custom domain is configured
                list.addAll(new HostWebUrlProvider(session.getHost()).toUrl(file));
            }
        }
        if(file.isFile()) {
            if(!session.getHost().getCredentials().isAnonymousLogin()) {
                // X-Amz-Expires must be less than a week (in seconds); that is, the given X-Amz-Expires must be less
                // than 604800 seconds
                // In one hour
                list.add(this.toSignedUrl(file, (int) TimeUnit.HOURS.toSeconds(1)));
                // Default signed URL expiring in 24 hours.
                list.add(this.toSignedUrl(file, (int) TimeUnit.SECONDS.toSeconds(
                        new HostPreferences(session.getHost()).getInteger("s3.url.expire.seconds"))));
                // 1 Week
                list.add(this.toSignedUrl(file, (int) TimeUnit.DAYS.toSeconds(7)));
                switch(session.getSignatureVersion()) {
                    case AWS2:
                        // 1 Month
                        list.add(this.toSignedUrl(file, (int) TimeUnit.DAYS.toSeconds(30)));
                        // 1 Year
                        list.add(this.toSignedUrl(file, (int) TimeUnit.DAYS.toSeconds(365)));
                        break;
                    case AWS4HMACSHA256:
                        break;
                }
            }
        }
        // AWS services require specifying an Amazon S3 bucket using S3://bucket
        list.add(new DescriptiveUrl(URI.create(String.format("s3://%s%s",
                containerService.getContainer(file).getName(),
                file.isRoot() ? Path.DELIMITER : containerService.isContainer(file) ? Path.DELIMITER : String.format("/%s", URIEncoder.encode(containerService.getKey(file))))),
                DescriptiveUrl.Type.provider,
                MessageFormat.format(LocaleFactory.localizedString("{0} URL"), "S3")));
        // Filter by matching container name
        final Optional<Set<Distribution>> filtered = distributions.entrySet().stream().filter(entry ->
                        new SimplePathPredicate(containerService.getContainer(file)).test(entry.getKey()))
                .map(Map.Entry::getValue).findFirst();
        if(filtered.isPresent()) {
            // Add CloudFront distributions
            for(Distribution distribution : filtered.get()) {
                list.addAll(new DistributionUrlProvider(distribution).toUrl(file));
            }
        }
        return list;
    }
@Test
    public void testToSignedUrlThirdparty() throws Exception {
        final S3Session session = new S3Session(new Host(new S3Protocol(), "s.greenqloud.com",
                new Credentials("k", "s"))) {
            @Override
            public RequestEntityRestStorageService getClient() {
                try {
                    return this.connect(new DisabledProxyFinder(), new DisabledHostKeyCallback(), new DisabledLoginCallback(), new DisabledCancelCallback());
                }
                catch(BackgroundException e) {
                    fail();
                    throw new RuntimeException(e);
                }
            }
        };
        final S3UrlProvider provider = new S3UrlProvider(session, Collections.emptyMap(), new DisabledPasswordStore() {
            @Override
            public String findLoginPassword(final Host bookmark) {
                return "k";
            }
        });
        assertNotNull(
                provider.toUrl(new Path("/test-eu-west-1-cyberduck/test", EnumSet.of(Path.Type.file))).find(DescriptiveUrl.Type.signed)
        );
    }