Skip to content

Commit

Permalink
Replace EclipseProject with custom local tooling model
Browse files Browse the repository at this point in the history
  • Loading branch information
donat committed Apr 13, 2022
1 parent ce39adf commit f689a4c
Show file tree
Hide file tree
Showing 34 changed files with 770 additions and 104 deletions.
Binary file added buildSrc/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 5 additions & 0 deletions buildSrc/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,20 @@ class ConvertOsgiBundleTask extends DefaultTask {
createNewBundle(project, JarBundleUtils.firstDependencyJar(pluginConfiguration))
}

void createNewBundle(Project project, File jar) {
void createNewBundle(Project project, File depJar) {
String sourceReference = PluginUtils.sourceReference(project)
String manifest = JarBundleUtils.manifestContent(jar, template.get(), packageFilter.get(), bundleVersion.get(), qualifier.get(), sourceReference)
Iterable<File> localJars = project.tasks['jar'].outputs.files
String manifest = JarBundleUtils.manifestContent([depJar] + localJars, template.get(), packageFilter.get(), bundleVersion.get(), qualifier.get(), sourceReference)

File extraResources = project.file("${project.buildDir}/tmp/bundle-resources")
File manifestFile = new File(extraResources, '/META-INF/MANIFEST.MF')
manifestFile.parentFile.mkdirs()
manifestFile.text = manifest

File osgiJar = new File(target, "osgi_${jar.name}")
File osgiJar = new File(target, "osgi_${project.name}.jar")
project.ant.zip(destfile: osgiJar) {
zipfileset(src: jar, excludes: 'META-INF/MANIFEST.MF')
localJars.each { jar -> zipfileset(src: jar, excludes: 'META-INF/MANIFEST.MF')}
zipfileset(src: depJar, excludes: 'META-INF/MANIFEST.MF')
}

project.ant.zip(update: 'true', destfile: osgiJar) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@ import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ResolvedArtifact
import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileCollection
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.provider.Property
import org.gradle.api.specs.Specs
import org.gradle.plugins.ide.eclipse.EclipsePlugin
import org.gradle.plugins.ide.eclipse.model.Library

Expand Down Expand Up @@ -51,7 +47,7 @@ class ExistingJarBundlePlugin implements Plugin<Project> {

@Override
public void apply(Project project) {
project.getPluginManager().apply(BasePlugin.class)
project.getPluginManager().apply(JavaPlugin.class)

configureExtensions(project)
configureConfigurations(project)
Expand All @@ -75,15 +71,15 @@ class ExistingJarBundlePlugin implements Plugin<Project> {
lib.sourcePath = fileReference(sourceJarName(project))
entries += lib
}

project.tasks[EclipsePlugin.ECLIPSE_CP_TASK_NAME].dependsOn TASK_NAME_CONVERT_TO_BUNDLE
project.tasks[EclipsePlugin.ECLIPSE_CP_TASK_NAME].doLast {
// copy jar file into project
File jar = JarBundleUtils.firstDependencyJar(getPluginConfiguration(project))
String jarName = jarName(project)
File depJar = JarBundleUtils.firstDependencyJar(getPluginConfiguration(project))
File localJar = (project.tasks[TASK_NAME_CONVERT_TO_BUNDLE].target as File).listFiles()[0]
project.copy {
from jar
from localJar
into project.file('.')
rename { jarName }
rename { jarName(project) }
}

// copy the source jar file into project
Expand All @@ -100,7 +96,7 @@ class ExistingJarBundlePlugin implements Plugin<Project> {
String bundleVersion = project.extensions.bundleInfo.bundleVersion.get()
String qualifier = 'qualifier'
project.file('META-INF').mkdirs()
project.file('META-INF/MANIFEST.MF').text = JarBundleUtils.manifestContent(jar, template, packageFilter, bundleVersion, qualifier)
project.file('META-INF/MANIFEST.MF').text = JarBundleUtils.manifestContent([depJar, localJar], template, packageFilter, bundleVersion, qualifier).replace("Bundle-ClassPath: .", "Bundle-ClassPath: ${jarName(project)}")
}
}
}
Expand All @@ -109,7 +105,6 @@ class ExistingJarBundlePlugin implements Plugin<Project> {
project.tasks.create(TASK_NAME_CONVERT_TO_BUNDLE, ConvertOsgiBundleTask) {
group = Constants.gradleTaskGroupName
dependsOn project.getConfigurations().getByName(PLUGIN_CONFIGURATION_NAME)

bundleName = project.extensions.bundleInfo.bundleName
bundleVersion = project.extensions.bundleInfo.bundleVersion
qualifier = project.extensions.bundleInfo.qualifier
Expand All @@ -118,6 +113,7 @@ class ExistingJarBundlePlugin implements Plugin<Project> {
resources = project.extensions.bundleInfo.resources
target = new File(project.buildDir, "$BUNDLES_STAGING_FOLDER/plugins")
pluginConfiguration = getPluginConfiguration(project)
dependsOn 'jar'
}
}

Expand Down
27 changes: 14 additions & 13 deletions buildSrc/src/main/groovy/eclipsebuild/jar/JarBundleUtils.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,27 @@ class JarBundleUtils {
dependency.moduleArtifacts.find { it.classifier == 'sources' }
}


static String manifestContent(File jar, String template, String packageFilter, String bundleVersion, String qualifier, String sourceReference = null) {
List<String> packageNames = packageNames(jar, packageFilter) as List
static String manifestContent(Iterable<File> jars, String template, String packageFilter, String bundleVersion, String qualifier, String sourceReference = null) {
List<String> packageNames = packageNames(jars, packageFilter) as List
packageNames.sort()
String fullVersion = "${bundleVersion}.${qualifier}"
manifestFor(template, packageNames, bundleVersion, fullVersion, sourceReference)
}

private static Set<String> packageNames(File jar, String filteredPackagesPattern) {
private static Set<String> packageNames(Iterable<File> jars, String filteredPackagesPattern) {
def result = [] as Set
Pattern filteredPackages = Pattern.compile(filteredPackagesPattern)
new ZipInputStream(new FileInputStream(jar)).withCloseable { zip ->
ZipEntry e
while (e = zip.nextEntry) {
if (!e.directory && e.name.endsWith(".class")) {
int index = e.name.lastIndexOf('/')
if (index < 0) index = e.name.length()
String packageName = e.name.substring(0, index).replace('/', '.')
if (!packageName.matches(filteredPackages)) {
result.add(packageName)
jars.each { jar->
new ZipInputStream(new FileInputStream(jar)).withCloseable { zip ->
ZipEntry e
while (e = zip.nextEntry) {
if (!e.directory && e.name.endsWith(".class")) {
int index = e.name.lastIndexOf('/')
if (index < 0) index = e.name.length()
String packageName = e.name.substring(0, index).replace('/', '.')
if (!packageName.matches(filteredPackages)) {
result.add(packageName)
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion gradle/config/checkstyle/required-header.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
^/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*$
^ \* Copyright \(c\) (2019|2020) Gradle Inc\.$
^ \* Copyright \(c\) (2019|2020|2021|2022) Gradle Inc\.$
^ \*$
^ \* This program and the accompanying materials are made$
^ \* available under the terms of the Eclipse Public License 2.0$
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import org.eclipse.buildship.core.internal.CorePlugin
import org.eclipse.buildship.core.internal.console.ProcessStreamsProvider
import org.eclipse.buildship.core.internal.test.fixtures.TestProcessStreamProvider
import org.eclipse.buildship.core.internal.util.gradle.IdeFriendlyClassLoading
import org.eclipse.buildship.core.internal.workspace.EclipseModelUtils
import org.eclipse.buildship.core.internal.workspace.ExtendedEclipseModelUtils
import org.eclipse.buildship.model.ExtendedEclipseModel

class GradleBuildConnectionCachingTest extends BaseProjectConfiguratorTest {

Expand Down Expand Up @@ -88,8 +89,8 @@ class GradleBuildConnectionCachingTest extends BaseProjectConfiguratorTest {
def "Build action loads value from cache during synchronization"() {
setup:
ResultHandler<Collection<EclipseProject>> resultHandler = Mock(ResultHandler)
Function<ProjectConnection, EclipseProject> firstAction = { ProjectConnection p -> p.action(IdeFriendlyClassLoading.loadCompositeModelQuery(EclipseProject.class)).run() }
Function<ProjectConnection, EclipseProject> secondAction = { ProjectConnection p -> p.action(IdeFriendlyClassLoading.loadCompositeModelQuery(EclipseProject.class)).run(resultHandler) }
Function<ProjectConnection, EclipseProject> firstAction = { ProjectConnection p -> p.action(IdeFriendlyClassLoading.loadCompositeModelQuery(ExtendedEclipseModel.class)).run() }
Function<ProjectConnection, EclipseProject> secondAction = { ProjectConnection p -> p.action(IdeFriendlyClassLoading.loadCompositeModelQuery(ExtendedEclipseModel.class)).run(resultHandler) }
TestConfigurator firstConfigurator = new TestConfigurator(firstAction)
TestConfigurator secondConfigurator = new TestConfigurator(secondAction)
registerConfigurator(firstConfigurator)
Expand All @@ -108,8 +109,8 @@ class GradleBuildConnectionCachingTest extends BaseProjectConfiguratorTest {
def "Build action loads value from cache during synchronization while supplying eclipseRuntime"() {
setup:
ResultHandler<Collection<EclipseProject>> resultHandler = Mock(ResultHandler)
Function<ProjectConnection, EclipseProject> firstAction = { ProjectConnection p -> p.action(IdeFriendlyClassLoading.loadCompositeModelQuery(EclipseProject.class, EclipseRuntime.class, EclipseModelUtils.buildEclipseRuntimeConfigurer())).run() }
Function<ProjectConnection, EclipseProject> secondAction = { ProjectConnection p -> p.action(IdeFriendlyClassLoading.loadCompositeModelQuery(EclipseProject.class, EclipseRuntime.class, EclipseModelUtils.buildEclipseRuntimeConfigurer())).run(resultHandler) }
Function<ProjectConnection, EclipseProject> firstAction = { ProjectConnection p -> p.action(IdeFriendlyClassLoading.loadCompositeModelQuery(ExtendedEclipseModel.class, EclipseRuntime.class, ExtendedEclipseModelUtils.buildEclipseRuntimeConfigurer())).run() }
Function<ProjectConnection, EclipseProject> secondAction = { ProjectConnection p -> p.action(IdeFriendlyClassLoading.loadCompositeModelQuery(ExtendedEclipseModel.class, EclipseRuntime.class, ExtendedEclipseModelUtils.buildEclipseRuntimeConfigurer())).run(resultHandler) }
TestConfigurator firstConfigurator = new TestConfigurator(firstAction)
TestConfigurator secondConfigurator = new TestConfigurator(secondAction)
registerConfigurator(firstConfigurator)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public interface GradleBuild {
* You can load the <a href="https://docs.gradle.org/current/javadoc/org/gradle/tooling/ProjectConnection.html#model-java.lang.Class-"> default models</a>.
* Also, You can load custom models provided by Gradle plugins or even inject your own with an init script:
* <pre><code>
* connection.model(CustomModel.class).withArguments("--init-script", "/path/to/init-script/with/model").get();
* connection.model(ExtendedEclipseModel.class).withArguments("--init-script", "/path/to/init-script/with/model").get();
* </code></pre>
* An example project with custom model loading is available at <a href="https://github.com/eclipse/buildship/tree/master/samples/custom-model">https://github.com/eclipse/buildship/tree/master/samples/custom-model</a>.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
******************************************************************************/
package org.eclipse.buildship.core.internal;

import java.io.File;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Map;
Expand All @@ -23,6 +25,7 @@
import com.google.common.collect.Maps;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;

Expand Down Expand Up @@ -309,4 +312,14 @@ public static ToolingApiOperationManager operationManager() {
public static ExtensionManager extensionManager() {
return getInstance().extensionManager;
}

public static File pluginLocation(String pluginId) {
try {
BundleContext bundleContext = getInstance().getBundle().getBundleContext();
Bundle bundle = Arrays.stream(bundleContext.getBundles()).filter(b -> b.getSymbolicName().equals(pluginId)).findFirst().get();
return FileLocator.getBundleFile(bundle);
} catch (Exception e) {
throw new GradlePluginsRuntimeException("Cannot retrieve location of plugin " + pluginId, e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.eclipse.buildship.core.internal.util.gradle.IdeAttachedProjectConnection;
import org.eclipse.buildship.core.internal.workspace.ConnectionAwareLauncherProxy;
import org.eclipse.buildship.core.internal.workspace.DefaultModelProvider;
import org.eclipse.buildship.core.internal.workspace.ExtendedEclipseModelUtils;
import org.eclipse.buildship.core.internal.workspace.ImportRootProjectOperation;
import org.eclipse.buildship.core.internal.workspace.InternalGradleBuild;
import org.eclipse.buildship.core.internal.workspace.ModelProvider;
Expand Down Expand Up @@ -223,7 +224,8 @@ public void runInToolingApi(CancellationTokenSource tokenSource, IProgressMonito
SubMonitor progress = SubMonitor.convert(monitor, 5);
progress.setTaskName((String.format("Synchronizing Gradle build at %s with workspace", this.gradleBuild.getBuildConfig().getRootProjectDirectory())));
new ImportRootProjectOperation(this.gradleBuild.getBuildConfig(), this.newProjectHandler).run(progress.newChild(1));
Set<EclipseProject> allProjects = collectAll(this.gradleBuild.modelProvider.fetchEclipseProjectAndRunSyncTasks(tokenSource, progress.newChild(1)));
Map<String, EclipseProject> result = this.gradleBuild.withConnection(connection -> ExtendedEclipseModelUtils.collectEclipseModels(ExtendedEclipseModelUtils.runTasksAndQueryModels(connection)), progress.newChild(1));
Set<EclipseProject> allProjects = collectAll(result);
new ValidateProjectLocationOperation(allProjects).run(progress.newChild(1));
new RunOnImportTasksOperation(allProjects, this.gradleBuild.getBuildConfig()).run(progress.newChild(1), tokenSource);
this.failures = new SynchronizeGradleBuildOperation(allProjects, this.gradleBuild, this.newProjectHandler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

Expand All @@ -27,8 +28,11 @@
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;

import org.eclipse.core.runtime.Platform;

import org.eclipse.buildship.core.GradleDistribution;
import org.eclipse.buildship.core.internal.CorePlugin;
import org.eclipse.buildship.core.internal.GradlePluginsRuntimeException;
Expand All @@ -45,7 +49,8 @@
*/
public final class GradleArguments {

private static final String INITSCRIPT_LOCATION="/org/eclipse/buildship/core/internal/configuration/eclipsePlugin.gradle";
private static final String INITSCRIPT_NAME = "buildshipInitScript.gradle";
private static final String INITSCRIPT_LOCATION="/org/eclipse/buildship/core/internal/configuration/" + INITSCRIPT_NAME;

private final File rootDir;
private final GradleDistribution gradleDistribution;
Expand Down Expand Up @@ -146,30 +151,58 @@ private static String buildScanArgumentFor(BuildEnvironment environment) {
}

private static List<String> getInitScriptArguments() {
File initScript = getEclipsePluginInitScriptLocation();
File initScriptLocation = getEclipsePluginInitScriptLocation();
try {
if (!initScript.exists()) {
Files.createParentDirs(initScript);
Files.touch(initScript);
URL resource = GradleVersion.class.getResource(INITSCRIPT_LOCATION);
if (resource == null) {
throw new GradlePluginsRuntimeException(String.format("Resource '%s' not found.", INITSCRIPT_LOCATION));
}

URLConnection connection = resource.openConnection();
try (InputStream inputStream = connection.getInputStream()) {
Files.asByteSink(initScript).writeFrom(inputStream);
}

String existingInitScriptText = readInitScriptContent(initScriptLocation);
String newInitScriptContent = createInitScriptContent();
if (existingInitScriptText == null || !existingInitScriptText.equals(newInitScriptContent)) {
writeInitScript(initScriptLocation, createInitScriptContent());
}
return Arrays.asList("--init-script", initScript.getAbsolutePath());
return Arrays.asList("--init-script", initScriptLocation.getAbsolutePath());
} catch (IOException e) {
throw new GradlePluginsRuntimeException("Failed to create init script", e);
}
}



private static void writeInitScript(File initScript, String content) throws IOException {
Files.createParentDirs(initScript);
Files.touch(initScript);
URL resource = GradleVersion.class.getResource(INITSCRIPT_LOCATION);
if (resource == null) {
throw new GradlePluginsRuntimeException(String.format("Resource '%s' not found.", INITSCRIPT_LOCATION));
}

URLConnection connection = resource.openConnection();
try (InputStream inputStream = connection.getInputStream()) {
Files.asByteSink(initScript).write(content.getBytes());
}
}

private static String readInitScriptContent(File initScript) throws IOException {
if (initScript.exists() && initScript.isFile()) {
return Files.asCharSource(initScript, StandardCharsets.UTF_8).read();
} else {
return null;
}
}

private static String createInitScriptContent() throws IOException {
URL resource = GradleVersion.class.getResource(INITSCRIPT_LOCATION);
if (resource == null) {
throw new GradlePluginsRuntimeException(String.format("Resource '%s' not found.", INITSCRIPT_LOCATION));
}

URLConnection connection = resource.openConnection();
try (InputStream inputStream = connection.getInputStream()) {
String ideModelClassapth = CorePlugin.pluginLocation("org.gradle.toolingapi").getAbsolutePath() + (Platform.inDevelopmentMode() ? "/bin/main" : "");
return new String(ByteStreams.toByteArray(inputStream)).replace("IDEMODEL_CLASSPATH", ideModelClassapth.replaceAll("\\\\", "/"));
}
}

private static File getEclipsePluginInitScriptLocation() {
return CorePlugin.getInstance().getStateLocation().append("init.d").append("eclipsePlugin.gradle").toFile();
return CorePlugin.getInstance().getStateLocation().append("init.d").append(INITSCRIPT_NAME).toFile();
}

}
Loading

0 comments on commit f689a4c

Please sign in to comment.