fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.internal.Neo4JRuntimesManager.java Source code

Java tutorial

Introduction

Here is the source code for fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.internal.Neo4JRuntimesManager.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Atlanmod INRIA LINA Mines Nantes
 * 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
 *
 * Contributors:
 *     Atlanmod INRIA LINA Mines Nantes - initial API and implementation
 *******************************************************************************/
package fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.internal;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

import fr.inria.atlanmod.neo4emf.neo4jresolver.Neo4jResolverPlugin;
import fr.inria.atlanmod.neo4emf.neo4jresolver.collections.ObservableArrayList;
import fr.inria.atlanmod.neo4emf.neo4jresolver.logger.Logger;
import fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.AbstractNeo4jRuntimeInstaller;
import fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.INeo4jRuntime;
import fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.INeo4jRuntimesManager;
import fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.JarFilter;
import fr.inria.atlanmod.neo4emf.neo4jresolver.wizards.ImportNeo4jRuntimeWizard;

/**
 * @author abelgomez
 *
 */
public class Neo4JRuntimesManager implements INeo4jRuntimesManager {

    /**
     * 
     */
    private static final String EXPORT_PACKAGE = "Export-Package";
    /**
     * 
     */
    private static final String BUNDLE_CLASS_PATH = "Bundle-ClassPath";
    /**
     * 
     */
    private static final String BUNDLE_VERSION = "Bundle-Version";
    /**
     * 
     */
    private static final String BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
    /**
     * 
     */
    private static final String BUNDLE_NAME = "Bundle-Name";
    /**
     * 
     */
    private static final String BUNDLE_MANIFEST_VERSION = "Bundle-ManifestVersion";
    private static final String MANIFEST_MF = "MANIFEST.MF";
    private static final String META_INF = "META-INF";

    private static final String CLASSPATH = ".classpath";
    private static final String PROJECT = ".project";
    private static final String BUILD_PROPERTIES = "build.properties";

    private static final String RUNTIMES_DIR = "runtimes";
    private static final String INSTALLERS_EXTENSION_POINT_ID = "fr.inria.atlanmod.neo4emf.neo4jresolver.neo4jInstallers";
    private static final String ATT_ID = "id";
    private static final String ATT_NAME = "name";
    private static final String ATT_VERSION = "version";
    private static final String ATT_DESCRIPTION = "description";
    private static final String ATT_URL = "url";
    private static final String ATT_PATH = "path";
    private static final String ATT_HANDLER = "handler";
    private static final String CHILD_LICENSE = "License";
    private static final String CHILD_ZIPENTRY = "ZipEntry";

    public static final Neo4JRuntimesManager INSTANCE;

    private static List<INeo4jRuntime> installedRuntimes;
    private static List<AbstractNeo4jRuntimeInstaller> installers;

    private static IPath dataAreaPath;

    private volatile Runnable checkRuntimeRunnable = new Runnable() {
        @Override
        public void run() {
            if (Neo4JRuntimesManager.INSTANCE.getRuntimes().isEmpty()) {
                boolean launch = MessageDialog.openQuestion(getDisplay().getActiveShell(), "Install Neo4J runtime?",
                        "No available Neo4J runtimes found. Launch the installation wizard?");
                if (launch) {
                    Neo4JRuntimesManager.INSTANCE.launchInstallRuntimesWizard();
                }
            }
        }
    };

    static {
        INSTANCE = new Neo4JRuntimesManager();
    }

    public List<INeo4jRuntime> getRuntimes() {
        if (installedRuntimes == null) {
            load();
        }
        return installedRuntimes;
    }

    /* (non-Javadoc)
     * @see fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.INeo4jRuntimesManager#checkRuntimes(boolean)
     */
    @Override
    public synchronized void checkRuntimes() {
        getDisplay().syncExec(checkRuntimeRunnable);
    }

    /* (non-Javadoc)
     * @see fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.internal.INeo4jRuntimesManager#getRuntime(java.lang.String)
     */
    @Override
    public INeo4jRuntime getRuntime(String id) {
        for (INeo4jRuntime runtime : getRuntimes()) {
            if (runtime.getId() != null && runtime.getId().equals(id)) {
                return runtime;
            }
        }
        return null;
    }

    /* (non-Javadoc)
     * @see fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.INeo4jRuntimesManager#uninstall(java.lang.String)
     */
    //   @Override
    public void uninstall(String id) throws IOException {
        INeo4jRuntime runtime = getRuntime(id);
        try {
            FileUtils.forceDelete(runtime.getPath().toFile());
        } catch (FileNotFoundException e) {
        }
        load();
    }

    /* (non-Javadoc)
     * @see fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.internal.INeo4jRuntimesManager#launchInstallRuntimesWizard()
     */
    //   @Override
    public void launchInstallRuntimesWizard() {
        final Display display = getDisplay();
        display.syncExec(new Runnable() {
            @Override
            public void run() {
                Shell shell = display.getActiveShell();
                ImportNeo4jRuntimeWizard wizard = new ImportNeo4jRuntimeWizard();
                WizardDialog dialog = new WizardDialog(shell, wizard);
                dialog.setTitle(wizard.getWindowTitle());
                dialog.setBlockOnOpen(true);
                dialog.open();
            }
        });
    }

    public List<AbstractNeo4jRuntimeInstaller> getInstallers() {
        if (installers == null) {
            installers = new ArrayList<AbstractNeo4jRuntimeInstaller>();
            IConfigurationElement[] elements = Platform.getExtensionRegistry()
                    .getConfigurationElementsFor(INSTALLERS_EXTENSION_POINT_ID);
            for (IConfigurationElement element : elements) {
                try {
                    AbstractNeo4jRuntimeInstaller installer = null;
                    if (element.getAttribute(ATT_HANDLER) != null) {
                        installer = (AbstractNeo4jRuntimeInstaller) element.createExecutableExtension(ATT_HANDLER);
                    } else {
                        Neo4jZippedInstaller zippedInstaller = new Neo4jZippedInstaller();
                        zippedInstaller.setId(element.getAttribute(ATT_ID));
                        zippedInstaller.setName(element.getAttribute(ATT_NAME));
                        zippedInstaller.setVersion(element.getAttribute(ATT_VERSION));
                        zippedInstaller.setDescription(element.getAttribute(ATT_DESCRIPTION));
                        zippedInstaller.setId(element.getAttribute(ATT_ID));
                        zippedInstaller.setUrl(new URL(element.getAttribute(ATT_URL)));
                        for (IConfigurationElement childElement : element.getChildren(CHILD_LICENSE)) {
                            zippedInstaller.setLicenseText(childElement.getValue());
                        }
                        for (IConfigurationElement childElement : element.getChildren(CHILD_ZIPENTRY)) {
                            zippedInstaller.getJarFiles().add(childElement.getAttribute(ATT_PATH));
                        }
                        installer = zippedInstaller;
                    }
                    installers.add(installer);
                } catch (CoreException | MalformedURLException | InvalidRegistryObjectException e) {
                    Logger.log(Logger.SEVERITY_ERROR, e);
                }
            }
        }
        return Collections.unmodifiableList(installers);
    }

    /* (non-Javadoc)
     * @see fr.inria.atlanmod.neo4emf.neo4jresolver.runtimes.INeo4jRuntimesManager#getInstaller(java.lang.String)
     */
    //   @Override
    public AbstractNeo4jRuntimeInstaller getInstaller(String id) {
        for (AbstractNeo4jRuntimeInstaller installer : getInstallers()) {
            if (StringUtils.equals(installer.getId(), id)) {
                return installer;
            }
        }
        return null;
    }

    private void load() {
        if (installedRuntimes == null) {
            installedRuntimes = new ObservableArrayList<INeo4jRuntime>();
        } else {
            installedRuntimes.clear();
        }
        File runtimeDataDir = getRuntimeDataArea().toFile();
        if (runtimeDataDir.isDirectory()) {
            for (File versionDir : runtimeDataDir.listFiles()) {
                if (versionDir.isDirectory()) {
                    for (File idDir : versionDir.listFiles()) {
                        INeo4jRuntime runtimeFromLocation = getRuntimeFromLocation(
                                new Path(idDir.getAbsolutePath()));
                        if (runtimeFromLocation != null) {
                            installedRuntimes.add(runtimeFromLocation);
                        }
                    }
                }
            }
        }
    }

    public IPath getRuntimeDataArea() {
        if (dataAreaPath == null) {
            dataAreaPath = Neo4jResolverPlugin.getDefault().getStateLocation().append(RUNTIMES_DIR);
        }
        return dataAreaPath;
    }

    public INeo4jRuntime getRuntimeFromLocation(IPath path) {
        INeo4jRuntime runtime = null;
        File manifestMF = path.append(META_INF).append(MANIFEST_MF).toFile();
        if (manifestMF.exists()) {
            FileInputStream stream = null;
            try {
                stream = new FileInputStream(manifestMF);
                Manifest manifest = new Manifest(stream);
                String id = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLIC_NAME);
                String version = manifest.getMainAttributes().getValue(BUNDLE_VERSION);
                runtime = new Neo4jRuntime(version, id, path);
            } catch (Exception e) {
                Logger.log(Logger.SEVERITY_ERROR, e);
            } finally {
                IOUtils.closeQuietly(stream);
            }
        }
        return runtime;
    }

    public void initializeRuntimeMetadata(AbstractNeo4jRuntimeInstaller installer, IPath path) {
        File dirFile = path.toFile();
        File manifestFile = path.append(META_INF).append(MANIFEST_MF).toFile();
        FileOutputStream outputStream = null;
        try {
            FileUtils.forceMkdir(manifestFile.getParentFile());
            outputStream = new FileOutputStream(manifestFile);
            Manifest manifest = new Manifest();
            Attributes atts = manifest.getMainAttributes();
            atts.put(Attributes.Name.MANIFEST_VERSION, "1.0");
            atts.putValue(BUNDLE_MANIFEST_VERSION, "2");
            atts.putValue(BUNDLE_NAME, installer.getName());
            atts.putValue(BUNDLE_SYMBOLIC_NAME, installer.getId());
            atts.putValue(BUNDLE_VERSION, installer.getVersion());
            atts.putValue(BUNDLE_CLASS_PATH, buildJarFilesList(dirFile));
            atts.putValue(EXPORT_PACKAGE, buildPackagesList(dirFile));
            manifest.write(outputStream);
            load();
        } catch (Exception e) {
            Logger.log(Logger.SEVERITY_ERROR, e);
        } finally {
            IOUtils.closeQuietly(outputStream);
        }
    }

    public void configureAsProjectPlugin(AbstractNeo4jRuntimeInstaller installer, IPath path) {
        File dirFile = path.toFile();
        File projectFile = path.append(PROJECT).toFile();
        Writer writer = null;
        try {
            FileUtils.forceMkdir(projectFile.getParentFile());
            writer = new FileWriter(projectFile);
            writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
            writer.write("<projectDescription>\n");
            writer.write("   <name>" + installer.getId() + "</name>\n");
            writer.write("   <comment></comment>\n");
            writer.write("   <projects>\n");
            writer.write("   </projects>\n");
            writer.write("   <buildSpec>\n");
            writer.write("      <buildCommand>\n");
            writer.write("         <name>org.eclipse.jdt.core.javabuilder</name>\n");
            writer.write("         <arguments>\n");
            writer.write("         </arguments>\n");
            writer.write("      </buildCommand>\n");
            writer.write("      <buildCommand>\n");
            writer.write("         <name>org.eclipse.pde.ManifestBuilder</name>\n");
            writer.write("         <arguments>\n");
            writer.write("         </arguments>\n");
            writer.write("      </buildCommand>\n");
            writer.write("      <buildCommand>\n");
            writer.write("         <name>org.eclipse.pde.SchemaBuilder</name>\n");
            writer.write("         <arguments>\n");
            writer.write("         </arguments>\n");
            writer.write("      </buildCommand>\n");
            writer.write("   </buildSpec>\n");
            writer.write("   <natures>\n");
            writer.write("      <nature>org.eclipse.pde.PluginNature</nature>\n");
            writer.write("      <nature>org.eclipse.jdt.core.javanature</nature>\n");
            writer.write("   </natures>\n");
            writer.write("</projectDescription>\n");
        } catch (Exception e) {
            Logger.log(Logger.SEVERITY_ERROR, e);
        } finally {
            IOUtils.closeQuietly(writer);
        }
        File classPathFile = path.append(CLASSPATH).toFile();
        try {
            FileUtils.forceMkdir(classPathFile.getParentFile());
            writer = new FileWriter(classPathFile);
            writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
            writer.write("<classpath>\n");
            writer.write("   <classpathentry kind=\"con\" path=\"org.eclipse.jdt.launching.JRE_CONTAINER\"/>\n");
            writer.write("   <classpathentry kind=\"con\" path=\"org.eclipse.pde.core.requiredPlugins\"/>\n");
            for (String jarFile : getJarFilesList(dirFile)) {
                writer.write("   <classpathentry exported=\"true\" kind=\"lib\" path=\"" + jarFile + "\"/>\n");
            }
            writer.write("</classpath>\n");
        } catch (Exception e) {
            Logger.log(Logger.SEVERITY_ERROR, e);
        } finally {
            IOUtils.closeQuietly(writer);
        }
        File buildPropertiesFile = path.append(BUILD_PROPERTIES).toFile();
        try {
            FileUtils.forceMkdir(buildPropertiesFile.getParentFile());
            writer = new FileWriter(buildPropertiesFile);
            writer.write("bin.includes = META-INF/,\\\n");
            writer.write("               .\n");
        } catch (Exception e) {
            Logger.log(Logger.SEVERITY_ERROR, e);
        } finally {
            IOUtils.closeQuietly(writer);
        }
    }

    private List<String> getJarFilesList(File directory) {
        List<String> files = new ArrayList<String>();
        for (File file : directory.listFiles(new JarFilter())) {
            files.add(file.getName());
        }
        return files;
    }

    private String buildJarFilesList(File directory) {
        final String SEPARATOR = ", ";
        StringBuilder builder = new StringBuilder();
        if (directory != null && directory.isDirectory()) {
            for (String fileName : getJarFilesList(directory)) {
                builder.append(fileName);
                builder.append(SEPARATOR);
            }
            if (builder.length() >= SEPARATOR.length()) {
                builder.setLength(builder.length() - SEPARATOR.length());
            }
            return builder.toString();
        } else {
            return null;
        }
    }

    private String buildPackagesList(File directory) {
        Set<String> packages = new HashSet<>();
        final String SEPARATOR = ", ";
        StringBuilder builder = new StringBuilder();
        if (directory != null && directory.isDirectory()) {
            for (File file : directory.listFiles(new JarFilter())) {
                ZipInputStream zipStream = null;
                try {
                    zipStream = new ZipInputStream(new FileInputStream(file));
                    ZipEntry entry;
                    while ((entry = zipStream.getNextEntry()) != null) {
                        if (FilenameUtils.getExtension(entry.getName()).equals("class")) {
                            packages.add(FilenameUtils.getPathNoEndSeparator(entry.getName()).replace('/', '.'));
                        }
                    }
                } catch (IOException e) {
                    Logger.log(Logger.SEVERITY_ERROR, e);
                } finally {
                    IOUtils.closeQuietly(zipStream);
                }
            }
            for (String pkg : packages) {
                builder.append(pkg);
                builder.append(SEPARATOR);
            }
            if (builder.length() >= SEPARATOR.length()) {
                builder.setLength(builder.length() - SEPARATOR.length());
            }
            return builder.toString();
        } else {
            return null;
        }
    }

    private Display getDisplay() {
        return Display.getCurrent() != null ? Display.getCurrent() : Display.getDefault();
    }
}