/*******************************************************************************
 * Copyright (c) 2009-2011 Sonatype, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution.
 * The Eclipse Public License is available at
 *   http://www.eclipse.org/legal/epl-v10.html
 * The Apache License v2.0 is available at
 *   http://www.apache.org/licenses/LICENSE-2.0.html
 * You may elect to redistribute this code under either of these licenses.
 *******************************************************************************/
package org.sonatype.guice.bean.reflect;

import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;

import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;

/**
 * {@link ClassSpace} backed by a strongly-referenced {@link Bundle}.
 */
public final class BundleClassSpace
    implements ClassSpace
{
    // ----------------------------------------------------------------------
    // Constants
    // ----------------------------------------------------------------------

    private static final Enumeration<URL> NO_URLS = Collections.enumeration( Collections.<URL> emptyList() );

    // ----------------------------------------------------------------------
    // Implementation fields
    // ----------------------------------------------------------------------

    private final Bundle bundle;

    // ----------------------------------------------------------------------
    // Constructors
    // ----------------------------------------------------------------------

    public BundleClassSpace( final Bundle bundle )
    {
        this.bundle = bundle;
    }

    // ----------------------------------------------------------------------
    // Public methods
    // ----------------------------------------------------------------------

    public Class<?> loadClass( final String name )
    {
        try
        {
            return bundle.loadClass( name );
        }
        catch ( final Throwable e )
        {
            throw new TypeNotPresentException( name, e );
        }
    }

    public DeferredClass<?> deferLoadClass( final String name )
    {
        return new NamedClass<Object>( this, name );
    }

    public URL getResource( final String name )
    {
        return bundle.getResource( name );
    }

    @SuppressWarnings( "unchecked" )
    public Enumeration<URL> getResources( final String name )
    {
        try
        {
            return bundle.getResources( name );
        }
        catch ( final IOException e )
        {
            return NO_URLS;
        }
    }

    public Enumeration<URL> findEntries( final String path, final String glob, final boolean recurse )
    {
        @SuppressWarnings( "unchecked" )
        final Enumeration<URL> e = bundle.findEntries( null != path ? path : "/", glob, recurse );
        return null != e ? e : NO_URLS;
    }

    public boolean loadedClass( final Class<?> clazz )
    {
        return bundle.equals( FrameworkUtil.getBundle( clazz ) );
    }

    @Override
    public int hashCode()
    {
        return bundle.hashCode();
    }

    @Override
    public boolean equals( final Object rhs )
    {
        if ( this == rhs )
        {
            return true;
        }
        if ( rhs instanceof BundleClassSpace )
        {
            return bundle.equals( ( (BundleClassSpace) rhs ).bundle );
        }
        return false;
    }

    @Override
    public String toString()
    {
        return bundle.toString();
    }
}

@@ -779,84 +779,245 @@
 til.
-Collections;%0Aimport java.util.Enumeration;%0A%0Aimport org.osgi.framework.Bundle
+ArrayList;%0Aimport java.util.Arrays;%0Aimport java.util.Collections;%0Aimport java.util.Enumeration;%0Aimport java.util.HashSet;%0Aimport java.util.List;%0Aimport java.util.Set;%0A%0Aimport org.osgi.framework.Bundle;%0Aimport org.osgi.framework.Constants
 ;%0Aim
@@ -1364,32 +1364,86 @@
 --------------%0A%0A
+    private static final URL%5B%5D NO_URLS = new URL%5B0%5D;%0A%0A
     private stat
@@ -1467,27 +1467,30 @@
 ion%3CURL%3E NO_
-URL
+ENTRIE
 S = Collecti
@@ -1510,36 +1510,31 @@
 on( 
-Collections.%3CURL%3E emptyList(
+Arrays.asList( NO_URLS 
 ) );
@@ -1755,16 +1755,46 @@
 undle;%0A%0A
+    private URL%5B%5D classPath;%0A%0A
     // -
@@ -2975,27 +2975,30 @@
   return NO_
-URL
+ENTRIE
 S;%0A        %7D
@@ -3008,32 +3008,45 @@
   %7D%0A%0A    public 
+synchronized 
 Enumeration%3CURL%3E
@@ -3119,32 +3119,273 @@
 recurse )%0A    %7B%0A
+        if ( null == classPath )%0A        %7B%0A            classPath = getBundleClassPath( bundle );%0A        %7D%0A        if ( classPath.length %3E 0 )%0A        %7B%0A            return new ResourceEnumeration( path, glob, recurse, classPath );%0A        %7D%0A
         @Suppres
@@ -3542,19 +3542,22 @@
  e : NO_
-URL
+ENTRIE
 S;%0A    %7D
@@ -4172,11 +4172,973 @@
 );%0A    %7D
+%0A%0A    // ----------------------------------------------------------------------%0A    // Implementation methods%0A    // ----------------------------------------------------------------------%0A%0A    private static URL%5B%5D getBundleClassPath( final Bundle bundle )%0A    %7B%0A        final String path = (String) bundle.getHeaders().get( Constants.BUNDLE_CLASSPATH );%0A        if ( null == path %7C%7C %22.%22.equals( path.trim() ) )%0A        %7B%0A            return NO_URLS;%0A        %7D%0A%0A        final List%3CURL%3E classPath = new ArrayList%3CURL%3E();%0A        final Set%3CString%3E visited = new HashSet%3CString%3E();%0A%0A        for ( String entry : path.split( %22%5C%5Cs*,%5C%5Cs*%22 ) )%0A        %7B%0A            if ( visited.add( entry ) )%0A            %7B%0A                final URL url = bundle.getEntry( entry );%0A                if ( null != url )%0A                %7B%0A                    classPath.add( url );%0A                %7D%0A            %7D%0A        %7D%0A        return classPath.toArray( new URL%5BclassPath.size()%5D );%0A    %7D
 %0A%7D%0A

fix scanning of embedded JARs in OSGi bundles