org.eclipse.eclipsemonkey.lang.python.PythonClassLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.eclipsemonkey.lang.python.PythonClassLoader.java

Source

/*******************************************************************************
 * Copyright (c) 2005-2006 Aptana, Inc.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html. If redistributing this code,
 * this entire header must remain intact.
 * 
 * Contributions:
 *    Kevin Lindsey based on code by Patrick Mueller
 *    Jos Fonseca - adapted for python
 *******************************************************************************/

package org.eclipse.eclipsemonkey.lang.python;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;

import org.osgi.framework.Bundle;
import org.python.core.PySystemState;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

/**
 * @author Kevin Lindsey based on code by Patrick Mueller
 */
public class PythonClassLoader extends ClassLoader {

    private ArrayList<Bundle> _bundles;

    /**
     * ScriptClassLoader
     */
    public PythonClassLoader() {
        super(PythonClassLoader.class.getClassLoader());

        this._bundles = new ArrayList<Bundle>();
    }

    /**
     * addBundle
     * 
     * @param bundle
     */
    public void addBundle(Bundle bundle) {
        if (bundle == null) {
            throw new IllegalArgumentException("ScriptClassLoader_Bundle_Not_Defined");
        }

        if (this._bundles.contains(bundle) == false) {
            addPackagesFromBundle(bundle);
        }
    }

    private void addPackagesFromBundle(Bundle bundle) {
        this._bundles.add(bundle);
        addPackage(bundle, "Provide-Package");
        addPackage(bundle, "Export-Package");
    }

    private static Multimap<String, Bundle> packageToBundle = null;

    protected Multimap<String, Bundle> getMapPackageToBundle() {
        if (packageToBundle == null) {
            packageToBundle = ArrayListMultimap.create();
        }
        return packageToBundle;
    }

    private void addPackage(Bundle b, String propName) {
        String packages = (String) b.getHeaders().get(propName);
        if (packages != null) {
            String[] names = packages.split(",");
            for (int j = 0; j < names.length; ++j) {
                String packageSpec = names[j];
                PySystemState.add_package(packageSpec);
                String[] pacakgeProperty = packageSpec.split(";");
                if (pacakgeProperty != null && pacakgeProperty.length > 0) {
                    String packageName = pacakgeProperty[0].trim();
                    getMapPackageToBundle().put(packageName, b);
                }
            }
        }
    }

    /**
     * findClass
     * 
     * @param name
     * @return Class
     * @throws ClassNotFoundException
     */
    @Override
    protected Class findClass(String name) throws ClassNotFoundException {
        Class result = this.loadClassFromBundles(name);

        if (result == null) {
            String message = "ScriptClassLoader_Unable_To_Find_Class: " + name;

            throw new ClassNotFoundException(message);
        }

        return result;
    }

    /**
     * findResource
     * 
     * @param name
     * @return URL
     */
    @Override
    protected URL findResource(String name) {
        URL result = super.findResource(name);

        if (result == null) {
            Iterator<Bundle> iterator = this._bundles.iterator();

            while (iterator.hasNext()) {
                Bundle bundle = iterator.next();

                result = bundle.getResource(name);

                if (result != null) {
                    break;
                }
            }
        }

        return result;
    }

    /**
     * findResources
     * 
     * @param name
     * @return Enumeration
     * @throws IOException
     */
    @Override
    protected Enumeration findResources(String name) throws IOException {
        Enumeration result = super.findResources(name);

        if (result == null) {
            Iterator<Bundle> iterator = this._bundles.iterator();

            while (iterator.hasNext()) {
                Bundle bundle = iterator.next();

                result = bundle.getResources(name);

                if (result != null) {
                    break;
                }
            }
        }

        if (result == null) {
            String message = "ScriptClassLoader_Unable_To_Find_Resource: " + name;

            throw new IOException(message);
        }

        return result;
    }

    /**
     * loadClass
     * 
     * @param name
     * @return Class
     * @throws ClassNotFoundException
     */
    @Override
    public Class loadClass(String name) throws ClassNotFoundException {
        Class result = null;
        try {
            result = super.loadClass(name);
        } catch (ClassNotFoundException e) {
            result = this.loadClassFromBundles(name);
        }

        if (result == null) {
            String message = "ScriptClassLoader_Unable_To_Load_Class: " + name;

            throw new ClassNotFoundException(message);
        }

        return result;
    }

    /**
     * loadClass
     * 
     * @param name
     * @param resolve
     * @return Class
     * @throws ClassNotFoundException
     */
    @Override
    protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
        Class result = super.loadClass(name, resolve);

        if (result == null) {
            result = this.loadClassFromBundles(name);
        }

        if (result == null) {
            String message = "ScriptClassLoader_Unable_To_Load_Class: " + name;

            throw new ClassNotFoundException(message);
        }

        return result;
    }

    /**
     * loadClassFromBundles
     * 
     * @param name
     * @return Class
     * @throws ClassNotFoundException
     */
    private Class loadClassFromBundles(String name) throws ClassNotFoundException {
        Class result = null;
        String pacakgeName = getPackageName(name);
        if (pacakgeName != null) {
            for (Bundle b : getMapPackageToBundle().get(pacakgeName)) {
                result = b.loadClass(name);
                if (result != null) {
                    return result;
                }
            }
        }
        return result;
    }

    protected String getPackageName(String name) {
        String[] segments = name.split("\\.");
        if (segments != null && segments.length > 0) {
            String pacakgeName = name.replace("." + segments[segments.length - 1], "");
            return pacakgeName;
        }
        return null;
    }
}