Package com.redhat.ceylon.compiler.loader.model

Source Code of com.redhat.ceylon.compiler.loader.model.LazyModule

/*
* Copyright Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the authors tag. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License version 2.
*
* This particular file is subject to the "Classpath" exception as provided in the
* LICENSE file that accompanied this code.
*
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License,
* along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*/

package com.redhat.ceylon.compiler.loader.model;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import com.redhat.ceylon.cmr.api.ArtifactResult;
import com.redhat.ceylon.cmr.api.JDKUtils;
import com.redhat.ceylon.cmr.api.PathFilter;
import com.redhat.ceylon.compiler.java.util.Util;
import com.redhat.ceylon.compiler.loader.AbstractModelLoader;
import com.redhat.ceylon.compiler.loader.ContentAwareArtifactResult;
import com.redhat.ceylon.compiler.typechecker.model.Module;
import com.redhat.ceylon.compiler.typechecker.model.ModuleImport;
import com.redhat.ceylon.compiler.typechecker.model.Package;

/**
* Represents a lazy Module declaration.
*
* @author Stéphane Épardaud <stef@epardaud.fr>
*/
public abstract class LazyModule extends Module {

    private boolean isJava = false;
    protected Set<String> jarPackages = new HashSet<String>();

    public LazyModule() {
    }

    @Override
    public Package getDirectPackage(String name) {
        return findPackageInModule(this, name);
    }
   
    @Override
    public Package getPackage(String name) {
        // try here first
        Package pkg = null;
       
        // unless we're the default module, in which case we have to check this at the end,
        // since every package can be part of the default module
        boolean defaultModule = isDefault();
        if(!defaultModule){
            pkg = findPackageInModule(this, name);
            if(pkg != null)
                return pkg;
        }
        // then try in dependencies
        Set<Module> visited = new HashSet<Module>();
        for(ModuleImport dependency : getImports()){
            // we don't have to worry about the default module here since we can't depend on it
            pkg = findPackageInImport(name, dependency, visited);
            if(pkg != null)
                return pkg;
        }
        // The JDK uses arrays, which we pretend are in java.lang, and ByteArray needs ceylon.language.Byte,
        // so we pretend the JDK imports the language module
        if(JDKUtils.isJDKModule(getNameAsString()) || JDKUtils.isOracleJDKModule(getNameAsString())){
            Module languageModule = getModelLoader().getLanguageModule();
            if(languageModule instanceof LazyModule){
                pkg = findPackageInModule((LazyModule) languageModule, name);
                if(pkg != null)
                    return pkg;
            }
        }
        // never try to load java packages from the default module because it would
        // work and appear to come from there
        if(JDKUtils.isJDKAnyPackage(name) || JDKUtils.isOracleJDKAnyPackage(name)){
            return null;
        }
        // do the lookup of the default module last
        if(defaultModule)
            pkg = getModelLoader().findExistingPackage(this, name);
        return pkg;
    }

    private Package findPackageInImport(String name, ModuleImport dependency, Set<Module> visited) {
        Module module = dependency.getModule();
        // only visit modules once
        if(!visited.add(module))
            return null;
        if (module instanceof LazyModule) {
            // this is the equivalent of getDirectPackage, it does not recurse
            Package pkg =  findPackageInModule((LazyModule) dependency.getModule(), name);
            if(pkg != null)
                return pkg;
            // not found, try in its exported dependencies
            for(ModuleImport dep : module.getImports()){
                if(!dep.isExport())
                    continue;
                pkg = findPackageInImport(name, dep, visited);
                if(pkg != null)
                    return pkg;
            }
            // not found
            return null;
        }
        else
            return module.getPackage(name);
    }

    private Package findPackageInModule(LazyModule module, String name) {
        if(module.containsPackage(name)){
            // first try the already loaded packages from that module
            AbstractModelLoader modelLoader = getModelLoader();
            synchronized(modelLoader.getLock()){
                for(Package pkg : module.getPackages()){
                    if(pkg.getNameAsString().equals(name))
                        return pkg;
                }
                // create/load a new one
                return getModelLoader().findExistingPackage(module, name);
            }
        }
        return null;
    }

    public Package findPackageNoLazyLoading(String name) {
        // make sure we don't call any overloaded getPackages() that might trigger lazy loading
        for(Package pkg : super.getPackages()){
            if(pkg.getNameAsString().equals(name))
                return pkg;
        }
        return null;
    }

    protected abstract AbstractModelLoader getModelLoader();

    public boolean isJava() {
        return isJava;
    }

    public void setJava(boolean isJava) {
        this.isJava = isJava;
    }

    public void loadPackageList(ArtifactResult artifact) {
        if (artifact instanceof ContentAwareArtifactResult) {
            for (String entry : ((ContentAwareArtifactResult) artifact).getEntries()) {
                addPackageForPath(entry, artifact.filter());
            }
        } else {
            File file = artifact.artifact();
            if (file != null) {
                ZipFile zipFile;
                try {
                    zipFile = new ZipFile(artifact.artifact());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                try{
                    Enumeration<? extends ZipEntry> entries = zipFile.entries();
                    while(entries.hasMoreElements())
                        loadPackageList(entries.nextElement(), artifact.filter());
                }finally{
                    try {
                        zipFile.close();
                    } catch (IOException e) {
                        // ignore
                    }
                }
            }
        }
    }
   
    private void loadPackageList(ZipEntry entry, PathFilter pathFilter) {
        if(!entry.isDirectory()){
            String path = entry.getName();
            addPackageForPath(path, pathFilter);
        }
    }

    private void addPackageForPath(String path, PathFilter pathFilter) {
        if(path.toLowerCase().endsWith(".class")){
            int sep = path.lastIndexOf('/');
            if(sep != -1)
                path = path.substring(0, sep);
            String pkg = path;
            // make sure we unquote any package part
            pkg = pkg.replace("$", "");
            String pathQuery;
            if(path.isEmpty())
                pathQuery = pkg;
            else
                pathQuery = pkg+"/";
            if(pathFilter == null || pathFilter.accept(pathQuery)){
                pkg = pkg.replace('/', '.');
                jarPackages.add(pkg);
            }
        }
    }

    public boolean containsPackage(String pkgName){
        String moduleName = getNameAsString();
        if(!isJava){
            List<Package> superPackages = super.getPackages();
            for(int i=0,l=superPackages.size();i<l;i++){
                if(superPackages.get(i).getNameAsString().equals(pkgName))
                    return true;
            }
            // The language module is in the classpath and does not have its jarPackages loaded
            if(moduleName.equals(Module.LANGUAGE_MODULE_NAME)){
                return Util.isSubPackage(moduleName, pkgName)
                        || pkgName.startsWith("com.redhat.ceylon.compiler.java.runtime")
                        || pkgName.startsWith("com.redhat.ceylon.compiler.java.language")
                        || pkgName.startsWith("com.redhat.ceylon.compiler.java.metadata");
            }
            return jarPackages.contains(pkgName);
        }else{
            // special rules for the JDK which we don't load from the repo
            if(JDKUtils.isJDKPackage(moduleName, pkgName)
                    || JDKUtils.isOracleJDKPackage(moduleName, pkgName))
                return true;
            // otherwise we have the list of packages contained in that module jar
            return jarPackages.contains(pkgName);
        }
    }
   
    @Override
    protected boolean isJdkModule(String moduleName) {
        return JDKUtils.isJDKModule(moduleName) || JDKUtils.isOracleJDKModule(moduleName);
    }
   
    @Override
    protected boolean isJdkPackage(String moduleName, String packageName) {
        return JDKUtils.isJDKPackage(moduleName, packageName)
                || JDKUtils.isOracleJDKPackage(moduleName, packageName);
    }

    public void addPackage(Package pkg){
        // make sure we don't call any overloaded getPackages() that might trigger lazy loading
        super.getPackages().add(pkg);
    }
}
TOP

Related Classes of com.redhat.ceylon.compiler.loader.model.LazyModule

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.