001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.maven.resolver.examples.util; 020 021import java.io.PrintStream; 022import java.text.DecimalFormat; 023import java.text.DecimalFormatSymbols; 024import java.util.Locale; 025import java.util.Map; 026import java.util.concurrent.ConcurrentHashMap; 027 028import org.eclipse.aether.transfer.AbstractTransferListener; 029import org.eclipse.aether.transfer.MetadataNotFoundException; 030import org.eclipse.aether.transfer.TransferEvent; 031import org.eclipse.aether.transfer.TransferResource; 032 033import static java.util.Objects.requireNonNull; 034 035/** 036 * A simplistic transfer listener that logs uploads/downloads to the console. 037 */ 038public class ConsoleTransferListener extends AbstractTransferListener { 039 040 private final PrintStream out; 041 042 private final Map<TransferResource, Long> downloads = new ConcurrentHashMap<>(); 043 044 private int lastLength; 045 046 public ConsoleTransferListener() { 047 this(null); 048 } 049 050 public ConsoleTransferListener(PrintStream out) { 051 this.out = (out != null) ? out : System.out; 052 } 053 054 @Override 055 public void transferInitiated(TransferEvent event) { 056 requireNonNull(event, "event cannot be null"); 057 String message = event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploading" : "Downloading"; 058 059 out.println(message + ": " + event.getResource().getRepositoryUrl() 060 + event.getResource().getResourceName()); 061 } 062 063 @Override 064 public void transferProgressed(TransferEvent event) { 065 requireNonNull(event, "event cannot be null"); 066 TransferResource resource = event.getResource(); 067 downloads.put(resource, event.getTransferredBytes()); 068 069 StringBuilder buffer = new StringBuilder(64); 070 071 for (Map.Entry<TransferResource, Long> entry : downloads.entrySet()) { 072 long total = entry.getKey().getContentLength(); 073 long complete = entry.getValue(); 074 075 buffer.append(getStatus(complete, total)).append(" "); 076 } 077 078 int pad = lastLength - buffer.length(); 079 lastLength = buffer.length(); 080 pad(buffer, pad); 081 buffer.append('\r'); 082 083 out.print(buffer); 084 } 085 086 private String getStatus(long complete, long total) { 087 if (total >= 1024) { 088 return toKB(complete) + "/" + toKB(total) + " KB "; 089 } else if (total >= 0) { 090 return complete + "/" + total + " B "; 091 } else if (complete >= 1024) { 092 return toKB(complete) + " KB "; 093 } else { 094 return complete + " B "; 095 } 096 } 097 098 private void pad(StringBuilder buffer, int spaces) { 099 String block = " "; 100 while (spaces > 0) { 101 int n = Math.min(spaces, block.length()); 102 buffer.append(block, 0, n); 103 spaces -= n; 104 } 105 } 106 107 @Override 108 public void transferSucceeded(TransferEvent event) { 109 requireNonNull(event, "event cannot be null"); 110 transferCompleted(event); 111 112 TransferResource resource = event.getResource(); 113 long contentLength = event.getTransferredBytes(); 114 if (contentLength >= 0) { 115 String type = (event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploaded" : "Downloaded"); 116 String len = contentLength >= 1024 ? toKB(contentLength) + " KB" : contentLength + " B"; 117 118 String throughput = ""; 119 long duration = System.currentTimeMillis() - resource.getTransferStartTime(); 120 if (duration > 0) { 121 long bytes = contentLength - resource.getResumeOffset(); 122 DecimalFormat format = new DecimalFormat("0.0", new DecimalFormatSymbols(Locale.ENGLISH)); 123 double kbPerSec = (bytes / 1024.0) / (duration / 1000.0); 124 throughput = " at " + format.format(kbPerSec) + " KB/sec"; 125 } 126 127 out.println(type + ": " + resource.getRepositoryUrl() + resource.getResourceName() + " (" + len + throughput 128 + ")"); 129 } 130 } 131 132 @Override 133 public void transferFailed(TransferEvent event) { 134 requireNonNull(event, "event cannot be null"); 135 transferCompleted(event); 136 137 if (!(event.getException() instanceof MetadataNotFoundException)) { 138 event.getException().printStackTrace(out); 139 } 140 } 141 142 private void transferCompleted(TransferEvent event) { 143 requireNonNull(event, "event cannot be null"); 144 downloads.remove(event.getResource()); 145 146 StringBuilder buffer = new StringBuilder(64); 147 pad(buffer, lastLength); 148 buffer.append('\r'); 149 out.print(buffer); 150 } 151 152 public void transferCorrupted(TransferEvent event) { 153 requireNonNull(event, "event cannot be null"); 154 event.getException().printStackTrace(out); 155 } 156 157 @SuppressWarnings("checkstyle:magicnumber") 158 protected long toKB(long bytes) { 159 return (bytes + 1023) / 1024; 160 } 161}