avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dona...@apache.org
Subject cvs commit: jakarta-avalon-excalibur/fortress/src/ng/org/apache/excalibur/fortress/util/classloader ComponentClassLoader.java DirectoryChangeListener.java DirectoryClassManager.java JarEntries.java JarScanner.java
Date Fri, 08 Nov 2002 07:06:14 GMT
donaldp     2002/11/07 23:06:13

  Modified:    fortress/src/ng/org/apache/excalibur/fortress/container
                        MetaDataContainer.java
               fortress/src/ng/org/apache/excalibur/fortress/container/commands
                        CheckTypeInfoCommand.java
  Added:       fortress/src/ng/org/apache/excalibur/fortress/util
                        AbstractServiceManager.java
               fortress/src/ng/org/apache/excalibur/fortress/util/classloader
                        ComponentClassLoader.java
                        DirectoryChangeListener.java
                        DirectoryClassManager.java JarEntries.java
                        JarScanner.java
  Log:
  Import the classloader work into fortress.
  
  Revision  Changes    Path
  1.2       +4 -4      jakarta-avalon-excalibur/fortress/src/ng/org/apache/excalibur/fortress/container/MetaDataContainer.java
  
  Index: MetaDataContainer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/fortress/src/ng/org/apache/excalibur/fortress/container/MetaDataContainer.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MetaDataContainer.java	8 Nov 2002 06:06:12 -0000	1.1
  +++ MetaDataContainer.java	8 Nov 2002 07:06:12 -0000	1.2
  @@ -64,9 +64,9 @@
   import org.apache.avalon.framework.service.ServiceException;
   import org.apache.avalon.framework.service.ServiceManager;
   import org.apache.avalon.framework.service.Serviceable;
  -import org.apache.excalibur.container.classloader.ComponentClassLoader;
  -import org.apache.excalibur.container.classloader.JarEntries;
  -import org.apache.excalibur.container.classloader.JarScanner;
  +import org.apache.excalibur.fortress.util.classloader.ComponentClassLoader;
  +import org.apache.excalibur.fortress.util.classloader.JarEntries;
  +import org.apache.excalibur.fortress.util.classloader.JarScanner;
   import org.apache.excalibur.event.Queue;
   import org.apache.excalibur.event.SinkException;
   import org.apache.excalibur.event.command.Command;
  
  
  
  1.2       +2 -2      jakarta-avalon-excalibur/fortress/src/ng/org/apache/excalibur/fortress/container/commands/CheckTypeInfoCommand.java
  
  Index: CheckTypeInfoCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/fortress/src/ng/org/apache/excalibur/fortress/container/commands/CheckTypeInfoCommand.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- CheckTypeInfoCommand.java	8 Nov 2002 06:06:12 -0000	1.1
  +++ CheckTypeInfoCommand.java	8 Nov 2002 07:06:13 -0000	1.2
  @@ -53,7 +53,6 @@
   import java.util.Map;
   import org.apache.avalon.framework.logger.Logger;
   import org.apache.avalon.framework.logger.NullLogger;
  -import org.apache.excalibur.container.classloader.JarEntries;
   import org.apache.excalibur.event.command.Command;
   import org.apache.excalibur.meta.info.ServiceDescriptor;
   import org.apache.excalibur.meta.info.StageDescriptor;
  @@ -62,6 +61,7 @@
   import org.apache.excalibur.meta.info.builder.ServiceBuilder;
   import org.apache.excalibur.meta.info.builder.TypeBuilder;
   import org.apache.excalibur.meta.verifier.ComponentVerifier;
  +import org.apache.excalibur.fortress.util.classloader.JarEntries;
   
   /**
    * Execute this command to verify all the entries in a @link{JarEntries} object.
  
  
  
  1.1                  jakarta-avalon-excalibur/fortress/src/ng/org/apache/excalibur/fortress/util/AbstractServiceManager.java
  
  Index: AbstractServiceManager.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.excalibur.fortress.util;
  
  import javax.naming.Context;
  import javax.naming.InitialContext;
  import javax.naming.NamingException;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.service.ServiceManager;
  
  /**
   * Abstract implementation of a <code>ServiceManager</code>.  This will
   * make it easier to implement ServiceManagers that use exposed management
   * services, as well as respect the hierarchical nature of ServiceManagers.
   *
   * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
   */
  public abstract class AbstractServiceManager implements ServiceManager
  {
      private final ServiceManager m_parent;
      private final Context m_context;
  
      public AbstractServiceManager()
      {
          this( null, null );
      }
  
      public AbstractServiceManager( ServiceManager parent )
      {
          this( parent, null );
      }
  
      public AbstractServiceManager( ServiceManager parent, Context initContext )
      {
          m_parent = parent;
  
          Context checkContext = initContext;
  
          if( null == checkContext )
          {
              // If there is a public context for services use it.
              try
              {
                  checkContext = new InitialContext();
              }
              catch( NamingException ne )
              {
                  checkContext = null;
              }
          }
  
          m_context = checkContext;
      }
  
      protected abstract boolean serviceExists( String role );
  
      protected abstract Object obtainService( String role ) throws ServiceException;
  
      public abstract void release( Object service );
  
      /**
       * The logic for testing if a service exists.  First we test ourselves,
       * second we test the parent ServiceManager if it exists, and lastly
       * we test the JNDI context if it exists.
       */
      public boolean hasService( String role )
      {
          boolean exists = serviceExists( role );
  
          if( !exists && null != m_parent )
          {
              exists = m_parent.hasService( role );
          }
  
          if( !exists && null != m_context )
          {
              exists = ( null != obtainServiceFromJNDI( role ) );
          }
  
          return exists;
      }
  
      /**
       * The logic for obtaining a service from a ServiceManager.  First we
       * try to get it from this ServiceManager, then we try to get it from the
       * parent manager.  If it exists, we will lastly try the JNDI context.
       */
      public Object lookup( String role )
          throws ServiceException
      {
          Object service = obtainService( role );
  
          if( null == service && null != m_parent )
          {
              service = obtainServiceFromParent( role );
          }
  
          if( null == service && null != m_context )
          {
              service = obtainServiceFromJNDI( role );
          }
  
          if( null == service )
          {
              throw new ServiceException( role, "Service does not exist." );
          }
  
          return service;
      }
  
      /**
       * Grabs the service from the parent.  If it does not exist, we
       * don't even try.
       */
      protected Object obtainServiceFromParent( String role )
      {
          Object service = null;
  
          if( m_parent.hasService( role ) )
          {
              try
              {
                  service = m_parent.lookup( role );
              }
              catch( ServiceException se )
              {
                  // ignore, it is already null
              }
          }
  
          return service;
      }
  
      /**
       * Grabs the service from the JNDI role.  Unfortunately, there is
       * no way to test the context before we grab it.  As a result we
       * have to incur the overhead of a lookup/exception if it is not
       * bound.
       */
      protected Object obtainServiceFromJNDI( String role )
      {
          Object service = null;
  
          try
          {
              service = m_context.lookup( role );
          }
          catch( NamingException se )
          {
              // ignore, it is already null
          }
  
          return service;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/fortress/src/ng/org/apache/excalibur/fortress/util/classloader/ComponentClassLoader.java
  
  Index: ComponentClassLoader.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.excalibur.fortress.util.classloader;
  
  import java.net.URL;
  import java.net.URLClassLoader;
  import java.net.URLStreamHandlerFactory;
  import java.util.Set;
  
  /**
   * 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 ComponentClassLoader extends URLClassLoader
  {
      private final JarEntries m_entries;
  
      /**
       * Constructs a new <code>ComponentClassLoader</code> and extracts a list
       * of services and components.
       */
      public ComponentClassLoader( URL[] classPath )
      {
          this( classPath, null, null );
      }
  
      /**
       * Constructs a new <code>ComponentClassLoader</code> and extracts a list
       * of services and components.
       */
      public ComponentClassLoader( URL[] classPath, ClassLoader parent )
      {
          this( classPath, parent, null );
      }
  
      /**
       * Constructs a new <code>ComponentClassLoader</code> and extracts a list
       * of services and components.
       */
      public ComponentClassLoader( URL[] classPath,
                                   ClassLoader parent,
                                   URLStreamHandlerFactory urlHandlerFactory )
      {
          super( classPath, parent, urlHandlerFactory );
          m_entries = new JarEntries();
  
          for( int i = 0; i < classPath.length; i++ )
          {
              m_entries.merge( JarScanner.scan( classPath[ i ] ) );
          }
      }
  
      /**
       * Return the JarEntries instead of directly working with the
       * arrays.
       */
      public JarEntries getEntries()
      {
          return m_entries;
      }
  
      /**
       * Expose the <code>addURL()</code> from the
       * @link{java.net.URLClassLoader} publically.  Please note that there is
       * no facility to remove a URL from the ClassLoader.
       */
      public void addURL( URL classPath )
      {
          super.addURL( classPath );
          m_entries.merge( JarScanner.scan( classPath ) );
      }
  
      /**
       * Get an array of the block names.  These are treated separately from
       * the generic <code>Type</code>
       */
      public String[] getBlockEntries()
      {
          Set blocks = m_entries.getBlockEntries();
          return (String[])blocks.toArray( new String[ blocks.size() ] );
      }
  
      /**
       * Get an array of the type names.  These are treated separately from
       * the Phoenix specific <code>Block</code>
       */
      public String[] getTypeEntries()
      {
          Set types = m_entries.getTypeEntries();
          return (String[])types.toArray( new String[ types.size() ] );
      }
  
      /**
       * Get an array of the service names.
       */
      public String[] getServiceEntries()
      {
          Set services = m_entries.getServiceEntries();
          return (String[])services.toArray( new String[ services.size() ] );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/fortress/src/ng/org/apache/excalibur/fortress/util/classloader/DirectoryChangeListener.java
  
  Index: DirectoryChangeListener.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.excalibur.fortress.util.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/fortress/src/ng/org/apache/excalibur/fortress/util/classloader/DirectoryClassManager.java
  
  Index: DirectoryClassManager.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.excalibur.fortress.util.classloader;
  
  import java.io.File;
  import java.io.IOException;
  import java.io.InputStream;
  import java.net.URL;
  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
              }
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/fortress/src/ng/org/apache/excalibur/fortress/util/classloader/JarEntries.java
  
  Index: JarEntries.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.excalibur.fortress.util.classloader;
  
  import java.util.Collections;
  import java.util.HashSet;
  import java.util.Set;
  
  /**
   * 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 JarEntries
  {
      private final Set m_blocks;
      private final Set m_types;
      private final Set m_services;
  
      /**
       * Constructs a new <code>ComponentClassLoader</code> and extracts a list
       * of services and components.
       */
      public JarEntries()
      {
          m_blocks = new HashSet();
          m_types = new HashSet();
          m_services = new HashSet();
      }
  
      /**
       * Allow JarScanner to add Block entries to this class.
       */
      protected void addBlockEntry( String entry )
      {
          m_blocks.add( entry );
      }
  
      /**
       * Allow JarScanner to add Type entries to this class.
       */
      protected void addTypeEntry( String entry )
      {
          m_types.add( entry );
      }
  
      /**
       * Allow JarScanner to add Service entries to this class.
       */
      protected void addServiceEntry( String entry )
      {
          m_services.add( entry );
      }
  
      /**
       * Get an array of the block names.  These are treated separately from
       * the generic <code>Type</code>
       */
      public Set getBlockEntries()
      {
          return Collections.unmodifiableSet( m_blocks );
      }
  
      /**
       * Get an array of the type names.  These are treated separately from
       * the Phoenix specific <code>Block</code>
       */
      public Set getTypeEntries()
      {
          return Collections.unmodifiableSet( m_types );
      }
  
      /**
       * Get an array of the service names.
       */
      public Set getServiceEntries()
      {
          return Collections.unmodifiableSet( m_services );
      }
  
      /**
       * Merge two different JarEntries into one
       */
      public void merge( JarEntries entries )
      {
          m_blocks.addAll( entries.getBlockEntries() );
          m_types.addAll( entries.getTypeEntries() );
          m_services.addAll( entries.getServiceEntries() );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/fortress/src/ng/org/apache/excalibur/fortress/util/classloader/JarScanner.java
  
  Index: JarScanner.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.excalibur.fortress.util.classloader;
  
  import java.io.File;
  import java.io.IOException;
  import java.net.JarURLConnection;
  import java.net.URL;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.StringTokenizer;
  import java.util.jar.Attributes;
  
  /**
   * The JarScanner will scan any URL pointing to a jar, and check for any Avalon
   * component declaration entries.  We have a convenience method to grab all the
   * entries in the System class path and extension directories.
   *
   * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
   */
  public final class JarScanner
  {
      private static final String AVALON = "Avalon";
      private static final String BLOCK = AVALON + "-Block";
      private static final String TYPE = "Type";
      private static final String SERVICE = "Service";
  
      private static JarEntries m_systemJarEntries = null;
  
      private JarScanner()
      {
      }
  
      /**
       * The logic to look through the manifest entries in the JAR url passed
       * in.  It is used to populate the sets of Services, Types, and Blocks.
       */
      public static JarEntries scan( URL jarLocation )
      {
          JarEntries entries = new JarEntries();
  
          try
          {
              final JarURLConnection jar = (JarURLConnection)
                  new URL( "jar:" + jarLocation.toString() + "!/" ).openConnection();
  
              final Map manifest = jar.getManifest().getEntries();
              final Iterator it = manifest.keySet().iterator();
  
              while( it.hasNext() )
              {
                  final String entry = (String)it.next();
                  final Attributes attributes = (Attributes)manifest.get( entry );
                  final Iterator attrIt = attributes.keySet().iterator();
  
                  while( attrIt.hasNext() )
                  {
                      final String attrName = attrIt.next().toString();
  
                      if( attrName.equals( BLOCK ) &&
                          attributes.getValue( attrName ).equals( "true" ) )
                      {
                          entries.addBlockEntry( cleanName( entry ) );
                      }
                      else if( attrName.equals( AVALON ) )
                      {
                          final String attrVal = attributes.getValue( attrName );
  
                          if( attrVal.equals( TYPE ) )
                          {
                              entries.addTypeEntry( cleanName( entry ) );
                          }
                          else if( attrVal.equals( SERVICE ) )
                          {
                              entries.addServiceEntry( cleanName( entry ) );
                          }
                          else
                          {
                              // TODO: Handle error condition
                          }
                      }
                  }
              }
          }
          catch( IOException ioe )
          {
              // TODO: Handle error condition
          }
  
          return entries;
      }
  
      /**
       * Scan all the jar files in <code>System.getProperty("java.class.path")</code>
       * and <code>System.getProperty("java.ext.dirs")</code>
       */
      public static JarEntries getSystemJarEntries()
      {
          if( m_systemJarEntries == null )
          {
              m_systemJarEntries = loadSystemJarEntries();
          }
  
          return m_systemJarEntries;
      }
  
      /**
       * Scan all the jar files in <code>System.getProperty("java.class.path")</code>
       * and <code>System.getProperty("java.ext.dirs")</code>
       */
      private static JarEntries loadSystemJarEntries()
      {
          JarEntries entries = new JarEntries();
          String pathSeparator = System.getProperty( "path.separator" );
  
          StringTokenizer classPath = new StringTokenizer( System.getProperty( "java.class.path"
),
                                                           pathSeparator, false );
  
          while( classPath.hasMoreTokens() )
          {
              String path = classPath.nextToken();
  
              try
              {
                  entries.merge( scan( new URL( path ) ) );
              }
              catch( Exception e )
              {
                  // skip and move on
              }
          }
  
          classPath = new StringTokenizer( System.getProperty( "java.ext.dirs" ),
                                           pathSeparator, false );
  
          while( classPath.hasMoreTokens() )
          {
              String dir = classPath.nextToken();
  
              entries.merge( scanDirectory( new File( dir ) ) );
          }
  
          return entries;
      }
  
      /**
       * Scans for all jars in a directory, and also treats the directory itself
       * as a possible classpath location.
       */
      public static JarEntries scanDirectory( File path )
      {
          JarEntries entries = new JarEntries();
  
          if( path.isDirectory() )
          {
              File[] pathEntries = path.listFiles();
  
              for( int i = 0; i < pathEntries.length; i++ )
              {
                  if( pathEntries[ i ].isFile() )
                  {
                      try
                      {
                          entries.merge( scan( pathEntries[ i ].toURL() ) );
                      }
                      catch( Exception e )
                      {
                          // ignore and move on to the next entry
                      }
                  }
              }
          }
  
          try
          {
              entries.merge( scan( path.toURL() ) );
          }
          catch( Exception e )
          {
              // ignore and move on
          }
  
          return entries;
      }
  
      /**
       * Strips the ".class" ending off of a Type/Block/Service name.
       */
      private static final String cleanName( String name )
      {
          int end = name.indexOf( ".class" );
          return name.substring( 0, ( end >= 0 ) ? end : name.length() );
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:avalon-cvs-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-cvs-help@jakarta.apache.org>


Mime
View raw message