net.officefloor.eclipse.classpath.ClasspathUtil.java Source code

Java tutorial

Introduction

Here is the source code for net.officefloor.eclipse.classpath.ClasspathUtil.java

Source

/*
 * OfficeFloor - http://www.officefloor.net
 * Copyright (C) 2005-2013 Daniel Sagenschneider
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.officefloor.eclipse.classpath;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJarEntryResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.ide.IDE;

import net.officefloor.eclipse.common.editor.AbstractOfficeFloorEditor;
import net.officefloor.eclipse.repository.project.ProjectConfigurationContext;

/**
 * Utility methods for working with class path.
 * 
 * @author Daniel Sagenschneider
 */
public class ClasspathUtil {

    /**
     * Loads the {@link Class} from the {@link IProject} class path.
     * 
     * @param project
     *            {@link IProject}.
     * @param className
     *            Class name.
     * @return {@link Class}.
     * @throws ClassNotFoundException
     *             If {@link Class} not found.
     */
    public static Class<?> loadProjectClass(IProject project, String className) throws ClassNotFoundException {

        // Obtain via project class loader
        ProjectClassLoader classLoader = ProjectClassLoader.create(project);
        Class<?> clazz = classLoader.loadClass(className);

        // Return the class
        return clazz;
    }

    /**
     * Loads the {@link Class} from the plug-in class path.
     * 
     * @param className
     *            Class name.
     * @return {@link Class}.
     * @throws ClassNotFoundException
     *             If {@link Class} not found.
     */
    public static Class<?> loadPluginClass(String className) throws ClassNotFoundException {
        return Thread.currentThread().getContextClassLoader().loadClass(className);
    }

    /**
     * Obtains the {@link IClasspathEntry} of the input variable and path.
     * 
     * @param variable
     *            Name of variable.
     * @param path
     *            Path from variable.
     * @return {@link IClasspathEntry} for the variable or <code>null</code> if
     *         fails to create.
     */
    public static IClasspathEntry createClasspathEntry(String variable, String path) {

        // Create the path
        IPath variablePath = new Path(variable).append(path);

        // Return the variable class path entry
        return JavaCore.newVariableEntry(variablePath, null, null);
    }

    /**
     * Opens the class path resource.
     * 
     * @param resourcePath
     *            Path to the resource on the class path.
     * @param editor
     *            {@link AbstractOfficeFloorEditor} opening the resource.
     */
    public static void openClasspathResource(String resourcePath, AbstractOfficeFloorEditor<?, ?> editor) {

        // Extensions
        final String CLASS_EXTENSION = ".class";
        final String SOURCE_EXTENSION = ".java";

        try {
            // Obtain the package and resource name
            int index = resourcePath.lastIndexOf('/');
            String packageName = (index < 0 ? "" : resourcePath.substring(0, index)).replace('/', '.');
            String resourceName = (index < 0 ? resourcePath : resourcePath.substring(index + 1)); // +1
            // to
            // skip
            // separator

            // Obtain the java project
            IJavaProject project = JavaCore.create(ProjectConfigurationContext.getProject(editor.getEditorInput()));

            // Iterate over the fragment roots searching for the file
            for (IPackageFragmentRoot root : project.getAllPackageFragmentRoots()) {

                // Attempt to obtain the package
                IPackageFragment packageFragment = root.getPackageFragment(packageName);
                if (!packageFragment.exists()) {
                    continue; // must have package
                }

                // Handle if a java or class file
                if (JavaCore.isJavaLikeFileName(resourceName) || resourceName.endsWith(CLASS_EXTENSION)) {

                    // Handle based on kind of fragment root
                    int rootKind = root.getKind();
                    switch (rootKind) {
                    case IPackageFragmentRoot.K_BINARY:
                        // Binary, so ensure extension is class
                        if (resourceName.endsWith(SOURCE_EXTENSION)) {
                            resourceName = resourceName.replace(SOURCE_EXTENSION, CLASS_EXTENSION);
                        }

                        // Attempt to obtain and open the class file
                        IClassFile classFile = packageFragment.getClassFile(resourceName);
                        if (classFile != null) {
                            openEditor(editor, classFile);
                            return; // opened
                        }
                        break;

                    case IPackageFragmentRoot.K_SOURCE:
                        // Source, so ensure extension is java
                        if (resourceName.endsWith(CLASS_EXTENSION)) {
                            resourceName = resourceName.replace(CLASS_EXTENSION, SOURCE_EXTENSION);
                        }

                        // Attempt to obtain the compilation unit (source file)
                        ICompilationUnit sourceFile = packageFragment.getCompilationUnit(resourceName);
                        if (sourceFile != null) {
                            openEditor(editor, sourceFile);
                            return; // opened
                        }
                        break;

                    default:
                        throw new IllegalStateException("Unknown package fragment root kind: " + rootKind);
                    }

                } else {
                    // Not java file, so open as resource
                    for (Object nonJavaResource : packageFragment.getNonJavaResources()) {
                        // Should only be opening files
                        if (nonJavaResource instanceof IFile) {
                            IFile file = (IFile) nonJavaResource;

                            // Determine if the file looking for
                            if (resourceName.equals(file.getName())) {
                                // Found file to open, so open
                                openEditor(editor, file);
                                return;
                            }
                        } else {
                            // Unknown resource type
                            throw new IllegalStateException(
                                    "Unkown resource type: " + nonJavaResource.getClass().getName());
                        }
                    }
                }
            }

            // Unable to open as could not find
            MessageDialog.openWarning(editor.getEditorSite().getShell(), "Open", "Could not find: " + resourcePath);

        } catch (Throwable ex) {
            // Failed to open file
            MessageDialog.openInformation(editor.getEditorSite().getShell(), "Open",
                    "Failed to open '" + resourcePath + "': " + ex.getMessage());
        }
    }

    /**
     * Opens the editor for the {@link IFile}.
     * 
     * @param editor
     *            {@link AbstractOfficeFloorEditor} requiring to open the
     *            {@link IFile}.
     * @param file
     *            {@link IFile} to open.
     */
    public static void openEditor(AbstractOfficeFloorEditor<?, ?> editor, IFile file) {
        try {

            // Open the file
            IDE.openEditor(editor.getEditorSite().getPage(), file);

        } catch (Throwable ex) {
            // Failed to open file
            MessageDialog.openInformation(editor.getEditorSite().getShell(), "Open",
                    "Failed to open '" + file.getFullPath().toString() + "': " + ex.getMessage());
        }
    }

    /**
     * Opens the editor for the {@link IJavaElement}.
     * 
     * @param editor
     *            {@link AbstractOfficeFloorEditor} requiring to open the
     *            {@link IFile}.
     * @param element
     *            {@link IEditorInput} to open.
     */
    private static void openEditor(AbstractOfficeFloorEditor<?, ?> editor, IJavaElement element) {
        try {

            // Open the java element
            JavaUI.openInEditor(element);

        } catch (Throwable ex) {
            // Failed to open file
            MessageDialog.openInformation(editor.getEditorSite().getShell(), "Open",
                    "Failed to open '" + element.getElementName() + "': " + ex.getMessage());
        }
    }

    /**
     * Obtains the class name of the input {@link IJavaElement}.
     * 
     * @param javaElement
     *            {@link IJavaElement}.
     * @return Class name or <code>null</code> if {@link IJavaElement} not a
     *         class or contained within a class.
     */
    public static String getClassName(IJavaElement javaElement) {

        // Find the type
        IType type;
        if (javaElement instanceof IType) {
            type = (IType) javaElement;
        } else if (javaElement instanceof IClassFile) {
            type = ((IClassFile) javaElement).getType();
        } else if (javaElement instanceof ICompilationUnit) {
            ICompilationUnit unit = (ICompilationUnit) javaElement;

            // Strip extension from name
            String name = javaElement.getElementName().split("\\.")[0];

            // Obtain the type
            type = unit.getType(name);
        } else {
            // Look upwards for type
            type = (IType) javaElement.getAncestor(IJavaElement.TYPE);
        }

        // Ensure have type
        if (type == null) {
            return null;
        }

        // Determine the fully qualified name
        return type.getFullyQualifiedName();
    }

    /**
     * Obtains the location on the class path for the input full path.
     * 
     * @param fullPath
     *            Full path.
     * @return Location on the class path for the input full path.
     */
    public static String getClassPathLocation(String fullPath) {
        return getClassPathLocation(new Path(fullPath));
    }

    /**
     * Obtains the location on the class path for the input {@link IPath}.
     * 
     * @param path
     *            {@link IPath}.
     * @return Location on the class path for the input {@link IPath}.
     */
    public static String getClassPathLocation(IPath path) {

        // Obtain the resource for the path
        IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
        IResource pathResource = workspaceRoot.findMember(path);
        IResource resource = pathResource;

        // Obtain the java element
        IJavaElement javaElement = null;
        do {

            // Ensure have the resource
            if (resource == null) {
                // Did not find java element for resource
                return null;
            }

            // Obtain the java element from the resource
            javaElement = JavaCore.create(resource);

            // Obtain the parent resource
            resource = resource.getParent();

        } while (javaElement == null);

        // Obtain the package fragment root for the java element
        IPackageFragmentRoot fragmentRoot = null;
        do {

            // Determine if package fragment root
            if (javaElement instanceof IPackageFragmentRoot) {
                fragmentRoot = (IPackageFragmentRoot) javaElement;
            }

            // Obtain the parent java element
            javaElement = javaElement.getParent();

        } while ((fragmentRoot == null) && (javaElement != null));

        // Determine if have fragment root
        if (fragmentRoot == null) {
            // Return path as is
            return path.toString();
        }

        // Obtain the fragment root full path
        String fragmentPath = fragmentRoot.getResource().getFullPath().toString() + "/";

        // Obtain the class path location (by removing fragment root path)
        String fullPath = pathResource.getFullPath().toString();
        String location = fullPath.substring(fragmentPath.length());

        // Return the location
        return location;
    }

    /**
     * Obtains the descendants of the input item.
     * 
     * @param item
     *            Item.
     * @return Descendants of the item.
     */
    // TODO remove as use StandardJavaElementContentProvider
    @Deprecated
    public static Object[] getDescendants(Object item) {
        List<Object> descendants = new LinkedList<Object>();
        loadDescendants(item, descendants);
        return descendants.toArray();
    }

    /**
     * Loads the descendants of the input item.
     * 
     * @param item
     *            Item.
     * @param descendants
     *            Listing to add descendants.
     */
    public static void loadDescendants(Object item, List<Object> descendants) {
        // Load the children
        for (Object child : getChildren(item)) {

            // Add the child
            descendants.add(child);

            // Load the grand children
            loadDescendants(child, descendants);
        }
    }

    /**
     * Obtains the children of the input parent.
     * 
     * @param parent
     *            Parent.
     * @return Children.
     */
    // TODO remove as use StandardJavaElementContentProvider
    public static Object[] getChildren(Object parent) {

        // No children for null
        if (parent == null) {
            return new Object[0];
        }

        // Return children based on type
        if (parent instanceof IResource) {
            IResource resource = (IResource) parent;
            return getChildren(resource);

        } else if (parent instanceof IJavaElement) {
            IJavaElement javaElement = (IJavaElement) parent;
            return getChildren(javaElement);

        } else if (parent instanceof IJarEntryResource) {
            IJarEntryResource jarEntryResource = (IJarEntryResource) parent;
            return getChildren(jarEntryResource);

        } else {
            // Unhandled type
            MessageDialog.openWarning(null, "Unknown", "Unhandled parent type " + parent.getClass().getName());
            return new Object[0];
        }
    }

    /**
     * Obtains the children of the {@link IResource}.
     * 
     * @param resource
     *            {@link IResource}.
     * @return Children.
     */
    public static Object[] getChildren(IResource resource) {
        try {
            // Handle based on type of resource
            if (resource instanceof IWorkspaceRoot) {
                IWorkspaceRoot workspaceRoot = (IWorkspaceRoot) resource;

                // Return the open projects of the workspace
                List<Object> projects = new LinkedList<Object>();
                for (IProject project : workspaceRoot.getProjects()) {
                    if (project.isOpen()) {
                        // Obtain the specific project
                        Object specificProject = getSpecificProject(project);
                        projects.add(specificProject);
                    }
                }
                return projects.toArray();

            } else if (resource instanceof IProject) {
                IProject project = (IProject) resource;

                // Obtain the specific project
                Object specificProject = getSpecificProject(project);

                // Return children if only a java project
                if (!(specificProject instanceof IJavaProject)) {
                    // Not java project so no class path children
                    return new Object[0];
                }
                IJavaProject javaProject = (IJavaProject) specificProject;

                // Return the children of the java project
                return getChildren(javaProject);

            } else if (resource instanceof IFolder) {
                IFolder folder = (IFolder) resource;

                // Return the sub folders and files of folder
                return folder.members();

            } else if (resource instanceof IFile) {

                // No children of file
                return new Object[0];

            } else {
                // Unhandled resource
                MessageDialog.openWarning(null, "Unhandled resource type",
                        "Unhandled resource type " + resource.getClass().getName());
                return new Object[0];
            }

        } catch (CoreException ex) {
            MessageDialog.openError(null, "Error", ex.getMessage());
            return new Object[0];
        }
    }

    /**
     * Obtains the children of the {@link IJavaElement}.
     * 
     * @param javaElement
     *            {@link IJavaElement}.
     * @return Children.
     */
    public static Object[] getChildren(IJavaElement javaElement) {
        try {
            // Children to return
            List<Object> children = new LinkedList<Object>();

            // Handle based on type of java element
            if (javaElement instanceof IJavaProject) {
                IJavaProject javaProject = (IJavaProject) javaElement;

                // Add the package fragment roots on the class path
                IClasspathEntry[] classPath = javaProject.getResolvedClasspath(true);
                for (IClasspathEntry entry : classPath) {
                    // Obtain the Package Fragment Root of the class path entry
                    IPath entryPath = entry.getPath();
                    IPackageFragmentRoot fragmentRoot = javaProject.findPackageFragmentRoot(entryPath);

                    // Add the package fragment root
                    children.add(fragmentRoot);
                }

            } else if (javaElement instanceof IPackageFragmentRoot) {
                IPackageFragmentRoot fragmentRoot = (IPackageFragmentRoot) javaElement;

                // Add the package fragment root children
                children.addAll(Arrays.asList(fragmentRoot.getChildren()));
                children.addAll(Arrays.asList(fragmentRoot.getNonJavaResources()));

            } else if (javaElement instanceof IPackageFragment) {
                IPackageFragment fragment = (IPackageFragment) javaElement;

                // Add the fragment children
                children.addAll(Arrays.asList(fragment.getClassFiles()));
                children.addAll(Arrays.asList(fragment.getCompilationUnits()));
                children.addAll(Arrays.asList(fragment.getNonJavaResources()));

            } else if (javaElement instanceof ITypeRoot) {

                // No children of class file

            } else {
                // Unhandled java type
                MessageDialog.openWarning(null, "Unhandled java element type",
                        "Unhandled java element type " + javaElement.getClass().getName());
            }

            // Return the children
            return children.toArray();

        } catch (CoreException ex) {
            MessageDialog.openError(null, "Error", ex.getMessage());
            return new Object[0];
        }
    }

    /**
     * Obtains the children of the {@link IJarEntryResource}.
     * 
     * @param jarEntryResource
     *            {@link IJarEntryResource}.
     * @return Children.
     */
    public static Object[] getChildren(IJarEntryResource jarEntryResource) {
        return jarEntryResource.getChildren();
    }

    /**
     * Obtains the specific project, being either {@link IJavaProject} of the
     * input {@link IProject} or the input {@link IProject}.
     * 
     * @param project
     *            {@link IProject}.
     * @return Specific project.
     */
    public static Object getSpecificProject(IProject project) {
        try {
            // Determine if is a java project
            if (project.hasNature(JavaCore.NATURE_ID)) {
                // Obtain the java project
                IJavaProject javaProject = JavaCore.create(project);

                // Return the java project
                return javaProject;

            } else {
                // Return project as is
                return project;
            }

        } catch (CoreException ex) {
            MessageDialog.openError(null, "Error", ex.getMessage());
            return project; // just return the project
        }
    }

    /**
     * All access via static methods.
     */
    private ClasspathUtil() {
    }

}