From 94aa2ddd90fb6075de6d4d3217ae7499019c48d0 Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Wed, 25 Oct 2023 20:00:20 +0200 Subject: [PATCH 1/8] Revert "Priming build and reload improvements." This reverts commit 409740b82f24d8c243ac4550023d7bb25611f7b1. --- .github/workflows/main.yml | 2 +- .../nbcode/integration/maven.properties | 1 - java/maven/apichanges.xml | 14 - java/maven/build.xml | 3 +- java/maven/nbproject/project.properties | 2 +- .../modules/maven/NbArtifactFixer.java | 49 -- .../modules/maven/NbMavenProjectImpl.java | 182 +----- .../modules/maven/api/NbMavenProject.java | 54 +- .../AbstractProjectClassPathImpl.java | 9 - .../classpath/ClassPathProviderImpl.java | 2 - .../maven/classpath/CompileClassPathImpl.java | 7 +- .../maven/customizer/BasicInfoPanel.java | 4 - .../execute/MavenCommandLineExecutor.java | 15 +- .../modules/maven/execute/ReactorChecker.java | 12 +- .../maven/modelcache/MavenProjectCache.java | 223 +++---- .../maven/nodes/AddDependencyPanel.java | 3 - .../problems/MavenModelProblemsProvider.java | 11 +- .../maven/problems/ProblemReporterImpl.java | 2 +- .../maven/problems/SanityBuildAction.java | 17 +- .../spi/newproject/CreateProjectBuilder.java | 2 +- .../projects/multiproject/democa/.gitignore | 15 - .../data/projects/multiproject/democa/LICENSE | 201 ------ .../projects/multiproject/democa/lib/pom.xml | 198 ------ .../projects/multiproject/democa/oci/pom.xml | 253 -------- .../data/projects/multiproject/democa/pom.xml | 50 -- .../maven/NbMavenProjectImpl2Test.java | 597 ------------------ .../modules/maven/NbMavenProjectImplTest.java | 3 - .../maven/execute/MavenExecMonitor.java | 50 -- .../modules/maven/execute/MockMavenExec.java | 23 +- .../maven/problems/PrimingActionTest.java | 14 +- .../actions/ProvidedConfigurationsTest.java | 7 +- 31 files changed, 142 insertions(+), 1883 deletions(-) delete mode 100644 java/maven/test/unit/data/projects/multiproject/democa/.gitignore delete mode 100644 java/maven/test/unit/data/projects/multiproject/democa/LICENSE delete mode 100644 java/maven/test/unit/data/projects/multiproject/democa/lib/pom.xml delete mode 100644 java/maven/test/unit/data/projects/multiproject/democa/oci/pom.xml delete mode 100644 java/maven/test/unit/data/projects/multiproject/democa/pom.xml delete mode 100644 java/maven/test/unit/src/org/netbeans/modules/maven/NbMavenProjectImpl2Test.java delete mode 100644 java/maven/test/unit/src/org/netbeans/modules/maven/execute/MavenExecMonitor.java diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 321a2450faf5..13521bf848dd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -758,7 +758,7 @@ jobs: timeout-minutes: 60 strategy: matrix: - java: [ '11', '17' ] + java: [ '11' ] steps: - name: Set up JDK ${{ matrix.java }} diff --git a/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/maven.properties b/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/maven.properties index 22eaeaae63d3..aca469984308 100644 --- a/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/maven.properties +++ b/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/maven.properties @@ -17,4 +17,3 @@ primingBuild.snapshot.goals=install primingBuild.regular.goals=install -skipTests=true diff --git a/java/maven/apichanges.xml b/java/maven/apichanges.xml index eb9cc37425b9..8854fb3799e7 100644 --- a/java/maven/apichanges.xml +++ b/java/maven/apichanges.xml @@ -83,20 +83,6 @@ is the proper place. - - - Support for partially loaded projects - - - - - - Added a - getPratialProject that returns potentially incompletely loaded project instead of a mocked-up fallback (see isErrorPlaceholder(). - Also added a isIncomplete() check that checks project's status. - - - diff --git a/java/maven/build.xml b/java/maven/build.xml index 1cfa92a1a7d3..6bd5eb7fd1a7 100644 --- a/java/maven/build.xml +++ b/java/maven/build.xml @@ -99,8 +99,7 @@ - - + diff --git a/java/maven/nbproject/project.properties b/java/maven/nbproject/project.properties index f20d64491d08..871f4bacb8d7 100644 --- a/java/maven/nbproject/project.properties +++ b/java/maven/nbproject/project.properties @@ -22,7 +22,7 @@ javadoc.apichanges=${basedir}/apichanges.xml javadoc.arch=${basedir}/arch.xml javahelp.hs=maven.hs extra.module.files=maven-nblib/ -spec.version.base=2.161.0 +spec.version.base=2.160.0 # The CPExtender test fails in library processing (not randomly) since NetBeans 8.2; disabling. test.excludes=**/CPExtenderTest.class diff --git a/java/maven/src/org/netbeans/modules/maven/NbArtifactFixer.java b/java/maven/src/org/netbeans/modules/maven/NbArtifactFixer.java index 0d8e7ae2cff7..e44c2ffc5812 100644 --- a/java/maven/src/org/netbeans/modules/maven/NbArtifactFixer.java +++ b/java/maven/src/org/netbeans/modules/maven/NbArtifactFixer.java @@ -27,7 +27,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.maven.artifact.DefaultArtifact; @@ -106,10 +105,6 @@ public class NbArtifactFixer implements ArtifactFixer { //instead of workarounds down the road, we set the artifact's file here. // some stacktraces to maven/aether do set it after querying our code, but some don't for reasons unknown to me. artifact.setFile(f); - Set s = CAPTURE_FAKE_ARTIFACTS.get(); - if (s != null) { - s.add(artifact); - } return f; } catch (IOException x) { Exceptions.printStackTrace(x); @@ -154,48 +149,4 @@ private static synchronized File createFallbackPOM(String groupId, String artifa return fallbackPOM; } - public interface ExceptionCallable { - public T call() throws E; - } - - @SuppressWarnings("unchecked") - private static void sneakyThrow(Throwable exception) throws T { - throw (T) exception; - } - - /** - * Collects faked artifacts, which would be otherwise hidden in maven infrastructure. The value is only valid during {@link #collectFallbackArtifacts}, which - * can be invoked recursively. - */ - private static ThreadLocal> CAPTURE_FAKE_ARTIFACTS = new ThreadLocal>(); - - /** - * Performs an operation and collects forged artifacts created during that operation. The invocation can be nested; each invocation gets only artifacts from its own 'level', - * not those from possible nested invocations. The function passes on all runtime exceptions and checked exception thrown by the operation. - * - * @param value produced by the executed operation - * @param exception thrown from the operation - * @param code the operation to call and monitor - * @param collector callback that will get collected artifacts. - * @return - * @throws E - */ - public static T collectFallbackArtifacts(ExceptionCallable code, Consumer> collector) throws E { - Set save = CAPTURE_FAKE_ARTIFACTS.get(); - try { - CAPTURE_FAKE_ARTIFACTS.set(new HashSet<>()); - return code.call(); - } catch (Error | RuntimeException r) { - throw r; - } catch (Exception ex) { - sneakyThrow(ex); - // unreachable - throw new Error(); - } finally { - if (collector != null) { - collector.accept(CAPTURE_FAKE_ARTIFACTS.get()); - } - CAPTURE_FAKE_ARTIFACTS.set(save); - } - } } diff --git a/java/maven/src/org/netbeans/modules/maven/NbMavenProjectImpl.java b/java/maven/src/org/netbeans/modules/maven/NbMavenProjectImpl.java index 4fa076bc0c37..d8a0bedca2d3 100644 --- a/java/maven/src/org/netbeans/modules/maven/NbMavenProjectImpl.java +++ b/java/maven/src/org/netbeans/modules/maven/NbMavenProjectImpl.java @@ -41,6 +41,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.WeakHashMap; @@ -55,6 +56,7 @@ import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.cli.MavenCli; import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.execution.MavenExecutionResult; import org.apache.maven.model.Model; import org.apache.maven.model.Resource; import org.apache.maven.model.building.ModelBuildingException; @@ -107,7 +109,6 @@ import org.openide.util.Lookup; import org.openide.util.NbBundle.Messages; import org.openide.util.NbCollections; -import org.openide.util.Pair; import org.openide.util.RequestProcessor; import org.openide.util.Utilities; import org.openide.util.WeakListeners; @@ -133,14 +134,6 @@ public final class NbMavenProjectImpl implements Project { private final RequestProcessor.Task reloadTask = RELOAD_RP.create(new Runnable() { @Override public void run() { - if (LOG.isLoggable(Level.FINE)) { - MavenProject x; - synchronized (NbMavenProjectImpl.this) { - x = project == null ? null : project.get(); - } - LOG.log(Level.FINE, "Project {0} starting reload. Currentproject is: {1}", - new Object[] { System.identityHashCode(x == null ? this : x ), x }); - } problemReporter.clearReports(); //#167741 -this will trigger node refresh? MavenProject prj = loadOriginalMavenProject(true); MavenProject old; @@ -310,15 +303,6 @@ public String getHintJavaPlatform() { */ //TODO revisit usage, eventually should be only reuse MavenProjectCache public @NonNull MavenProject loadMavenProject(MavenEmbedder embedder, List activeProfiles, Properties properties) { - ProjectActionContext.Builder b = ProjectActionContext.newBuilder(this). - withProfiles(activeProfiles); - for (String pn : properties.stringPropertyNames()) { - b.withProperty(pn, properties.getProperty(pn)); - } - - return MavenProjectCache.loadMavenProject(projectFile, - b.context(), null); - /* try { MavenExecutionRequest req = embedder.createMavenExecutionRequest(); req.addActiveProfiles(activeProfiles); @@ -356,7 +340,6 @@ public String getHintJavaPlatform() { LOG.log(Level.INFO, "Runtime exception thrown while loading maven project at " + getProjectDirectory(), exc); //NOI18N } return MavenProjectCache.getFallbackProject(this.getPOMFile()); - */ } /** @@ -391,8 +374,7 @@ public MavenProject loadParentOf(MavenEmbedder embedder, MavenProject project) t request.setRepositorySession(maven.newRepositorySession(req)); if (project.getParentFile() != null) { - req.setPom(project.getParentFile()); - parent = MavenProjectCache.loadOriginalMavenProjectInternal(embedder, req); + parent = builder.build(project.getParentFile(), request).getProject(); } else if (project.getModel().getParent() != null) { parent = builder.build(project.getParentArtifact(), request).getProject(); } @@ -426,21 +408,6 @@ public Map createSystemPropsForPropertyExpres public Map createUserPropsForPropertyExpressions() { return NbCollections.checkedMapByCopy(configProvider.getActiveConfiguration().getProperties(), String.class, String.class, true); } - - /** - * Returns the current parsed project state. May return {@code null}, if the project was never loaded or expired from the cache, but - * never blocks on Maven infrastructure and is very fast. - * @return current project or {@code null} - */ - @CheckForNull - public MavenProject getOriginalMavenProjectOrNull() { - synchronized (this) { - if (project == null) { - return null; - } - return project.get(); - } - } /** * getter for the maven's own project representation.. this instance is cached but gets reloaded @@ -468,8 +435,7 @@ public MavenProject getOriginalMavenProjectOrNull() { } /** - * Returns the original project, or waits for reload task if already pending. Use with care, as - * the method blocks until the project reload eventually finishes in the reload thread / RP. + * Returns the original project, or waits for reload task if already pending. * @return possibly reloaded Maven project. */ public MavenProject getFreshOriginalMavenProject() { @@ -578,6 +544,12 @@ void stopHardReferencingMavenPoject() { model = null; } newproject = MavenProjectCache.getMavenProject(this.getPOMFile(), reload); + if (newproject == null) { //null when no pom.xml in project folder.. + newproject = MavenProjectCache.getFallbackProject(projectFile); + LOG.log(Level.FINE, "Project {0} going to fallback, with packaging: {1}", new Object[] { getPOMFile(), newproject.getPackaging() }); + } + final MavenExecutionResult res = MavenProjectCache.getExecutionResult(newproject); + final MavenProject np = newproject; } finally { if (LOG.isLoggable(Level.FINE) && SwingUtilities.isEventDispatchThread()) { LOG.log(Level.FINE, "Project " + getProjectDirectory().getPath() + " loaded in AWT event dispatching thread!", new RuntimeException()); @@ -587,141 +559,29 @@ void stopHardReferencingMavenPoject() { return newproject; } - /** - * Task that potential project reloads should wait on. If set, a {@link fireProjectReload}(true) will be scheduled only after this blocker finishes. - */ - // @GuardedBy(this) - private List blockingList = new ArrayList<>(); - - /** - * Task, that will be returned if the reload is blocked. Needed as an existing available reload task instance is finished before it is scheduled again. - */ - // @GuardedBy(this) - private RequestProcessor.Task reloadCompletionTask; - - // tests only ! - synchronized Pair, RequestProcessor.Task> reloadBlockingState() { - return Pair.of(new ArrayList<>(this.blockingList), this.reloadCompletionTask); - } - - // tests only ! - RequestProcessor.Task getReloadTask() { - return reloadTask; - } - - /** - * Schedules project operation that delays potential reloads. If a reload is posted, it will be performed only after - * this operation compeltes (successfully, or erroneously). Multiple project operations can be scheduled, an eventual project reload - * should happen after all those operations complete. It is possible to postpone project reload indefinitely, avoid unnecessary - * operation schedules. - *

- * To avoid race condition on task startup, this method actually creates and schedules the task so it blocks reloads from its inception. - * It returns the value of the worker task as the result value. - * wrapper. - * @param rp request processor that should schedule the task - * @param delay optional delay, use 0 for immediate run - * @param r operation to run - * @return the scheduled task - */ - public RequestProcessor.Task scheduleProjectOperation(RequestProcessor rp, Runnable r, int delay) { - RequestProcessor.Task t = rp.create(r); - if (Boolean.getBoolean("test.reload.sync")) { - LOG.log(Level.FINE, "Running the blocking task synchronously (test.reload.sync set)"); - t.run(); - return t; - } else { - synchronized (this) { - blockingList.add(t); - if (LOG.isLoggable(Level.FINER)) { - LOG.log(Level.FINER, "Blocking project reload on task {0}, blocking queue: {1}", new Object[] { t, blockingList }); - } - t.addTaskListener((e) -> { - synchronized (this) { - blockingList.remove(t); - if (!blockingList.isEmpty()) { - LOG.log(Level.FINER, "Project {0} task {1} finished, still blocked", new Object[] { this, t }); - return; - } - if (reloadCompletionTask == null) { - LOG.log(Level.FINER, "Project {0} task {1} finished, no reload requested", new Object[] { this, t }); - return; - } - } - LOG.log(Level.FINER, "Project {0} task {1} finished, project reload released", new Object[] { this, t }); - fireProjectReload(true); - }); - } - t.schedule(delay); - return t; - } - } - + + public RequestProcessor.Task fireProjectReload() { - return fireProjectReload(false); - } - - /** - * Schedules project reload. If `waitForBlockers` is true and {@link #scheduleProjectOperation} registered some task(s), project reload - * will be postponed until after those task(s) finish. The returned task completes after the project reload itself completes (after the potential - * delays). - *

- * As a result of project's reload, child projects may be reloaded, but the returned task does not wait for children reload to complete. - * - * @param waitForBlockers - * @return the task that completes after project reloads. - */ - public RequestProcessor.Task fireProjectReload(boolean waitForBlockers) { //#227101 not only AWT and project read/write mutex has to be checked, there are some additional more //complex scenarios that can lead to deadlock. Just give up and always fire changes in separate RP. if (Boolean.getBoolean("test.reload.sync")) { reloadTask.run(); //for tests just do sync reload, even though silly, even sillier is to attempt to sync the threads.. } else { - synchronized (this) { - if (blockingList.isEmpty()) { - RequestProcessor.Task fin; - - fin = this.reloadCompletionTask; - reloadCompletionTask = null; - LOG.log(Level.FINER, "Project {0} reload scheduled, no blockers", this ); - reloadTask.schedule(0); - if (fin != null) { - reloadTask.addTaskListener((e) -> { - fin.run(); - }); - } - } else if (waitForBlockers) { - LOG.log(Level.FINER, "Project {0} reload blocked, blockers: {1}", new Object[] { this, blockingList }); - if (reloadCompletionTask == null) { - reloadCompletionTask = RELOAD_RP.create(() -> {}); - } - return reloadCompletionTask; - } else { - // potentially reload will happen again, after all blocking tasks will complete. - LOG.log(Level.FINER, "Project {0} reload forced, blockers: {1}, completion task: {2}", new Object[] { this, blockingList, reloadCompletionTask }); - reloadTask.schedule(0); - } - } + reloadTask.schedule(0); //asuming here that schedule(0) will move the scheduled task in the queue if not yet executed } return reloadTask; } private void reloadPossibleBrokenModules(MavenProject preceding, MavenProject p) { - LOG.log(Level.FINE, "Recovery for project {2}, preceding: {0}, current: {1}, ", - new Object[] { preceding == null ? -1 : System.identityHashCode(preceding), System.identityHashCode(p), p }); // restrict to just poms that were marked as broken/incomplete. - if (!(MavenProjectCache.isIncompleteProject(preceding) || + if (!(MavenProjectCache.isFallbackproject(preceding) || // the project is tagged by Boolean.TRUE, if a SanityBuildAction was created for it. preceding.getContextValue("org.netbeans.modules.maven.problems.primingNotDone") == Boolean.TRUE)) { - LOG.log(Level.FINER, "Project is not fallbach: {0}, {1}", new Object[] { - MavenProjectCache.isIncompleteProject(preceding), - preceding.getContextValue("org.netbeans.modules.maven.problems.primingNotDone") - }); return; } // but do not cascade from projects, which are themselves broken. if (MavenProjectCache.isFallbackproject(p)) { - LOG.log(Level.FINE, "New project is still fallback, skipping"); return; } File basePOMFile = p.getFile().getParentFile(); @@ -733,15 +593,10 @@ private void reloadPossibleBrokenModules(MavenProject preceding, MavenProject p) } MavenProject child = MavenProjectCache.getMavenProject(modPom, true, false); if (child == null) { - LOG.log(Level.FINE, "Child project {0} is not cached yet", modPom); continue; } - LOG.log(Level.FINE, "Child project fallback status: {0}, {1}", new Object[] { - MavenProjectCache.isIncompleteProject(child), - child.getContextValue("org.netbeans.modules.maven.problems.primingNotDone") - }); // the project may have more problems, more subtle, but now repair just total breakage - if (!MavenProjectCache.isIncompleteProject(child) && child.getContextValue("org.netbeans.modules.maven.problems.primingNotDone") != Boolean.TRUE) { + if (!MavenProjectCache.isFallbackproject(child) && child.getContextValue("org.netbeans.modules.maven.problems.primingNotDone") != Boolean.TRUE) { LOG.log(Level.FINE, "Project for module {0} is not a fallback, skipping", modName); continue; } @@ -757,7 +612,7 @@ private void reloadPossibleBrokenModules(MavenProject preceding, MavenProject p) } else { LOG.log(Level.INFO, "Recovering module {0}, pomfile {1}", new Object[] { modName, modPom }); NbMavenProjectImpl childImpl = c.getLookup().lookup(NbMavenProjectImpl.class); - childImpl.fireProjectReload(true); + childImpl.fireProjectReload(); } } catch (IOException ex) { LOG.log(Level.FINE, "Error getting module project {0} is not a project", modName); @@ -1404,10 +1259,7 @@ protected List getParents() { while(true) { try { MavenProject parent = loadParentOf(getEmbedder(), project); - if (parent == null || NbMavenProject.isErrorPlaceholder(parent)) { - break; - } - File parentFile = parent.getFile(); + File parentFile = parent != null ? parent.getFile() : null; if(parentFile != null) { ret.add(parentFile); project = parent; diff --git a/java/maven/src/org/netbeans/modules/maven/api/NbMavenProject.java b/java/maven/src/org/netbeans/modules/maven/api/NbMavenProject.java index c8c3e86b87c7..e1575a269dd3 100644 --- a/java/maven/src/org/netbeans/modules/maven/api/NbMavenProject.java +++ b/java/maven/src/org/netbeans/modules/maven/api/NbMavenProject.java @@ -194,9 +194,9 @@ private NbMavenProject(NbMavenProjectImpl proj) { } /** - * Checks if the project is completely broken. Also see {@link #getPartialProject}. - * @return true, if the project is broken and could not be loaded - * @see #getPartialProject + * + * @return + * @since */ public boolean isUnloadable() { return MavenProjectCache.isFallbackproject(getMavenProject()); @@ -586,12 +586,10 @@ private void fireChange(URI uri) { * */ private RequestProcessor.Task fireProjectReload() { - return project.fireProjectReload(true); + return project.fireProjectReload(); } private void doFireReload() { - MavenProject p = project.getOriginalMavenProjectOrNull(); - LOG.log(Level.FINE, "Firing PROJECT change for maven project {0}, mavenprj {1}", new Object[] { this, System.identityHashCode(p == null ? this : p) }); FileUtil.refreshFor(FileUtil.toFile(project.getProjectDirectory())); NbMavenProjectImpl.refreshLocalRepository(project); support.firePropertyChange(PROP_PROJECT, null, null); @@ -632,58 +630,16 @@ public static void removePropertyChangeListener(Project prj, PropertyChangeListe assert false : "Attempted to remove PropertyChangeListener from project " + prj; //NOI18N } } - - /** - * Retrieves at least partial project information. A MavenProject instance may be a fallback in case the reading - * fails because of locally missing artifacts and/or referenced parents. However partial model may be available. The function - * returns the passed project, if it read correctly. Otherwise, it attempts to locate a partially load project and returns that one. - * If a partial project is not available, it will return the passed (fallback) project. - *

- * The result can be checked to be {@link #isErrorPlaceholder} to determine if the result was a returned partial project or not. - * Note that partial projects may not resolve all references properly, be prepared for unresolved artifacts and/or plugins. Do not pass - * partial projects blindly around. - *

- * Returns {@code null} if the passed project is {@code null} - * @param project the project to check - * @return partial project if the passed project did not load properly and the partial project is available. - * @since 2.161 - */ - public static MavenProject getPartialProject(MavenProject project) { - if (project == null) { - return null; - } - if (isIncomplete(project)) { - MavenProject pp = MavenProjectCache.getPartialProject(project); - if (pp != null) { - return pp; - } - } - return project; - } /** - * Checks whether a given project is just an error placeholder. Such project may be fundamentally broken, i.e. missing - * declarations from the parent, unresolved dependencies or versions. Also see {@link #isIncomplete} + * Checks whether a given project is just an error placeholder. * @param project a project loaded by e.g. {@link #getMavenProject} * @return true if it was loaded as an error fallback, false for a normal project * @since 2.24 - * @see #isIncomplete - * @see #getPartialProject */ public static boolean isErrorPlaceholder(@NonNull MavenProject project) { return MavenProjectCache.isFallbackproject(project); // see NbMavenProjectImpl.getFallbackProject } - - /** - * Checks if the project resolved using incomplete or missing information. Each {@link #isErrorPlaceholder} is an incomplete project. - * If the project is just missing proper referenced artifacts, it will not be reported as a {@link #isErrorPlaceholder}, but as {@link #isIncomplete}. - * @param project - * @return true, if the project is not completely resolved - * @since 2.161 - */ - public static boolean isIncomplete(@NonNull MavenProject project) { - return MavenProjectCache.isIncompleteProject(project); - } @Override public String toString() { return project.toString(); diff --git a/java/maven/src/org/netbeans/modules/maven/classpath/AbstractProjectClassPathImpl.java b/java/maven/src/org/netbeans/modules/maven/classpath/AbstractProjectClassPathImpl.java index b2dd0c66c27a..ba919d114150 100644 --- a/java/maven/src/org/netbeans/modules/maven/classpath/AbstractProjectClassPathImpl.java +++ b/java/maven/src/org/netbeans/modules/maven/classpath/AbstractProjectClassPathImpl.java @@ -32,7 +32,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.apache.maven.artifact.Artifact; -import org.apache.maven.project.MavenProject; import org.netbeans.modules.maven.NbMavenProjectImpl; import org.netbeans.modules.maven.api.NbMavenProject; import org.netbeans.spi.java.classpath.ClassPathImplementation; @@ -55,18 +54,13 @@ public abstract class AbstractProjectClassPathImpl implements ClassPathImplement protected AbstractProjectClassPathImpl(NbMavenProjectImpl proj) { project = proj; - LOGGER.log(Level.FINER, "Creating {0} for project {1}, with original {2}", new Object[] { getClass(), proj, proj.getOriginalMavenProjectOrNull() }); //TODO make weak or remove the listeners as well?? NbMavenProject.addPropertyChangeListener(proj, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { //explicitly listing both RESOURCE and PROJECT properties, it's unclear if both are required but since some other places call addWatchedPath but don't listen it's likely required if (NbMavenProject.PROP_RESOURCE.equals(evt.getPropertyName()) || NbMavenProject.PROP_PROJECT.equals(evt.getPropertyName())) { - MavenProject mp = project.getOriginalMavenProjectOrNull(); - LOGGER.log(Level.FINE, "{0} got change {1} from project: {2} with maven project {3}", new Object[] { getClass(), evt.getPropertyName(), project, - System.identityHashCode(mp == null ? this : null) }); if (project.getProjectWatcher().isUnloadable()) { - LOGGER.log(Level.FINER, "{0} is not loadable, exiting", project); return; //let's just continue with the old value, stripping classpath for broken project and re-creating it later serves no greater good. } List newValues = getPath(); @@ -75,9 +69,6 @@ public void propertyChange(PropertyChangeEvent evt) { synchronized (AbstractProjectClassPathImpl.this) { oldvalue = resources; hasChanged = hasChanged(oldvalue, newValues); - LOGGER.log(Level.FINER, "{0}: {1} classpath is: {2}, {3} entries", new Object[] { - getClass(), project, newValues, newValues.size() - }); // System.out.println("checking=" + AbstractProjectClassPathImpl.this.getClass()); if (hasChanged) { resources = newValues; diff --git a/java/maven/src/org/netbeans/modules/maven/classpath/ClassPathProviderImpl.java b/java/maven/src/org/netbeans/modules/maven/classpath/ClassPathProviderImpl.java index fda13392d1e8..009555c25326 100644 --- a/java/maven/src/org/netbeans/modules/maven/classpath/ClassPathProviderImpl.java +++ b/java/maven/src/org/netbeans/modules/maven/classpath/ClassPathProviderImpl.java @@ -538,7 +538,6 @@ protected boolean isReset(PropertyChangeEvent evt) { boolean reset = false; if( (NbMavenProject.PROP_RESOURCE.equals(evt.getPropertyName()) && evt.getNewValue() instanceof URI)) { File file = Utilities.toFile((URI) evt.getNewValue()); - LOGGER.log(Level.FINER, "{0} checking reset with file {1}", new Object[] { getClass(), file }); for (String sourceRoot : proj.getOriginalMavenProject().getCompileSourceRoots()) { if(file.equals(new File(sourceRoot, MODULE_INFO_JAVA))) { reset = true; @@ -702,7 +701,6 @@ public ClassPathSelector(NbMavenProjectImpl proj) { // maven checks recursively all source roots for module-info, // for performace reasons we will be checking and listening only on the root of a source root NbMavenProject.addPropertyChangeListener(proj, (evt) -> { - LOGGER.log(Level.FINER, "{0} got property change {1} from {2}", new Object[] { getClass(), evt, proj }); if (isReset(evt)) { active = null; support.firePropertyChange(PROP_ACTIVE_CLASS_PATH, null, null); diff --git a/java/maven/src/org/netbeans/modules/maven/classpath/CompileClassPathImpl.java b/java/maven/src/org/netbeans/modules/maven/classpath/CompileClassPathImpl.java index c748267e63a6..26b789cd80ed 100644 --- a/java/maven/src/org/netbeans/modules/maven/classpath/CompileClassPathImpl.java +++ b/java/maven/src/org/netbeans/modules/maven/classpath/CompileClassPathImpl.java @@ -26,8 +26,6 @@ import java.util.EnumSet; import java.util.List; import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; import org.apache.maven.artifact.Artifact; import org.apache.maven.project.MavenProject; import org.netbeans.api.java.classpath.ClassPath; @@ -40,7 +38,7 @@ * @author Milos Kleint */ class CompileClassPathImpl extends AbstractProjectClassPathImpl implements FlaggedClassPathImplementation { - private static final Logger LOGGER = Logger.getLogger(CompileClassPathImpl.class.getName()); + private volatile boolean incomplete; private final boolean addOutputDir; @@ -54,9 +52,6 @@ public CompileClassPathImpl(NbMavenProjectImpl proj, boolean addOutputDir) { URI[] createPath() { List lst = new ArrayList<>(); boolean broken = getCompileArtifacts(getMavenProject().getOriginalMavenProject(), lst); - MavenProject mp = getMavenProject().getOriginalMavenProjectOrNull(); - LOGGER.log(Level.FINER, "{0} for project {1}: creating path for {2}: size {4} - {3}", - new Object[] { getClass(), getMavenProject(), System.identityHashCode(mp == null ? this : mp), lst, lst.size() }); if(addOutputDir) { lst.add(Utilities.toURI(getProject().getProjectWatcher().getOutputDirectory(false))); } diff --git a/java/maven/src/org/netbeans/modules/maven/customizer/BasicInfoPanel.java b/java/maven/src/org/netbeans/modules/maven/customizer/BasicInfoPanel.java index abfb42514be1..1ae432b9eea9 100644 --- a/java/maven/src/org/netbeans/modules/maven/customizer/BasicInfoPanel.java +++ b/java/maven/src/org/netbeans/modules/maven/customizer/BasicInfoPanel.java @@ -28,7 +28,6 @@ import org.apache.maven.project.MavenProject; import org.apache.maven.project.ProjectBuildingException; import org.netbeans.modules.maven.NbMavenProjectImpl; -import org.netbeans.modules.maven.api.NbMavenProject; import org.netbeans.modules.maven.api.customizer.ModelHandle2; import org.netbeans.modules.maven.api.customizer.support.ReflectionTextComponentUpdater; import org.netbeans.modules.maven.api.customizer.support.TextComponentUpdater; @@ -67,9 +66,6 @@ private void initValues() { NbMavenProjectImpl nbi = prj.getLookup().lookup(NbMavenProjectImpl.class); assert nbi != null; project = nbi.loadParentOf(EmbedderFactory.getProjectEmbedder(), handle.getProject()); - if (NbMavenProject.isErrorPlaceholder(project)) { - project = null; - } } catch (ProjectBuildingException ex) { project = null; } diff --git a/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java b/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java index c26f350c5f41..99e500c34c85 100644 --- a/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java +++ b/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java @@ -173,14 +173,9 @@ public static ExecutorTask executeMaven(final RunConfig config, InputOutput io, * Hooks for tests to mock the Maven execution. */ public static class ExecuteMaven { - // tests only - MavenExecutor createCommandLineExecutor(RunConfig config, InputOutput io, TabContext tc) { - return new MavenCommandLineExecutor(config, io, tc); - } - public ExecutorTask execute(RunConfig config, InputOutput io, TabContext tc) { LifecycleManager.getDefault().saveAll(); - MavenExecutor exec = createCommandLineExecutor(config, io, tc); + MavenExecutor exec = new MavenCommandLineExecutor(config, io, tc); ExecutorTask task = ExecutionEngine.getDefault().execute(config.getTaskDisplayName(), exec, new ProxyNonSelectableInputOutput(exec.getInputOutput())); exec.setTask(task); task.addTaskListener(new TaskListener() { @@ -395,7 +390,6 @@ public void actionPerformed(ActionEvent e) { if (prj != null) { NbMavenProjectImpl impl = prj.getLookup().lookup(NbMavenProjectImpl.class); if (impl != null) { - // this reload must not wait for blockers. RequestProcessor.Task reloadTask = impl.fireProjectReload(); reloadTask.waitFinished(); } @@ -522,7 +516,7 @@ private static List createMavenExecutionCommand(RunConfig config, Constr } if (config.getReactorStyle() != RunConfig.ReactorStyle.NONE) { File basedir = config.getExecutionDirectory(); - MavenProject mp = NbMavenProject.getPartialProject(config.getMavenProject()); + MavenProject mp = config.getMavenProject(); File projdir = NbMavenProject.isErrorPlaceholder(mp) ? basedir : mp.getBasedir(); String rel = basedir != null && projdir != null ? FileUtilities.relativizeFile(basedir, projdir) : null; if (!".".equals(rel)) { @@ -633,8 +627,7 @@ private static String quote2apos(String s) { return sb.toString(); } - // tests only - ProcessBuilder constructBuilder(final RunConfig clonedConfig, InputOutput ioput) { + private ProcessBuilder constructBuilder(final RunConfig clonedConfig, InputOutput ioput) { File javaHome = null; Map envMap = new LinkedHashMap(); for (Map.Entry entry : clonedConfig.getProperties().entrySet()) { @@ -1107,7 +1100,7 @@ private File getAltMavenLocation() { private File searchMavenWrapper(RunConfig config) { String fileName = Utilities.isWindows() ? "mvnw.cmd" : "mvnw"; //NOI18N - MavenProject project = NbMavenProject.getPartialProject(config.getMavenProject()); + MavenProject project = config.getMavenProject(); while (project != null) { File baseDir = project.getBasedir(); if (baseDir != null) { diff --git a/java/maven/src/org/netbeans/modules/maven/execute/ReactorChecker.java b/java/maven/src/org/netbeans/modules/maven/execute/ReactorChecker.java index d23c4cdd9157..35bc3692cdf3 100644 --- a/java/maven/src/org/netbeans/modules/maven/execute/ReactorChecker.java +++ b/java/maven/src/org/netbeans/modules/maven/execute/ReactorChecker.java @@ -64,6 +64,9 @@ public class ReactorChecker implements PrerequisitesChecker { // Unloadable? return true; } + if (NbMavenProject.isErrorPlaceholder(mavenprj.getMavenProject())) { + return true; // broken project + } NbMavenProject reactor = findReactor(mavenprj); File reactorRoot = reactor.getMavenProject().getBasedir(); @@ -101,7 +104,7 @@ public class ReactorChecker implements PrerequisitesChecker { * @return its apparent reactor root; maybe just the same project */ public static @NonNull NbMavenProject findReactor(@NonNull NbMavenProject module) { // #197232 - MavenProject prj = NbMavenProject.getPartialProject(module.getMavenProject()); + MavenProject prj = module.getMavenProject(); List models = MavenEmbedder.getModelDescriptors(prj); File moduleDir = prj.getBasedir(); File current = moduleDir; @@ -131,11 +134,8 @@ public class ReactorChecker implements PrerequisitesChecker { } } NbMavenProject p = load(prj.getBasedir().getParentFile()); - if (p != null) { - MavenProject mp = NbMavenProject.getPartialProject(p.getMavenProject()); - if (listsModule(moduleDir.getParentFile(), moduleDir, mp.getModules())) { - return findReactor(p); - } + if (p != null && listsModule(moduleDir.getParentFile(), moduleDir, p.getMavenProject().getModules())) { + return findReactor(p); } return module; } diff --git a/java/maven/src/org/netbeans/modules/maven/modelcache/MavenProjectCache.java b/java/maven/src/org/netbeans/modules/maven/modelcache/MavenProjectCache.java index 61a50730718e..6d8c521e2b0e 100644 --- a/java/maven/src/org/netbeans/modules/maven/modelcache/MavenProjectCache.java +++ b/java/maven/src/org/netbeans/modules/maven/modelcache/MavenProjectCache.java @@ -25,19 +25,16 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.Set; import java.util.WeakHashMap; import java.util.function.BiConsumer; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.SwingUtilities; import org.apache.maven.AbstractMavenLifecycleParticipant; -import org.apache.maven.artifact.Artifact; import org.apache.maven.execution.DefaultMavenExecutionResult; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenExecutionResult; @@ -48,7 +45,6 @@ import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.project.ProjectActionContext; import org.netbeans.modules.maven.M2AuxilaryConfigImpl; -import org.netbeans.modules.maven.NbArtifactFixer; import org.netbeans.modules.maven.api.NbMavenProject; import org.netbeans.modules.maven.api.execute.RunConfig; import org.netbeans.modules.maven.configurations.M2Configuration; @@ -71,27 +67,7 @@ public final class MavenProjectCache { private static final Logger LOG = Logger.getLogger(MavenProjectCache.class.getName()); private static final String CONTEXT_EXECUTION_RESULT = "NB_Execution_Result"; - - /** - * The value contains the set of artifacts, that have been faked during the reading operation. - */ - private static final String CONTEXT_FAKED_ARTIFACTS = "NB_FakedArtifacts"; - - /** - * Marks a project that observed unknown build participants. - */ private static final String CONTEXT_PARTICIPANTS = "NB_AbstractParticipant_Present"; - /** - * Marks a fallback project. The project was not fully read. Value of the context key is either a Boolean.TRUE as an indicator, or - * the partially read project, which does not resolve fully. Can be extracted with {@link #getPartialProject(org.apache.maven.project.MavenProject)}. - */ - private static final String CONTEXT_PARTIAL_PROJECT = "org.netbeans.modules.maven.partialProject"; // NOI18N - - /** - * Marks a fallback project. The project is forged and is not read from the maven infrastructure. A fallback project may have a {@link #getPartialProject(org.apache.maven.project.MavenProject) partial project} - * attached. - */ - private static final String CONTEXT_FALLBACK_PROJECT = "org.netbeans.modules.maven.fallbackProject"; // NOI18N /** * Folder with module-configurable whitelist of lifecycle participants. Currently only 'ignore' can be specified. @@ -196,107 +172,8 @@ private static boolean isLifecycleParticipatnIgnored(AbstractMavenLifecycleParti return check != null && check.getAttribute(ATTR_IGNORE_ON_LOAD) == Boolean.TRUE; } - public static MavenProject loadOriginalMavenProjectInternal(MavenEmbedder projectEmbedder, MavenExecutionRequest req) { - MavenProject newproject = null; - File pomFile = req.getPom(); - - MavenExecutionResult res = null; - Set fakes = new HashSet<>(); - long startLoading = System.currentTimeMillis(); - - try { - res = NbArtifactFixer.collectFallbackArtifacts(() -> projectEmbedder.readProjectWithDependencies(req, true), (c) -> - c.forEach(a -> { - // artifact fixer only fakes POMs. - fakes.add(projectEmbedder.createArtifactWithClassifier(a.getGroupId(), a.getArtifactId(), a.getVersion(), "pom", a.getClassifier())); // NOI18N - } - )); - newproject = res.getProject(); - - //#204898 - if (newproject != null) { - LOG.log(Level.FINE, "Loaded project for {0}, packaging: {1}", new Object[] { pomFile, newproject.getPackaging() }); - ClassLoader projectRealm = newproject.getClassRealm(); - if (projectRealm != null) { - ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(projectRealm); - try { - //boolean execute = EnableParticipantsBuildAction.isEnabled(aux); - List lookup = projectEmbedder.getPlexus().lookupList(AbstractMavenLifecycleParticipant.class); - if (lookup.size() > 0) { //just in case.. -// if (execute) { -// LOG.info("Executing External Build Participants..."); -// MavenSession session = new MavenSession( projectEmbedder.getPlexus(), newproject.getProjectBuildingRequest().getRepositorySession(), req, res ); -// session.setCurrentProject(newproject); -// session.setProjects(Collections.singletonList(newproject)); -// projectEmbedder.setUpLegacySupport(); -// projectEmbedder.getPlexus().lookup(LegacySupport.class).setSession(session); -// -// for (AbstractMavenLifecycleParticipant part : lookup) { -// try { -// Thread.currentThread().setContextClassLoader( part.getClass().getClassLoader() ); -// part.afterSessionStart(session); -// part.afterProjectsRead(session); -// } catch (MavenExecutionException ex) { -// Exceptions.printStackTrace(ex); -// } -// } -// } else { - List parts = new ArrayList(); - for (AbstractMavenLifecycleParticipant part : lookup) { - if (isLifecycleParticipatnIgnored(part)) { - //#204898 create a whitelist of known not harmful participants that can be just ignored - continue; - } - String name = part.getClass().getName(); - parts.add(name); - } - if (parts.size() > 0) { - newproject.setContextValue(CONTEXT_PARTICIPANTS, parts); - } -// } - } - } catch (ComponentLookupException e) { - // this is just silly, lookupList should return an empty list! - } finally { - Thread.currentThread().setContextClassLoader(originalClassLoader); - } - } - } - } catch (RuntimeException exc) { - //guard against exceptions that are not processed by the embedder - //#136184 NumberFormatException - LOG.log(Level.INFO, "Runtime exception thrown while loading maven project at " + pomFile, exc); //NOI18N - res = new DefaultMavenExecutionResult(); - res.addException(exc); - } finally { - if (newproject == null) { - newproject = getFallbackProject(res, pomFile); - } - //#215159 clear the project building request, it references multiple Maven Models via the RepositorySession cache - //is not used in maven itself, most likely used by m2e only.. - newproject.setProjectBuildingRequest(null); - long endLoading = System.currentTimeMillis(); - LOG.log(Level.FINE, "Loaded project in {0} msec at {1}", new Object[] {endLoading - startLoading, pomFile.getPath()}); - if (LOG.isLoggable(Level.FINE) && SwingUtilities.isEventDispatchThread()) { - LOG.log(Level.FINE, "Project " + pomFile.getPath() + " loaded in AWT event dispatching thread!", new RuntimeException()); - } - if (LOG.isLoggable(Level.FINE) && !res.getExceptions().isEmpty()) { - LOG.log(Level.FINE, "Errors encountered during loading the project:"); - for (Throwable t : res.getExceptions()) { - LOG.log(Level.FINE, "Maven reported:", t); - } - } - if (!fakes.isEmpty() && !isIncompleteProject(newproject)) { - LOG.log(Level.FINE, "Incomplete artifact encountered during loading the project: {0}", fakes); - newproject.setContextValue(CONTEXT_PARTIAL_PROJECT, Boolean.TRUE); - newproject.setContextValue(CONTEXT_FAKED_ARTIFACTS, fakes); - } - } - return newproject; - } - private static @NonNull MavenProject loadOriginalMavenProject(final File pomFile, ProjectActionContext ctx, RunConfig runConf) { + long startLoading = System.currentTimeMillis(); MavenEmbedder projectEmbedder = EmbedderFactory.getProjectEmbedder(); MavenProject newproject = null; //TODO have independent from M2AuxiliaryConfigImpl @@ -317,6 +194,7 @@ public static MavenProject loadOriginalMavenProjectInternal(MavenEmbedder projec } } + MavenExecutionResult res = null; try { List mavenConfigOpts = Collections.emptyList(); for (FileObject root = projectDir; root != null; root = root.getParent()) { @@ -399,19 +277,92 @@ public static MavenProject loadOriginalMavenProjectInternal(MavenEmbedder projec LOG.log(Level.FINE, "request property 'packaging': {0}", req.getSystemProperties().get("packaging")); LOG.log(Level.FINE, "embedder property 'packaging': {0}", projectEmbedder.getSystemProperties().get("packaging")); } - newproject = loadOriginalMavenProjectInternal(projectEmbedder, req); - } catch (IOException exc) { - MavenExecutionResult res = null; + res = projectEmbedder.readProjectWithDependencies(req, true); + newproject = res.getProject(); + + //#204898 + if (newproject != null) { + LOG.log(Level.FINE, "Loaded project for {0}, packaging: {1}", new Object[] { pomFile, newproject.getPackaging() }); + ClassLoader projectRealm = newproject.getClassRealm(); + if (projectRealm != null) { + ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(projectRealm); + try { + //boolean execute = EnableParticipantsBuildAction.isEnabled(aux); + List lookup = projectEmbedder.getPlexus().lookupList(AbstractMavenLifecycleParticipant.class); + if (lookup.size() > 0) { //just in case.. +// if (execute) { +// LOG.info("Executing External Build Participants..."); +// MavenSession session = new MavenSession( projectEmbedder.getPlexus(), newproject.getProjectBuildingRequest().getRepositorySession(), req, res ); +// session.setCurrentProject(newproject); +// session.setProjects(Collections.singletonList(newproject)); +// projectEmbedder.setUpLegacySupport(); +// projectEmbedder.getPlexus().lookup(LegacySupport.class).setSession(session); +// +// for (AbstractMavenLifecycleParticipant part : lookup) { +// try { +// Thread.currentThread().setContextClassLoader( part.getClass().getClassLoader() ); +// part.afterSessionStart(session); +// part.afterProjectsRead(session); +// } catch (MavenExecutionException ex) { +// Exceptions.printStackTrace(ex); +// } +// } +// } else { + List parts = new ArrayList(); + for (AbstractMavenLifecycleParticipant part : lookup) { + if (isLifecycleParticipatnIgnored(part)) { + //#204898 create a whitelist of known not harmful participants that can be just ignored + continue; + } + String name = part.getClass().getName(); + parts.add(name); + } + if (parts.size() > 0) { + newproject.setContextValue(CONTEXT_PARTICIPANTS, parts); + } +// } + } + } catch (ComponentLookupException e) { + // this is just silly, lookupList should return an empty list! + } finally { + Thread.currentThread().setContextClassLoader(originalClassLoader); + } + } + } + } catch (RuntimeException | IOException exc) { //guard against exceptions that are not processed by the embedder //#136184 NumberFormatException LOG.log(Level.INFO, "Runtime exception thrown while loading maven project at " + pomFile, exc); //NOI18N res = new DefaultMavenExecutionResult(); res.addException(exc); - newproject = getFallbackProject(res, pomFile); + } finally { + if (newproject == null) { + newproject = getFallbackProject(res, pomFile); + } + //#215159 clear the project building request, it references multiple Maven Models via the RepositorySession cache + //is not used in maven itself, most likely used by m2e only.. + newproject.setProjectBuildingRequest(null); + //TODO some exceptions in result contain various model caches as well.. + newproject.setContextValue(CONTEXT_EXECUTION_RESULT, res); + long endLoading = System.currentTimeMillis(); + LOG.log(Level.FINE, "Loaded project in {0} msec at {1}", new Object[] {endLoading - startLoading, pomFile.getPath()}); + if (LOG.isLoggable(Level.FINE) && SwingUtilities.isEventDispatchThread()) { + LOG.log(Level.FINE, "Project " + pomFile.getPath() + " loaded in AWT event dispatching thread!", new RuntimeException()); + } + if (LOG.isLoggable(Level.FINE) && !res.getExceptions().isEmpty()) { + LOG.log(Level.FINE, "Errors encountered during loading the project:"); + for (Throwable t : res.getExceptions()) { + LOG.log(Level.FINE, "Maven reported:", t); + } + } } return newproject; } + private static final String CONTEXT_PARTIAL_PROJECT = "org.netbeans.modules.maven.partialProject"; // NOI18N + private static final String CONTEXT_FALLBACK_PROJECT = "org.netbeans.modules.maven.fallbackProject"; // NOI18N + /** * Create a fallback project, but patch the incomplete project from the building result into it. * The method will eventually start to return the partial project but still flagged as a fallback - see {@link #isFallbackproject(org.apache.maven.project.MavenProject)}. @@ -426,7 +377,6 @@ public static MavenProject getFallbackProject(MavenExecutionResult result, File if (result == null) { return toReturn; } - toReturn.setContextValue(CONTEXT_EXECUTION_RESULT, result); MavenProject partial = null; for (Throwable t : result.getExceptions()) { @@ -467,24 +417,11 @@ public static MavenProject getFallbackProject(File projectFile) throws Assertion return newproject; } - public static boolean isIncompleteProject(MavenProject prj) { - return prj.getContextValue(CONTEXT_PARTIAL_PROJECT) != null; - } - public static boolean isFallbackproject(MavenProject prj) { if ("error".equals(prj.getGroupId()) && "error".equals(prj.getArtifactId()) && Bundle.LBL_Incomplete_Project_Name().equals(prj.getName())) { return true; } else { - return prj.getContextValue(CONTEXT_FALLBACK_PROJECT) != null; - } - } - - public static MavenProject getPartialProject(MavenProject prj) { - Object o = prj.getContextValue(CONTEXT_PARTIAL_PROJECT); - if (o instanceof MavenProject) { - return (MavenProject)o; - } else { - return null; + return prj.getContextValue(CONTEXT_PARTIAL_PROJECT) == Boolean.TRUE; } } diff --git a/java/maven/src/org/netbeans/modules/maven/nodes/AddDependencyPanel.java b/java/maven/src/org/netbeans/modules/maven/nodes/AddDependencyPanel.java index 4d7345bbab4d..3f86da7bbcef 100644 --- a/java/maven/src/org/netbeans/modules/maven/nodes/AddDependencyPanel.java +++ b/java/maven/src/org/netbeans/modules/maven/nodes/AddDependencyPanel.java @@ -821,9 +821,6 @@ private static List getDependenciesFromDM(MavenProject project, Proj } try { localProj = p.loadParentOf(EmbedderFactory.getProjectEmbedder(), localProj); - if (NbMavenProject.isErrorPlaceholder(localProj)) { - break; - } } catch (ProjectBuildingException x) { break; } diff --git a/java/maven/src/org/netbeans/modules/maven/problems/MavenModelProblemsProvider.java b/java/maven/src/org/netbeans/modules/maven/problems/MavenModelProblemsProvider.java index b842285ff812..34cddf8c5e44 100644 --- a/java/maven/src/org/netbeans/modules/maven/problems/MavenModelProblemsProvider.java +++ b/java/maven/src/org/netbeans/modules/maven/problems/MavenModelProblemsProvider.java @@ -33,6 +33,9 @@ import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.maven.artifact.Artifact; @@ -83,7 +86,7 @@ }, projectType = "org-netbeans-modules-maven" ) public class MavenModelProblemsProvider implements ProjectProblemsProvider, InternalActionDelegate { - static final RequestProcessor RP = new RequestProcessor(MavenModelProblemsProvider.class); + static final ScheduledExecutorService RP = new RequestProcessor(MavenModelProblemsProvider.class); private static final Logger LOG = Logger.getLogger(MavenModelProblemsProvider.class.getName()); private final PropertyChangeSupport support = new PropertyChangeSupport(this); @@ -247,10 +250,6 @@ private Pair, Boolean> doGetProblems1(boolean sync) { prj = ((NbMavenProjectImpl)project).getFreshOriginalMavenProject(); } } - if (prj != null && !sanityBuildStatus) { - prj.setContextValue("org.netbeans.modules.maven.problems.primingNotDone", null); - LOG.log(Level.FINE, "Clearing priming status of {0}, fallback status is {1}", new Object[] { prj, NbMavenProject.isErrorPlaceholder(prj) }); - } //mark the project model as checked once and cached firePropertyChange(); return Pair.of(toRet, sanityBuildStatus); @@ -496,7 +495,7 @@ public void invokeAction(String command, Lookup context) throws IllegalArgumentE listener.finished(true); } else { LOG.log(Level.FINE, "Resolving sanity build action"); - CompletableFuture r = saba.resolve(context); + CompletableFuture r = saba.resolve(); r.whenComplete((a, e) -> { listener.finished(e == null); }); diff --git a/java/maven/src/org/netbeans/modules/maven/problems/ProblemReporterImpl.java b/java/maven/src/org/netbeans/modules/maven/problems/ProblemReporterImpl.java index cab78a8bf229..296cf3035f86 100644 --- a/java/maven/src/org/netbeans/modules/maven/problems/ProblemReporterImpl.java +++ b/java/maven/src/org/netbeans/modules/maven/problems/ProblemReporterImpl.java @@ -93,7 +93,7 @@ public final class ProblemReporterImpl implements ProblemReporter, Comparator getPendingResult() { }) @Override public CompletableFuture resolve() { - return resolve(null); - } - - public CompletableFuture resolve(Lookup context) { CompletableFuture pr = pendingResult; if (pr != null && !pr.isDone()) { LOG.log(Level.FINE, "SanityBuild.resolve returns: {0}", pendingResult); @@ -117,12 +112,8 @@ public void run() { try { LOG.log(Level.FINE, "Configuring sanity build"); BeanRunConfig config = new BeanRunConfig(); - if (context != null) { - config.setActionContext(context); - } config.setExecutionDirectory(FileUtil.toFile(nbproject.getProjectDirectory())); NbMavenProject mavenPrj = nbproject.getLookup().lookup(NbMavenProject.class); - MavenProject loaded = NbMavenProject.getPartialProject(mavenPrj.getMavenProject()); String goals; if (mavenPrj != null && mavenPrj.getMavenProject().getVersion() != null @@ -184,7 +175,7 @@ public void run() { } pendingResult = publicResult; } - ((NbMavenProjectImpl)this.nbproject).scheduleProjectOperation(MavenModelProblemsProvider.RP, toRet, 0); + MavenModelProblemsProvider.RP.submit(toRet); return publicResult; } diff --git a/java/maven/src/org/netbeans/modules/maven/spi/newproject/CreateProjectBuilder.java b/java/maven/src/org/netbeans/modules/maven/spi/newproject/CreateProjectBuilder.java index 11b3b563d090..5e01527baeca 100644 --- a/java/maven/src/org/netbeans/modules/maven/spi/newproject/CreateProjectBuilder.java +++ b/java/maven/src/org/netbeans/modules/maven/spi/newproject/CreateProjectBuilder.java @@ -129,7 +129,7 @@ public void create() { } } } - if (parent != null && NbMavenProject.isErrorPlaceholder(parent)) { + if (parent != null && MavenProjectCache.isFallbackproject(parent)) { //#240989 - guessing that unloadable parent project could be the problem. parent = null; } diff --git a/java/maven/test/unit/data/projects/multiproject/democa/.gitignore b/java/maven/test/unit/data/projects/multiproject/democa/.gitignore deleted file mode 100644 index 5a03bc30a460..000000000000 --- a/java/maven/test/unit/data/projects/multiproject/democa/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -Thumbs.db -.DS_Store -.gradle -build/ -target/ -out/ -.micronaut/ -.idea -*.iml -*.ipr -*.iws -.project -.settings -.classpath -.factorypath diff --git a/java/maven/test/unit/data/projects/multiproject/democa/LICENSE b/java/maven/test/unit/data/projects/multiproject/democa/LICENSE deleted file mode 100644 index 20e4bd85661f..000000000000 --- a/java/maven/test/unit/data/projects/multiproject/democa/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/java/maven/test/unit/data/projects/multiproject/democa/lib/pom.xml b/java/maven/test/unit/data/projects/multiproject/democa/lib/pom.xml deleted file mode 100644 index 6d19155a44fe..000000000000 --- a/java/maven/test/unit/data/projects/multiproject/democa/lib/pom.xml +++ /dev/null @@ -1,198 +0,0 @@ - - - - 4.0.0 - com.exampleca - lib - 1.0-SNAPSHOT - jar - - - com.exampleca - democa-parent - 1.0-SNAPSHOT - - - - jar - 17 - 17 - 4.0.3-oracle-00001 - - - - - central - https://repo.maven.apache.org/maven2 - - - - gcn - https://maven.oracle.com/public - - - - - - - cloud.graal.gcn - gcn-bom - 2.0 - pom - import - - - - - - io.micronaut - micronaut-inject - compile - - - io.micronaut.validation - micronaut-validation - compile - - - io.micronaut - micronaut-http-client - compile - - - io.micronaut - micronaut-http-server-netty - compile - - - io.micronaut.data - micronaut-data-jdbc - compile - - - io.micronaut.objectstorage - micronaut-object-storage-core - compile - - - io.micronaut.objectstorage - micronaut-object-storage-oracle-cloud - compile - - - io.micronaut.oraclecloud - micronaut-oraclecloud-atp - compile - - - io.micronaut.serde - micronaut-serde-jackson - compile - - - io.micronaut.sql - micronaut-jdbc-hikari - compile - - - jakarta.validation - jakarta.validation-api - compile - - - ch.qos.logback - logback-classic - runtime - - - io.micronaut - micronaut-http-server - provided - - - io.micronaut.testresources - micronaut-test-resources-client - provided - - - io.micronaut.test - micronaut-test-junit5 - test - - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - - - - - ${basedir}/src/main/resources - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - io.micronaut - micronaut-inject-java - ${micronaut.core.version} - - - io.micronaut.data - micronaut-data-processor - ${micronaut.data.version} - - - io.micronaut - micronaut-graal - ${micronaut.core.version} - - - io.micronaut.serde - micronaut-serde-processor - ${micronaut.serialization.version} - - - io.micronaut.validation - micronaut-validation-processor - ${micronaut.validation.version} - - - - - - - - diff --git a/java/maven/test/unit/data/projects/multiproject/democa/oci/pom.xml b/java/maven/test/unit/data/projects/multiproject/democa/oci/pom.xml deleted file mode 100644 index e1c7953baaed..000000000000 --- a/java/maven/test/unit/data/projects/multiproject/democa/oci/pom.xml +++ /dev/null @@ -1,253 +0,0 @@ - - - - 4.0.0 - com.exampleca - oci - 1.0-SNAPSHOT - ${packaging} - democa-${artifactId} - - - com.exampleca - democa-parent - 1.0-SNAPSHOT - - - jar - 17 - 17 - 4.0.3-oracle-00001 - true - netty - com.exampleca.Application - - - - - central - https://repo.maven.apache.org/maven2 - - - - gcn - https://maven.oracle.com/public - - - - - - - cloud.graal.gcn - gcn-bom - 2.0 - pom - import - - - - - - com.oracle.oci.sdk - oci-java-sdk-addons-graalvm - compile - - - io.micronaut - micronaut-http-client - compile - - - io.micronaut - micronaut-http-server-netty - compile - - - io.micronaut.data - micronaut-data-jdbc - compile - - - io.micronaut.flyway - micronaut-flyway - compile - - - io.micronaut.objectstorage - micronaut-object-storage-oracle-cloud - compile - - - io.micronaut.oraclecloud - micronaut-oraclecloud-atp - compile - - - io.micronaut.oraclecloud - micronaut-oraclecloud-httpclient-netty - compile - - - io.micronaut.oraclecloud - micronaut-oraclecloud-sdk - compile - - - io.micronaut.serde - micronaut-serde-jackson - compile - - - io.micronaut.sql - micronaut-jdbc-hikari - compile - - - io.micronaut.validation - micronaut-validation - compile - - - jakarta.validation - jakarta.validation-api - compile - - - ch.qos.logback - logback-classic - runtime - - - org.flywaydb - flyway-database-oracle - runtime - - - io.micronaut.testresources - micronaut-test-resources-client - provided - - - io.micronaut.test - micronaut-test-junit5 - test - - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - org.mockito - mockito-core - test - - - com.exampleca - lib - 1.0-SNAPSHOT - compile - - - - - - com.google.cloud.tools - jib-maven-plugin - - - ${project.name} - - - - - io.micronaut.maven - micronaut-maven-plugin - - frolvlad/alpine-glibc:alpine-3.16 - - - - org.apache.maven.plugins - maven-enforcer-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - - - io.micronaut - micronaut-inject-java - ${micronaut.core.version} - - - io.micronaut.data - micronaut-data-processor - ${micronaut.data.version} - - - io.micronaut - micronaut-inject - - - - - io.micronaut - micronaut-graal - ${micronaut.core.version} - - - io.micronaut.serde - micronaut-serde-processor - ${micronaut.serialization.version} - - - io.micronaut - micronaut-inject - - - - - io.micronaut.validation - micronaut-validation-processor - ${micronaut.validation.version} - - - io.micronaut - micronaut-inject - - - - - - - - - - diff --git a/java/maven/test/unit/data/projects/multiproject/democa/pom.xml b/java/maven/test/unit/data/projects/multiproject/democa/pom.xml deleted file mode 100644 index 7611c2999e79..000000000000 --- a/java/maven/test/unit/data/projects/multiproject/democa/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - 4.0.0 - - io.micronaut.platform - micronaut-parent - 4.0.3-oracle-00001 - - - - central - https://repo.maven.apache.org/maven2 - - - gcn - https://maven.oracle.com/public - - - democa-parent - 1.0-SNAPSHOT - com.exampleca - democa - pom - - - lib - oci - - diff --git a/java/maven/test/unit/src/org/netbeans/modules/maven/NbMavenProjectImpl2Test.java b/java/maven/test/unit/src/org/netbeans/modules/maven/NbMavenProjectImpl2Test.java deleted file mode 100644 index 62cbe2c31d52..000000000000 --- a/java/maven/test/unit/src/org/netbeans/modules/maven/NbMavenProjectImpl2Test.java +++ /dev/null @@ -1,597 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.netbeans.modules.maven; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.logging.ConsoleHandler; -import java.util.logging.Level; -import java.util.logging.Logger; -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertTrue; -import org.junit.Assume; -import org.netbeans.api.project.Project; -import org.netbeans.api.project.ProjectManager; -import org.netbeans.junit.NbTestCase; -import org.netbeans.modules.maven.api.NbMavenProject; -import org.netbeans.modules.maven.api.execute.ExecutionContext; -import org.netbeans.modules.maven.api.execute.LateBoundPrerequisitesChecker; -import org.netbeans.modules.maven.api.execute.RunConfig; -import org.netbeans.modules.maven.embedder.EmbedderFactory; -import org.netbeans.modules.maven.execute.MavenExecMonitor; -import org.netbeans.spi.project.ActionProgress; -import org.netbeans.spi.project.ActionProvider; -import org.netbeans.spi.project.ProjectServiceProvider; -import org.openide.filesystems.FileObject; -import org.openide.filesystems.FileUtil; -import org.openide.modules.DummyInstalledFileLocator; -import org.openide.util.Pair; -import org.openide.util.RequestProcessor; -import org.openide.util.RequestProcessor.Task; -import org.openide.util.lookup.Lookups; -import org.openide.util.test.MockLookup; -import org.openide.windows.IOProvider; - -public class NbMavenProjectImpl2Test extends NbTestCase { - public NbMavenProjectImpl2Test(String name) { - super(name); - - } - - private FileObject wd; - private File repo; - private FileObject repoFO; - private FileObject dataFO; - - private static File getTestNBDestDir() { - String destDir = System.getProperty("test.netbeans.dest.dir"); - // set in project.properties as test-unit-sys-prop.test.netbeans.dest.dir - assertNotNull("test.netbeans.dest.dir property has to be set when running within binary distribution", destDir); - return new File(destDir); - } - - protected @Override void setUp() throws Exception { - // this property could be eventually initialized by NB module system, as MavenCacheDisabler i @OnStart, but that's unreliable. - System.setProperty("maven.defaultProjectBuilder.disableGlobalModelCache", "true"); - - clearWorkDir(); - - wd = FileUtil.toFileObject(getWorkDir()); - //synchronous reload of maven project asserts sanoty in some tests.. - System.setProperty("test.reload.sync", "false"); - - // This is needed, otherwose the core window's startup code will redirect - // System.out/err to the IOProvider, and its Trivial implementation will redirect - // it back to System.err - loop is formed. Initialize IOProvider first, it gets - // the real System.err/out references. - IOProvider p = IOProvider.getDefault(); - - repo = EmbedderFactory.getProjectEmbedder().getLocalRepositoryFile(); - repoFO = FileUtil.toFileObject(repo); - dataFO = FileUtil.toFileObject(getDataDir()); - - // Configure the DummyFilesLocator with NB harness dir - File destDirF = getTestNBDestDir(); - DummyInstalledFileLocator.registerDestDir(destDirF); - - useTestJdk = true; - } - - @Override - protected void tearDown() throws Exception { - useTestJdk = false; - super.tearDown(); - } - - - - protected @Override Level logLevel() { - return Level.FINE; - } - - protected @Override String logRoot() { - return "org.netbeans.modules.maven"; - } - - volatile static boolean useTestJdk; - - /** - * Forces Maven execution on the test JDK. Should not affect other classes. This is significant - * on the developer's machine with multiple JDKs installed. Not so interesting on CI. - */ - @ProjectServiceProvider(projectType = NbMavenProject.TYPE, service = LateBoundPrerequisitesChecker.class) - public static class JdkChecker implements LateBoundPrerequisitesChecker { - @Override - public boolean checkRunConfig(RunConfig config, ExecutionContext con) { - if (useTestJdk) { - config.setProperty("Env.JAVA_HOME", System.getProperty("java.home")); - } - return true; - } - } - - private void cleanMavenRepository() throws IOException { - Path path = Paths.get(System.getProperty("user.home"), ".m2", "repository"); - if (!Files.isDirectory(path)) { - return; - } - FileUtil.toFileObject(path.toFile()).delete(); - } - - /** - * Primes the project including dependency fetch, waits for the operation to complete. - * @throws Exception - */ - void primeProject(Project p) throws Exception { - ActionProvider ap = p.getLookup().lookup(ActionProvider.class); - if (ap == null) { - throw new IllegalStateException("No action provider"); - } - assertTrue(Arrays.asList(ap.getSupportedActions()).contains(ActionProvider.COMMAND_PRIME)); - - CountDownLatch primeLatch = new CountDownLatch(1); - ActionProgress prg = new ActionProgress() { - @Override - protected void started() { - } - - @Override - public void finished(boolean success) { - primeLatch.countDown(); - } - }; - ap.invokeAction(ActionProvider.COMMAND_PRIME, Lookups.fixed(prg)); - primeLatch.await(300, TimeUnit.SECONDS); - } - - MavenExecMonitor mme; - - Project reloadProject; - NbMavenProjectImpl reloadProjectImpl; - - AtomicInteger projectEventCount = new AtomicInteger(); - CompletableFuture event = new CompletableFuture<>(); - CompletableFuture task = new CompletableFuture<>(); - - - private void reloadProjectSetup() throws Exception { - clearWorkDir(); - - FileObject testApp = dataFO.getFileObject("parent-projects/single"); - FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "simpleProject"); - - - Project p = ProjectManager.getDefault().findProject(prjCopy); - assertNotNull(p); - NbMavenProjectImpl impl = p.getLookup().lookup(NbMavenProjectImpl.class); - - Pair, Task> blockState = impl.reloadBlockingState(); - assertTrue(blockState.first().isEmpty()); - assertNull(blockState.second()); - - reloadProject = p; - reloadProjectImpl = impl; - - NbMavenProject.addPropertyChangeListener(reloadProject, (e) -> { - if (NbMavenProject.PROP_PROJECT.equals(e.getPropertyName())) { - projectEventCount.incrementAndGet(); - event.complete(null); - } - }); - } - - // Let's have per-testcase RP, so an eventually dangling task does not ruin other testcases. - private final RequestProcessor processor = new RequestProcessor(NbMavenProjectImplTest.class); - - private List asyncThrowable = Collections.synchronizedList(new ArrayList<>()); - - private void recordAsync(Throwable t) { - asyncThrowable.add(t); - } - - public void testProjectReloadsSchedulesTask() throws Exception { - reloadProjectSetup(); - AtomicBoolean firedAtCompletion = new AtomicBoolean(); - - // blocks the reload task from completing - synchronized (reloadProjectImpl) { - assertTrue("Project must not be reloading", reloadProjectImpl.getReloadTask().isFinished()); - - Task t = reloadProjectImpl.fireProjectReload(true); - t.addTaskListener((e) -> { - firedAtCompletion.set(event.isDone()); - task.complete(e); - }); - - assertFalse("Project reload started", reloadProjectImpl.getReloadTask().isFinished()); - } - - CompletableFuture.allOf(event, task).get(10, TimeUnit.SECONDS); - assertTrue("Project event fired before task completion", firedAtCompletion.get()); - } - - /** - * Checks that the project reload is NOT planned after fireProjectReload(true), if there's a blocking task. Then it checks, - * that completing the blocker, the reload task gets scheduled and completes. - */ - public void testProjectOperationDelaysReload() throws Exception { - reloadProjectSetup(); - - AtomicBoolean firedAtCompletion = new AtomicBoolean(); - CountDownLatch blocker = new CountDownLatch(1); - RequestProcessor.Task blockerTask = reloadProjectImpl.scheduleProjectOperation(processor, () -> { - try { - blocker.await(); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - }, 0); - - - Task reloadTask; - synchronized (reloadProjectImpl) { - assertTrue("Project must not be reloading", reloadProjectImpl.getReloadTask().isFinished()); - - reloadTask = reloadProjectImpl.fireProjectReload(true); - assertTrue("Reload task must not start with active blockers", reloadProjectImpl.getReloadTask().isFinished()); - } - - Thread.sleep(1000); - assertTrue("Reload task must not start with active blockers", reloadProjectImpl.getReloadTask().isFinished()); - - CountDownLatch delay1 = new CountDownLatch(1); - - // the blocker tasks's listener already present should eventually release / schedule reload task, so - // this listener should get an already scheduled task. - blockerTask.addTaskListener((e) -> { - reloadTask.addTaskListener((e2) -> { - firedAtCompletion.set(event.isDone()); - task.complete(e); - }); - delay1.countDown(); - }); - - // unblock the task - blocker.countDown(); - - delay1.await(); - - try { - task.get(10, TimeUnit.SECONDS); - } catch (TimeoutException e) { - fail("Reload was not scheduled"); - } - - assertTrue("Project event fired before task completion", firedAtCompletion.get()); - } - - /** - * Checks that reload that ignores blockers completes regardless of blockers still unfinished. - */ - public void testForcedReloadBypassesBlockers() throws Exception { - reloadProjectSetup(); - - CountDownLatch blocker = new CountDownLatch(1); - - AtomicReference reloadTask = new AtomicReference<>(); - - RequestProcessor.Task blockerTask = reloadProjectImpl.scheduleProjectOperation(processor, () -> { - try { - blocker.await(); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - }, 0); - - synchronized (reloadProjectImpl) { - assertTrue("Project must not be reloading", reloadProjectImpl.getReloadTask().isFinished()); - reloadTask.set(reloadProjectImpl.fireProjectReload(false)); - assertFalse("Forced reload should be scheduled immediately", reloadProjectImpl.getReloadTask().isFinished()); - } - - assertTrue("Reload finished despite blockers", reloadTask.get().waitFinished(10 * 1000)); - assertFalse(blockerTask.isFinished()); - - blockerTask.cancel(); - } - - /** - * Force-reload should not clean the blocker list. - */ - public void testForcedReloadKeepsWaiters() throws Exception { - reloadProjectSetup(); - - CountDownLatch blocker = new CountDownLatch(1); - AtomicReference reloadTask = new AtomicReference<>(); - reloadProjectImpl.scheduleProjectOperation(processor, () -> { - try { - blocker.await(); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - }, 0); - - synchronized (reloadProjectImpl) { - assertTrue("Project must not be reloading", reloadProjectImpl.getReloadTask().isFinished()); - reloadTask.set(reloadProjectImpl.fireProjectReload(false)); - assertFalse("Forced reload should be scheduled immediately", reloadProjectImpl.getReloadTask().isFinished()); - } - - - Pair, Task> blockState = reloadProjectImpl.reloadBlockingState(); - assertFalse(blockState.first().isEmpty()); - assertNull("No soft-reload was requested", blockState.second()); - reloadProjectImpl.fireProjectReload(true); - blockState = reloadProjectImpl.reloadBlockingState(); - assertNotNull("Soft-reload requested, completion task must have been created", blockState.second()); - blocker.countDown(); - } - - /** - * Reload is called several times while blocked. Should happen and fire just once after unblocking. - */ - public void testDelayedReloadTwiceHappensOnce() throws Exception { - reloadProjectSetup(); - - CountDownLatch blocker = new CountDownLatch(1); - Task reloadTask1; - Task reloadTask2; - reloadProjectImpl.scheduleProjectOperation(processor, () -> { - try { - blocker.await(); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - }, 0); - - assertTrue("Project must not be reloading", reloadProjectImpl.getReloadTask().isFinished()); - reloadTask1 = reloadProjectImpl.fireProjectReload(true); - reloadTask2 = reloadProjectImpl.fireProjectReload(true); - - blocker.countDown(); - - reloadTask1.waitFinished(10 * 1000); - reloadTask2.waitFinished(10 * 1000); - - assertEquals("Reload must complete exactly once", 1, this.projectEventCount.get()); - } - - public void testForcedReloadReloadsAgainAfterBlockersComplete() throws Exception { - reloadProjectSetup(); - CountDownLatch blocker = new CountDownLatch(1); - - reloadProjectImpl.scheduleProjectOperation(processor, () -> { - try { - blocker.await(); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - }, 0); - - Task reloadTask1; - Task reloadTask2; - reloadTask1 = reloadProjectImpl.fireProjectReload(true); - // now force-reload - reloadTask2 = reloadProjectImpl.fireProjectReload(false); - - reloadTask2.waitFinished(); - - assertEquals("The force-reload must complete and fire", 1, projectEventCount.get()); - blocker.countDown(); - - reloadTask1.waitFinished(); - assertEquals("The reload scheduled during blocker must run separately", 2, projectEventCount.get()); - } - - public void testDoubleBlockersReleaseAtEnd() throws Exception { - reloadProjectSetup(); - - CountDownLatch blocker = new CountDownLatch(1); - CountDownLatch blocker2 = new CountDownLatch(1); - - Task b1 = reloadProjectImpl.scheduleProjectOperation(processor, () -> { - try { - blocker.await(); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - }, 0); - - Task b2 = reloadProjectImpl.scheduleProjectOperation(processor, () -> { - try { - blocker2.await(); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - }, 0); - - - Pair, Task> blockState = reloadProjectImpl.reloadBlockingState(); - assertEquals("Two blockers are registered", 2, blockState.first().size()); - - RequestProcessor.Task t; - synchronized (reloadProjectImpl) { - t = reloadProjectImpl.fireProjectReload(true); - assertFalse(t.isFinished()); - } - - blocker.countDown(); - assertFalse("Blocked reload should be still unscheduled", t.waitFinished(300)); - blocker2.countDown(); - t.waitFinished(10 * 1000); - assertTrue(b1.isFinished()); - assertTrue(b2.isFinished()); - assertEquals("Project events must fire once", 1, projectEventCount.get()); - } - - public void testCompleteBlockersWithoutReloadDoesNotReload() throws Exception { - reloadProjectSetup(); - - CountDownLatch blocker = new CountDownLatch(1); - CountDownLatch blocker2 = new CountDownLatch(1); - - Task b1 = reloadProjectImpl.scheduleProjectOperation(processor, () -> { - try { - blocker.await(); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - }, 0); - - Task b2 = reloadProjectImpl.scheduleProjectOperation(processor, () -> { - try { - blocker2.await(); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - }, 0); - - - Pair, Task> blockState = reloadProjectImpl.reloadBlockingState(); - assertEquals(2, blockState.first().size()); - - blocker.countDown(); - blocker2.countDown(); - b1.waitFinished(10 * 1000); - b2.waitFinished(10 * 1000); - - blockState = reloadProjectImpl.reloadBlockingState(); - assertEquals(0, blockState.first().size()); - assertEquals(0, projectEventCount.get()); - } - - /** - * Checks that subproject reload after the subproject primes. - */ - public void testSubprojectsReloadAfterPriming() throws Exception { - cleanMavenRepository(); - clearWorkDir(); - - FileUtil.toFileObject(getWorkDir()).refresh(); - - FileObject testApp = dataFO.getFileObject("projects/multiproject/democa"); - FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "simpleProject"); - - Project p = ProjectManager.getDefault().findProject(prjCopy); - assertNotNull(p); - - Project sub = ProjectManager.getDefault().findProject(prjCopy.getFileObject("lib")); - assertNotNull(sub); - - // check the project's validity: - NbMavenProject subMaven = sub.getLookup().lookup(NbMavenProject.class); - assertTrue("Fallback parent project is expected on unpopulated repository", NbMavenProject.isErrorPlaceholder(subMaven.getMavenProject())); - assertTrue("Fallback subproject project is expected on unpopulated repository", NbMavenProject.isErrorPlaceholder(subMaven.getMavenProject())); - - primeProject(sub); - assertFalse("Subproject must recover after priming itself", NbMavenProject.isIncomplete(subMaven.getMavenProject())); - } - - /** - * Checks that Priming action on a subproject actually runs on a reactor with --auto-make to build the subproject. - * @throws Exception - */ - public void testSubprojectPrimeRunsReactor() throws Exception { - cleanMavenRepository(); - clearWorkDir(); - - mme = new MavenExecMonitor(); - MockLookup.setLayersAndInstances(mme); - - FileUtil.toFileObject(getWorkDir()).refresh(); - - FileObject testApp = dataFO.getFileObject("projects/multiproject/democa"); - FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "simpleProject"); - - Project p = ProjectManager.getDefault().findProject(prjCopy); - assertNotNull(p); - - Project sub = ProjectManager.getDefault().findProject(prjCopy.getFileObject("lib")); - assertNotNull(sub); - - // check the project's validity: - NbMavenProject subMaven = sub.getLookup().lookup(NbMavenProject.class); - assertTrue("Fallback parent project is expected on unpopulated repository", NbMavenProject.isErrorPlaceholder(subMaven.getMavenProject())); - assertTrue("Fallback subproject project is expected on unpopulated repository", NbMavenProject.isErrorPlaceholder(subMaven.getMavenProject())); - - primeProject(sub); - - assertEquals("Just single maven executed:", 1, mme.builders.size()); - - ProcessBuilder b = mme.builders.getFirst(); - assertEquals("Runs in root project's dir", FileUtil.toFile(prjCopy), b.directory()); - assertTrue("Specifies also-make", b.command().indexOf("--also-make") > 0); - int idx = b.command().indexOf("--projects"); - assertTrue("Specifies projects", idx > 0); - assertEquals("Runs up to the lib subprojectsd", "lib", b.command().get(idx + 1)); - } - - /** - * Checks that subproject reload after its parent project primes. - */ - public void testSubprojectsReloadAfterParentPriming() throws Exception { - String jv = System.getProperty("java.specification.version"); - Assume.assumeTrue("Need JDK17", !jv.startsWith("1.") && Integer.parseInt(jv) >= 17); - cleanMavenRepository(); - clearWorkDir(); - - FileUtil.toFileObject(getWorkDir()).refresh(); - - FileObject testApp = dataFO.getFileObject("projects/multiproject/democa"); - FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "simpleProject"); - - Project p = ProjectManager.getDefault().findProject(prjCopy); - assertNotNull(p); - - Project sub = ProjectManager.getDefault().findProject(prjCopy.getFileObject("lib")); - assertNotNull(sub); - - // check the project's validity: - NbMavenProject parentMaven = p.getLookup().lookup(NbMavenProject.class); - NbMavenProject subMaven = sub.getLookup().lookup(NbMavenProject.class); - assertTrue("Fallback parent project is expected on unpopulated repository", NbMavenProject.isErrorPlaceholder(subMaven.getMavenProject())); - assertTrue("Fallback subproject project is expected on unpopulated repository", NbMavenProject.isErrorPlaceholder(subMaven.getMavenProject())); - - primeProject(p); - // subprojects are reloaded asynchronously. Watch out for child project's property for some time. - CountDownLatch latch = new CountDownLatch(1); - subMaven.addPropertyChangeListener((e) -> { - if (NbMavenProject.PROP_PROJECT.equals(e.getPropertyName())) { - latch.countDown(); - } - }); - latch.await(10, TimeUnit.SECONDS); - assertFalse("Subproject must recover after priming the parent", NbMavenProject.isIncomplete(subMaven.getMavenProject())); - } -} diff --git a/java/maven/test/unit/src/org/netbeans/modules/maven/NbMavenProjectImplTest.java b/java/maven/test/unit/src/org/netbeans/modules/maven/NbMavenProjectImplTest.java index d2db62b8d349..5106ae265274 100644 --- a/java/maven/test/unit/src/org/netbeans/modules/maven/NbMavenProjectImplTest.java +++ b/java/maven/test/unit/src/org/netbeans/modules/maven/NbMavenProjectImplTest.java @@ -22,9 +22,6 @@ import java.io.IOException; import java.lang.ref.Reference; import java.lang.ref.WeakReference; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Collections; import java.util.Set; import java.util.TreeSet; diff --git a/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MavenExecMonitor.java b/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MavenExecMonitor.java deleted file mode 100644 index d7b3761bae51..000000000000 --- a/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MavenExecMonitor.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.netbeans.modules.maven.execute; - -import java.util.concurrent.ConcurrentLinkedDeque; -import org.netbeans.modules.maven.api.execute.RunConfig; -import org.openide.windows.InputOutput; - -/** - * - * @author sdedic - */ -public class MavenExecMonitor extends MavenCommandLineExecutor.ExecuteMaven { - public ConcurrentLinkedDeque builders = new ConcurrentLinkedDeque<>(); - - @Override - MavenExecutor createCommandLineExecutor(RunConfig config, InputOutput io, AbstractMavenExecutor.TabContext tc) { - return new CmdlineExecutor(config, io, tc); - } - - class CmdlineExecutor extends MavenCommandLineExecutor { - - public CmdlineExecutor(RunConfig conf, InputOutput io, TabContext tc) { - super(conf, io, tc); - } - - @Override - ProcessBuilder constructBuilder(RunConfig clonedConfig, InputOutput ioput) { - ProcessBuilder b = super.constructBuilder(clonedConfig, ioput); - builders.add(b); - return b; - } - } -} diff --git a/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MockMavenExec.java b/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MockMavenExec.java index 03e4367210f6..cf1217e9a4ae 100644 --- a/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MockMavenExec.java +++ b/java/maven/test/unit/src/org/netbeans/modules/maven/execute/MockMavenExec.java @@ -28,23 +28,14 @@ */ public class MockMavenExec extends MavenCommandLineExecutor.ExecuteMaven { - public static class Reporter { - public volatile boolean executed; - public volatile RunConfig executedConfig; - public CountDownLatch executedLatch = new CountDownLatch(1); - - public void executed(RunConfig config) { - executed = true; - executedConfig = config; - } - } + public volatile boolean executed; + public volatile RunConfig executedConfig; + public CountDownLatch executedLatch = new CountDownLatch(1); @Override public ExecutorTask execute(RunConfig config, InputOutput io, AbstractMavenExecutor.TabContext tc) { - Reporter r = config.getActionContext().lookup(Reporter.class); - if (r != null) { - r.executed(config); - } + executed = true; + executedConfig = config; ExecutorTask t = new ExecutorTask(() -> { }) { @Override @@ -62,9 +53,7 @@ public InputOutput getInputOutput() { } }; t.run(); - if (r != null) { - r.executedLatch.countDown(); - } + executedLatch.countDown(); return t; } diff --git a/java/maven/test/unit/src/org/netbeans/modules/maven/problems/PrimingActionTest.java b/java/maven/test/unit/src/org/netbeans/modules/maven/problems/PrimingActionTest.java index f49a5090500a..60d6dab6cdf5 100644 --- a/java/maven/test/unit/src/org/netbeans/modules/maven/problems/PrimingActionTest.java +++ b/java/maven/test/unit/src/org/netbeans/modules/maven/problems/PrimingActionTest.java @@ -172,13 +172,13 @@ public void testActionNotEnabledOnOKProject() throws Exception { assertFalse(enabled); } + /** * Checks that the priming build does not actually run on OK project, although * the action may be temporarily enabled. */ public void testPrimingBuildNotRunOnOK() throws Exception { MockMavenExec mme = new MockMavenExec(); - MockMavenExec.Reporter r = new MockMavenExec.Reporter(); MockLookup.setLayersAndInstances(mme); CountDownLatch cdl = new CountDownLatch(1); MavenModelProblemsProvider.RP.submit(() -> { @@ -194,8 +194,7 @@ public void testPrimingBuildNotRunOnOK() throws Exception { Collection probs = collectProblems(p); assertEquals(0, probs.size()); ActionProvider ap = p.getLookup().lookup(ActionProvider.class); - - boolean enabled = ap.isActionEnabled(ActionProvider.COMMAND_PRIME, Lookups.fixed(r)); + boolean enabled = ap.isActionEnabled(ActionProvider.COMMAND_PRIME, Lookup.EMPTY); // the actual detection is still broken. assertTrue(enabled); @@ -229,7 +228,7 @@ public void finished(boolean success) { assertTrue(progress.finished); // but the execution was NOT really done - assertFalse(r.executed); + assertFalse(mme.executed); // check that the action is now disabled. assertFalse(ap.isActionEnabled(ActionProvider.COMMAND_PRIME, Lookup.EMPTY)); @@ -245,13 +244,12 @@ public void testPrimingBuildExecutes() throws Exception { System.setProperty("test.reload.sync", "true"); - MockMavenExec.Reporter r = new MockMavenExec.Reporter(); setupBrokenProject(); Project p = ProjectManager.getDefault().findProject(FileUtil.toFileObject(getWorkDir())); Collection probs = collectProblems(p); assertEquals(1, probs.size()); ActionProvider ap = p.getLookup().lookup(ActionProvider.class); - boolean enabled = ap.isActionEnabled(ActionProvider.COMMAND_PRIME, Lookups.fixed(r)); + boolean enabled = ap.isActionEnabled(ActionProvider.COMMAND_PRIME, Lookup.EMPTY); assertTrue(enabled); class Prog extends ActionProgress { CountDownLatch finish = new CountDownLatch(1); @@ -272,10 +270,10 @@ public void finished(boolean success) { Prog progress = new Prog(); - ap.invokeAction(ActionProvider.COMMAND_PRIME, Lookups.fixed(progress, r)); + ap.invokeAction(ActionProvider.COMMAND_PRIME, Lookups.fixed(progress)); progress.finish.await(); // but the execution was NOT really done - assertTrue(r.executed); + assertTrue(mme.executed); } } diff --git a/java/maven/test/unit/src/org/netbeans/modules/maven/spi/actions/ProvidedConfigurationsTest.java b/java/maven/test/unit/src/org/netbeans/modules/maven/spi/actions/ProvidedConfigurationsTest.java index 1183cfe90e71..d15793e1be20 100644 --- a/java/maven/test/unit/src/org/netbeans/modules/maven/spi/actions/ProvidedConfigurationsTest.java +++ b/java/maven/test/unit/src/org/netbeans/modules/maven/spi/actions/ProvidedConfigurationsTest.java @@ -241,7 +241,6 @@ public void testContributedProfileActionCanCustomize() throws Exception { */ public void testExampleProviderConfigurationUsage() throws Exception { MockMavenExec mme = new MockMavenExec(); - MockMavenExec.Reporter r = new MockMavenExec.Reporter(); MockLookup.setLayersAndInstances(mme); setupOKProject(); @@ -253,15 +252,15 @@ public void testExampleProviderConfigurationUsage() throws Exception { ProjectConfigurationProvider pcp = p.getLookup().lookup(ProjectConfigurationProvider.class); ProjectConfiguration configToUse = pcp.getConfigurations().stream(). filter(x -> "Micronaut: dev mode".equals(x.getDisplayName())).findAny().get(); - Lookup ctx = Lookups.fixed(theFile, configToUse, r); + Lookup ctx = Lookups.fixed(theFile, configToUse); if (!ap.isActionEnabled(ActionProvider.COMMAND_RUN, ctx)) { // action not enabled return; } ap.invokeAction(ActionProvider.COMMAND_RUN, ctx); - r.executedLatch.await(); - assertEquals(Arrays.asList("mn:run"), r.executedConfig.getGoals()); + mme.executedLatch.await(); + assertEquals(Arrays.asList("mn:run"), mme.executedConfig.getGoals()); } @ProjectServiceProvider(service = MavenActionsProvider.class, projectType = NbMavenProject.TYPE) From 36a9b160decfad0ff6d9cfa1b9b6f950dbcf16d4 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Thu, 26 Oct 2023 22:47:11 +0200 Subject: [PATCH 2/8] [NETBEANS-6599] Do not throw a CompletionFailure for empty java.lang package outside of java.base. --- .../org/netbeans/lib/nbjavac/services/NBClassFinder.java | 5 +++++ .../netbeans/lib/nbjavac/services/NBClassFinderTest.java | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBClassFinder.java b/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBClassFinder.java index 11f67b376918..7e91e79cbbf1 100644 --- a/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBClassFinder.java +++ b/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBClassFinder.java @@ -24,6 +24,8 @@ import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.Completer; import com.sun.tools.javac.code.Symbol.CompletionFailure; +import com.sun.tools.javac.code.Symbol.PackageSymbol; +import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.JCDiagnostic; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticInfo; @@ -54,6 +56,7 @@ public ClassFinder make(Context c) { private final Context context; private final Names names; + private final Symtab syms; private final JCDiagnostic.Factory diagFactory; private final Log log; @@ -61,6 +64,7 @@ public NBClassFinder(Context context) { super(context); this.context = context; this.names = Names.instance(context); + this.syms = Symtab.instance(context); this.diagFactory = JCDiagnostic.Factory.instance(context); this.log = Log.instance(context); } @@ -95,6 +99,7 @@ public Completer getCompleter() { delegate.complete(sym); if (sym.kind == Kind.PCK && sym.flatName() == names.java_lang && + ((PackageSymbol) sym).modle == syms.java_base && sym.members().isEmpty()) { sym.flags_field |= Flags.EXISTS; try { diff --git a/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBClassFinderTest.java b/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBClassFinderTest.java index 9e3df9b1406d..1181762d0efd 100644 --- a/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBClassFinderTest.java +++ b/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBClassFinderTest.java @@ -69,6 +69,15 @@ public void testEmptyClassPath() throws Exception { assertEquals(expectedErrors, actualErrors); } + public void testEmptyClassPath2() throws Exception { + String code = "package java.lang.nb.test; public class Test { String t(String s) { return s.toString(); } }"; + List expectedErrors; + expectedErrors = Arrays.asList(""); + List actualErrors; + actualErrors = compile(code, "-XDrawDiagnostics", "-XDide", "-Xlint:-options"); + assertEquals(expectedErrors, actualErrors); + } + private static class MyFileObject extends SimpleJavaFileObject { private String text; From 6468b247675ed17dc11b3b7a1810a5f9d3cd2e7f Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 30 Oct 2023 15:09:13 +0100 Subject: [PATCH 3/8] [JAVAVSCODE-53] Assignments to parameters to record compact constructors should not be marked as unused. --- .../hints/bugs/UnusedAssignmentOrBranch.java | 28 ++++++++++++++++--- .../bugs/UnusedAssignmentOrBranchTest.java | 27 ++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/UnusedAssignmentOrBranch.java b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/UnusedAssignmentOrBranch.java index 1ec8ac006187..0e13f8e6d68f 100644 --- a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/UnusedAssignmentOrBranch.java +++ b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/UnusedAssignmentOrBranch.java @@ -31,6 +31,7 @@ import java.util.Set; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import org.netbeans.api.java.source.CompilationInfo; @@ -133,25 +134,44 @@ private static Pair, Set> computeUsedAssignments(final HintCo @TriggerPattern("$mods$ $type $var = $value;") }) public static ErrorDescription unusedAssignment(final HintContext ctx) { + final CompilationInfo info = ctx.getInfo(); + Element var = info.getTrees().getElement(ctx.getVariables().get("$var")); + + if (var == null || !LOCAL_VARIABLES.contains(var.getKind()) || + isImplicitParamOfRecordCanonicalConstructor(info, var)) { + return null; + } + final String unusedAssignmentLabel = NbBundle.getMessage(UnusedAssignmentOrBranch.class, "LBL_UNUSED_ASSIGNMENT_LABEL"); Pair, Set> computedAssignments = computeUsedAssignments(ctx); if (ctx.isCanceled() || computedAssignments == null) return null; - final CompilationInfo info = ctx.getInfo(); final Set usedAssignments = computedAssignments.first(); final Set usedVariables = computedAssignments.second(); - Element var = info.getTrees().getElement(ctx.getVariables().get("$var")); TreePath valuePath = ctx.getVariables().get("$value"); Tree value = (valuePath == null ? ctx.getPath() : valuePath).getLeaf(); - if (var != null && LOCAL_VARIABLES.contains(var.getKind()) && !usedAssignments.contains(value) && usedVariables.contains(var)) { + if (!usedAssignments.contains(value) && usedVariables.contains(var)) { return ErrorDescriptionFactory.forTree(ctx, value, unusedAssignmentLabel); } return null; } - + + private static boolean isImplicitParamOfRecordCanonicalConstructor(CompilationInfo info, Element el) { + Element enclosingElement = el.getEnclosingElement(); + + if (enclosingElement.getKind() != ElementKind.CONSTRUCTOR) { + return false; + } + + ExecutableElement constr = (ExecutableElement) enclosingElement; + + return info.getElements().isCompactConstructor(constr) && + constr.getParameters().contains(el); + } + private static boolean mayHaveSideEffects(HintContext ctx, TreePath path) { SideEffectVisitor visitor = new SideEffectVisitor(ctx).stopOnUnknownMethods(true); Tree culprit = null; diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedAssignmentOrBranchTest.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedAssignmentOrBranchTest.java index c03f5d9fc7a2..94532dbf045a 100644 --- a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedAssignmentOrBranchTest.java +++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedAssignmentOrBranchTest.java @@ -18,6 +18,7 @@ */ package org.netbeans.modules.java.hints.bugs; +import org.junit.Assume; import org.netbeans.junit.NbTestCase; import org.netbeans.modules.java.hints.test.api.HintTest; @@ -211,4 +212,30 @@ public void testImplicitlyStaticFieldWithInitializer() throws Exception { .run(UnusedAssignmentOrBranch.class) .assertWarnings(); } + + public void testRecordCompactConstructor() throws Exception { + Assume.assumeTrue(isRecordClassPresent()); + + HintTest + .create() + .input("package test;\n" + + "\n" + + "public record Test(int i, int j) {\n" + + " public Test {\n" + + " i = -i;\n" + + " }\n" + + "}") + .sourceLevel("21") + .run(UnusedAssignmentOrBranch.class) + .assertWarnings(); + } + + private boolean isRecordClassPresent() { + try { + Class.forName("java.lang.Record"); + return true; + } catch (ClassNotFoundException ex) { + return false; + } + } } From 0136307ef350e47ceab15cdb1bb4487802b2b853 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 31 Oct 2023 08:26:41 +0100 Subject: [PATCH 4/8] [NETBEANS-6638]: Avoid adding a space after opening curly brace. --- .../netbeans/modules/editor/java/TypingCompletion.java | 10 ++++++++-- .../modules/editor/java/TypingCompletionUnitTest.java | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java b/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java index 59340af52c2e..5f2172b49d88 100644 --- a/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java +++ b/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java @@ -168,8 +168,10 @@ static void completeOpeningBracket(TypedTextInterceptor.MutableContext context) return; } + char insChr = context.getText().charAt(0); + if (isString(currentToken)) { - if (context.getOffset() >= 1 && context.getText().charAt(0) == '{') { + if (context.getOffset() >= 1 && insChr == '{') { char chr = context.getDocument().getText(context.getOffset() - 1, 1).charAt(0); if (chr == '\\') { @@ -180,10 +182,14 @@ static void completeOpeningBracket(TypedTextInterceptor.MutableContext context) return ; } + if (insChr == '{') { + //curly brace should only be matched in string templates: + return ; + } + char chr = context.getDocument().getText(context.getOffset(), 1).charAt(0); if (chr == ')' || chr == ',' || chr == '\"' || chr == '\'' || chr == ' ' || chr == ']' || chr == '}' || chr == '\n' || chr == '\t' || chr == ';') { - char insChr = context.getText().charAt(0); context.setText("" + insChr + matching(insChr), 1); // NOI18N } } diff --git a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java index 1b6ca1162506..a0713d608f6c 100644 --- a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java +++ b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java @@ -1413,6 +1413,12 @@ public void testSkipTemplate1() throws Exception { ctx.assertDocumentTextEquals("\"\\{}|\""); } + public void testX() throws Exception { + Context ctx = new Context(new JavaKit(), ""); + ctx.typeChar('{'); + ctx.assertDocumentTextEquals("{"); + } + private boolean isInsideString(String code) throws BadLocationException { int pos = code.indexOf('|'); From 7b478ba8ba11c57fa3aa94568dac1b71219be01b Mon Sep 17 00:00:00 2001 From: Alexey Borokhvostov Date: Tue, 31 Oct 2023 20:15:01 +0700 Subject: [PATCH 5/8] PHP: Fix autocomplete for exception class when adding exception breakpoint. --- .../php/dbgp/ui/completion/ExceptionCompletionItem.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionCompletionItem.java b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionCompletionItem.java index fb4bfa39f9d2..65dfc1580088 100644 --- a/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionCompletionItem.java +++ b/php/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/completion/ExceptionCompletionItem.java @@ -155,7 +155,7 @@ public int getSortPriority() { @Override public CharSequence getSortText() { - return getName(); + return element.getName(); } @Override @@ -164,7 +164,7 @@ public CharSequence getInsertPrefix() { } public String getName() { - return element.getName(); + return element.getNamespaceName().append(element.getName()).toString(); } public static class Builtin extends ExceptionCompletionItem { @@ -201,6 +201,11 @@ public int getSortPriority() { return -1; } + @Override + public CharSequence getSortText() { + return this.element; + } + @Override public CharSequence getInsertPrefix() { return element; From 9e4a2603dd3416b3e68e23ad5b53084a143c4367 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 31 Oct 2023 16:42:33 +0100 Subject: [PATCH 6/8] [NETBEANS-5659] Collection.forEach is always a read from the collection. --- .../modules/java/hints/bugs/Unbalanced.java | 9 +++- .../java/hints/bugs/UnbalancedTest.java | 49 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Unbalanced.java b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Unbalanced.java index 01f969084f59..126b3a218be6 100644 --- a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Unbalanced.java +++ b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Unbalanced.java @@ -199,8 +199,10 @@ public static final class Collection { private static final Set READ_METHODS = new HashSet<>(Arrays.asList( "get", "getOrDefault", "contains", "remove", "containsAll", "removeAll", "removeIf", "retain", "retainAll", "containsKey", "containsValue", "iterator", "listIterator", "isEmpty", "size", "toArray", "entrySet", "keySet", "values", "indexOf", "lastIndexOf", - "stream", "parallelStream", "spliterator", "forEach")); - private static final Set WRITE_METHODS = new HashSet<>(Arrays.asList("add", "addAll", "set", "put", "putAll", "putIfAbsent")); + "stream", "parallelStream", "spliterator", "reversed", "getFirst", "getLast", "removeFirst", "removeLast")); + private static final Set STANDALONE_READ_METHODS = new HashSet<>(Arrays.asList( + "forEach")); + private static final Set WRITE_METHODS = new HashSet<>(Arrays.asList("add", "addAll", "set", "put", "putAll", "putIfAbsent", "addFirst", "addLast")); private static boolean testType(CompilationInfo info, TypeMirror actualType, String superClass) { TypeElement juCollection = info.getElements().getTypeElement(superClass); @@ -244,6 +246,9 @@ public static ErrorDescription before(HintContext ctx) { record(ctx.getInfo(), var, State.READ); } return null; + } else if (STANDALONE_READ_METHODS.contains(methodName)) { + record(ctx.getInfo(), var, State.READ); + return null; } else if (WRITE_METHODS.contains(methodName)) { if (tp.getParentPath().getParentPath().getParentPath().getLeaf().getKind() != Kind.EXPRESSION_STATEMENT) { record(ctx.getInfo(), var, State.WRITE, State.READ); diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnbalancedTest.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnbalancedTest.java index fbd11e325505..8df9338bbf73 100644 --- a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnbalancedTest.java +++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnbalancedTest.java @@ -527,4 +527,53 @@ public void testCollectionNegEnhForLoop() throws Exception { .run(Unbalanced.Collection.class) .assertWarnings(); } + + public void testListForEach() throws Exception { + HintTest + .create() + .input("package test;\n" + + "public class Test {\n" + + " public void t() {\n" + + " java.util.List coll = new java.util.ArrayList();\n" + + " coll.add(\"\");\n" + + " coll.forEach(e -> {});\n" + + " }\n" + + "}\n") + .run(Unbalanced.Collection.class) + .assertWarnings(); + } + + public void testSequencedCollection1() throws Exception { + HintTest + .create() + .input("package test;\n" + + "public class Test {\n" + + " public void t() {\n" + + " java.util.List coll = new java.util.ArrayList();\n" + + " coll.addFirst(\"\");\n" + + " coll.addLast(\"\");\n" + + " }\n" + + "}\n", false) + .run(Unbalanced.Collection.class) + .assertWarnings("3:31-3:35:verifier:ERR_UnbalancedCollectionWRITE coll"); + } + + public void testSequencedCollection2() throws Exception { + HintTest + .create() + .input("package test;\n" + + "public class Test {\n" + + " public void t() {\n" + + " java.util.List coll = new java.util.ArrayList();\n" + + " Object sink;\n" + + " sink = coll.reversed();\n" + + " sink = coll.getFirst();\n" + + " sink = coll.getLast();\n" + + " sink = coll.removeFirst();\n" + + " sink = coll.removeLast();\n" + + " }\n" + + "}\n", false) + .run(Unbalanced.Collection.class) + .assertWarnings("3:31-3:35:verifier:ERR_UnbalancedCollectionREAD coll"); + } } From 0e0560d95027d4fca137921bcb480e3d8fad6076 Mon Sep 17 00:00:00 2001 From: Neil C Smith Date: Tue, 31 Oct 2023 14:21:57 +0000 Subject: [PATCH 7/8] Drop horizontal scroll mouse button events on Linux to fix trackpad issues. --- .../modules/editor/resources/NetBeans-keybindings.xml | 2 -- .../windows/ShortcutAndMenuKeyEventProcessor.java | 11 ++++++++++- .../src/org/openide/util/Utilities.java | 8 +++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ide/editor/src/org/netbeans/modules/editor/resources/NetBeans-keybindings.xml b/ide/editor/src/org/netbeans/modules/editor/resources/NetBeans-keybindings.xml index 9181a8ec6a2f..fcb9bc4caad6 100644 --- a/ide/editor/src/org/netbeans/modules/editor/resources/NetBeans-keybindings.xml +++ b/ide/editor/src/org/netbeans/modules/editor/resources/NetBeans-keybindings.xml @@ -97,11 +97,9 @@ - - diff --git a/platform/core.windows/src/org/netbeans/core/windows/ShortcutAndMenuKeyEventProcessor.java b/platform/core.windows/src/org/netbeans/core/windows/ShortcutAndMenuKeyEventProcessor.java index 4d8eea21ad1d..f26e59f59b7e 100644 --- a/platform/core.windows/src/org/netbeans/core/windows/ShortcutAndMenuKeyEventProcessor.java +++ b/platform/core.windows/src/org/netbeans/core/windows/ShortcutAndMenuKeyEventProcessor.java @@ -318,11 +318,20 @@ private void processMouseEvent(MouseEvent mev) { || mev.isConsumed()) { return; } + int button = mev.getButton(); + if (Utilities.getOperatingSystem() == Utilities.OS_LINUX) { + // the JDK drops buttons for vertical scroll + // drop buttons for horizontal scroll here. + button -= 2; + if (button <= 3) { + return; + } + } //ignore when the IDE is shutting down if (NbLifecycleManager.isExiting()) { return; } - int keycode = Utilities.mouseButtonKeyCode(mev.getButton()); + int keycode = Utilities.mouseButtonKeyCode(button); if (keycode == KeyEvent.VK_UNDEFINED) { return; } diff --git a/platform/openide.util.ui/src/org/openide/util/Utilities.java b/platform/openide.util.ui/src/org/openide/util/Utilities.java index faf0d04f8872..29402965a749 100644 --- a/platform/openide.util.ui/src/org/openide/util/Utilities.java +++ b/platform/openide.util.ui/src/org/openide/util/Utilities.java @@ -842,7 +842,13 @@ public static int mouseWheelDownKeyCode() { * {@link KeyEvent#VK_UNDEFINED} if not available. *

* Implementation note : only extended mouse buttons in the range BUTTON4 to - * BUTTON9 are currently mapped to keycodes. + * BUTTON9 are currently mapped to keycodes. The caller may pass in values + * that best reflect the desired mouse button rather than the actual value + * from the OS or MouseEvent. eg. on Linux, the JDK excludes X button values + * for vertical scrolling when generating the range of buttons, and the + * default NetBeans window system further excludes the horizontal scroll + * button values - button 4 passed in here might be JDK button 6 and X event + * button 8. * * @param button mouse button * @return keycode if defined From 77185eab0f6a40b02364063ae383a0af967ceff2 Mon Sep 17 00:00:00 2001 From: Neil C Smith Date: Thu, 2 Nov 2023 12:06:17 +0000 Subject: [PATCH 8/8] Enable JUnit output processing if the Maven goals include failsafe:integration-test --- .../modules/maven/junit/JUnitOutputProcessorFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/maven.junit/src/org/netbeans/modules/maven/junit/JUnitOutputProcessorFactory.java b/java/maven.junit/src/org/netbeans/modules/maven/junit/JUnitOutputProcessorFactory.java index e9d09d953d58..060100b174c7 100644 --- a/java/maven.junit/src/org/netbeans/modules/maven/junit/JUnitOutputProcessorFactory.java +++ b/java/maven.junit/src/org/netbeans/modules/maven/junit/JUnitOutputProcessorFactory.java @@ -48,8 +48,9 @@ public Set createProcessorsSet(Project project, RunConfig confi if (config.getGoals().contains("test") //NOI18N || config.getGoals().contains("integration-test") //NOI18N || config.getGoals().contains("surefire:test") //NOI81N + || config.getGoals().contains("failsafe:integration-test") //NOI18N || config.getGoals().contains("verify")) { //NOI18N - Set toReturn = new HashSet(); + Set toReturn = new HashSet<>(); if (project != null) { toReturn.add(new JUnitOutputListenerProvider(config)); }