Package org.jboss.fresh.events.impl

Source Code of org.jboss.fresh.events.impl.EventCentralImpl$ForwardListener

package org.jboss.fresh.events.impl;

import org.jboss.fresh.events.EventCentral;
import org.jboss.fresh.events.EventListener;
import org.jboss.fresh.events.EventFilter;
import org.jboss.fresh.events.Event;
import org.jboss.fresh.events.EventBroadcaster;
import org.jboss.fresh.events.RegistrationException;
import org.jboss.fresh.events.InvalidFormatException;
import org.jboss.fresh.events.net.EventNetRouter;

import java.util.Map;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;

import org.jboss.fresh.persist.RandomKeyPKGenerator;

public class EventCentralImpl implements EventCentral {

  private static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(EventCentralImpl.class);
  private static org.apache.log4j.Logger fwlog = org.apache.log4j.Logger.getLogger(EventCentralImpl.ForwardListener.class);

  private HashMap routers = new HashMap();
  private LinkedHashMap allListenersByID = new LinkedHashMap();
  private LinkedHashMap listenersByID = new LinkedHashMap();
  private LinkedHashMap allBcsByID = new LinkedHashMap();
  private LinkedHashMap bcsByID = new LinkedHashMap();
  private LinkedHashMap centrals = new LinkedHashMap();

  private EventListener forwardLis = new ForwardListener();

  private EventBroadcaster eb;

  private RandomKeyPKGenerator pkgen;
  private String host;
  private String app;

  private LinkedHashMap seenEvents = new LinkedHashMap() {
    protected boolean removeEldestEntry(Map.Entry ent) {
      return size() > 10000;
    }
  };
 
  private boolean silentlyDropSeen = false;

  public EventCentralImpl(String hostLabel, String subdomain) {
   
    host = hostLabel;
    app = subdomain;
   
    // Uses
    pkgen = new RandomKeyPKGenerator("11,31", null);
    pkgen.reseed(hostLabel + subdomain + System.currentTimeMillis());

    eb = new EventBroadcaster(this, "EventCentral");
  }

  public void registerEventListener(String name, EventListener lis) {
    try {
      registerEventListener(name, lis, (List) null, 0);
    } catch(InvalidFormatException ex) {
      log.error("Internal application error - illegal state: ", ex);
    }
  }

  public void registerEventListener(String name, EventListener lis, int flags) {
    try {
      registerEventListener(name, lis, (List) null, flags);
    } catch(InvalidFormatException ex) {
      log.error("Internal application error - illegal state: ", ex);
    }
  }

  public void registerEventListener(String name, EventListener lis, String [] filters) throws InvalidFormatException {
    registerEventListener(name, lis, filters == null ? (List) null : java.util.Arrays.asList(filters), 0);
  }

  public void registerEventListener(String name, EventListener lis, String [] filters, int flags) throws InvalidFormatException {
    registerEventListener(name, lis, filters == null ? (List) null : java.util.Arrays.asList(filters), flags);
  }

  public void registerEventListener(String id, EventListener lis, List filters) throws InvalidFormatException {
    registerEventListener(id, lis, new EventFilter(filters), 0);
  }

  public void registerEventListener(String id, EventListener lis, List filters, int flags) throws InvalidFormatException {
    registerEventListener(id, lis, new EventFilter(filters), flags);
  }


  public void registerEventListener(String id, EventListener lis, EventFilter filter) throws InvalidFormatException {
    registerEventListener(id, lis, filter, 0);
  }

  /**
   *  id - lis - filters
   *  When event is dispatched it is passed through all EventFilters
   *  The list it passes through could be minimized if EventFilters were categorized
   *  in hierarchical manner:
   *
   *  /
   *    <any>
   *    hostLabel1
   *    hostLabel2
   *    hostLabel3
   *    |
   *    <any>
   *    elan
   *    lds
   *      |
   *      <any>
   *      component
   *
   *  What if name contains a pattern? This would complicate the code. For now we keep it simple
   */
  public void registerEventListener(String id, EventListener lis, EventFilter filter, int flags) throws InvalidFormatException {

log.info("[" + host + "/" + app + "] registerEventListener() : " + id + ", " + filter + "  :: " + lis); // , new Exception("REG TRACE")

    filter = filter==null ? new EventFilter((List)null) : new EventFilter(filter, this);

    if((flags & SILENT) == 0) {
      Object [] dat = new Object[2];
      dat[0] = id;
      dat[1] = new ListenerData(lis, filter);

      Event ev = new Event("ECentral", "RegisterListener", dat);
      try {
        dispatch(eb.produceEvent(ev));
      } catch(Exception ex) {
        log.warn("Dispatching of RegisterListener event produced exception: ", ex);
      }
    }

    // we dispatch registerListener event first to avoid sending it to just registered listener

    synchronized (this) {
      //ListenerData l = (ListenerData) listenersByID.get(id);
      //if (l != null) {
      //  listenersByID.remove(id);
        //throw new RegistrationException("EventListener already registered for id: " + id + " (unregister it first)");
      //}

      ListenerData dat = new ListenerData(lis, filter);
     
      if((flags & HIDDEN) == 0)
        listenersByID.put(id, dat);
     
      allListenersByID.put(id, dat);

    }

  }


  // remove specified event listener from all listen targets
/*
  public synchronized void unregisterEventListener(EventListener lis) {

    LinkedList l = (LinkedList) lmap.get(lis);

    if (l == null) return;

    Iterator it = l.iterator();
    while (it.hasNext()) {
      Object key = it.next();
      LinkedList l2 = (LinkedList) lismap.get(key);
      if (l2 == null) continue;

      Iterator it2 = l2.iterator();
      while (it2.hasNext()) {
        if (it2.next().equals(lis)) {
          it2.remove();
          break;
        }
      }

      if (l2.size() == 0) lismap.remove(key);
    }

    lmap.remove(lis);

  }
*/


  public synchronized EventListener unregisterEventListener(String id) {

    ListenerData l = (ListenerData) allListenersByID.remove(id);
    listenersByID.remove(id);
//    if (l != null) {
//      listenersByID.remove(id);
      //throw new RegistrationException("EventListener already registered for id: " + id + " (unregister it first)");
//    }

    return l.getListener();
  }


  public synchronized void unregisterEventListener(EventListener lis) {

    // iterate over everything find all occurencies of lis and unregister them all
    Iterator it = new HashSet(allListenersByID.entrySet()).iterator();
    while(it.hasNext()) {
      Map.Entry ent = (Map.Entry) it.next();
      EventListener el = ((ListenerData)ent.getValue()).getListener();
      if(el.equals(lis)) {
        listenersByID.remove(ent.getKey());
        allListenersByID.remove(ent.getKey());
      }
    }
  }


  // This method is part of dead-end idea how ECs will be grouped together
  // we'll remove it
  public synchronized void registerEventCentral(EventCentral ec, String lisid, EventListener lis) throws InvalidFormatException {
    // get app part
    int start = lisid.indexOf("/");
    if(start==-1) throw new InvalidFormatException(lisid);

    String host = lisid.substring(0, start);

    int end = lisid.indexOf("/", start+1);
    if(end==-1) throw new InvalidFormatException(lisid);

    String app = lisid.substring(start+1, end);

    centrals.put(app, lis);

    // app EC registers when it's comming up. It has no broadcasters or listeners registered at this point
    // now we go over our listeners - see which are interested in anything to do with host/app


    // we register listeners only for those interested
    Iterator it = listenersByID.entrySet().iterator();
    while(it.hasNext()) {
      Map.Entry ent = (Map.Entry) it.next();
      EventFilter filter = ((ListenerData) ent.getValue()).getFilter();
      ec.registerEventListener((String) ent.getKey(), forwardLis, filter);
    }


    // we register all broadcasters
    it = bcsByID.entrySet().iterator();
    while(it.hasNext()) {
      Map.Entry ent = (Map.Entry) it.next();
      ec.registerEventBroadcaster((String) ent.getKey(), (EventBroadcaster) ent.getValue());
    }


    // register the other EC's listener
    registerEventListener(lisid, lis, new String[] {"//ECentral//"});
  }


  public void registerEventBroadcaster(String id, EventBroadcaster bc) {
    registerEventBroadcaster(id, bc, 0);
  }

  public synchronized void registerEventBroadcaster(String id, EventBroadcaster bc, int flags) {

    if((flags & HIDDEN) == 0)
      bcsByID.put(id, bc);

    allBcsByID.put(id, bc);
  }

  public synchronized EventBroadcaster unregisterEventBroadcaster(String id) {
    //log.info("Unregistering for id: "+id);
    EventBroadcaster eb = (EventBroadcaster) allBcsByID.remove(id);
    bcsByID.remove(id);
    //log.info("Remainging: "+bcsByID);
    return eb;
  }

  public Map getBroadcasters() {
    return getBroadcasters(false);
  }

  public synchronized Map getBroadcasters(boolean hidden) {
   
    if(hidden) return new LinkedHashMap(allBcsByID);
   
    return new LinkedHashMap(bcsByID);
  }

  public Iterator broadcastersIterator() {
    return broadcastersIterator(false);
  }

  public synchronized Iterator broadcastersIterator(boolean hidden) {
   
    if(hidden) return new ArrayList(allBcsByID.entrySet()).iterator();
   
    return new ArrayList(bcsByID.entrySet()).iterator();   
  }



  public void dispatchEvent(Event ev) throws Exception {

    ev.addTrace("EventCentralImpl:" + host + "/" + app);
    if(!checkEvent(ev)) return;

    if("ECentral".equals(ev.getEventClass())) {
      if("RegisterListener".equals(ev.getEventName())) {
        Object [] dat = (Object []) ev.getValueObject();
        String id = (String) dat[0];
        EventCentral.ListenerData ld = (EventCentral.ListenerData) dat[1];
//log.info("   EVENT:RegisterListener : " + id + " :: " + ld.getListener() + " :: " + ld.getFilter());
        // this event listener must be hidden - it's part of infrastructure and should only be used locally
        // WTF?
        // �e ni hidden potem broadcasta, da je bil registriran in to se potem na taisti remote client
        // ponese, ki je spro�il event. Seveda pa no�emo da je dejansko hidden - samo da ne broadcasta
        // registration eventa. Ampak to je pa spet lame. Mi lahko registration event broadcastamo, ampak ne sme iti
        // na remote EC, kjer je originalno nastal. Ne. Ker To bo samo �e en RegisterListener ustrelilo in se botsta
        // zdaj propagirala 2 saj vidi� v nadaljevanju da originalni event dispatchamo listenerjem. Mi samo hkrati
        // potihem �e registriramo listenerja pri sebi - da je viden zainteresiranim. Zato je prav, da je
        // NO_BROADCAST oz. 'hidden' . Tukaj tudi vidimo potrebo po distinkciji med hidden in silent.
        // To tukaj je silent and not hidden
        registerEventListener(id, ld.getListener(), ld.getFilter(), SILENT);
      }
    }

    dispatch(ev, false);
  }


  protected synchronized boolean checkEvent(Event ev) {
    String evid = ev.getOrigin() + "/" + ev.getID();
//log.debug("eventid: " + evid);
    if(seenEvents.get(evid) != null) {
      // we silently drop events that already passed through
      if(!silentlyDropSeen)
        log.warn("Event has already passed through: " + ev + "  trace: " + ev.getTrace());
      return false;
    }

    seenEvents.put(evid, evid); // we don't really need the event
    return true;
  }


  public void dispatch(Event ev) throws Exception {
    dispatch(ev, true);
  }

  protected void dispatch(Event ev, boolean checkEvent) throws Exception {

//log.debug(" dispatch() :: " + ev);
if(log.isDebugEnabled()) log.debug(" dispatch() " + this + " :: " + ev);
    // make a copy of listeners then iterate over them
    List ls = null;
    synchronized(this) {
if(log.isDebugEnabled()) log.debug("  checking event ...");
      if(checkEvent && !checkEvent(ev)) return;
      ls = new ArrayList(allListenersByID.entrySet());
    }

/*
    Iterator it = ls.iterator();
    while(it.hasNext()) {
      Map.Entry ent = (Map.Entry) it.next();
      ListenerData data = (ListenerData)ent.getValue();
     
      if(data.getFilter().match(ev)) {
        data.getListener().event(ev);
      }
    }
*/
//log.info("All listeners: " + ls);
    for(int i=0; i<6 ; i++) {
      ls = matchField(ls, i, ev);
    }

if(log.isDebugEnabled()) log.debug("Matching listeners: " + ls);
    HashSet dispatched = new HashSet();

    Iterator it = ls.iterator();
    while(it.hasNext()) {
      Map.Entry ent = (Map.Entry) it.next();
      ListenerData data = (ListenerData)ent.getValue();

      EventListener lis = data.getListener();
      if(!dispatched.contains(lis)) {
        ev.addTrace(ent.getKey() + ":" + data.getListener());
if(log.isDebugEnabled()) log.debug("dispatching event to: " + ent.getKey() + ":" + data.getListener());
        lis.event(ev);
        dispatched.add(lis);
      }
    }
  }


  private List matchField(List ls, int field, Event ev) {

//log.info("matchField() " + field + " on " + ev + "  for " + ls);
    Iterator it = ls.iterator();
    while(it.hasNext()) {
      Map.Entry ent = (Map.Entry) it.next();
      ListenerData data = (ListenerData)ent.getValue();
      EventFilter filt = data.getFilter();

//log.info("Matching event " + ev + " against filter: " + filt + " (" + data.getListener() + ")    for field: " + field);

      boolean bMatch = false;
     
      switch(field) {
        case 0:
          bMatch = filt.matchHost(ev);
          break;
        case 1:
          bMatch = filt.matchApplication(ev);
          break;
        case 2:
          bMatch = filt.matchComponent(ev);
          break;
        case 3:
          bMatch = filt.matchComponentID(ev);
          break;
        case 4:
          bMatch = filt.matchEventClass(ev);
          break;
        case 5:
          bMatch = filt.matchEventName(ev);
          break;
        default:
          throw new RuntimeException("Field out of range: " + field);
      }
     
      if(!bMatch) {
        log.info("   <no match>");
        it.remove();
      }
    }

    return ls;
  }


  public Map getListeners() {
    return getListeners(false);
  }

  public synchronized Map getListeners(boolean hidden) {

    if(hidden) return new LinkedHashMap(allListenersByID);
   
    return new LinkedHashMap(listenersByID);
  }


  public Iterator listenersIterator() {
    return listenersIterator(false);
  }

  public synchronized Iterator listenersIterator(boolean hidden) {
   
    if(hidden) return new ArrayList(allListenersByID.entrySet()).iterator();
   
    return new ArrayList(listenersByID.entrySet()).iterator();
  }


  public Iterator listenersIteratorInverse() {
    return null;
  }


  public synchronized void registerEventNetRouter(String agentid, EventNetRouter router) throws RegistrationException {
    EventNetRouter rt = (EventNetRouter) routers.get(agentid);
    if(rt != null) throw new RegistrationException("Router is already registered under the specified agentid: " + agentid + " (Either you should reuse existing one or there are more agents with same agentid - which should never be - which means wrong configuration.)");

    routers.put(agentid, router);
  }


  public synchronized EventNetRouter getEventNetRouter(String agentid) {
    return (EventNetRouter) routers.get(agentid);
  }


  public List getEventListenerFilters(String id) {
    ListenerData data = (ListenerData) listenersByID.get(id);
    return data.getFilter().getFilters();
  }


  public String generateID() {
    try {
      return (String) pkgen.newKey();
    } catch(RuntimeException ex) {
      throw ex;
    } catch(Exception ex) {
      throw new RuntimeException("Exception happened while generating id: ", ex);
    }
  }


  public String produceOrigin(String componentName) {
    return getHostLabel() + "/" + getApplication() + "/" + componentName + "(" + generateID() + ")";
  }

  public String produceOrigin(String componentName, String id) {
    return getHostLabel() + "/" + getApplication() + "/" + componentName + "(" + id + ")";
  }

  public String getHostLabel() {
    return host;
  }


  public String getApplication() {
    return app;
  }

  public boolean isOriginOf(String origin) {
//log.info("\n\r\n\r>>>>>>>>>>>>>>>>>>>>>>>>>>> checking " + origin + "  vs. " + host + "/" + "\n\r\n\r");
    return origin.startsWith(host+"/");
  }

  class ForwardListener implements EventListener {

    public void event(Event ev) {
      // if ECentral RegisterListener
      // register the damn listener

      // broadcast it to all listeners
      try {
//log.info("##### " + this + ": event() " + ev);
        dispatchEvent(ev);
      } catch(Exception ex) {
        fwlog.error("failed to dispatch event: " + ev, ex);
      }
    }
  }


  public String toString() {
    return super.toString() + " " + host + "/" + app;
  }
}
TOP

Related Classes of org.jboss.fresh.events.impl.EventCentralImpl$ForwardListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.