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/11 19:38:49 UTC

cvs commit: jakarta-avalon-excalibur/container/src/java/org/apache/excalibur/container/classloader ComponentClassLoader.java

bloritsch    2002/09/11 10:38:49

  Added:       container/src/java/org/apache/excalibur/container/classloader
                        ComponentClassLoader.java
  Log:
  add a generic ClassLoader that will assemble a list of components/services/blocks--there is no affinity to meta model library
  
  Revision  Changes    Path
  1.1                  jakarta-avalon-excalibur/container/src/java/org/apache/excalibur/container/classloader/ComponentClassLoader.java
  
  Index: ComponentClassLoader.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.lookup;
  
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Set;
  import java.util.jar.Attributes;
  
  import java.io.IOException;
  
  import java.net.JarURLConnection;
  import java.net.URL;
  import java.net.URLClassLoader;
  import java.net.URLStreamHandlerFactory;
  
  /**
   * 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
  {
      protected static final String AVALON = "Avalon";
      protected static final String BLOCK = AVALON + "-Block";
      protected static final String TYPE = "Type";
      protected static final String SERVICE = "Service";
  
      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 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_blocks = new HashSet();
          m_types = new HashSet();
          m_services = new HashSet();
  
          for ( int i = 0; i < classPath.length; i++ )
          {
              scan( classPath[i] );
          }
      }
  
      /**
       * 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 );
          scan ( classPath );
      }
  
      /**
       * Get an array of the block names.  These are treated separately from
       * the generic <code>Type</code>
       */
      public String[] getBlocks()
      {
          return (String[]) m_blocks.toArray( new String[ m_blocks.size() ] );
      }
  
      /**
       * Get an array of the type names.  These are treated separately from
       * the Phoenix specific <code>Block</code>
       */
      public String[] getTypes()
      {
          return (String[]) m_types.toArray( new String[ m_types.size() ] );
      }
  
      /**
       * Get an array of the service names.
       */
      public String[] getServices()
      {
          return (String[]) m_services.toArray( new String[ m_services.size() ] );
      }
  
      /**
       * 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.
       */
      protected void scan( URL jarLocation )
      {
          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 = (String) it.next();
  
                      if ( attrName.equals( BLOCK ) &&
                          attributes.getValue( attrName ).equals( "true" ) )
                      {
                          m_blocks.add( cleanName( attrName ) );
                      }
                      else if ( attrName.equals( AVALON ) )
                      {
                          final String attrVal = attributes.getValue( attrName );
  
                          if ( attrVal.equals( TYPE ) )
                          {
                              m_types.add( cleanName( attrName ) );
                          }
                          else if ( attrVal.equals( SERVICE ) )
                          {
                              m_types.add( cleanName( attrName ) );
                          }
                          else
                          {
                              // TODO: Handle error condition
                          }
                      }
                  }
              }
          }
          catch ( IOException ioe )
          {
              // TODO: Handle error condition
          }
      }
  
      /**
       * Strips the ".class" ending off of a Type/Block/Service name.
       */
      private final String cleanName( String name )
      {
          return name.substring( 0, name.indexOf( ".class" ) );
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>