geronimo-xbean-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From xuhaih...@apache.org
Subject svn commit: r941557 - in /geronimo/xbean/trunk: ./ xbean-bundleutils/ xbean-bundleutils/src/main/java/org/apache/xbean/osgi/bundle/util/ xbean-finder/ xbean-finder/src/main/java/org/apache/xbean/finder/
Date Thu, 06 May 2010 01:16:59 GMT
Author: xuhaihong
Date: Thu May  6 01:16:59 2010
New Revision: 941557

URL: http://svn.apache.org/viewvc?rev=941557&view=rev
Log:
Add a ASM based class finder

Added:
    geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/BundleAssignableClassFinder.java
  (with props)
Modified:
    geronimo/xbean/trunk/pom.xml
    geronimo/xbean/trunk/xbean-bundleutils/pom.xml
    geronimo/xbean/trunk/xbean-bundleutils/src/main/java/org/apache/xbean/osgi/bundle/util/BundleClassFinder.java
    geronimo/xbean/trunk/xbean-finder/pom.xml

Modified: geronimo/xbean/trunk/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/pom.xml?rev=941557&r1=941556&r2=941557&view=diff
==============================================================================
--- geronimo/xbean/trunk/pom.xml (original)
+++ geronimo/xbean/trunk/pom.xml Thu May  6 01:16:59 2010
@@ -287,7 +287,12 @@
                 <artifactId>qdox</artifactId>
                 <version>1.6.3</version>
             </dependency>
-
+            
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>1.5.11</version>                
+            </dependency>
         </dependencies>
     </dependencyManagement>
 

Modified: geronimo/xbean/trunk/xbean-bundleutils/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-bundleutils/pom.xml?rev=941557&r1=941556&r2=941557&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-bundleutils/pom.xml (original)
+++ geronimo/xbean/trunk/xbean-bundleutils/pom.xml Thu May  6 01:16:59 2010
@@ -30,6 +30,10 @@
 
     <dependencies>
         <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
             <version>4.2.0</version>

Modified: geronimo/xbean/trunk/xbean-bundleutils/src/main/java/org/apache/xbean/osgi/bundle/util/BundleClassFinder.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-bundleutils/src/main/java/org/apache/xbean/osgi/bundle/util/BundleClassFinder.java?rev=941557&r1=941556&r2=941557&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-bundleutils/src/main/java/org/apache/xbean/osgi/bundle/util/BundleClassFinder.java
(original)
+++ geronimo/xbean/trunk/xbean-bundleutils/src/main/java/org/apache/xbean/osgi/bundle/util/BundleClassFinder.java
Thu May  6 01:16:59 2010
@@ -20,11 +20,13 @@
 package org.apache.xbean.osgi.bundle.util;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -39,6 +41,8 @@ import org.osgi.framework.Bundle;
 import org.osgi.service.packageadmin.ExportedPackage;
 import org.osgi.service.packageadmin.PackageAdmin;
 import org.osgi.service.packageadmin.RequiredBundle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Finds all available classes to a bundle by scanning Bundle-ClassPath,
@@ -49,28 +53,36 @@ import org.osgi.service.packageadmin.Req
  */
 public class BundleClassFinder {
 
+    private static final Logger logger = LoggerFactory.getLogger(BundleClassFinder.class);
+
     public static final ClassDiscoveryFilter FULL_CLASS_DISCOVERY_FILTER = new DummyDiscoveryFilter();
+
     public static final ClassDiscoveryFilter IMPORTED_PACKAGE_EXCLUSIVE_FILTER = new NonImportedPackageDiscoveryFilter();
-    private static final String EXT = ".class";
-    private static final String PATTERN = "*.class";
 
-    private Bundle bundle;
-    private PackageAdmin packageAdmin;
+    protected static final String EXT = ".class";
+
+    protected static final String PATTERN = "*.class";
+
+    protected Bundle bundle;
+
+    protected PackageAdmin packageAdmin;
+
     private Map<Bundle, Set<String>> classMap;
-    private ClassDiscoveryFilter discoveryFilter;
+
+    protected ClassDiscoveryFilter discoveryFilter;
 
     public BundleClassFinder(PackageAdmin packageAdmin, Bundle bundle) {
         this(packageAdmin, bundle, FULL_CLASS_DISCOVERY_FILTER);
     }
 
-    public BundleClassFinder(PackageAdmin packageAdmin, Bundle bundle, ClassDiscoveryFilter
discoveryFilter){
+    public BundleClassFinder(PackageAdmin packageAdmin, Bundle bundle, ClassDiscoveryFilter
discoveryFilter) {
         this.packageAdmin = packageAdmin;
         this.bundle = bundle;
         this.discoveryFilter = discoveryFilter;
     }
 
     public List<Class> loadClasses(Set<String> classes) {
-        List<Class> loadedClasses = new ArrayList<Class>();
+        List<Class> loadedClasses = new ArrayList<Class>(classes.size());
         for (String clazz : classes) {
             try {
                 loadedClasses.add(bundle.loadClass(clazz));
@@ -113,36 +125,79 @@ public class BundleClassFinder {
         return classes;
     }
 
-    private void scanImportPackages(Collection<String> classes, Bundle host, Bundle
fragment) {
-        BundleDescription description = new BundleDescription(fragment.getHeaders());
-        List<BundleDescription.ImportPackage> imports = description.getExternalImports();
-        for (BundleDescription.ImportPackage packageImport : imports) {
-            if (discoveryFilter.packageDiscoveryRequired(packageImport.getName())) {
-                ExportedPackage[] exports = packageAdmin.getExportedPackages(packageImport.getName());
-                Bundle wiredBundle = isWired(host, exports);
-                if (wiredBundle != null) {
-                    Set<String> allClasses = findAllClasses(wiredBundle);
-                    addMatchingClasses(classes, allClasses, packageImport.getName());
-                }
-            }
+    protected boolean isClassAcceptable(String name, InputStream in) throws IOException {
+        return true;
+    }
+
+    protected boolean isClassAcceptable(URL url) {
+        return true;
+    }
+
+    protected BundleClassFinder createSubBundleClassFinder(PackageAdmin packageAdmin, Bundle
bundle, ClassDiscoveryFilter classDiscoveryFilter) {
+        return new BundleClassFinder(packageAdmin, bundle, classDiscoveryFilter);
+    }
+
+    protected String toJavaStyleClassName(String name) {
+        if (name.endsWith(EXT)) {
+            name = name.substring(0, name.length() - EXT.length());
         }
+        name = name.replace('/', '.');
+        return name;
     }
 
-    private Set<String> findAllClasses(Bundle bundle) {
+    /**
+     * Get the normal Java style package name from the parameter className.
+     * If the className is ended with .class extension, e.g.  /org/apache/geronimo/TestCass.class
or org.apache.geronimo.TestClass.class,
+     *      then org/apache/geronimo is returned
+     * If the className is not ended with .class extension, e.g.  /org/apache/geronimo/TestCass
or org.apache.geronimo.TestClass,
+     *      then org/apache/geronimo is returned
+     * @return Normal Java style package name, should be like org.apache.geronimo
+     */
+    protected String toJavaStylePackageName(String className) {
+        if (className.endsWith(EXT)) {
+            className = className.substring(0, className.length() - EXT.length());
+        }
+        className = className.replace('/', '.');
+        int iLastDotIndex = className.lastIndexOf('.');
+        if (iLastDotIndex != -1) {
+            return className.substring(0, iLastDotIndex);
+        } else {
+            return "";
+        }
+    }
+
+    private Set<String> findAllClasses(Bundle bundle, ClassDiscoveryFilter userClassDiscoveryFilter,
Set<String> exportedPackageNames) {
+        Set<String> allClasses = classMap.get(bundle);
+        if (allClasses == null) {
+            BundleClassFinder finder = createSubBundleClassFinder(packageAdmin, bundle, new
ImportExclusivePackageDiscoveryFilterAdapter(userClassDiscoveryFilter, exportedPackageNames));
+            allClasses = finder.find();
+            classMap.put(bundle, allClasses);
+        }
+        return allClasses;
+    }
+
+    private Set<String> findAllClasses(Bundle bundle, String packageName) {
         Set<String> allClasses = classMap.get(bundle);
         if (allClasses == null) {
-            BundleClassFinder finder = new BundleClassFinder(packageAdmin, bundle, IMPORTED_PACKAGE_EXCLUSIVE_FILTER);
+            BundleClassFinder finder = createSubBundleClassFinder(packageAdmin, bundle, new
ImportExclusivePackageDiscoveryFilter(packageName));
             allClasses = finder.find();
             classMap.put(bundle, allClasses);
         }
         return allClasses;
     }
 
-    private void addMatchingClasses(Collection<String> classes, Set<String> allClasses,
String packageName) {
-        String prefix = packageName + ".";
-        for (String clazz : allClasses) {
-            if (clazz.startsWith(prefix) && clazz.indexOf('.', prefix.length()) ==
-1) {
-                classes.add(clazz);
+    private void scanImportPackages(Collection<String> classes, Bundle host, Bundle
fragment) {
+        BundleDescription description = new BundleDescription(fragment.getHeaders());
+        List<BundleDescription.ImportPackage> imports = description.getExternalImports();
+        for (BundleDescription.ImportPackage packageImport : imports) {
+            String packageName = packageImport.getName();
+            if (discoveryFilter.packageDiscoveryRequired(packageName)) {
+                ExportedPackage[] exports = packageAdmin.getExportedPackages(packageName);
+                Bundle wiredBundle = isWired(host, exports);
+                if (wiredBundle != null) {
+                    Set<String> allClasses = findAllClasses(wiredBundle, packageName);
+                    classes.addAll(allClasses);
+                }
             }
         }
     }
@@ -154,14 +209,14 @@ public class BundleClassFinder {
             RequiredBundle[] requiredBundles = packageAdmin.getRequiredBundles(requiredBundle.getName());
             Bundle wiredBundle = isWired(bundle, requiredBundles);
             if (wiredBundle != null) {
-                Set<String> allClasses = findAllClasses(wiredBundle);
                 BundleDescription wiredBundleDescription = new BundleDescription(wiredBundle.getHeaders());
                 List<ExportPackage> exportPackages = wiredBundleDescription.getExportPackage();
+                Set<String> exportedPackageNames = new HashSet<String>();
                 for (ExportPackage exportPackage : exportPackages) {
-                    if (discoveryFilter.packageDiscoveryRequired(exportPackage.getName()))
{
-                        addMatchingClasses(classes, allClasses, exportPackage.getName());
-                    }
+                    exportedPackageNames.add(exportPackage.getName());
                 }
+                Set<String> allClasses = findAllClasses(wiredBundle, discoveryFilter,
exportedPackageNames);
+                classes.addAll(allClasses);
             }
         }
     }
@@ -193,12 +248,16 @@ public class BundleClassFinder {
         if (!discoveryFilter.directoryDiscoveryRequired(basePath)) {
             return;
         }
-        Enumeration e = bundle.findEntries(basePath, PATTERN, true);
+        Enumeration<URL> e = bundle.findEntries(basePath, PATTERN, true);
         if (e != null) {
             while (e.hasMoreElements()) {
-                URL u = (URL) e.nextElement();
-                String name = u.getPath().substring(basePath.length());
-                classes.add(toClassName(name));
+                URL u = e.nextElement();
+                String entryName = u.getPath().substring(basePath.length());
+                if (discoveryFilter.packageDiscoveryRequired(toJavaStylePackageName(entryName)))
{
+                    if (isClassAcceptable(u)) {
+                        classes.add(toJavaStyleClassName(entryName));
+                    }
+                }
             }
         }
     }
@@ -217,33 +276,32 @@ public class BundleClassFinder {
             ZipEntry entry;
             while ((entry = in.getNextEntry()) != null) {
                 String name = entry.getName();
-                if (name.endsWith(EXT)) {
-                    classes.add(toClassName(name));
+                if (name.endsWith(EXT) && discoveryFilter.packageDiscoveryRequired(toJavaStylePackageName(name)))
{
+                    if (isClassAcceptable(name, in)) {
+                        classes.add(toJavaStyleClassName(name));
+                    }
                 }
             }
         } catch (IOException ignore) {
-            // ignore
+            logger.warn("Fail to check zip file " + zipName, ignore);
         } finally {
             if (in != null) {
-                try { in.close(); } catch (IOException e) {}
+                try {
+                    in.close();
+                } catch (IOException e) {
+                }
             }
         }
     }
 
-    private static String toClassName(String name) {
-        name = name.substring(0, name.length() - EXT.length());
-        name = name.replaceAll("/", ".");
-        return name;
-    }
-
-    private static String addSlash(String name) {
+    protected String addSlash(String name) {
         if (!name.endsWith("/")) {
             name = name + "/";
         }
         return name;
     }
 
-    private static Bundle isWired(Bundle bundle, ExportedPackage[] exports) {
+    protected Bundle isWired(Bundle bundle, ExportedPackage[] exports) {
         if (exports != null) {
             for (ExportedPackage exportedPackage : exports) {
                 Bundle[] importingBundles = exportedPackage.getImportingBundles();
@@ -259,7 +317,7 @@ public class BundleClassFinder {
         return null;
     }
 
-    private static Bundle isWired(Bundle bundle, RequiredBundle[] requiredBundles) {
+    protected Bundle isWired(Bundle bundle, RequiredBundle[] requiredBundles) {
         if (requiredBundles != null) {
             for (RequiredBundle requiredBundle : requiredBundles) {
                 Bundle[] requiringBundles = requiredBundle.getRequiringBundles();
@@ -317,7 +375,68 @@ public class BundleClassFinder {
 
         @Override
         public boolean rangeDiscoveryRequired(DiscoveryRange discoveryRange) {
-           return !discoveryRange.equals(DiscoveryRange.IMPORT_PACKAGES);
+            return !discoveryRange.equals(DiscoveryRange.IMPORT_PACKAGES);
+        }
+    }
+
+    private static class ImportExclusivePackageDiscoveryFilter implements ClassDiscoveryFilter
{
+
+        private String expectedPckageName;
+
+        public ImportExclusivePackageDiscoveryFilter(String expectedPckageName) {
+            this.expectedPckageName = expectedPckageName;
+        }
+
+        @Override
+        public boolean directoryDiscoveryRequired(String url) {
+            return true;
+        }
+
+        @Override
+        public boolean jarFileDiscoveryRequired(String url) {
+            return true;
+        }
+
+        @Override
+        public boolean packageDiscoveryRequired(String packageName) {
+            return expectedPckageName.equals(packageName);
+        }
+
+        @Override
+        public boolean rangeDiscoveryRequired(DiscoveryRange discoveryRange) {
+            return !discoveryRange.equals(DiscoveryRange.IMPORT_PACKAGES);
+        }
+    }
+
+    private static class ImportExclusivePackageDiscoveryFilterAdapter implements ClassDiscoveryFilter
{
+
+        private Set<String> acceptedPackageNames;
+
+        private ClassDiscoveryFilter classDiscoveryFilter;
+
+        public ImportExclusivePackageDiscoveryFilterAdapter(ClassDiscoveryFilter classDiscoveryFilter,
Set<String> acceptedPackageNames) {
+            this.classDiscoveryFilter = classDiscoveryFilter;
+            this.acceptedPackageNames = acceptedPackageNames;
+        }
+
+        @Override
+        public boolean directoryDiscoveryRequired(String url) {
+            return true;
+        }
+
+        @Override
+        public boolean jarFileDiscoveryRequired(String url) {
+            return true;
+        }
+
+        @Override
+        public boolean packageDiscoveryRequired(String packageName) {
+            return acceptedPackageNames.contains(packageName) && classDiscoveryFilter.packageDiscoveryRequired(packageName);
+        }
+
+        @Override
+        public boolean rangeDiscoveryRequired(DiscoveryRange discoveryRange) {
+            return !discoveryRange.equals(DiscoveryRange.IMPORT_PACKAGES);
         }
     }
 }

Modified: geronimo/xbean/trunk/xbean-finder/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/pom.xml?rev=941557&r1=941556&r2=941557&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/pom.xml (original)
+++ geronimo/xbean/trunk/xbean-finder/pom.xml Thu May  6 01:16:59 2010
@@ -33,10 +33,12 @@
     <description>XBean Finder helps to find annotations in classes</description>
     <dependencies>
         <dependency>
-            <artifactId>xbean-bundleutils</artifactId>
             <groupId>org.apache.xbean</groupId>
-            <version>3.7-SNAPSHOT</version>
-            <scope>provided</scope>
+            <artifactId>xbean-bundleutils</artifactId>            
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
         </dependency>
         <dependency>
             <groupId>asm</groupId>

Added: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/BundleAssignableClassFinder.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/BundleAssignableClassFinder.java?rev=941557&view=auto
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/BundleAssignableClassFinder.java
(added)
+++ geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/BundleAssignableClassFinder.java
Thu May  6 01:16:59 2010
@@ -0,0 +1,265 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.xbean.finder;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.xbean.osgi.bundle.util.BundleClassFinder;
+import org.apache.xbean.osgi.bundle.util.BundleDescription;
+import org.apache.xbean.osgi.bundle.util.ClassDiscoveryFilter;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.Opcodes;
+import org.osgi.framework.Bundle;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class BundleAssignableClassFinder extends BundleClassFinder {
+
+    private static final Logger logger = LoggerFactory.getLogger(BundleAssignableClassFinder.class);
+
+    private Class<?>[] clses;
+
+    private Set<String> targetClassNames = new HashSet<String>();
+
+    private Set<String> targetInterfaceNames = new HashSet<String>();
+
+    private Set<String> wiredImportedPackageNames = new HashSet<String>();
+
+    /**
+     * Create a new BundleClassFinder, it will search all the classes based the rule defined
by the parameters via ASM tool
+     * @param packageAdmin
+     * @param bundle
+     * @param clses
+     * @param discoveryFilter
+     */
+    public BundleAssignableClassFinder(PackageAdmin packageAdmin, Bundle bundle, Class<?>[]
clses, ClassDiscoveryFilter discoveryFilter) {
+        super(packageAdmin, bundle, discoveryFilter);
+        if (clses == null || clses.length == 0) {
+            throw new IllegalArgumentException("At least one class or interface should be
specified");
+        }
+        this.clses = clses;
+        for (Class<?> cls : clses) {
+            String asmStyleName = cls.getName().replace('.', '/');
+            if (cls.isInterface()) {
+                targetInterfaceNames.add(asmStyleName);
+            } else {
+                targetClassNames.add(asmStyleName);
+            }
+        }
+        initialize();
+    }
+
+    public BundleAssignableClassFinder(PackageAdmin packageAdmin, Class<?>[] clses,
Bundle bundle) {
+        this(packageAdmin, bundle, clses, FULL_CLASS_DISCOVERY_FILTER);
+    }
+
+    @Override
+    protected BundleClassFinder createSubBundleClassFinder(PackageAdmin packageAdmin, Bundle
bundle, ClassDiscoveryFilter classDiscoveryFilter) {
+        return new BundleAssignableClassFinder(packageAdmin, bundle, clses, classDiscoveryFilter);
+    }
+
+    @Override
+    protected boolean isClassAcceptable(String name, InputStream in) throws IOException {
+        ClassReader classReader = new ClassReader(in);
+        String className = classReader.getClassName();
+        if ((classReader.getAccess() & Opcodes.ACC_INTERFACE) == 0) {
+            if (targetClassNames.contains(className)) {
+                return true;
+            }
+        } else {
+            if (targetInterfaceNames.contains(className)) {
+                return true;
+            }
+        }
+        String[] interfaceNames = classReader.getInterfaces();
+        try {
+            for (String interfaceName : interfaceNames) {
+                if (wiredImportedPackageNames.contains(toASMStylePackageName(interfaceName)))
{
+                    return isClassAssignable(bundle.loadClass(toJavaStyleClassName(interfaceName)));
+                } else {
+                    if (isInterfaceAssignable(interfaceName)) {
+                        return true;
+                    }
+                }
+            }
+            String superClassName = classReader.getSuperName();
+            if (wiredImportedPackageNames.contains(toASMStylePackageName(superClassName)))
{
+                return isClassAssignable(bundle.loadClass(toJavaStyleClassName(superClassName)));
+            }
+            return isSuperClassAssignable(superClassName);
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+    }
+
+    @Override
+    protected boolean isClassAcceptable(URL url) {
+        InputStream in = null;
+        try {
+            in = url.openStream();
+            return isClassAcceptable("", in);
+        } catch (IOException e) {
+            logger.warn("Unable to check the class of url " + url, e);
+            return false;
+        } finally {
+            if (in != null)
+                try {
+                    in.close();
+                } catch (Exception e) {
+                }
+        }
+    }
+
+    private void initialize() {
+        BundleDescription description = new BundleDescription(bundle.getHeaders());
+        List<BundleDescription.ImportPackage> imports = description.getExternalImports();
+        for (BundleDescription.ImportPackage packageImport : imports) {
+            String packageName = packageImport.getName();
+            ExportedPackage[] exports = packageAdmin.getExportedPackages(packageName);
+            Bundle wiredBundle = isWired(bundle, exports);
+            if (wiredBundle != null) {
+                wiredImportedPackageNames.add(packageName.replace('.', '/'));
+                break;
+            }
+        }
+    }
+
+    private boolean isClassAssignable(Class<?> cls) {
+        for (Class<?> targetClass : clses) {
+            if (targetClass.isAssignableFrom(cls)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     *
+     * @param interfaceName The interface name should be in the format of org/test/SimpleInterface
+     * @return return true if the method parameter interfaceName is assignable to any interface
in the expected interfaces
+     */
+    private boolean isInterfaceAssignable(String interfaceName) {
+        //Check each interface in interfaceNames set
+        if (targetInterfaceNames.contains(interfaceName)) {
+            return true;
+        }
+        //Check ancestor intefaces
+        URL url = bundle.getResource("/" + interfaceName + ".class");
+        if (url == null) {
+            //TODO what should we do if we do not find the interface ?
+            return false;
+        }
+        InputStream in = null;
+        try {
+            in = url.openStream();
+            ClassReader classReader = new ClassReader(in);
+            String[] superInterfaceNames = classReader.getInterfaces();
+            for (String superInterfaceName : superInterfaceNames) {
+                if (isInterfaceAssignable(superInterfaceName)) {
+                    return true;
+                }
+            }
+            return false;
+        } catch (IOException e) {
+            logger.warn("Unable to check the interface " + interfaceName, e);
+            return false;
+        } finally {
+            if (in != null)
+                try {
+                    in.close();
+                } catch (Exception e) {
+                }
+        }
+    }
+
+    /**
+     *
+     * @param superClassName The super class name should be in the format of org/test/SimpleClass
+     * @return return true if the method parameter superClassName  is assignable to any interface
in the expected interfaces or any class in the expected classes
+     */
+    private boolean isSuperClassAssignable(String superClassName) {
+        if (targetClassNames.contains(superClassName)) {
+            return true;
+        }
+        //Check parent class
+        URL url = bundle.getResource("/" + superClassName + ".class");
+        if (url == null) {
+            //TODO what should we do if we do not find the super class ?
+            return false;
+        }
+        InputStream in = null;
+        try {
+            in = url.openStream();
+            ClassReader classReader = new ClassReader(in);
+            String[] superInterfaceNames = classReader.getInterfaces();
+            //Check interfaces
+            for (String superInterfaceName : superInterfaceNames) {
+                if (isInterfaceAssignable(superInterfaceName)) {
+                    return true;
+                }
+            }
+            //Check className
+            if (classReader.getSuperName().equals("java/lang/Object")) {
+                return targetClassNames.contains("java/lang/Object");
+            } else {
+                return isSuperClassAssignable(classReader.getSuperName());
+            }
+        } catch (IOException e) {
+            logger.warn("Unable to check the super class  " + superClassName, e);
+            return false;
+        } finally {
+            if (in != null)
+                try {
+                    in.close();
+                } catch (Exception e) {
+                }
+        }
+    }
+
+    /**
+     * Get the ASM style package name from the parameter className.
+     * If the className is ended with .class extension, e.g.  /org/apache/geronimo/TestCass.class
or org.apache.geronimo.TestClass.class,
+     *      then org/apache/geronimo is returned
+     * If the className is not ended with .class extension, e.g.  /org/apache/geronimo/TestCass
or org.apache.geronimo.TestClass,
+     *      then org/apache/geronimo is returned
+     * @param className
+     * @return ASM style package name, should be in the format of  "org/apache/geronimo"
+     */
+    protected String toASMStylePackageName(String className) {
+        if (className.endsWith(EXT)) {
+            className = className.substring(0, className.length() - EXT.length());
+        }
+        className = className.replace('.', '/');
+        int iLastDotIndex = className.lastIndexOf('/');
+        if (iLastDotIndex != -1) {
+            return className.substring(0, iLastDotIndex);
+        } else {
+            return "";
+        }
+    }
+}

Propchange: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/BundleAssignableClassFinder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/BundleAssignableClassFinder.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/BundleAssignableClassFinder.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message