View Javadoc
1   package org.kuali.common.aws.s3;
2   
3   import static com.google.common.base.Stopwatch.createStarted;
4   import static com.google.common.collect.Lists.newArrayList;
5   import static java.lang.String.format;
6   import static org.kuali.common.core.collect.Lists.shuffledCopy;
7   import static org.kuali.common.util.base.Exceptions.illegalState;
8   import static org.kuali.common.util.log.Loggers.newLogger;
9   
10  import java.io.File;
11  import java.util.List;
12  import java.util.concurrent.Callable;
13  
14  import org.kuali.common.aws.s3.model.ObjectSummary;
15  import org.kuali.common.core.base.TimedInterval;
16  import org.kuali.common.core.build.ValidatingBuilder;
17  import org.kuali.common.core.validate.annotation.IdiotProofImmutable;
18  import org.kuali.common.util.inform.PercentCompleteInformer;
19  import org.slf4j.Logger;
20  
21  import com.amazonaws.services.s3.model.AmazonS3Exception;
22  import com.google.common.base.Function;
23  import com.google.common.base.Stopwatch;
24  import com.google.common.collect.ImmutableList;
25  
26  @IdiotProofImmutable
27  public final class CopyObjectToFileCallable implements Callable<List<TimedInterval>> {
28  
29  	private static final Logger logger = newLogger();
30  
31  	private final S3Service s3;
32  	private final ImmutableList<ObjectSummary> objects;
33  	private final Function<String, String> keyToPath;
34  	private final String bucket;
35  	private final PercentCompleteInformer informer;
36  
37  	@Override
38  	public List<TimedInterval> call() {
39  		List<TimedInterval> timings = newArrayList();
40  		List<ObjectSummary> shuffled = shuffledCopy(objects);
41  		for (ObjectSummary object : shuffled) {
42  			Stopwatch sw = createStarted();
43  			try {
44  				String path = keyToPath.apply(object.getKey());
45  				File file = new File(path);
46  				logger.debug(format("creating    -> %s", file));
47  				s3.copyObjectToFile(bucket, object.getKey(), file);
48  			} catch (AmazonS3Exception e) {
49  				throw illegalState(e, "key=%s", object.getKey());
50  			}
51  			TimedInterval timing = TimedInterval.build(sw);
52  			timings.add(timing);
53  			informer.incrementProgress();
54  		}
55  		return timings;
56  	}
57  
58  	private CopyObjectToFileCallable(Builder builder) {
59  		this.s3 = builder.s3;
60  		this.objects = ImmutableList.copyOf(builder.objects);
61  		this.bucket = builder.bucket;
62  		this.informer = builder.informer;
63  		this.keyToPath = builder.keyToPath;
64  	}
65  
66  	public static Builder builder() {
67  		return new Builder();
68  	}
69  
70  	public static class Builder extends ValidatingBuilder<CopyObjectToFileCallable> {
71  
72  		private S3Service s3;
73  		private List<ObjectSummary> objects;
74  		private String bucket;
75  		private PercentCompleteInformer informer;
76  		private Function<String, String> keyToPath;
77  
78  		public Builder withObjects(List<ObjectSummary> objects) {
79  			this.objects = objects;
80  			return this;
81  		}
82  
83  		public Builder withKeyToPath(Function<String, String> keyToPath) {
84  			this.keyToPath = keyToPath;
85  			return this;
86  		}
87  
88  		public Builder withS3(S3Service s3) {
89  			this.s3 = s3;
90  			return this;
91  		}
92  
93  		public Builder withBucket(String bucket) {
94  			this.bucket = bucket;
95  			return this;
96  		}
97  
98  		public Builder withInformer(PercentCompleteInformer informer) {
99  			this.informer = informer;
100 			return this;
101 		}
102 
103 		@Override
104 		public CopyObjectToFileCallable build() {
105 			return validate(new CopyObjectToFileCallable(this));
106 		}
107 	}
108 
109 	public S3Service getS3() {
110 		return s3;
111 	}
112 
113 	public String getBucket() {
114 		return bucket;
115 	}
116 
117 	public PercentCompleteInformer getInformer() {
118 		return informer;
119 	}
120 
121 	public List<ObjectSummary> getObjects() {
122 		return objects;
123 	}
124 
125 	public Function<String, String> getKeyToPath() {
126 		return keyToPath;
127 	}
128 
129 }