View Javadoc
1   package org.eclipse.aether.util.listener;
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.util.Arrays;
23  import java.util.Collection;
24  import java.util.List;
25  import java.util.concurrent.CopyOnWriteArrayList;
26  
27  import org.eclipse.aether.transfer.AbstractTransferListener;
28  import org.eclipse.aether.transfer.TransferCancelledException;
29  import org.eclipse.aether.transfer.TransferEvent;
30  import org.eclipse.aether.transfer.TransferListener;
31  
32  /**
33   * A transfer listener that delegates to zero or more other listeners (multicast). The list of target listeners is
34   * thread-safe, i.e. target listeners can be added or removed by any thread at any time.
35   */
36  public final class ChainedTransferListener
37      extends AbstractTransferListener
38  {
39  
40      private final List<TransferListener> listeners = new CopyOnWriteArrayList<>();
41  
42      /**
43       * Creates a new multicast listener that delegates to the specified listeners. In contrast to the constructor, this
44       * factory method will avoid creating an actual chained listener if one of the specified readers is actually
45       * {@code null}.
46       * 
47       * @param listener1 The first listener, may be {@code null}.
48       * @param listener2 The second listener, may be {@code null}.
49       * @return The chained listener or {@code null} if no listener was supplied.
50       */
51      public static TransferListener newInstance( TransferListener listener1, TransferListener listener2 )
52      {
53          if ( listener1 == null )
54          {
55              return listener2;
56          }
57          else if ( listener2 == null )
58          {
59              return listener1;
60          }
61          return new ChainedTransferListener( listener1, listener2 );
62      }
63  
64      /**
65       * Creates a new multicast listener that delegates to the specified listeners.
66       * 
67       * @param listeners The listeners to delegate to, may be {@code null} or empty.
68       */
69      public ChainedTransferListener( TransferListener... listeners )
70      {
71          if ( listeners != null )
72          {
73              add( Arrays.asList( listeners ) );
74          }
75      }
76  
77      /**
78       * Creates a new multicast listener that delegates to the specified listeners.
79       * 
80       * @param listeners The listeners to delegate to, may be {@code null} or empty.
81       */
82      public ChainedTransferListener( Collection<? extends TransferListener> listeners )
83      {
84          add( listeners );
85      }
86  
87      /**
88       * Adds the specified listeners to the end of the multicast chain.
89       * 
90       * @param listeners The listeners to add, may be {@code null} or empty.
91       */
92      public void add( Collection<? extends TransferListener> listeners )
93      {
94          if ( listeners != null )
95          {
96              for ( TransferListener listener : listeners )
97              {
98                  add( listener );
99              }
100         }
101     }
102 
103     /**
104      * Adds the specified listener to the end of the multicast chain.
105      * 
106      * @param listener The listener to add, may be {@code null}.
107      */
108     public void add( TransferListener listener )
109     {
110         if ( listener != null )
111         {
112             listeners.add( listener );
113         }
114     }
115 
116     /**
117      * Removes the specified listener from the multicast chain. Trying to remove a non-existing listener has no effect.
118      * 
119      * @param listener The listener to remove, may be {@code null}.
120      */
121     public void remove( TransferListener listener )
122     {
123         if ( listener != null )
124         {
125             listeners.remove( listener );
126         }
127     }
128 
129     @SuppressWarnings( "EmptyMethod" )
130     protected void handleError( TransferEvent event, TransferListener listener, RuntimeException error )
131     {
132         // default just swallows errors
133     }
134 
135     @Override
136     public void transferInitiated( TransferEvent event )
137         throws TransferCancelledException
138     {
139         for ( TransferListener listener : listeners )
140         {
141             try
142             {
143                 listener.transferInitiated( event );
144             }
145             catch ( RuntimeException e )
146             {
147                 handleError( event, listener, e );
148             }
149         }
150     }
151 
152     @Override
153     public void transferStarted( TransferEvent event )
154         throws TransferCancelledException
155     {
156         for ( TransferListener listener : listeners )
157         {
158             try
159             {
160                 listener.transferStarted( event );
161             }
162             catch ( RuntimeException e )
163             {
164                 handleError( event, listener, e );
165             }
166         }
167     }
168 
169     @Override
170     public void transferProgressed( TransferEvent event )
171         throws TransferCancelledException
172     {
173         for ( TransferListener listener : listeners )
174         {
175             try
176             {
177                 listener.transferProgressed( event );
178             }
179             catch ( RuntimeException e )
180             {
181                 handleError( event, listener, e );
182             }
183         }
184     }
185 
186     @Override
187     public void transferCorrupted( TransferEvent event )
188         throws TransferCancelledException
189     {
190         for ( TransferListener listener : listeners )
191         {
192             try
193             {
194                 listener.transferCorrupted( event );
195             }
196             catch ( RuntimeException e )
197             {
198                 handleError( event, listener, e );
199             }
200         }
201     }
202 
203     @Override
204     public void transferSucceeded( TransferEvent event )
205     {
206         for ( TransferListener listener : listeners )
207         {
208             try
209             {
210                 listener.transferSucceeded( event );
211             }
212             catch ( RuntimeException e )
213             {
214                 handleError( event, listener, e );
215             }
216         }
217     }
218 
219     @Override
220     public void transferFailed( TransferEvent event )
221     {
222         for ( TransferListener listener : listeners )
223         {
224             try
225             {
226                 listener.transferFailed( event );
227             }
228             catch ( RuntimeException e )
229             {
230                 handleError( event, listener, e );
231             }
232         }
233     }
234 
235 }