1 package ch
.cyberduck
.core
.openstack
;
4 * Copyright (c) 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:
18 * feedback@cyberduck.ch
21 import ch
.cyberduck
.core
.AttributedList
;
22 import ch
.cyberduck
.core
.Cache
;
23 import ch
.cyberduck
.core
.DefaultIOExceptionMappingService
;
24 import ch
.cyberduck
.core
.Host
;
25 import ch
.cyberduck
.core
.HostKeyCallback
;
26 import ch
.cyberduck
.core
.ListProgressListener
;
27 import ch
.cyberduck
.core
.LoginCallback
;
28 import ch
.cyberduck
.core
.PasswordStore
;
29 import ch
.cyberduck
.core
.Path
;
30 import ch
.cyberduck
.core
.UrlProvider
;
31 import ch
.cyberduck
.core
.analytics
.AnalyticsProvider
;
32 import ch
.cyberduck
.core
.analytics
.QloudstatAnalyticsProvider
;
33 import ch
.cyberduck
.core
.cdn
.DistributionConfiguration
;
34 import ch
.cyberduck
.core
.exception
.AccessDeniedException
;
35 import ch
.cyberduck
.core
.exception
.BackgroundException
;
36 import ch
.cyberduck
.core
.exception
.InteroperabilityException
;
37 import ch
.cyberduck
.core
.exception
.LoginFailureException
;
38 import ch
.cyberduck
.core
.features
.Attributes
;
39 import ch
.cyberduck
.core
.features
.Copy
;
40 import ch
.cyberduck
.core
.features
.Delete
;
41 import ch
.cyberduck
.core
.features
.Directory
;
42 import ch
.cyberduck
.core
.features
.Headers
;
43 import ch
.cyberduck
.core
.features
.Home
;
44 import ch
.cyberduck
.core
.features
.Location
;
45 import ch
.cyberduck
.core
.features
.Move
;
46 import ch
.cyberduck
.core
.features
.Read
;
47 import ch
.cyberduck
.core
.features
.Touch
;
48 import ch
.cyberduck
.core
.features
.Upload
;
49 import ch
.cyberduck
.core
.features
.Write
;
50 import ch
.cyberduck
.core
.http
.HttpSession
;
51 import ch
.cyberduck
.core
.proxy
.ProxyFinder
;
52 import ch
.cyberduck
.core
.ssl
.DefaultX509KeyManager
;
53 import ch
.cyberduck
.core
.ssl
.DisabledX509TrustManager
;
54 import ch
.cyberduck
.core
.ssl
.X509KeyManager
;
55 import ch
.cyberduck
.core
.ssl
.X509TrustManager
;
56 import ch
.cyberduck
.core
.threading
.CancelCallback
;
57 import ch
.cyberduck
.core
.threading
.ThreadPool
;
59 import org
.apache
.http
.impl
.client
.HttpClientBuilder
;
60 import org
.apache
.log4j
.Logger
;
62 import javax
.net
.SocketFactory
;
63 import java
.io
.IOException
;
64 import java
.util
.HashMap
;
65 import java
.util
.Iterator
;
69 import ch
.iterate
.openstack
.swift
.Client
;
70 import ch
.iterate
.openstack
.swift
.exception
.GenericException
;
71 import ch
.iterate
.openstack
.swift
.method
.AuthenticationRequest
;
72 import ch
.iterate
.openstack
.swift
.model
.AccountInfo
;
73 import ch
.iterate
.openstack
.swift
.model
.Region
;
78 public class SwiftSession
extends HttpSession
<Client
> {
79 private static final Logger log
= Logger
.getLogger(SwiftSession
.class);
81 private SwiftDistributionConfiguration cdn
82 = new SwiftDistributionConfiguration(this);
84 protected Map
<Region
, AccountInfo
> accounts
85 = new HashMap
<Region
, AccountInfo
>();
87 public SwiftSession(final Host h
) {
88 super(h
, new DisabledX509TrustManager(), new DefaultX509KeyManager());
91 public SwiftSession(final Host host
, final X509TrustManager trust
, final X509KeyManager key
) {
92 super(host
, trust
, key
);
95 public SwiftSession(final Host host
, final X509TrustManager trust
, final X509KeyManager key
, final ProxyFinder proxy
) {
96 super(host
, trust
, key
, proxy
);
99 public SwiftSession(final Host host
, final X509TrustManager trust
, final X509KeyManager key
, final SocketFactory socketFactory
) {
100 super(host
, trust
, key
, socketFactory
);
104 public Client
connect(final HostKeyCallback key
) throws BackgroundException
{
105 // Always inject new pool to builder on connect because the pool is shutdown on disconnect
106 final HttpClientBuilder pool
= builder
.build(this);
107 pool
.disableContentCompression();
108 return new Client(pool
.build());
112 protected void logout() throws BackgroundException
{
116 catch(IOException e
) {
117 throw new DefaultIOExceptionMappingService().map(e
);
122 public void login(final PasswordStore keychain
, final LoginCallback prompt
, final CancelCallback cancel
,
123 final Cache
<Path
> cache
) throws BackgroundException
{
125 final Set
<?
extends AuthenticationRequest
> options
= new SwiftAuthenticationService().getRequest(host
, prompt
);
126 for(Iterator
<?
extends AuthenticationRequest
> iter
= options
.iterator(); iter
.hasNext(); ) {
128 final AuthenticationRequest auth
= iter
.next();
129 if(log
.isInfoEnabled()) {
130 log
.info(String
.format("Attempt authentication with %s", auth
));
132 client
.authenticate(auth
);
135 catch(GenericException failure
) {
136 final BackgroundException reason
= new SwiftExceptionMappingService().map(failure
);
137 if(reason
instanceof LoginFailureException
138 || reason
instanceof AccessDeniedException
139 || reason
instanceof InteroperabilityException
) {
140 if(!iter
.hasNext()) {
150 final ThreadPool pool
= new ThreadPool(5, "accounts");
152 pool
.execute(new Runnable() {
155 for(Region region
: client
.getRegions()) {
157 final AccountInfo info
= client
.getAccountInfo(region
);
158 if(log
.isInfoEnabled()) {
159 log
.info(String
.format("Signing key is %s", info
.getTempUrlKey()));
161 accounts
.put(region
, info
);
163 catch(IOException e
) {
164 log
.warn(String
.format("Failure loading account info for region %s", region
));
171 // Shutdown gracefully
175 catch(GenericException e
) {
176 throw new SwiftExceptionMappingService().map(e
);
178 catch(IOException e
) {
179 throw new DefaultIOExceptionMappingService().map(e
);
184 public AttributedList
<Path
> list(final Path directory
, final ListProgressListener listener
) throws BackgroundException
{
185 if(directory
.isRoot()) {
186 return new AttributedList
<Path
>(new SwiftContainerListService(this,
187 new SwiftLocationFeature
.SwiftRegion(host
.getRegion())).list(listener
));
190 SwiftLocationFeature
.SwiftRegion region
= new SwiftLocationFeature
.SwiftRegion(host
.getRegion());
191 if(Location
.unknown
.equals(region
)) {
192 region
= new SwiftLocationFeature
.SwiftRegion(directory
.attributes().getRegion());
194 if(Location
.unknown
.equals(region
)) {
195 directory
.attributes().setRegion(
196 new SwiftRegionService(this).lookup(this.getFeature(Location
.class).getLocation(directory
)).getRegionId());
198 return new SwiftObjectListService(this).list(directory
, listener
);
203 public <T
> T
getFeature(final Class
<T
> type
) {
204 if(type
== Read
.class) {
205 return (T
) new SwiftReadFeature(this);
207 if(type
== Write
.class) {
208 return (T
) new SwiftWriteFeature(this);
210 if(type
== Upload
.class) {
211 return (T
) new SwiftThresholdUploadService(this);
213 if(type
== Directory
.class) {
214 return (T
) new SwiftDirectoryFeature(this);
216 if(type
== Delete
.class) {
217 return (T
) new SwiftMultipleDeleteFeature(this);
219 if(type
== Headers
.class) {
220 return (T
) new SwiftMetadataFeature(this);
222 if(type
== Copy
.class) {
223 return (T
) new SwiftCopyFeature(this);
225 if(type
== Move
.class) {
226 return (T
) new SwiftMoveFeature(this);
228 if(type
== Touch
.class) {
229 return (T
) new SwiftTouchFeature(this);
231 if(type
== Location
.class) {
232 return (T
) new SwiftLocationFeature(this);
234 if(type
== AnalyticsProvider
.class) {
235 return (T
) new QloudstatAnalyticsProvider();
237 if(type
== DistributionConfiguration
.class) {
238 for(Region region
: accounts
.keySet()) {
239 if(null == region
.getCDNManagementUrl()) {
240 log
.warn(String
.format("Missing CDN Management URL for region %s", region
.getRegionId()));
246 if(type
== UrlProvider
.class) {
247 if(host
.getHostname().endsWith("identity.hpcloudsvc.com")) {
248 return (T
) new SwiftHpUrlProvider(this);
250 return (T
) new SwiftUrlProvider(this, accounts
);
252 if(type
== Attributes
.class) {
253 return (T
) new SwiftAttributesFeature(this);
255 if(type
== Home
.class) {
256 return (T
) new SwiftHomeFinderService(this);
258 return super.getFeature(type
);