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>