You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by bl...@apache.org on 2002/09/19 00:45:34 UTC
cvs commit: jakarta-avalon-excalibur/container/src/java/org/apache/excalibur/container/classloader DirectoryChangeListener.java DirectoryClassManager.java
bloritsch 2002/09/18 15:45:34
Added: container/src/java/org/apache/excalibur/container/classloader
DirectoryChangeListener.java
DirectoryClassManager.java
Log:
add ClassLoaderManager so that we can manage a directory of reloadable jars
Revision Changes Path
1.1 jakarta-avalon-excalibur/container/src/java/org/apache/excalibur/container/classloader/DirectoryChangeListener.java
Index: DirectoryChangeListener.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.excalibur.container.classloader;
import java.io.File;
/**
* The DirectoryChangeListener lets the DirectoryClassManager notify an
* external class if the directory changed.
*
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
*/
public interface DirectoryChangeListener
{
void directoryChanged( File dir, JarEntries oldEntries, JarEntries newEntries );
}
1.1 jakarta-avalon-excalibur/container/src/java/org/apache/excalibur/container/classloader/DirectoryClassManager.java
Index: DirectoryClassManager.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.excalibur.container.classloader;
import java.net.URL;
import java.io.InputStream;
import java.io.IOException;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
/**
* A ClassLoader that lists all the entries of a particular type. Using
* this classloader we can resolve all the Avalon types and services,
* and iterate through the list. In all other ways, this
* <code>ClassLoader</code> behaves identically to the
* @link{java.net.URLClassLoader}
*
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
*/
public class DirectoryClassManager
{
private final static long RECHECK_PERIOD = 60 * 1000; // One minute
private final ClassLoader m_parentClassLoader;
private final Map m_classLoaders;
private final Map m_modifiedMap;
private final Timer m_timer;
private final File m_rootDir;
private DirectoryChangeListener m_listener = null;
public DirectoryClassManager( String path )
throws IOException
{
this( new File( path ) );
}
public DirectoryClassManager( File rootDir )
throws IOException
{
this( rootDir, Thread.currentThread().getContextClassLoader() );
}
public DirectoryClassManager( File rootDir, ClassLoader parent )
throws IOException
{
if ( rootDir.isFile() )
{
throw new IOException( "The File object passed in must be a directory" );
}
m_rootDir = rootDir;
File[] entries = rootDir.listFiles();
m_parentClassLoader = parent;
m_classLoaders = new HashMap( entries.length );
m_modifiedMap = new HashMap( entries.length );
m_classLoaders.put( m_rootDir,
new ComponentClassLoader( new URL[] { m_rootDir.toURL() }, m_parentClassLoader ) );
m_modifiedMap.put( m_rootDir, new Long( m_rootDir.lastModified() ) );
for ( int i = 0; i < entries.length; i++ )
{
if ( entries[i].isFile() )
{
m_classLoaders.put( entries[i],
new ComponentClassLoader( new URL[] { entries[i].toURL() }, m_parentClassLoader ) );
m_modifiedMap.put( entries[i], new Long( entries[i].lastModified() ) );
}
}
m_timer = new Timer( true );
m_timer.scheduleAtFixedRate( new DCMTimerTask(), RECHECK_PERIOD, RECHECK_PERIOD );
}
public void setListener( DirectoryChangeListener listener )
{
m_listener = listener;
}
public Class loadClass( String className )
throws ClassNotFoundException
{
Iterator it = m_classLoaders.values().iterator();
Class klass = null;
while ( it.hasNext() && klass == null)
{
ClassLoader loader = (ClassLoader) it.next();
try
{
klass = loader.loadClass( className );
}
catch ( Exception e )
{
// ignore
}
}
if ( null == klass )
{
throw new ClassNotFoundException( className );
}
return klass;
}
public URL getResource( String path )
{
Iterator it = m_classLoaders.values().iterator();
URL resource = null;
while ( it.hasNext() && resource == null)
{
ClassLoader loader = (ClassLoader) it.next();
try
{
resource = loader.getResource( path );
}
catch ( Exception e )
{
// ignore
}
}
return resource;
}
public InputStream getResourceAsStream( String path )
throws IOException
{
return getResource( path ).openConnection().getInputStream();
}
protected void finalize()
{
m_timer.cancel();
}
private final class DCMTimerTask extends TimerTask
{
public void run()
{
try
{
Iterator it = m_modifiedMap.keySet().iterator();
while ( it.hasNext() )
{
File curFile = (File) it.next();
long lastModified = curFile.lastModified();
if ( lastModified > ( (Long) m_modifiedMap.get( curFile ) ).longValue() )
{
ComponentClassLoader loader = (ComponentClassLoader) m_classLoaders.get( curFile );
JarEntries oldEntries = loader.getEntries();
loader = new ComponentClassLoader( new URL[] { curFile.toURL() }, m_parentClassLoader );
m_classLoaders.put( curFile, loader );
JarEntries newEntries = loader.getEntries();
if ( null != m_listener )
{
m_listener.directoryChanged( curFile, oldEntries, newEntries );
}
}
}
}
catch ( Exception e )
{
// ignore for now
}
}
}
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>