Merge pull request #64 in ITERATE/cyberduck from feature/windows/9074 to master
[cyberduck.git] / source / ch / cyberduck / core / openstack / SwiftContainerListService.java
blobaef0cbd60417ed5d9a30fb774d0a9f50539b0c0e
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.DefaultIOExceptionMappingService;
23 import ch.cyberduck.core.DisabledLoginCallback;
24 import ch.cyberduck.core.ListProgressListener;
25 import ch.cyberduck.core.Path;
26 import ch.cyberduck.core.PathAttributes;
27 import ch.cyberduck.core.RootListService;
28 import ch.cyberduck.core.cdn.Distribution;
29 import ch.cyberduck.core.cdn.DistributionConfiguration;
30 import ch.cyberduck.core.exception.BackgroundException;
31 import ch.cyberduck.core.preferences.Preferences;
32 import ch.cyberduck.core.preferences.PreferencesFactory;
33 import ch.cyberduck.core.threading.ThreadPool;
35 import org.apache.commons.lang3.StringUtils;
36 import org.apache.log4j.Logger;
38 import java.io.IOException;
39 import java.util.ArrayList;
40 import java.util.EnumSet;
41 import java.util.List;
43 import ch.iterate.openstack.swift.Client;
44 import ch.iterate.openstack.swift.exception.GenericException;
45 import ch.iterate.openstack.swift.model.Container;
46 import ch.iterate.openstack.swift.model.ContainerInfo;
47 import ch.iterate.openstack.swift.model.Region;
49 /**
50 * @version $Id$
52 public class SwiftContainerListService implements RootListService {
53 private static final Logger log = Logger.getLogger(SwiftContainerListService.class);
55 private final ThreadPool pool = new ThreadPool("cdn");
57 private SwiftSession session;
59 private Preferences preferences
60 = PreferencesFactory.get();
62 private boolean cdn;
64 private boolean size;
66 private SwiftLocationFeature.SwiftRegion region;
68 public SwiftContainerListService(final SwiftSession session, final SwiftLocationFeature.SwiftRegion region) {
69 this(session, region,
70 PreferencesFactory.get().getBoolean("openstack.cdn.preload"),
71 PreferencesFactory.get().getBoolean("openstack.container.size.preload"));
74 public SwiftContainerListService(final SwiftSession session, final SwiftLocationFeature.SwiftRegion region,
75 final boolean cdn, final boolean size) {
76 this.session = session;
77 this.region = region;
78 this.cdn = cdn;
79 this.size = size;
82 @Override
83 public List<Path> list(final ListProgressListener listener) throws BackgroundException {
84 if(log.isDebugEnabled()) {
85 log.debug(String.format("List containers for %s", session));
87 try {
88 final List<Path> containers = new ArrayList<Path>();
89 final int limit = preferences.getInteger("openstack.list.container.limit");
90 final Client client = session.getClient();
91 for(final Region r : client.getRegions()) {
92 if(region.getIdentifier() != null) {
93 if(!StringUtils.equals(r.getRegionId(), region.getIdentifier())) {
94 log.warn(String.format("Skip region %s", r));
95 continue;
98 // List all containers
99 List<Container> chunk;
100 String marker = null;
101 do {
102 chunk = client.listContainers(r, limit, marker);
103 for(final Container f : chunk) {
104 final PathAttributes attributes = new PathAttributes();
105 attributes.setRegion(f.getRegion().getRegionId());
106 containers.add(new Path(String.format("/%s", f.getName()),
107 EnumSet.of(Path.Type.volume, Path.Type.directory), attributes));
108 marker = f.getName();
110 listener.chunk(new Path(String.valueOf(Path.DELIMITER), EnumSet.of(Path.Type.volume, Path.Type.directory)),
111 new AttributedList<Path>(containers));
113 while(!chunk.isEmpty());
114 if(cdn) {
115 final DistributionConfiguration feature = session.getFeature(DistributionConfiguration.class);
116 if(feature != null) {
117 for(final Path container : containers) {
118 pool.execute(new Runnable() {
119 @Override
120 public void run() {
121 for(Distribution.Method method : feature.getMethods(container)) {
122 try {
123 final Distribution distribution = feature.read(container, method, new DisabledLoginCallback());
124 if(log.isInfoEnabled()) {
125 log.info(String.format("Cached distribution %s", distribution));
128 catch(BackgroundException e) {
129 log.warn(String.format("Failure caching CDN configuration for container %s %s", container, e.getMessage()));
137 if(size) {
138 for(final Path container : containers) {
139 pool.execute(new Runnable() {
140 @Override
141 public void run() {
142 try {
143 final ContainerInfo info = client.getContainerInfo(r, container.getName());
144 container.attributes().setSize(info.getTotalSize());
146 catch(IOException e) {
147 log.warn(String.format("Failure reading info for container %s %s", container, e.getMessage()));
154 return containers;
156 catch(GenericException e) {
157 throw new SwiftExceptionMappingService().map("Listing directory {0} failed", e,
158 new Path(String.valueOf(Path.DELIMITER), EnumSet.of(Path.Type.volume, Path.Type.directory)));
160 catch(IOException e) {
161 throw new DefaultIOExceptionMappingService().map(e);
163 finally {
164 // Shutdown gracefully
165 pool.shutdown();