/******************************************************************************* * Copyright (c) 2012 Pivotal Software, Inc. * 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: * Pivotal Software, Inc. - initial API and implementation *******************************************************************************/ package org.grails.ide.eclipse.core.internal; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathEntry; 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.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.grails.ide.eclipse.commands.GrailsCommandUtils; import org.grails.ide.eclipse.core.GrailsCoreActivator; import org.grails.ide.eclipse.core.internal.classpath.GrailsClasspathContainer; import org.grails.ide.eclipse.core.internal.classpath.GrailsClasspathUtils; import org.grails.ide.eclipse.core.internal.plugins.GrailsProjectStructureManager; import org.grails.ide.eclipse.core.internal.plugins.GrailsProjectStructureTypes; import org.springsource.ide.eclipse.commons.core.JdtUtils; /** * @author Nieraj Singh * @author Kris De Volder * @author Andrew Eisenberg */ public class GrailsResourceUtil { private GrailsResourceUtil() { // util } /** * Returns all accessible Grails projects in the workspace. If no accessible * Grails projects are found, empty list is returned. <br/> * Closed projects, or projects that cannot be read are not included in the * list. * * @return All accessible Grails projects in the workspace, or empty list if * nothing found */ public static final List<IProject> getAllGrailsProjects() { IProject[] projects = ResourcesPlugin.getWorkspace().getRoot() .getProjects(); List<IProject> grailsProjects = new ArrayList<IProject>(); if (projects != null) { for (IProject project : projects) { if (GrailsNature.isGrailsProject(project)) { grailsProjects.add(project); } } } return grailsProjects; } public static boolean hasClasspathContainer(IResource context) { if (JdtUtils.isJavaProject(context)) { return GrailsClasspathUtils.hasClasspathContainer(JdtUtils .getJavaProject(context)); } return false; } public static IPackageFragmentRoot[] getGrailsDependencyPackageFragmentRoots( IProject project, IPath path) { if (project == null) { return null; } IJavaProject javaProject = JavaCore.create(project); try { IClasspathEntry[] entries = javaProject.getRawClasspath(); for (IClasspathEntry entry : entries) { if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { for (IClasspathAttribute attr : entry.getExtraAttributes()) { if (attr.getName().equals( GrailsClasspathContainer.PLUGIN_SOURCEFOLDER_ATTRIBUTE_NAME)) { IFolder folder = ResourcesPlugin.getWorkspace() .getRoot().getFolder(entry.getPath()); if (folder.getLocation().equals(path)) { return javaProject .findPackageFragmentRoots(entry); } } } } } } catch (JavaModelException e) { GrailsCoreActivator.log(e); } return null; } public static boolean isGrailsDependencyPackageFragmentRoot( IPackageFragmentRoot root) { if (root == null) { return false; } try { return isGrailsClasspathEntry(root.getRawClasspathEntry()); } catch (JavaModelException e) { GrailsCoreActivator.log(e); return false; } } public static boolean isGrailsClasspathEntry(IClasspathEntry entry) { return hasClasspathAttribute(entry, GrailsClasspathContainer.PLUGIN_SOURCEFOLDER_ATTRIBUTE_NAME); } public static boolean hasClasspathAttribute(IClasspathEntry entry, String attributeName) { if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { for (IClasspathAttribute attr : entry.getExtraAttributes()) { if (attr.getName().equals(attributeName)) { return true; } } } return false; } /** * Certain file folders containing source files are now filtered out as they * are represented by reimaged source package fragment roots. * <p> * This may include folders that are NOT reimaged but have corresponding * source class path entries * </p> * * @param folder * to check if it is a filtered file folder * @return true if it is a filtered file folder, false otherwise */ public static boolean isFilteredGrailsFolder(IFolder folder) { if (isReimagedGrailsSourceFolder(folder)) { // Reimaged source folders are filtered, as // there are corresponding package fragment roots for them return true; } else if (isSourceFolder(folder)) { // if there is a source class path entry, it should be filtered out return true; } return false; } /** * A grails folder id is represented by the last two segments in a given * folder path. * * @param folder * to determine the last 2 folder path segments * @return the last two folder path segments */ public static String getGrailsFolderID(IFolder folder) { if (folder != null) { IProject project = folder.getProject(); IPath projectLocation = project.getLocation(); if (projectLocation==null) { GrailsCoreActivator.log(new Status( IStatus.WARNING, GrailsCoreActivator.PLUGIN_ID, "Couldn't compute project location for "+project+" in GrailsResourceUtil.getGrailsFolderID")); } else { IPath folderLocation = folder.getLocation(); if (folderLocation==null) { GrailsCoreActivator.log(new Status( IStatus.WARNING, GrailsCoreActivator.PLUGIN_ID, "Couldn't compute folder location for "+folder+" in GrailsResourceUtil.getGrailsFolderID")); } else { folderLocation = folderLocation.makeRelativeTo(projectLocation); int segNumber = folderLocation.segmentCount(); IPath comparison = (segNumber > 2) ? folderLocation.removeFirstSegments(segNumber - 2) : folderLocation; String segString = comparison.toPortableString(); int device = segString.indexOf(IPath.DEVICE_SEPARATOR); if (device >= 0 && device + 1 < segString.length()) { return segString.substring(device + 1); } return segString; } } } return null; } /** * Determines if the given folder is a grails project non-source file folder * that is reimaged with a new icon and display name. * * @param folder * to check if is a reimaged grails file folder * @return true if it is a grails file folder, false otherwise */ public static boolean isReimagedGrailsProjectFileFolder(IFolder folder) { GrailsProjectStructureTypes type = getGrailsContainerType(folder); if (GrailsProjectStructureManager.getInstance().getGrailsFileFolders() .contains(type)) { return true; } return false; } /** * Determines if the given source folder is a grails source folder that is * reimaged with a different name and icon. * * @param folder * to check if it is a reimaged grails source folder * @return true if it is a reimaged folder, false otherwise */ public static boolean isReimagedGrailsSourceFolder(IFolder folder) { GrailsProjectStructureTypes type = getGrailsContainerType(folder); if (GrailsProjectStructureManager.getInstance() .getGrailsSourceFolders().contains(type)) { return true; } return false; } /** * Determines if the given package fragment root is a grails source folder * that is reimaged with a different name and icon. * * @param root * to check if it is a reimaged grails package fragment root * @return true if it is a reimaged folder, false otherwise */ public static boolean isReimagedGrailsSourceFolder(IPackageFragmentRoot root) { IFolder folder = getFolder(root); return isReimagedGrailsSourceFolder(folder); } /** * Converts a grails dependency plugin name containing at least one dash * into a path separator. Removes the plugin name and only returns the * source package name with separators. <br> * Example: <br> * input: hibernate-10-src-groovy <br> * output: src/groovy * * * @param name * containing dashed plugin name to be converted to a OS path * separator * @return converted name if it contains dashes, or the original name if it * contains no dashes, or null if original name is null */ public static String convertRootName(String name) { if (name == null) { return null; } int lastIndex = name.lastIndexOf('-'); if (lastIndex < 0) { return name; } while (lastIndex > 0) { // find the second to last dash if (name.charAt(lastIndex - 1) == '-') { break; } lastIndex--; } String conversionPortion = name.substring(lastIndex); return conversionPortion.replace('-', IPath.SEPARATOR); } /** * Given a folder, which may represent either a file folder, or source * folder (package fragment or package fragment root), this will determine * if there is a Grails container type definition for it. If so, returns * true. False otherwise * <p> * Typically, a folder that is associated with a Grails container type is a * reimaged folder that is shown in the Project Explorer with its own icon * and label. * </p> * * @param folder * to check against a Grails container type * @return true if there is an associated type for the folder. False * otherwise. */ public static GrailsProjectStructureTypes getGrailsContainerType( IFolder folder) { if (folder == null) { return null; } String id = getGrailsFolderID(folder); if (id!=null) { if (GrailsProjectStructureManager.getInstance() .getAllGrailsFolderNames().contains(id)) { GrailsProjectStructureTypes[] types = GrailsProjectStructureTypes.values(); for (GrailsProjectStructureTypes type : types) { if (type.getFolderName().equals(id)) { return type; } } } } return null; } /** * Determines if the given folder corresponds to a Java source folder (i.e. * there is a source class path entry for it). * <p> * The folder could be either a package fragment or a package fragment root * </p> * * @param folder * to check if there is a corresponding source class path entry * for it * @return true if there is a corresponding source class path entry for it. * False otherwise. */ public static boolean isSourceFolder(IFolder folder) { if (folder == null) { return false; } IJavaElement possiblePackageFragRoot = JavaCore.create(folder); if (possiblePackageFragRoot == null) { return false; } if (possiblePackageFragRoot instanceof IPackageFragment) { possiblePackageFragRoot = ((IPackageFragment) possiblePackageFragRoot) .getParent(); } if (possiblePackageFragRoot instanceof IPackageFragmentRoot) { IPackageFragmentRoot root = (IPackageFragmentRoot) possiblePackageFragRoot; try { if (root.getRawClasspathEntry().getEntryKind() == IClasspathEntry.CPE_SOURCE) { return true; } } catch (JavaModelException e) { GrailsCoreActivator.log(e); } } return false; } /** * Given a package fragment root, this will determine if it has a Grails * container type. If so, it most likely is a reimaged root. * * @param root * to check for grails container type * @return true if it has a type, false otherwise */ public static GrailsProjectStructureTypes getGrailsContainerType( IPackageFragmentRoot root) { IFolder folder = getFolder(root); if (folder != null) { return getGrailsContainerType(folder); } return null; } /** * Retrieves the corresponding workspace folder for the given root, or null * if it cannot be resolved. * * @param root * to obtain workspace folder * @return workspace folder, or null if it cannot be resolved */ protected static IFolder getFolder(IPackageFragmentRoot root) { if (root == null) { return null; } try { IResource resource = root.getCorrespondingResource(); if (resource instanceof IFolder) { return (IFolder) resource; } } catch (JavaModelException e) { GrailsCoreActivator.log(e); } return null; } /** * @return true if the resource is either one of the Grails source folders * containing unit/integration/functional tests. */ public static boolean isTestFolder(IResource resource) { IPath path = resource.getProjectRelativePath(); String[] segments = path.segments(); if (segments.length==2) { return typeOfTest(resource)!=null; } return false; } /** * Checks whether a given resource is inside the "test" folder. * @param resource * @return The type of the test (unit/integration/functional) if the resource is inside * the test folder. Return null if the resource is not in the test folder. */ public static String typeOfTest(IResource resource) { IPath path = resource.getProjectRelativePath(); String[] segments = path.segments(); if (segments.length>=2 && segments[0].equals("test")) { return segments[1]; } return null; } public static boolean isSourceFile(IResource resource) { IJavaElement javaElement = (IJavaElement) resource.getAdapter(IJavaElement.class); return javaElement!=null && isSourceFile(javaElement); } public static boolean isSourceFile(IJavaElement javaElement) { IPackageFragmentRoot root = (IPackageFragmentRoot) javaElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); return root!=null && isSourceFolder(root); } public static boolean isSourceFolder(IPackageFragmentRoot root) { IJavaProject jp = root.getJavaProject(); try { IResource rootRsrc = root.getCorrespondingResource(); if (rootRsrc==null) { return false; } IPath rootPath = rootRsrc.getFullPath(); for (IClasspathEntry entry : jp.getRawClasspath()) { if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { if (entry.getPath() != null && entry.getPath().equals(rootPath)) { return true; } } } } catch (JavaModelException e) { e.printStackTrace(); } return false; } /** * If object is a {@link IResource} or adapatable to {@link IResource} then this returns the corresponding * IREsource otjerwise it returns null. */ public static IResource asResource(Object object) { if (object instanceof IResource) { return (IResource) object; } else if (object instanceof IAdaptable) { return (IResource) ((IAdaptable) object).getAdapter(IResource.class); } return null; } public static boolean isDefaultOutputFolder(IFolder folder) { IPath filteredPath = new Path(GrailsCommandUtils.DEFAULT_GRAILS_OUTPUT_FOLDER); IPath folderPath = folder.getProjectRelativePath(); return folderPath.isPrefixOf(filteredPath); } }