diff options
9 files changed, 678 insertions, 221 deletions
diff --git a/org.eclipse.m2e.refactoring/META-INF/MANIFEST.MF b/org.eclipse.m2e.refactoring/META-INF/MANIFEST.MF index 4b8c7af7..707bb2cd 100644 --- a/org.eclipse.m2e.refactoring/META-INF/MANIFEST.MF +++ b/org.eclipse.m2e.refactoring/META-INF/MANIFEST.MF @@ -25,4 +25,7 @@ Require-Bundle: org.eclipse.m2e.core;bundle-version="[0.13.0,0.14.0)", Eclipse-LazyStart: true Bundle-RequiredExecutionEnvironment: J2SE-1.5, JavaSE-1.6 -Export-Package: org.eclipse.m2e.refactoring.exclude +Export-Package: org.eclipse.m2e.refactoring.exclude;x-internal="true" +Import-Package: org.eclipse.m2e.editor.pom, + org.eclipse.search.ui.text, + org.eclipse.ui.forms.editor diff --git a/org.eclipse.m2e.refactoring/plugin.xml b/org.eclipse.m2e.refactoring/plugin.xml index 0ee236c6..651902a3 100644 --- a/org.eclipse.m2e.refactoring/plugin.xml +++ b/org.eclipse.m2e.refactoring/plugin.xml @@ -44,7 +44,7 @@ adaptable="true"> <action id="org.eclipse.m2e.projectMenu.action" class="org.eclipse.m2e.refactoring.exclude.DependencyExcludeAction" - enablesFor="1" + enablesFor="+" icon="icons/exclude.gif" label="%action.exclude1.label" menubarPath="additions"/> @@ -55,7 +55,7 @@ adaptable="true"> <action id="org.eclipse.m2e.projectMenu.action" class="org.eclipse.m2e.refactoring.exclude.DependencyExcludeAction" - enablesFor="1" + enablesFor="+" icon="icons/exclude.gif" label="%action.exclude2.label" menubarPath="additions"/> @@ -66,7 +66,7 @@ adaptable="true"> <action id="org.eclipse.m2e.projectMenu.action" class="org.eclipse.m2e.refactoring.exclude.DependencyExcludeAction" - enablesFor="1" + enablesFor="+" icon="icons/exclude.gif" label="%action.exclude3.label" menubarPath="additions"/> @@ -82,7 +82,7 @@ icon="icons/exclude.gif" style="push" menubarPath="org.eclipse.m2e.classpathMenu/open" - enablesFor="1"/> + enablesFor="+"/> <enablement> <test property="org.eclipse.m2e.hasArtifactKey"/> </enablement> @@ -96,7 +96,7 @@ icon="icons/exclude.gif" style="push" menubarPath="org.eclipse.m2e.classpathMenuWrapper/open" - enablesFor="1"/> + enablesFor="+"/> <enablement> <test property="org.eclipse.m2e.hasArtifactKey"/> </enablement> diff --git a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/AbstractPomHeirarchyRefactoring.java b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/AbstractPomHeirarchyRefactoring.java new file mode 100644 index 00000000..e6679601 --- /dev/null +++ b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/AbstractPomHeirarchyRefactoring.java @@ -0,0 +1,357 @@ +/******************************************************************************* + * Copyright (c) 2010 Sonatype, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Sonatype, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.m2e.refactoring; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.project.MavenProject; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.emf.common.command.BasicCommandStack; +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.emf.edit.provider.ComposedAdapterFactory; +import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory; +import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.CompositeChange; +import org.eclipse.ltk.core.refactoring.Refactoring; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; +import org.eclipse.ltk.core.refactoring.resource.ResourceChange; +import org.eclipse.m2e.core.MavenPlugin; +import org.eclipse.m2e.core.embedder.IMaven; +import org.eclipse.m2e.core.project.IMavenProjectFacade; +import org.eclipse.m2e.core.project.MavenProjectManager; +import org.eclipse.m2e.editor.pom.MavenPomEditor; +import org.eclipse.m2e.model.edit.pom.Model; +import org.eclipse.m2e.model.edit.pom.util.PomResourceImpl; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +public abstract class AbstractPomHeirarchyRefactoring extends Refactoring { + + public static final String PLUGIN_ID = "org.eclipse.m2e.refactoring"; + + protected IMavenProjectFacade projectFacade; + + protected EditingDomain editingDomain; + + protected Model model; + + protected IFile file; + + protected List<MavenProject> hierarchy; + + protected List<MavenProject> targets; + + private Map<IFile, Model> modelCache = new HashMap<IFile, Model>(); + + public AbstractPomHeirarchyRefactoring(IMavenProjectFacade projectFacade, Model model, EditingDomain editingDomain, IFile file) { + this.editingDomain = editingDomain; + this.file = file; + this.model = model; + this.projectFacade = projectFacade; + modelCache.put(file, model); + } + + /* + * Called to notify checkInitialConditions has been called. Should be used to reset state not perform calculations + */ + protected abstract void checkInitial(IProgressMonitor pm); + + /* + * Called to notify checkFinalConditions has been called. Should be used to reset state not perform calculations + */ + protected abstract void checkFinal(IProgressMonitor pm); + + /* + * Called during checkInitialConditions, should be used to indicate missing targets, etc. + */ + protected abstract RefactoringStatusEntry[] isReady(IProgressMonitor pm); + + /* + * Is the project a target for this refactoring + */ + protected abstract boolean isChanged(EditingDomain editingDomain, MavenProject project, IProgressMonitor pm) + throws CoreException, OperationCanceledException, IOException; + + /* + * Change associated with the MavenProject + */ + protected abstract Change getChange(MavenProject project, IProgressMonitor pm) throws CoreException; + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.Refactoring#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor) + */ + public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { + SubMonitor monitor = SubMonitor.convert(pm, 103); + try { + checkInitial(monitor.newChild(1)); + RefactoringStatus status = new RefactoringStatus(); + if(model == null && file == null) { + status.addEntry(new RefactoringStatusEntry(RefactoringStatus.FATAL, + Messages.AbstractPomHeirarchyRefactoring_noModelOrPom)); + return status; + } + loadWorkspaceAncestors(monitor.newChild(1)); + if(monitor.isCanceled()) { + throw new OperationCanceledException(); + } + + targets = new ArrayList<MavenProject>(); + for(MavenProject project : hierarchy) { + IMavenProjectFacade facade = getMavenProjectFacade(project); + if(isChanged(getEditingDomain(facade), project, monitor.newChild(100 / hierarchy.size()))) { + targets.add(project); + } + if(monitor.isCanceled()) { + throw new OperationCanceledException(); + } + } + if(targets.isEmpty()) { + status.addEntry(new RefactoringStatusEntry(RefactoringStatus.FATAL, + Messages.AbstractPomHeirarchyRefactoring_noTargets)); + } + for(RefactoringStatusEntry entry : isReady(monitor.newChild(1))) { + status.addEntry(entry); + } + return status; + } catch(IOException e) { + throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, + Messages.AbstractPomHeirarchyRefactoring_failedToLoadModel, + e)); + } finally { + monitor.done(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.Refactoring#checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor) + */ + public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { + checkFinal(pm); + return new RefactoringStatus(); + } + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.Refactoring#createChange(org.eclipse.core.runtime.IProgressMonitor) + */ + public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { + CompositeChange compositeChange = new CompositeChange(getName()); + + SubMonitor monitor = SubMonitor.convert(pm, targets.size() * 2); + try { + for(MavenProject project : targets) { + Change change = getChange(project, monitor.newChild(1)); + if(change != null) { + compositeChange.add(change); + } + if(monitor.isCanceled()) { + throw new OperationCanceledException(); + } + } + return compositeChange; + } finally { + monitor.done(); + } + } + + /* + * Get the EditingDomain for a given project + */ + protected EditingDomain getEditingDomain(IMavenProjectFacade facade) { + if(facade.getMavenProject().equals(hierarchy.get(0)) && editingDomain != null) { + return editingDomain; + } + // Check if an editor is open + MavenPomEditor editor = getOpenEditor(facade); + if(editor != null) { + return editor.getEditingDomain(); + } + // Create a fake one + List<AdapterFactoryImpl> factories = new ArrayList<AdapterFactoryImpl>(); + factories.add(new ResourceItemProviderAdapterFactory()); + factories.add(new ReflectiveItemProviderAdapterFactory()); + + ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(factories); + BasicCommandStack commandStack = new BasicCommandStack(); + return new AdapterFactoryEditingDomain(adapterFactory, // + commandStack, new HashMap<Resource, Boolean>()); + } + + private MavenPomEditor getOpenEditor(IMavenProjectFacade facade) { + for(IWorkbenchWindow window : PlatformUI.getWorkbench().getWorkbenchWindows()) { + for(IWorkbenchPage page : window.getPages()) { + for(IEditorReference editor : page.getEditorReferences()) { + if(MavenPomEditor.EDITOR_ID.equals(editor.getId())) { + IEditorPart part = editor.getEditor(false); + if(part instanceof MavenPomEditor) { + MavenPomEditor mpe = (MavenPomEditor) part; + if(facade.getPom().equals(mpe.getPomFile())) { + return mpe; + } + } + } + } + } + } + return null; + } + + /* + * Get the model associated with the Project + */ + protected Model getModel(MavenProject mavenProject) throws CoreException, IOException { + IFile pomFile = getMavenProjectFacade(mavenProject).getPom(); + Model m = modelCache.get(pomFile); + if(m == null) { + MavenPomEditor editor = getOpenEditor(getMavenProjectFacade(mavenProject)); + if(editor != null) { + m = editor.readProjectDocument(); + } else { + PomResourceImpl resource = MavenPlugin.getDefault().getMavenModelManager().loadResource(pomFile); + resource.load(Collections.EMPTY_MAP); + m = resource.getModel(); + } + modelCache.put(pomFile, m); + } + return m; + } + + protected IMavenProjectFacade getMavenProjectFacade(MavenProject mavenProject) { + return MavenPlugin.getDefault().getMavenProjectManager() + .getMavenProject(mavenProject.getGroupId(), mavenProject.getArtifactId(), mavenProject.getVersion()); + } + + protected IFile getPomFile(MavenProject project) { + IMavenProjectFacade facade = getMavenProjectFacade(project); + if(facade.equals(projectFacade)) { + return file; + } + return facade.getPom(); + } + + /* + * Get the heirarchy of parents that exist in the workspace + */ + private List<MavenProject> loadWorkspaceAncestors(IProgressMonitor progressMonitor) throws CoreException { + SubMonitor monitor = SubMonitor.convert(progressMonitor); + try { + IMaven maven = MavenPlugin.getDefault().getMaven(); + MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager(); + + MavenProject project = projectFacade.getMavenProject(); + maven.detachFromSession(project); + + hierarchy = new LinkedList<MavenProject>(); + hierarchy.add(project); + while(project.getModel().getParent() != null) { + if(monitor.isCanceled()) { + return null; + } + MavenExecutionRequest request = projectManager.createExecutionRequest(projectFacade, monitor); + project = maven.resolveParentProject(request, project, monitor); + if(getMavenProjectFacade(project) != null) { + hierarchy.add(project); + } + } + + return hierarchy; + } finally { + monitor.done(); + } + } + + /* + * Wraps a {@link org.eclipse.emf.common.command.Command} to the pom in a Resource + */ + protected static class PomResourceChange extends ResourceChange { + private Command command; + + private IFile pom; + + private EditingDomain domain; + + private PomResourceChange redo; + + private String name; + + private PomResourceChange(PomResourceChange redo, EditingDomain domain, Command command, IFile pom, String name) { + this(domain, command, pom, name); + this.redo = redo; + } + + public PomResourceChange(EditingDomain domain, Command command, IFile pom, String changes) { + this.command = command; + this.domain = domain; + this.pom = pom; + this.name = pom.getFullPath().toString() + " - " + changes; + } + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.resource.ResourceChange#getModifiedResource() + */ + protected IResource getModifiedResource() { + return pom; + } + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.Change#getName() + */ + public String getName() { + return name; + } + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.Change#perform(org.eclipse.core.runtime.IProgressMonitor) + */ + public Change perform(IProgressMonitor pm) throws CoreException { + SubMonitor monitor = SubMonitor.convert(pm, 3); + try { + Display.getDefault().syncExec(new Runnable() { + public void run() { + domain.getCommandStack().execute(command); + } + }); + monitor.worked(2); + + if(redo == null && domain.getCommandStack().canUndo()) { + redo = new PomResourceChange(this, domain, domain.getCommandStack().getUndoCommand(), pom, name); + } + monitor.worked(1); + return redo; + } finally { + monitor.done(); + } + } + } +} diff --git a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/Messages.java b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/Messages.java index 6dfe7d59..50c85711 100644 --- a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/Messages.java +++ b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/Messages.java @@ -34,6 +34,18 @@ public class Messages extends NLS { public static String ExcludeRefactoring_title; + public static String ExcludeArtifactRefactoring_failedToLocateArtifact; + + public static String AbstractPomHeirarchyRefactoring_failedToLoadModel; + + public static String ExcludeArtifactRefactoring_noArtifactsSet; + + public static String AbstractPomHeirarchyRefactoring_noModelOrPom; + + public static String AbstractPomHeirarchyRefactoring_noTargets; + + public static String ExcludeArtifactRefactoring_refactoringName; + public static String MavenRenameWizardPage_cbRenameWorkspace; public static String MavenRenameWizardPage_desc; diff --git a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/DependencyExcludeAction.java b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/DependencyExcludeAction.java index 18f4348d..b0713aa7 100644 --- a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/DependencyExcludeAction.java +++ b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/DependencyExcludeAction.java @@ -11,8 +11,14 @@ package org.eclipse.m2e.refactoring.exclude; +import java.util.ArrayList; +import java.util.List; + import org.apache.maven.artifact.Artifact; import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.internal.ui.packageview.ClassPathContainer.RequiredProjectWrapper; @@ -20,8 +26,13 @@ import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; +import org.eclipse.m2e.core.MavenPlugin; import org.eclipse.m2e.core.embedder.ArtifactKey; +import org.eclipse.m2e.core.project.IMavenProjectFacade; +import org.eclipse.m2e.core.project.MavenProjectManager; import org.eclipse.m2e.core.ui.internal.actions.SelectionUtil; +import org.eclipse.m2e.editor.pom.MavenPomEditor; +import org.eclipse.m2e.model.edit.pom.Model; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IActionDelegate; import org.eclipse.ui.IEditorPart; @@ -39,13 +50,20 @@ public class DependencyExcludeAction implements IActionDelegate { public static final String ID = "org.eclipse.m2e.refactoring.DependencyExclude"; //$NON-NLS-1$ private IFile file; - private ArtifactKey artifactKey; + + private ArtifactKey[] keys; + + private Model model; + + private IMavenProjectFacade projectFacade; + + private EditingDomain editingDomain; public void run(IAction action) { - if (artifactKey != null && file != null) { + if(keys != null && file != null) { Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); - MavenExcludeWizard wizard = new MavenExcludeWizard(file, // - artifactKey.getGroupId(), artifactKey.getArtifactId()); + ExcludeArtifactRefactoring r = new ExcludeArtifactRefactoring(projectFacade, model, editingDomain, keys, file); + MavenExcludeWizard wizard = new MavenExcludeWizard(r); try { String titleForFailedChecks = ""; //$NON-NLS-1$ RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard); @@ -58,38 +76,45 @@ public class DependencyExcludeAction implements IActionDelegate { public void selectionChanged(IAction action, ISelection selection) { file = null; - artifactKey = null; + keys = null; + model = null; + editingDomain = null; // TODO move logic into adapters if (selection instanceof IStructuredSelection) { IStructuredSelection structuredSelection = (IStructuredSelection) selection; - if(structuredSelection.size()==1) { - Object selected = structuredSelection.getFirstElement(); + + List<ArtifactKey> keys = new ArrayList<ArtifactKey>(structuredSelection.size()); + for(Object selected : structuredSelection.toArray()) { if (selected instanceof Artifact) { file = getFileFromEditor(); - artifactKey = new ArtifactKey((Artifact) selected); - + keys.add(new ArtifactKey((Artifact) selected)); + model = getModelFromEditor(); + projectFacade = getFacade(file); + editingDomain = getEditingDomain(); } else if (selected instanceof org.sonatype.aether.graph.DependencyNode) { file = getFileFromEditor(); - artifactKey = new ArtifactKey(((org.sonatype.aether.graph.DependencyNode) selected).getDependency().getArtifact()); - + keys.add(new ArtifactKey(((org.sonatype.aether.graph.DependencyNode) selected).getDependency().getArtifact())); + model = getModelFromEditor(); + projectFacade = getFacade(file); + editingDomain = getEditingDomain(); } else if (selected instanceof RequiredProjectWrapper) { RequiredProjectWrapper w = (RequiredProjectWrapper) selected; file = getFileFromProject(w.getParentClassPathContainer().getJavaProject()); - artifactKey = SelectionUtil.getType(selected, ArtifactKey.class); - + projectFacade = getFacade(file); + keys.add(SelectionUtil.getType(selected, ArtifactKey.class)); } else { - artifactKey = SelectionUtil.getType(selected, ArtifactKey.class); + keys.add(SelectionUtil.getType(selected, ArtifactKey.class)); if (selected instanceof IJavaElement) { IJavaElement el = (IJavaElement) selected; file = getFileFromProject(el.getParent().getJavaProject()); + projectFacade = getFacade(file); } - } } + this.keys = keys.toArray(new ArtifactKey[keys.size()]); } - - if (artifactKey != null && file != null) { + if(keys.length > 0 && file != null) { action.setEnabled(true); } else { action.setEnabled(false); @@ -109,4 +134,29 @@ public class DependencyExcludeAction implements IActionDelegate { return null; } + private Model getModelFromEditor() { + IEditorPart part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + if(part != null && part instanceof MavenPomEditor) { + try { + return ((MavenPomEditor) part).readProjectDocument(); + } catch(CoreException ex) { + // TODO Should we do something here, or do we not care + } + } + return null; + } + + private EditingDomain getEditingDomain() { + IEditorPart part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + if(part != null && part instanceof MavenPomEditor) { + return ((MavenPomEditor) part).getEditingDomain(); + } + return null; + } + + private IMavenProjectFacade getFacade(IFile file) { + MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager(); + return projectManager.create(file, true, new NullProgressMonitor()); + } + } diff --git a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/ExcludeArtifactRefactoring.java b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/ExcludeArtifactRefactoring.java new file mode 100644 index 00000000..34ec2c83 --- /dev/null +++ b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/ExcludeArtifactRefactoring.java @@ -0,0 +1,225 @@ +/******************************************************************************* + * Copyright (c) 2011 Sonatype, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Sonatype, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.m2e.refactoring.exclude; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.maven.project.MavenProject; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.emf.common.command.CompoundCommand; +import org.eclipse.emf.edit.command.AddCommand; +import org.eclipse.emf.edit.command.RemoveCommand; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; +import org.eclipse.m2e.core.MavenPlugin; +import org.eclipse.m2e.core.core.IMavenConstants; +import org.eclipse.m2e.core.embedder.ArtifactKey; +import org.eclipse.m2e.core.embedder.MavenModelManager; +import org.eclipse.m2e.core.project.IMavenProjectFacade; +import org.eclipse.m2e.model.edit.pom.Dependency; +import org.eclipse.m2e.model.edit.pom.Exclusion; +import org.eclipse.m2e.model.edit.pom.Model; +import org.eclipse.m2e.model.edit.pom.PomPackage; +import org.eclipse.m2e.model.edit.pom.impl.PomFactoryImpl; +import org.eclipse.m2e.refactoring.AbstractPomHeirarchyRefactoring; +import org.eclipse.m2e.refactoring.Messages; +import org.eclipse.osgi.util.NLS; +import org.sonatype.aether.artifact.Artifact; +import org.sonatype.aether.graph.DependencyNode; +import org.sonatype.aether.graph.DependencyVisitor; +import org.sonatype.aether.util.artifact.JavaScopes; + + +public class ExcludeArtifactRefactoring extends AbstractPomHeirarchyRefactoring { + + private final ArtifactKey[] keys; + + private Map<MavenProject, Change> changeMap; + + private Set<ArtifactKey> locatedKeys; + + public ExcludeArtifactRefactoring(IMavenProjectFacade projectFacade, Model model, EditingDomain editingDomain, + ArtifactKey[] keys, IFile pom) { + super(projectFacade, model, editingDomain, pom); + this.keys = keys; + } + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.Refactoring#getName() + */ + public String getName() { + StringBuilder builder = new StringBuilder(); + for(ArtifactKey key : keys) { + builder.append(key.toString()).append(", "); + } + builder.delete(builder.length() - 2, builder.length()); + return NLS.bind(Messages.ExcludeArtifactRefactoring_refactoringName, builder.toString()); + } + + protected boolean isChanged(final EditingDomain editingDomain, final MavenProject project, + final IProgressMonitor progressMonitor) throws CoreException, + OperationCanceledException, IOException { + final SubMonitor monitor = SubMonitor.convert(progressMonitor); + final Model m = getModel(project); + final List<Dependency> deps = m.getDependencies(); + final IStatus[] status = new IStatus[1]; + final CompoundCommand exclusionCommand = new CompoundCommand(); + final List<Dependency> toRemove = new ArrayList<Dependency>(); + + final StringBuilder msg = new StringBuilder(); + + MavenModelManager modelManager = MavenPlugin.getDefault().getMavenModelManager(); + DependencyNode root = modelManager.readDependencyTree(project, JavaScopes.TEST, monitor.newChild(1)); + root.accept(new DependencyVisitor() { + + private int depth; + + private DependencyNode topLevel; + + public boolean visitLeave(DependencyNode node) { + depth-- ; + return status[0] == null; + } + + public boolean visitEnter(DependencyNode node) { + if(depth == 1) { + topLevel = node; + } + depth++ ; + + if(node.getDependency() != null) { + Artifact a = node.getDependency().getArtifact(); + for(ArtifactKey key : keys) { + if(a.getGroupId().equals(key.getGroupId()) && a.getArtifactId().equals(key.getArtifactId())) { + if(topLevel == null) { + // do not touch itself + } else if(node == topLevel) { + msg.append(key.toString()).append(','); + // need to remove top-level dependency + toRemove.add(findDependency(topLevel)); + locatedKeys.add(key); + } else { + // need to add exclusion to top-level dependency + Dependency dependency = findDependency(topLevel); + if(dependency == null) { + status[0] = new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, NLS.bind( + Messages.ExcludeRefactoring_error_parent, topLevel.getDependency().getArtifact().getGroupId(), + topLevel.getDependency().getArtifact().getArtifactId())); + } else { + addExclusion(exclusionCommand, dependency, key); + locatedKeys.add(key); + } + } + return false; + } + } + } + + return true; + } + + private void addExclusion(CompoundCommand command, Dependency dep, ArtifactKey key) { + Exclusion exclusion = PomFactoryImpl.eINSTANCE.createExclusion(); + exclusion.setArtifactId(key.getArtifactId()); + exclusion.setGroupId(key.getGroupId()); + command.append(AddCommand.create(editingDomain, dep, + PomPackage.eINSTANCE.getDependency_Exclusions(), exclusion)); + msg.append(key.toString()).append(','); + } + + private Dependency findDependency(String groupId, String artifactId) { + for(Dependency d : deps) { + if(d.getGroupId().equals(groupId) && d.getArtifactId().equals(artifactId)) { + return d; + } + } + return null; + } + + private Dependency findDependency(DependencyNode node) { + Artifact artifact; + if(node.getRelocations().isEmpty()) { + artifact = node.getDependency().getArtifact(); + } else { + artifact = node.getRelocations().get(0); + } + return findDependency(artifact.getGroupId(), artifact.getArtifactId()); + } + }); + + for(Dependency remove : toRemove) { + exclusionCommand.append(RemoveCommand.create(editingDomain, remove)); + } +// for(Iterator<Dependency> rem = toRemove.iterator(); rem.hasNext();) { +// RemoveCommand.create(editingDomain, model, null, rem.next()); +// exclusionCommand.append(new RemoveCommand(editingDomain, model.getDependencies(), rem.next())); +// } + if(!exclusionCommand.isEmpty()) { + changeMap.put(project, new PomResourceChange(editingDomain, exclusionCommand, getPomFile(project),// + msg.delete(msg.length() - 1, msg.length()).toString())); + } + return !exclusionCommand.isEmpty(); + } + + /* (non-Javadoc) + * @see org.eclipse.m2e.refactoring.exclude.AbstractRefactoring#isReady(org.eclipse.core.runtime.IProgressMonitor) + */ + protected RefactoringStatusEntry[] isReady(IProgressMonitor pm) { + if(keys == null || keys.length == 0) { + return new RefactoringStatusEntry[] {new RefactoringStatusEntry(RefactoringStatus.FATAL, + Messages.ExcludeArtifactRefactoring_noArtifactsSet)}; + } + List<RefactoringStatusEntry> entries = new ArrayList<RefactoringStatusEntry>(); + for (ArtifactKey key : keys) { + if (!locatedKeys.contains(key)) { + entries.add(new RefactoringStatusEntry(RefactoringStatus.FATAL, NLS.bind( + Messages.ExcludeArtifactRefactoring_failedToLocateArtifact, key.toString()))); + } + } + return entries.toArray(new RefactoringStatusEntry[entries.size()]); + } + + /* (non-Javadoc) + * @see org.eclipse.m2e.refactoring.AbstractRefactoring#getChange(org.apache.maven.project.MavenProject, org.eclipse.core.runtime.IProgressMonitor) + */ + protected Change getChange(MavenProject project, IProgressMonitor pm) { + return changeMap.get(project); + } + + /* (non-Javadoc) + * @see org.eclipse.m2e.refactoring.AbstractPomHeirarchyRefactoring#checkInitial(org.eclipse.core.runtime.IProgressMonitor) + */ + protected void checkInitial(IProgressMonitor pm) { + locatedKeys = new HashSet<ArtifactKey>(keys.length); + changeMap = new HashMap<MavenProject, Change>(); + } + + /* (non-Javadoc) + * @see org.eclipse.m2e.refactoring.AbstractPomHeirarchyRefactoring#checkFinal(org.eclipse.core.runtime.IProgressMonitor) + */ + protected void checkFinal(IProgressMonitor pm) { + // Do nothing + } +}
\ No newline at end of file diff --git a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/ExcludeRefactoring.java b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/ExcludeRefactoring.java deleted file mode 100644 index a0524178..00000000 --- a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/ExcludeRefactoring.java +++ /dev/null @@ -1,195 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008-2010 Sonatype, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Sonatype, Inc. - initial API and implementation - *******************************************************************************/ - -package org.eclipse.m2e.refactoring.exclude; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.core.runtime.Status; -import org.eclipse.emf.common.command.CompoundCommand; -import org.eclipse.emf.edit.command.AddCommand; -import org.eclipse.emf.edit.command.RemoveCommand; -import org.eclipse.ltk.core.refactoring.RefactoringStatus; -import org.eclipse.m2e.core.MavenPlugin; -import org.eclipse.m2e.core.core.IMavenConstants; -import org.eclipse.m2e.core.embedder.MavenModelManager; -import org.eclipse.m2e.model.edit.pom.Dependency; -import org.eclipse.m2e.model.edit.pom.Exclusion; -import org.eclipse.m2e.model.edit.pom.Model; -import org.eclipse.m2e.model.edit.pom.impl.PomFactoryImpl; -import org.eclipse.m2e.refactoring.AbstractPomRefactoring; -import org.eclipse.m2e.refactoring.Messages; -import org.eclipse.m2e.refactoring.PomRefactoringException; -import org.eclipse.m2e.refactoring.PomVisitor; -import org.eclipse.m2e.refactoring.RefactoringModelResources; -import org.eclipse.osgi.util.NLS; -import org.sonatype.aether.artifact.Artifact; -import org.sonatype.aether.graph.DependencyNode; -import org.sonatype.aether.graph.DependencyVisitor; -import org.sonatype.aether.util.artifact.JavaScopes; - - -/** - * Exclude artifact refactoring implementation - * - * @author Anton Kraev - */ -public class ExcludeRefactoring extends AbstractPomRefactoring { - - private String excludedArtifactId; - - private String excludedGroupId; - - /** - * @param file - */ - public ExcludeRefactoring(IFile file, String excludedGroupId, String excludedArtifactId) { - super(file); - this.excludedGroupId = excludedGroupId; - this.excludedArtifactId = excludedArtifactId; - } - - public PomVisitor getVisitor() { - return new PomVisitor() { - - public CompoundCommand applyChanges(RefactoringModelResources resources, IProgressMonitor pm) - throws CoreException, IOException { - final CompoundCommand command = new CompoundCommand(); - - final List<Dependency> toRemove = new ArrayList<Dependency>(); - - Model model = resources.getTmpModel(); - - final List<Dependency> deps = model.getDependencies(); - - final IStatus[] status = new IStatus[] {null}; - - pm.beginTask(Messages.ExcludeRefactoring_task_loading, 1); - MavenModelManager modelManager = MavenPlugin.getDefault().getMavenModelManager(); - DependencyNode root = modelManager.readDependencyTree(resources.getPomFile(), JavaScopes.TEST, pm); - pm.worked(1); - root.accept(new DependencyVisitor() { - - private Dependency findDependency(String groupId, String artifactId) { - for(Dependency d : deps) { - if(d.getGroupId().equals(groupId) && d.getArtifactId().equals(artifactId)) { - return d; - } - } - return null; - } - - private Dependency findDependency(DependencyNode node) { - Artifact artifact; - if(node.getRelocations().isEmpty()) { - artifact = node.getDependency().getArtifact(); - } else { - artifact = node.getRelocations().get(0); - } - return findDependency(artifact.getGroupId(), artifact.getArtifactId()); - } - - private int depth; - - private DependencyNode topLevel; - - private Set<Dependency> excluded = new HashSet<Dependency>(); - - public boolean visitLeave(DependencyNode node) { - depth-- ; - return status[0] == null; - } - - public boolean visitEnter(DependencyNode node) { - if(depth == 1) { - topLevel = node; - } - depth++ ; - - if(node.getDependency() != null) { - Artifact a = node.getDependency().getArtifact(); - if(a.getGroupId().equals(excludedGroupId) && a.getArtifactId().equals(excludedArtifactId)) { - if(topLevel == null) { - // do not touch itself - } else if(node == topLevel) { - // need to remove top-level dependency - toRemove.add(findDependency(topLevel)); - } else { - // need to add exclusion to top-level dependency - Dependency dependency = findDependency(topLevel); - if(dependency == null) { - status[0] = new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, NLS.bind(Messages.ExcludeRefactoring_error_parent, - topLevel.getDependency().getArtifact().getGroupId(), - topLevel.getDependency().getArtifact().getArtifactId())); - } - if(excluded.add(dependency)) { - addExclusion(command, dependency); - } - } - return false; - } - } - - return true; - } - - }); - - if(status[0] != null) { - throw new PomRefactoringException(status[0]); - } - - for(Iterator<Dependency> rem = toRemove.iterator(); rem.hasNext();) { - command.append(new RemoveCommand(editingDomain, model.getDependencies(), rem.next())); - } - - // XXX scan management as well - - return command; - } - - private void addExclusion(CompoundCommand command, Dependency dep) { - Exclusion exclusion = PomFactoryImpl.eINSTANCE.createExclusion(); - exclusion.setArtifactId(excludedArtifactId); - exclusion.setGroupId(excludedGroupId); - command.append(new AddCommand(editingDomain, dep.getExclusions(), exclusion)); - } - }; - } - - public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { - return new RefactoringStatus(); - } - - public String getName() { - return Messages.ExcludeRefactoring_name; - } - - public String getTitle() { - return NLS.bind(Messages.ExcludeRefactoring_title, new Object[] {excludedGroupId, excludedArtifactId, file.getParent().getName()}); - } - - public boolean scanAllArtifacts() { - //do not scan other artifacts - return false; - } - -} diff --git a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/MavenExcludeWizard.java b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/MavenExcludeWizard.java index 8bfd857a..f707929f 100644 --- a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/MavenExcludeWizard.java +++ b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/exclude/MavenExcludeWizard.java @@ -11,7 +11,6 @@ package org.eclipse.m2e.refactoring.exclude; -import org.eclipse.core.resources.IFile; import org.eclipse.ltk.ui.refactoring.RefactoringWizard; @@ -20,8 +19,8 @@ import org.eclipse.ltk.ui.refactoring.RefactoringWizard; */ public class MavenExcludeWizard extends RefactoringWizard { - public MavenExcludeWizard(IFile file, String excludedGroupId, String excludedArtifactId) { - super(new ExcludeRefactoring(file, excludedGroupId, excludedArtifactId), DIALOG_BASED_USER_INTERFACE); + public MavenExcludeWizard(ExcludeArtifactRefactoring refactoring) { + super(refactoring, DIALOG_BASED_USER_INTERFACE); } @Override diff --git a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/messages.properties b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/messages.properties index 6c4053d5..f8a24e98 100644 --- a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/messages.properties +++ b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/messages.properties @@ -5,6 +5,12 @@ ExcludeRefactoring_error_parent=Parent dependency not found for {0}:{1} ExcludeRefactoring_name=Exclude Maven Artifact ExcludeRefactoring_task_loading=Loading dependency tree ExcludeRefactoring_title=Excluding {0}:{1} from {2} +AbstractPomHeirarchyRefactoring_failedToLoadModel=Failed to load model +ExcludeArtifactRefactoring_failedToLocateArtifact=Failed to locate: {0} +ExcludeArtifactRefactoring_noArtifactsSet=No Artifacts to exclude +AbstractPomHeirarchyRefactoring_noModelOrPom=Model does not exist +AbstractPomHeirarchyRefactoring_noTargets=No pom found for operation +ExcludeArtifactRefactoring_refactoringName=Exclude Artifacts: {0} MavenRenameWizardPage_cbRenameWorkspace=&Rename Eclipse project in Workspace MavenRenameWizardPage_desc=Specify new group Id, artifact Id or version MavenRenameWizardPage_lblArtifactId=&Artifact Id: |