/*
 * 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.camel.core.osgi;

import java.lang.reflect.Method;
import java.net.URL;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.camel.core.osgi.utils.BundleDelegatingClassLoader;
import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
import org.apache.camel.spi.PackageScanFilter;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

public class OsgiPackageScanClassResolver extends DefaultPackageScanClassResolver {

    private final Bundle bundle;

    public OsgiPackageScanClassResolver(BundleContext context) {
        this(context.getBundle());
    }

    public OsgiPackageScanClassResolver(Bundle bundle) {
        this.bundle = bundle;
        // add the BundleDelegatingClassLoader to the class loaders
        addClassLoader(new BundleDelegatingClassLoader(bundle));
    }

    @Override
    public void find(PackageScanFilter test, String packageName, Set<Class<?>> classes) {
        packageName = packageName.replace('.', '/');
        // remember the number of classes found so far
        int classesSize = classes.size();
        // look in osgi bundles
        loadImplementationsInBundle(test, packageName, classes);
        // if we did not find any new, then fallback to use regular non bundle class loading
        if (classes.size() == classesSize) {
            // Using the non-OSGi classloaders as a fallback
            // this is necessary when use JBI packaging for servicemix-camel SU
            // so that we get chance to use SU classloader to scan packages in the SU
            log.trace("Cannot find any classes in bundles, not trying regular classloaders scanning: {}", packageName);
            for (ClassLoader classLoader : super.getClassLoaders()) {
                if (!isOsgiClassloader(classLoader)) {
                    find(test, packageName, classLoader, classes);
                }
            }  
        }
    }
    
    private static boolean isOsgiClassloader(ClassLoader loader) {
        try {
            Method mth = loader.getClass().getMethod("getBundle", new Class[] {});
            if (mth != null) {
                return true;
            }
        } catch (NoSuchMethodException e) {
            // ignore its not an osgi loader
        }
        return false;
    }
    
    private void loadImplementationsInBundle(PackageScanFilter test, String packageName, Set<Class<?>> classes) {       
        Set<String> urls = getImplementationsInBundle(test, packageName);
        if (urls != null) {
            for (String url : urls) {
                // substring to avoid leading slashes
                addIfMatching(test, url, classes);
            }
        }
    }

    private Set<String> getImplementationsInBundle(PackageScanFilter test, String packageName) {
        Bundle[] bundles;
        if (bundle.getBundleContext() != null) {
            bundles = bundle.getBundleContext().getBundles();
        } else {
            bundles = new Bundle[]{bundle};
        }
        Set<String> urls = new LinkedHashSet<>();
        for (Bundle bd : bundles) {
            log.trace("Searching in bundle: {}", bd);
            try {
                Enumeration<URL> paths = bd.findEntries("/" + packageName, "*.class", true);
                while (paths != null && paths.hasMoreElements()) {
                    URL path = paths.nextElement();
                    String pathString = path.getPath();
                    String urlString = pathString.substring(pathString.indexOf(packageName));
                    urls.add(urlString);
                    log.trace("Added url: {}", urlString);
                }
            } catch (Throwable t) {
                log.warn("Cannot search in bundle: " + bundle + " for classes matching criteria: " + test + " due: "
                        + t.getMessage() + ". This exception will be ignored.", t);
            }
        }
        return urls;
    }

}
