Package org.jboss.internal.soa.esb.services.registry

Source Code of org.jboss.internal.soa.esb.services.registry.LocalRegistryInterceptor

/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat Middleware LLC, and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*/
package org.jboss.internal.soa.esb.services.registry;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.log4j.Logger;
import org.jboss.soa.esb.Service;
import org.jboss.soa.esb.addressing.EPR;
import org.jboss.soa.esb.services.registry.AbstractRegistryInterceptor;
import org.jboss.soa.esb.services.registry.RegistryException;
import org.jboss.soa.esb.services.registry.ServiceNotFoundException;

/**
* Local registry interceptor.
*
* @author <a href='mailto:Kevin.Conner@jboss.com'>Kevin Conner</a>
*/
public class LocalRegistryInterceptor extends AbstractRegistryInterceptor
{
    /**
     * The logger for the registry cache
     */
    private static final Logger LOGGER = Logger.getLogger(LocalRegistryInterceptor.class) ;
   
    /**
     * Mapping of service names to service informatio.
     */
    private final HashMap<Service, ServiceInfo> serviceInfoMap = new HashMap<Service, ServiceInfo>() ;

    /**
     * Find all Services assigned to the Red Hat/JBossESB organization.
     * @return Collection of Strings containing the service names.
     * @throws RegistryException
     */
    public List<String> findAllServices() throws RegistryException
    {
        return getRegistry().findAllServices() ;
    }

    /**
     * Find all services that belong to the supplied category.
     *
     * @param serviceCategoryName - name of the category to which the service belongs.
     * @return Collection of Strings containing the service names
     * @throws RegistryException
     */
    public List<String> findServices(final String category)
            throws RegistryException
    {
        return getRegistry().findServices(category) ;
    }

    /**
     * Returns the first EPR in the list that belong to a specific category and service combination.
     *
     * @param serviceCategoryName - name of the category to which the service belongs.
     * @param serviceName         - name of the service to which the EPS belongs.
     * @return EPR.
     * @throws RegistryException
     */
    public EPR findEPR(final String category, final String name)
            throws RegistryException, ServiceNotFoundException
    {
        final Service service = new Service(category, name) ;
        final ConcurrentMap<EPR, AtomicLong> eprMap = getEPRs(service) ;
       
        if (eprMap != null)
        {
            final Iterator<EPR> eprIter = eprMap.keySet().iterator() ;
            if (eprIter.hasNext())
            {
                final EPR epr = eprIter.next() ;
                if (LOGGER.isDebugEnabled())
                {
                    LOGGER.debug("Returning locally registered EPR for category " + category + ", name " + name) ;
                }
                return epr ;
            }
        }
        return getRegistry().findEPR(category, name);
    }

    /**
     * Finds all the EPRs that belong to a specific category and service combination.
     *
     * @param serviceCategoryName - name of the category to which the service belongs.
     * @param serviceName         - name of the service to which the EPS belongs.
     * @return Collection of EPRs.
     * @throws RegistryException
     */
    public List<EPR> findEPRs(final String category, final String name)
            throws RegistryException, ServiceNotFoundException
    {
        final Service service = new Service(category, name) ;
        final ConcurrentMap<EPR, AtomicLong> eprMap = getEPRs(service) ;
       
        if (eprMap != null)
        {
            final Set<EPR> eprSet = eprMap.keySet() ;
            final List<EPR> eprs = Arrays.asList(eprSet.toArray(new EPR[0])) ;
            if (!eprs.isEmpty())
            {
                if (LOGGER.isDebugEnabled())
                {
                    LOGGER.debug("Returning locally registered EPRs for category " + category + ", name " + name) ;
                }
                return eprs ;
            }
        }
        return getRegistry().findEPRs(category, name) ;
    }

    /**
     * Registers an EPR under the specified category and service. If the specified service does
     * not exist, it will be created at the same time.
     *
     * @param serviceCategoryName - name of the category to which the service belongs.
     * @param serviceName         - name of the service to which the EPS belongs.
     * @param serviceDescription  - human readable description of the service,
     *                             only used when it the service does not yet exist.
     * @param epr                 - the EndPointReference (EPR) that needs to be registered.
     * @param eprDescription      - human readable description of the EPR
     * @throws RegistryException
     */
    public void registerEPR(final String category, final String name,
            final String serviceDescription, final EPR epr, final String eprDescription)
            throws RegistryException
    {
        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("Registering EPR " + epr + " for category " + category + ", name " + name) ;
        }
        final Service service = new Service(category, name) ;
        final ServiceInfo serviceInfo = createWriteLockServiceInfo(service) ;
        try
        {
            getRegistry().registerEPR(category, name, serviceDescription, epr, eprDescription) ;
            final ConcurrentMap<EPR, AtomicLong> eprs = serviceInfo.getEPRs() ;
            addEPR(eprs, epr) ;
        }
        finally
        {
            serviceInfo.getWriteLock().unlock() ;
        }
    }

    /**
     * Removes an EPR from the Registry.
     * @param serviceCategoryName - name of the category to which the service belongs.
     * @param serviceName         - name of the service to which the EPS belongs.
     * @param epr                 - the EndPointReference (EPR) that needs to be unregistered.
     * @throws RegistryException
     */
    public void unRegisterEPR(final String category, final String name,
            final EPR epr) throws RegistryException, ServiceNotFoundException
    {
        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("Unregistering EPR " + epr + " for category " + category + ", name " + name) ;
        }
        final Service service = new Service(category, name) ;
        final ServiceInfo serviceInfo = getWriteLockServiceInfo(service) ;
        if (serviceInfo != null)
        {
            try
            {
                final ConcurrentMap<EPR, AtomicLong> eprs = serviceInfo.getEPRs() ;
                final AtomicLong count = eprs.get(epr) ;
                if (count != null)
                {
                    if (count.decrementAndGet() == 0)
                    {
                        eprs.remove(epr) ;
                        if (eprs.isEmpty())
                        {
                            removeServiceInfo(service, serviceInfo) ;
                        }
                    }
                }
                getRegistry().unRegisterEPR(category, name, epr) ;
            }
            finally
            {
                serviceInfo.getWriteLock().unlock() ;
            }
        }
        else
        {
            getRegistry().unRegisterEPR(category, name, epr) ;
        }
    }

    /**
     * Removes a service from the Registry along with all the ServiceBindings underneath it.
     *
     * @param category           - name of the service category, for example 'transformation'.
     * @param serviceName        - name of the service, for example 'smooks'.
     * @throws RegistryException
     */
    public void unRegisterService(final String category, final String name)
            throws RegistryException, ServiceNotFoundException
    {
        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("Unregistering service category " + category + ", name " + name) ;
        }
       
        final Service service = new Service(category, name) ;
        final ServiceInfo serviceInfo = getWriteLockServiceInfo(service) ;
        if (serviceInfo != null)
        {
            try
            {
                removeServiceInfo(service, serviceInfo) ;
                getRegistry().unRegisterService(category, name) ;
            }
            finally
            {
                serviceInfo.getWriteLock().unlock() ;
            }
        }
        else
        {
            getRegistry().unRegisterService(category, name) ;
        }
    }

    /**
     * Add an EPR entry into the map.
     * @param eprs The current map.
     * @param epr The epr to add.
     */
    private static void addEPR(final ConcurrentMap<EPR, AtomicLong> eprs, final EPR epr)
    {
        final AtomicLong newCount = new AtomicLong(1) ;
        final AtomicLong count = eprs.putIfAbsent(epr, newCount) ;
        if (count != null)
        {
            count.incrementAndGet() ;
        }
    }

    /**
     * Remove the service info from the current map.
     * @param service The service to remove.
     * @param serviceInfo The service information being removed.
     * @param ifEmpty Only remove the service information if it is empty.
     */
    private synchronized void removeServiceInfo(final Service service, final ServiceInfo serviceInfo)
    {
        final ServiceInfo currentServiceInfo = serviceInfoMap.remove(service) ;
        if (serviceInfo != currentServiceInfo)
        {
            serviceInfoMap.put(service, currentServiceInfo) ;
        }
    }

    /**
     * Acquire a read lock for the current service info.
     * @param service The service to lock.
     * @return The current service info in the map.
     */
    private ConcurrentMap<EPR, AtomicLong> getEPRs(final Service service)
    {
        final boolean traceEnabled = LOGGER.isTraceEnabled() ;
        while(true)
        {
            final ServiceInfo serviceInfo ;
            final Lock readLock ;
            synchronized(this)
            {
                serviceInfo = serviceInfoMap.get(service) ;
                if (traceEnabled)
                {
                    LOGGER.trace("Retrieved service information for service " + service + ", serviceInfo: " + serviceInfo) ;
                }
                if (serviceInfo == null)
                {
                    return null ;
                }
                readLock = serviceInfo.getReadLock() ;
               
                if (readLock.tryLock())
                {
                    if (traceEnabled)
                    {
                        LOGGER.trace("Obtained read lock, returning EPRs") ;
                    }
                    try
                    {
                        return serviceInfo.getEPRs() ;
                    }
                    finally
                    {
                        readLock.unlock() ;
                    }
                }
            }
            LOGGER.trace("Waiting for read lock") ;
            readLock.lock() ;
            try
            {
                synchronized(this)
                {
                    if (serviceInfo == serviceInfoMap.get(service))
                    {
                        if (traceEnabled)
                        {
                            LOGGER.trace("Returning current EPRs") ;
                        }
                        return serviceInfo.getEPRs() ;
                    }
                }
            }
            finally
            {
                readLock.unlock() ;
            }
        }
    }

    /**
     * Acquire a write lock for the current service info, caller <b>must</b> release the lock.
     * @param service The service to lock.
     * @return The current service info in the map.
     */
    private ServiceInfo getWriteLockServiceInfo(final Service service)
    {
        final boolean traceEnabled = LOGGER.isTraceEnabled() ;
        while(true)
        {
            final ServiceInfo serviceInfo ;
            final Lock writeLock ;
            synchronized(this)
            {
                serviceInfo = serviceInfoMap.get(service) ;
                if (traceEnabled)
                {
                    LOGGER.trace("Retrieved service information for service " + service + ", serviceInfo: " + serviceInfo) ;
                }
                if (serviceInfo == null)
                {
                    return null ;
                }
                writeLock = serviceInfo.getWriteLock() ;
               
                if (writeLock.tryLock())
                {
                    if (traceEnabled)
                    {
                        LOGGER.trace("Obtained write lock, returning locked serviceInfo") ;
                    }
                    return serviceInfo ;
                }
            }
            LOGGER.trace("Waiting for write lock") ;
            writeLock.lock() ;
            synchronized(this)
            {
                if (serviceInfo == serviceInfoMap.get(service))
                {
                    if (traceEnabled)
                    {
                        LOGGER.trace("ServiceInfo stilll current, returning locked serviceInfo") ;
                    }
                    return serviceInfo ;
                }
                else
                {
                    writeLock.unlock() ;
                }
            }
        }
    }

    /**
     * Acquire a write lock for the current service info, caller <b>must</b> release the lock.
     * ServiceInfo will be created if not present.
     * @param service The service to lock.
     * @return The current service info in the map.
     */
    private ServiceInfo createWriteLockServiceInfo(final Service service)
    {
        final boolean traceEnabled = LOGGER.isTraceEnabled() ;
        while(true)
        {
            final ServiceInfo serviceInfo ;
            final Lock writeLock ;
            synchronized(this)
            {
                serviceInfo = serviceInfoMap.get(service) ;
                if (serviceInfo == null)
                {
                    if (traceEnabled)
                    {
                        LOGGER.trace("Creating service information for service " + service) ;
                    }
                    final ServiceInfo newServiceInfo = new ServiceInfo() ;
                    serviceInfoMap.put(service, newServiceInfo) ;
                    newServiceInfo.getWriteLock().lock() ;
                    return newServiceInfo ;
                }
                if (traceEnabled)
                {
                    LOGGER.trace("Retrieved service information for service " + service + ", serviceInfo: " + serviceInfo) ;
                }
                writeLock = serviceInfo.getWriteLock() ;
               
                if (writeLock.tryLock())
                {
                    if (traceEnabled)
                    {
                        LOGGER.trace("Obtained write lock, returning locked serviceInfo") ;
                    }
                    return serviceInfo ;
                }
            }
            writeLock.lock() ;
            synchronized(this)
            {
                if (serviceInfo == serviceInfoMap.get(service))
                {
                    if (traceEnabled)
                    {
                        LOGGER.trace("ServiceInfo stilll current, returning locked serviceInfo") ;
                    }
                    return serviceInfo ;
                }
                else
                {
                    writeLock.unlock() ;
                }
            }
        }
    }

    /**
     * Class representing the service information
     * @author kevin
     */
    private static class ServiceInfo
    {
        private ConcurrentMap<EPR, AtomicLong> eprs = new ConcurrentHashMap<EPR, AtomicLong>() ;
       
        private ReadWriteLock lock = new ReentrantReadWriteLock() ;
       
        ConcurrentMap<EPR, AtomicLong> getEPRs()
        {
            return eprs ;
        }
       
        Lock getWriteLock()
        {
            return lock.writeLock() ;
        }
       
        Lock getReadLock()
        {
            return lock.readLock() ;
        }
    }
}
TOP

Related Classes of org.jboss.internal.soa.esb.services.registry.LocalRegistryInterceptor

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.