Skip to content

Commit

Permalink
Abstract the delta handling from the resource API
Browse files Browse the repository at this point in the history
Currently m2e is directly wired to the resource delta API, while this
seems good in the context of eclipse for m2e this imposes to restrictive
API as it is all noimplement/extend interfaces and offer much more than
m2e actually using.

This aims to implement a thin wrapper for further improvement of delta
detection especially when it comes to resource see for example
#1302

This will not fix anything but is an important first step to ensure
things are still working as before.
  • Loading branch information
laeubi committed Aug 1, 2023
1 parent 0e7d484 commit a4869ce
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand Down Expand Up @@ -45,6 +44,14 @@ public interface BuildResultCollector {
Set<File> 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
Expand All @@ -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;

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand All @@ -36,7 +35,7 @@ public abstract class InternalBuildParticipant {

private MavenSession session;

private AbstractEclipseBuildContext buildContext;
private BuildContext buildContext;

protected IMavenProjectFacade getMavenProjectFacade() {
return facade;
Expand Down Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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$
Expand Down Expand Up @@ -129,7 +132,10 @@ public Set<IProject> 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);
}
Expand Down Expand Up @@ -223,8 +229,10 @@ private boolean hasRelevantDelta(IMavenProjectFacade projectFacade, IResourceDel
private List<IIncrementalBuildFramework.BuildContext> setupProjectBuildContext(IProject project, int kind,
IResourceDelta delta, IIncrementalBuildFramework.BuildResultCollector results) throws CoreException {
List<IIncrementalBuildFramework.BuildContext> 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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, Object> context;

private File baseDir;

public EclipseIncrementalBuildContext(IResourceDelta delta, Map<String, Object> context,
IIncrementalBuildFramework.BuildResultCollector results) {
super(context, results);
this(new EclipseResourceBuildDelta(delta), context, results,
delta.getResource().getProject().getLocation().toFile());
}

public EclipseIncrementalBuildContext(BuildDelta delta, Map<String, Object> 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
Expand All @@ -63,7 +79,7 @@ public boolean hasDelta(List relPaths) {

@Override
public boolean hasDelta(File file) {
return hasDelta(getRelativePath(file));
return delta.hasDelta(file);
}

@Override
Expand All @@ -77,36 +93,53 @@ 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);
}

@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) {
Expand Down Expand Up @@ -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);
}

}
Original file line number Diff line number Diff line change
@@ -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> T getAdapter(Class<T> adapter) {
if(adapter.isInstance(delta)) {
return adapter.cast(delta);
}
if(adapter.isInstance(resource)) {
return adapter.cast(resource);
}
return null;
}

}
Loading

0 comments on commit a4869ce

Please sign in to comment.