001package org.eclipse.aether.util.listener; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.Arrays; 023import java.util.Collection; 024import java.util.List; 025import java.util.concurrent.CopyOnWriteArrayList; 026 027import org.eclipse.aether.AbstractRepositoryListener; 028import org.eclipse.aether.RepositoryEvent; 029import org.eclipse.aether.RepositoryListener; 030 031import static java.util.Objects.requireNonNull; 032 033/** 034 * A repository listener that delegates to zero or more other listeners (multicast). The list of target listeners is 035 * thread-safe, i.e. target listeners can be added or removed by any thread at any time. 036 */ 037public final class ChainedRepositoryListener 038 extends AbstractRepositoryListener 039{ 040 041 private final List<RepositoryListener> listeners = new CopyOnWriteArrayList<>(); 042 043 /** 044 * Creates a new multicast listener that delegates to the specified listeners. In contrast to the constructor, this 045 * factory method will avoid creating an actual chained listener if one of the specified readers is actually 046 * {@code null}. 047 * 048 * @param listener1 The first listener, may be {@code null}. 049 * @param listener2 The second listener, may be {@code null}. 050 * @return The chained listener or {@code null} if no listener was supplied. 051 */ 052 public static RepositoryListener newInstance( RepositoryListener listener1, RepositoryListener listener2 ) 053 { 054 if ( listener1 == null ) 055 { 056 return listener2; 057 } 058 else if ( listener2 == null ) 059 { 060 return listener1; 061 } 062 return new ChainedRepositoryListener( listener1, listener2 ); 063 } 064 065 /** 066 * Creates a new multicast listener that delegates to the specified listeners. 067 * 068 * @param listeners The listeners to delegate to, may be {@code null} or empty. 069 */ 070 public ChainedRepositoryListener( RepositoryListener... listeners ) 071 { 072 if ( listeners != null ) 073 { 074 add( Arrays.asList( listeners ) ); 075 } 076 } 077 078 /** 079 * Creates a new multicast listener that delegates to the specified listeners. 080 * 081 * @param listeners The listeners to delegate to, may be {@code null} or empty. 082 */ 083 public ChainedRepositoryListener( Collection<? extends RepositoryListener> listeners ) 084 { 085 add( listeners ); 086 } 087 088 /** 089 * Adds the specified listeners to the end of the multicast chain. 090 * 091 * @param listeners The listeners to add, may be {@code null} or empty. 092 */ 093 public void add( Collection<? extends RepositoryListener> listeners ) 094 { 095 if ( listeners != null ) 096 { 097 for ( RepositoryListener listener : listeners ) 098 { 099 add( listener ); 100 } 101 } 102 } 103 104 /** 105 * Adds the specified listener to the end of the multicast chain. 106 * 107 * @param listener The listener to add, may be {@code null}. 108 */ 109 public void add( RepositoryListener listener ) 110 { 111 if ( listener != null ) 112 { 113 listeners.add( listener ); 114 } 115 } 116 117 /** 118 * Removes the specified listener from the multicast chain. Trying to remove a non-existing listener has no effect. 119 * 120 * @param listener The listener to remove, may be {@code null}. 121 */ 122 public void remove( RepositoryListener listener ) 123 { 124 if ( listener != null ) 125 { 126 listeners.remove( listener ); 127 } 128 } 129 130 @SuppressWarnings( "EmptyMethod" ) 131 protected void handleError( RepositoryEvent event, RepositoryListener listener, RuntimeException error ) 132 { 133 // default just swallows errors 134 } 135 136 @Override 137 public void artifactDeployed( RepositoryEvent event ) 138 { 139 requireNonNull( event, "event cannot be null" ); 140 for ( RepositoryListener listener : listeners ) 141 { 142 try 143 { 144 listener.artifactDeployed( event ); 145 } 146 catch ( RuntimeException e ) 147 { 148 handleError( event, listener, e ); 149 } 150 } 151 } 152 153 @Override 154 public void artifactDeploying( RepositoryEvent event ) 155 { 156 requireNonNull( event, "event cannot be null" ); 157 for ( RepositoryListener listener : listeners ) 158 { 159 try 160 { 161 listener.artifactDeploying( event ); 162 } 163 catch ( RuntimeException e ) 164 { 165 handleError( event, listener, e ); 166 } 167 } 168 } 169 170 @Override 171 public void artifactDescriptorInvalid( RepositoryEvent event ) 172 { 173 requireNonNull( event, "event cannot be null" ); 174 for ( RepositoryListener listener : listeners ) 175 { 176 try 177 { 178 listener.artifactDescriptorInvalid( event ); 179 } 180 catch ( RuntimeException e ) 181 { 182 handleError( event, listener, e ); 183 } 184 } 185 } 186 187 @Override 188 public void artifactDescriptorMissing( RepositoryEvent event ) 189 { 190 requireNonNull( event, "event cannot be null" ); 191 for ( RepositoryListener listener : listeners ) 192 { 193 try 194 { 195 listener.artifactDescriptorMissing( event ); 196 } 197 catch ( RuntimeException e ) 198 { 199 handleError( event, listener, e ); 200 } 201 } 202 } 203 204 @Override 205 public void artifactDownloaded( RepositoryEvent event ) 206 { 207 requireNonNull( event, "event cannot be null" ); 208 for ( RepositoryListener listener : listeners ) 209 { 210 try 211 { 212 listener.artifactDownloaded( event ); 213 } 214 catch ( RuntimeException e ) 215 { 216 handleError( event, listener, e ); 217 } 218 } 219 } 220 221 @Override 222 public void artifactDownloading( RepositoryEvent event ) 223 { 224 requireNonNull( event, "event cannot be null" ); 225 for ( RepositoryListener listener : listeners ) 226 { 227 try 228 { 229 listener.artifactDownloading( event ); 230 } 231 catch ( RuntimeException e ) 232 { 233 handleError( event, listener, e ); 234 } 235 } 236 } 237 238 @Override 239 public void artifactInstalled( RepositoryEvent event ) 240 { 241 requireNonNull( event, "event cannot be null" ); 242 for ( RepositoryListener listener : listeners ) 243 { 244 try 245 { 246 listener.artifactInstalled( event ); 247 } 248 catch ( RuntimeException e ) 249 { 250 handleError( event, listener, e ); 251 } 252 } 253 } 254 255 @Override 256 public void artifactInstalling( RepositoryEvent event ) 257 { 258 requireNonNull( event, "event cannot be null" ); 259 for ( RepositoryListener listener : listeners ) 260 { 261 try 262 { 263 listener.artifactInstalling( event ); 264 } 265 catch ( RuntimeException e ) 266 { 267 handleError( event, listener, e ); 268 } 269 } 270 } 271 272 @Override 273 public void artifactResolved( RepositoryEvent event ) 274 { 275 requireNonNull( event, "event cannot be null" ); 276 for ( RepositoryListener listener : listeners ) 277 { 278 try 279 { 280 listener.artifactResolved( event ); 281 } 282 catch ( RuntimeException e ) 283 { 284 handleError( event, listener, e ); 285 } 286 } 287 } 288 289 @Override 290 public void artifactResolving( RepositoryEvent event ) 291 { 292 requireNonNull( event, "event cannot be null" ); 293 for ( RepositoryListener listener : listeners ) 294 { 295 try 296 { 297 listener.artifactResolving( event ); 298 } 299 catch ( RuntimeException e ) 300 { 301 handleError( event, listener, e ); 302 } 303 } 304 } 305 306 @Override 307 public void metadataDeployed( RepositoryEvent event ) 308 { 309 requireNonNull( event, "event cannot be null" ); 310 for ( RepositoryListener listener : listeners ) 311 { 312 try 313 { 314 listener.metadataDeployed( event ); 315 } 316 catch ( RuntimeException e ) 317 { 318 handleError( event, listener, e ); 319 } 320 } 321 } 322 323 @Override 324 public void metadataDeploying( RepositoryEvent event ) 325 { 326 requireNonNull( event, "event cannot be null" ); 327 for ( RepositoryListener listener : listeners ) 328 { 329 try 330 { 331 listener.metadataDeploying( event ); 332 } 333 catch ( RuntimeException e ) 334 { 335 handleError( event, listener, e ); 336 } 337 } 338 } 339 340 @Override 341 public void metadataDownloaded( RepositoryEvent event ) 342 { 343 requireNonNull( event, "event cannot be null" ); 344 for ( RepositoryListener listener : listeners ) 345 { 346 try 347 { 348 listener.metadataDownloaded( event ); 349 } 350 catch ( RuntimeException e ) 351 { 352 handleError( event, listener, e ); 353 } 354 } 355 } 356 357 @Override 358 public void metadataDownloading( RepositoryEvent event ) 359 { 360 requireNonNull( event, "event cannot be null" ); 361 for ( RepositoryListener listener : listeners ) 362 { 363 try 364 { 365 listener.metadataDownloading( event ); 366 } 367 catch ( RuntimeException e ) 368 { 369 handleError( event, listener, e ); 370 } 371 } 372 } 373 374 @Override 375 public void metadataInstalled( RepositoryEvent event ) 376 { 377 requireNonNull( event, "event cannot be null" ); 378 for ( RepositoryListener listener : listeners ) 379 { 380 try 381 { 382 listener.metadataInstalled( event ); 383 } 384 catch ( RuntimeException e ) 385 { 386 handleError( event, listener, e ); 387 } 388 } 389 } 390 391 @Override 392 public void metadataInstalling( RepositoryEvent event ) 393 { 394 requireNonNull( event, "event cannot be null" ); 395 for ( RepositoryListener listener : listeners ) 396 { 397 try 398 { 399 listener.metadataInstalling( event ); 400 } 401 catch ( RuntimeException e ) 402 { 403 handleError( event, listener, e ); 404 } 405 } 406 } 407 408 @Override 409 public void metadataInvalid( RepositoryEvent event ) 410 { 411 requireNonNull( event, "event cannot be null" ); 412 for ( RepositoryListener listener : listeners ) 413 { 414 try 415 { 416 listener.metadataInvalid( event ); 417 } 418 catch ( RuntimeException e ) 419 { 420 handleError( event, listener, e ); 421 } 422 } 423 } 424 425 @Override 426 public void metadataResolved( RepositoryEvent event ) 427 { 428 requireNonNull( event, "event cannot be null" ); 429 for ( RepositoryListener listener : listeners ) 430 { 431 try 432 { 433 listener.metadataResolved( event ); 434 } 435 catch ( RuntimeException e ) 436 { 437 handleError( event, listener, e ); 438 } 439 } 440 } 441 442 @Override 443 public void metadataResolving( RepositoryEvent event ) 444 { 445 requireNonNull( event, "event cannot be null" ); 446 for ( RepositoryListener listener : listeners ) 447 { 448 try 449 { 450 listener.metadataResolving( event ); 451 } 452 catch ( RuntimeException e ) 453 { 454 handleError( event, listener, e ); 455 } 456 } 457 } 458 459}