View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.util.listener;
20  
21  import java.util.Arrays;
22  import java.util.Collection;
23  import java.util.List;
24  import java.util.concurrent.CopyOnWriteArrayList;
25  
26  import org.eclipse.aether.AbstractRepositoryListener;
27  import org.eclipse.aether.RepositoryEvent;
28  import org.eclipse.aether.RepositoryListener;
29  
30  import static java.util.Objects.requireNonNull;
31  
32  /**
33   * A repository 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 class ChainedRepositoryListener extends AbstractRepositoryListener {
37  
38      private final List<RepositoryListener> listeners = new CopyOnWriteArrayList<>();
39  
40      /**
41       * Creates a new multicast listener that delegates to the specified listeners. In contrast to the constructor, this
42       * factory method will avoid creating an actual chained listener if one of the specified readers is actually
43       * {@code null}.
44       *
45       * @param listener1 The first listener, may be {@code null}.
46       * @param listener2 The second listener, may be {@code null}.
47       * @return The chained listener or {@code null} if no listener was supplied.
48       */
49      public static RepositoryListener newInstance(RepositoryListener listener1, RepositoryListener listener2) {
50          if (listener1 == null) {
51              return listener2;
52          } else if (listener2 == null) {
53              return listener1;
54          }
55          return new ChainedRepositoryListener(listener1, listener2);
56      }
57  
58      /**
59       * Creates a new multicast listener that delegates to the specified listeners.
60       *
61       * @param listeners The listeners to delegate to, may be {@code null} or empty.
62       */
63      public ChainedRepositoryListener(RepositoryListener... listeners) {
64          if (listeners != null) {
65              add(Arrays.asList(listeners));
66          }
67      }
68  
69      /**
70       * Creates a new multicast listener that delegates to the specified listeners.
71       *
72       * @param listeners The listeners to delegate to, may be {@code null} or empty.
73       */
74      public ChainedRepositoryListener(Collection<? extends RepositoryListener> listeners) {
75          add(listeners);
76      }
77  
78      /**
79       * Adds the specified listeners to the end of the multicast chain.
80       *
81       * @param listeners The listeners to add, may be {@code null} or empty.
82       */
83      public void add(Collection<? extends RepositoryListener> listeners) {
84          if (listeners != null) {
85              for (RepositoryListener listener : listeners) {
86                  add(listener);
87              }
88          }
89      }
90  
91      /**
92       * Adds the specified listener to the end of the multicast chain.
93       *
94       * @param listener The listener to add, may be {@code null}.
95       */
96      public void add(RepositoryListener listener) {
97          if (listener != null) {
98              listeners.add(listener);
99          }
100     }
101 
102     /**
103      * Removes the specified listener from the multicast chain. Trying to remove a non-existing listener has no effect.
104      *
105      * @param listener The listener to remove, may be {@code null}.
106      */
107     public void remove(RepositoryListener listener) {
108         if (listener != null) {
109             listeners.remove(listener);
110         }
111     }
112 
113     /**
114      * Invoked when any listener throws, by default is no op, extend if required.
115      */
116     @SuppressWarnings("EmptyMethod")
117     protected void handleError(RepositoryEvent event, RepositoryListener listener, RuntimeException error) {
118         // default just swallows errors
119     }
120 
121     @Override
122     public void artifactDeployed(RepositoryEvent event) {
123         requireNonNull(event, "event cannot be null");
124         for (RepositoryListener listener : listeners) {
125             try {
126                 listener.artifactDeployed(event);
127             } catch (RuntimeException e) {
128                 handleError(event, listener, e);
129             }
130         }
131     }
132 
133     @Override
134     public void artifactDeploying(RepositoryEvent event) {
135         requireNonNull(event, "event cannot be null");
136         for (RepositoryListener listener : listeners) {
137             try {
138                 listener.artifactDeploying(event);
139             } catch (RuntimeException e) {
140                 handleError(event, listener, e);
141             }
142         }
143     }
144 
145     @Override
146     public void artifactDescriptorInvalid(RepositoryEvent event) {
147         requireNonNull(event, "event cannot be null");
148         for (RepositoryListener listener : listeners) {
149             try {
150                 listener.artifactDescriptorInvalid(event);
151             } catch (RuntimeException e) {
152                 handleError(event, listener, e);
153             }
154         }
155     }
156 
157     @Override
158     public void artifactDescriptorMissing(RepositoryEvent event) {
159         requireNonNull(event, "event cannot be null");
160         for (RepositoryListener listener : listeners) {
161             try {
162                 listener.artifactDescriptorMissing(event);
163             } catch (RuntimeException e) {
164                 handleError(event, listener, e);
165             }
166         }
167     }
168 
169     @Override
170     public void artifactDownloaded(RepositoryEvent event) {
171         requireNonNull(event, "event cannot be null");
172         for (RepositoryListener listener : listeners) {
173             try {
174                 listener.artifactDownloaded(event);
175             } catch (RuntimeException e) {
176                 handleError(event, listener, e);
177             }
178         }
179     }
180 
181     @Override
182     public void artifactDownloading(RepositoryEvent event) {
183         requireNonNull(event, "event cannot be null");
184         for (RepositoryListener listener : listeners) {
185             try {
186                 listener.artifactDownloading(event);
187             } catch (RuntimeException e) {
188                 handleError(event, listener, e);
189             }
190         }
191     }
192 
193     @Override
194     public void artifactInstalled(RepositoryEvent event) {
195         requireNonNull(event, "event cannot be null");
196         for (RepositoryListener listener : listeners) {
197             try {
198                 listener.artifactInstalled(event);
199             } catch (RuntimeException e) {
200                 handleError(event, listener, e);
201             }
202         }
203     }
204 
205     @Override
206     public void artifactInstalling(RepositoryEvent event) {
207         requireNonNull(event, "event cannot be null");
208         for (RepositoryListener listener : listeners) {
209             try {
210                 listener.artifactInstalling(event);
211             } catch (RuntimeException e) {
212                 handleError(event, listener, e);
213             }
214         }
215     }
216 
217     @Override
218     public void artifactResolved(RepositoryEvent event) {
219         requireNonNull(event, "event cannot be null");
220         for (RepositoryListener listener : listeners) {
221             try {
222                 listener.artifactResolved(event);
223             } catch (RuntimeException e) {
224                 handleError(event, listener, e);
225             }
226         }
227     }
228 
229     @Override
230     public void artifactResolving(RepositoryEvent event) {
231         requireNonNull(event, "event cannot be null");
232         for (RepositoryListener listener : listeners) {
233             try {
234                 listener.artifactResolving(event);
235             } catch (RuntimeException e) {
236                 handleError(event, listener, e);
237             }
238         }
239     }
240 
241     @Override
242     public void metadataDeployed(RepositoryEvent event) {
243         requireNonNull(event, "event cannot be null");
244         for (RepositoryListener listener : listeners) {
245             try {
246                 listener.metadataDeployed(event);
247             } catch (RuntimeException e) {
248                 handleError(event, listener, e);
249             }
250         }
251     }
252 
253     @Override
254     public void metadataDeploying(RepositoryEvent event) {
255         requireNonNull(event, "event cannot be null");
256         for (RepositoryListener listener : listeners) {
257             try {
258                 listener.metadataDeploying(event);
259             } catch (RuntimeException e) {
260                 handleError(event, listener, e);
261             }
262         }
263     }
264 
265     @Override
266     public void metadataDownloaded(RepositoryEvent event) {
267         requireNonNull(event, "event cannot be null");
268         for (RepositoryListener listener : listeners) {
269             try {
270                 listener.metadataDownloaded(event);
271             } catch (RuntimeException e) {
272                 handleError(event, listener, e);
273             }
274         }
275     }
276 
277     @Override
278     public void metadataDownloading(RepositoryEvent event) {
279         requireNonNull(event, "event cannot be null");
280         for (RepositoryListener listener : listeners) {
281             try {
282                 listener.metadataDownloading(event);
283             } catch (RuntimeException e) {
284                 handleError(event, listener, e);
285             }
286         }
287     }
288 
289     @Override
290     public void metadataInstalled(RepositoryEvent event) {
291         requireNonNull(event, "event cannot be null");
292         for (RepositoryListener listener : listeners) {
293             try {
294                 listener.metadataInstalled(event);
295             } catch (RuntimeException e) {
296                 handleError(event, listener, e);
297             }
298         }
299     }
300 
301     @Override
302     public void metadataInstalling(RepositoryEvent event) {
303         requireNonNull(event, "event cannot be null");
304         for (RepositoryListener listener : listeners) {
305             try {
306                 listener.metadataInstalling(event);
307             } catch (RuntimeException e) {
308                 handleError(event, listener, e);
309             }
310         }
311     }
312 
313     @Override
314     public void metadataInvalid(RepositoryEvent event) {
315         requireNonNull(event, "event cannot be null");
316         for (RepositoryListener listener : listeners) {
317             try {
318                 listener.metadataInvalid(event);
319             } catch (RuntimeException e) {
320                 handleError(event, listener, e);
321             }
322         }
323     }
324 
325     @Override
326     public void metadataResolved(RepositoryEvent event) {
327         requireNonNull(event, "event cannot be null");
328         for (RepositoryListener listener : listeners) {
329             try {
330                 listener.metadataResolved(event);
331             } catch (RuntimeException e) {
332                 handleError(event, listener, e);
333             }
334         }
335     }
336 
337     @Override
338     public void metadataResolving(RepositoryEvent event) {
339         requireNonNull(event, "event cannot be null");
340         for (RepositoryListener listener : listeners) {
341             try {
342                 listener.metadataResolving(event);
343             } catch (RuntimeException e) {
344                 handleError(event, listener, e);
345             }
346         }
347     }
348 }