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