View Javadoc
1   package org.codehaus.mojo.wagon.shared;
2   
3   import static java.lang.String.format;
4   import static java.lang.System.currentTimeMillis;
5   import static org.apache.commons.io.FileUtils.touch;
6   import static org.apache.commons.lang3.StringUtils.leftPad;
7   import static org.kuali.common.util.FormatUtils.getCount;
8   import static org.kuali.common.util.FormatUtils.getRate;
9   import static org.kuali.common.util.FormatUtils.getSize;
10  import static org.kuali.common.util.FormatUtils.getTime;
11  import static org.kuali.common.util.base.Exceptions.illegalState;
12  import static org.kuali.common.util.log.Loggers.newLogger;
13  
14  import java.io.File;
15  import java.text.NumberFormat;
16  
17  import javax.validation.constraints.Min;
18  
19  import org.apache.maven.wagon.Wagon;
20  import org.kuali.common.core.build.ValidatingBuilder;
21  import org.kuali.common.core.validate.annotation.IdiotProofImmutable;
22  import org.kuali.common.util.Counter;
23  import org.kuali.common.util.LongCounter;
24  import org.kuali.common.util.execute.Executable;
25  import org.kuali.common.util.inform.Inform;
26  import org.kuali.common.util.inform.PercentCompleteInformer;
27  import org.slf4j.Logger;
28  
29  @IdiotProofImmutable
30  public final class WagonDownloadExecutable implements Executable {
31  
32  	private static final Logger logger = newLogger();
33  
34  	private final String remoteFile;
35  	private final File destination;
36  	private final Wagon wagon;
37  	private final Counter counter;
38  	private final LongCounter bytesCounter;
39  	@Min(0)
40  	private final int total;
41  	@Min(0)
42  	private final long start;
43  	private final NumberFormat numberFormatter;
44  	private final NumberFormat rateFormatter;
45  	private final PercentCompleteInformer informer;
46  
47  	@Override
48  	public void execute() {
49  		try {
50  			touch(destination);
51  			wagon.get(remoteFile, destination);
52  			counter.increment();
53  			if (useInformer()) {
54  				inform();
55  			} else {
56  				stats();
57  			}
58  		} catch (Exception e) {
59  			throw illegalState(e);
60  		}
61  	}
62  
63  	private void inform() {
64  		synchronized (informer) {
65  			informer.incrementProgress();
66  			if (informer.getProgress() % informer.getTotal() == 0) {
67  				Inform inform = informer.getInform();
68  				String msg = String.format(" - [%s of %s]%s%s", informer.getProgress(), total, inform.getCompleteToken(), inform.getStartToken());
69  				inform.getPrintStream().print(msg);
70  			}
71  		}
72  	}
73  
74  	private boolean useInformer() {
75  		return "warn".equalsIgnoreCase(System.getProperty("org.slf4j.simpleLogger.log.org.kuali.maven.wagon"));
76  	}
77  
78  	private void stats() {
79  		bytesCounter.increment(destination.length());
80  		int count = counter.getValue();
81  		long elapsed = currentTimeMillis() - start;
82  		String rate = getRate(elapsed, bytesCounter.getValue(), rateFormatter);
83  		// long millisPerFile = elapsed / count;
84  		int filesRemaining = total - count;
85  		// long timeRemaining = millisPerFile * filesRemaining;
86  		// int percent = new Double((count / (total * 1D)) * 100).intValue();
87  		String amount = lpad(getSize(bytesCounter.getValue(), numberFormatter), 6);
88  		Object[] args = { lpad(getCount(count), 6), lpad(getCount(total), 6), lpad(getCount(filesRemaining), 6), ltime(elapsed), lpad(rate, 8), amount };
89  		logger.info(format("%s of %s - remaining %s [elapsed:%s  rate:%s  downloaded:%s]", args));
90  	}
91  
92  	private String ltime(long millis) {
93  		return leftPad(getTime(millis, numberFormatter), 5, " ");
94  	}
95  
96  	private String lpad(Object object, int size) {
97  		return leftPad(object.toString(), size, " ");
98  	}
99  
100 	private WagonDownloadExecutable(Builder builder) {
101 		this.remoteFile = builder.remoteFile;
102 		this.destination = builder.destination;
103 		this.wagon = builder.wagon;
104 		this.counter = builder.counter;
105 		this.total = builder.total;
106 		this.start = builder.start;
107 		this.bytesCounter = builder.bytesCounter;
108 		this.numberFormatter = builder.numberFormatter;
109 		this.rateFormatter = builder.rateFormatter;
110 		this.informer = builder.informer;
111 	}
112 
113 	public static Builder builder() {
114 		return new Builder();
115 	}
116 
117 	public static class Builder extends ValidatingBuilder<WagonDownloadExecutable> {
118 
119 		private String remoteFile;
120 		private File destination;
121 		private Wagon wagon;
122 		private Counter counter;
123 		private int total;
124 		private long start;
125 		private LongCounter bytesCounter;
126 		private NumberFormat numberFormatter = getDefaultNumberFormatter();
127 		private NumberFormat rateFormatter = getDefaultRateFormatter();
128 		private PercentCompleteInformer informer;
129 
130 		public Builder withInformer(PercentCompleteInformer informer) {
131 			this.informer = informer;
132 			return this;
133 		}
134 
135 		public Builder withRateFormatter(NumberFormat rateFormatter) {
136 			this.rateFormatter = rateFormatter;
137 			return this;
138 		}
139 
140 		public Builder withNumberFormatter(NumberFormat numberFormatter) {
141 			this.numberFormatter = numberFormatter;
142 			return this;
143 		}
144 
145 		public Builder withBytesCounter(LongCounter bytesCounter) {
146 			this.bytesCounter = bytesCounter;
147 			return this;
148 		}
149 
150 		public Builder withStart(long start) {
151 			this.start = start;
152 			return this;
153 		}
154 
155 		public Builder withTotal(int total) {
156 			this.total = total;
157 			return this;
158 		}
159 
160 		public Builder withCounter(Counter counter) {
161 			this.counter = counter;
162 			return this;
163 		}
164 
165 		public Builder withRemoteFile(String remoteFile) {
166 			this.remoteFile = remoteFile;
167 			return this;
168 		}
169 
170 		public Builder withDestination(File destination) {
171 			this.destination = destination;
172 			return this;
173 		}
174 
175 		public Builder withWagon(Wagon wagon) {
176 			this.wagon = wagon;
177 			return this;
178 		}
179 
180 		@Override
181 		public WagonDownloadExecutable build() {
182 			return validate(new WagonDownloadExecutable(this));
183 		}
184 
185 		private NumberFormat getDefaultNumberFormatter() {
186 			NumberFormat nf = NumberFormat.getInstance();
187 			nf.setMaximumFractionDigits(1);
188 			nf.setMinimumFractionDigits(1);
189 			return nf;
190 		}
191 
192 		private NumberFormat getDefaultRateFormatter() {
193 			NumberFormat nf = NumberFormat.getInstance();
194 			nf.setMaximumFractionDigits(0);
195 			return nf;
196 		}
197 
198 	}
199 
200 	public String getRemoteFile() {
201 		return remoteFile;
202 	}
203 
204 	public File getDestination() {
205 		return destination;
206 	}
207 
208 	public Wagon getWagon() {
209 		return wagon;
210 	}
211 
212 	public Counter getCounter() {
213 		return counter;
214 	}
215 
216 	public int getTotal() {
217 		return total;
218 	}
219 
220 	public long getStart() {
221 		return start;
222 	}
223 
224 	public PercentCompleteInformer getInformer() {
225 		return informer;
226 	}
227 
228 	public LongCounter getBytesCounter() {
229 		return bytesCounter;
230 	}
231 
232 }