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-phoenix/src/java/org/apache/avalon/phoenix/components/classloader DefaultClassLoaderManager.java Resources.properties
Date Sat, 17 Nov 2001 11:54:08 GMT
donaldp     01/11/17 03:54:08

  Modified:    src/java/org/apache/avalon/phoenix/components/classloader
                        DefaultClassLoaderManager.java Resources.properties
  Log:
  Allow jars inside the .sar to declare dependencies on Extensions. The Extensions are provided
by "Optional Packages" as defined by guide/extensions/versioning.html in the jdk1.3 docs.
  
  This allows us to have a central repository of "Optional Packages" that multiple applications
could declare dependencies upon. The default extensions repository is in ${phoenix.home}/ext
  
  Revision  Changes    Path
  1.17      +178 -7    jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/classloader/DefaultClassLoaderManager.java
  
  Index: DefaultClassLoaderManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/classloader/DefaultClassLoaderManager.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- DefaultClassLoaderManager.java	2001/11/09 21:14:30	1.16
  +++ DefaultClassLoaderManager.java	2001/11/17 11:54:08	1.17
  @@ -8,18 +8,26 @@
   package org.apache.avalon.phoenix.components.classloader;
   
   import java.io.File;
  -import java.net.MalformedURLException;
  +import java.io.IOException;
  +import java.net.JarURLConnection;
   import java.net.URL;
  -import java.net.URLStreamHandler;
  -import java.net.URLStreamHandlerFactory;
   import java.security.Policy;
   import java.util.ArrayList;
  -import java.util.jar.JarFile;
  -import org.apache.avalon.framework.component.Component;
  +import java.util.Arrays;
  +import java.util.jar.Manifest;
  +import org.apache.avalon.excalibur.extension.PackageManager;
  +import org.apache.avalon.excalibur.extension.OptionalPackage;
  +import org.apache.avalon.excalibur.extension.Extension;
  +import org.apache.avalon.excalibur.i18n.ResourceManager;
  +import org.apache.avalon.excalibur.i18n.Resources;
  +import org.apache.avalon.framework.component.ComponentException;
  +import org.apache.avalon.framework.component.ComponentManager;
  +import org.apache.avalon.framework.component.Composable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.avalon.phoenix.interfaces.ClassLoaderManager;
  +import org.apache.avalon.phoenix.interfaces.PackageRepository;
   
   /**
    * Component that creates and manages the <code>ClassLoader</code>
  @@ -37,8 +45,21 @@
    */
   public class DefaultClassLoaderManager
       extends AbstractLogEnabled
  -    implements ClassLoaderManager
  +    implements ClassLoaderManager, Composable
   {
  +    private static final Resources REZ =
  +        ResourceManager.getPackageResources( DefaultClassLoaderManager.class );
  +
  +    private PackageManager m_packageManager;
  +
  +    public void compose( final ComponentManager componentManager )
  +        throws ComponentException
  +    {
  +        final PackageRepository packageRepository =
  +            (PackageRepository)componentManager.lookup( PackageRepository.ROLE );
  +        m_packageManager = new PackageManager( packageRepository );
  +    }
  +
       /**
        * Create a <code>ClassLoader</code> for a specific application.
        * See Class Javadoc for description of technique for creating
  @@ -63,6 +84,13 @@
           final Policy policy = configurePolicy( policyConfig, homeDirectory );
   
           //TODO: Load Extensions from Package Repository as required
  +        final File[] extensions = getOptionalPackagesFor( classPath );
  +        if( getLogger().isDebugEnabled() )
  +        {
  +            final String message = 
  +                REZ.getString( "optional-packages-added", Arrays.asList( extensions ) );
  +            getLogger().debug( message );
  +        }
   
           //TODO: Determine parentClassLoader in a safer fashion
           final ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader();
  @@ -77,10 +105,153 @@
           //URL.setURLStreamHandlerFactory( factory );
           //}
   
  -        final PolicyClassLoader classLoader = 
  +        final PolicyClassLoader classLoader =
               new PolicyClassLoader( classPath, parentClassLoader, null, policy );
           setupLogger( classLoader, "classloader" );
  +
  +        for( int i = 0; i < extensions.length; i++ )
  +        {
  +            final URL url = extensions[ i ].toURL();
  +            classLoader.addURL( url );
  +        }
  +        
           return classLoader;
  +    }
  +
  +    /**
  +     * Retrieve the files for the optional packages required by
  +     * the jars in ClassPath.
  +     *
  +     * @param classPath the Classpath array
  +     * @return the files that need to be added to ClassLoader
  +     */
  +    private File[] getOptionalPackagesFor( final String[] classPath )
  +        throws Exception
  +    {
  +        final Manifest[] manifests = getManifests( classPath );
  +        final Extension[] available = getAvailable( manifests );
  +        final Extension[] required = getRequired( manifests );
  +
  +        if( getLogger().isDebugEnabled() )
  +        {
  +            final String message1 = 
  +                REZ.getString( "available-extensions", Arrays.asList( available ) );
  +            getLogger().debug( message1 );
  +            final String message2 = 
  +                REZ.getString( "required-extensions", Arrays.asList( required ) );
  +            getLogger().debug( message2 );
  +        }
  +
  +        final ArrayList dependencies = new ArrayList();
  +        final ArrayList unsatisfied = new ArrayList();
  +
  +        m_packageManager.scanDependencies( required,
  +                                           available,
  +                                           dependencies,
  +                                           unsatisfied );
  +
  +        if( 0 != unsatisfied.size() )
  +        {
  +            final int size = unsatisfied.size();
  +            for( int i = 0; i < size; i++ )
  +            {
  +                final Extension extension = (Extension)unsatisfied.get( i );
  +                final Object[] params = new Object[]
  +                {
  +                    extension.getExtensionName(), 
  +                    extension.getSpecificationVendor(), 
  +                    extension.getSpecificationVersion(),
  +                    extension.getImplementationVendor(), 
  +                    extension.getImplementationVendorId(),
  +                    extension.getImplementationVersion(), 
  +                    extension.getImplementationURL()
  +                };
  +                final String message = REZ.format( "missing.extension", params );
  +                getLogger().warn( message );
  +            }
  +
  +            final String message =
  +                REZ.getString( "unsatisfied.extensions", new Integer( size ) );
  +            throw new Exception( message );
  +        }
  +
  +        final OptionalPackage[] packages =
  +            (OptionalPackage[])dependencies.toArray( new OptionalPackage[ 0 ] );
  +        return OptionalPackage.toFiles( packages );
  +    }
  +
  +    /**
  +     * Retrieve an array of available extensions from the specified manifests.
  +     *
  +     * @param manifests the manifests to scan
  +     * @return the extensions
  +     */
  +    private Extension[] getAvailable( final Manifest[] manifests )
  +    {
  +        final ArrayList availableSet = new ArrayList();
  +
  +        for( int i = 0; i < manifests.length; i++ )
  +        {
  +            final Extension[] available = Extension.getAvailable( manifests[ i ] );
  +            for( int j = 0; j < available.length; j++ )
  +            {
  +                availableSet.add( available[ j ] );
  +            }
  +        }
  +
  +        return (Extension[])availableSet.toArray( new Extension[ 0 ] );
  +    }
  +
  +    /**
  +     * Retrieve an array of required extensions from the specified manifests.
  +     *
  +     * @param manifests the manifests to scan
  +     * @return the extensions
  +     */
  +    private Extension[] getRequired( final Manifest[] manifests )
  +    {
  +        final ArrayList availableSet = new ArrayList();
  +
  +        for( int i = 0; i < manifests.length; i++ )
  +        {
  +            final Extension[] available = Extension.getRequired( manifests[ i ] );
  +            for( int j = 0; j < available.length; j++ )
  +            {
  +                availableSet.add( available[ j ] );
  +            }
  +        }
  +
  +        return (Extension[])availableSet.toArray( new Extension[ 0 ] );
  +    }
  +
  +    private Manifest[] getManifests( final String[] classPath )
  +        throws Exception
  +    {
  +        final ArrayList manifests = new ArrayList();
  +
  +        for( int i = 0; i < classPath.length; i++ )
  +        {
  +            final String element = classPath[ i ];
  +
  +            if( element.endsWith( ".jar" ) )
  +            {
  +                try
  +                {
  +                    final URL url = new URL( "jar:" + element + "!/" );
  +                    final JarURLConnection connection = (JarURLConnection)url.openConnection();
  +                    final Manifest manifest = connection.getManifest();
  +                    manifests.add( manifest );
  +                }
  +                catch( final IOException ioe )
  +                {
  +                    final String message = REZ.getString( "bad-classpath-entry", element
);
  +                    getLogger().warn( message );
  +                    throw new Exception( message );
  +                }
  +            }
  +        }
  +
  +        return (Manifest[])manifests.toArray( new Manifest[ 0 ] );
       }
   
       /**
  
  
  
  1.5       +7 -0      jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/classloader/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/classloader/Resources.properties,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Resources.properties	2001/11/09 21:14:30	1.4
  +++ Resources.properties	2001/11/17 11:54:08	1.5
  @@ -9,3 +9,10 @@
   
   create-connection=Cannot create connection using {0} protocol.
   parse-url=No {0}/ found in url spec: {1}
  +
  +missing.extension=Unable to locate an extension that is required by application.\nExtension
Name: {0}\nSpecification Vendor: {1}\nSpecification Version: {2}\nImplementation Vendor: {3}\nImplementation
Vendor-Id: {4}\nImplementation Version: {5}\nImplementation URL: {6}
  +unsatisfied.extensions=Missing {0} extensions and thus can not build ClassLoader for application.
  +bad-classpath-entry=There is a bad entry ("{0}") on classpath that made it impossible to
load a manifest. 
  +available-extensions=The list of available extensions for application includes; {0}
  +required-extensions=The list of required extensions for application includes; {0}
  +optional-packages-added=The list of "Optional Packages" added to the application includes;
{0}
  \ No newline at end of file
  
  
  

--
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