1 /******************************************************************************* 2 * Copyright (c) 2000, 2016 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage; 15 16 import java.lang.reflect.InvocationTargetException; 17 import java.util.ArrayList; 18 import java.util.HashSet; 19 import java.util.List; 20 import java.util.Set; 21 22 import org.eclipse.swt.widgets.Shell; 23 24 import org.eclipse.core.runtime.CoreException; 25 import org.eclipse.core.runtime.IPath; 26 import org.eclipse.core.runtime.IProgressMonitor; 27 import org.eclipse.core.runtime.OperationCanceledException; 28 import org.eclipse.core.runtime.SubProgressMonitor; 29 30 import org.eclipse.core.resources.IContainer; 31 import org.eclipse.core.resources.IFolder; 32 import org.eclipse.core.resources.IProject; 33 import org.eclipse.core.resources.IResource; 34 import org.eclipse.core.resources.IWorkspaceRoot; 35 36 import org.eclipse.jface.dialogs.IDialogConstants; 37 import org.eclipse.jface.dialogs.MessageDialog; 38 import org.eclipse.jface.operation.IRunnableContext; 39 import org.eclipse.jface.operation.IRunnableWithProgress; 40 import org.eclipse.jface.viewers.IStructuredSelection; 41 import org.eclipse.jface.viewers.StructuredSelection; 42 43 import org.eclipse.ui.IWorkbenchSite; 44 import org.eclipse.ui.PlatformUI; 45 import org.eclipse.ui.part.ISetSelectionTarget; 46 47 import org.eclipse.jdt.core.IClasspathEntry; 48 import org.eclipse.jdt.core.IJavaElement; 49 import org.eclipse.jdt.core.IJavaProject; 50 import org.eclipse.jdt.core.IPackageFragment; 51 import org.eclipse.jdt.core.JavaCore; 52 53 import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels; 54 import org.eclipse.jdt.internal.corext.buildpath.BuildpathDelta; 55 import org.eclipse.jdt.internal.corext.buildpath.ClasspathModifier; 56 import org.eclipse.jdt.internal.corext.util.Messages; 57 58 import org.eclipse.jdt.ui.JavaElementLabels; 59 60 import org.eclipse.jdt.internal.ui.JavaPlugin; 61 import org.eclipse.jdt.internal.ui.JavaPluginImages; 62 import org.eclipse.jdt.internal.ui.dialogs.StatusInfo; 63 import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages; 64 import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage; 65 import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathsBlock; 66 import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement; 67 import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.OutputFolderQuery; 68 69 //SelectedElements iff enabled: IJavaProject || IPackageFrament || IFolder 70 public class AddFolderToBuildpathAction extends BuildpathModifierAction { 71 72 private final IRunnableContext fContext; 73 AddFolderToBuildpathAction(IWorkbenchSite site)74 public AddFolderToBuildpathAction(IWorkbenchSite site) { 75 this(site, null, PlatformUI.getWorkbench().getProgressService()); 76 } 77 AddFolderToBuildpathAction(IRunnableContext context, ISetSelectionTarget selectionTarget)78 public AddFolderToBuildpathAction(IRunnableContext context, ISetSelectionTarget selectionTarget) { 79 this(null, selectionTarget, context); 80 } 81 AddFolderToBuildpathAction(IWorkbenchSite site, ISetSelectionTarget selectionTarget, IRunnableContext context)82 private AddFolderToBuildpathAction(IWorkbenchSite site, ISetSelectionTarget selectionTarget, IRunnableContext context) { 83 super(site, selectionTarget, BuildpathModifierAction.ADD_SEL_SF_TO_BP); 84 85 fContext= context; 86 87 setText(NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_AddSelSFToCP_label); 88 setImageDescriptor(JavaPluginImages.DESC_ELCL_ADD_AS_SOURCE_FOLDER); 89 setToolTipText(NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_AddSelSFToCP_tooltip); 90 } 91 92 @Override getDetailedDescription()93 public String getDetailedDescription() { 94 if (!isEnabled()) 95 return null; 96 97 if (getSelectedElements().size() != 1) 98 return NewWizardMessages.PackageExplorerActionGroup_FormText_Default_toBuildpath; 99 100 Object obj= getSelectedElements().get(0); 101 String elementLabel= JavaElementLabels.getTextLabel(obj, JavaElementLabels.ALL_DEFAULT); 102 if (obj instanceof IJavaProject) { 103 return Messages.format(NewWizardMessages.PackageExplorerActionGroup_FormText_ProjectToBuildpath, elementLabel); 104 } else if (obj instanceof IPackageFragment) { 105 return Messages.format(NewWizardMessages.PackageExplorerActionGroup_FormText_PackageToBuildpath, elementLabel); 106 } else if (obj instanceof IResource) { 107 return Messages.format(NewWizardMessages.PackageExplorerActionGroup_FormText_FolderToBuildpath, elementLabel); 108 } 109 110 return null; 111 } 112 113 @Override run()114 public void run() { 115 116 try { 117 final IJavaProject project; 118 Object object= getSelectedElements().get(0); 119 if (object instanceof IJavaProject) { 120 project= (IJavaProject)object; 121 } else if (object instanceof IPackageFragment) { 122 project= ((IPackageFragment)object).getJavaProject(); 123 } else { 124 IFolder folder= (IFolder)object; 125 project= JavaCore.create(folder.getProject()); 126 if (project == null) 127 return; 128 } 129 130 final Shell shell= getShell(); 131 132 final boolean removeProjectFromClasspath; 133 IPath outputLocation= project.getOutputLocation(); 134 final IPath defaultOutputLocation= outputLocation.makeRelative(); 135 final IPath newDefaultOutputLocation; 136 final boolean removeOldClassFiles; 137 IPath projPath= project.getProject().getFullPath(); 138 if (((getSelectedElements().size() != 1) || !(getSelectedElements().get(0) instanceof IJavaProject)) && //if only the project should be added, then the query does not need to be executed 139 (outputLocation.equals(projPath) || defaultOutputLocation.segmentCount() == 1)) { 140 141 142 final OutputFolderQuery outputFolderQuery= ClasspathModifierQueries.getDefaultFolderQuery(shell, defaultOutputLocation); 143 if (outputFolderQuery.doQuery(true, ClasspathModifier.getValidator(getSelectedElements(), project), project)) { 144 newDefaultOutputLocation= outputFolderQuery.getOutputLocation(); 145 removeProjectFromClasspath= outputFolderQuery.removeProjectFromClasspath(); 146 147 if (BuildPathsBlock.hasClassfiles(project.getProject()) && outputLocation.equals(projPath)) { 148 String title= NewWizardMessages.BuildPathsBlock_RemoveBinariesDialog_title; 149 String message= Messages.format(NewWizardMessages.BuildPathsBlock_RemoveBinariesDialog_description, BasicElementLabels.getPathLabel(projPath, false)); 150 MessageDialog dialog= new MessageDialog(shell, title, null, message, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, 0); 151 int answer= dialog.open(); 152 switch (answer) { 153 case 0: 154 removeOldClassFiles= true; 155 break; 156 case 1: 157 removeOldClassFiles= false; 158 break; 159 default: 160 return; 161 } 162 } else { 163 removeOldClassFiles= false; 164 } 165 } else { 166 return; 167 } 168 } else { 169 removeProjectFromClasspath= false; 170 removeOldClassFiles= false; 171 newDefaultOutputLocation= defaultOutputLocation; 172 } 173 174 try { 175 final IRunnableWithProgress runnable= new IRunnableWithProgress() { 176 @Override 177 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { 178 try { 179 List<IJavaElement> result= addToClasspath(getSelectedElements(), project, newDefaultOutputLocation.makeAbsolute(), removeProjectFromClasspath, removeOldClassFiles, monitor); 180 selectAndReveal(new StructuredSelection(result)); 181 } catch (CoreException e) { 182 throw new InvocationTargetException(e); 183 } 184 } 185 }; 186 fContext.run(false, false, runnable); 187 } catch (final InvocationTargetException e) { 188 if (e.getCause() instanceof CoreException) { 189 showExceptionDialog((CoreException)e.getCause(), NewWizardMessages.AddSourceFolderToBuildpathAction_ErrorTitle); 190 } else { 191 JavaPlugin.log(e); 192 } 193 } catch (final InterruptedException e) { 194 } 195 } catch (CoreException e) { 196 showExceptionDialog(e, NewWizardMessages.AddSourceFolderToBuildpathAction_ErrorTitle); 197 } 198 } 199 addToClasspath(List<?> elements, IJavaProject project, IPath outputLocation, boolean removeProjectFromClasspath, boolean removeOldClassFiles, IProgressMonitor monitor)200 private List<IJavaElement> addToClasspath(List<?> elements, IJavaProject project, IPath outputLocation, boolean removeProjectFromClasspath, boolean removeOldClassFiles, IProgressMonitor monitor) throws OperationCanceledException, CoreException { 201 if (!project.getProject().hasNature(JavaCore.NATURE_ID)) { 202 StatusInfo rootStatus= new StatusInfo(); 203 rootStatus.setError(NewWizardMessages.ClasspathModifier_Error_NoNatures); 204 throw new CoreException(rootStatus); 205 } 206 207 try { 208 monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_AddToBuildpath, elements.size() + 4); 209 IWorkspaceRoot workspaceRoot= JavaPlugin.getWorkspace().getRoot(); 210 211 if (removeOldClassFiles) { 212 IResource res= workspaceRoot.findMember(project.getOutputLocation()); 213 if (res instanceof IContainer && BuildPathsBlock.hasClassfiles(res)) { 214 BuildPathsBlock.removeOldClassfiles(res); 215 } 216 } 217 218 BuildpathDelta delta= new BuildpathDelta(getToolTipText()); 219 220 if (!project.getOutputLocation().equals(outputLocation)) { 221 project.setOutputLocation(outputLocation, new SubProgressMonitor(monitor, 1)); 222 delta.setDefaultOutputLocation(outputLocation); 223 } else { 224 monitor.worked(1); 225 } 226 227 List<CPListElement> existingEntries= ClasspathModifier.getExistingEntries(project); 228 if (removeProjectFromClasspath) { 229 ClasspathModifier.removeFromClasspath(project, existingEntries, new SubProgressMonitor(monitor, 1)); 230 } else { 231 monitor.worked(1); 232 } 233 234 List<CPListElement> newEntries= new ArrayList<>(); 235 for (Object element : elements) { 236 CPListElement entry; 237 if (element instanceof IResource) 238 entry= ClasspathModifier.addToClasspath((IResource) element, existingEntries, newEntries, project, new SubProgressMonitor(monitor, 1)); 239 else 240 entry= ClasspathModifier.addToClasspath((IJavaElement) element, existingEntries, newEntries, project, new SubProgressMonitor(monitor, 1)); 241 newEntries.add(entry); 242 } 243 244 Set<CPListElement> modifiedSourceEntries= new HashSet<>(); 245 BuildPathBasePage.fixNestingConflicts(newEntries.toArray(new CPListElement[newEntries.size()]), existingEntries.toArray(new CPListElement[existingEntries.size()]), modifiedSourceEntries); 246 247 ClasspathModifier.setNewEntry(existingEntries, newEntries, project, new SubProgressMonitor(monitor, 1)); 248 249 ClasspathModifier.commitClassPath(existingEntries, project, new SubProgressMonitor(monitor, 1)); 250 251 delta.setNewEntries(existingEntries.toArray(new CPListElement[existingEntries.size()])); 252 informListeners(delta); 253 254 List<IJavaElement> result= new ArrayList<>(); 255 for (CPListElement newEntrie : newEntries) { 256 IClasspathEntry entry= newEntrie.getClasspathEntry(); 257 IJavaElement root; 258 if (entry.getPath().equals(project.getPath())) 259 root= project; 260 else 261 root= project.findPackageFragmentRoot(entry.getPath()); 262 if (root != null) { 263 result.add(root); 264 } 265 } 266 267 return result; 268 } finally { 269 monitor.done(); 270 } 271 } 272 273 @Override canHandle(IStructuredSelection elements)274 protected boolean canHandle(IStructuredSelection elements) { 275 if (elements.size() == 0) 276 return false; 277 try { 278 for (Object element : elements) { 279 if (element instanceof IJavaProject) { 280 if (ClasspathModifier.isSourceFolder((IJavaProject)element)) 281 return false; 282 } else if (element instanceof IPackageFragment) { 283 IPackageFragment fragment= (IPackageFragment)element; 284 if (ClasspathModifier.isDefaultFragment(fragment)) 285 return false; 286 287 if (ClasspathModifier.isInExternalOrArchive(fragment)) 288 return false; 289 IResource res; 290 if ((res= fragment.getResource()) != null && res.isVirtual()) 291 return false; 292 } else if (element instanceof IFolder) { 293 IProject project= ((IFolder)element).getProject(); 294 IJavaProject javaProject= JavaCore.create(project); 295 if (javaProject == null || !javaProject.exists() || ((IFolder)element).isVirtual()) 296 return false; 297 } else { 298 return false; 299 } 300 } 301 return true; 302 } catch (CoreException e) { 303 } 304 return false; 305 } 306 } 307