package org.jboss.soa.esb.listeners.gateway.remotestrategies.cache;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import org.apache.log4j.Logger;
import org.jboss.cache.CacheException;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.TreeCache;
import org.jboss.cache.TreeCacheListener;
import org.jboss.soa.esb.util.ClassUtil;
/**
* Implements a cache of file names which can be replicated in a cluster.
*
* See the <a href="http://labs.jboss.com/jbosscache">JBoss Cache</a> docs
* for details on configuring the cache.
*
* @author <a href="daniel.bevenius@redpill.se">Daniel Bevenius</a>
*
*/
public class FtpFileCache
{
@SuppressWarnings("unused")
private Logger log = Logger.getLogger( FtpFileCache.class );
/**
* Default configuration file for jboss cache.
* Used if no config is specified upon calling the constructor.
* Note that this file must then exist on the classpath
*/
private static final String DEFAULT_CONFIG_FILE = "/ftpfile-cache-config.xml";
/**
* The fqn to use.
*/
private String fqn = "/ftp/cache/";
/**
* The configuration file used to configure the tree cache
*/
private String config;
/**
* The JBoss TreeCache instance
*/
private TreeCache treeCache;
/**
*
* @param config either an absolute path of a relative path
* @throws Exception
*/
public FtpFileCache ( String config ) throws FtpFileCacheException
{
if ( config == null )
config = DEFAULT_CONFIG_FILE;
this.config = config;
InputStream in = null;
try
{
treeCache = new TreeCache();
in = getConfigInputStream( this.config );
PropertyConfigurator configurator = new PropertyConfigurator();
configurator.configure( treeCache, in );
}
catch ( Exception e )
{
log.error( e );
throw new FtpFileCacheException ( e );
}
finally
{
close( in );
}
}
/**
* Gets an input stream from the specified path.
*
* If the path denotes a file on the filesystem, that file
* will be used.
* If a file is not found in the filesystem, this method will look
* for the file on the classpath.
*
* @param path the path to the JBossCache configuration file
* @return InputStream the inputstream for the passed-in path
*/
protected InputStream getConfigInputStream( final String path )
{
InputStream in = null;
File configFile = new File( path );
if ( configFile.exists() )
{
log.debug("Reading jboss cache configuration from : " + path );
try
{
in = new FileInputStream ( path );
}
catch (FileNotFoundException e)
{
log.error( e );
}
}
else
{
log.debug("Reading jgroups configuration classpath : " + path );
in = ClassUtil.getResourceAsStream( path, getClass() );
}
return in;
}
/**
* Start the cache
* @throws Exception
*/
public void start() throws FtpFileCacheException
{
try
{
treeCache.startService();
}
catch (Exception e)
{
log.error( e );
throw new FtpFileCacheException( e );
}
}
/**
* Stops the cache
*
*/
public void stop()
{
treeCache.stopService();
}
/**
* Will add the filename to the cache.
*
* @param fileName
* @throws CacheException
*/
public void putFileName( final String fileName) throws CacheException
{
treeCache.put ( fqn, fileName, fileName );
}
/**
* Will get the filename if it exists in the cache.
*
* @param fileName
* @throws CacheException
*/
public Object getFileName( final String fileName) throws CacheException
{
return treeCache.get ( fqn, fileName );
}
/**
* Removed the fileName from the cache if it exist there
*
* @param fileName
* @return Object the value of the removed object
* @throws CacheException
*/
public Object deleteFile( final String fileName ) throws CacheException
{
return treeCache.remove( fqn, fileName );
}
/**
* Checks to see if the filename exists in the cache
*
* @param fileName the filename to look for
* @return true if the file exists in the cache
*/
public boolean containsFile( final String fileName )
{
return treeCache.exists( fqn, fileName );
}
/**
* Gets the a string of all files in the cache
* @return String
*/
public String getCache()
{
return treeCache.print( fqn );
}
public String getFqn()
{
return fqn;
}
public void setFqn(String fqn)
{
this.fqn = fqn;
}
public String getConfigFile( )
{
return config;
}
/**
* Removes all data under the fqn, but not the fqn
* itself
*
* @throws CacheException
*/
public void removeAll() throws CacheException
{
treeCache.removeData( fqn );
}
public void setDeleteOnEviction()
{
treeCache.addTreeCacheListener( new DeleteOnEvictTreeCacheListener( treeCache) );
}
public void addCacheListener( final TreeCacheListener listener )
{
if ( listener != null )
treeCache.addTreeCacheListener( listener );
}
public Map getCacheListeners()
{
return treeCache.getTreeCacheListeners();
}
public void setCacheListener( final Class cacheListenerClass ) throws FtpFileCacheException
{
if ( cacheListenerClass == null )
return;
try
{
Constructor constructor = cacheListenerClass.getConstructor( TreeCache.class );
Object object = constructor.newInstance( treeCache );
if ( object instanceof TreeCacheListener )
{
TreeCacheListener listener = ( TreeCacheListener ) object;
treeCache.addTreeCacheListener( listener );
}
}
catch (SecurityException e)
{
throw createFtpFileCacheException( "SecurityException while trying set the CacheListener:", e );
}
catch (NoSuchMethodException e)
{
throw createFtpFileCacheException( "NoSuchMethodException while trying set the CacheListener:", e );
}
catch (IllegalArgumentException e)
{
throw createFtpFileCacheException( "IllegalArgumentException while trying set the CacheListener:", e );
}
catch (InstantiationException e)
{
throw createFtpFileCacheException( "InstantiationException while trying set the CacheListener:", e );
}
catch (IllegalAccessException e)
{
throw createFtpFileCacheException( "IllegalAccessException while trying set the CacheListener:", e );
}
catch (InvocationTargetException e)
{
throw createFtpFileCacheException( "InvocationTargetException while trying set the CacheListener:", e );
}
}
private FtpFileCacheException createFtpFileCacheException( final String msg, Exception e )
{
log.error( msg, e );
return new FtpFileCacheException( e );
}
private void close( Closeable c )
{
if ( c == null )
return;
try
{
c.close();
}
catch ( IOException e )
{
log.warn( "Error while trying to close Closable", e);
}
}
public void destroy()
{
log.info( "destroy method of FtpFileCache called" );
treeCache.destroy();
}
}