| /******************************************************************************* |
| * 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); |
| } |
| } |