avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mcconn...@apache.org
Subject cvs commit: avalon-sandbox/merlin/composition/src/java/org/apache/avalon/composition/model/impl Scanner.java
Date Sat, 05 Jul 2003 07:57:50 GMT
mcconnell    2003/07/05 00:57:50

  Added:       merlin/composition/src/java/org/apache/avalon/composition/model/impl
                        Scanner.java
  Log:
  Utility class that handles the scanning of directories, jar files and streams for type and
service defintions.
  
  Revision  Changes    Path
  1.1                  avalon-sandbox/merlin/composition/src/java/org/apache/avalon/composition/model/impl/Scanner.java
  
  Index: Scanner.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.avalon.composition.model.impl;
  
  import java.io.File;
  import java.io.IOException;
  import java.io.InputStream;
  import java.net.JarURLConnection;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.ArrayList;
  import java.util.Enumeration;
  import java.util.List;
  import java.util.jar.JarFile;
  import java.util.jar.JarInputStream;
  import java.util.zip.ZipEntry;
  
  import org.apache.avalon.composition.model.ModelException;
  import org.apache.avalon.composition.util.ExceptionHelper;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.meta.data.Profile;
  import org.apache.avalon.meta.info.Service;
  import org.apache.avalon.meta.info.Type;
  import org.apache.avalon.meta.info.builder.TypeBuilder;
  import org.apache.avalon.meta.info.builder.ServiceBuilder;
  
  /**
   * A repository for services, types and profiles.
   *
   * @author <a href="mailto:shea@gtsdesign.com">Gary Shea</a>
   * @version $Revision: 1.1 $ $Date: 2003/07/05 07:57:50 $
   */
  public class Scanner extends AbstractLogEnabled
  {
      //===================================================================
      // static
      //===================================================================
  
      private static final String X_INFO = ".xinfo";
  
      private static final String X_TYPE = ".xtype";
  
      private static final String X_SERVICE = ".xservice";
  
      private static final String X_PROFILE = ".xprofile";
  
      /**
       * The type builder.
       */
      private static final TypeBuilder TYPE_BUILDER = 
        new TypeBuilder();
  
      /**
       * The service builder.
       */
      private static final ServiceBuilder SERVICE_BUILDER = 
        new ServiceBuilder();
  
      //===================================================================
      // state
      //===================================================================
  
      /**
       * Parent repository.
       */
      private ClassLoader m_classloader;
  
      //===================================================================
      // constructor
      //===================================================================
  
      /**
       * Creation of a new scanner using a supplied classloader.  
       * The scanner is responsible for scanning suppied URLs for 
       * service and types.
       *
       * @param classloader the classloader
       */
      public Scanner( ClassLoader classloader )
      {
          if( classloader == null )
          {
              throw new NullPointerException( "classloader" );
          }
          m_classloader = classloader;
      }
  
      //=======================================================================
      // Repository
      //=======================================================================
  
      /**
       * Scan the supplied url for Service and Type defintions.
       * @param urls the URL array to scan
       * @return an object array containing {@link Service} and 
       *   {@link Type} instances
       */
      public void scan( URL[] urls, List types, List services ) throws ModelException
      {
          for( int i=0; i<urls.length; i++ )
          {
              URL url = urls[i];
              scanURL( url, types, services );
          }
      }
  
      /**
       * Add a URL to the classpath.
       * @param url the URL to add to the repository
       */
      private void scanURL( URL url, List types, List services ) throws ModelException
      {
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "scanning: " + url );
          }
  
          if( isDirectory( url ) )
          {
              scanDirectory( url, types, services );
          }
          else if( 
            url.getProtocol().equals( "jar" ) 
            || ( url.getProtocol().equals( "file" ) && url.toString().endsWith( ".jar"
) ) )
          {
              scanJarFileURL( url, types, services );
          }
          else
          {
              scanInputStream( url, types, services );
          }
      }
  
      private void scanDirectory( URL url, List types, List services ) throws ModelException
      {
          try
          {
              File directory = getDirectory( url );
              scanDirectoryContent( directory, directory, types, services );
          } 
          catch( Throwable e )
          {
              final String error =
                "Unexpected Ierror while attempting to scan directory: " 
                + url;
              throw new ModelException( error, e );
          }
      }
  
      private void scanJarFileURL( URL url, List types, List services ) throws ModelException
      {
          URL uri = url;
          try
          {
              if( !url.getProtocol().equals( "jar" ) )
              {
                 uri = getJarURL( url );
              }
  
              if( !uri.toString().endsWith( "!/" ) )
              {
                  final String error =
                      "Embeded jar file loading not supported: " + url;
                  throw new IllegalArgumentException( error );
              }
  
              final JarURLConnection jar = (JarURLConnection) uri.openConnection();
              final JarFile base = jar.getJarFile();
              scanJarFile( base, types, services );
          } 
          catch( Throwable e )
          {
              final String error =
                "Unexpected error while scanning jar file: " + url;
              throw new ModelException( error );
          }
      }
  
      private void scanJarFile( JarFile base, List types, List services ) throws Exception
      {
          Enumeration entries = base.entries();
          while( entries.hasMoreElements() )
          {
              ZipEntry entry = (ZipEntry) entries.nextElement();
              String name = entry.getName();
              if( name.endsWith( X_TYPE ) || name.endsWith( X_INFO ) )
              {
                  addType( types, name );
              } 
              else if( name.endsWith( X_SERVICE ) )
              {
                  addService( services, name );
              }
          }
      }
  
      private void scanInputStream( URL url, List types, List services )
      {
          try
          {
              Object object = url.openStream();
              if( object != null )
              {
                  JarInputStream stream = new JarInputStream( (InputStream) object );
                  scanJarInputStream( stream, types, services );
                  return;
              } 
              else
              {
                  if( getLogger().isWarnEnabled() )
                  {
                      getLogger().warn(
                        "Unrecognized content from url " + url );
                  }
              }
          }
          catch( Throwable e )
          {
              if( getLogger().isWarnEnabled() )
              {
                  final String error = 
                    "Content related error while scanning url: " + url;
                  getLogger().warn( ExceptionHelper.packException( 
                    error, e, getLogger().isDebugEnabled() ) );
              }
          }
      }
  
      private void scanJarInputStream( JarInputStream stream, List types, List services )
throws Exception
      {
          ZipEntry entry = null;
          try
          {
              entry = stream.getNextEntry();
          } 
          catch( Throwable e )
          {
              entry = null;
          }
  
          while( entry != null )
          {
              String name = entry.getName();
              if( name.endsWith( X_TYPE ) || name.endsWith( X_INFO ) )
              {
                  addType( types, name );
              } 
              else if( name.endsWith( X_SERVICE ) )
              {
                  addService( services, name );
              }
  
              try
              {
                  entry = stream.getNextEntry();
              } 
              catch( Throwable e )
              {
                  entry = null;
              }
          }
      }
  
      private void scanDirectoryContent( File base, File dir, List types, List services )
throws Exception
      {
          File[] files = dir.listFiles();
          String path = base.toString();
          int j = path.length();
          for( int i = 0; i < files.length; i++ )
          {
              File file = files[i];
              if( file.isDirectory() )
              {
                  getLogger().debug( "scanning dir: " + file );
                  scanDirectoryContent( base, file, types, services );
              } 
              else
              {
                  scanFile( j, file, types, services );
              }
          }
      }
  
      private void scanFile( int j, File file, List types, List services ) throws Exception
      {
          String filename = file.toString();
          String name = filename.substring( j, filename.length() );
          if( name.endsWith( X_TYPE ) || name.endsWith( X_INFO ) )
          {
               addType( types, name );
          } 
          else if( name.endsWith( X_SERVICE ) )
          {
               addService( services, name );
          }
      }
  
      private void addType( List list, String name ) throws Exception
      {
          String classname = parseResourceName( name );
          list.add( TYPE_BUILDER.build( classname, m_classloader ) );
      }
  
      private void addService( List list, String name ) throws Exception
      {
          String classname = parseResourceName( name );
          list.add( SERVICE_BUILDER.build( classname, m_classloader ) );
      }
  
      private boolean isDirectory( URL url )
      {
          if( url.getProtocol().equals( "file" ) )
          {
              return getFile( url ).isDirectory();
          }
          return false;
      }
  
      private File getDirectory( URL url ) throws IllegalArgumentException
      {
          File file = getFile( url );
          if( file.isDirectory() )
          {
              return file;
          }
          throw new IllegalArgumentException(
            "URL does not refer to a directory: " + url );
      }
  
      private File getFile( URL url ) throws IllegalArgumentException
      {
          if( url.getProtocol().equals( "file" ) )
          {
              return new File( url.toString().substring( 5 ) );
          }
          throw new IllegalArgumentException(
            "URL protocol does not match the required file: protocol: " + url );
      }
  
      private String parseResourceName( String resource )
      {
          int i = resource.lastIndexOf( "." );
          String name = resource.substring( 0, i );
          String name2 = name.replace( '/', '.' );
          String name3 = name2.replace( '\\', '.' );
          if( name3.startsWith( "." ) )
          {
              return name3.substring( 1, name3.length() );
          } else
          {
              return name3;
          }
      }
  
      private URL getJarURL( URL url ) throws MalformedURLException
      {
          if( url.getProtocol().equals( "jar" ) )
          {
              return url;
          } else
          {
              return new URL( "jar:" + url.toString() + "!/" );
          }
      }
  
  }
  
  
  

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


Mime
View raw message