1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.cli.transfer;
20
21 import java.io.PrintStream;
22 import java.text.DecimalFormat;
23 import java.text.DecimalFormatSymbols;
24 import java.util.Locale;
25 import org.apache.commons.lang3.Validate;
26 import org.eclipse.aether.transfer.AbstractTransferListener;
27 import org.eclipse.aether.transfer.TransferCancelledException;
28 import org.eclipse.aether.transfer.TransferEvent;
29 import org.eclipse.aether.transfer.TransferResource;
30
31
32
33
34 public abstract class AbstractMavenTransferListener extends AbstractTransferListener {
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 static class FileSizeFormat {
50 enum ScaleUnit {
51 BYTE {
52 @Override
53 public long bytes() {
54 return 1L;
55 }
56
57 @Override
58 public String symbol() {
59 return "B";
60 }
61 },
62 KILOBYTE {
63 @Override
64 public long bytes() {
65 return 1000L;
66 }
67
68 @Override
69 public String symbol() {
70 return "kB";
71 }
72 },
73 MEGABYTE {
74 @Override
75 public long bytes() {
76 return KILOBYTE.bytes() * KILOBYTE.bytes();
77 }
78
79 @Override
80 public String symbol() {
81 return "MB";
82 }
83 },
84 GIGABYTE {
85 @Override
86 public long bytes() {
87 return MEGABYTE.bytes() * KILOBYTE.bytes();
88 }
89 ;
90
91 @Override
92 public String symbol() {
93 return "GB";
94 }
95 };
96
97 public abstract long bytes();
98
99 public abstract String symbol();
100
101 public static ScaleUnit getScaleUnit(long size) {
102 Validate.isTrue(size >= 0L, "file size cannot be negative: %s", size);
103
104 if (size >= GIGABYTE.bytes()) {
105 return GIGABYTE;
106 } else if (size >= MEGABYTE.bytes()) {
107 return MEGABYTE;
108 } else if (size >= KILOBYTE.bytes()) {
109 return KILOBYTE;
110 } else {
111 return BYTE;
112 }
113 }
114 }
115
116 private DecimalFormat smallFormat;
117 private DecimalFormat largeFormat;
118
119 FileSizeFormat(Locale locale) {
120 smallFormat = new DecimalFormat("#0.0", new DecimalFormatSymbols(locale));
121 largeFormat = new DecimalFormat("###0", new DecimalFormatSymbols(locale));
122 }
123
124 public String format(long size) {
125 return format(size, null);
126 }
127
128 public String format(long size, ScaleUnit unit) {
129 return format(size, unit, false);
130 }
131
132 @SuppressWarnings("checkstyle:magicnumber")
133 public String format(long size, ScaleUnit unit, boolean omitSymbol) {
134 Validate.isTrue(size >= 0L, "file size cannot be negative: %s", size);
135
136 if (unit == null) {
137 unit = ScaleUnit.getScaleUnit(size);
138 }
139
140 double scaledSize = (double) size / unit.bytes();
141 String scaledSymbol = " " + unit.symbol();
142
143 if (omitSymbol) {
144 scaledSymbol = "";
145 }
146
147 if (unit == ScaleUnit.BYTE) {
148 return largeFormat.format(size) + scaledSymbol;
149 }
150
151 if (scaledSize < 0.05 || scaledSize >= 10.0) {
152 return largeFormat.format(scaledSize) + scaledSymbol;
153 } else {
154 return smallFormat.format(scaledSize) + scaledSymbol;
155 }
156 }
157
158 public String formatProgress(long progressedSize, long size) {
159 Validate.isTrue(progressedSize >= 0L, "progressed file size cannot be negative: %s", progressedSize);
160 Validate.isTrue(
161 size < 0L || progressedSize <= size,
162 "progressed file size cannot be greater than size: %s > %s",
163 progressedSize,
164 size);
165
166 if (size >= 0L && progressedSize != size) {
167 ScaleUnit unit = ScaleUnit.getScaleUnit(size);
168 String formattedProgressedSize = format(progressedSize, unit, true);
169 String formattedSize = format(size, unit);
170
171 return formattedProgressedSize + "/" + formattedSize;
172 } else {
173 return format(progressedSize);
174 }
175 }
176 }
177
178 protected PrintStream out;
179
180 protected AbstractMavenTransferListener(PrintStream out) {
181 this.out = out;
182 }
183
184 @Override
185 public void transferInitiated(TransferEvent event) {
186 String action = event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploading" : "Downloading";
187 String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
188
189 TransferResource resource = event.getResource();
190 StringBuilder message = new StringBuilder();
191 message.append(action).append(' ').append(direction).append(' ').append(resource.getRepositoryId());
192 message.append(": ");
193 message.append(resource.getRepositoryUrl()).append(resource.getResourceName());
194
195 out.println(message.toString());
196 }
197
198 @Override
199 public void transferCorrupted(TransferEvent event) throws TransferCancelledException {
200 TransferResource resource = event.getResource();
201
202 out.println("[WARNING] " + event.getException().getMessage() + " from " + resource.getRepositoryId() + " for "
203 + resource.getRepositoryUrl() + resource.getResourceName());
204 }
205
206 @Override
207 public void transferSucceeded(TransferEvent event) {
208 String action = (event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploaded" : "Downloaded");
209 String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
210
211 TransferResource resource = event.getResource();
212 long contentLength = event.getTransferredBytes();
213 FileSizeFormat format = new FileSizeFormat(Locale.ENGLISH);
214
215 StringBuilder message = new StringBuilder();
216 message.append(action).append(' ').append(direction).append(' ').append(resource.getRepositoryId());
217 message.append(": ");
218 message.append(resource.getRepositoryUrl()).append(resource.getResourceName());
219 message.append(" (").append(format.format(contentLength));
220
221 long duration = System.currentTimeMillis() - resource.getTransferStartTime();
222 if (duration > 0L) {
223 double bytesPerSecond = contentLength / (duration / 1000.0);
224 message.append(" at ").append(format.format((long) bytesPerSecond)).append("/s");
225 }
226
227 message.append(')');
228 out.println(message.toString());
229 }
230 }