Coverage Summary for Class: CompositeEthereumListener (org.ethereum.listener)

Class Class, % Method, % Line, %
CompositeEthereumListener 100% (1/1) 31.6% (6/19) 27.3% (12/44)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2017 RSK Labs Ltd. 4  * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>) 5  * 6  * This program is free software: you can redistribute it and/or modify 7  * it under the terms of the GNU Lesser General Public License as published by 8  * the Free Software Foundation, either version 3 of the License, or 9  * (at your option) any later version. 10  * 11  * This program is distributed in the hope that it will be useful, 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14  * GNU Lesser General Public License for more details. 15  * 16  * You should have received a copy of the GNU Lesser General Public License 17  * along with this program. If not, see <http://www.gnu.org/licenses/>. 18  */ 19  20 package org.ethereum.listener; 21  22 import co.rsk.panic.PanicProcessor; 23 import org.ethereum.core.Block; 24 import org.ethereum.core.Transaction; 25 import org.ethereum.core.TransactionPool; 26 import org.ethereum.core.TransactionReceipt; 27 import org.ethereum.net.eth.message.StatusMessage; 28 import org.ethereum.net.message.Message; 29 import org.ethereum.net.p2p.HelloMessage; 30 import org.ethereum.net.rlpx.Node; 31 import org.ethereum.net.server.Channel; 32 import org.slf4j.Logger; 33 import org.slf4j.LoggerFactory; 34  35 import java.util.List; 36 import java.util.concurrent.CopyOnWriteArrayList; 37 import java.util.function.Consumer; 38  39 /** 40  * @author Roman Mandeleil 41  * @since 12.11.2014 42  */ 43 public class CompositeEthereumListener implements EthereumListener { 44  private static final Logger logger = LoggerFactory.getLogger("events"); 45  private static final PanicProcessor panicProcessor = new PanicProcessor(); 46  47  // Using a concurrent list 48  // (the add and remove methods copy an internal array, 49  // but the iterator directly use the internal array) 50  private final List<EthereumListener> listeners = new CopyOnWriteArrayList<>(); 51  52  public void addListener(EthereumListener listener) { 53  listeners.add(listener); 54  } 55  public void removeListener(EthereumListener listener) { 56  listeners.remove(listener); 57  } 58  59  @Override 60  public void trace(String output) { 61  scheduleListenerCallbacks(listener -> listener.trace(output)); 62  } 63  64  @Override 65  public void onBlock(Block block, List<TransactionReceipt> receipts) { 66  scheduleListenerCallbacks(listener -> listener.onBlock(block, receipts)); 67  } 68  69  @Override 70  public void onBestBlock(Block block, List<TransactionReceipt> receipts) { 71  scheduleListenerCallbacks(listener -> listener.onBestBlock(block, receipts)); 72  } 73  74  @Override 75  public void onRecvMessage(Channel channel, Message message) { 76  scheduleListenerCallbacks(listener -> listener.onRecvMessage(channel, message)); 77  } 78  79  @Override 80  public void onPeerDisconnect(String host, long port) { 81  scheduleListenerCallbacks(listener -> listener.onPeerDisconnect(host, port)); 82  } 83  84  @Override 85  public void onPendingTransactionsReceived(List<Transaction> transactions) { 86  scheduleListenerCallbacks(listener -> listener.onPendingTransactionsReceived(transactions)); 87  } 88  89  @Override 90  public void onTransactionPoolChanged(TransactionPool transactionPool) { 91  scheduleListenerCallbacks(listener -> listener.onTransactionPoolChanged(transactionPool)); 92  } 93  94  @Override 95  public void onNoConnections() { 96  scheduleListenerCallbacks(EthereumListener::onNoConnections); 97  } 98  99  @Override 100  public void onHandShakePeer(Channel channel, HelloMessage helloMessage) { 101  scheduleListenerCallbacks(listener -> listener.onHandShakePeer(channel, helloMessage)); 102  } 103  104  @Override 105  public void onNodeDiscovered(Node node) { 106  scheduleListenerCallbacks(listener -> listener.onNodeDiscovered(node)); 107  } 108  109  @Override 110  public void onEthStatusUpdated(Channel channel, StatusMessage status) { 111  scheduleListenerCallbacks(listener -> listener.onEthStatusUpdated(channel, status)); 112  } 113  114  @Override 115  public void onPeerAddedToSyncPool(Channel peer) { 116  scheduleListenerCallbacks(listener -> listener.onPeerAddedToSyncPool(peer)); 117  } 118  119  @Override 120  public void onLongSyncDone() { 121  scheduleListenerCallbacks(EthereumListener::onLongSyncDone); 122  } 123  124  @Override 125  public void onLongSyncStarted() { 126  scheduleListenerCallbacks(EthereumListener::onLongSyncStarted); 127  } 128  129  private void scheduleListenerCallbacks(Consumer<EthereumListener> callback) { 130  for (EthereumListener listener : listeners) { 131  try { 132  callback.accept(listener); 133  } catch (Throwable e) { 134  logger.error("Listener callback failed with exception", e); 135  panicProcessor.panic("thread", String.format("Listener callback failed with exception %s", e.getMessage())); 136  } 137  } 138  } 139 }