| /******************************************************************************* |
| * Copyright (c) 2000, 2006 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 |
| * Matt Chapman, mpchapman@gmail.com - 89977 Make JDT .java agnostic |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.corext.buildpath; |
| |
| import java.net.URI; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.core.filesystem.EFS; |
| import org.eclipse.core.filesystem.IFileStore; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspaceRoot; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| |
| import org.eclipse.jdt.core.IClasspathEntry; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaModelStatus; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.JavaConventions; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.dialogs.StatusInfo; |
| import org.eclipse.jdt.internal.ui.packageview.ClassPathContainer; |
| import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.ArchiveFileFilter; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathsBlock; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementAttribute; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathsBlock.IRemoveOldBinariesQuery; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.IAddArchivesQuery; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.IAddLibrariesQuery; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.ICreateFolderQuery; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.IInclusionExclusionQuery; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.ILinkToQuery; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.IOutputLocationQuery; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.IRemoveLinkedFolderQuery; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.OutputFolderQuery; |
| import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.OutputFolderValidator; |
| |
| public class ClasspathModifier { |
| |
| /** |
| * Interface for listeners that want to receive a notification about |
| * changes on <code>IClasspathEntry</code>. For example, if a source |
| * folder changes one of it's inclusion/exclusion filters, then |
| * this event will be fired. |
| */ |
| public static interface IClasspathModifierListener { |
| /** |
| * The new build path entry that was generated upon calling a method of |
| * <code>ClasspathModifier</code>. The type indicates which kind of |
| * interaction was executed on this entry. |
| * |
| * Note that the list does not contain elements of type |
| * <code>IClasspathEntry</code>, but <code>CPListElement</code> |
| * |
| * @param newEntries list of <code>CPListElement</code> |
| */ |
| public void classpathEntryChanged(List newEntries); |
| } |
| |
| private IClasspathModifierListener fListener; |
| |
| public ClasspathModifier() { |
| this(null); |
| } |
| |
| protected ClasspathModifier(IClasspathModifierListener listener) { |
| fListener= listener; |
| } |
| |
| /** |
| * Create a linked source folder. |
| * |
| * @param query a query to create a linked source folder |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return a list containing a <code>IPackageFragmentRoot</code> representing |
| * the linked source folder |
| * @throws CoreException |
| */ |
| protected List createLinkedSourceFolder(ILinkToQuery query, IJavaProject project, IProgressMonitor monitor) throws CoreException { |
| if (query.doQuery()) { |
| IFolder folder= query.getCreatedFolder(); |
| if (folder != null) { |
| List folderList= new ArrayList(); |
| folderList.add(folder); |
| List root= addToClasspath(folderList, project, query.getOutputFolderQuery(), monitor); |
| if (root.size() == 0) |
| folder.delete(false, null); |
| return root; |
| } |
| } |
| return new ArrayList(); |
| } |
| |
| /** |
| * Create a folder given a <code>FolderCreationQuery</code>. |
| * The query does only have to handle the creation of the folder, |
| * filter manipulations are handlet by the <code> |
| * Classpathmodifier</code> itself using the return value |
| * of <code>FolderCreationQuery.getCreatedFolder()</code>. |
| * |
| * @param folderQuery query to create the new folder |
| * @param outputQuery query to get information about whether the project should be |
| * removed as source folder and update build folder to <code>outputLocation</code> |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return a list containing the created object (either of type <code>IResource</code> |
| * of <code>IJavaElement</code>, or an empty list if no folder was created |
| * (e.g. the operation was cancelled). |
| * @throws CoreException |
| * @throws OperationCanceledException |
| * @see ClasspathModifierQueries.ICreateFolderQuery |
| * @see ClasspathModifierQueries.OutputFolderQuery |
| */ |
| protected List createFolder(ICreateFolderQuery folderQuery, OutputFolderQuery outputQuery, IJavaProject project, IProgressMonitor monitor) throws OperationCanceledException, CoreException { |
| if (folderQuery.doQuery()) { |
| IFolder folder= folderQuery.getCreatedFolder(); |
| if (folder != null) { |
| List folderList= new ArrayList(); |
| folderList.add(folder); |
| if (folderQuery.isSourceFolder()) { |
| List root= addToClasspath(folderList, project, outputQuery, monitor); |
| if (root.size() == 0) |
| folder.delete(false, null); |
| return root; |
| } else { |
| List entries= getExistingEntries(project); |
| exclude(folder.getFullPath(), entries, new ArrayList(), project, monitor); |
| updateClasspath(entries, project, null); |
| } |
| return folderList; |
| } |
| } |
| return new ArrayList(); |
| } |
| |
| /** |
| * Add a list of elements to the build path. |
| * |
| * @param elements a list of elements to be added to the build path. An element |
| * must either be of type <code>IFolder</code>, <code>IJavaElement</code> or |
| * <code>IFile</code> (only allowed if the file is a .jar or .zip file!). |
| * @param project the Java project |
| * @param query for information about whether the project should be removed as |
| * source folder and update build folder |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return returns a list of elements of type <code>IPackageFragmentRoot</code> or |
| * <code>IJavaProject</code> that have been added to the build path or an |
| * empty list if the operation was aborted |
| * @throws CoreException |
| * @throws OperationCanceledException |
| * @see ClasspathModifierQueries.OutputFolderQuery |
| */ |
| protected List addToClasspath(List elements, IJavaProject project, OutputFolderQuery query, IProgressMonitor monitor) throws OperationCanceledException, CoreException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_AddToBuildpath, 2 * elements.size() + 3); |
| IWorkspaceRoot workspaceRoot= JavaPlugin.getWorkspace().getRoot(); |
| |
| if (project.getProject().hasNature(JavaCore.NATURE_ID)) { |
| IPath outputLocation= project.getOutputLocation(); |
| IPath projPath= project.getProject().getFullPath(); |
| List existingEntries= getExistingEntries(project); |
| if (!(elements.size() == 1 && elements.get(0) instanceof IJavaProject) && //if only the project should be added, then the query does not need to be executed |
| (outputLocation.equals(projPath) || query.getDesiredOutputLocation().segmentCount() == 1)) { |
| if (query.doQuery(false, getValidator(elements, project), project)) { |
| project.setOutputLocation(query.getOutputLocation(), null); |
| // remove the project |
| if (query.removeProjectFromClasspath()) { |
| removeFromClasspath(project, existingEntries, null); |
| } |
| |
| IRemoveOldBinariesQuery reorgQuery= BuildPathsBlock.getRemoveOldBinariesQuery(null); |
| if (BuildPathsBlock.hasClassfiles(project.getProject()) && outputLocation.equals(projPath) && reorgQuery.doQuery(projPath)) { |
| IResource res= workspaceRoot.findMember(outputLocation); |
| if (res instanceof IContainer && BuildPathsBlock.hasClassfiles(res)) { |
| BuildPathsBlock.removeOldClassfiles(res); |
| } |
| } |
| outputLocation= project.getOutputLocation(); |
| } else |
| return new ArrayList(); |
| } |
| |
| List newEntries= new ArrayList(); |
| for (int i= 0; i < elements.size(); i++) { |
| Object element= elements.get(i); |
| CPListElement entry; |
| if (element instanceof IResource) |
| entry= addToClasspath((IResource) element, existingEntries, newEntries, project, monitor); |
| else |
| entry= addToClasspath((IJavaElement) element, existingEntries, newEntries, project, monitor); |
| newEntries.add(entry); |
| } |
| |
| Set modifiedSourceEntries= new HashSet(); |
| BuildPathBasePage.fixNestingConflicts((CPListElement[])newEntries.toArray(new CPListElement[newEntries.size()]), (CPListElement[])existingEntries.toArray(new CPListElement[existingEntries.size()]), modifiedSourceEntries); |
| |
| setNewEntry(existingEntries, newEntries, project, new SubProgressMonitor(monitor, 1)); |
| |
| updateClasspath(existingEntries, project, new SubProgressMonitor(monitor, 1)); |
| |
| List result= new ArrayList(); |
| for (int i= 0; i < newEntries.size(); i++) { |
| IClasspathEntry entry= ((CPListElement) newEntries.get(i)).getClasspathEntry(); |
| IJavaElement root; |
| if (entry.getPath().equals(project.getPath())) |
| root= project; |
| else |
| root= project.findPackageFragmentRoot(entry.getPath()); |
| if (root != null) { |
| result.add(root); |
| } |
| } |
| |
| return result; |
| } else { |
| StatusInfo rootStatus= new StatusInfo(); |
| rootStatus.setError(NewWizardMessages.ClasspathModifier_Error_NoNatures); |
| throw new CoreException(rootStatus); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Add external archives (.jar and .zip files) to the buildpath. The |
| * method uses the query to find out which entries need to be added. |
| * |
| * @param query the query to get the information which entries need to be added |
| * @param project the java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return a list of <code>IPackageFragmentRoot</code>s representing the added |
| * archives or an empty list if no element was added. |
| * @throws CoreException |
| * |
| * @see IAddArchivesQuery |
| */ |
| protected List addExternalJars(IAddArchivesQuery query, IJavaProject project, IProgressMonitor monitor) throws CoreException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| IPath[] selected= query.doQuery(); |
| List addedEntries= new ArrayList(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_AddToBuildpath, 4); |
| if (selected != null) { |
| for (int i= 0; i < selected.length; i++) { |
| addedEntries.add(new CPListElement(project, IClasspathEntry.CPE_LIBRARY, selected[i], null)); |
| } |
| monitor.worked(1); |
| |
| List existingEntries= getExistingEntries(project); |
| setNewEntry(existingEntries, addedEntries, project, new SubProgressMonitor(monitor, 1)); |
| updateClasspath(existingEntries, project, new SubProgressMonitor(monitor, 1)); |
| |
| List result= new ArrayList(addedEntries.size()); |
| for (int i= 0; i < addedEntries.size(); i++) { |
| IClasspathEntry entry= ((CPListElement) addedEntries.get(i)).getClasspathEntry(); |
| IJavaElement elem= project.findPackageFragmentRoot(entry.getPath()); |
| if (elem != null) { |
| result.add(elem); |
| } |
| } |
| monitor.worked(1); |
| return result; |
| } |
| } finally { |
| monitor.done(); |
| } |
| return new ArrayList(); |
| } |
| |
| /** |
| * Add libraries to the buildpath. The |
| * method uses the query to find out which entries need to be added. |
| * |
| * @param query the query to get the information which entries need to be added |
| * @param project the java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return a list of <code>ClasspathContainer</code>s representing the added |
| * archives or an empty list if no element was added. |
| * @throws CoreException |
| * |
| * @see IAddArchivesQuery |
| */ |
| protected List addLibraries(IAddLibrariesQuery query, IJavaProject project, IProgressMonitor monitor) throws CoreException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| IClasspathEntry[] selected= query.doQuery(project, project.getRawClasspath()); |
| List addedEntries= new ArrayList(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_AddToBuildpath, 4); |
| if (selected != null) { |
| for (int i= 0; i < selected.length; i++) { |
| addedEntries.add(new CPListElement(project, IClasspathEntry.CPE_CONTAINER, selected[i].getPath(), null)); |
| } |
| monitor.worked(1); |
| |
| List existingEntries= getExistingEntries(project); |
| setNewEntry(existingEntries, addedEntries, project, new SubProgressMonitor(monitor, 1)); |
| updateClasspath(existingEntries, project, new SubProgressMonitor(monitor, 1)); |
| |
| List result= new ArrayList(addedEntries.size()); |
| for (int i= 0; i < addedEntries.size(); i++) { |
| result.add(new ClassPathContainer(project, selected[i])); |
| } |
| monitor.worked(1); |
| return result; |
| } |
| } finally { |
| monitor.done(); |
| } |
| return new ArrayList(); |
| } |
| |
| protected List addLibraryEntries(List resources, IJavaProject project, IProgressMonitor monitor) throws CoreException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| List addedEntries= new ArrayList(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_AddToBuildpath, 4); |
| for (int i= 0; i < resources.size(); i++) { |
| IResource res= (IResource) resources.get(i); |
| addedEntries.add(new CPListElement(project, IClasspathEntry.CPE_LIBRARY, res.getFullPath(), res)); |
| } |
| monitor.worked(1); |
| |
| List existingEntries= getExistingEntries(project); |
| setNewEntry(existingEntries, addedEntries, project, new SubProgressMonitor(monitor, 1)); |
| updateClasspath(existingEntries, project, new SubProgressMonitor(monitor, 1)); |
| |
| List result= new ArrayList(addedEntries.size()); |
| for (int i= 0; i < resources.size(); i++) { |
| IResource res= (IResource) resources.get(i); |
| IJavaElement elem= project.getPackageFragmentRoot(res); |
| if (elem != null) { |
| result.add(elem); |
| } |
| } |
| |
| monitor.worked(1); |
| return result; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| |
| /** |
| * Remove a list of elements to the build path. |
| * |
| * @param query query to remove unused linked folders from the project |
| * @param elements a list of elements to be removed from the build path. An element |
| * must either be of type <code>IJavaProject</code>, <code>IPackageFragmentRoot</code> or |
| * <code>ClassPathContainer</code> |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return returns a list of elements of type <code>IFile</code> (in case of removed archives) or |
| * <code>IFolder</code> that have been removed from the build path |
| * @throws CoreException |
| * @throws OperationCanceledException |
| */ |
| protected List removeFromClasspath(IRemoveLinkedFolderQuery query, List elements, IJavaProject project, IProgressMonitor monitor) throws CoreException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_RemoveFromBuildpath, elements.size() + 1); |
| List existingEntries= getExistingEntries(project); |
| List resultElements= new ArrayList(); |
| |
| boolean archiveRemoved= false; |
| for (int i= 0; i < elements.size(); i++) { |
| Object element= elements.get(i); |
| Object res= null; |
| if (element instanceof IJavaProject) { |
| res= removeFromClasspath(project, existingEntries, new SubProgressMonitor(monitor, 1)); |
| } else { |
| if (element instanceof IPackageFragmentRoot) { |
| IPackageFragmentRoot root= (IPackageFragmentRoot) element; |
| if (root.getKind() == IPackageFragmentRoot.K_BINARY) { |
| archiveRemoved= true; |
| res= removeFromClasspath(root, existingEntries, project, new SubProgressMonitor(monitor, 1)); |
| } else { |
| final IResource resource= root.getCorrespondingResource(); |
| if (resource instanceof IFolder) { |
| final IFolder folder= (IFolder) resource; |
| if (folder.isLinked()) { |
| final int result= query.doQuery(folder); |
| if (result != IRemoveLinkedFolderQuery.REMOVE_CANCEL) { |
| if (result == IRemoveLinkedFolderQuery.REMOVE_BUILD_PATH) { |
| res= removeFromClasspath(root, existingEntries, project, new SubProgressMonitor(monitor, 1)); |
| } else if (result == IRemoveLinkedFolderQuery.REMOVE_BUILD_PATH_AND_FOLDER) { |
| res= removeFromClasspath(root, existingEntries, project, new SubProgressMonitor(monitor, 1)); |
| folder.delete(true, true, new SubProgressMonitor(monitor, 1)); |
| } |
| } |
| } else { |
| res= removeFromClasspath(root, existingEntries, project, new SubProgressMonitor(monitor, 1)); |
| } |
| } else { |
| res= removeFromClasspath(root, existingEntries, project, new SubProgressMonitor(monitor, 1)); |
| } |
| } |
| } else { |
| archiveRemoved= true; |
| ClassPathContainer container= (ClassPathContainer) element; |
| existingEntries.remove(CPListElement.createFromExisting(container.getClasspathEntry(), project)); |
| } |
| } |
| if (res != null) { |
| resultElements.add(res); |
| } |
| |
| } |
| |
| updateClasspath(existingEntries, project, new SubProgressMonitor(monitor, 1)); |
| fireEvent(existingEntries); |
| if (archiveRemoved && resultElements.size() == 0) |
| resultElements.add(project); |
| return resultElements; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Include a list of elements to the build path. This means that the inclusion filter for the |
| * corresponding <code>IPackageFragmentRoot</code>s need to be modified. |
| * All elements must be either be of type <code>IResource</code> |
| * or <code>IJavaElement</code>. |
| * |
| * Note: the <code>IJavaElement</code>'s fragment (if there is one) |
| * is not allowed to be excluded! However, inclusion (or simply no |
| * filter) on the parent fragment is allowed. |
| * |
| * @param elements a list of elements to be included. The elements must be either of type |
| * <code>IResource</code> or <code>IJavaElement</code>. |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return a list of <code>IJavaElement</code>s corresponding to the included ones. |
| * @throws JavaModelException |
| * |
| * @see #exclude(List, IJavaProject, IProgressMonitor) |
| */ |
| protected List include(List elements, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_Including, 2 * elements.size()); |
| |
| List existingEntries= getExistingEntries(project); |
| List resources= new ArrayList(); |
| for (int i= 0; i < elements.size(); i++) { |
| IResource resource; |
| if (elements.get(i) instanceof IResource) |
| resource= (IResource) elements.get(i); |
| else { |
| IJavaElement elem= (IJavaElement) elements.get(i); |
| resource= elem.getResource(); |
| } |
| resources.add(resource); |
| IPackageFragmentRoot root= getFragmentRoot(resource, project, new SubProgressMonitor(monitor, 1)); |
| if (root != null) { |
| CPListElement entry= getClasspathEntry(existingEntries, root); |
| include(resource, entry, project, new SubProgressMonitor(monitor, 1)); |
| } |
| } |
| |
| updateClasspath(existingEntries, project, new SubProgressMonitor(monitor, 4)); |
| List javaElements= getCorrespondingElements(resources, project); |
| return javaElements; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Exclude a list of <code>IJavaElement</code>s. This means that the exclusion filter for the |
| * corresponding <code>IPackageFragmentRoot</code>s needs to be modified. |
| * |
| * Note: the <code>IJavaElement</code>'s fragment (if there is one) |
| * is not allowed to be excluded! However, inclusion (or simply no |
| * filter) on the parent fragment is allowed. |
| * |
| * @param javaElements list of Java elements to be excluded |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return list of objects representing the excluded elements |
| * @throws JavaModelException |
| */ |
| protected List exclude(List javaElements, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_Excluding, javaElements.size() + 4); |
| |
| List existingEntries= getExistingEntries(project); |
| List resources= new ArrayList(); |
| for (int i= 0; i < javaElements.size(); i++) { |
| IJavaElement javaElement= (IJavaElement) javaElements.get(i); |
| IPackageFragmentRoot root= (IPackageFragmentRoot) javaElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); |
| CPListElement entry= getClasspathEntry(existingEntries, root); |
| |
| IResource resource= exclude(javaElement, entry, project, new SubProgressMonitor(monitor, 1)); |
| if (resource != null) { |
| resources.add(resource); |
| } |
| } |
| |
| updateClasspath(existingEntries, project, new SubProgressMonitor(monitor, 4)); |
| return resources; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Inverse operation to include. |
| * The <code>IJavaElement</code>s in the list will be removed from |
| * their fragment roots inclusion filter. |
| * |
| * Note: the <code>IJavaElement</code>'s fragment (if there is one) |
| * is not allowed to be excluded! However, inclusion (or simply no |
| * filter) on the parent fragment is allowed. |
| * |
| * @param javaElements a list of <code>IJavaElements</code> to be unincluded |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return a list of elements representing unexcluded elements |
| * @throws JavaModelException |
| * |
| * @see #include(List, IJavaProject, IProgressMonitor) |
| */ |
| protected List unInclude(List javaElements, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_RemoveInclusion, 10); |
| |
| List existingEntries= getExistingEntries(project); |
| for (int i= 0; i < javaElements.size(); i++) { |
| IJavaElement javaElement= (IJavaElement) javaElements.get(i); |
| IPackageFragmentRoot root= (IPackageFragmentRoot) javaElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); |
| CPListElement entry= getClasspathEntry(existingEntries, root); |
| |
| unInclude(javaElement, entry, project, new SubProgressMonitor(monitor, 1)); |
| } |
| |
| updateClasspath(existingEntries, project, new SubProgressMonitor(monitor, 4)); |
| List result= getCorrespondingElements(javaElements, project); |
| return result; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Inverse operation to <code>exclude</code>. |
| * The list of elements of type <code>IResource</code> will be |
| * removed from the exclusion filters of their parent roots. |
| * |
| * Note: the <code>IJavaElement</code>'s fragment (if there is one) |
| * is not allowed to be excluded! However, inclusion (or simply no |
| * filter) on the parent fragment is allowed. |
| * |
| * @param elements list of <code>IResource</code>s to be unexcluded |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return an object representing the unexcluded element |
| * @throws JavaModelException |
| * |
| * @see #exclude(List, IJavaProject, IProgressMonitor) |
| * @see #unExclude(List, IJavaProject, IProgressMonitor) |
| */ |
| protected List unExclude(List elements, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_Including, 2 * elements.size()); |
| |
| List entries= getExistingEntries(project); |
| for (int i= 0; i < elements.size(); i++) { |
| IResource resource= (IResource) elements.get(i); |
| IPackageFragmentRoot root= getFragmentRoot(resource, project, new SubProgressMonitor(monitor, 1)); |
| if (root != null) { |
| CPListElement entry= getClasspathEntry(entries, root); |
| unExclude(resource, entry, project, new SubProgressMonitor(monitor, 1)); |
| } |
| } |
| |
| updateClasspath(entries, project, new SubProgressMonitor(monitor, 4)); |
| List resultElements= getCorrespondingElements(elements, project); |
| return resultElements; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Edit the filters of a given <code>IJavaElement</code> by using the |
| * passed <code>IInclusionExclusionQuery</code>. |
| * |
| * @param element the Java element to edit the filters on. Must be either of |
| * type <code>IJavaProject</code> or <code>IPackageFragmentRoot</code>. |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return returns the edited Java element or <code>null</code> if the operation was |
| * cancelled |
| * @throws JavaModelException |
| */ |
| protected IJavaElement editFilters(IJavaElement element, IJavaProject project, IInclusionExclusionQuery query, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_EditInclusionExclusionFilters, 4); |
| List existingEntries= getExistingEntries(project); |
| CPListElement entry= getListElement(element.getPath(), existingEntries); |
| if (entry != null) { |
| if (query.doQuery(entry, false)) { |
| entry.setAttribute(CPListElement.INCLUSION, query.getInclusionPattern()); |
| entry.setAttribute(CPListElement.EXCLUSION, query.getExclusionPattern()); |
| updateClasspath(existingEntries, project, new SubProgressMonitor(monitor, 4)); |
| return element; |
| } |
| } |
| } finally { |
| monitor.done(); |
| } |
| return null; |
| } |
| |
| /** |
| * Creates an output folder for the given fragment root. |
| * |
| * Note: the folder is also created in the file system. |
| * Therefore clients have to ensure that is is deleted if |
| * necessary because the <code>ClasspathModifier</code> does |
| * not handle this. |
| * |
| * @param root the fragment root to create the ouptut folder for |
| * @param query a query to get information about the output |
| * location that should be used for a given element |
| * @param project the current Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return a CPListElementAttribute object representing the new folder or <code>null</code> |
| * if the folder was not created (e.g. because the user cancelled the creation) |
| * @throws CoreException |
| * @see #editOutputFolder(CPListElement, IJavaProject, IOutputLocationQuery, IProgressMonitor) |
| * @see ClasspathModifierQueries.IOutputLocationQuery |
| */ |
| protected CPListElementAttribute createOutputFolder(IPackageFragmentRoot root, IOutputLocationQuery query, IJavaProject project, IProgressMonitor monitor) throws CoreException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| IClasspathEntry entry= root.getRawClasspathEntry(); |
| CPListElement elem= CPListElement.createFromExisting(entry, project); |
| return editOutputFolder(elem, project, query, monitor); |
| } |
| |
| /** |
| * Edit the output folder entry for a given <code> |
| * CPListElement</code> which corresponds to |
| * a <code>IPackageFragmentRoot</code>. The <code> |
| * IOutputLocationQuery</code> provides the information |
| * necessary to edit this entry. |
| * |
| * Note: a folder can be created in the file system. |
| * Therefore clients have to ensure that is is deleted if |
| * necessary because the <code>ClasspathModifier</code> does |
| * not handle this. |
| * |
| * @param element an element representing the output folder's parent |
| * @param project the Java project |
| * @param query Query to get information about the output |
| * location that should be used for a given element |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return an attribute representing the modified output folder, or |
| * <code>null</code> if editing was cancelled |
| * @throws CoreException |
| * @see #createOutputFolder(IPackageFragmentRoot, IOutputLocationQuery, IJavaProject, IProgressMonitor) |
| * @see CPListElement#createFromExisting(IClasspathEntry, IJavaProject) |
| */ |
| protected CPListElementAttribute editOutputFolder(CPListElement element, IJavaProject project, IOutputLocationQuery query, IProgressMonitor monitor) throws CoreException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| List entries= getExistingEntries(project); |
| element= getClasspathEntry(entries, element); |
| if (query.doQuery(element)) { |
| OutputFolderQuery outputFolderQuery= query.getOutputFolderQuery(query.getOutputLocation()); |
| if (outputFolderQuery.getDesiredOutputLocation().segmentCount() == 1) { |
| if (!outputFolderQuery.doQuery(true, getTrueValidator(project), project)) |
| return null; |
| project.setOutputLocation(outputFolderQuery.getOutputLocation(), null); |
| if (outputFolderQuery.removeProjectFromClasspath()) { |
| removeFromClasspath(project, entries, null); |
| } |
| } |
| if (query.getOutputLocation() == null) { |
| CPListElementAttribute attr= resetOutputFolder(element, project); |
| updateClasspath(entries, project, new NullProgressMonitor()); |
| return attr; |
| } |
| exclude(query.getOutputLocation(), entries, new ArrayList(), project, null); |
| element.setAttribute(CPListElement.OUTPUT, query.getOutputLocation()); |
| CPListElementAttribute outputFolder= new CPListElementAttribute(element, CPListElement.OUTPUT, element.getAttribute(CPListElement.OUTPUT), true); |
| updateClasspath(entries, project, new NullProgressMonitor()); |
| return outputFolder; |
| } |
| return null; |
| } |
| |
| /** |
| * Reset all output folder for the given Java project. |
| * |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| */ |
| protected void resetOutputFolders(IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| IPackageFragmentRoot[] roots= project.getPackageFragmentRoots(); |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ResetOutputFolder, roots.length + 10); |
| List entries= new ArrayList(); |
| for (int i= 0; i < roots.length; i++) { |
| monitor.worked(1); |
| if (roots[i].isArchive()) |
| continue; |
| IClasspathEntry entry= roots[i].getRawClasspathEntry(); |
| CPListElement element= CPListElement.createFromExisting(entry, project); |
| CPListElementAttribute outputFolder= new CPListElementAttribute(element, CPListElement.OUTPUT, element.getAttribute(CPListElement.OUTPUT), true); |
| entries.add(outputFolder); |
| } |
| reset(entries, project, new SubProgressMonitor(monitor, 10)); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Reset a list of elements. The elements can be either of type |
| * <li><code>IJavaProject</code></li> |
| * <li><code>IPackageFragmentRoot</code></li> |
| * <li><code>CPListElementAttribute</code></li><br> |
| * |
| * Depending on the element, resetting performs two different operations: |
| * <li>On <code>IJavaProject</code> or <code>IPackageFragmentRoot</code>, the |
| * inclusion and exclusion filters are reset. Only entries in the filters that |
| * correspond to either source folders or output folders will not be |
| * removed (to prevent damage on the project layout)</li> |
| * <li>On <code>CPListElementAttribute</code>, the output location of the |
| * given attribute is reset to the default output location.</li> |
| * |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return a list of elements representing the elements on which 'reset' was called. |
| * They can either be of type <code>CPListElement</code>, <code>IJavaProject</code> or |
| * <code>IPackageFragmentRoot</code> |
| */ |
| protected List reset(List elements, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_Resetting, elements.size()); |
| List entries= getExistingEntries(project); |
| List result= new ArrayList(); |
| for (int i= 0; i < elements.size(); i++) { |
| Object element= elements.get(i); |
| if (element instanceof IJavaElement) { |
| IJavaElement javaElement= (IJavaElement) element; |
| IPackageFragmentRoot root; |
| if (element instanceof IJavaProject) |
| root= project.getPackageFragmentRoot(project.getResource()); |
| else |
| root= (IPackageFragmentRoot) element; |
| CPListElement entry= getClasspathEntry(entries, root); |
| resetFilters(javaElement, entry, project, new SubProgressMonitor(monitor, 1)); |
| result.add(javaElement); |
| } else { |
| CPListElement selElement= ((CPListElementAttribute) element).getParent(); |
| CPListElement entry= getClasspathEntry(entries, selElement); |
| CPListElementAttribute outputFolder= resetOutputFolder(entry, project); |
| result.add(outputFolder); |
| } |
| } |
| |
| updateClasspath(entries, project, null); |
| fireEvent(entries); |
| return result; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Get the <code>IClasspathEntry</code> from the project and |
| * convert it into a list of <code>CPListElement</code>s. |
| * |
| * @param project the Java project to get it's build path entries from |
| * @return a list of <code>CPListElement</code>s corresponding to the |
| * build path entries of the project |
| * @throws JavaModelException |
| */ |
| public static List getExistingEntries(IJavaProject project) throws JavaModelException { |
| IClasspathEntry[] classpathEntries= project.getRawClasspath(); |
| ArrayList newClassPath= new ArrayList(); |
| for (int i= 0; i < classpathEntries.length; i++) { |
| IClasspathEntry curr= classpathEntries[i]; |
| newClassPath.add(CPListElement.createFromExisting(curr, project)); |
| } |
| return newClassPath; |
| } |
| |
| /** |
| * Try to find the corresponding and modified <code>CPListElement</code> for the root |
| * in the list of elements and return it. |
| * If no one can be found, the roots <code>ClasspathEntry</code> is converted to a |
| * <code>CPListElement</code> and returned. |
| * |
| * @param elements a list of <code>CPListElements</code> |
| * @param root the root to find the <code>ClasspathEntry</code> for represented by |
| * a <code>CPListElement</code> |
| * @return the <code>CPListElement</code> found in the list (matching by using the path) or |
| * the roots own <code>IClasspathEntry</code> converted to a <code>CPListElement</code>. |
| * @throws JavaModelException |
| */ |
| public static CPListElement getClasspathEntry(List elements, IPackageFragmentRoot root) throws JavaModelException { |
| IClasspathEntry entry= root.getRawClasspathEntry(); |
| for (int i= 0; i < elements.size(); i++) { |
| CPListElement element= (CPListElement) elements.get(i); |
| if (element.getPath().equals(root.getPath()) && element.getEntryKind() == entry.getEntryKind()) |
| return (CPListElement) elements.get(i); |
| } |
| CPListElement newElement= CPListElement.createFromExisting(entry, root.getJavaProject()); |
| elements.add(newElement); |
| return newElement; |
| } |
| |
| /** |
| * For a given <code>IResource</code>, try to |
| * convert it into a <code>IPackageFragmentRoot</code> |
| * if possible or return <code>null</code> if no |
| * fragment root could be created. |
| * |
| * @param resource the resource to be converted |
| * @return the <code>resource<code> as |
| * <code>IPackageFragment</code>,or <code>null</code> |
| * if failed to convert |
| */ |
| public static IPackageFragment getFragment(IResource resource) { |
| IJavaElement elem= JavaCore.create(resource); |
| if (elem instanceof IPackageFragment) |
| return (IPackageFragment) elem; |
| return null; |
| } |
| |
| /** |
| * Get the source folder of a given <code>IResource</code> element, |
| * starting with the resource's parent. |
| * |
| * @param resource the resource to get the fragment root from |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return resolved fragment root |
| * @throws JavaModelException |
| */ |
| public static IPackageFragmentRoot getFragmentRoot(IResource resource, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| IJavaElement javaElem= null; |
| if (resource.getFullPath().equals(project.getPath())) |
| return project.getPackageFragmentRoot(resource); |
| IContainer container= resource.getParent(); |
| do { |
| if (container instanceof IFolder) |
| javaElem= JavaCore.create((IFolder) container); |
| if (container.getFullPath().equals(project.getPath())) { |
| javaElem= project; |
| break; |
| } |
| container= container.getParent(); |
| if (container == null) |
| return null; |
| } while (javaElem == null || !(javaElem instanceof IPackageFragmentRoot)); |
| if (javaElem instanceof IJavaProject) |
| javaElem= project.getPackageFragmentRoot(project.getResource()); |
| return (IPackageFragmentRoot) javaElem; |
| } |
| |
| /** |
| * Get the <code>IClasspathEntry</code> for the |
| * given path by looking up all |
| * build path entries on the project |
| * |
| * @param path the path to find a build path entry for |
| * @param project the Java project |
| * @return the <code>IClasspathEntry</code> corresponding |
| * to the <code>path</code> or <code>null</code> if there |
| * is no such entry |
| * @throws JavaModelException |
| */ |
| public static IClasspathEntry getClasspathEntryFor(IPath path, IJavaProject project, int entryKind) throws JavaModelException { |
| IClasspathEntry[] entries= project.getRawClasspath(); |
| for (int i= 0; i < entries.length; i++) { |
| IClasspathEntry entry= entries[i]; |
| if (entry.getPath().equals(path) && equalEntryKind(entry, entryKind)) |
| return entry; |
| } |
| return null; |
| } |
| |
| /** |
| * Check whether the current selection is the project's |
| * default output folder or not |
| * |
| * @param attrib the attribute to be checked |
| * @return <code>true</code> if is the default output folder, |
| * <code>false</code> otherwise. |
| */ |
| public static boolean isDefaultOutputFolder(CPListElementAttribute attrib) { |
| return attrib.getValue() == null; |
| } |
| |
| /** |
| * Determines whether the current selection (of type |
| * <code>ICompilationUnit</code> or <code>IPackageFragment</code>) |
| * is on the inclusion filter of it's parent source folder. |
| * |
| * @param selection the current Java element |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return <code>true</code> if the current selection is included, |
| * <code>false</code> otherwise. |
| * @throws JavaModelException |
| */ |
| public static boolean isIncluded(IJavaElement selection, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ContainsPath, 4); |
| IPackageFragmentRoot root= (IPackageFragmentRoot) selection.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); |
| IClasspathEntry entry= root.getRawClasspathEntry(); |
| if (entry == null) |
| return false; |
| return contains(selection.getPath().removeFirstSegments(root.getPath().segmentCount()), entry.getInclusionPatterns(), new SubProgressMonitor(monitor, 2)); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Find out whether the <code>IResource</code> excluded or not. |
| * |
| * @param resource the resource to be checked |
| * @param project the Java project |
| * @return <code>true</code> if the resource is excluded, <code> |
| * false</code> otherwise |
| * @throws JavaModelException |
| */ |
| public static boolean isExcluded(IResource resource, IJavaProject project) throws JavaModelException { |
| IPackageFragmentRoot root= getFragmentRoot(resource, project, null); |
| if (root == null) |
| return false; |
| String fragmentName= getName(resource.getFullPath(), root.getPath()); |
| fragmentName= completeName(fragmentName); |
| IClasspathEntry entry= root.getRawClasspathEntry(); |
| return entry != null && contains(new Path(fragmentName), entry.getExclusionPatterns(), null); |
| } |
| |
| /** |
| * Find out whether one of the <code>IResource</code>'s parents |
| * is excluded. |
| * |
| * @param resource check the resources parents whether they are |
| * excluded or not |
| * @param project the Java project |
| * @return <code>true</code> if there is an excluded parent, |
| * <code>false</code> otherwise |
| * @throws JavaModelException |
| */ |
| public static boolean parentExcluded(IResource resource, IJavaProject project) throws JavaModelException { |
| if (resource.getFullPath().equals(project.getPath())) |
| return false; |
| IPackageFragmentRoot root= getFragmentRoot(resource, project, null); |
| if (root == null) { |
| return true; |
| } |
| IPath path= resource.getFullPath().removeFirstSegments(root.getPath().segmentCount()); |
| IClasspathEntry entry= root.getRawClasspathEntry(); |
| if (entry == null) |
| return true; // there is no build path entry, this is equal to the fact that the parent is excluded |
| while (path.segmentCount() > 0) { |
| if (contains(path, entry.getExclusionPatterns(), null)) |
| return true; |
| path= path.removeLastSegments(1); |
| } |
| return false; |
| } |
| |
| /** |
| * Check wheter the output location of the <code>IPackageFragmentRoot</code> |
| * is <code>null</code>. If this holds, then the root |
| * does use the default output folder. |
| * |
| * @param root the root to examine the output location for |
| * @return <code>true</code> if the root uses the default output folder, <code>false |
| * </code> otherwise. |
| * @throws JavaModelException |
| */ |
| public static boolean hasDefaultOutputFolder(IPackageFragmentRoot root) throws JavaModelException { |
| return root.getRawClasspathEntry().getOutputLocation() == null; |
| } |
| |
| /** |
| * Check whether at least one source folder of the given |
| * Java project has an output folder set. |
| * |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return <code>true</code> if at least one outputfolder |
| * is set, <code>false</code> otherwise |
| * @throws JavaModelException |
| */ |
| public static boolean hasOutputFolders(IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| IPackageFragmentRoot[] roots= project.getPackageFragmentRoots(); |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_CheckOutputFolders, roots.length); |
| for (int i= 0; i < roots.length; i++) { |
| if (roots[i].getRawClasspathEntry().getOutputLocation() != null) |
| return true; |
| monitor.worked(1); |
| } |
| } finally { |
| monitor.done(); |
| } |
| return false; |
| } |
| |
| protected static String escapeSpecialChars(String value) { |
| StringBuffer buf = new StringBuffer(); |
| for (int i = 0; i < value.length(); i++) { |
| char c = value.charAt(i); |
| |
| switch (c) { |
| case '&': |
| buf.append("&"); //$NON-NLS-1$ |
| break; |
| case '<': |
| buf.append("<"); //$NON-NLS-1$ |
| break; |
| case '>': |
| buf.append(">"); //$NON-NLS-1$ |
| break; |
| case '\'': |
| buf.append("'"); //$NON-NLS-1$ |
| break; |
| case '\"': |
| buf.append("""); //$NON-NLS-1$ |
| break; |
| case 160: |
| buf.append(" "); //$NON-NLS-1$ |
| break; |
| default: |
| buf.append(c); |
| break; |
| } |
| } |
| return buf.toString(); |
| } |
| |
| |
| /** |
| * Check whether the <code>IJavaProject</code> |
| * is a source folder |
| * |
| * @param project the project to test |
| * @return <code>true</code> if <code>project</code> is a source folder |
| * <code>false</code> otherwise. |
| */ |
| public static boolean isSourceFolder(IJavaProject project) throws JavaModelException { |
| return ClasspathModifier.getClasspathEntryFor(project.getPath(), project, IClasspathEntry.CPE_SOURCE) != null; |
| } |
| |
| /** |
| * Check whether the <code>IPackageFragment</code> |
| * corresponds to the project's default fragment. |
| * |
| * @param fragment the package fragment to be checked |
| * @return <code>true</code> if is the default package fragment, |
| * <code>false</code> otherwise. |
| */ |
| public static boolean isDefaultFragment(IPackageFragment fragment) { |
| return fragment.getElementName().length() == 0; |
| } |
| |
| /** |
| * Determines whether the inclusion filter of the element's source folder is empty |
| * or not |
| * @return <code>true</code> if the inclusion filter is empty, |
| * <code>false</code> otherwise. |
| * @throws JavaModelException |
| */ |
| public static boolean includeFiltersEmpty(IResource resource, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ExamineInputFilters, 4); |
| IPackageFragmentRoot root= getFragmentRoot(resource, project, new SubProgressMonitor(monitor, 4)); |
| if (root != null) { |
| IClasspathEntry entry= root.getRawClasspathEntry(); |
| return entry.getInclusionPatterns().length == 0; |
| } |
| return true; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Check whether the input paramenter of type <code> |
| * IPackageFragmentRoot</code> has either it's inclusion or |
| * exclusion filter or both set (that means they are |
| * not empty). |
| * |
| * @param root the fragment root to be inspected |
| * @return <code>true</code> inclusion or exclusion filter set, |
| * <code>false</code> otherwise. |
| */ |
| public static boolean filtersSet(IPackageFragmentRoot root) throws JavaModelException { |
| if (root == null) |
| return false; |
| IClasspathEntry entry= root.getRawClasspathEntry(); |
| IPath[] inclusions= entry.getInclusionPatterns(); |
| IPath[] exclusions= entry.getExclusionPatterns(); |
| if (inclusions != null && inclusions.length > 0) |
| return true; |
| if (exclusions != null && exclusions.length > 0) |
| return true; |
| return false; |
| } |
| |
| /** |
| * Add a resource to the build path. |
| * |
| * @param resource the resource to be added to the build path |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return returns the new element of type <code>IPackageFragmentRoot</code> that has been added to the build path |
| * @throws CoreException |
| * @throws OperationCanceledException |
| */ |
| public static CPListElement addToClasspath(IResource resource, List existingEntries, List newEntries, IJavaProject project, IProgressMonitor monitor) throws OperationCanceledException, CoreException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_AddToBuildpath, 2); |
| exclude(resource.getFullPath(), existingEntries, newEntries, project, new SubProgressMonitor(monitor, 1)); |
| CPListElement entry= new CPListElement(project, IClasspathEntry.CPE_SOURCE, resource.getFullPath(), resource); |
| return entry; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Check whether the provided file is an archive (.jar or .zip). |
| * |
| * @param file the file to be checked |
| * @param project the Java project |
| * @return <code>true</code> if the file is an archive, <code>false</code> |
| * otherwise |
| * @throws JavaModelException |
| */ |
| public static boolean isArchive(IFile file, IJavaProject project) throws JavaModelException { |
| if (!ArchiveFileFilter.isArchivePath(file.getFullPath())) |
| return false; |
| if (project != null && project.exists() && (project.findPackageFragmentRoot(file.getFullPath()) == null)) |
| return true; |
| return false; |
| } |
| |
| /** |
| * Add a Java element to the build path. |
| * |
| * @param javaElement element to be added to the build path |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return returns the new element of type <code>IPackageFragmentRoot</code> that has been added to the build path |
| * @throws CoreException |
| * @throws OperationCanceledException |
| */ |
| public static CPListElement addToClasspath(IJavaElement javaElement, List existingEntries, List newEntries, IJavaProject project, IProgressMonitor monitor) throws OperationCanceledException, CoreException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_AddToBuildpath, 10); |
| CPListElement entry= new CPListElement(project, IClasspathEntry.CPE_SOURCE, javaElement.getPath(), javaElement.getResource()); |
| return entry; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Remove the Java project from the build path |
| * |
| * @param project the project to be removed |
| * @param existingEntries a list of existing <code>CPListElement</code>. This list |
| * will be traversed and the entry for the project will be removed. |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return returns the Java project |
| * @throws CoreException |
| */ |
| public static IJavaProject removeFromClasspath(IJavaProject project, List existingEntries, IProgressMonitor monitor) throws CoreException { |
| CPListElement elem= getListElement(project.getPath(), existingEntries); |
| if (elem != null) { |
| existingEntries.remove(elem); |
| } |
| return project; |
| } |
| |
| /** |
| * Remove a given <code>IPackageFragmentRoot</code> from the build path. |
| * |
| * @param root the <code>IPackageFragmentRoot</code> to be removed from the build path |
| * @param existingEntries a list of <code>CPListElements</code> representing the build path |
| * entries of the project. The entry for the root will be looked up and removed from the list. |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return returns the <code>IResource</code> that has been removed from the build path; |
| * is of type <code>IFile</code> if the root was an archive, otherwise <code>IFolder</code> or <code>null<code> for external archives. |
| */ |
| public static IResource removeFromClasspath(IPackageFragmentRoot root, List existingEntries, IJavaProject project, IProgressMonitor monitor) throws CoreException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_RemoveFromBuildpath, 1); |
| IClasspathEntry entry= root.getRawClasspathEntry(); |
| CPListElement elem= CPListElement.createFromExisting(entry, project); |
| existingEntries.remove(elem); |
| removeFilters(elem.getPath(), project, existingEntries); |
| return elem.getResource(); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Remove <code>path</code> from inclusion/exlusion filters in all <code>existingEntries</code> |
| * |
| * @param path the path to remove |
| * @param project the Java project |
| * @param existingEntries a list of <code>CPListElement</code> representing the build path |
| * entries of the project. |
| * @return returns a <code>List</code> of <code>CPListElement</code> of modified elements, not null. |
| */ |
| public static List removeFilters(IPath path, IJavaProject project, List existingEntries) { |
| if (path == null) |
| return Collections.EMPTY_LIST; |
| |
| IPath projPath= project.getPath(); |
| if (projPath.isPrefixOf(path)) { |
| path= path.removeFirstSegments(projPath.segmentCount()).addTrailingSeparator(); |
| } |
| |
| List result= new ArrayList(); |
| for (Iterator iter= existingEntries.iterator(); iter.hasNext();) { |
| CPListElement element= (CPListElement)iter.next(); |
| boolean hasChange= false; |
| IPath[] exlusions= (IPath[])element.getAttribute(CPListElement.EXCLUSION); |
| if (exlusions != null) { |
| List exlusionList= new ArrayList(exlusions.length); |
| for (int i= 0; i < exlusions.length; i++) { |
| if (!exlusions[i].equals(path)) { |
| exlusionList.add(exlusions[i]); |
| } else { |
| hasChange= true; |
| } |
| } |
| element.setAttribute(CPListElement.EXCLUSION, exlusionList.toArray(new IPath[exlusionList.size()])); |
| } |
| |
| IPath[] inclusion= (IPath[])element.getAttribute(CPListElement.INCLUSION); |
| if (inclusion != null) { |
| List inclusionList= new ArrayList(inclusion.length); |
| for (int i= 0; i < inclusion.length; i++) { |
| if (!inclusion[i].equals(path)) { |
| inclusionList.add(inclusion[i]); |
| } else { |
| hasChange= true; |
| } |
| } |
| element.setAttribute(CPListElement.INCLUSION, inclusionList.toArray(new IPath[inclusionList.size()])); |
| } |
| if (hasChange) { |
| result.add(element); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Include the given <code>IResource</code>. This means that the inclusion filter for the |
| * corresponding <code>IPackageFragmentRoot</code> needs to be modified. |
| * |
| * Note: the <code>IJavaElement</code>'s fragment (if there is one) |
| * is not allowed to be excluded! However, inclusion (or simply no |
| * filter) on the parent fragment is allowed. |
| * |
| * @param resource the element to be included |
| * @param entry the <code>CPListElement</code> representing the |
| * <code>IClasspathEntry</code> of the resource's root |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * |
| * @throws JavaModelException |
| * |
| * @see #exclude(List, IJavaProject, IProgressMonitor) |
| */ |
| private void include(IResource resource, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_Including, 10); |
| |
| String name= getName(resource.getFullPath(), entry.getPath()); |
| |
| IPath[] includedPath= (IPath[]) entry.getAttribute(CPListElement.INCLUSION); |
| IPath[] newIncludedPath= new IPath[includedPath.length + 1]; |
| String completedName= completeName(name); |
| IPath relPath= new Path(completedName); |
| if (!contains(relPath, includedPath, new SubProgressMonitor(monitor, 2))) { |
| System.arraycopy(includedPath, 0, newIncludedPath, 0, includedPath.length); |
| newIncludedPath[includedPath.length]= relPath; |
| entry.setAttribute(CPListElement.INCLUSION, newIncludedPath); |
| entry.setAttribute(CPListElement.EXCLUSION, remove(relPath, (IPath[]) entry.getAttribute(CPListElement.EXCLUSION), new SubProgressMonitor(monitor, 2))); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Exclude an element with a given name and absolute path |
| * from the build path. |
| * |
| * @param name the name of the element to be excluded |
| * @param fullPath the absolute path of the element |
| * @param entry the build path entry to be modified |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return a <code>IResource</code> corresponding to the excluded element |
| * @throws JavaModelException |
| */ |
| private static IResource exclude(String name, IPath fullPath, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| IResource result; |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_Excluding, 6); |
| IPath[] excludedPath= (IPath[]) entry.getAttribute(CPListElement.EXCLUSION); |
| IPath[] newExcludedPath= new IPath[excludedPath.length + 1]; |
| name= completeName(name); |
| IPath path= new Path(name); |
| if (!contains(path, excludedPath, new SubProgressMonitor(monitor, 2))) { |
| System.arraycopy(excludedPath, 0, newExcludedPath, 0, excludedPath.length); |
| newExcludedPath[excludedPath.length]= path; |
| entry.setAttribute(CPListElement.EXCLUSION, newExcludedPath); |
| entry.setAttribute(CPListElement.INCLUSION, remove(path, (IPath[]) entry.getAttribute(CPListElement.INCLUSION), new SubProgressMonitor(monitor, 4))); |
| } |
| result= fullPath == null ? null : getResource(fullPath, project); |
| } finally { |
| monitor.done(); |
| } |
| return result; |
| } |
| |
| /** |
| * Exclude an object at a given path. |
| * This means that the exclusion filter for the |
| * corresponding <code>IPackageFragmentRoot</code> needs to be modified. |
| * |
| * First, the fragment root needs to be found. To do so, the new entries |
| * are and the existing entries are traversed for a match and the entry |
| * with the path is removed from one of those lists. |
| * |
| * Note: the <code>IJavaElement</code>'s fragment (if there is one) |
| * is not allowed to be excluded! However, inclusion (or simply no |
| * filter) on the parent fragment is allowed. |
| * |
| * @param path absolute path of an object to be excluded |
| * @param existingEntries a list of existing build path entries |
| * @param newEntries a list of new build path entries |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| */ |
| public static void exclude(IPath path, List existingEntries, List newEntries, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_Excluding, 1); |
| CPListElement elem= null; |
| CPListElement existingElem= null; |
| int i= 0; |
| do { |
| i++; |
| IPath rootPath= path.removeLastSegments(i); |
| |
| if (rootPath.segmentCount() == 0) |
| return; |
| |
| elem= getListElement(rootPath, newEntries); |
| existingElem= getListElement(rootPath, existingEntries); |
| } while (existingElem == null && elem == null); |
| if (elem == null) { |
| elem= existingElem; |
| } |
| exclude(path.removeFirstSegments(path.segmentCount() - i).toString(), null, elem, project, new SubProgressMonitor(monitor, 1)); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Exclude a <code>IJavaElement</code>. This means that the exclusion filter for the |
| * corresponding <code>IPackageFragmentRoot</code>s need to be modified. |
| * |
| * Note: the <code>IJavaElement</code>'s fragment (if there is one) |
| * is not allowed to be excluded! However, inclusion (or simply no |
| * filter) on the parent fragment is allowed. |
| * |
| * @param javaElement the Java element to be excluded |
| * @param entry the <code>CPListElement</code> representing the |
| * <code>IClasspathEntry</code> of the Java element's root. |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * |
| * @return the resulting <code>IResource<code> |
| * @throws JavaModelException |
| */ |
| public static IResource exclude(IJavaElement javaElement, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| String name= getName(javaElement.getPath(), entry.getPath()); |
| return exclude(name, javaElement.getPath(), entry, project, new SubProgressMonitor(monitor, 1)); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Inverse operation to <code>include</code>. The provided |
| * <code>IJavaElement</code> will be removed from the inclusion |
| * filters of it's root. |
| * |
| * Note: the <code>IJavaElement</code>'s fragment (if there is one) |
| * is not allowed to be excluded! However, inclusion (or simply no |
| * filter) on the parent fragment is allowed. |
| * |
| * @param javaElement the Java element to be unincluded |
| * @param entry the <code>CPListElement</code> representing the |
| * <code>IClasspathEntry</code> of the root. |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @throws JavaModelException |
| * |
| * @see #include(List, IJavaProject, IProgressMonitor) |
| */ |
| private void unInclude(IJavaElement javaElement, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_RemoveInclusion, 10); |
| String name= getName(javaElement.getPath(), entry.getPath()); |
| |
| IPath[] includedPath= (IPath[]) entry.getAttribute(CPListElement.INCLUSION); |
| IPath relPath= new Path(completeName(name)); |
| IPath[] newIncludedPath= remove(relPath, includedPath, new SubProgressMonitor(monitor, 3)); |
| entry.setAttribute(CPListElement.INCLUSION, newIncludedPath); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Inverse operation to <code>exclude</code>. |
| * The resource removed from it's fragment roots exlusion filter. |
| * |
| * Note: the <code>IJavaElement</code>'s fragment (if there is one) |
| * is not allowed to be excluded! However, inclusion (or simply no |
| * filter) on the parent fragment is allowed. |
| * |
| * @param resource the resource to be unexcluded |
| * @param entry the <code>CPListElement</code> representing the |
| * <code>IClasspathEntry</code> of the resource's root. |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @throws JavaModelException |
| * |
| * @see #exclude(List, IJavaProject, IProgressMonitor) |
| */ |
| public static void unExclude(IResource resource, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_RemoveExclusion, 10); |
| String name= getName(resource.getFullPath(), entry.getPath()); |
| IPath[] excludedPath= (IPath[]) entry.getAttribute(CPListElement.EXCLUSION); |
| IPath[] newExcludedPath= remove(new Path(completeName(name)), excludedPath, new SubProgressMonitor(monitor, 3)); |
| entry.setAttribute(CPListElement.EXCLUSION, newExcludedPath); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Resets inclusion and exclusion filters for the given |
| * <code>IJavaElement</code> |
| * |
| * @param element element to reset it's filters |
| * @param entry the <code>CPListElement</code> to reset its filters for |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @throws JavaModelException |
| */ |
| private void resetFilters(IJavaElement element, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ResetFilters, 3); |
| |
| List exclusionList= getFoldersOnCP(element.getPath(), project, new SubProgressMonitor(monitor, 2)); |
| IPath outputLocation= (IPath) entry.getAttribute(CPListElement.OUTPUT); |
| if (outputLocation != null) { |
| IPath[] exclusionPatterns= (IPath[]) entry.getAttribute(CPListElement.EXCLUSION); |
| if (contains(new Path(completeName(outputLocation.lastSegment())), exclusionPatterns, null)) { |
| exclusionList.add(new Path(completeName(outputLocation.lastSegment()))); |
| } |
| } |
| IPath[] exclusions= (IPath[]) exclusionList.toArray(new IPath[exclusionList.size()]); |
| |
| entry.setAttribute(CPListElement.INCLUSION, new IPath[0]); |
| entry.setAttribute(CPListElement.EXCLUSION, exclusions); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Reset the output folder for the given entry to the default output folder |
| * |
| * @param entry the <code>CPListElement</code> to be edited |
| * @param project the Java project |
| * @return an attribute representing the modified output folder |
| * @throws JavaModelException |
| */ |
| public static CPListElementAttribute resetOutputFolder(CPListElement entry, IJavaProject project) throws JavaModelException { |
| entry.setAttribute(CPListElement.OUTPUT, null); |
| CPListElementAttribute outputFolder= new CPListElementAttribute(entry, CPListElement.OUTPUT, entry.getAttribute(CPListElement.OUTPUT), true); |
| return outputFolder; |
| } |
| |
| /** |
| * Try to find the corresponding and modified <code>CPListElement</code> for the provided |
| * <code>CPListElement</code> in the list of elements and return it. |
| * If no one can be found, the provided <code>CPListElement</code> is returned. |
| * |
| * @param elements a list of <code>CPListElements</code> |
| * @param cpElement the <code>CPListElement</code> to find the corresponding entry in |
| * the list |
| * @return the <code>CPListElement</code> found in the list (matching by using the path) or |
| * the second <code>CPListElement</code> parameter itself if there is no match. |
| * @throws JavaModelException |
| */ |
| public static CPListElement getClasspathEntry(List elements, CPListElement cpElement) throws JavaModelException { |
| for (int i= 0; i < elements.size(); i++) { |
| if (((CPListElement) elements.get(i)).getPath().equals(cpElement.getPath())) |
| return (CPListElement) elements.get(i); |
| } |
| elements.add(cpElement); |
| return cpElement; |
| } |
| |
| /** |
| * For a given path, find the corresponding element in the list. |
| * |
| * @param path the path to found an entry for |
| * @param elements a list of <code>CPListElement</code>s |
| * @return the mathed <code>CPListElement</code> or <code>null</code> if |
| * no match could be found |
| */ |
| private static CPListElement getListElement(IPath path, List elements) { |
| for (int i= 0; i < elements.size(); i++) { |
| CPListElement element= (CPListElement) elements.get(i); |
| if (element.getEntryKind() == IClasspathEntry.CPE_SOURCE && element.getPath().equals(path)) { |
| return element; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Updates the build path if changes have been applied to a |
| * build path entry. For example, this can be necessary after |
| * having edited some filters on a build path entry, which can happen |
| * when including or excluding an object. |
| * |
| * @param newEntries a list of <code>CPListElements</code> that should be used |
| * as build path entries for the project. |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @throws JavaModelException in case that validation for the new entries fails |
| */ |
| private void updateClasspath(List newEntries, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| IClasspathEntry[] entries= convert(newEntries); |
| IPath outputLocation= project.getOutputLocation(); |
| |
| IJavaModelStatus status= JavaConventions.validateClasspath(project, entries, outputLocation); |
| if (!status.isOK()) |
| throw new JavaModelException(status); |
| |
| project.setRawClasspath(entries, outputLocation, new SubProgressMonitor(monitor, 2)); |
| fireEvent(newEntries); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| public static void commitClassPath(List newEntries, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| IClasspathEntry[] entries= convert(newEntries); |
| IPath outputLocation= project.getOutputLocation(); |
| |
| IJavaModelStatus status= JavaConventions.validateClasspath(project, entries, outputLocation); |
| if (!status.isOK()) |
| throw new JavaModelException(status); |
| |
| project.setRawClasspath(entries, outputLocation, new SubProgressMonitor(monitor, 2)); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * For a given list of entries, find out what representation they |
| * will have in the project and return a list with corresponding |
| * elements. |
| * |
| * @param entries a list of entries to find an appropriate representation |
| * for. The list can contain elements of two types: |
| * <li><code>IResource</code></li> |
| * <li><code>IJavaElement</code></li> |
| * @param project the Java project |
| * @return a list of elements corresponding to the passed entries. |
| */ |
| public static List getCorrespondingElements(List entries, IJavaProject project) { |
| List result= new ArrayList(); |
| for (int i= 0; i < entries.size(); i++) { |
| Object element= entries.get(i); |
| IPath path; |
| if (element instanceof IResource) |
| path= ((IResource) element).getFullPath(); |
| else |
| path= ((IJavaElement) element).getPath(); |
| IResource resource= getResource(path, project); |
| if (resource != null) { |
| IJavaElement elem= JavaCore.create(resource); |
| if (elem != null && project.isOnClasspath(elem)) |
| result.add(elem); |
| else |
| result.add(resource); |
| } |
| |
| } |
| return result; |
| } |
| |
| /** |
| * Returns for the given absolute path the corresponding |
| * resource, this is either element of type <code>IFile</code> |
| * or <code>IFolder</code>. |
| * |
| * @param path an absolute path to a resource |
| * @param project the Java project |
| * @return the resource matching to the path. Can be |
| * either an <code>IFile</code> or an <code>IFolder</code>. |
| */ |
| private static IResource getResource(IPath path, IJavaProject project) { |
| return project.getProject().getWorkspace().getRoot().findMember(path); |
| } |
| |
| /** |
| * Find out whether the provided path equals to one |
| * in the array. |
| * |
| * @param path path to find an equivalent for |
| * @param paths set of paths to compare with |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return <code>true</code> if there is an occurrence, <code> |
| * false</code> otherwise |
| */ |
| private static boolean contains(IPath path, IPath[] paths, IProgressMonitor monitor) { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| if (path == null) |
| return false; |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ComparePaths, paths.length); |
| if (path.getFileExtension() == null) |
| path= new Path(completeName(path.toString())); |
| for (int i= 0; i < paths.length; i++) { |
| if (paths[i].equals(path)) |
| return true; |
| monitor.worked(1); |
| } |
| } finally { |
| monitor.done(); |
| } |
| return false; |
| } |
| |
| /** |
| * Add a '/' at the end of the name if |
| * it does not end with '.java', or other Java-like extension. |
| * |
| * @param name append '/' at the end if |
| * necessary |
| * @return modified string |
| */ |
| private static String completeName(String name) { |
| if (!JavaCore.isJavaLikeFileName(name)) { |
| name= name + "/"; //$NON-NLS-1$ |
| name= name.replace('.', '/'); |
| return name; |
| } |
| return name; |
| } |
| |
| /** |
| * Removes <code>path</code> out of the set of given <code> |
| * paths</code>. If the path is not contained, then the |
| * initially provided array of paths is returned. |
| * |
| * Only the first occurrence will be removed. |
| * |
| * @param path path to be removed |
| * @param paths array of path to apply the removal on |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return array which does not contain <code>path</code> |
| */ |
| private static IPath[] remove(IPath path, IPath[] paths, IProgressMonitor monitor) { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_RemovePath, paths.length + 5); |
| if (!contains(path, paths, new SubProgressMonitor(monitor, 5))) |
| return paths; |
| |
| ArrayList newPaths= new ArrayList(); |
| for (int i= 0; i < paths.length; i++) { |
| monitor.worked(1); |
| if (!paths[i].equals(path)) |
| newPaths.add(paths[i]); |
| } |
| |
| return (IPath[]) newPaths.toArray(new IPath[newPaths.size()]); |
| } finally { |
| monitor.done(); |
| } |
| |
| } |
| |
| /** |
| * Find all folders that are on the build path and |
| * <code>path</code> is a prefix of those folders |
| * path entry, that is, all folders which are a |
| * subfolder of <code>path</code>. |
| * |
| * For example, if <code>path</code>=/MyProject/src |
| * then all folders having a path like /MyProject/src/*, |
| * where * can be any valid string are returned if |
| * they are also on the project's build path. |
| * |
| * @param path absolute path |
| * @param project the Java project |
| * @param monitor progress monitor, can be <code>null</code> |
| * @return an array of paths which belong to subfolders |
| * of <code>path</code> and which are on the build path |
| * @throws JavaModelException |
| */ |
| private List getFoldersOnCP(IPath path, IJavaProject project, IProgressMonitor monitor) throws JavaModelException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| List srcFolders= new ArrayList(); |
| IClasspathEntry[] cpEntries= project.getRawClasspath(); |
| for (int i= 0; i < cpEntries.length; i++) { |
| IPath cpPath= cpEntries[i].getPath(); |
| if (path.isPrefixOf(cpPath) && path.segmentCount() + 1 == cpPath.segmentCount()) |
| srcFolders.add(new Path(completeName(cpPath.lastSegment()))); |
| } |
| return srcFolders; |
| } |
| |
| /** |
| * Returns a string corresponding to the <code>path</code> |
| * with the <code>rootPath<code>'s number of segments |
| * removed |
| * |
| * @param path path to remove segments |
| * @param rootPath provides the number of segments to |
| * be removed |
| * @return a string corresponding to the mentioned |
| * action |
| */ |
| private static String getName(IPath path, IPath rootPath) { |
| return path.removeFirstSegments(rootPath.segmentCount()).toString(); |
| } |
| |
| /** |
| * Sets and validates the new entries. Note that the elments of |
| * the list containing the new entries will be added to the list of |
| * existing entries (therefore, there is no return list for this method). |
| * |
| * @param existingEntries a list of existing classpath entries |
| * @param newEntries a list of entries to be added to the existing ones |
| * @param project the Java project |
| * @param monitor a progress monitor, can be <code>null</code> |
| * @throws CoreException in case that validation on one of the new entries fails |
| */ |
| public static void setNewEntry(List existingEntries, List newEntries, IJavaProject project, IProgressMonitor monitor) throws CoreException { |
| try { |
| monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_SetNewEntry, existingEntries.size()); |
| for (int i= 0; i < newEntries.size(); i++) { |
| CPListElement entry= (CPListElement) newEntries.get(i); |
| validateAndAddEntry(entry, existingEntries, project); |
| monitor.worked(1); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Convert a list of <code>CPListElement</code>s to |
| * an array of <code>IClasspathEntry</code>. |
| * |
| * @param list the list to be converted |
| * @return an array containing build path entries |
| * corresponding to the list |
| */ |
| private static IClasspathEntry[] convert(List list) { |
| IClasspathEntry[] entries= new IClasspathEntry[list.size()]; |
| for (int i= 0; i < list.size(); i++) { |
| CPListElement element= (CPListElement) list.get(i); |
| entries[i]= element.getClasspathEntry(); |
| } |
| return entries; |
| } |
| |
| /** |
| * Validate the new entry in the context of the existing entries. Furthermore, |
| * check if exclusion filters need to be applied and do so if necessary. |
| * |
| * If validation was successfull, add the new entry to the list of existing entries. |
| * |
| * @param entry the entry to be validated and added to the list of existing entries. |
| * @param existingEntries a list of existing entries representing the build path |
| * @param project the Java project |
| * @throws CoreException in case that validation fails |
| */ |
| private static void validateAndAddEntry(CPListElement entry, List existingEntries, IJavaProject project) throws CoreException { |
| IPath path= entry.getPath(); |
| IPath projPath= project.getProject().getFullPath(); |
| IWorkspaceRoot workspaceRoot= ResourcesPlugin.getWorkspace().getRoot(); |
| IStatus validate= workspaceRoot.getWorkspace().validatePath(path.toString(), IResource.FOLDER); |
| StatusInfo rootStatus= new StatusInfo(); |
| rootStatus.setOK(); |
| boolean isExternal= isExternalArchiveOrLibrary(entry, project); |
| if (!isExternal && validate.matches(IStatus.ERROR) && !project.getPath().equals(path)) { |
| rootStatus.setError(Messages.format(NewWizardMessages.NewSourceFolderWizardPage_error_InvalidRootName, validate.getMessage())); |
| throw new CoreException(rootStatus); |
| } else { |
| if (!isExternal && !project.getPath().equals(path)) { |
| IResource res= workspaceRoot.findMember(path); |
| if (res != null) { |
| if (res.getType() != IResource.FOLDER && res.getType() != IResource.FILE) { |
| rootStatus.setError(NewWizardMessages.NewSourceFolderWizardPage_error_NotAFolder); |
| throw new CoreException(rootStatus); |
| } |
| } else { |
| URI projLocation= project.getProject().getLocationURI(); |
| if (projLocation != null) { |
| IFileStore store= EFS.getStore(projLocation).getChild(path); |
| if (store.fetchInfo().exists()) { |
| rootStatus.setError(NewWizardMessages.NewSourceFolderWizardPage_error_AlreadyExistingDifferentCase); |
| throw new CoreException(rootStatus); |
| } |
| } |
| } |
| } |
| |
| for (int i= 0; i < existingEntries.size(); i++) { |
| CPListElement curr= (CPListElement) existingEntries.get(i); |
| if (curr.getEntryKind() == IClasspathEntry.CPE_SOURCE) { |
| if (path.equals(curr.getPath()) && !project.getPath().equals(path)) { |
| rootStatus.setError(NewWizardMessages.NewSourceFolderWizardPage_error_AlreadyExisting); |
| throw new CoreException(rootStatus); |
| } |
| } |
| } |
| |
| if (!isExternal && !entry.getPath().equals(project.getPath())) |
| exclude(entry.getPath(), existingEntries, new ArrayList(), project, null); |
| |
| IPath outputLocation= project.getOutputLocation(); |
| insertAtEndOfCategory(entry, existingEntries); |
| |
| IClasspathEntry[] entries= convert(existingEntries); |
| |
| IJavaModelStatus status= JavaConventions.validateClasspath(project, entries, outputLocation); |
| if (!status.isOK()) { |
| if (outputLocation.equals(projPath)) { |
| IStatus status2= JavaConventions.validateClasspath(project, entries, outputLocation); |
| if (status2.isOK()) { |
| if (project.isOnClasspath(project)) { |
| rootStatus.setInfo(Messages.format(NewWizardMessages.NewSourceFolderWizardPage_warning_ReplaceSFandOL, outputLocation.makeRelative().toString())); |
| } else { |
| rootStatus.setInfo(Messages.format(NewWizardMessages.NewSourceFolderWizardPage_warning_ReplaceOL, outputLocation.makeRelative().toString())); |
| } |
| return; |
| } |
| } |
| rootStatus.setError(status.getMessage()); |
| throw new CoreException(rootStatus); |
| } |
| |
| if (isSourceFolder(project) || project.getPath().equals(path)) { |
| rootStatus.setWarning(NewWizardMessages.NewSourceFolderWizardPage_warning_ReplaceSF); |
| return; |
| } |
| |
| rootStatus.setOK(); |
| return; |
| } |
| } |
| |
| private static void insertAtEndOfCategory(CPListElement entry, List existingEntries) { |
| int length= existingEntries.size(); |
| CPListElement[] elements= (CPListElement[])existingEntries.toArray(new CPListElement[length]); |
| int i= 0; |
| while (i < length && elements[i].getClasspathEntry().getEntryKind() != entry.getClasspathEntry().getEntryKind()) { |
| i++; |
| } |
| if (i < length) { |
| i++; |
| while (i < length && elements[i].getClasspathEntry().getEntryKind() == entry.getClasspathEntry().getEntryKind()) { |
| i++; |
| } |
| existingEntries.add(i, entry); |
| return; |
| } |
| |
| switch (entry.getClasspathEntry().getEntryKind()) { |
| case IClasspathEntry.CPE_SOURCE: |
| existingEntries.add(0, entry); |
| break; |
| case IClasspathEntry.CPE_CONTAINER: |
| case IClasspathEntry.CPE_LIBRARY: |
| case IClasspathEntry.CPE_PROJECT: |
| case IClasspathEntry.CPE_VARIABLE: |
| default: |
| existingEntries.add(entry); |
| break; |
| } |
| } |
| |
| private static boolean isExternalArchiveOrLibrary(CPListElement entry, IJavaProject project) { |
| if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY || entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { |
| if (entry.getResource() instanceof IFolder) { |
| return false; |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Test if the provided kind is of type |
| * <code>IClasspathEntry.CPE_SOURCE</code> |
| * |
| * @param entry the classpath entry to be compared with the provided type |
| * @param kind the kind to be checked |
| * @return <code>true</code> if kind equals |
| * <code>IClasspathEntry.CPE_SOURCE</code>, |
| * <code>false</code> otherwise |
| */ |
| private static boolean equalEntryKind(IClasspathEntry entry, int kind) { |
| return entry.getEntryKind() == kind; |
| } |
| |
| /** |
| * Event fired whenever build pathentries changed. |
| * The event parameter corresponds to the |
| * a <code>List</code> of <code>CPListElement</code>s |
| * |
| * @param newEntries |
| * |
| * @see #addToClasspath(List, IJavaProject, OutputFolderQuery, IProgressMonitor) |
| * @see #removeFromClasspath(IRemoveLinkedFolderQuery, List, IJavaProject, IProgressMonitor) |
| */ |
| private void fireEvent(List newEntries) { |
| if (fListener != null) |
| fListener.classpathEntryChanged(newEntries); |
| } |
| |
| private OutputFolderValidator getTrueValidator(IJavaProject project) throws JavaModelException { |
| return new OutputFolderValidator(null, project) { |
| public boolean validate(IPath outputLocation) { |
| return true; |
| } |
| }; |
| } |
| |
| public static OutputFolderValidator getValidator(final List newElements, final IJavaProject project) throws JavaModelException { |
| return new OutputFolderValidator(newElements, project) { |
| |
| public boolean validate(IPath outputLocation) { |
| for (int i= 0; i < newElements.size(); i++) { |
| if (isInvalid(newElements.get(i), outputLocation)) |
| return false; |
| } |
| |
| for (int i= 0; i < fEntries.length; i++) { |
| if (isInvalid(fEntries[i], outputLocation)) |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Check if the output location for the given object is valid |
| * |
| * @param object the object to retrieve its path from and compare it |
| * to the output location |
| * @param outputLocation the output location |
| * @return <code>true</code> if the output location is invalid, that is, |
| * if it is a subfolder of the provided object. |
| */ |
| private boolean isInvalid(Object object, IPath outputLocation) { |
| IPath path= null; |
| if (object instanceof IFolder) |
| path= getFolderPath(object); |
| else |
| if (object instanceof IJavaElement) |
| path= getJavaElementPath(object); |
| else |
| if (object instanceof IClasspathEntry) |
| path= getCPEntryPath(object); |
| return isSubFolderOf(path, outputLocation); |
| } |
| |
| /** |
| * Get an <code>IFolder</code>'s path |
| * |
| * @param element an element which is of type <code>IFolder</code> |
| * @return the path of the folder |
| */ |
| private IPath getFolderPath(Object element) { |
| return ((IFolder) element).getFullPath(); |
| } |
| |
| /** |
| * Get an <code>IJavaElement</code>'s path |
| * |
| * @param element an element which is of type <code>IJavaElement</code> |
| * @return the path of the Java element |
| */ |
| private IPath getJavaElementPath(Object element) { |
| return ((IJavaElement) element).getPath(); |
| } |
| |
| /** |
| * Get an <code>IClasspathEntry</code>'s path |
| * |
| * @param entry an element which is of type <code>IClasspathEntry</code> |
| * @return the path of the classpath entry |
| */ |
| private IPath getCPEntryPath(Object entry) { |
| return ((IClasspathEntry) entry).getPath(); |
| } |
| |
| /** |
| * |
| * @param path1 the first path |
| * @param path2 the second path |
| * @return <code>true</code> if path1 is a subfolder of |
| * path2, <code>false</code> otherwise |
| */ |
| private boolean isSubFolderOf(IPath path1, IPath path2) { |
| if (path1 == null || path2 == null) { |
| if (path1 == null && path2 == null) |
| return true; |
| return false; |
| } |
| return path2.matchingFirstSegments(path1) == path2.segmentCount(); |
| } |
| |
| }; |
| } |
| } |