View Javadoc
1   package org.kuali.common.devops.jenkins.upgrade;
2   
3   import static com.amazonaws.services.s3.Headers.CONTENT_TYPE;
4   import static com.google.common.base.Stopwatch.createStarted;
5   import static com.google.common.collect.Lists.newArrayList;
6   import static com.google.common.collect.Maps.newHashMap;
7   import static java.lang.String.format;
8   import static org.kuali.common.core.collect.Lists.shuffledCopy;
9   import static org.kuali.common.devops.archive.sweep.Functions.hostnameToKey;
10  import static org.kuali.common.devops.jenkins.upgrade.Jenkins.jenkinsContentType;
11  import static org.kuali.common.util.Encodings.UTF8;
12  import static org.kuali.common.util.log.Loggers.newLogger;
13  
14  import java.io.File;
15  import java.util.List;
16  import java.util.Map;
17  import java.util.concurrent.Callable;
18  
19  import org.kuali.common.aws.s3.S3Service;
20  import org.kuali.common.aws.s3.model.ObjectMetadata;
21  import org.kuali.common.aws.s3.model.PutFileRequest;
22  import org.kuali.common.core.base.TimedInterval;
23  import org.kuali.common.core.build.ValidatingBuilder;
24  import org.kuali.common.core.io.BasicFile;
25  import org.kuali.common.core.validate.annotation.IdiotProofImmutable;
26  import org.kuali.common.util.inform.PercentCompleteInformer;
27  import org.slf4j.Logger;
28  
29  import com.google.common.base.Function;
30  import com.google.common.base.Optional;
31  import com.google.common.base.Stopwatch;
32  import com.google.common.collect.ImmutableList;
33  
34  @IdiotProofImmutable
35  public final class BasicFileUploadCallable implements Callable<List<TimedInterval>> {
36  
37  	private static final Logger logger = newLogger();
38  
39  	private final S3Service s3;
40  	private final ImmutableList<BasicFile> files;
41  	private final String hostname;
42  	private final String bucket;
43  	private final PercentCompleteInformer informer;
44  	private final Function<BasicFile, Double> weigher;
45  	// TODO Pass this in instead of hard coding it here
46  	private final Function<BasicFile, Optional<String>> contentType = jenkinsContentType();
47  
48  	@Override
49  	public List<TimedInterval> call() {
50  		String prefix = hostnameToKey().apply(hostname);
51  		List<TimedInterval> timings = newArrayList();
52  		List<BasicFile> shuffled = shuffledCopy(files);
53  		for (BasicFile file : shuffled) {
54  			Stopwatch sw = createStarted();
55  			String s3Key = prefix + file.getPath();
56  			try {
57  				PutFileRequest request = getPutFileRequest(file, s3Key);
58  				s3.putFile(request);
59  			} catch (Exception e) {
60  				logger.info(format("error -> %s", e));
61  			}
62  			TimedInterval timing = TimedInterval.build(sw);
63  			timings.add(timing);
64  			long progress = weigher.apply(file).longValue();
65  			informer.incrementProgress(progress);
66  		}
67  		return timings;
68  	}
69  
70  	private PutFileRequest getPutFileRequest(BasicFile file, String s3Key) {
71  		PutFileRequest.Builder builder = PutFileRequest.builder().withBucket(bucket).withEncoding(UTF8).withFile(new File(file.getPath())).withKey(s3Key);
72  		Optional<String> contentType = this.contentType.apply(file);
73  		if (contentType.isPresent()) {
74  			Map<String, Object> raw = newHashMap();
75  			raw.put(CONTENT_TYPE, contentType.get());
76  			ObjectMetadata meta = ObjectMetadata.builder().withRawMetadata(raw).build();
77  			builder.withMetadata(meta);
78  		}
79  		return builder.build();
80  	}
81  
82  	private BasicFileUploadCallable(Builder builder) {
83  		this.s3 = builder.s3;
84  		this.files = ImmutableList.copyOf(builder.files);
85  		this.hostname = builder.hostname;
86  		this.bucket = builder.bucket;
87  		this.informer = builder.informer;
88  		this.weigher = builder.weigher;
89  	}
90  
91  	public static Builder builder() {
92  		return new Builder();
93  	}
94  
95  	public static class Builder extends ValidatingBuilder<BasicFileUploadCallable> {
96  
97  		private S3Service s3;
98  		private List<BasicFile> files;
99  		private String hostname;
100 		private String bucket;
101 		private PercentCompleteInformer informer;
102 		private Function<BasicFile, Double> weigher;
103 
104 		public Builder withWeigher(Function<BasicFile, Double> weigher) {
105 			this.weigher = weigher;
106 			return this;
107 		}
108 
109 		public Builder withS3(S3Service s3) {
110 			this.s3 = s3;
111 			return this;
112 		}
113 
114 		public Builder withFiles(List<BasicFile> files) {
115 			this.files = files;
116 			return this;
117 		}
118 
119 		public Builder withHostname(String hostname) {
120 			this.hostname = hostname;
121 			return this;
122 		}
123 
124 		public Builder withBucket(String bucket) {
125 			this.bucket = bucket;
126 			return this;
127 		}
128 
129 		public Builder withInformer(PercentCompleteInformer informer) {
130 			this.informer = informer;
131 			return this;
132 		}
133 
134 		@Override
135 		public BasicFileUploadCallable build() {
136 			return validate(new BasicFileUploadCallable(this));
137 		}
138 	}
139 
140 	public S3Service getS3() {
141 		return s3;
142 	}
143 
144 	public List<BasicFile> getFiles() {
145 		return files;
146 	}
147 
148 	public String getHostname() {
149 		return hostname;
150 	}
151 
152 	public String getBucket() {
153 		return bucket;
154 	}
155 
156 	public PercentCompleteInformer getInformer() {
157 		return informer;
158 	}
159 
160 	public Function<BasicFile, Double> getWeigher() {
161 		return weigher;
162 	}
163 
164 }