Add callback for delete operation.
[cyberduck.git] / source / ch / cyberduck / core / openstack / SwiftSession.java
blob9c76b856cfe55d8a81055cf1db4633f6e0078ec0
1 package ch.cyberduck.core.openstack;
3 /*
4 * Copyright (c) 2013 David Kocher. All rights reserved.
5 * http://cyberduck.ch/
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;
66 import java.util.Map;
67 import java.util.Set;
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;
75 /**
76 * @version $Id$
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);
103 @Override
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());
111 @Override
112 protected void logout() throws BackgroundException {
113 try {
114 client.disconnect();
116 catch(IOException e) {
117 throw new DefaultIOExceptionMappingService().map(e);
121 @Override
122 public void login(final PasswordStore keychain, final LoginCallback prompt, final CancelCallback cancel,
123 final Cache<Path> cache) throws BackgroundException {
124 try {
125 final Set<? extends AuthenticationRequest> options = new SwiftAuthenticationService().getRequest(host, prompt);
126 for(Iterator<? extends AuthenticationRequest> iter = options.iterator(); iter.hasNext(); ) {
127 try {
128 final AuthenticationRequest auth = iter.next();
129 if(log.isInfoEnabled()) {
130 log.info(String.format("Attempt authentication with %s", auth));
132 client.authenticate(auth);
133 break;
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()) {
141 throw failure;
144 else {
145 throw failure;
148 cancel.verify();
150 final ThreadPool pool = new ThreadPool(5, "accounts");
151 try {
152 pool.execute(new Runnable() {
153 @Override
154 public void run() {
155 for(Region region : client.getRegions()) {
156 try {
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));
170 finally {
171 // Shutdown gracefully
172 pool.shutdown();
175 catch(GenericException e) {
176 throw new SwiftExceptionMappingService().map(e);
178 catch(IOException e) {
179 throw new DefaultIOExceptionMappingService().map(e);
183 @Override
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));
189 else {
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);
202 @Override
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()));
241 return null;
244 return (T) cdn;
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);