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 [EMAIL PROTECTED]
*
* 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 [EMAIL PROTECTED]
*
* 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 [EMAIL PROTECTED]
*
* 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 [EMAIL PROTECTED]
*
* 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 [EMAIL PROTECTED]
*
* 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 [EMAIL PROTECTED]
*
* 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>