org.nuxeo.ide.sdk.java.ClasspathEditor.java Source code

Java tutorial

Introduction

Here is the source code for org.nuxeo.ide.sdk.java.ClasspathEditor.java

Source

/*
 * (C) Copyright 2006-2013 Nuxeo SAS (http://nuxeo.com/) and contributors.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * Contributors:
 *     slacoin
 *     Vladimir Pasquier <vpasquier@nuxeo.com>
 *     Sun Seng David TAN <stan@nuxeo.com>
 */
package org.nuxeo.ide.sdk.java;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.jar.JarFile;

import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.nuxeo.ide.common.JarUtils;
import org.nuxeo.ide.common.UI;
import org.nuxeo.ide.sdk.NuxeoSDK;
import org.nuxeo.ide.sdk.model.M2PomModelProvider;
import org.nuxeo.ide.sdk.model.PomModel;
import org.nuxeo.ide.sdk.userlibs.UserLib;
import org.nuxeo.ide.sdk.userlibs.UserLibPreferences;
import org.osgi.service.prefs.BackingStoreException;

/**
 *
 * @author matic
 * @since 1.1
 */
public class ClasspathEditor {

    public ClasspathEditor(IProject project) throws JavaModelException {
        this.project = project;
        java = JavaCore.create(project);
        entries.addAll(Arrays.asList(java.getRawClasspath()));
    }

    protected final IJavaProject java;

    protected final IProject project;

    protected final List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>();

    boolean dirty = false;

    /**
     * Extends classpath target project with src folder
     *
     * @param name
     * @throws JavaModelException
     */
    public void extendClasspath(String name) throws JavaModelException {
        IProject project = java.getProject();
        IFolder folder = project.getFolder("src/main/" + name);
        IPackageFragmentRoot root = java.getPackageFragmentRoot(folder);
        if (root.exists()) {
            IClasspathEntry entry = root.getRawClasspathEntry();
            if (entry.getOutputLocation() != null) {
                return;
            }
            entries.remove(entry);
        }
        // extend project class path
        IFolder binFolder = project.getFolder("bin/" + name);
        IClasspathEntry newEntry = JavaCore.newSourceEntry(folder.getFullPath(), new IPath[0], new IPath[0],
                binFolder.getFullPath());
        entries.add(newEntry);
        dirty = true;
    }

    /**
     * Adding containers to the project classpath
     *
     * @param containers
     * @throws JavaModelException
     */
    public void addContainers(String[] containers) throws JavaModelException {
        for (String container : containers) {
            IClasspathEntry classPathEntry = JavaCore.newContainerEntry(new Path(container), new IAccessRule[0],
                    null, false);
            entries.add(classPathEntry);
        }
        dirty = true;
    }

    public void addLibrary(IPath path) {
        IClasspathEntry newEntry = JavaCore.newLibraryEntry(path, null, null);
        entries.add(newEntry);
        dirty = true;
    }

    public void removeLibrary(Path path) {
        Iterator<IClasspathEntry> it = entries.iterator();
        while (it.hasNext()) {
            IClasspathEntry entry = it.next();
            if (path.equals(entry.getPath())) {
                it.remove();
                dirty = true;
            }
        }
    }

    public void removeLibraries() {
        Iterator<IClasspathEntry> it = entries.iterator();
        while (it.hasNext()) {
            IClasspathEntry entry = it.next();
            switch (entry.getEntryKind()) {
            case IClasspathEntry.CPE_LIBRARY:
            case IClasspathEntry.CPE_VARIABLE:
                it.remove();
                dirty = true;
            }
        }
    }

    public void flush() throws JavaModelException {
        if (!dirty) {
            return;
        }
        java.setRawClasspath(entries.toArray(new IClasspathEntry[entries.size()]), null);
        dirty = false;
    }

    /**
     * Removing containers to the project classpath
     *
     * @param containers
     * @throws JavaModelException
     */
    public void removeContainers(String[] containers) {
        for (String container : containers) {
            IClasspathEntry classPathEntry = JavaCore.newContainerEntry(new Path(container), new IAccessRule[0],
                    null, false);
            entries.remove(classPathEntry);
        }
        dirty = true;
    }

    protected String artifactKey(IClasspathEntry entry) throws Exception {
        IPath jarPath = JavaCore.getResolvedClasspathEntry(entry).getPath();
        IPath pomPath = jarPath.removeFileExtension().addFileExtension("pom");
        File pomFile = pomPath.toFile();
        if (!pomFile.exists()) {
            pomFile = JarUtils.getPom(jarPath.toFile());
        }
        PomModel pomModel = new PomModel(pomFile);
        return pomModel.getGroupId() + ":" + pomModel.getArtifactId();
    }

    protected String artifactKey(String gav) {
        int twoDotIndex = 0;
        for (int i = 0; i < 2; i++) {
            twoDotIndex = gav.indexOf(':', twoDotIndex + 1);
        }
        return gav.substring(0, twoDotIndex);
    }

    /**
     * Removing classpath entries that are in already in the containers. This
     * method is intended to be called after a mvn eclipse:eclipse
     */
    protected void removeDuplicates() {

        // classpath index
        Map<String, IClasspathEntry> cpIndex = new HashMap<String, IClasspathEntry>();
        List<IClasspathEntry> duplicateEntries = new ArrayList<IClasspathEntry>();
        for (IClasspathEntry each : entries) {
            if (each.getEntryKind() != IClasspathEntry.CPE_VARIABLE) {
                continue;
            }
            String key;
            try {
                key = artifactKey(each);
            } catch (Exception cause) {
                UI.showWarning("cannot compute artifact key for " + each + ", skipping");
                continue;
            }
            if (cpIndex.containsKey(key)) {
                UI.showWarning("classpath contains duplicate entries for " + key + ", keeping last " + each);
                duplicateEntries.add(each);
                continue;
            }
            cpIndex.put(key, each);
        }
        entries.removeAll(duplicateEntries);

        // sdk index
        Collection<String> sdkIndex = new ArrayList<String>();
        sdkIndex.addAll(NuxeoSDK.getDefault().getArtifactIndex().getIndex().values());
        sdkIndex.addAll(NuxeoSDK.getDefault().getTestArtifactIndex().getIndex().values());

        // cleanup
        for (String each : sdkIndex) {
            String key = artifactKey(each);
            if (cpIndex.containsKey(key)) {
                IClasspathEntry entry = cpIndex.get(key);
                entries.remove(entry);
                dirty = true;
            }
        }
    }

    /**
     * Check into the classpath entries and add all as a NuxeoSDK UserLib (can
     * be deployed in the sdk)
     *
     */
    public void setLibsAsSdkUserLibs() throws CoreException, BackingStoreException {
        removeDuplicates();
        UserLibPreferences prefs = UserLibPreferences.load();
        ArrayList<IClasspathEntry> entriesToRemove = new ArrayList<IClasspathEntry>();
        for (IClasspathEntry iClasspathEntry : entries) {
            String path = JavaCore.getResolvedClasspathEntry(iClasspathEntry).getPath().toString();
            File file = new File(path);
            // a userlib is normally a jar file, right ?
            if (path.endsWith(".jar")) {
                UserLib lib = new UserLib(file.getAbsolutePath());
                M2PomModelProvider m2PomModelProvider = new M2PomModelProvider(path);
                try {
                    PomModel model = m2PomModelProvider.getPomModel();
                    if (model != null) {
                        lib.setGroupId(model.getGroupId());
                        lib.setArtifactId(model.getArtifactId());
                        lib.setVersion(model.getArtifactVersion());
                    }
                } catch (Exception e) {
                    UI.showError("Failed to parse associated pom", e);
                }
                prefs.addUserLib(lib);
                // removing from the classpath entries to avoid duplicated
                // entries
                entriesToRemove.add(iClasspathEntry);
            }
        }
        // in 2 steps to avoid concurent access to entries
        for (IClasspathEntry iClasspathEntry : entriesToRemove) {
            entries.remove(iClasspathEntry);
            dirty = true;
        }

        if (prefs.isModified()) {
            prefs.save();
            NuxeoSDK.reloadSDKClasspathContainer();
        }

    }

}