org.eclipse.jem.workbench.utility.JemProjectUtilities.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jem.workbench.utility.JemProjectUtilities.java

Source

/*******************************************************************************
 * Copyright (c) 2001, 2005 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jem.workbench.utility;
/*
 * $RCSfile: JemProjectUtilities.java,v $ $Revision: 1.15 $ $Date: 2011/03/30 21:01:20 $
 */

import java.net.URL;
import java.util.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;

import org.eclipse.jem.internal.plugin.JavaEMFNature;
import org.eclipse.jem.java.JavaClass;
import org.eclipse.jem.java.JavaRefFactory;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jem.util.emf.workbench.WorkbenchResourceHelperBase;
import org.eclipse.jem.util.emf.workbench.nature.EMFNature;
import org.eclipse.jem.util.plugin.JEMUtilPlugin;

/**
 * Project Utilities for JEM and Java.
 * 
 * @since 1.1.0
 */
public class JemProjectUtilities extends ProjectUtilities {

    private JemProjectUtilities() {
    }

    /**
     * The nature id for JEM Nature.
     * 
     * @since 1.1.0
     */
    public static final String JEM_EMF_NatureID = IJavaEMFNature.NATURE_ID;

    /**
     * Get the EMF nature for JEM for the project. 
     * @param project
     * @param addNature <code>true</code> if add the nature to the project if not set. <code>false</code> if don't add nature if not already on project.
     * @return the EMFNature or <code>null</code> if not found and addNature was <code>false</code> or it was not a java project.
     * @throws CoreException 
     * 
     * @since 1.1.0
     */
    public static EMFNature getJEM_EMF_Nature(IProject project, boolean addNature) throws CoreException {
        return addNature ? JavaEMFNature.createRuntime(project) : JavaEMFNature.getRuntime(project);
    }

    /**
     * Get the JavaClass from an IFile.
     * @param aFile
     * @return
     * 
     * @since 1.1.0
     */
    public static JavaClass getJavaClass(IFile aFile) {
        if (aFile == null)
            return null;
        IProject project = aFile.getProject();
        List folders = getSourceContainers(project);
        folders.addAll(getLibraryContainers(project));
        IContainer folder = null;
        IPath folderPath, filePath, javaPath;
        filePath = aFile.getProjectRelativePath();

        for (int i = 0; i < folders.size(); i++) {
            folder = (IContainer) folders.get(i);
            folderPath = folder.getProjectRelativePath();
            int segments = filePath.matchingFirstSegments(folderPath);
            if (segments > 0) {
                javaPath = filePath.removeFirstSegments(segments);
                javaPath = javaPath.removeFileExtension();
                String qualifiedName = javaPath.toString().replace('/', '.');
                return (JavaClass) JavaRefFactory.eINSTANCE.reflectType(qualifiedName,
                        WorkbenchResourceHelperBase.getResourceSet(project));
            }
        }

        return null;
    }

    /**
     * Get source containers for the project.
     * 
     * @param p
     *            project
     * @return list of source containers.
     * 
     * @since 1.0.0
     */
    public static List getSourceContainers(IProject p) {
        try {
            List sourceContainers = new ArrayList();
            List sourcePaths = getSourcePaths(p);
            if (sourcePaths != null && !sourcePaths.isEmpty()) {
                for (int i = 0; i < sourcePaths.size(); i++) {
                    IPath path = (IPath) sourcePaths.get(i);
                    if (path.isEmpty())
                        sourceContainers.add(p);
                    else
                        sourceContainers.add(p.getFolder(path));
                }
            }
            return sourceContainers;
        } catch (IllegalArgumentException ex) {
            return Collections.EMPTY_LIST;
        }
    }

    protected static List getSourcePaths(IProject p) {
        IJavaProject javaProj = getJavaProject(p);
        if (javaProj == null)
            return null;
        IClasspathEntry[] cp = null;
        try {
            cp = javaProj.getRawClasspath();
        } catch (JavaModelException ex) {
            JEMUtilPlugin.getLogger().logError(ex);
            return null;
        }
        List sourcePaths = new ArrayList();
        for (int i = 0; i < cp.length; i++) {
            if (cp[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
                sourcePaths.add(cp[i].getPath().removeFirstSegments(1));
            }
        }
        return sourcePaths;
    }

    /**
     * Return list of IContainers that are Libraries in the classpath.
     * 
     * @param p
     *            project
     * @return list of library IContainers.
     * 
     * @since 1.0.0
     */
    public static List getLibraryContainers(IProject p) {
        try {
            List libraryContainers = new ArrayList();
            List libraryPaths = getlibraryPaths(p);
            if (libraryPaths != null && !libraryPaths.isEmpty()) {
                for (int i = 0; i < libraryPaths.size(); i++) {
                    IPath path = (IPath) libraryPaths.get(i);
                    if (path.isEmpty())
                        libraryContainers.add(p);
                    else
                        libraryContainers.add(p.getFolder(path));
                }
            }
            return libraryContainers;
        } catch (IllegalArgumentException ex) {
            return Collections.EMPTY_LIST;
        }
    }

    protected static List getlibraryPaths(IProject p) {
        IJavaProject javaProj = getJavaProject(p);
        if (javaProj == null)
            return null;
        IClasspathEntry[] cp = null;
        try {
            cp = javaProj.getRawClasspath();
        } catch (JavaModelException ex) {
            JEMUtilPlugin.getLogger().logError(ex);
            return null;
        }
        List libraryPaths = new ArrayList();
        for (int i = 0; i < cp.length; i++) {
            if (cp[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
                libraryPaths.add(cp[i].getPath().removeFirstSegments(1));
            }
        }
        return libraryPaths;
    }

    /**
     * Get the java project nature for the given project.
     * 
     * @param p
     *            project
     * @return the java project nature for the project or <code>null</code> if not a java project.
     * 
     * @since 1.0.0
     */
    public static IJavaProject getJavaProject(IProject p) {
        if (p != null) {
            try {
                return (IJavaProject) p.getNature(JavaCore.NATURE_ID);
            } catch (CoreException ignore) {
                return null;
            }
        }
        return null;
    }

    /**
     * Touch classpath. It simply takes the classpath and sets it back in.
     * 
     * @param javaProject
     * @throws JavaModelException
     * 
     * @since 1.0.0
     */
    public static void updateClasspath(IJavaProject javaProject) throws JavaModelException {
        if (javaProject != null)
            javaProject.setRawClasspath(javaProject.getRawClasspath(), new NullProgressMonitor());
    }

    /**
     * Return the location of the binary output files for the JavaProject.
     * 
     * @param p
     *            project
     * @return path to binary output folder or <code>null</code> if not java project or other problem.
     * 
     * @since 1.0.0
     */
    public static IPath getJavaProjectOutputLocation(IProject p) {
        try {
            IJavaProject javaProj = getJavaProject(p);
            if (javaProj == null)
                return null;
            if (!javaProj.isOpen())
                javaProj.open(null);
            return javaProj.readOutputLocation();
        } catch (JavaModelException e) {
            return null;
        }
    }

    /**
     * Get the project's binary output container.
     * 
     * @param p
     *            project
     * @return project's output container or <code>null</code> if not java project or some other error.
     * 
     * @since 1.0.0
     */
    public static IContainer getJavaProjectOutputContainer(IProject p) {
        IPath path = getJavaProjectOutputLocation(p);
        if (path == null)
            return null;
        if (path.segmentCount() == 1)
            return p;
        return p.getFolder(path.removeFirstSegments(1));
    }

    /**
     * Get the binary output absolute (local file system) path.
     * 
     * @param p
     *            project
     * @return project's output path or <code>null</code> if not java project or some other error.
     * 
     * @since 1.0.0
     */
    public static IPath getJavaProjectOutputAbsoluteLocation(IProject p) {
        IContainer container = getJavaProjectOutputContainer(p);
        if (container != null)
            return container.getLocation();
        return null;
    }

    /**
     * Get the JDT JavaModel.
     * 
     * @return JDT's JavaModel
     * 
     * @since 1.0.0
     */
    public static IJavaModel getJavaModel() {
        return JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
    }

    /**
     * Get all source package fragment roots.
     * 
     * @param javaProj
     * @return source package fragment roots
     * @throws JavaModelException
     * 
     * @since 1.0.0
     */
    public static List getSourcePackageFragmentRoots(IJavaProject javaProj) throws JavaModelException {
        List result = new ArrayList();
        IPackageFragmentRoot[] roots = javaProj.getPackageFragmentRoots();
        for (int i = 0; i < roots.length; i++) {
            IPackageFragmentRoot root = roots[i];
            if (root.getKind() == IPackageFragmentRoot.K_SOURCE)
                result.add(root);
        }
        return result;
    }

    /**
     * Remove the resource from the classpath
     * 
     * @param p
     *            project
     * @param res
     *            resource
     * @throws JavaModelException
     * 
     * @since 1.0.0
     */
    public static void removeFromJavaClassPath(IProject p, IResource res) throws JavaModelException {
        IClasspathEntry entry = JavaCore.newLibraryEntry(res.getFullPath(), null, null);
        removeFromJavaClassPath(p, entry);
    }

    /**
     * Remove the path from the classpath
     * 
     * @param p
     *            project
     * @param path
     *            path to remove
     * @throws JavaModelException
     * 
     * @since 1.0.0
     */
    public static void removeFromJavaClassPath(IProject p, IPath path) throws JavaModelException {
        org.eclipse.core.resources.IFile f = p.getFile(path);
        removeFromJavaClassPath(p, f);
    }

    /**
     * Remove the classpath entry from the project's classpath.
     * 
     * @param p
     * @param entry
     * @throws JavaModelException
     * 
     * @since 1.0.0
     */
    public static void removeFromJavaClassPath(IProject p, IClasspathEntry entry) throws JavaModelException {
        IJavaProject javaProject = null;
        try {
            javaProject = (IJavaProject) p.getNature(JavaCore.NATURE_ID);
        } catch (CoreException ignore) {
        }
        if (javaProject != null) {
            IClasspathEntry[] classpath = javaProject.getRawClasspath();
            javaProject.setRawClasspath(primRemoveFromJavaClassPath(classpath, entry), new NullProgressMonitor());
        }
    }

    /**
     * Remove the list of entries from the classpath of the project.
     * 
     * @param p
     *            project
     * @param entries
     *            list of IClassPathEntry's
     * @throws JavaModelException
     * 
     * @since 1.0.0
     */
    public static void removeFromJavaClassPath(IProject p, List entries) throws JavaModelException {
        IJavaProject javaProject = null;
        try {
            javaProject = (IJavaProject) p.getNature(JavaCore.NATURE_ID);
        } catch (CoreException ignore) {
        }
        if (javaProject != null) {
            IClasspathEntry[] classpath = javaProject.getRawClasspath();
            javaProject.setRawClasspath(primRemoveFromJavaClassPath(classpath, entries), new NullProgressMonitor());
        }
    }

    protected static IClasspathEntry[] primRemoveFromJavaClassPath(IClasspathEntry[] classpath,
            IClasspathEntry entry) throws JavaModelException {
        List result = new ArrayList();
        boolean didRemove = false;
        for (int i = 0; i < classpath.length; i++) {
            IClasspathEntry cpEntry = classpath[i];
            if (!entry.getPath().equals(classpath[i].getPath()))
                result.add(cpEntry);
            else
                didRemove = true;
        }
        if (!didRemove)
            return classpath;
        return (IClasspathEntry[]) result.toArray(new IClasspathEntry[result.size()]);
    }

    protected static IClasspathEntry[] primRemoveFromJavaClassPath(IClasspathEntry[] classpath, List entries)
            throws JavaModelException {
        List arrayList = Arrays.asList(classpath);
        List removeable = new ArrayList(arrayList);
        IClasspathEntry entry;
        boolean didRemove = false;
        int size = entries.size();
        for (int i = 0; i < size; i++) {
            entry = (IClasspathEntry) entries.get(i);
            for (int j = 0; j < classpath.length; j++) {
                IClasspathEntry cpEntry = classpath[j];
                if (entry.getPath().equals(classpath[j].getPath())) {
                    if (removeable.remove(cpEntry))
                        didRemove = true;
                }
            }
        }
        if (!didRemove)
            return classpath;
        return (IClasspathEntry[]) removeable.toArray(new IClasspathEntry[removeable.size()]);
    }

    /**
     * Get the classpath as an array or URL's.
     * 
     * @param javaProject
     * @return array of URL's or <code>null</code> if javaProject was <code>null</code>.
     * 
     * @since 1.0.0
     */
    public static URL[] getClasspathAsURLArray(IJavaProject javaProject) {
        if (javaProject == null)
            return null;
        Set visited = new HashSet();
        List urls = new ArrayList(20);
        collectClasspathURLs(javaProject, urls, visited, true);
        URL[] result = new URL[urls.size()];
        urls.toArray(result);
        return result;
    }

    private static void collectClasspathURLs(IJavaProject javaProject, List urls, Set visited,
            boolean isFirstProject) {
        if (visited.contains(javaProject))
            return;
        visited.add(javaProject);
        IPath outPath = getJavaProjectOutputAbsoluteLocation(javaProject.getProject());
        outPath = outPath.addTrailingSeparator();
        URL out = ProjectUtilities.createFileURL(outPath);
        urls.add(out);
        IClasspathEntry[] entries = null;
        try {
            entries = javaProject.getResolvedClasspath(true);
        } catch (JavaModelException e) {
            return;
        }
        IClasspathEntry entry;
        for (int i = 0; i < entries.length; i++) {
            entry = entries[i];
            switch (entry.getEntryKind()) {
            case IClasspathEntry.CPE_LIBRARY:
            case IClasspathEntry.CPE_CONTAINER:
            case IClasspathEntry.CPE_VARIABLE:
                collectClasspathEntryURL(entry, urls);
                break;
            case IClasspathEntry.CPE_PROJECT: {
                if (isFirstProject || entry.isExported())
                    collectClasspathURLs(getJavaProject(entry), urls, visited, false);
                break;
            }
            }
        }
    }

    private static void collectClasspathEntryURL(IClasspathEntry entry, List urls) {
        IPath path = entry.getPath();
        if (null == path.getDevice()) {
            // workspace resource - is the IPath a file, folder, or a class folder whose location is the project root?
            if (path.segmentCount() == 1) {
                // It's a class folder whose location is the project root
                path = ResourcesPlugin.getWorkspace().getRoot().getProject(path.lastSegment()).getLocation();
            } else {
                // It's a file or folder - capture it's absolute location
                IFile jarFile = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
                if (jarFile.exists()) {
                    path = jarFile.getLocation();
                }
            }
        }

        URL url = ProjectUtilities.createFileURL(path);
        if (url != null)
            urls.add(url);
    }

    private static IJavaProject getJavaProject(IClasspathEntry entry) {
        IProject proj = ResourcesPlugin.getWorkspace().getRoot().getProject(entry.getPath().segment(0));
        if (proj != null)
            return getJavaProject(proj);
        return null;
    }

    /**
     * Is this project a binary project.
     * <p>
     * Typically a Java project is considered binary if it does not have a source entry in the classpath.
     * 
     * @param project
     *            Project to test
     * @return <code>true</code> if project is a binary project.
     */
    public static boolean isBinaryProject(IProject aProject) {

        IJavaProject javaProj = getJavaProject(aProject);
        if (javaProj == null)
            return false;
        IClasspathEntry[] entries = null;
        entries = javaProj.readRawClasspath();
        for (int i = 0; i < entries.length; i++) {
            IClasspathEntry entry = entries[i];
            if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE)
                return false;
        }
        return true;
    }

    /**
     * Append to java class path.
     * <p>
     * Append a list of IClasspathEntry's to the build path of the passed project. Updated to remove existing occurrences of the passed entries before
     * appending.
     * </p>
     * 
     * @param p
     *            project
     * @param appendClasspathEntries
     *            list of entries
     * @throws JavaModelException
     * 
     * @since 1.0.0
     */
    public static void appendJavaClassPath(IProject p, List appendClasspathEntries) throws JavaModelException {
        IJavaProject javaProject = null;
        try {
            javaProject = (IJavaProject) p.getNature(JavaCore.NATURE_ID);
        } catch (CoreException ignore) {
        }
        if (javaProject != null) {
            IClasspathEntry[] classpath = javaProject.getRawClasspath();
            List newPathList = new ArrayList(classpath.length);
            for (int i = 0; i < classpath.length; i++) {
                IClasspathEntry entry = classpath[i];
                // Skip entries which are in the append list
                if (appendClasspathEntries.indexOf(entry) < 0)
                    newPathList.add(entry);
            }
            newPathList.addAll(appendClasspathEntries);
            IClasspathEntry[] newClasspath = (IClasspathEntry[]) newPathList
                    .toArray(new IClasspathEntry[newPathList.size()]);
            javaProject.setRawClasspath(newClasspath, new NullProgressMonitor());
        }
    }

    /**
     * Append classpath entry.
     * <p>
     * Append one IClasspathEntry to the build path of the passed project. If a classpath entry having the same path as the parameter already exists,
     * then does nothing.
     * </p>
     * 
     * @param p
     *            Project
     * @param newEntry
     *            Entry
     * @throws JavaModelException
     * 
     * @since 1.0.0
     */
    public static void appendJavaClassPath(IProject p, IClasspathEntry newEntry) throws JavaModelException {
        IJavaProject javaProject = getJavaProject(p);
        if (javaProject == null)
            return;
        IClasspathEntry[] classpath = javaProject.getRawClasspath();
        List newPathList = new ArrayList(classpath.length);
        for (int i = 0; i < classpath.length; i++) {
            IClasspathEntry entry = classpath[i];
            // fix dup class path entry for .JETEmitter project
            // Skip the entry to be added if it already exists
            if (Platform.getOS().equals(Platform.OS_WIN32)) {
                if (!entry.getPath().toString().equalsIgnoreCase(newEntry.getPath().toString()))
                    newPathList.add(entry);
                else
                    return;
            } else {
                if (!entry.getPath().equals(newEntry.getPath()))
                    newPathList.add(entry);
                else
                    return;
            }
        }
        newPathList.add(newEntry);
        IClasspathEntry[] newClasspath = (IClasspathEntry[]) newPathList
                .toArray(new IClasspathEntry[newPathList.size()]);
        javaProject.setRawClasspath(newClasspath, new NullProgressMonitor());
    }

    /**
     * Return the source path matching the parameter; if the parameter is null, or if the source folder is not on the classpath, return the first
     * source path on the classpath
     * 
     * @param p
     *            project
     * @param defaultSourceName
     *            source folder to find if on classpath, or if <code>null</code> the first folder
     * @return path searched for or <code>null</code> if not java project or some other problem.
     * 
     * @since 1.0.0
     */
    public static IPath getSourcePathOrFirst(IProject p, String defaultSourceName) {
        IJavaProject javaProj = getJavaProject(p);
        if (javaProj == null)
            return null;
        IClasspathEntry[] cp = null;
        try {
            cp = javaProj.getRawClasspath();
        } catch (JavaModelException ex) {
            JEMUtilPlugin.getLogger().logError(ex);
            return null;
        }
        IClasspathEntry firstSource = null;
        IPath defaultSourcePath = null;
        if (defaultSourceName != null)
            defaultSourcePath = ProjectUtilities.createPath(p, defaultSourceName);
        for (int i = 0; i < cp.length; i++) {
            if (cp[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
                if (firstSource == null) {
                    firstSource = cp[i];
                    if (defaultSourcePath == null)
                        break;
                }
                if (cp[i].getPath().equals(defaultSourcePath))
                    return defaultSourcePath.removeFirstSegments(1);
            }
        }
        if (firstSource == null)
            return null;
        if (firstSource.getPath().segment(0).equals(p.getName()))
            return firstSource.getPath().removeFirstSegments(1);
        return null;
    }

    /**
     * Hack to force a reload of the .classpath file
     * 
     * @param project
     *            project to reload
     * @since 1.0.0
     */
    public static void forceClasspathReload(IProject project) throws JavaModelException {
        IJavaProject javaProj = getJavaProject(project);
        if (javaProj != null) {
            IClasspathEntry[] entries = javaProj.readRawClasspath();
            if (entries != null) {
                IPath output = javaProj.readOutputLocation();
                if (output != null)
                    javaProj.setRawClasspath(entries, output, null);
            }
        }
    }

    /**
     * Get the paths of all of the local jars in the classpath for the project. It does not recurse into referenced projects.
     * 
     * @param proj
     *            project to search (should be a java project).
     * @return A list of IPath, where each entry is a project relative path to a JAR contained in the project.
     */
    public static List getLocalJARPathsFromClasspath(IProject proj) {
        IJavaProject javaProj = getJavaProject(proj);
        if (javaProj == null)
            return null;
        IPath projectPath = proj.getFullPath();
        List result = new ArrayList();
        IClasspathEntry[] entries = javaProj.readRawClasspath();
        for (int i = 0; i < entries.length; i++) {
            IClasspathEntry entry = entries[i];
            if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
                IPath path = entry.getPath();
                int segments = path.matchingFirstSegments(projectPath);
                if (segments > 0)
                    result.add(path.removeFirstSegments(segments));
            }
        }
        return result;
    }

    /**
     * Return the source folder matching the parameter; if the parameter is null, or if the source folder is not on the classpath, return the first
     * source folder on the classpath
     * 
     * @param p
     *            project
     * @param defaultSourceName
     *            source folder to find if on classpath, or if <code>null</code> the first folder
     * @return container searched for or <code>null</code> if not java project or some other problem.
     * 
     * @since 1.0.0
     */
    public static IContainer getSourceFolderOrFirst(IProject p, String defaultSourceName) {
        try {
            IPath sourcePath = getSourcePathOrFirst(p, defaultSourceName);
            if (sourcePath == null)
                return null;
            else if (sourcePath.isEmpty())
                return p;
            else
                return p.getFolder(sourcePath);
        } catch (IllegalArgumentException ex) {
            return null;
        }
    }

    /**
     * Returns a list of IFolder that represents each source folder in a java project
     * 
     * @deprecated Use {@link #getSourceContainers(IProject)}because the project itself might be a source container
     * 
     * @param p
     *            project
     * @return
     * 
     * @since 1.0.0
     */
    public static List getSourceFolders(IProject p) {
        try {
            List sourceFolders = new ArrayList();
            List sourcePaths = getSourcePaths(p);
            if (sourcePaths != null && !sourcePaths.isEmpty()) {
                for (int i = 0; i < sourcePaths.size(); i++) {
                    IPath path = (IPath) sourcePaths.get(i);
                    if (!path.isEmpty())
                        sourceFolders.add(p.getFolder(path));
                }
            }
            return sourceFolders;
        } catch (IllegalArgumentException ex) {
            return Collections.EMPTY_LIST;
        }
    }
}