Package org.apache.ws.resource.impl

Source Code of org.apache.ws.resource.impl.AbstractResourceHome$Sweeper

/*=============================================================================*
*  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.resource.InvalidResourceKeyException;
import org.apache.ws.resource.JndiConstants;
import org.apache.ws.resource.NoSuchResourceException;
import org.apache.ws.resource.PersistenceCallback;
import org.apache.ws.resource.Resource;
import org.apache.ws.resource.ResourceException;
import org.apache.ws.resource.ResourceHome;
import org.apache.ws.resource.ResourceKey;
import org.apache.ws.resource.PropertiesResource;
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.resource.properties.ResourcePropertySet;
import org.apache.ws.util.Cache;
import org.apache.ws.util.i18n.Messages;
import org.apache.ws.util.jndi.Initializable;
import org.apache.ws.util.jndi.JNDIUtils;
import org.apache.ws.util.lock.Lock;
import org.apache.ws.util.lock.LockManager;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
* LOG-DONE
* An implementation of the <code>ResourceHome</code> interface. This implementation was designed to work with resources
* that implement the {@link PersistenceCallback PersistenceCallback} interface as well as memory resident resources. If
* the resource class implements the {@link PersistenceCallback 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 PersistenceCallback#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>
*    &lt;parameter&gt;
*     &lt;name&gt;sweeperDelay&lt;/name&gt;
*     &lt;value&gt;60000&lt;/value&gt;
*    &lt;/parameter&gt;
* </pre>
* <li> resourceClass - configures the name of the resource class. For example:
* <pre>
*    &lt;parameter&gt;
*     &lt;name&gt;resourceClass&lt;/name&gt;
*     &lt;value&gt;org.globus.wsrf.samples.counter.PersistentCounter&lt;/value&gt;
*    &lt;/parameter&gt;
* </pre>
* <li> resourceKeyType - configures the key type class. By default <code>java.lang.String</code> is used. For example:
* <pre>
*    &lt;parameter&gt;
*     &lt;name&gt;resourceKeyType&lt;/name&gt;
*     &lt;value&gt;java.lang.Integer&lt;/value&gt;
*    &lt;/parameter&gt;
* </pre>
* <li> resourceKeyName - configures the key name. For example:
* <pre>
*    &lt;parameter&gt;
*     &lt;name&gt;resourceKeyName&lt;/name&gt;
*     &lt;value&gt;{http://counter.com}CounterKey&lt;/value&gt;
*    &lt;/parameter&gt;
* </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 P. Springer
*/
public abstract class AbstractResourceHome
   implements ResourceHome,
              Initializable
{
   private static final int DEFAULT_SWEEPER_DELAY = 60000;
   private static final Log LOG = LogFactory.getLog( AbstractResourceHome.class );
   public static final Messages MSG = MessagesImpl.getInstance();

   /**
    * DOCUMENT_ME
    */
   protected Map m_resources;

   /**
    * DOCUMENT_ME
    */
   protected String m_resourceClassName;
   private boolean  m_resourceIsPersistent;
   private String   m_resourceKeyClassName;
   private String   m_resourceKeyName;
   private String   m_wsdlTargetNamespace;
   private String   m_serviceClassName;

   /**
    * 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 Class         m_resourceClass;
   private Class         m_serviceClass;
   private Class         m_resourceKeyClass;

   /**
    * 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
    *
    * @param resourceClass DOCUMENT_ME
    */
   public void setResourceClassName( String resourceClass )
   {
      m_resourceClassName = resourceClass;
   }

   /**
    * DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    */
   public String getResourceClassName(  )
   {
      return m_resourceClassName;
   }

   /**
    * DOCUMENT_ME
    *
    * @param keyClass DOCUMENT_ME
    */
   public void setResourceKeyClassName( String keyClass )
   {
      m_resourceKeyClassName = keyClass;
   }

   /**
    * DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    */
   public String getResourceKeyClassName(  )
   {
      return m_resourceKeyClassName;
   }

   /**
    * DOCUMENT_ME
    *
    * @param keyName DOCUMENT_ME
    */
   public void setResourceKeyName( String keyName )
   {
      m_resourceKeyName = keyName;
   }

   /**
    * DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    */
   public String getResourceKeyName(  )
   {
      return m_resourceKeyName;
   }

   /**
    * DOCUMENT_ME
    *
    * @param serviceClass DOCUMENT_ME
    */
   public void setServiceClass( String serviceClass )
   {
      m_serviceClassName = serviceClass;
   }

   /**
    * DOCUMENT_ME
    *
    * @param className DOCUMENT_ME
    */
   public void setServiceClassName( String className )
   {
      m_serviceClassName = className;
   }

   /**
    * DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    */
   public String getServiceClassName(  )
   {
      return m_serviceClassName;
   }

   /**
    * 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;
   }

   /**
    * DOCUMENT_ME
    *
    * @param key DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    *
    * @throws ResourceException           if
    * @throws InvalidResourceKeyException DOCUMENT_ME
    */
   public Resource find( ResourceKey key )
   throws ResourceException
   {

      LOG.debug(MSG.getMessage(Keys.FINDING_RESOURCE_WITH_KEY, String.valueOf(key)));

      Resource resource = null;
      Lock lock = getLock(key);
       try
      {
         lock.acquire(  );
      }
      catch ( InterruptedException e )
      {
         throw new ResourceException( e );
      }

      try
      {
         resource = get( key );
         if ( m_cache != null )
         {
            m_cache.update( resource );
         }
      }
      finally
      {
         lock.release(  );
      }

      return resource;
   }

    private Lock getLock(ResourceKey key)
    {
        Lock lock;
        Object lockKey = getLookupKey(key);
        lock = m_lockManager.getLock( lockKey );
        return lock;
    }

    /**
    * DOCUMENT_ME
    *
    * @throws Exception DOCUMENT_ME
    */
   public synchronized void init(  )
   throws Exception
   {
      LOG.debug(MSG.getMessage(Keys.INIT_HOME));
      if ( m_initialized )
      {
         return;
      }

      /*if ( m_resourceKeyClassName == null )
         {
            m_resourceKeyClassName = String.class;
         }
       */


      if ( m_resourceClassName == null )
      {
         throw new Exception( MSG.getMessage( Keys.RESOURCE_CLASS_NULL) );
      }

      /*  if ( !Resource.class.isAssignableFrom( m_resourceClassName ) )
         {
            throw new Exception( "invalidResourceType: " + m_resourceClassName.getName() );
         }
         if ( PersistenceCallback.class.isAssignableFrom( m_resourceClassName ) )
         {
            m_resourceIsPersistent = true;
         }*/
      Context initialContext = new InitialContext(  );
      initResourceMap( initialContext );
      m_lockManager = new LockManager(  );
      if ( ScheduledResourceTerminationResource.class.isAssignableFrom( getResourceClass(  ) ) )
      {
         initSweeper( initialContext );
      }

      m_initialized = true;
   }

   /**
    * DOCUMENT_ME
    *
    * @param key DOCUMENT_ME
    *
    * @throws ResourceException           DOCUMENT_ME
    * @throws InvalidResourceKeyException DOCUMENT_ME
    */
   public void remove( ResourceKey key )
   throws ResourceException
   {

      Resource resource = null;
      Lock  lock = getLock(key);
       try
      {
         lock.acquire(  );
      }
      catch ( InterruptedException ie )
      {
         throw new ResourceException( ie );
      }

      try
      {
         resource = get( key );

            try
            {
               resource.destroy(  );
            }
            catch ( RuntimeException re )
            {
               throw new ResourceException( MSG.getMessage( Keys.FAILED_TO_DESTROY_RESOURCE, resource, re ));
            }


         m_resources.remove( getLookupKey(key) );

         LOG.debug( MSG.getMessage( Keys.REMOVED_RESOURCE_WITH_KEY, resource.getClass(  ).getName(  ) ,String.valueOf(key) ));
         if ( m_cache != null )
         {
            m_cache.remove( resource );
         }
      }
      finally
      {
         lock.release(  );
      }

      // TODO: send resource-terminated notification
   }

   /**
    * DOCUMENT_ME
    *
    * @param key      DOCUMENT_ME
    * @param resource DOCUMENT_ME
    */
   protected void add( ResourceKey key,
                       Resource    resource )
   {
      addResource( key, resource );
      if ( m_cache != null )
      {
         m_cache.update( resource );
      }
   }

   /**
    * DOCUMENT_ME
    *
    * @param key DOCUMENT_ME
    * @return DOCUMENT_ME
    *
    * @throws ResourceException DOCUMENT_ME
    * @throws IllegalStateException DOCUMENT_ME
    */
   protected Resource createInstance(ResourceKey key)
   throws ResourceException
   {
      LOG.debug(MSG.getMessage( Keys.CREATING_INSTANCE_WITH_KEY, String.valueOf(key)));
      Resource resource;
      try
      {
         resource = (Resource) getResourceClass(  ).newInstance(  );
      }
      catch ( Exception e )
      {
         throw new ResourceException( e );
      }

         resource.setID( key != null ? key.getValue() : null );

         try
         {
            LOG.debug(MSG.getMessage( Keys.INIT_RESOURCE_LIFECYCLE_INSTANCE, resource.getClass().getName()));
            resource.init();
         }
         catch ( RuntimeException re )
         {
            throw new ResourceException( MSG.getMessage( Keys.FAILED_TO_INIT_RESOURCE, resource, re ));
         }

      return resource;
   }

   /**
    * DOCUMENT_ME
    *
    * @param key DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    *
    * @throws ResourceException DOCUMENT_ME
    */
   protected Resource createNewInstanceAndLoad( ResourceKey key )
   throws ResourceException
   {
      Resource resource = createInstance( key);
      LOG.debug(MSG.getMessage( Keys.LOADING_RESORUCE_FROM_PERSISTENCE, String.valueOf(key)));
      ( (PersistenceCallback) resource ).load( key );
      return resource;
   }

   private Class getResourceClass(  )
   throws ClassNotFoundException, ResourceException
   {
      if ( m_resourceClass == null )
      {
         if ( m_resourceClassName != null )
         {
            m_resourceClass = Class.forName( m_resourceClassName );
         }
         else
         {
            throw new ClassNotFoundException( MSG.getMessage( Keys.RESOURCE_CLASSNAME_NOT_FOUND) );
         }
      }
      return m_resourceClass;
   }

   private void addResource( ResourceKey key,
                             Resource    resource )
   {
      LOG.debug(MSG.getMessage( Keys.ADDING_RESOURCE_FOR_KEY, String.valueOf(key)));
      m_resources.put( getLookupKey(key), resource );

      // schedule sweeper task if needed
      if ( m_sweeper != null )
      {
         m_sweeper.schedule(  );
      }
   }

   private Resource get( ResourceKey key )
   throws ResourceException
   {
      LOG.debug(MSG.getMessage( Keys.GET_RESOURCE_FOR_KEY,String.valueOf(key)));
       Object lookupKey = getLookupKey(key);
       Resource resource = (Resource) m_resources.get( lookupKey );
      if ( resource == null )
      {
         if ( m_resourceIsPersistent )
         {
            resource = createNewInstanceAndLoad( key );
            addResource( key, resource );
            if ( ResourceSweeper.isExpired( resource ) )
            {
               remove( key );
               throw new NoSuchResourceException(  );
            }
         }
         else
         {
            throw new NoSuchResourceException(  );
         }
      }

      return resource;
   }

    private Object getLookupKey(ResourceKey key)
    {
        Object lookupKey = key != null ? key : (Object)this;
        return lookupKey;
    }

    private void initCachePolicy( Context initialContext )
   throws NamingException
   {
      if ( m_cacheLocation != null )
      {
         m_cache = (Cache) JNDIUtils.lookup( initialContext, m_cacheLocation, Cache.class );
      }
   }

   private void initResourceMap( Context initialContext )
   throws NamingException
   {
      if ( m_resourceIsPersistent )
      {
         m_resources = new ReferenceMap( ReferenceMap.HARD, ReferenceMap.SOFT, true );
         initCachePolicy( initialContext );
      }
      else
      {
         m_resources = new HashMap(  );
      }

      m_resources = Collections.synchronizedMap( m_resources );
   }

   private void initSweeper( Context initialContext )
   throws NamingException
   {
      LOG.debug( MSG.getMessage( Keys.TIMER_LOOKUP_WITH_JNDI_NAME,JndiConstants.KEY_NAME_DEFAULT_TIMER ) );
      TimerManager timerManager = (TimerManager) initialContext.lookup( JndiConstants.KEY_NAME_DEFAULT_TIMER );

      // TimerManager timerManager = new TimerManagerImpl();
      m_sweeper = new Sweeper( this, m_resources, timerManager, m_sweeperDelay );
   }

   /**
    * 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(  );
         }
      }

      /**
       * DOCUMENT_ME
       *
       * @param key DOCUMENT_ME
       *
       * @return DOCUMENT_ME
       *
       * @throws ResourceException DOCUMENT_ME
       */
      protected Resource getResource( ResourceKey key )
      throws ResourceException
      {
         LOG.debug(MSG.getMessage( Keys.GET_RESOURCE_FOR_KEY, key.getValue()));
         return (Resource) m_resources.get( key );
      }

      /**
       * 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;
         }
      }
   }
}
TOP

Related Classes of org.apache.ws.resource.impl.AbstractResourceHome$Sweeper

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.