Package org.apache.tuscany.sca.contribution.impl

Source Code of org.apache.tuscany.sca.contribution.impl.ContributionClassLoader

/*
* 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.tuscany.sca.contribution.impl;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;

import org.apache.tuscany.sca.contribution.Contribution;
import org.apache.tuscany.sca.contribution.Export;
import org.apache.tuscany.sca.contribution.Import;
import org.apache.tuscany.sca.contribution.java.JavaImport;
import org.apache.tuscany.sca.contribution.namespace.NamespaceImport;

public class ContributionClassLoader extends URLClassLoader {
   
    private Contribution contribution;

    /**
     * Constructor for contribution classloader
     *
     * @param contribution
     * @throws MalformedURLException
     */
    public ContributionClassLoader(Contribution contribution) {
       
        // To enable contributions to access code outside of SCA contributions
        // (typically by providing them on CLASSPATH), use the thread context
        // classloader as the parent of all contribution classloaders.
       
        super(new URL[0], Thread.currentThread().getContextClassLoader());
        this.contribution = contribution;
    }

   
    /**
     * Add the URL of the contribution to the classloader search path.
     *
     * @param location Contribution URL
     */
    public void setContributionLocation(String location) {
       
        try {
            this.addURL(new URL(contribution.getLocation()));
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }
   

    /* (non-Javadoc)
     * @see java.net.URLClassLoader#findClass(java.lang.String)
     *
     * Search path for class:
     *     This contribution
     *     Imported contributions
     */
    @Override  
    protected Class<?> findClass(String className) throws ClassNotFoundException {
       
        Class<?> clazz = null;
        try {
            clazz = findClassFromContribution(className);
        } catch (ClassNotFoundException e) {
               
            for (Import import_ : this.contribution.getImports()) {
                if (matchesImport(className, import_, true)) {
                    // Delegate the resolution to the imported contribution
                    for (Contribution exportingContribution : import_.getExportContributions()) {
                                   
                        if (exportingContribution.getClassLoader() instanceof ContributionClassLoader) {

                            for (Export export : exportingContribution.getExports()) {
                                try {
                                    if (import_.match(export)) {
                                        clazz = ((ContributionClassLoader)exportingContribution.getClassLoader()).findClassFromContribution(className);
                                        break;
                                    }
                                } catch (ClassNotFoundException e1) {
                                    continue;
                                }
                                   
                            }
                            if (clazz != nullbreak;
                        }
                    }
                    if (clazz != null) break;
                }
            }

            if (clazz == null) throw e;
        }
        return clazz;
    }

   
    /* (non-Javadoc)
     * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
     *
     * Search path for class:
     *     Parent classloader
     *     This contribution
     *     Imported contributions
     *    
     */
    @Override
    protected synchronized Class<?> loadClass(String className, boolean resolveClass)
        throws ClassNotFoundException {
      
        Class<?> clazz = null;
        try {
           
            if (this.getParent() != null)
                clazz = this.getParent().loadClass(className);
           
        } catch (ClassNotFoundException e) {
        }

        if (clazz == null)
            clazz = findClass(className);


        if (resolveClass)
            this.resolveClass(clazz);
        return clazz;
       
    }


  
    /*
     * (non-Javadoc)
     *
     * @see java.net.URLClassLoader#findResource(java.lang.String)
     */
    @Override
    public URL findResource(String name) {
       
        URL url = findResourceFromContribution(name);
       
        if (url == null) {
            for (Import import_ : this.contribution.getImports()) {
                if (matchesImport(name, import_, false)) {
                    // Delegate the resolution to the imported contribution
                    for (Contribution exportingContribution : import_.getExportContributions()) {
                               
                        if (exportingContribution.getClassLoader() instanceof ContributionClassLoader) {

                            for (Export export : exportingContribution.getExports()) {
                                if (import_.match(export)) {
                                    url = ((ContributionClassLoader)exportingContribution.getClassLoader()).findResourceFromContribution(name);
                                    if (url != null) break;
                                }
                            }
                            if (url != nullbreak;
                        }
                    }
                    if (url != null) break;
                }
            }

        }
        return url;
    }


    /* (non-Javadoc)
     * @see java.net.URLClassLoader#findResources(java.lang.String)
     */
    @Override
    public Enumeration<URL> findResources(String name) throws IOException {
             
        return Collections.enumeration(findResourceSet(name));
    }
   
   

   
    /* (non-Javadoc)
     * @see java.lang.ClassLoader#getResource(java.lang.String)
     *
     * Find a resource.
     * Search path for resource:
     *     Parent classloader
     *     This contribution
     *     Imported contributions
     */
    @Override
    public URL getResource(String resName) {
        URL resource  = null;
       
        if (this.getParent() != null) {
            resource  = this.getParent().getResource(resName);
        }       
        if (resource == null)
            resource  = findResource(resName);
       
        return resource;
    }


   
    /* (non-Javadoc)
     * @see java.lang.ClassLoader#getResources(java.lang.String)
     *
     * Return list of resources from this contribution, resources
     * imported through imported contributions and resources from parent
     * classloader.
     */
    @Override
    public Enumeration<URL> getResources(String resName) throws IOException {
      
        HashSet<URL> resourceSet = findResourceSet(resName);
        addEnumerationToCollection(resourceSet, super.getResources(resName));
       
        return Collections.enumeration(resourceSet);
    }
   

    /*
     * Find set of resources
     */
    private HashSet<URL> findResourceSet(String name) throws IOException {
       
        HashSet<URL> resources = new HashSet<URL>();

        addEnumerationToCollection(resources, super.findResources(name));
       
        for (Import import_ : this.contribution.getImports()) {
            if (matchesImport(name, import_, false)) {
                // Delegate the resolution to the imported contribution
                for (Contribution exportingContribution : import_.getExportContributions()) {
                               
                    if (exportingContribution.getClassLoader() instanceof ContributionClassLoader) {

                        for (Export export : exportingContribution.getExports()) {
                            if (import_.match(export)) {
                                addEnumerationToCollection(resources,
                                        ((ContributionClassLoader)exportingContribution.getClassLoader()).findResources(name));
                            }
                        }
                    }
                }
            }
         }

        return resources;
    }


    /*
     * Find class from contribution. If class has already been loaded, return loaded class.
     */
    private Class<?> findClassFromContribution(String className) throws ClassNotFoundException {
       
        Class<?> clazz = findLoadedClass(className);
        if (clazz == null)
            clazz =  super.findClass(className);
        return clazz;
      
    }
   
    /*
     * Find resource from contribution.
     */
    private URL findResourceFromContribution(String name) {
       
        return super.findResource(name);
    }
   
    /**
     * Check if a class or resource matches an import statement.
     * Class matches if the package name used in <import.java/> matches
     * Resource matches if package/namespace match the directory of resource.
     *
     * @param name    Name of class or resource
     * @param import_ SCA contribution import
     * @param matchJavaClass
     * @return true if this is a matching import
     */
    private boolean matchesImport(String name, Import import_, boolean matchJavaClass) {
      
        if (matchJavaClass) {
            if (import_ instanceof JavaImport && name != null && name.lastIndexOf('.') > 0) {
                JavaImport javaImport = (JavaImport) import_;
                String packageName = name.substring(0, name.lastIndexOf('.'));
                if (javaImport.getPackage() == null)
                    return false;
                else
                    return packageName.equals(javaImport.getPackage());
            }
           
        } else {
            if (name == null || name.lastIndexOf('/') <= 0)
                return false;
            else if (import_ instanceof JavaImport) {
                JavaImport javaImport = (JavaImport) import_;
                String packageName = name.substring(0, name.lastIndexOf('/'));
                if (javaImport.getPackage() == null)
                    return false;
                else
                    return packageName.equals(javaImport.getPackage().replaceAll("\\.", "/"));
            } else if (import_ instanceof NamespaceImport) {
                NamespaceImport namespaceImport = (NamespaceImport) import_;
                String namespace = name.substring(0, name.lastIndexOf('/'));
                if (namespaceImport.getNamespace() == null)
                    return false;
                else
                    return namespaceImport.getNamespace().equals(namespace);
            }
        }
        return false;
    }
   
    /*
     * Add an enumeration to a Collection
     */
    private <T extends Object> void addEnumerationToCollection(Collection<T> collection, Enumeration<T> enumeration) {
       
        while (enumeration.hasMoreElements())
            collection.add(enumeration.nextElement());
    }
   
   
    @Override
    public String toString() {
        return "SCA contribution classloader for : " + contribution.getLocation();
    }
   
   
}
TOP

Related Classes of org.apache.tuscany.sca.contribution.impl.ContributionClassLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.