blob: 72bffc338cac58a96ba1dee7cd9a5e5e1082e6ce [file] [log] [blame]
package org.apache.maven.cli.transfer;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.PrintStream;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
import org.apache.commons.lang3.Validate;
import org.eclipse.aether.transfer.AbstractTransferListener;
import org.eclipse.aether.transfer.TransferCancelledException;
import org.eclipse.aether.transfer.TransferEvent;
import org.eclipse.aether.transfer.TransferResource;
/**
* AbstractMavenTransferListener
*/
public abstract class AbstractMavenTransferListener
extends AbstractTransferListener
{
// CHECKSTYLE_OFF: LineLength
/**
* Formats file size with the associated <a href="https://en.wikipedia.org/wiki/Metric_prefix">SI</a> prefix
* (GB, MB, kB) and using the patterns <code>#0.0</code> for numbers between 1 and 10
* and <code>###0</code> for numbers between 10 and 1000+ by default.
*
* @see <a href="https://en.wikipedia.org/wiki/Metric_prefix">https://en.wikipedia.org/wiki/Metric_prefix</a>
* @see <a href="https://en.wikipedia.org/wiki/Binary_prefix">https://en.wikipedia.org/wiki/Binary_prefix</a>
* @see <a
* href="https://en.wikipedia.org/wiki/Octet_%28computing%29">https://en.wikipedia.org/wiki/Octet_(computing)</a>
*/
// CHECKSTYLE_ON: LineLength
// TODO Move me to Maven Shared Utils
static class FileSizeFormat
{
enum ScaleUnit
{
BYTE
{
@Override
public long bytes()
{
return 1L;
}
@Override
public String symbol()
{
return "B";
}
},
KILOBYTE
{
@Override
public long bytes()
{
return 1000L;
}
@Override
public String symbol()
{
return "kB";
}
},
MEGABYTE
{
@Override
public long bytes()
{
return KILOBYTE.bytes() * KILOBYTE.bytes();
}
@Override
public String symbol()
{
return "MB";
}
},
GIGABYTE
{
@Override
public long bytes()
{
return MEGABYTE.bytes() * KILOBYTE.bytes();
};
@Override
public String symbol()
{
return "GB";
}
};
public abstract long bytes();
public abstract String symbol();
public static ScaleUnit getScaleUnit( long size )
{
Validate.isTrue( size >= 0L, "file size cannot be negative: %s", size );
if ( size >= GIGABYTE.bytes() )
{
return GIGABYTE;
}
else if ( size >= MEGABYTE.bytes() )
{
return MEGABYTE;
}
else if ( size >= KILOBYTE.bytes() )
{
return KILOBYTE;
}
else
{
return BYTE;
}
}
}
private DecimalFormat smallFormat;
private DecimalFormat largeFormat;
FileSizeFormat( Locale locale )
{
smallFormat = new DecimalFormat( "#0.0", new DecimalFormatSymbols( locale ) );
largeFormat = new DecimalFormat( "###0", new DecimalFormatSymbols( locale ) );
}
public String format( long size )
{
return format( size, null );
}
public String format( long size, ScaleUnit unit )
{
return format( size, unit, false );
}
@SuppressWarnings( "checkstyle:magicnumber" )
public String format( long size, ScaleUnit unit, boolean omitSymbol )
{
Validate.isTrue( size >= 0L, "file size cannot be negative: %s", size );
if ( unit == null )
{
unit = ScaleUnit.getScaleUnit( size );
}
double scaledSize = (double) size / unit.bytes();
String scaledSymbol = " " + unit.symbol();
if ( omitSymbol )
{
scaledSymbol = "";
}
if ( unit == ScaleUnit.BYTE )
{
return largeFormat.format( size ) + scaledSymbol;
}
if ( scaledSize < 0.05 || scaledSize >= 10.0 )
{
return largeFormat.format( scaledSize ) + scaledSymbol;
}
else
{
return smallFormat.format( scaledSize ) + scaledSymbol;
}
}
public String formatProgress( long progressedSize, long size )
{
Validate.isTrue( progressedSize >= 0L, "progressed file size cannot be negative: %s", progressedSize );
Validate.isTrue( size < 0L || progressedSize <= size,
"progressed file size cannot be greater than size: %s > %s", progressedSize, size );
if ( size >= 0L && progressedSize != size )
{
ScaleUnit unit = ScaleUnit.getScaleUnit( size );
String formattedProgressedSize = format( progressedSize, unit, true );
String formattedSize = format( size, unit );
return formattedProgressedSize + "/" + formattedSize;
}
else
{
return format( progressedSize );
}
}
}
protected PrintStream out;
protected AbstractMavenTransferListener( PrintStream out )
{
this.out = out;
}
@Override
public void transferInitiated( TransferEvent event )
{
String action = event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploading" : "Downloading";
String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
TransferResource resource = event.getResource();
StringBuilder message = new StringBuilder();
message.append( action ).append( ' ' ).append( direction ).append( ' ' ).append( resource.getRepositoryId() );
message.append( ": " );
message.append( resource.getRepositoryUrl() ).append( resource.getResourceName() );
out.println( message.toString() );
}
@Override
public void transferCorrupted( TransferEvent event )
throws TransferCancelledException
{
TransferResource resource = event.getResource();
// TODO This needs to be colorized
out.println( "[WARNING] " + event.getException().getMessage() + " from " + resource.getRepositoryId() + " for "
+ resource.getRepositoryUrl() + resource.getResourceName() );
}
@Override
public void transferSucceeded( TransferEvent event )
{
String action = ( event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploaded" : "Downloaded" );
String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
TransferResource resource = event.getResource();
long contentLength = event.getTransferredBytes();
FileSizeFormat format = new FileSizeFormat( Locale.ENGLISH );
StringBuilder message = new StringBuilder();
message.append( action ).append( ' ' ).append( direction ).append( ' ' ).append( resource.getRepositoryId() );
message.append( ": " );
message.append( resource.getRepositoryUrl() ).append( resource.getResourceName() );
message.append( " (" ).append( format.format( contentLength ) );
long duration = System.currentTimeMillis() - resource.getTransferStartTime();
if ( duration > 0L )
{
double bytesPerSecond = contentLength / ( duration / 1000.0 );
message.append( " at " ).append( format.format( (long) bytesPerSecond ) ).append( "/s" );
}
message.append( ')' );
out.println( message.toString() );
}
}