blob: 35f1b6bc1fe4f0470e15326c6f1b2cc75976cdfd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2012 Sonatype Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sonatype Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.tycho.osgi.runtime;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.maven.MavenExecutionException;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ResolutionErrorHandler;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.RepositorySystem;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.UnArchiver;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.FileUtils;
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;
/**
* Implementation of {@link org.eclipse.sisu.equinox.embedder.EquinoxRuntimeLocator} for Tycho's
* OSGi runtime.
*/
@Component(role = EquinoxRuntimeLocator.class)
public class TychoOsgiRuntimeLocator implements EquinoxRuntimeLocator {
/**
* List of packages exported by the shared bundles. The shared bundles are loaded by the Maven
* class loader (see transitive dependencies of <code>tycho-maven-plugin</code>) but their
* classes are also exposed to the implementation bundles in in Tycho's OSGi runtime (see
* {@link TychoOsgiRuntimeArtifacts#getRuntimeArtifacts()}) via the system packages extra
* option.
*/
private static final String[] SYSTEM_PACKAGES_EXTRA = { "org.eclipse.tycho", //
"org.eclipse.tycho.artifacts", //
"org.eclipse.tycho.core.ee.shared", //
"org.eclipse.tycho.core.shared", //
"org.eclipse.tycho.core.resolver.shared", //
"org.eclipse.tycho.locking.facade", //
"org.eclipse.tycho.p2.metadata", //
"org.eclipse.tycho.p2.repository", //
"org.eclipse.tycho.p2.resolver.facade", //
"org.eclipse.tycho.p2.target.facade", //
"org.eclipse.tycho.p2.tools", //
"org.eclipse.tycho.p2.tools.director.shared", //
"org.eclipse.tycho.p2.tools.publisher.facade", //
"org.eclipse.tycho.p2.tools.mirroring.facade", //
"org.eclipse.tycho.p2.tools.verifier.facade", //
"org.eclipse.tycho.repository.registry.facade",//
"org.eclipse.tycho.p2.tools.baseline.facade" };
@Requirement
private Logger logger;
@Requirement
private RepositorySystem repositorySystem;
@Requirement
private ResolutionErrorHandler resolutionErrorHandler;
@Requirement
private LegacySupport buildContext;
@Requirement(hint = "zip")
private UnArchiver unArchiver;
@Requirement
private FileLockService fileLockService;
@Requirement
private Map<String, TychoOsgiRuntimeArtifacts> runtimeArtifacts;
@Requirement
private DevWorkspaceResolver workspaceState;
@Override
public void locateRuntime(EquinoxRuntimeDescription description) throws MavenExecutionException {
WorkspaceTychoOsgiRuntimeLocator workspaceLocator = WorkspaceTychoOsgiRuntimeLocator
.getResolver(this.workspaceState);
MavenSession session = buildContext.getSession();
addRuntimeArtifacts(workspaceLocator, session, description);
for (String systemPackage : SYSTEM_PACKAGES_EXTRA) {
description.addExtraSystemPackage(systemPackage);
}
if (workspaceLocator != null) {
workspaceLocator.addPlatformProperties(description);
}
}
public void addRuntimeArtifacts(WorkspaceTychoOsgiRuntimeLocator workspaceLocator, MavenSession session,
EquinoxRuntimeDescription description) throws MavenExecutionException {
TychoOsgiRuntimeArtifacts framework = runtimeArtifacts.get(TychoOsgiRuntimeArtifacts.HINT_FRAMEWORK);
if (framework != null) {
addRuntimeArtifacts(workspaceLocator, description, session, framework);
}
for (Map.Entry<String, TychoOsgiRuntimeArtifacts> entry : runtimeArtifacts.entrySet()) {
if (!TychoOsgiRuntimeArtifacts.HINT_FRAMEWORK.equals(entry.getKey())) {
addRuntimeArtifacts(workspaceLocator, description, session, entry.getValue());
}
}
}
private void addRuntimeArtifacts(WorkspaceTychoOsgiRuntimeLocator workspaceLocator,
EquinoxRuntimeDescription description, MavenSession session, TychoOsgiRuntimeArtifacts framework)
throws MavenExecutionException {
for (Dependency dependency : framework.getRuntimeArtifacts()) {
if (workspaceLocator != null) {
Dependency dependencyPom = new Dependency();
dependencyPom.setType("pom");
dependencyPom.setGroupId(dependency.getGroupId());
dependencyPom.setArtifactId(dependency.getArtifactId());
dependencyPom.setVersion(dependency.getVersion());
Artifact pom = resolveDependency(session, dependencyPom);
boolean resolved;
if ("zip".equals(dependency.getType())) {
resolved = workspaceLocator.addProduct(description, pom);
} else {
resolved = workspaceLocator.addBundle(description, pom);
}
if (resolved) {
continue;
}
// fallback to regular resolution logic if requested dependency is not found in the workspace
}
addRuntimeArtifact(description, session, dependency);
}
}
private void addRuntimeArtifact(EquinoxRuntimeDescription description, MavenSession session, Dependency dependency)
throws MavenExecutionException {
Artifact artifact = resolveDependency(session, dependency);
if ("zip".equals(dependency.getType())) {
File artifactFile = new File(session.getLocalRepository().getBasedir(), session.getLocalRepository()
.pathOf(artifact));
File eclipseDir = new File(artifactFile.getParentFile(), "eclipse");
FileLocker locker = fileLockService.getFileLocker(artifactFile);
locker.lock();
try {
if (!eclipseDir.exists() || artifact.isSnapshot()) {
logger.debug("Extracting Tycho's OSGi runtime");
if (artifact.getFile().lastModified() > eclipseDir.lastModified()) {
logger.debug("Unpacking Tycho's OSGi runtime to " + eclipseDir);
try {
FileUtils.deleteDirectory(eclipseDir);
} catch (IOException e) {
logger.warn("Failed to delete Tycho's OSGi runtime " + eclipseDir + ": " + e.getMessage());
}
unArchiver.setSourceFile(artifact.getFile());
unArchiver.setDestDirectory(eclipseDir.getParentFile());
try {
unArchiver.extract();
} catch (ArchiverException e) {
throw new MavenExecutionException("Failed to unpack Tycho's OSGi runtime: "
+ e.getMessage(), e);
}
eclipseDir.setLastModified(artifact.getFile().lastModified());
}
}
} finally {
locker.release();
}
description.addInstallation(eclipseDir);
} else {
description.addBundle(artifact.getFile());
}
}
public Artifact resolveDependency(MavenSession session, Dependency dependency) throws MavenExecutionException {
Artifact artifact = repositorySystem.createArtifact(dependency.getGroupId(), dependency.getArtifactId(),
dependency.getVersion(), dependency.getType());
ArtifactResolutionRequest request = new ArtifactResolutionRequest();
request.setArtifact(artifact);
request.setResolveRoot(true).setResolveTransitively(false);
request.setLocalRepository(session.getLocalRepository());
request.setRemoteRepositories(getPluginRepositories(session));
request.setCache(session.getRepositoryCache());
request.setOffline(session.isOffline());
request.setProxies(session.getSettings().getProxies());
request.setForceUpdate(session.getRequest().isUpdateSnapshots());
ArtifactResolutionResult result = repositorySystem.resolve(request);
try {
resolutionErrorHandler.throwErrors(request, result);
} catch (ArtifactResolutionException e) {
throw new MavenExecutionException("Could not resolve artifact for Tycho's OSGi runtime", e);
}
return artifact;
}
protected List<ArtifactRepository> getPluginRepositories(MavenSession session) {
List<ArtifactRepository> repositories = new ArrayList<>();
for (MavenProject project : session.getProjects()) {
repositories.addAll(project.getPluginArtifactRepositories());
}
return repositorySystem.getEffectiveRepositories(repositories);
}
}