diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/IIncrementalBuildFramework.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/IIncrementalBuildFramework.java index 3af09194ae..9be6c498b5 100644 --- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/IIncrementalBuildFramework.java +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/IIncrementalBuildFramework.java @@ -17,7 +17,6 @@ import java.util.Set; import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.runtime.CoreException; @@ -45,6 +44,14 @@ public interface BuildResultCollector { Set getFiles(); } + /** + * @experimental this interface is part of work in progress and can be changed or removed without notice. + * @since 2.4 + */ + public interface BuildDelta { + boolean hasDelta(File file); + } + /** * @experimental this interface is part of work in progress and can be changed or removed without notice. * @since 1.6 @@ -53,7 +60,7 @@ public interface BuildContext { void release(); } - BuildContext setupProjectBuildContext(IProject project, int kind, IResourceDelta delta, - BuildResultCollector results) throws CoreException; + BuildContext setupProjectBuildContext(IProject project, int kind, BuildDelta delta, BuildResultCollector results) + throws CoreException; } diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/InternalBuildParticipant.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/InternalBuildParticipant.java index f062278539..43ed3258bc 100644 --- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/InternalBuildParticipant.java +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/InternalBuildParticipant.java @@ -24,7 +24,6 @@ import org.sonatype.plexus.build.incremental.BuildContext; -import org.eclipse.m2e.core.internal.builder.plexusbuildapi.AbstractEclipseBuildContext; import org.eclipse.m2e.core.project.IMavenProjectFacade; @@ -36,7 +35,7 @@ public abstract class InternalBuildParticipant { private MavenSession session; - private AbstractEclipseBuildContext buildContext; + private BuildContext buildContext; protected IMavenProjectFacade getMavenProjectFacade() { return facade; @@ -71,7 +70,7 @@ public void clean(IProgressMonitor monitor) throws CoreException { public abstract boolean callOnEmptyDelta(); - void setBuildContext(AbstractEclipseBuildContext buildContext) { + void setBuildContext(BuildContext buildContext) { this.buildContext = buildContext; } diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilderImpl.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilderImpl.java index de559785ac..f299e2467f 100644 --- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilderImpl.java +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilderImpl.java @@ -52,7 +52,9 @@ import org.eclipse.m2e.core.internal.URLConnectionCaches; import org.eclipse.m2e.core.internal.builder.BuildResultCollector.Message; import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework.BuildContext; +import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework.BuildDelta; import org.eclipse.m2e.core.internal.builder.plexusbuildapi.AbstractEclipseBuildContext; +import org.eclipse.m2e.core.internal.builder.plexusbuildapi.EclipseResourceBuildDelta; import org.eclipse.m2e.core.internal.builder.plexusbuildapi.PlexusBuildAPI; import org.eclipse.m2e.core.internal.embedder.MavenProjectMutableState; import org.eclipse.m2e.core.internal.markers.IMavenMarkerManager; @@ -65,6 +67,7 @@ public class MavenBuilderImpl { + private static Logger log = LoggerFactory.getLogger(MavenBuilderImpl.class); public static final QualifiedName BUILD_CONTEXT_KEY = new QualifiedName(IMavenConstants.PLUGIN_ID, "BuildContext"); //$NON-NLS-1$ @@ -129,7 +132,10 @@ public Set build(MavenSession session, IMavenProjectFacade projectFaca participant.setMavenProjectFacade(projectFacade); participant.setGetDeltaCallback(deltaProvider); participant.setSession(session); - participant.setBuildContext((AbstractEclipseBuildContext) incrementalContexts.get(0)); + BuildContext buildContext = incrementalContexts.get(0); + if(buildContext instanceof org.sonatype.plexus.build.incremental.BuildContext incremental) { + participant.setBuildContext(incremental); + } if(participant instanceof InternalBuildParticipant2 participant2) { participant2.setArgs(args); } @@ -223,8 +229,10 @@ private boolean hasRelevantDelta(IMavenProjectFacade projectFacade, IResourceDel private List setupProjectBuildContext(IProject project, int kind, IResourceDelta delta, IIncrementalBuildFramework.BuildResultCollector results) throws CoreException { List contexts = new ArrayList<>(); + + BuildDelta buildDelta = delta != null ? new EclipseResourceBuildDelta(delta) : null; for(IIncrementalBuildFramework framework : incrementalBuildFrameworks) { - contexts.add(framework.setupProjectBuildContext(project, kind, delta, results)); + contexts.add(framework.setupProjectBuildContext(project, kind, buildDelta, results)); } return contexts; } diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/EclipseIncrementalBuildContext.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/EclipseIncrementalBuildContext.java index 35faf2dd18..6eebcf8a97 100644 --- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/EclipseIncrementalBuildContext.java +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/EclipseIncrementalBuildContext.java @@ -14,41 +14,57 @@ package org.eclipse.m2e.core.internal.builder.plexusbuildapi; import java.io.File; +import java.io.IOException; +import java.io.OutputStream; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.runtime.Adapters; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.Scanner; +import org.sonatype.plexus.build.incremental.BuildContext; import org.sonatype.plexus.build.incremental.EmptyScanner; +import org.sonatype.plexus.build.incremental.ThreadBuildContext; import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework; +import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework.BuildDelta; +import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework.BuildResultCollector; -public class EclipseIncrementalBuildContext extends AbstractEclipseBuildContext { +public class EclipseIncrementalBuildContext implements BuildContext, IIncrementalBuildFramework.BuildContext { - private final IResourceDelta delta; + private final BuildDelta delta; + + private BuildResultCollector results; + + private Map context; + + private File baseDir; public EclipseIncrementalBuildContext(IResourceDelta delta, Map context, IIncrementalBuildFramework.BuildResultCollector results) { - super(context, results); + this(new EclipseResourceBuildDelta(delta), context, results, + delta.getResource().getProject().getLocation().toFile()); + } + + public EclipseIncrementalBuildContext(BuildDelta delta, Map context, + IIncrementalBuildFramework.BuildResultCollector results, File baseDir) { this.delta = delta; + this.context = context; + this.results = results; + this.baseDir = baseDir; } @Override public boolean hasDelta(String relPath) { - IPath path = new Path(relPath); - return hasDelta(path); - } - - protected boolean hasDelta(IPath path) { - return delta == null || path == null || delta.findMember(path) != null; + return hasDelta(new File(baseDir, relPath)); } @Override @@ -63,7 +79,7 @@ public boolean hasDelta(List relPaths) { @Override public boolean hasDelta(File file) { - return hasDelta(getRelativePath(file)); + return delta.hasDelta(file); } @Override @@ -77,6 +93,31 @@ public Scanner newDeleteScanner(File basedir) { return new ResourceDeltaScanner(reldelta, true); } + private IResourceDelta getDelta(File file) { + IResourceDelta adapt = Adapters.adapt(delta, IResourceDelta.class); + if(adapt == null) { + return null; + } + IPath relpath = getRelativePath(file); + if(relpath == null) { + return null; + } + return adapt.findMember(relpath); + } + + private IPath getRelativePath(File file) { + IResource adapt = Adapters.adapt(delta, IResource.class); + if(adapt == null) { + return null; + } + IPath basepath = adapt.getLocation(); + IPath path = Path.fromOSString(file.getAbsolutePath()); + if(!basepath.isPrefixOf(path)) { + return null; + } + return path.removeFirstSegments(basepath.segmentCount()); + } + @Override public Scanner newScanner(File basedir) { return newScanner(basedir, false); @@ -84,29 +125,21 @@ public Scanner newScanner(File basedir) { @Override public Scanner newScanner(File basedir, boolean ignoreDelta) { - if(!ignoreDelta) { - IResourceDelta reldelta = getDelta(basedir); - - if(reldelta == null || !isContentChange(reldelta)) { - return new EmptyScanner(basedir); - } - - return new ResourceDeltaScanner(reldelta, false); + DirectoryScanner ds; + if(ignoreDelta) { + ds = new DirectoryScanner(); + } else { + ds = new DirectoryScanner() { + @Override + protected boolean isSelected(String name, File file) { + return hasDelta(file); + } + }; } - - DirectoryScanner ds = new DirectoryScanner(); ds.setBasedir(basedir); return ds; } - private IResourceDelta getDelta(File file) { - IPath relpath = getRelativePath(file); - if(relpath == null) { - return null; - } - return delta.findMember(relpath); - } - static boolean isContentChange(IResourceDelta delta) { int kind = delta.getKind(); if(IResourceDelta.ADDED == kind) { @@ -141,13 +174,68 @@ static boolean isRemove(IResourceDelta delta) { } @Override - protected IResource getBaseResource() { - return delta.getResource(); + public boolean isIncremental() { + return true; } @Override - public boolean isIncremental() { - return true; + public void refresh(File file) { + results.refresh(file); + } + + @Override + public OutputStream newFileOutputStream(File file) throws IOException { + return new ChangedFileOutputStream(file, this); + } + + @Override + public void setValue(String key, Object value) { + context.put(key, value); + } + + @Override + public Object getValue(String key) { + return context.get(key); + } + + /** + * @deprecated Use addMessage instead + */ + @Deprecated + @Override + public void addError(File file, int line, int column, String message, Throwable cause) { + addMessage(file, line, column, message, BuildContext.SEVERITY_ERROR, cause); + } + + /** + * @deprecated + * @deprecated Use addMessage instead + */ + @Deprecated + @Override + public void addWarning(File file, int line, int column, String message, Throwable cause) { + addMessage(file, line, column, message, BuildContext.SEVERITY_WARNING, cause); + } + + @Override + public void addMessage(File file, int line, int column, String message, int severity, Throwable cause) { + results.addMessage(file, line, column, message, severity, cause); + } + + @Override + public void removeMessages(File file) { + results.removeMessages(file); + } + + @Override + public boolean isUptodate(File target, File source) { + return target != null && target.exists() && source != null && source.exists() + && target.lastModified() > source.lastModified(); + } + + @Override + public void release() { + ThreadBuildContext.setThreadBuildContext(null); } } diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/EclipseResourceBuildDelta.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/EclipseResourceBuildDelta.java new file mode 100644 index 0000000000..f161a0ff6e --- /dev/null +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/EclipseResourceBuildDelta.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2008-2023 Sonatype, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Sonatype, Inc. - initial API and implementation + * Christoph Läubrich - extracted and implement wrapper API + *******************************************************************************/ + +package org.eclipse.m2e.core.internal.builder.plexusbuildapi; + +import java.io.File; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework; + + +public final class EclipseResourceBuildDelta implements IIncrementalBuildFramework.BuildDelta, IAdaptable { + private final IResource resource; + + private final IResourceDelta delta; + + /** + * @param resource + * @param delta + */ + public EclipseResourceBuildDelta(IResourceDelta delta) { + this.resource = delta != null ? delta.getResource() : null; + this.delta = delta; + } + + @Override + public boolean hasDelta(File file) { + return hasDelta(getRelativePath(file)); + } + + private boolean hasDelta(IPath path) { + return path == null || this.delta.findMember(path) != null; + } + + /** + * Returns path relative to delta resource location. + */ + private IPath getRelativePath(File file) { + IPath basepath = this.resource.getLocation(); + IPath path = Path.fromOSString(file.getAbsolutePath()); + + if(!basepath.isPrefixOf(path)) { + return null; + } + + return path.removeFirstSegments(basepath.segmentCount()); + } + + @Override + public T getAdapter(Class adapter) { + if(adapter.isInstance(delta)) { + return adapter.cast(delta); + } + if(adapter.isInstance(resource)) { + return adapter.cast(resource); + } + return null; + } + +} diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/PlexusBuildAPI.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/PlexusBuildAPI.java index f2fba6c891..74f38eda23 100644 --- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/PlexusBuildAPI.java +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/PlexusBuildAPI.java @@ -21,7 +21,6 @@ import java.util.Map; import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.QualifiedName; @@ -39,13 +38,13 @@ public class PlexusBuildAPI implements IIncrementalBuildFramework { public static QualifiedName BUILD_CONTEXT_KEY = new QualifiedName(IMavenConstants.PLUGIN_ID, "BuildContext"); //$NON-NLS-1$ @Override - public AbstractEclipseBuildContext setupProjectBuildContext(IProject project, int kind, IResourceDelta delta, + public BuildContext setupProjectBuildContext(IProject project, int kind, BuildDelta delta, IIncrementalBuildFramework.BuildResultCollector results) throws CoreException { @SuppressWarnings("unchecked") Map contextState = (Map) project.getSessionProperty(BUILD_CONTEXT_KEY); - AbstractEclipseBuildContext buildContext; + BuildContext buildContext; if(delta != null && contextState != null && (INCREMENTAL_BUILD == kind || AUTO_BUILD == kind)) { - buildContext = new EclipseIncrementalBuildContext(delta, contextState, results); + buildContext = new EclipseIncrementalBuildContext(delta, contextState, results, project.getLocation().toFile()); } else if(CLEAN_BUILD == kind) { project.setSessionProperty(BUILD_CONTEXT_KEY, null); // clean context state buildContext = new EclipseBuildContext(project, new HashMap(), results); @@ -59,7 +58,7 @@ public AbstractEclipseBuildContext setupProjectBuildContext(IProject project, in buildContext = new EclipseBuildContext(project, contextState, results); } } - ThreadBuildContext.setThreadBuildContext(buildContext); + ThreadBuildContext.setThreadBuildContext((org.sonatype.plexus.build.incremental.BuildContext) buildContext); return buildContext; }