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