All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.loicoudot.java4cpp.Context Maven / Gradle / Ivy

package com.github.loicoudot.java4cpp;

import static com.github.loicoudot.java4cpp.Utils.newArrayList;
import static com.github.loicoudot.java4cpp.Utils.newHashMap;

import java.io.File;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URL;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import com.github.loicoudot.java4cpp.model.ClassModel;
import com.github.loicoudot.java4cpp.model.ClassType;

/**
 * {@code Context} class contains all the environement of an execution of
 * java4cpp.
 * 
 * @author Loic Oudot
 * 
 */
public final class Context {

    private final Settings settings;
    private final FileManager fileManager;
    private final MappingsManager mappingsManager;
    private final TemplateManager templateManager;
    private Java4CppClassLoader classLoader = new Java4CppClassLoader();
    private final BlockingQueue classesToDo = new ArrayBlockingQueue(1024);
    private final List classesAlreadyDone = newArrayList();
    private final Map classModelCache = newHashMap();
    private final Analyzer[] analyzers;
    private final Analyzer typeAnalyzer;

    public Context(Settings settings) {
        this.settings = settings;
        fileManager = new FileManager(this);
        mappingsManager = new MappingsManager(this);
        templateManager = new TemplateManager(this);
        typeAnalyzer = new TypeAnalyzer(this);
        analyzers = new Analyzer[] { typeAnalyzer, new SuperclassAnalyzer(this), new InterfacesAnalyzer(this), new InnerClassAnalyzer(this),
                new FieldsAnalyzer(this), new EnumAnalyzer(this), new ConstructorsAnalyzer(this), new MethodsAnalyzer(this) };
    }

    /**
     * Called before begining the processing of classes. Initialize all internal
     * parts with all the configurations.
     */
    public void start() {
        createClassLoader();
        getFileManager().start();
        getMappingsManager().start();
        addClassToDoFromJars();
        getTemplateManager().start();
    }

    /**
     * Called after all the classes are processed. Finalize the job by cleaning
     * up the target directory.
     */
    public void stop() {
        getFileManager().stop();
    }

    /**
     * Construct the context class loader by adding all jars.
     */
    private void createClassLoader() {
        if (!Utils.isNullOrEmpty(settings.getJarFiles())) {
            try {
                String[] files = settings.getJarFiles().split(";");
                List urls = newArrayList();
                for (String path : files) {
                    File file = new File(path);
                    if (file.isFile()) {
                        urls.add(file.toURI().toURL());
                    }
                }
                classLoader = new Java4CppClassLoader(urls.toArray(new URL[files.length]), classLoader);
            } catch (Exception e) {
                throw new RuntimeException("Failed to load jar " + e.getMessage());
            }
        }
    }

    /**
     * Add annotated classes with {@code Java4Cpp} annotation to the current
     * list of class to be processed by introspecting jar files.
     */
    private void addClassToDoFromJars() {
        if (!Utils.isNullOrEmpty(settings.getJarFiles())) {
            try {
                String[] files = settings.getJarFiles().split(";");
                for (String path : files) {
                    File file = new File(path);
                    if (!file.isFile()) {
                        String jarPath = classLoader.getJar(path);
                        if (jarPath == null) {
                            getFileManager().logInfo("can't find " + path);
                        }
                        file = new File(new URI(jarPath));
                    }
                    getFileManager().logInfo("searching classes to wrappe in " + file.getAbsolutePath());
                    JarFile jf = new JarFile(file);
                    Enumeration entries = jf.entries();
                    while (entries.hasMoreElements()) {
                        String clName = entries.nextElement().getName();
                        if (clName.endsWith(".class")) {
                            Class clazz = classLoader.loadClass(clName.split("\\.")[0].replace('/', '.'));
                            if (clazz.isAnnotationPresent(Java4Cpp.class)) {
                                addClassToDo(clazz);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException("Failed to load jar " + e.getMessage());
            }
        }
    }

    public void addClassToDo(Type type) {
        addClassToDo(Java4CppType.fromType(type));
    }

    public void addClassToDo(Java4CppType type) {
        synchronized (classesToDo) {
            if (!classesAlreadyDone.contains(type) && !classesToDo.contains(type)) {
                classesToDo.add(type);
                classesAlreadyDone.add(type);
                getFileManager().logInfo("add dependency " + type);
            }
        }
    }

    public BlockingQueue getClassesToDo() {
        return classesToDo;
    }

    public boolean workToDo() {
        return !classesToDo.isEmpty();
    }

    public List getClassesAlreadyDone() {
        return classesAlreadyDone;
    }

    public Settings getSettings() {
        return settings;
    }

    public FileManager getFileManager() {
        return fileManager;
    }

    public MappingsManager getMappingsManager() {
        return mappingsManager;
    }

    public TemplateManager getTemplateManager() {
        return templateManager;
    }

    public Class loadClass(String clazz) {
        try {
            return classLoader.loadClass(clazz);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public ClassModel analyzeClassModel(Java4CppType type) {
        try {
            getFileManager().enter("analyzing " + type);
            ClassModel classModel = getClassModel(type);
            if (getTemplateManager().getTypeTemplates(type.getRawClass()).isNeedAnalyzing()) {
                for (Analyzer analyzer : analyzers) {
                    analyzer.fill(classModel);
                }
            } else {
                typeAnalyzer.fill(classModel);
            }
            return classModel;
        } finally {
            getFileManager().leave();
        }
    }

    public ClassModel executeTypeTemplate(Java4CppType type) {
        try {
            getFileManager().enter("templating " + type);
            ClassModel classModel = getClassModel(type);
            ClassType typeModel = classModel.getType();

            TypeTemplates typeTemplates = getTemplateManager().getTypeTemplates(type.getRawClass());
            typeModel.setCppType(typeTemplates.getCppType(classModel));
            typeModel.setCppReturnType(typeTemplates.getCppReturnType(classModel));
            typeTemplates.executeDependencies(classModel);
            typeModel.setFunctions(typeTemplates.getFunctions(classModel));
            return classModel;
        } finally {
            getFileManager().leave();
        }
    }

    public ClassModel getClassModel(Type type) {
        return getClassModel(Java4CppType.fromType(type));
    }

    public ClassModel getClassModel(Java4CppType type) {
        if (!classModelCache.containsKey(type)) {
            synchronized (classModelCache) {
                if (!classModelCache.containsKey(type)) {
                    ClassModel classModel = new ClassModel(type);
                    classModelCache.put(type, classModel);
                    addClassToDo(type.getRawClass());
                    addClassToDo(type);

                    for (Java4CppType argumentType : type.getParameterizedTypes()) {
                        classModel.addParameter(getClassModel(argumentType));
                    }
                }
            }
        }
        return classModelCache.get(type);
    }

    public ClassModel getClassModel(String name) {
        try {
            return getClassModel(classLoader.loadClass(name));
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Failed to load class " + e.getMessage());
        }
    }

    public List getClassesModels(Type[] types) {
        List result = newArrayList();
        for (Type type : types) {
            result.add(getClassModel(type));
        }
        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy