/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY 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 along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.soa.esb.couriers;
/**
*
* @author - esteban
* @author - kstam@redhat.com
*
*/
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.couriers.TwoWayCourierImpl;
import org.jboss.soa.esb.addressing.EPR;
import org.jboss.soa.esb.addressing.MalformedEPRException;
import org.jboss.soa.esb.lifecycle.LifecyclePriorities;
import org.jboss.soa.esb.lifecycle.LifecycleResource;
import org.jboss.soa.esb.lifecycle.LifecycleResourceException;
import org.jboss.soa.esb.lifecycle.LifecycleResourceFactory;
public class CourierFactory
{
/**
* The logger for this instance.
*/
private static final Logger LOGGER = Logger.getLogger(CourierFactory.class) ;
/**
* The lifecycle resource factory.
*/
private static final LifecycleResourceFactory<Map<TwoWayCourier, Exception>> lifecycleCourierFactory = new LifecycleCourierFactory() ;
/**
* Lifecycle couriers.
*/
private static final LifecycleResource<Map<TwoWayCourier, Exception>> lifecycleCouriers =
new LifecycleResource<Map<TwoWayCourier,Exception>>(lifecycleCourierFactory,
LifecyclePriorities.COURIER_PRIORITY) ;
/**
* Factory singleton instance.
*/
private static CourierFactory instance = new CourierFactory();
// protected default constructor
protected CourierFactory() {}
/**
* Get the CourierFactory method.
* @return The Courier factory instance.
*/
public static CourierFactory getInstance() {
return instance;
}
/**
* Set the CourierFactory method.
* <p/>
* Supports unit testing.
*
* @param instance New factory instance.
*/
public static void setInstance(CourierFactory instance) {
CourierFactory.instance = instance;
}
/**
* Obtain a courier which can perform deliveries only and prime it with the "to address" (toEPR).
*
* @param toEPR - the 'to address', the address on where to deliverAsync a Message.
* @return The courier.
* @throws CourierException if the specific courier implementation cannot be created.
*/
public TwoWayCourier getMessageCourier(EPR toEPR) throws CourierException, MalformedEPRException {
return getCourier(toEPR, null);
}
/**
* Obtain a courier which can perform deliveries only and prime it with the "to address" (toEPR).
*
* @param toEPR - the 'to address', the address on where to deliverAsync a Message.
* @return Courier
* @throws CourierException if the specific courier implementation cannot be created.
*/
public static Courier getCourier(EPR toEPR) throws CourierException, MalformedEPRException
{
return getCourier(toEPR, null);
}
/**
* Obtain a courier which can perform pickups only and prime it with the "to address" (toEPR)
* and the "replyTo address" (replyToEPR).
*
* @param replyToEPR - the 'replyTo address', the address where to deliverAsync the Message we pickup.
* @return TwoWayCourier
* @throws CourierException if the specific courier implementation cannot be created.
*/
public static TwoWayCourier getPickupCourier(EPR replyToEPR) throws CourierException, MalformedEPRException
{
return getCourier(null, replyToEPR);
}
/**
* Obtain a courier which can perform both deliveries and pickups and prime it with
* the "to address" (toEPR) and the "replyTo address" (replyToEPR).
*
* @param toEPR - the 'to address', the address on where to deliverAsync a Message.
* @param replyToEPR - the 'replyTo address', the address where to deliverAsync the Message we pickup.
* @return TwoWayCourier
* @throws CourierException if the specific courier implementation cannot be created.
*/
public static TwoWayCourier getCourier(EPR toEPR, EPR replyToEPR) throws CourierException, MalformedEPRException
{
final TwoWayCourier result = new TwoWayCourierImpl(toEPR, replyToEPR);
registerCourier(result) ;
return result ;
}
/**
* Register the courier as part of the current set.
* @param courier The current courier.
*/
private static void registerCourier(final TwoWayCourier courier)
throws CourierException
{
final Exception ex ;
if (LOGGER.isDebugEnabled())
{
ex = new Exception("Courier Assignment stacktrace") ;
}
else
{
ex = null ;
}
final Map<TwoWayCourier, Exception> map ;
try
{
map = lifecycleCouriers.getLifecycleResource() ;
}
catch (final LifecycleResourceException lre)
{
throw new CourierException("Unexpected lifecycle resource exception while registering courier", lre) ;
}
synchronized(map)
{
map.put(courier, ex) ;
}
}
/**
* Deregister the courier from the current set.
* @param courier The current courier.
*/
public static void deregisterCourier(final TwoWayCourier courier)
{
final Map<TwoWayCourier, Exception> map ;
try
{
map = lifecycleCouriers.getLifecycleResource() ;
synchronized(map)
{
map.remove(courier) ;
}
}
catch (final LifecycleResourceException lre)
{
LOGGER.warn("Unexpected error removing courier: " + lre.getMessage()) ;
if (LOGGER.isDebugEnabled())
{
LOGGER.debug("Unexpected error removing courier", lre) ;
}
}
}
/**
* The lifecycle resource factory
* @author kevin
*/
private static class LifecycleCourierFactory implements LifecycleResourceFactory<Map<TwoWayCourier, Exception>>
{
/**
* Create a resource object which will be associated with the specified lifecycle identity.
* @param lifecycleIdentity The associated lifecycle identity.
* @return The lifecycle resource
* @throws LifecycleResourceException for errors during construction.
*/
public Map<TwoWayCourier, Exception> createLifecycleResource(final String lifecycleIdentity)
throws LifecycleResourceException
{
return new HashMap<TwoWayCourier, Exception>() ;
}
/**
* Destroy a resource object which is associated with the specified lifecycle identity.
* @param resource The lifecycle resource.
* @param lifecycleIdentity The associated lifecycle identity.
* @return The lifecycle resource.
* @throws LifecycleResourceException for errors during destroy.
*/
public void destroyLifecycleResource(final Map<TwoWayCourier, Exception> resource,
final String lifecycleIdentity)
throws LifecycleResourceException
{
if (resource.size() > 0)
{
LOGGER.warn("Calling cleanup on existing couriers for identity " + lifecycleIdentity) ;
final Iterator<Entry<TwoWayCourier, Exception>> entryIter = resource.entrySet().iterator() ;
while(entryIter.hasNext())
{
final Entry<TwoWayCourier, Exception> entry = entryIter.next();
entryIter.remove() ;
if (LOGGER.isDebugEnabled() && (entry.getValue() != null))
{
LOGGER.debug("Courier allocation stacktrace", entry.getValue()) ;
}
try
{
entry.getKey().cleanup() ;
}
catch (final Exception ex)
{
LOGGER.warn("Unexpected exception cleaning up courier", ex) ;
}
}
}
}
}
}