/*=============================================================================*
* Copyright 2004 The Apache Software Foundation
*
* Licensed 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.ws.resource.impl;
import commonj.timers.Timer;
import commonj.timers.TimerManager;
import org.apache.commons.collections.map.ReferenceMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.Soap1_1Constants;
import org.apache.ws.addressing.EndpointReference;
import org.apache.ws.addressing.XmlBeansEndpointReference;
import org.apache.ws.metadata.MetadataConfiguration;
import org.apache.ws.resource.IllegalResourceTypeException;
import org.apache.ws.resource.JndiConstants;
import org.apache.ws.resource.PersistentResource;
import org.apache.ws.resource.PropertiesResource;
import org.apache.ws.resource.Resource;
import org.apache.ws.resource.ResourceContext;
import org.apache.ws.resource.ResourceCreationEvent;
import org.apache.ws.resource.ResourceCreationListener;
import org.apache.ws.resource.ResourceDestructionEvent;
import org.apache.ws.resource.ResourceDestructionListener;
import org.apache.ws.resource.ResourceException;
import org.apache.ws.resource.ResourceHome;
import org.apache.ws.resource.ResourceUnknownException;
import org.apache.ws.resource.WsrfRuntime;
import org.apache.ws.resource.faults.FaultException;
import org.apache.ws.resource.i18n.Keys;
import org.apache.ws.resource.i18n.MessagesImpl;
import org.apache.ws.resource.lifetime.ScheduledResourceTerminationResource;
import org.apache.ws.util.Cache;
import org.apache.ws.util.NameUtils;
import org.apache.ws.util.XmlBeanUtils;
import org.apache.ws.util.i18n.Messages;
import org.apache.ws.util.jndi.Initializable;
import org.apache.ws.util.jndi.XmlBeanJndiUtils;
import org.apache.ws.util.lock.Lock;
import org.apache.ws.util.lock.LockManager;
import org.apache.ws.util.platform.JaxRpcPlatform;
import org.apache.ws.util.timer.TimerManagerImpl;
import org.apache.xmlbeans.XmlObject;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ListableBeanFactory;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.xml.namespace.QName;
import javax.xml.rpc.JAXRPCException;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* TODO: Update these Javadocs
* <p/>
* LOG-DONE An implementation of the <code>ResourceHome</code> interface. This implementation was designed to work with
* resources that implement the {@link PersistentResource PersistenceCallback} interface as well as memory resident
* resources. If the resource class implements the {@link PersistentResource PersistenceCallback} interface
* <code>SoftReference</code>s will be used to recycle resource objects. The resource class implementation is
* responsible for saving its state to disk. This implementation will <b>not</b> call {@link PersistentResource#store()
* PersistenceCallback.store()}. The resource implementation must have a default constructor. <br><br> Configuration
* options: <ul> <li> sweeperDelay - configures how often the resource sweeper runs in msec. By default the resource
* sweeper runs every minute. For example:
* <pre>
* <parameter>
* <name>sweeperDelay</name>
* <value>60000</value>
* </parameter>
* </pre>
* <li> resourceClass - configures the name of the resource class. For example:
* <pre>
* <parameter>
* <name>resourceClass</name>
* <value>org.globus.wsrf.samples.counter.PersistentCounter</value>
* </parameter>
* </pre>
* <li> resourceKeyType - configures the key type class. By default <code>java.lang.String</code> is used. For example:
* <pre>
* <parameter>
* <name>resourceKeyType</name>
* <value>java.lang.Integer</value>
* </parameter>
* </pre>
* <li> resourceKeyName - configures the key name. For example:
* <pre>
* <parameter>
* <name>resourceKeyName</name>
* <value>{http://counter.com}CounterKey</value>
* </parameter>
* </pre>
* </ul> <br> <b>Note:</b> Must be deployed with <code>org.globus.wsrf.jndi.BeanFactory</code> in JNDI or user must
* first call {@link #init() initialize()} method. Also when overriding the {@link #init() initialize()} method make
* sure to call <code>super.initialize();</code>.
*
* @author Globus, Ian Springer
*/
public abstract class AbstractResourceHome
implements ResourceHome,
Initializable,
Serializable
{
private static final Log LOG = LogFactory.getLog( AbstractResourceHome.class );
private static final Messages MSG = MessagesImpl.getInstance( );
private static final int DEFAULT_SWEEPER_DELAY = 60000;
/*
* A static key used only for registering Singleton Resources
*/
private static final Object SINGLETON_KEY = new Object( );
private static final String CONTEXT_NAME_J2EE_TIMER_MANAGER = "java:comp/env/tm/TimerManager";
/**
* DOCUMENT_ME
*/
protected Map m_resources;
/**
* DOCUMENT_ME
*/
protected boolean m_resourceIsPersistent;
private QName m_resourceIdRefParamName;
private String m_wsdlTargetNamespace;
/**
* DOCUMENT_ME
*/
protected LockManager m_lockManager;
private String m_cacheLocation;
private Cache m_cache;
private long m_sweeperDelay = DEFAULT_SWEEPER_DELAY;
private Sweeper m_sweeper;
private boolean m_initialized;
private List m_creationListeners = new ArrayList( );
private List m_destructionListeners = new ArrayList( );
private Class m_resourceClass;
private Class m_serviceClass;
private String m_portComponentName;
private MetadataConfiguration m_metadataConfig;
/**
* DOCUMENT_ME
*
* @param jndiLocation DOCUMENT_ME
*/
public void setCacheLocation( String jndiLocation )
{
m_cacheLocation = jndiLocation;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String getCacheLocation( )
{
return m_cacheLocation;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public abstract org.apache.ws.resource.NamespaceVersionHolder getNamespaceSet( );
/**
* Returns the EndpointReference associated with this Resource. Only the required fields will be filled in (i.e.
* Address) AND the ReferenceProperty for the ResourceKey (if not a singleton)
* <p/>
* If the resourceKey is not equal to null ( not a singleton ), the reference properties will contain the key.
*
* @param resourceId the resource identifier, or null if the resource is a singleton
*
* @return an EndpointReference (EPR) for the resource
*/
public EndpointReference getEndpointReference( Object resourceId )
{
String endpointAddress =
JaxRpcPlatform.getJaxRpcPlatform( ).getEndpointUrl( WsrfRuntime.getRuntime( ).getBaseWebappUrl( )
.toString( ),
getServiceName( ).getLocalPart( ) );
String wsAddressingURI = getNamespaceSet( ).getAddressingNamespace( );
XmlBeansEndpointReference xBeansEPR = new XmlBeansEndpointReference( endpointAddress, wsAddressingURI );
if ( resourceId != null )
{
XmlObject resourceIdRefParam = XmlBeanUtils.createElement( m_resourceIdRefParamName );
XmlBeanUtils.setValue( resourceIdRefParam,
resourceId.toString( ) );
xBeansEPR.addReferenceParameter( resourceIdRefParam );
}
xBeansEPR.setPortTypeQName( getPortType( ) );
xBeansEPR.setServicePortName( getServicePortName( ) );
xBeansEPR.setServiceQName( getServiceName( ) );
return xBeansEPR;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public abstract QName getPortType( );
/**
* DOCUMENT_ME
*
* @param config DOCUMENT_ME
*/
public void setMetadataConfig( MetadataConfiguration config )
{
m_metadataConfig = config;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public MetadataConfiguration getMetadataConfig( )
{
return m_metadataConfig;
}
/**
* DOCUMENT_ME
*
* @param portComponentName DOCUMENT_ME
*/
public void setPortComponentName( String portComponentName )
{
m_portComponentName = portComponentName;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String getPortComponentName( )
{
return m_portComponentName;
}
/**
* DOCUMENT_ME
*
* @param resourceClass DOCUMENT_ME
*/
public void setResourceClass( Class resourceClass )
{
if ( ( resourceClass != null ) && !Resource.class.isAssignableFrom( resourceClass ) )
{
throw new IllegalArgumentException( "Specified resource class '" + resourceClass.getName( )
+ "' does not implement the " + Resource.class.getName( )
+ " interface." );
}
m_resourceClass = resourceClass;
}
/**
* DOCUMENT_ME
*
* @param resourceClassName DOCUMENT_ME
*
* @deprecated use {@link #setResourceClass(Class)} instead
*/
public void setResourceClassName( String resourceClassName )
{
try
{
m_resourceClass = Class.forName( resourceClassName );
}
catch ( ClassNotFoundException cnfe )
{
throw new RuntimeException( cnfe );
}
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String getResourceClassName( )
{
return ( m_resourceClass != null ) ? m_resourceClass.getName( ) : null;
}
/**
* DOCUMENT_ME
*
* @param serviceClass
*/
public void setServiceClass( Class serviceClass )
{
m_serviceClass = serviceClass;
}
/**
* DOCUMENT_ME
*
* @param serviceClassName DOCUMENT_ME
*
* @deprecated use {@link #setServiceClass(Class)} instead
*/
public void setServiceClassName( String serviceClassName )
{
try
{
m_serviceClass = Class.forName( serviceClassName );
}
catch ( ClassNotFoundException cnfe )
{
throw new RuntimeException( cnfe );
}
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String getServiceClassName( )
{
return ( m_serviceClass != null ) ? m_serviceClass.getName( ) : null;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public abstract QName getServiceName( );
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public abstract String getServicePortName( );
/**
* Returns true if the home has been initialized, else false
*
* @return true if the home has been initialized, else false
*/
public boolean isInitialized( )
{
return m_initialized;
}
/**
* DOCUMENT_ME
*
* @param name DOCUMENT_ME
*/
public void setResourceIdentifierReferenceParameterName( String name )
{
m_resourceIdRefParamName = QName.valueOf( name );
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String getResourceIdentifierReferenceParameterName( )
{
//case of singleton...
if ( m_resourceIdRefParamName == null )
{
return null;
}
return m_resourceIdRefParamName.toString( );
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public QName getResourceIdentifierReferenceParameterQName( )
{
return m_resourceIdRefParamName;
}
/**
* DOCUMENT_ME
*
* @param delay DOCUMENT_ME
*/
public void setSweeperDelay( long delay )
{
m_sweeperDelay = delay;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public long getSweeperDelay( )
{
return m_sweeperDelay;
}
/**
* DOCUMENT_ME
*
* @param targetNamespace DOCUMENT_ME
*/
public void setWsdlTargetNamespace( String targetNamespace )
{
m_wsdlTargetNamespace = targetNamespace;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String getWsdlTargetNamespace( )
{
return m_wsdlTargetNamespace;
}
/**
* @see ResourceHome#add(org.apache.ws.resource.Resource)
*/
public boolean add( Resource resource )
throws IllegalResourceTypeException
{
boolean resourceWasAdded = true;
if ( !m_resourceClass.isAssignableFrom( resource.getClass( ) ) )
{
throw new IllegalResourceTypeException( "This home only supports resources of type "
+ m_resourceClass.getName( ) );
}
if ( m_resources == null )
{
m_resources = getResourceMap( ); // in case this.init() was never called for some reason
}
try
{
initEndpointReference( resource );
resource.init( );
}
catch ( RuntimeException re )
{
re.printStackTrace( );
throw new RuntimeException( MSG.getMessage( Keys.FAILED_TO_INIT_RESOURCE, resource, re ), re );
}
LOG.debug( MSG.getMessage( Keys.ADDING_RESOURCE_WITH_ID,
resource.getID( ),
getClass( ).getName( ) ) );
m_resources.put( getNonNullKey( resource.getID( ) ),
resource );
scheduleSweeperTask( );
notifyResourceCreatedListeners( resource );
updateCache( resource );
return resourceWasAdded;
}
/**
* Adds a listener for ResourceCreationEvents
*
* @param listener
*/
public void addResourceCreationListener( ResourceCreationListener listener )
{
m_creationListeners.add( listener );
}
/**
* Adds a listener for ResourceDestructionEvents
*
* @param listener
*/
public void addResourceDestructionListener( ResourceDestructionListener listener )
{
m_destructionListeners.add( listener );
}
/**
* DOCUMENT_ME
*
* @param context DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public Object extractResourceIdentifier( ResourceContext context )
{
if ( getResourceIdentifierReferenceParameterName( ) == null )
{
return null;
}
try
{
SOAPHeader soapHeader = context.getSOAPMessage( ).getSOAPHeader( );
Iterator resourceIdElemsIter =
soapHeader.getChildElements( NameUtils.toName( getResourceIdentifierReferenceParameterQName( ) ) );
if ( !resourceIdElemsIter.hasNext( ) )
{
throw new FaultException( Soap1_1Constants.FAULT_CLIENT,
"The expected resource identifier reference parameter named "
+ getResourceIdentifierReferenceParameterName( )
+ " was not found in the SOAP header." );
}
SOAPHeaderElement resourceIdElem = (SOAPHeaderElement) resourceIdElemsIter.next( );
if ( resourceIdElemsIter.hasNext( ) )
{
throw new FaultException( Soap1_1Constants.FAULT_CLIENT,
"More than one resource identifier reference parameter named "
+ getResourceIdentifierReferenceParameterName( )
+ " was found in the SOAP header. Exactly one is expected." );
}
return resourceIdElem.getValue( );
}
catch ( SOAPException soape )
{
throw new JAXRPCException( soape );
}
}
/**
* DOCUMENT_ME
*
* @param epr the endpoint reference of a WS-Resource
*
* @return DOCUMENT_ME
*/
public Object extractResourceIdentifier( EndpointReference epr )
{
QName resourceIdElemName = getResourceIdentifierReferenceParameterQName( );
if ( resourceIdElemName == null ) // singletons have a null id
{
return null;
}
String resourceId = null;
if ( resourceIdElemName != null )
{
Object[] refProps = epr.getReferenceProperties( );
for ( int i = 0; i < refProps.length; i++ )
{
XmlObject refPropXBean = (XmlObject) refProps[i];
if ( XmlBeanUtils.getName( refPropXBean ).equals( resourceIdElemName ) )
{
resourceId = XmlBeanUtils.getValue( refPropXBean );
}
}
if ( resourceId == null )
{
Object[] refParams = epr.getReferenceParameters( );
for ( int i = 0; i < refParams.length; i++ )
{
XmlObject refParamXBean = (XmlObject) refParams[i];
if ( XmlBeanUtils.getName( refParamXBean ).equals( resourceIdElemName ) )
{
resourceId = XmlBeanUtils.getValue( refParamXBean );
}
}
}
if ( resourceId == null )
{
throw new FaultException( Soap1_1Constants.FAULT_CLIENT,
"The expected resource identifier reference parameter named "
+ getResourceIdentifierReferenceParameterName( )
+ " was not found in the SOAP header." );
}
}
return resourceId;
}
/**
* @see ResourceHome#find(Object)
*/
public Resource find( Object resourceId )
throws ResourceUnknownException,
ResourceException
{
LOG.debug( MSG.getMessage( Keys.FINDING_RESOURCE_WITH_KEY,
String.valueOf( resourceId ) ) );
Resource resource = null;
synchronized ( m_resources )
{
//Lock lock = acquireLock( resourceId );
//try
//{
resource = get( resourceId );
updateCache( resource );
//}
//finally
//{
// lock.release();
//}
}
return resource;
}
/**
* Initializes this home. Should be called <em>after</em> setters have been called on all bean properties.
*
* @throws Exception on error
*/
public void init( )
throws Exception
{
synchronized ( this )
{
if ( m_initialized )
{
return;
}
LOG.debug( MSG.getMessage( Keys.INIT_HOME ) );
if ( m_resourceClass == null )
{
throw new ResourceException( "The resourceClass property of this home is not defined." );
}
if ( PersistentResource.class.isAssignableFrom( m_resourceClass ) )
{
m_resourceIsPersistent = true;
}
Context initialContext = new InitialContext( );
m_resources = getResourceMap( );
m_lockManager = new LockManager( );
if ( ScheduledResourceTerminationResource.class.isAssignableFrom( m_resourceClass ) )
{
initSweeper( initialContext );
}
initCachePolicy( new InitialContext( ) );
m_initialized = true;
}
}
/**
* @see ResourceHome#remove(Object)
*/
public void remove( Object resourceId )
throws ResourceUnknownException,
ResourceException
{
Resource resource = null;
Lock lock = acquireLock( resourceId );
try
{
resource = get( resourceId );
try
{
resource.destroy( );
}
catch ( RuntimeException re )
{
throw new ResourceException( MSG.getMessage( Keys.FAILED_TO_DESTROY_RESOURCE, resource, re ) );
}
Resource removedResource = (Resource) m_resources.remove( getNonNullKey( resourceId ) );
if ( removedResource instanceof PropertiesResource )
{
notifyResourceDeletedListeners( removedResource );
}
LOG.debug( MSG.getMessage( Keys.REMOVED_RESOURCE_WITH_KEY,
resource.getClass( ).getName( ),
String.valueOf( resourceId ) ) );
if ( m_cache != null )
{
m_cache.remove( resource );
}
}
finally
{
lock.release( );
}
}
/**
* Removes a listener for ResourceCreationEvents
*
* @param listener
*
* @return true if the listener was removed, else false
*/
public boolean removeResourceCreationListener( ResourceCreationListener listener )
{
return m_creationListeners.remove( listener );
}
/**
* Removes a listener for ResourceDestructionEvents
*
* @param listener
*
* @return true if the listener was removed, else false
*/
public boolean removeResourceDestructionListener( ResourceDestructionListener listener )
{
return m_destructionListeners.remove( listener );
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
protected abstract Map getResourceMap( );
/**
* This method uses reflection to create an instance of a Resource which contains an empty constructor. It will not
* work with Resources which do not have an empty constructor.
* <p/>
* Note: the returned Resource will an EndpointReference associated with it.
*
* @param id the resource identifier
*
* @return a resource of the type associated with this home
*
* @throws ResourceException
*/
protected Resource createInstance( Object id )
throws ResourceException
{
LOG.debug( MSG.getMessage( Keys.CREATING_RESOURCE_WITH_ID, id ) );
Resource resource = createInstanceViaSpringBeanFactory( );
if ( resource == null )
{
resource = createInstanceViaReflection( );
}
if ( resource.getID( ) == null )
{
resource.setID( id );
}
return resource;
}
/**
* DOCUMENT_ME
*
* @param id DOCUMENT_ME
*
* @return DOCUMENT_ME
*
* @throws ResourceException DOCUMENT_ME
*/
protected Resource createNewInstanceAndLoad( Object id )
throws ResourceException
{
Resource resource = createInstance( id );
LOG.debug( MSG.getMessage( Keys.LOADING_RESOURCE_FROM_PERSISTENCE,
String.valueOf( id ) ) );
( (PersistentResource) resource ).load( );
if ( ResourceSweeper.isExpired( resource ) )
{
throw new ResourceUnknownException( getNonNullKey( id ),
getServicePortName( ) );
}
return resource;
}
/**
* Creates a synschronized map for storing {@link Resource}s. If the resource is persistent, a {@link ReferenceMap}
* is used, otherwise a {@link HashMap} is used. Provided for the convenience of subclasses, which are responsible
* for creating a map of resources and maintaining a static reference to that map.
*
* @param isPersistent if the resource is persistent
*
* @return a synschronized map for storing {@link Resource}s
*/
protected static Map createResourceMap( boolean isPersistent )
{
Map resourceMap;
if ( isPersistent )
{
resourceMap = new ReferenceMap( ReferenceMap.HARD, ReferenceMap.SOFT, true );
}
else
{
resourceMap = new HashMap( );
}
return Collections.synchronizedMap( resourceMap );
}
/**
* DOCUMENT_ME
*
* @param initialContext DOCUMENT_ME
*
* @throws NamingException DOCUMENT_ME
*/
protected void initCachePolicy( Context initialContext )
throws NamingException
{
if ( m_cacheLocation != null )
{
m_cache = (Cache) XmlBeanJndiUtils.lookup( initialContext, m_cacheLocation, Cache.class );
}
}
/**
* DOCUMENT_ME
*
* @param obj DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
Object getNonNullKey( Object obj )
{
return ( obj != null ) ? obj : SINGLETON_KEY;
}
private TimerManager getTimerManager( Context initialContext )
{
TimerManager timerManager;
try
{
timerManager = (TimerManager) initialContext.lookup( CONTEXT_NAME_J2EE_TIMER_MANAGER );
}
catch ( NamingException ne )
{
try
{
timerManager = (TimerManager) initialContext.lookup( JndiConstants.CONTEXT_NAME_DEFAULT_TIMER );
}
catch ( NamingException ne2 )
{
timerManager = new TimerManagerImpl( );
}
}
LOG.debug( MSG.getMessage( Keys.TIMER_MANAGER_IMPL,
timerManager.getClass( ).getName( ) ) );
return timerManager;
}
private Lock acquireLock( Object resourceId )
throws ResourceException
{
Lock lock = m_lockManager.getLock( getNonNullKey( resourceId ) );
try
{
lock.acquire( );
}
catch ( InterruptedException ie )
{
throw new ResourceException( ie );
}
return lock;
}
private Resource createInstanceViaReflection( )
throws ResourceException
{
Resource resource;
try
{
resource = (Resource) m_resourceClass.newInstance( );
}
catch ( Exception e )
{
throw new ResourceException( e );
}
return resource;
}
private Resource createInstanceViaSpringBeanFactory( )
throws ResourceException
{
Resource resource = null;
ListableBeanFactory beanFactory = WsrfRuntime.getRuntime( ).getBeanFactory( );
if ( beanFactory != null )
{
String[] beanDefNames = beanFactory.getBeanNamesForType( m_resourceClass );
if ( beanDefNames.length != 0 )
{
if ( beanDefNames.length > 1 )
{
LOG.warn( "More than one bean definition found for resource of type " + m_resourceClass.getName( ) );
}
try
{
resource = (Resource) beanFactory.getBean( beanDefNames[0], m_resourceClass );
}
catch ( BeansException be )
{
throw new ResourceException( "Failed to instantiate " + getResourceClassName( )
+ " resource via Spring bean factory.", be );
}
}
}
return resource;
}
private Resource get( Object resourceId )
throws ResourceException
{
LOG.debug( MSG.getMessage( Keys.GETTING_RESOURCE_WITH_ID,
resourceId,
getClass( ).getName( ) ) );
Resource resource = (Resource) m_resources.get( getNonNullKey( resourceId ) );
if ( resource == null )
{
if ( !m_resourceIsPersistent )
{
throw new ResourceUnknownException( resourceId,
getServicePortName( ) );
}
add( createNewInstanceAndLoad( resourceId ) );
}
return resource;
}
private void initEndpointReference( Resource resource )
{
if ( resource.getEndpointReference( ) == null )
{
resource.setEndpointReference( getEndpointReference( resource.getID( ) ) );
}
}
private void initSweeper( Context initialContext )
{
m_sweeper = new Sweeper( this,
m_resources,
getTimerManager( initialContext ),
m_sweeperDelay );
}
/**
* This method is used to notify listeners a resource has been created.
*
* @param resource The Resource which was created
*/
private void notifyResourceCreatedListeners( Resource resource )
{
for ( int i = 0; i < m_creationListeners.size( ); i++ )
{
ResourceCreationListener resourceCreationListener =
(ResourceCreationListener) m_creationListeners.get( i );
resourceCreationListener.creationOccurred( new ResourceCreationEvent( resource ) );
}
}
/**
* This method is used to notify listeners a resource has been deleted.
*
* @param resource The EndpointReference for the Resource which was created
*/
private void notifyResourceDeletedListeners( Resource resource )
{
for ( int i = 0; i < m_destructionListeners.size( ); i++ )
{
ResourceDestructionListener resourceDestructionListener =
(ResourceDestructionListener) m_destructionListeners.get( i );
ResourceDestructionEvent event = new ResourceDestructionEvent( resource );
resourceDestructionListener.destructionOccurred( event );
}
}
private void scheduleSweeperTask( )
{
if ( m_sweeper != null )
{
m_sweeper.schedule( );
}
}
private void updateCache( Resource resource )
{
if ( m_cache != null )
{
m_cache.update( resource );
}
}
/**
* This ResourceSweeper implementation just returns the resources currently stored in the map. The reason is that
* the sweeper doesn't have to reactivate/reload a persistent resource if the resource object was reclaimed. So
* lifetime checks are not done on reclained resources. Lifetime checks have to be done on resource load.
*/
private static class Sweeper
extends ResourceSweeper
{
private TimerManager m_timerManager;
private Timer m_timer;
private long m_delay;
/**
* Creates a new {@link Sweeper} object.
*
* @param home DOCUMENT_ME
* @param resources DOCUMENT_ME
* @param timerManager DOCUMENT_ME
* @param delay DOCUMENT_ME
*/
public Sweeper( ResourceHome home,
Map resources,
TimerManager timerManager,
long delay )
{
super( home, resources );
m_timerManager = timerManager;
m_delay = delay;
}
/**
* DOCUMENT_ME
*
* @param timer DOCUMENT_ME
*/
public void timerExpired( Timer timer )
{
super.timerExpired( timer );
cancel( );
if ( !m_resources.isEmpty( ) )
{
schedule( );
}
}
/**
* Schedules this resource sweeper.
*/
synchronized void schedule( )
{
if ( m_timer == null )
{
LOG.debug( MSG.getMessage( Keys.SCHEDULE_RESOURCE_SWEEPER ) );
m_timer = m_timerManager.schedule( this, m_delay );
}
}
/**
* Cancels this resource sweeper.
*/
private synchronized void cancel( )
{
if ( m_timer != null )
{
LOG.debug( MSG.getMessage( Keys.CANCEL_RESOURCE_SWEEPER ) );
m_timer = null;
}
}
}
}