Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load custom model during synchronization #1146

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,20 @@ abstract class ConvertOsgiBundleTask extends DefaultTask {
createNewBundle(project, JarBundleUtils.firstDependencyJar(pluginConfiguration.get()))
}

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(outputDirectory.get().asFile, "osgi_${jar.name}")
File osgiJar = new File(outputDirectory.get().asFile, "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,23 +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)
project.copy {
from jar
into project.file('.')
rename { jarName }
}

// copy the source jar file into project
File depJar = JarBundleUtils.firstDependencyJar(getPluginConfiguration(project))
File localJar = (project.tasks[TASK_NAME_CONVERT_TO_BUNDLE].outputDirectory.get().asFile).listFiles()[0]
project.copy {
File sourceJar = JarBundleUtils.firstDependencySourceJar(project, getPluginConfiguration(project))
from(sourceJar)
from localJar
into project.file('.')
rename { sourceJarName(project) }
rename { jarName(project) }
}

// update manifest file
Expand All @@ -100,7 +88,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 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
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private void collectRootModels(BuildController controller, GradleBuild build, Ma
models.put(buildPath, controller.getModel(build.getRootProject(), this.modelType));
}

for (GradleBuild includedBuild : build.getIncludedBuilds()) {
for (GradleBuild includedBuild : build.getEditableBuilds()) { // TODO add cross-version coverage
String includedBuildRootProjectName = includedBuild.getRootProject().getName();
if (!includedBuildRootProjectName.equals(rootBuildRootProjectName)) {
collectRootModels(controller, includedBuild, models, includedBuildRootProjectName, rootBuildRootProjectName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,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 @@ -93,8 +94,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 @@ -113,8 +114,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 @@ -225,7 +226,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
Loading