Package org.apache.mina.common.support

Source Code of org.apache.mina.common.support.IoServiceListenerSupport

/*
*  Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF licenses this file
*  to you under the Apache License, Version 2.0 (the
*  "License"); you may not use this file except in compliance
*  with the License.  You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing,
*  software distributed under the License is distributed on an
*  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
*  KIND, either express or implied.  See the License for the
*  specific language governing permissions and limitations
*  under the License.
*
*/
package org.apache.mina.common.support;

import java.net.SocketAddress;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.CountDownLatch;

import org.apache.mina.common.IoAcceptorConfig;
import org.apache.mina.common.IoConnector;
import org.apache.mina.common.IoFuture;
import org.apache.mina.common.IoFutureListener;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoService;
import org.apache.mina.common.IoServiceConfig;
import org.apache.mina.common.IoServiceListener;
import org.apache.mina.common.IoSession;
import org.apache.mina.common.RuntimeIOException;
import org.apache.mina.util.IdentityHashSet;

/**
* A helper which provides addition and removal of {@link IoServiceListener}s and firing
* events.
*
* @author The Apache Directory Project (mina-dev@directory.apache.org)
* @version $Rev: 471608 $, $Date: 2006-11-06 10:59:03 +0900 (월, 06 11월 2006) $
*/
public class IoServiceListenerSupport
{
    /**
     * A list of {@link IoServiceListener}s.
     */
    private final List<IoServiceListener> listeners = new CopyOnWriteArrayList<IoServiceListener>();

    /**
     * Tracks managed <tt>serviceAddress</tt>es.
     */
    private final Set<SocketAddress> managedServiceAddresses = new CopyOnWriteArraySet<SocketAddress>();

    /**
     * Tracks managed sesssions with <tt>serviceAddress</tt> as a key.
     */
    private final ConcurrentMap<SocketAddress, Set<IoSession>> managedSessions =
        new ConcurrentHashMap<SocketAddress, Set<IoSession>>();

    /**
     * Creates a new instance.
     */
    public IoServiceListenerSupport()
    {
    }

    /**
     * Adds a new listener.
     */
    public void add( IoServiceListener listener )
    {
        listeners.add( listener );
    }

    /**
     * Removes an existing listener.
     */
    public void remove( IoServiceListener listener )
    {
        listeners.remove( listener );
    }

    public Set<SocketAddress> getManagedServiceAddresses()
    {
        return Collections.unmodifiableSet( managedServiceAddresses );
    }

    public boolean isManaged( SocketAddress serviceAddress )
    {
        return managedServiceAddresses.contains( serviceAddress );
    }

    public Set<IoSession> getManagedSessions( SocketAddress serviceAddress )
    {
        Set<IoSession> sessions = managedSessions.get( serviceAddress );

        if( null == sessions )
        {
            return Collections.emptySet();
        }

        synchronized( sessions )
        {
            return new IdentityHashSet<IoSession>( sessions );
        }
    }

    /**
     * Calls {@link IoServiceListener#serviceActivated(IoService, SocketAddress, IoHandler, IoServiceConfig)}
     * for all registered listeners.
     */
    public void fireServiceActivated(
        IoService service, SocketAddress serviceAddress,
        IoHandler handler, IoServiceConfig config )
    {
        if( !managedServiceAddresses.add( serviceAddress ) )
        {
            return;
        }

        for( IoServiceListener listener : listeners )
        {
            listener.serviceActivated( service, serviceAddress, handler, config );
        }
    }

    /**
     * Calls {@link IoServiceListener#serviceDeactivated(IoService, SocketAddress, IoHandler, IoServiceConfig)}
     * for all registered listeners.
     */
    public synchronized void fireServiceDeactivated(
        IoService service, SocketAddress serviceAddress,
        IoHandler handler, IoServiceConfig config )
    {
        if( !managedServiceAddresses.remove( serviceAddress ) )
        {
            return;
        }

        try
        {
            for( IoServiceListener listener : listeners )
            {
                listener.serviceDeactivated( service, serviceAddress, handler, config );
            }
        }
        finally
        {
            disconnectSessions( serviceAddress, config );
        }
    }


    /**
     * Calls {@link IoServiceListener#sessionCreated(IoSession)} for all registered listeners.
     */
    public void fireSessionCreated( IoSession session )
    {
        SocketAddress serviceAddress = session.getServiceAddress();

        // Get the session set.
        Set<IoSession> s = new IdentityHashSet<IoSession>();
        Set<IoSession> sessions = managedSessions.putIfAbsent( serviceAddress, Collections.synchronizedSet( s ) );
        boolean firstSession;

        if( null == sessions ) {
            sessions = s;
            firstSession = true;
        } else {
            firstSession = false;
        }

        // If already registered, ignore.
        if( !sessions.add( session ) )
        {
            return;
        }

        // If the first connector session, fire a virtual service activation event.
        if( session.getService() instanceof IoConnector && firstSession )
        {
            fireServiceActivated(
                session.getService(), session.getServiceAddress(),
                session.getHandler(), session.getServiceConfig() );
        }

        // Fire session events.
        session.getFilterChain().fireSessionCreated( session );
        session.getFilterChain().fireSessionOpened( session );

        // Fire listener events.
        for( IoServiceListener listener : listeners )
        {
            listener.sessionCreated( session );
        }
    }

    /**
     * Calls {@link IoServiceListener#sessionDestroyed(IoSession)} for all registered listeners.
     */
    public void fireSessionDestroyed( IoSession session )
    {
        SocketAddress serviceAddress = session.getServiceAddress();

        // Get the session set.
        Set<IoSession> sessions = managedSessions.get( serviceAddress );
        // Ignore if unknown.
        if( sessions == null )
        {
            return;
        }

        sessions.remove( session );

        boolean lastSession = false;

        // Try to remove the remaining empty session set after removal.
        if( sessions.isEmpty() )
        {
            lastSession = managedSessions.remove( serviceAddress, sessions );
        }

        // Fire session events.
        session.getFilterChain().fireSessionClosed( session );

        // Fire listener events.
        try
        {
            for( IoServiceListener listener : listeners )
            {
                listener.sessionDestroyed( session );
            }
        }
        finally
        {
            // Fire a virtual service deactivation event for the last session of the connector.
            //TODO double-check that this is *STILL* the last session. May not be the case
            if( session.getService() instanceof IoConnector && lastSession )
            {
                fireServiceDeactivated(
                    session.getService(), session.getServiceAddress(),
                    session.getHandler(), session.getServiceConfig() );
            }
        }
    }

    private void disconnectSessions( SocketAddress serviceAddress, IoServiceConfig config )
    {
        if( !( config instanceof IoAcceptorConfig ) )
        {
            return;
        }

        if( !( ( IoAcceptorConfig ) config ).isDisconnectOnUnbind() )
        {
            return;
        }

        Set<IoSession> sessions = getManagedSessions( serviceAddress );

        if( sessions.isEmpty() ) {
            return;
        }

        final CountDownLatch latch = new CountDownLatch( sessions.size() );

        for( IoSession session : sessions )
        {
            session.close().addListener( new IoFutureListener()
            {
                public void operationComplete( IoFuture future )
                {
                    latch.countDown();
                }
            } );
        }

        try
        {
            latch.await();
        }
        catch( InterruptedException e )
        {
            throw new RuntimeIOException( e );
        }
    }
}
TOP

Related Classes of org.apache.mina.common.support.IoServiceListenerSupport

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.