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.shared.utils.logging.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 public String format(long size, ScaleUnit unit, boolean omitSymbol) {
140 if (size < 0L) {
141 throw new IllegalArgumentException("file size cannot be negative: " + size);
142 }
143
144 if (unit == null) {
145 unit = ScaleUnit.getScaleUnit(size);
146 }
147
148 double scaledSize = (double) size / unit.bytes();
149 String scaledSymbol = " " + unit.symbol();
150
151 if (omitSymbol) {
152 scaledSymbol = "";
153 }
154
155 if (unit == ScaleUnit.BYTE) {
156 return largeFormat.format(size) + scaledSymbol;
157 }
158
159 if (scaledSize < 0.05 || scaledSize >= 10.0) {
160 return largeFormat.format(scaledSize) + scaledSymbol;
161 } else {
162 return smallFormat.format(scaledSize) + scaledSymbol;
163 }
164 }
165
166 public String formatProgress(long progressedSize, long size) {
167 if (progressedSize < 0L) {
168 throw new IllegalArgumentException("progressed file size cannot be negative: " + progressedSize);
169 }
170 if (size >= 0L && progressedSize > size) {
171 throw new IllegalArgumentException(
172 "progressed file size cannot be greater than size: " + progressedSize + " > " + size);
173 }
174
175 if (size >= 0L && progressedSize != size) {
176 ScaleUnit unit = ScaleUnit.getScaleUnit(size);
177 String formattedProgressedSize = format(progressedSize, unit, true);
178 String formattedSize = format(size, unit);
179
180 return formattedProgressedSize + "/" + formattedSize;
181 } else {
182 return format(progressedSize);
183 }
184 }
185 }
186
187 protected PrintStream out;
188
189 protected AbstractMavenTransferListener(PrintStream out) {
190 this.out = out;
191 }
192
193 @Override
194 public void transferInitiated(TransferEvent event) {
195 String darkOn = MessageUtils.isColorEnabled() ? ANSI_DARK_SET : "";
196 String darkOff = MessageUtils.isColorEnabled() ? ANSI_DARK_RESET : "";
197
198 String action = event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploading" : "Downloading";
199 String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
200
201 TransferResource resource = event.getResource();
202 StringBuilder message = new StringBuilder();
203 message.append(darkOn).append(action).append(' ').append(direction).append(' ');
204 message.append(darkOff).append(resource.getRepositoryId());
205 message.append(darkOn).append(": ").append(resource.getRepositoryUrl());
206 message.append(darkOff).append(resource.getResourceName());
207
208 out.println(message.toString());
209 }
210
211 @Override
212 public void transferCorrupted(TransferEvent event) throws TransferCancelledException {
213 TransferResource resource = event.getResource();
214
215 out.println("[WARNING] " + event.getException().getMessage() + " from " + resource.getRepositoryId() + " for "
216 + resource.getRepositoryUrl() + resource.getResourceName());
217 }
218
219 @Override
220 public void transferSucceeded(TransferEvent event) {
221 String darkOn = MessageUtils.isColorEnabled() ? ANSI_DARK_SET : "";
222 String darkOff = MessageUtils.isColorEnabled() ? ANSI_DARK_RESET : "";
223
224 String action = (event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploaded" : "Downloaded");
225 String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
226
227 TransferResource resource = event.getResource();
228 long contentLength = event.getTransferredBytes();
229 FileSizeFormat format = new FileSizeFormat(Locale.ENGLISH);
230
231 StringBuilder message = new StringBuilder();
232 message.append(action).append(darkOn).append(' ').append(direction).append(' ');
233 message.append(darkOff).append(resource.getRepositoryId());
234 message.append(darkOn).append(": ").append(resource.getRepositoryUrl());
235 message.append(darkOff).append(resource.getResourceName());
236 message.append(darkOn).append(" (").append(format.format(contentLength));
237
238 long duration = System.currentTimeMillis() - resource.getTransferStartTime();
239 if (duration > 0L) {
240 double bytesPerSecond = contentLength / (duration / 1000.0);
241 message.append(" at ").append(format.format((long) bytesPerSecond)).append("/s");
242 }
243
244 message.append(')').append(darkOff);
245 out.println(message.toString());
246 }
247 }