From d2140837249eb18247adf7ae9399c1092803f8f5 Mon Sep 17 00:00:00 2001 From: Roland Grunberg Date: Tue, 12 Jun 2012 10:38:51 -0400 Subject: [PATCH] Implement a custom resolver for Tycho in local mode. When running in local mode, dependencies should be resolved by looking on the local system. Remote repositories should be ignored unless offline mode is disabled. Automatically create a local p2 repository of all bundles on the system so that they may be used for local dependency resolution. This is done using a modified version of Eclipse's copy-platform script. Since Fedora 17, we need an Execution Environment of at least JavaSE-1.6 for Eclipse bundles. Eclipse Juno platform bundles depend on javax.annotation. In Fedora this is provided by geronimo-annotation, but has a dependency on javax.lang.model (since 1.6). Use the defined target environments in local mode when the property tycho.local.keepTarget is set. Change-Id: Ia1ece07ece2412bc4a88901631f3f651ad2b634b --- .../tycho/p2/target/TargetDefinitionResolver.java | 11 +++-- .../tycho/p2/target/TargetPlatformBuilderImpl.java | 55 ++++++++++++++++++++-- tycho-core/pom.xml | 5 ++ .../core/maven/TychoMavenLifecycleParticipant.java | 16 +++++++ .../tycho/core/osgitools/AbstractTychoProject.java | 24 ++++++++++ .../tycho/core/osgitools/OsgiBundleProject.java | 29 +++++++++++- .../DefaultTargetPlatformConfigurationReader.java | 6 ++- .../osgi/runtime/TychoOsgiRuntimeLocator.java | 12 +++++ .../p2/resolver/P2TargetPlatformResolver.java | 11 +++++ 9 files changed, 159 insertions(+), 10 deletions(-) diff --git a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/TargetDefinitionResolver.java b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/TargetDefinitionResolver.java index 5cc8718..7e4fcc1 100644 --- a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/TargetDefinitionResolver.java +++ b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/TargetDefinitionResolver.java @@ -24,6 +24,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.URIUtil; import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.core.ProvisionException; import org.eclipse.equinox.p2.metadata.IInstallableUnit; @@ -104,9 +105,13 @@ public class TargetDefinitionResolver { List metadataRepositories = new ArrayList(); for (Repository repository : iuLocationDefinition.getRepositories()) { - repositoryIdManager.addMapping(repository.getId(), repository.getLocation()); - artifactRepositories.add(repository.getLocation()); - metadataRepositories.add(loadRepository(repository)); + // We cannot resolve a non-file URI in local mode + if ((System.getenv("TYCHO_MVN_LOCAL") == null && System.getenv("TYCHO_MVN_RPMBUILD") == null) + || URIUtil.isFileURI(repository.getLocation())) { + repositoryIdManager.addMapping(repository.getId(), repository.getLocation()); + artifactRepositories.add(repository.getLocation()); + metadataRepositories.add(loadRepository(repository)); + } } IQueryable locationUnits = new CompoundQueryable( diff --git a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/TargetPlatformBuilderImpl.java b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/TargetPlatformBuilderImpl.java index c56eeff..bb45548 100644 --- a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/TargetPlatformBuilderImpl.java +++ b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/TargetPlatformBuilderImpl.java @@ -38,6 +38,9 @@ import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.core.ProvisionException; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.metadata.VersionedId; +import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil; +import org.eclipse.equinox.p2.metadata.expression.IExpression; +import org.eclipse.equinox.p2.query.IQuery; import org.eclipse.equinox.p2.query.IQueryResult; import org.eclipse.equinox.p2.query.QueryUtil; import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; @@ -225,6 +228,12 @@ public class TargetPlatformBuilderImpl implements TargetPlatformBuilder { IMetadataRepository metadataRepository = null; IArtifactRepository artifactRepository = null; + // We cannot resolve a non-file URI in local mode while offline + if (System.getenv("TYCHO_MVN_RPMBUILD") != null && !URIUtil.isFileURI(location.getURL())) { + return; + } + + try { remoteRepositoryIdManager.addMapping(location.getId(), location.getURL()); @@ -365,12 +374,48 @@ public class TargetPlatformBuilderImpl implements TargetPlatformBuilder { result.addAll(contentPart.getUnits()); } - SubMonitor sub = SubMonitor.convert(monitor, metadataRepositories.size() * 200); - for (IMetadataRepository repository : metadataRepositories) { - IQueryResult matches = repository.query(QueryUtil.ALL_UNITS, sub.newChild(100)); - result.addAll(matches.toUnmodifiableSet()); + if (System.getenv("TYCHO_MVN_LOCAL") != null) { + final String uri = "file:" + System.getProperty("user.dir") + "/.m2/p2/repo"; + final IExpression notmatchIU_ID = ExpressionUtil.parse("id != $0"); + IMetadataRepository systemLocalP2Repo = null; + + // Sanity check even though the repo we want should be at index 1 + for (IMetadataRepository repository : metadataRepositories) { + if (repository.getLocation().toString().equals(uri)) { + systemLocalP2Repo = repository; + break; + } + } + + IQuery noLocalIUs = QueryUtil.createIUAnyQuery(); + + // Create a conjunction query that negates all IUs on the local system + for (IInstallableUnit unit : systemLocalP2Repo.query(QueryUtil.ALL_UNITS, null).toUnmodifiableSet()) { + noLocalIUs = QueryUtil.createCompoundQuery(noLocalIUs, QueryUtil.createMatchQuery(notmatchIU_ID, unit.getId()), true); + } + + SubMonitor sub = SubMonitor.convert(monitor, metadataRepositories.size() * 200); + for (IMetadataRepository repository : metadataRepositories) { + IQueryResult matches; + if (repository.getLocation().toString().equals(uri)) { + matches = repository.query(QueryUtil.ALL_UNITS, sub.newChild(100)); + } else { + // Don't collect any remote IUs that can be found on the system + // This will favour IUs in the system local p2 repository + matches = repository.query(noLocalIUs, sub.newChild(100)); + } + result.addAll(matches.toUnmodifiableSet()); + } + sub.done(); + } else { + SubMonitor sub = SubMonitor.convert(monitor, metadataRepositories.size() * 200); + for (IMetadataRepository repository : metadataRepositories) { + IQueryResult matches = repository.query(QueryUtil.ALL_UNITS, sub.newChild(100)); + matches = repository.query(QueryUtil.ALL_UNITS, sub.newChild(100)); + result.addAll(matches.toUnmodifiableSet()); + } + sub.done(); } - sub.done(); if (logger.isDebugEnabled()) { IQueryResult locallyInstalledIUs = localMetadataRepository.query(QueryUtil.ALL_UNITS, diff --git a/tycho-core/pom.xml b/tycho-core/pom.xml index c3d5288..d76c229 100644 --- a/tycho-core/pom.xml +++ b/tycho-core/pom.xml @@ -146,6 +146,11 @@ org.eclipse.tycho.core.shared ${project.version} + + org.fedoraproject.xmvn + xmvn-core + 0.3.0 + org.eclipse.tycho diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java b/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java index cccb6ff..fb8bf78 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java @@ -11,6 +11,7 @@ package org.eclipse.tycho.core.maven; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -73,6 +74,21 @@ public class TychoMavenLifecycleParticipant extends AbstractMavenLifecyclePartic registerExecutionListener(session); configureComponents(session); + // Create a system p2 repository for local dependency resolution + if (System.getenv("TYCHO_MVN_LOCAL") != null || System.getenv("TYCHO_MVN_RPMBUILD") != null) { + try { + String[] cmd = new String[] { "/usr/share/java/tycho/copy-platform-all", + System.getProperty("user.dir") + "/.m2/p2/repo" }; + System.out.println("Building system local p2 repository..."); + Process p = Runtime.getRuntime().exec(cmd); + p.waitFor(); + } catch (IOException e) { + // Continue + } catch (InterruptedException e) { + // Continue + } + } + for (MavenProject project : projects) { resolver.setupProject(session, project, DefaultReactorProject.adapt(project)); } diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/AbstractTychoProject.java b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/AbstractTychoProject.java index 695133d..6303f48 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/AbstractTychoProject.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/AbstractTychoProject.java @@ -20,6 +20,9 @@ import org.eclipse.tycho.artifacts.TargetPlatform; import org.eclipse.tycho.core.TargetPlatformConfiguration; import org.eclipse.tycho.core.TychoConstants; import org.eclipse.tycho.core.TychoProject; +import org.eclipse.tycho.core.ee.ExecutionEnvironmentUtils; +import org.eclipse.tycho.core.ee.UnknownEnvironmentException; +import org.eclipse.tycho.core.ee.shared.ExecutionEnvironment; import org.eclipse.tycho.core.ee.shared.ExecutionEnvironmentConfiguration; import org.eclipse.tycho.core.facade.TargetEnvironment; import org.eclipse.tycho.core.osgitools.targetplatform.LocalTargetPlatformResolver; @@ -92,17 +95,38 @@ public abstract class AbstractTychoProject extends AbstractLogEnabled implements String configuredForcedProfile = tpConfiguration.getExecutionEnvironment(); if (configuredForcedProfile != null) { + configuredForcedProfile = overrideToAtLeastJavaSE16(configuredForcedProfile); sink.overrideProfileConfiguration(configuredForcedProfile, "target-platform-configuration "); } String configuredDefaultProfile = tpConfiguration.getExecutionEnvironmentDefault(); if (configuredDefaultProfile != null) { + configuredDefaultProfile = overrideToAtLeastJavaSE16(configuredDefaultProfile); sink.setProfileConfiguration(configuredDefaultProfile, "target-platform-configuration "); } } + public String overrideToAtLeastJavaSE16 (String profile) { + try { + ExecutionEnvironment ee = ExecutionEnvironmentUtils.getExecutionEnvironment(profile); + + if (System.getenv("TYCHO_MVN_LOCAL") != null || System.getenv("TYCHO_MVN_RPMBUILD") != null) { + // EE must be at least JavaSE-1.6 + final ExecutionEnvironment javaSE16 = ExecutionEnvironmentUtils.getExecutionEnvironment("JavaSE-1.6"); + if (! ee.isCompatibleCompilerTargetLevel(javaSE16.getCompilerTargetLevel())) { + ee = javaSE16; + } + } + + return ee.getProfileName(); + } catch (UnknownEnvironmentException e) { + // can't happen, ee is validated during configuration parsing + return null; + } + } + public TargetPlatform getTargetPlatform(MavenProject project) { return (TargetPlatform) project.getContextValue(TychoConstants.CTX_TARGET_PLATFORM); } diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/OsgiBundleProject.java b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/OsgiBundleProject.java index fb73469..6c2cee3 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/OsgiBundleProject.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/OsgiBundleProject.java @@ -45,7 +45,9 @@ import org.eclipse.tycho.core.BundleProject; import org.eclipse.tycho.core.PluginDescription; import org.eclipse.tycho.core.TychoConstants; import org.eclipse.tycho.core.TychoProject; +import org.eclipse.tycho.core.ee.ExecutionEnvironmentUtils; import org.eclipse.tycho.core.ee.StandardExecutionEnvironment; +import org.eclipse.tycho.core.ee.UnknownEnvironmentException; import org.eclipse.tycho.core.ee.shared.ExecutionEnvironment; import org.eclipse.tycho.core.ee.shared.ExecutionEnvironmentConfiguration; import org.eclipse.tycho.core.facade.BuildPropertiesParser; @@ -492,6 +494,7 @@ public class OsgiBundleProject extends AbstractTychoProject implements BundlePro String pdeProfile = getEclipsePluginProject(DefaultReactorProject.adapt(project)).getBuildProperties() .getJreCompilationProfile(); if (pdeProfile != null) { + pdeProfile = overrideToAtLeastJavaSE16(pdeProfile); sink.setProfileConfiguration(pdeProfile.trim(), "build.properties"); } else { @@ -509,7 +512,31 @@ public class OsgiBundleProject extends AbstractTychoProject implements BundlePro if (envs.isEmpty()) { return null; } - return Collections.min(envs); + + ExecutionEnvironment manifestMinimalEE = Collections.min(envs); + ExecutionEnvironment tmp; + + if (System.getenv("TYCHO_MVN_LOCAL") != null || System.getenv("TYCHO_MVN_RPMBUILD") != null) { + try { + // EE must be at least JavaSE-1.6 + final ExecutionEnvironment javaSE16 = ExecutionEnvironmentUtils.getExecutionEnvironment("JavaSE-1.6"); + while (!envs.isEmpty()) { + tmp = Collections.min(envs); + if (tmp.isCompatibleCompilerTargetLevel(javaSE16.getCompilerTargetLevel())) { + manifestMinimalEE = tmp; + break; + } + envs.remove(tmp); + } + + if (envs.isEmpty()) { + return javaSE16; + } + } catch (UnknownEnvironmentException e) { + // Continue + } + } + return manifestMinimalEE; } } diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultTargetPlatformConfigurationReader.java b/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultTargetPlatformConfigurationReader.java index 5c4a26f..802c9dd 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultTargetPlatformConfigurationReader.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultTargetPlatformConfigurationReader.java @@ -64,7 +64,11 @@ public class DefaultTargetPlatformConfigurationReader { + configuration.toString()); } - addTargetEnvironments(result, project, configuration); + // Use the defined environments only in local mode with tycho.local.keepTarget + if ((System.getenv("TYCHO_MVN_LOCAL") == null && System.getenv("TYCHO_MVN_RPMBUILD") == null) + || System.getProperty("tycho.local.keepTarget") != null) { + addTargetEnvironments(result, project, configuration); + } setTargetPlatformResolver(result, configuration); diff --git a/tycho-core/src/main/java/org/eclipse/tycho/osgi/runtime/TychoOsgiRuntimeLocator.java b/tycho-core/src/main/java/org/eclipse/tycho/osgi/runtime/TychoOsgiRuntimeLocator.java index 9935c5f..8f63735 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/osgi/runtime/TychoOsgiRuntimeLocator.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/osgi/runtime/TychoOsgiRuntimeLocator.java @@ -38,6 +38,9 @@ import org.eclipse.sisu.equinox.embedder.EquinoxRuntimeLocator; import org.eclipse.tycho.dev.DevWorkspaceResolver; import org.eclipse.tycho.locking.facade.FileLockService; import org.eclipse.tycho.locking.facade.FileLocker; +import org.sonatype.aether.util.artifact.DefaultArtifact; + +import org.fedoraproject.maven.resolver.DefaultResolver; /** * Implementation of {@link org.eclipse.sisu.equinox.embedder.EquinoxRuntimeLocator} for Tycho's @@ -201,6 +204,15 @@ public class TychoOsgiRuntimeLocator implements EquinoxRuntimeLocator { Artifact artifact = repositorySystem.createArtifact(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), dependency.getType()); + // If we are in local mode, find the artifact on the system + if (System.getenv("TYCHO_MVN_LOCAL") != null || System.getenv("TYCHO_MVN_RPMBUILD") != null) { + DefaultResolver resolver = new DefaultResolver(); + File file = resolver.resolve(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), artifact.getType()); + if (file != null) { + artifact.setFile(file); + } + } + ArtifactResolutionRequest request = new ArtifactResolutionRequest(); request.setArtifact(artifact); request.setResolveRoot(true).setResolveTransitively(false); diff --git a/tycho-p2/tycho-p2-facade/src/main/java/org/eclipse/tycho/p2/resolver/P2TargetPlatformResolver.java b/tycho-p2/tycho-p2-facade/src/main/java/org/eclipse/tycho/p2/resolver/P2TargetPlatformResolver.java index 1c897b9..d869658 100644 --- a/tycho-p2/tycho-p2-facade/src/main/java/org/eclipse/tycho/p2/resolver/P2TargetPlatformResolver.java +++ b/tycho-p2/tycho-p2-facade/src/main/java/org/eclipse/tycho/p2/resolver/P2TargetPlatformResolver.java @@ -191,6 +191,17 @@ public class P2TargetPlatformResolver extends AbstractTargetPlatformResolver imp tpBuilder.setProjectLocation(project.getBasedir()); tpBuilder.setIncludePackedArtifacts(configuration.isIncludePackedArtifacts()); tpBuilder.setFailOnDuplicateIUs(failOnDuplicateIUs); + + // Add Fedora Local P2 Repository when running in local mode + if (System.getenv("TYCHO_MVN_LOCAL") != null || System.getenv("TYCHO_MVN_RPMBUILD") != null) { + String uri = "file:" + System.getProperty("user.dir") + "/.m2/p2/repo"; + try { + tpBuilder.addP2Repository(new MavenRepositoryLocation(uri, new URI(uri))); + } catch (URISyntaxException e) { + getLogger().warn("Unable to resolve repository URI : " + uri, e); + } + } + addThisReactorProjectToTargetPlatform(session, project, configuration, tpBuilder); addOtherReactorProjectsToTargetPlatform(project, reactorProjects, tpBuilder); -- 1.7.11.7