From 4e5200e54b164b755bad92f5518a029e545efc08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= <laeubi@laeubi-soft.de> Date: Fri, 24 Jan 2025 18:11:11 +0100 Subject: [PATCH] Support specification of an application to run In some cases one might want a special application (e.g. a full IDE) to start for a build, this is now possible by using the application parameter (cherry picked from commit 46edccf1cc1b8982f86b97d7e6d390efc103babb) --- .../osgi/framework/EclipseFramework.java | 20 +++++++++++++ .../eclipsebuild/AbstractEclipseBuild.java | 10 ++++++- .../AbstractEclipseBuildMojo.java | 29 ++++++++++++++++++- .../tycho/eclipsebuild/SetTargetPlatform.java | 3 ++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/tycho-core/src/main/java/org/eclipse/tycho/osgi/framework/EclipseFramework.java b/tycho-core/src/main/java/org/eclipse/tycho/osgi/framework/EclipseFramework.java index e546276f60..c00432c19e 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/osgi/framework/EclipseFramework.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/osgi/framework/EclipseFramework.java @@ -37,6 +37,7 @@ import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.launch.Framework; +import org.osgi.util.tracker.ServiceTracker; public class EclipseFramework implements AutoCloseable { @@ -84,6 +85,25 @@ public void start() throws Exception { } } + public boolean waitForApplicationStart(long timeout) { + String[] args = configuration.getNonFrameworkArgs(); + for (String arg : args) { + if (EclipseApplication.ARG_APPLICATION.equals(arg)) { + ServiceTracker<ApplicationLauncher, Object> tracker = new ServiceTracker<>(framework.getBundleContext(), + ApplicationLauncher.class, null); + tracker.open(true); + try { + return tracker.waitForService(timeout) != null; + } catch (InterruptedException e) { + return false; + } finally { + tracker.close(); + } + } + } + return true; + } + private int launchApplication(BundleContext systemBundleContext, EquinoxConfiguration configuration) throws Exception { EclipseAppLauncher appLauncher = new EclipseAppLauncher(systemBundleContext, false, true, null, configuration); diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuild.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuild.java index 46c449db14..5e67dbec89 100644 --- a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuild.java +++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuild.java @@ -19,6 +19,7 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.jobs.Job; /** * Abstract class for performing a build and producing a result @@ -42,7 +43,7 @@ public final Result call() throws Exception { deleteAllProjects(); IProject project = importProject(); project.build(IncrementalProjectBuilder.CLEAN_BUILD, this); - project.build(IncrementalProjectBuilder.FULL_BUILD, this); + buildProject(project); Result result = createResult(project); for (IMarker marker : project.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE)) { result.addMarker(marker); @@ -52,6 +53,13 @@ public final Result call() throws Exception { return result; } + protected void buildProject(IProject project) throws CoreException { + project.build(IncrementalProjectBuilder.FULL_BUILD, this); + while (!Job.getJobManager().isIdle()) { + Thread.yield(); + } + } + protected abstract Result createResult(IProject project) throws Exception; static void disableAutoBuild() throws CoreException { diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuildMojo.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuildMojo.java index 07e4c0206c..ff5b3492f3 100644 --- a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuildMojo.java +++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuildMojo.java @@ -21,6 +21,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -80,6 +81,8 @@ public abstract class AbstractEclipseBuildMojo<Result extends EclipseBuildResult @Parameter(defaultValue = "false") private boolean failOnResolutionError; + @Parameter + private String application; /** * Controls if the local target platform of the project should be used to * resolve the eclipse application @@ -137,11 +140,35 @@ public final void execute() throws MojoExecutionException, MojoFailureException } else { application = eclipseApplicationManager.getApplication(eclipseRepository, bundles, features, getName()); } + List<String> arguments; + String applicationName = this.application; + boolean useApplication = applicationName != null; + if (useApplication) { + arguments = List.of(EclipseApplication.ARG_APPLICATION, applicationName); + } else { + arguments = List.of(); + } try (EclipseFramework framework = application.startFramework(workspaceManager - .getWorkspace(EclipseApplicationManager.getRepository(eclipseRepository).getURL(), this), List.of())) { + .getWorkspace(EclipseApplicationManager.getRepository(eclipseRepository).getURL(), this), arguments)) { if (debug) { framework.printState(); } + if (useApplication) { + Thread thread = new Thread(new Runnable() { + + @Override + public void run() { + try { + framework.start(); + } catch (Exception e) { + getLog().error("Running application " + applicationName + " failed", e); + } + } + }); + thread.setName(getName() + " Application Thread"); + thread.start(); + framework.waitForApplicationStart(TimeUnit.SECONDS.toMillis(30)); + } if (hasPDENature(eclipseProject)) { if (framework.hasBundle(Bundles.BUNDLE_PDE_CORE)) { framework.execute(new SetTargetPlatform(projectDependencies, debug)); diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/SetTargetPlatform.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/SetTargetPlatform.java index c0e1473d7b..816956a41d 100644 --- a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/SetTargetPlatform.java +++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/SetTargetPlatform.java @@ -22,6 +22,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.ILogListener; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.pde.core.target.ITargetDefinition; @@ -29,6 +30,7 @@ import org.eclipse.pde.core.target.ITargetPlatformService; import org.eclipse.pde.core.target.LoadTargetDefinitionJob; import org.eclipse.pde.core.target.TargetBundle; +import org.eclipse.pde.internal.core.PluginModelManager; import org.eclipse.pde.internal.core.target.TargetPlatformService; public class SetTargetPlatform implements Callable<Serializable>, Serializable { @@ -64,6 +66,7 @@ public Serializable call() throws Exception { Job job = new LoadTargetDefinitionJob(target); job.schedule(); job.join(); + Job.getJobManager().join(PluginModelManager.class, new NullProgressMonitor()); return null; }