View Javadoc
1   package org.apache.maven.cli.transfer;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.PrintStream;
23  import java.util.Collections;
24  import java.util.Iterator;
25  import java.util.LinkedHashMap;
26  import java.util.Locale;
27  import java.util.Map;
28  
29  import org.apache.commons.lang3.StringUtils;
30  import org.eclipse.aether.transfer.TransferCancelledException;
31  import org.eclipse.aether.transfer.TransferEvent;
32  import org.eclipse.aether.transfer.TransferResource;
33  
34  /**
35   * Console download progress meter.
36   *
37   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
38   */
39  public class ConsoleMavenTransferListener
40      extends AbstractMavenTransferListener
41  {
42  
43      private Map<TransferResource, Long> transfers = Collections.synchronizedMap(
44                                                          new LinkedHashMap<TransferResource, Long>() );
45  
46      private boolean printResourceNames;
47      private int lastLength;
48  
49      public ConsoleMavenTransferListener( PrintStream out, boolean printResourceNames )
50      {
51          super( out );
52          this.printResourceNames = printResourceNames;
53      }
54  
55      @Override
56      public synchronized void transferInitiated( TransferEvent event )
57      {
58          overridePreviousTransfer( event );
59  
60          super.transferInitiated( event );
61      }
62  
63      @Override
64      public synchronized void transferCorrupted( TransferEvent event )
65          throws TransferCancelledException
66      {
67          overridePreviousTransfer( event );
68  
69          super.transferCorrupted( event );
70      }
71  
72      @Override
73      public synchronized void transferProgressed( TransferEvent event )
74          throws TransferCancelledException
75      {
76          TransferResource resource = event.getResource();
77          transfers.put( resource, event.getTransferredBytes() );
78  
79          StringBuilder buffer = new StringBuilder( 128 );
80          buffer.append( "Progress (" ).append(  transfers.size() ).append( "): " );
81  
82          synchronized ( transfers )
83          {
84              Iterator<Map.Entry<TransferResource, Long>> entries = transfers.entrySet().iterator();
85              while ( entries.hasNext() )
86              {
87                  Map.Entry<TransferResource, Long> entry = entries.next();
88                  long total = entry.getKey().getContentLength();
89                  Long complete = entry.getValue();
90                  buffer.append( getStatus( entry.getKey().getResourceName(), complete, total ) );
91                  if ( entries.hasNext() )
92                  {
93                      buffer.append( " | " );
94                  }
95              }
96          }
97  
98          int pad = lastLength - buffer.length();
99          lastLength = buffer.length();
100         pad( buffer, pad );
101         buffer.append( '\r' );
102         out.print( buffer );
103         out.flush();
104     }
105 
106     private String getStatus( String resourceName, long complete, long total )
107     {
108         FileSizeFormat format = new FileSizeFormat( Locale.ENGLISH );
109         StringBuilder status = new StringBuilder();
110 
111         if ( printResourceNames )
112         {
113             status.append( StringUtils.substringAfterLast( resourceName,  "/" ) );
114             status.append( " (" );
115         }
116 
117         status.append( format.formatProgress( complete, total ) );
118 
119         if ( printResourceNames )
120         {
121             status.append( ")" );
122         }
123 
124         return status.toString();
125     }
126 
127     private void pad( StringBuilder buffer, int spaces )
128     {
129         String block = "                                        ";
130         while ( spaces > 0 )
131         {
132             int n = Math.min( spaces, block.length() );
133             buffer.append( block, 0, n );
134             spaces -= n;
135         }
136     }
137 
138     @Override
139     public synchronized void transferSucceeded( TransferEvent event )
140     {
141         transfers.remove( event.getResource() );
142         overridePreviousTransfer( event );
143 
144         super.transferSucceeded( event );
145     }
146 
147     @Override
148     public synchronized void transferFailed( TransferEvent event )
149     {
150         transfers.remove( event.getResource() );
151         overridePreviousTransfer( event );
152 
153         super.transferFailed( event );
154     }
155 
156     private void overridePreviousTransfer( TransferEvent event )
157     {
158         if ( lastLength > 0 )
159         {
160             StringBuilder buffer = new StringBuilder( 128 );
161             pad( buffer, lastLength );
162             buffer.append( '\r' );
163             out.print( buffer );
164             out.flush();
165             lastLength = 0;
166         }
167     }
168 
169 }