All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tangosol.net.events.internal.AbstractEvent Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */
package com.tangosol.net.events.internal;

import com.oracle.coherence.common.base.Logger;

import com.tangosol.internal.tracing.Scope;
import com.tangosol.internal.tracing.Span;
import com.tangosol.internal.tracing.TracingHelper;

import com.tangosol.net.events.Event;
import com.tangosol.net.events.EventDispatcher;
import com.tangosol.net.events.EventInterceptor;

import com.tangosol.net.events.internal.AbstractEventDispatcher.EventStats;

import com.tangosol.util.Base;

import java.util.Collection;
import java.util.Iterator;

/**
 * Abstract base implementation of {@link Event}.
 *
 * @author mwj, nsa, rhl  2011.03.29
 * @since Coherence 12.1.2
 *
 * @param   the type of event
 */
public abstract class AbstractEvent>
        implements Event
    {

    // ----- constructor ----------------------------------------------------

    /**
     * Construct a new {@link Event} using the specified type.
     *
     * @param eventType  the type of {@link Event} raised
     */
    public AbstractEvent(T eventType)
        {
        this(null, eventType);
        }

    /**
     * Construct a new {@link Event} using the specified type.
     *
     * @param dispatcher  the event dispatcher that raised this event
     * @param eventType   the type of {@link Event} raised
     */
    public AbstractEvent(EventDispatcher dispatcher, T eventType)
        {
        m_dispatcher = dispatcher;
        m_eventType  = eventType;
        }

    // ----- accessors ------------------------------------------------------

    /**
     * Return the iterator of remaining interceptors to dispatch to.
     *
     * @return the iterator of interceptors
     */
    protected Iterator> getIterator()
        {
        return m_iterInterceptor;
        }

    /**
     * Set the iterator of interceptors to dispatch to.
     *
     * @param iter  the iterator of interceptors
     */
    protected void setIterator(Iterator> iter)
        {
        m_iterInterceptor = iter;
        }

    // ----- Event interface ------------------------------------------------

    /**
     * {@inheritDoc}
     */
    public T getType()
        {
        return m_eventType;
        }

    /**
     * {@inheritDoc}
     */
    public EventDispatcher getDispatcher()
        {
        return m_dispatcher;
        }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public void nextInterceptor()
        {
        EventDispatcher dispatcher = m_dispatcher;
        EventStats      stats      = null;
        boolean         fTracing   = TracingHelper.isEnabled();

        if (dispatcher instanceof AbstractEventDispatcher)
            {
            stats = ((AbstractEventDispatcher) dispatcher).getStats();
            }

        // EventInterceptors receiving this event can optionally call
        // nextInterceptor (recursively) to explicitly control dispatch to the
        // following interceptor(s), and subsequently observe any side-effects.
        // If the interceptor does not recurse, we continue the dispatch chain
        // iteratively.
        for (Iterator> iter = getIterator(); iter.hasNext(); )
            {
            EventInterceptor interceptor = iter.next();
            Span             span        = null;
            Scope            scope       = null;

            if (fTracing)
                {
                span  = TracingHelper.newSpan("process", this)
                        .withMetadata("interceptor", interceptor.getClass().getName())
                        .startSpan();
                scope = TracingHelper.getTracer().withSpan(span);
                }

            try
                {
                // dispatch the event
                interceptor.onEvent(this);
                }
            catch (Exception e)
                {
                TracingHelper.augmentSpanWithErrorDetails(span, true, e);
                if (stats != null)
                    {
                    stats.registerEventException(e, this, interceptor);
                    }

                if (isVetoable())
                    {
                    String sMsg = "Exception vetoed by \"" + interceptor + "\".";
                    if (fTracing)
                        {
                        span.log(sMsg);
                        }
                    // Drain the iterator so no one else can re-start processing
                    while (iter.hasNext())
                        {
                        iter.next();
                        }
                    throw Base.ensureRuntimeException(e, sMsg);
                    }
                else
                    {
                    Logger.err("Exception caught while dispatching to \"" + interceptor + "\": ", e);
                    }
                }
            finally
                {
                if (fTracing)
                    {
                    scope.close();
                    span.end();
                    }
                }
            }
        }

    // ----- AbstractEvent methods ------------------------------------------

    /**
     * Dispatch this event over the specified interceptors.
     *
     * @param colIter  the interceptors to trigger for this event
     */
    protected void dispatch(Collection> colIter)
        {
        setIterator(colIter.iterator());
        nextInterceptor();
        }

    /**
     * Return true if this represents a mutable operation.
     *
     * @return true if this event represents a mutable operation
     */
    protected boolean isMutableEvent()
        {
        return false;
        }

    /**
     * Return true iff an exception raised by an {@link EventInterceptor} during
     * the processing of this event should interrupt the {@link
     * EventInterceptor} chaining of the {@link Event} and terminate the
     * operation.
     *
     * @return true iff an exception raised during processing of this event
     *         should terminate the operation
     */
    protected boolean isVetoable()
        {
        // by default, all mutable events are terminal
        return isMutableEvent();
        }

    /**
    * Returns this Event's description.
    *
    * @return  this Event's description
    */
    protected String getDescription()
        {
        return "Type=" + getType();
        }

    // ----- Object methods -------------------------------------------------

    /**
     * {@inheritDoc}
     */
    public String toString()
        {
        String sEvt = getClass().getName();
        return sEvt.substring(sEvt.lastIndexOf('.') + 1) + '{' + getDescription() + '}';
        }

    // ----- data members ---------------------------------------------------

    /**
     * The event type being raised.
     */
    protected final T m_eventType;

    /**
     * The iterator used by nextInterceptor to iterate through a chain of interceptors.
     */
    protected Iterator> m_iterInterceptor;

    /**
     * Event dispatcher that raised this event.
     */
    protected final EventDispatcher m_dispatcher;
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy