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 }