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.util.Collections;
23 import java.util.Iterator;
24 import java.util.LinkedHashMap;
25 import java.util.Locale;
26 import java.util.Map;
27
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
36
37 public class ConsoleMavenTransferListener extends AbstractMavenTransferListener {
38
39 private final Map<TransferResourceIdentifier, TransferResourceAndSize> transfers =
40 Collections.synchronizedMap(new LinkedHashMap<TransferResourceIdentifier, TransferResourceAndSize>());
41
42 private final boolean printResourceNames;
43 private int lastLength;
44
45 public ConsoleMavenTransferListener(PrintStream out, boolean printResourceNames) {
46 super(out);
47 this.printResourceNames = printResourceNames;
48 }
49
50 @Override
51 public void transferInitiated(TransferEvent event) {
52 overridePreviousTransfer(event);
53
54 super.transferInitiated(event);
55 }
56
57 @Override
58 public void transferCorrupted(TransferEvent event) throws TransferCancelledException {
59 overridePreviousTransfer(event);
60
61 super.transferCorrupted(event);
62 }
63
64 @Override
65 public void transferProgressed(TransferEvent event) throws TransferCancelledException {
66 TransferResource resource = event.getResource();
67 transfers.put(
68 new TransferResourceIdentifier(resource),
69 new TransferResourceAndSize(resource, event.getTransferredBytes()));
70
71 StringBuilder buffer = new StringBuilder(128);
72 buffer.append("Progress (").append(transfers.size()).append("): ");
73
74 synchronized (transfers) {
75 Iterator<TransferResourceAndSize> entries = transfers.values().iterator();
76 while (entries.hasNext()) {
77 TransferResourceAndSize entry = entries.next();
78 long total = entry.resource.getContentLength();
79 Long complete = entry.transferredBytes;
80 buffer.append(getStatus(entry.resource.getResourceName(), complete, total));
81 if (entries.hasNext()) {
82 buffer.append(" | ");
83 }
84 }
85 }
86
87 int pad = lastLength - buffer.length();
88 lastLength = buffer.length();
89 pad(buffer, pad);
90 buffer.append('\r');
91 out.print(buffer);
92 out.flush();
93 }
94
95 private String getStatus(String resourceName, long complete, long total) {
96 FileSizeFormat format = new FileSizeFormat(Locale.ENGLISH);
97 StringBuilder status = new StringBuilder();
98
99 if (printResourceNames) {
100 status.append(resourceName(resourceName));
101 status.append(" (");
102 }
103
104 status.append(format.formatProgress(complete, total));
105
106 if (printResourceNames) {
107 status.append(")");
108 }
109
110 return status.toString();
111 }
112
113 private String resourceName(String resourceName) {
114 if (resourceName == null || resourceName.trim().isEmpty()) {
115 return "";
116 }
117 final int pos = resourceName.lastIndexOf("/");
118 if (pos == -1 || pos == resourceName.length() - 1) {
119 return "";
120 }
121 return resourceName.substring(pos + 1);
122 }
123
124 private void pad(StringBuilder buffer, int spaces) {
125 String block = " ";
126 while (spaces > 0) {
127 int n = Math.min(spaces, block.length());
128 buffer.append(block, 0, n);
129 spaces -= n;
130 }
131 }
132
133 @Override
134 public void transferSucceeded(TransferEvent event) {
135 transfers.remove(new TransferResourceIdentifier(event.getResource()));
136 overridePreviousTransfer(event);
137
138 super.transferSucceeded(event);
139 }
140
141 @Override
142 public void transferFailed(TransferEvent event) {
143 transfers.remove(new TransferResourceIdentifier(event.getResource()));
144 overridePreviousTransfer(event);
145
146 super.transferFailed(event);
147 }
148
149 private void overridePreviousTransfer(TransferEvent event) {
150 if (lastLength > 0) {
151 StringBuilder buffer = new StringBuilder(128);
152 pad(buffer, lastLength);
153 buffer.append('\r');
154 out.print(buffer);
155 out.flush();
156 lastLength = 0;
157 }
158 }
159
160 private final class TransferResourceAndSize {
161
162 private final TransferResource resource;
163 private final long transferredBytes;
164
165 private TransferResourceAndSize(TransferResource resource, long transferredBytes) {
166 this.resource = resource;
167 this.transferredBytes = transferredBytes;
168 }
169 }
170 }