Skip to content

Commit 40d3b44

Browse files
committed
Abstract the delta handling from the resource API
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.
1 parent 0e7d484 commit 40d3b44

File tree

6 files changed

+222
-45
lines changed

6 files changed

+222
-45
lines changed

org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/IIncrementalBuildFramework.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import java.util.Set;
1818

1919
import org.eclipse.core.resources.IProject;
20-
import org.eclipse.core.resources.IResourceDelta;
2120
import org.eclipse.core.runtime.CoreException;
2221

2322

@@ -45,6 +44,14 @@ public interface BuildResultCollector {
4544
Set<File> getFiles();
4645
}
4746

47+
/**
48+
* @experimental this interface is part of work in progress and can be changed or removed without notice.
49+
* @since 2.4
50+
*/
51+
public interface BuildDelta {
52+
boolean hasDelta(File file);
53+
}
54+
4855
/**
4956
* @experimental this interface is part of work in progress and can be changed or removed without notice.
5057
* @since 1.6
@@ -53,7 +60,7 @@ public interface BuildContext {
5360
void release();
5461
}
5562

56-
BuildContext setupProjectBuildContext(IProject project, int kind, IResourceDelta delta,
57-
BuildResultCollector results) throws CoreException;
63+
BuildContext setupProjectBuildContext(IProject project, int kind, BuildDelta delta, BuildResultCollector results)
64+
throws CoreException;
5865

5966
}

org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/InternalBuildParticipant.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
import org.sonatype.plexus.build.incremental.BuildContext;
2626

27-
import org.eclipse.m2e.core.internal.builder.plexusbuildapi.AbstractEclipseBuildContext;
2827
import org.eclipse.m2e.core.project.IMavenProjectFacade;
2928

3029

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

3736
private MavenSession session;
3837

39-
private AbstractEclipseBuildContext buildContext;
38+
private BuildContext buildContext;
4039

4140
protected IMavenProjectFacade getMavenProjectFacade() {
4241
return facade;
@@ -71,7 +70,7 @@ public void clean(IProgressMonitor monitor) throws CoreException {
7170

7271
public abstract boolean callOnEmptyDelta();
7372

74-
void setBuildContext(AbstractEclipseBuildContext buildContext) {
73+
void setBuildContext(BuildContext buildContext) {
7574
this.buildContext = buildContext;
7675
}
7776

org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilderImpl.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@
5252
import org.eclipse.m2e.core.internal.URLConnectionCaches;
5353
import org.eclipse.m2e.core.internal.builder.BuildResultCollector.Message;
5454
import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework.BuildContext;
55+
import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework.BuildDelta;
5556
import org.eclipse.m2e.core.internal.builder.plexusbuildapi.AbstractEclipseBuildContext;
57+
import org.eclipse.m2e.core.internal.builder.plexusbuildapi.EclipseResourceBuildDelta;
5658
import org.eclipse.m2e.core.internal.builder.plexusbuildapi.PlexusBuildAPI;
5759
import org.eclipse.m2e.core.internal.embedder.MavenProjectMutableState;
5860
import org.eclipse.m2e.core.internal.markers.IMavenMarkerManager;
@@ -65,6 +67,7 @@
6567

6668

6769
public class MavenBuilderImpl {
70+
6871
private static Logger log = LoggerFactory.getLogger(MavenBuilderImpl.class);
6972

7073
public static final QualifiedName BUILD_CONTEXT_KEY = new QualifiedName(IMavenConstants.PLUGIN_ID, "BuildContext"); //$NON-NLS-1$
@@ -129,7 +132,10 @@ public Set<IProject> build(MavenSession session, IMavenProjectFacade projectFaca
129132
participant.setMavenProjectFacade(projectFacade);
130133
participant.setGetDeltaCallback(deltaProvider);
131134
participant.setSession(session);
132-
participant.setBuildContext((AbstractEclipseBuildContext) incrementalContexts.get(0));
135+
BuildContext buildContext = incrementalContexts.get(0);
136+
if(buildContext instanceof org.sonatype.plexus.build.incremental.BuildContext incremental) {
137+
participant.setBuildContext(incremental);
138+
}
133139
if(participant instanceof InternalBuildParticipant2 participant2) {
134140
participant2.setArgs(args);
135141
}
@@ -223,8 +229,10 @@ private boolean hasRelevantDelta(IMavenProjectFacade projectFacade, IResourceDel
223229
private List<IIncrementalBuildFramework.BuildContext> setupProjectBuildContext(IProject project, int kind,
224230
IResourceDelta delta, IIncrementalBuildFramework.BuildResultCollector results) throws CoreException {
225231
List<IIncrementalBuildFramework.BuildContext> contexts = new ArrayList<>();
232+
233+
BuildDelta buildDelta = delta != null ? new EclipseResourceBuildDelta(delta) : null;
226234
for(IIncrementalBuildFramework framework : incrementalBuildFrameworks) {
227-
contexts.add(framework.setupProjectBuildContext(project, kind, delta, results));
235+
contexts.add(framework.setupProjectBuildContext(project, kind, buildDelta, results));
228236
}
229237
return contexts;
230238
}

org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/plexusbuildapi/EclipseIncrementalBuildContext.java

Lines changed: 120 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,41 +14,57 @@
1414
package org.eclipse.m2e.core.internal.builder.plexusbuildapi;
1515

1616
import java.io.File;
17+
import java.io.IOException;
18+
import java.io.OutputStream;
1719
import java.util.List;
1820
import java.util.Map;
1921

2022
import org.eclipse.core.resources.IContainer;
2123
import org.eclipse.core.resources.IResource;
2224
import org.eclipse.core.resources.IResourceDelta;
25+
import org.eclipse.core.runtime.Adapters;
2326
import org.eclipse.core.runtime.IPath;
2427
import org.eclipse.core.runtime.Path;
2528

2629
import org.codehaus.plexus.util.DirectoryScanner;
2730
import org.codehaus.plexus.util.Scanner;
2831

32+
import org.sonatype.plexus.build.incremental.BuildContext;
2933
import org.sonatype.plexus.build.incremental.EmptyScanner;
34+
import org.sonatype.plexus.build.incremental.ThreadBuildContext;
3035

3136
import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework;
37+
import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework.BuildDelta;
38+
import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework.BuildResultCollector;
3239

3340

34-
public class EclipseIncrementalBuildContext extends AbstractEclipseBuildContext {
41+
public class EclipseIncrementalBuildContext implements BuildContext, IIncrementalBuildFramework.BuildContext {
3542

36-
private final IResourceDelta delta;
43+
private final BuildDelta delta;
44+
45+
private BuildResultCollector results;
46+
47+
private Map<String, Object> context;
48+
49+
private File baseDir;
3750

3851
public EclipseIncrementalBuildContext(IResourceDelta delta, Map<String, Object> context,
3952
IIncrementalBuildFramework.BuildResultCollector results) {
40-
super(context, results);
53+
this(new EclipseResourceBuildDelta(delta), context, results,
54+
delta.getResource().getProject().getLocation().toFile());
55+
}
56+
57+
public EclipseIncrementalBuildContext(BuildDelta delta, Map<String, Object> context,
58+
IIncrementalBuildFramework.BuildResultCollector results, File baseDir) {
4159
this.delta = delta;
60+
this.context = context;
61+
this.results = results;
62+
this.baseDir = baseDir;
4263
}
4364

4465
@Override
4566
public boolean hasDelta(String relPath) {
46-
IPath path = new Path(relPath);
47-
return hasDelta(path);
48-
}
49-
50-
protected boolean hasDelta(IPath path) {
51-
return delta == null || path == null || delta.findMember(path) != null;
67+
return hasDelta(new File(baseDir, relPath));
5268
}
5369

5470
@Override
@@ -63,7 +79,7 @@ public boolean hasDelta(List relPaths) {
6379

6480
@Override
6581
public boolean hasDelta(File file) {
66-
return hasDelta(getRelativePath(file));
82+
return delta.hasDelta(file);
6783
}
6884

6985
@Override
@@ -77,36 +93,53 @@ public Scanner newDeleteScanner(File basedir) {
7793
return new ResourceDeltaScanner(reldelta, true);
7894
}
7995

96+
private IResourceDelta getDelta(File file) {
97+
IResourceDelta adapt = Adapters.adapt(delta, IResourceDelta.class);
98+
if(adapt == null) {
99+
return null;
100+
}
101+
IPath relpath = getRelativePath(file);
102+
if(relpath == null) {
103+
return null;
104+
}
105+
return adapt.findMember(relpath);
106+
}
107+
108+
private IPath getRelativePath(File file) {
109+
IResource adapt = Adapters.adapt(delta, IResource.class);
110+
if(adapt == null) {
111+
return null;
112+
}
113+
IPath basepath = adapt.getLocation();
114+
IPath path = Path.fromOSString(file.getAbsolutePath());
115+
if(!basepath.isPrefixOf(path)) {
116+
return null;
117+
}
118+
return path.removeFirstSegments(basepath.segmentCount());
119+
}
120+
80121
@Override
81122
public Scanner newScanner(File basedir) {
82123
return newScanner(basedir, false);
83124
}
84125

85126
@Override
86127
public Scanner newScanner(File basedir, boolean ignoreDelta) {
87-
if(!ignoreDelta) {
88-
IResourceDelta reldelta = getDelta(basedir);
89-
90-
if(reldelta == null || !isContentChange(reldelta)) {
91-
return new EmptyScanner(basedir);
92-
}
93-
94-
return new ResourceDeltaScanner(reldelta, false);
128+
DirectoryScanner ds;
129+
if(ignoreDelta) {
130+
ds = new DirectoryScanner();
131+
} else {
132+
ds = new DirectoryScanner() {
133+
@Override
134+
protected boolean isSelected(String name, File file) {
135+
return hasDelta(file);
136+
}
137+
};
95138
}
96-
97-
DirectoryScanner ds = new DirectoryScanner();
98139
ds.setBasedir(basedir);
99140
return ds;
100141
}
101142

102-
private IResourceDelta getDelta(File file) {
103-
IPath relpath = getRelativePath(file);
104-
if(relpath == null) {
105-
return null;
106-
}
107-
return delta.findMember(relpath);
108-
}
109-
110143
static boolean isContentChange(IResourceDelta delta) {
111144
int kind = delta.getKind();
112145
if(IResourceDelta.ADDED == kind) {
@@ -141,13 +174,68 @@ static boolean isRemove(IResourceDelta delta) {
141174
}
142175

143176
@Override
144-
protected IResource getBaseResource() {
145-
return delta.getResource();
177+
public boolean isIncremental() {
178+
return true;
146179
}
147180

148181
@Override
149-
public boolean isIncremental() {
150-
return true;
182+
public void refresh(File file) {
183+
results.refresh(file);
184+
}
185+
186+
@Override
187+
public OutputStream newFileOutputStream(File file) throws IOException {
188+
return new ChangedFileOutputStream(file, this);
189+
}
190+
191+
@Override
192+
public void setValue(String key, Object value) {
193+
context.put(key, value);
194+
}
195+
196+
@Override
197+
public Object getValue(String key) {
198+
return context.get(key);
199+
}
200+
201+
/**
202+
* @deprecated Use addMessage instead
203+
*/
204+
@Deprecated
205+
@Override
206+
public void addError(File file, int line, int column, String message, Throwable cause) {
207+
addMessage(file, line, column, message, BuildContext.SEVERITY_ERROR, cause);
208+
}
209+
210+
/**
211+
* @deprecated
212+
* @deprecated Use addMessage instead
213+
*/
214+
@Deprecated
215+
@Override
216+
public void addWarning(File file, int line, int column, String message, Throwable cause) {
217+
addMessage(file, line, column, message, BuildContext.SEVERITY_WARNING, cause);
218+
}
219+
220+
@Override
221+
public void addMessage(File file, int line, int column, String message, int severity, Throwable cause) {
222+
results.addMessage(file, line, column, message, severity, cause);
223+
}
224+
225+
@Override
226+
public void removeMessages(File file) {
227+
results.removeMessages(file);
228+
}
229+
230+
@Override
231+
public boolean isUptodate(File target, File source) {
232+
return target != null && target.exists() && source != null && source.exists()
233+
&& target.lastModified() > source.lastModified();
234+
}
235+
236+
@Override
237+
public void release() {
238+
ThreadBuildContext.setThreadBuildContext(null);
151239
}
152240

153241
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2008-2023 Sonatype, Inc.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License 2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Sonatype, Inc. - initial API and implementation
12+
* Christoph Läubrich - extracted and implement wrapper API
13+
*******************************************************************************/
14+
15+
package org.eclipse.m2e.core.internal.builder.plexusbuildapi;
16+
17+
import java.io.File;
18+
19+
import org.eclipse.core.resources.IResource;
20+
import org.eclipse.core.resources.IResourceDelta;
21+
import org.eclipse.core.runtime.IAdaptable;
22+
import org.eclipse.core.runtime.IPath;
23+
import org.eclipse.core.runtime.Path;
24+
25+
import org.eclipse.m2e.core.internal.builder.IIncrementalBuildFramework;
26+
27+
28+
public final class EclipseResourceBuildDelta implements IIncrementalBuildFramework.BuildDelta, IAdaptable {
29+
private final IResource resource;
30+
31+
private final IResourceDelta delta;
32+
33+
/**
34+
* @param resource
35+
* @param delta
36+
*/
37+
public EclipseResourceBuildDelta(IResourceDelta delta) {
38+
this.resource = delta != null ? delta.getResource() : null;
39+
this.delta = delta;
40+
}
41+
42+
@Override
43+
public boolean hasDelta(File file) {
44+
return hasDelta(getRelativePath(file));
45+
}
46+
47+
private boolean hasDelta(IPath path) {
48+
return path == null || this.delta.findMember(path) != null;
49+
}
50+
51+
/**
52+
* Returns path relative to delta resource location.
53+
*/
54+
private IPath getRelativePath(File file) {
55+
IPath basepath = this.resource.getLocation();
56+
IPath path = Path.fromOSString(file.getAbsolutePath());
57+
58+
if(!basepath.isPrefixOf(path)) {
59+
return null;
60+
}
61+
62+
return path.removeFirstSegments(basepath.segmentCount());
63+
}
64+
65+
@Override
66+
public <T> T getAdapter(Class<T> adapter) {
67+
if(adapter.isInstance(delta)) {
68+
return adapter.cast(delta);
69+
}
70+
if(adapter.isInstance(resource)) {
71+
return adapter.cast(resource);
72+
}
73+
return null;
74+
}
75+
76+
}

0 commit comments

Comments
 (0)