blob: 00a11de186a0222d5f1504b2c57e7c71479c76b5 [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2009 - 2013 SpringSource, a division of VMware, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.virgo.ide.runtime.core.provisioning;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.internal.misc.StringMatcher;
import org.eclipse.virgo.ide.bundlerepository.domain.OsgiVersion;
import org.eclipse.virgo.ide.bundlerepository.domain.PackageMember;
import org.eclipse.virgo.ide.facet.core.FacetUtils;
import org.eclipse.virgo.ide.manifest.core.BundleManifestCorePlugin;
import org.eclipse.virgo.ide.runtime.core.IServerRuntimeProvider;
import org.eclipse.virgo.ide.runtime.core.ServerCorePlugin;
import org.eclipse.virgo.ide.runtime.core.ServerUtils;
import org.eclipse.virgo.ide.runtime.core.artefacts.Artefact;
import org.eclipse.virgo.ide.runtime.core.artefacts.ArtefactRepository;
import org.eclipse.virgo.ide.runtime.core.artefacts.BundleArtefact;
import org.eclipse.virgo.ide.runtime.core.artefacts.IArtefact;
import org.eclipse.virgo.ide.runtime.core.artefacts.IArtefactTyped;
import org.eclipse.virgo.ide.runtime.core.artefacts.LibraryArtefact;
import org.eclipse.virgo.ide.runtime.core.artefacts.LocalBundleArtefact;
import org.eclipse.virgo.ide.runtime.core.artefacts.LocalLibraryArtefact;
import org.eclipse.virgo.ide.runtime.internal.core.ServerRuntimeUtils;
import org.eclipse.virgo.ide.runtime.internal.core.VirgoServerRuntime;
import org.eclipse.virgo.ide.runtime.internal.core.runtimes.InstallationType;
import org.eclipse.virgo.ide.runtime.internal.core.runtimes.RuntimeProviders;
import org.eclipse.virgo.ide.runtime.internal.core.runtimes.VirgoRuntimeProvider;
import org.eclipse.virgo.kernel.repository.BundleRepository;
import org.eclipse.virgo.repository.Repository;
import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
import org.eclipse.virgo.util.osgi.manifest.ExportedPackage;
import org.eclipse.wst.server.core.IRuntime;
import org.osgi.framework.Version;
/**
* Utility class that is able to create {@link Repository} instances from either the remote enterprise bundle repository
* or from a local installed Virgo instance.
*
* @author Christian Dupuis
* @author Leo Dos Santos
* @since 1.0.0
*/
@SuppressWarnings("restriction")
public class RepositoryUtils {
public static final String DOWNLOAD_TYPE_BINARY = "binary";
public static final String DOWNLOAD_TYPE_BINARY_HASH = "binary-hash";
public static final String DOWNLOAD_TYPE_LIBRARY = "library";
public static final String DOWNLOAD_TYPE_LIBRARY_HASH = "library-hash";
public static final String DOWNLOAD_TYPE_LICENSE = "license";
public static final String DOWNLOAD_TYPE_SOURCE = "source";
public static final String DOWNLOAD_TYPE_SOURCE_HASH = "source-hash";
private static final String BRITS_BASE = "http://www.springsource.com/repository/app";
private static final String DOWNLOAD_BASE = "http://repository.springsource.com/ivy";
public static boolean doesRuntimeSupportRepositories(IRuntime runtime) {
IServerRuntimeProvider provider = RuntimeProviders.getRuntimeProvider(runtime);
if (provider instanceof VirgoRuntimeProvider) {
VirgoRuntimeProvider virgoProvider = (VirgoRuntimeProvider) provider;
InstallationType install = virgoProvider.getInstallationType(runtime);
if (InstallationType.NANO.equals(install)) {
return false;
} else {
return true;
}
}
return false;
}
/**
* Downloads the given <code>artifacts</code>.
*/
public static void downloadArifacts(final Set<Artefact> artifacts, final IProject project, final Shell shell, boolean resolveDependencies) {
if (resolveDependencies) {
artifacts.addAll(resolveDependencies(artifacts, false));
}
final Set<IRuntime> runtimes = new HashSet<IRuntime>();
ServerRuntimeUtils.execute(project, new ServerRuntimeUtils.ServerRuntimeCallback() {
public boolean doWithRuntime(VirgoServerRuntime runtime) {
runtimes.add(runtime.getRuntime());
return true;
}
});
if (runtimes.size() > 0) {
IRunnableWithProgress runnable = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
RepositoryProvisioningJob job = new RepositoryProvisioningJob(runtimes, artifacts, true);
job.run(monitor);
}
};
try {
IRunnableContext context = new ProgressMonitorDialog(shell);
context.run(true, true, runnable);
} catch (InvocationTargetException e1) {
} catch (InterruptedException e2) {
}
}
}
/**
* Returns a BundleDefinition for the given bundle symbolic name and version
*/
public static org.eclipse.virgo.kernel.repository.BundleDefinition getBundleDefinition(final String bundle, final String version,
IProject project) {
final List<org.eclipse.virgo.kernel.repository.BundleDefinition> bundles = new ArrayList<org.eclipse.virgo.kernel.repository.BundleDefinition>();
ServerRuntimeUtils.execute(project, new ServerRuntimeUtils.ServerRuntimeCallback() {
public boolean doWithRuntime(VirgoServerRuntime runtime) {
try {
BundleRepository bundleRepository = ServerCorePlugin.getArtefactRepositoryManager().getBundleRepository(runtime.getRuntime());
org.eclipse.virgo.kernel.repository.BundleDefinition bundleDefinition = bundleRepository.findBySymbolicName(bundle,
new org.eclipse.virgo.util.osgi.manifest.VersionRange(version));
if (bundleDefinition != null) {
bundles.add(bundleDefinition);
return false;
}
} catch (Exception e) {
}
return true;
}
});
if (bundles.size() > 0) {
return bundles.get(0);
}
return null;
}
/**
* Returns {@link BundleArtefact}s which bundle symbolic name matches the given <code>value</code>.
*/
public static Set<Artefact> getImportBundleProposals(final IProject project, final String value) {
final Set<Artefact> packages = new TreeSet<Artefact>(new Comparator<Artefact>() {
public int compare(Artefact o1, Artefact o2) {
if (o1.getName() != null && o1.getName().equals(o2.getName())) {
return o1.getVersion().compareTo(o2.getVersion());
} else if (o1.getName() != null && o2.getName() != null) {
return o1.getName().compareTo(o2.getName());
} else if (o1.getSymbolicName() != null && o1.getSymbolicName().equals(o2.getSymbolicName())) {
return o1.getVersion().compareTo(o2.getVersion());
} else if (o1.getSymbolicName() != null) {
return o1.getSymbolicName().compareTo(o2.getSymbolicName());
}
return 0;
}
});
ServerRuntimeUtils.execute(project, new ServerRuntimeUtils.ServerRuntimeCallback() {
public boolean doWithRuntime(VirgoServerRuntime runtime) {
packages.addAll(getImportBundleProposalsForRuntime(runtime, project, value));
return true;
}
});
return packages;
}
/**
* Returns {@link LibraryArtefact}s which library symbolic name matches the given <code>value</code>.
*/
public static Set<Artefact> getImportLibraryProposals(final IProject project, final String value) {
final Set<Artefact> packages = new TreeSet<Artefact>(new Comparator<Artefact>() {
public int compare(Artefact o1, Artefact o2) {
if (o1.getName() != null && o1.getName().equals(o2.getName())) {
return o1.getVersion().compareTo(o2.getVersion());
} else if (o1.getName() != null) {
return o1.getName().compareTo(o2.getName());
}
return 0;
}
});
ServerRuntimeUtils.execute(project, new ServerRuntimeUtils.ServerRuntimeCallback() {
public boolean doWithRuntime(VirgoServerRuntime runtime) {
packages.addAll(getImportLibraryProposalsForRuntime(runtime, project, value));
return true;
}
});
return packages;
}
/**
* Returns {@link org.eclipse.virgo.ide.bundlerepository.domain.PackageExport}s which name matches the given
* <code>value</code>.
*/
public static Set<org.eclipse.virgo.ide.bundlerepository.domain.PackageExport> getImportPackageProposals(final IProject project,
final String value) {
final Set<org.eclipse.virgo.ide.bundlerepository.domain.PackageExport> packages = new TreeSet<org.eclipse.virgo.ide.bundlerepository.domain.PackageExport>(
new Comparator<org.eclipse.virgo.ide.bundlerepository.domain.PackageExport>() {
public int compare(org.eclipse.virgo.ide.bundlerepository.domain.PackageExport o1,
org.eclipse.virgo.ide.bundlerepository.domain.PackageExport o2) {
if (o1.getName().equals(o2.getName())) {
return o1.getVersion().compareTo(o2.getVersion());
}
return o1.getName().compareTo(o2.getName());
}
});
ServerRuntimeUtils.execute(project, new ServerRuntimeUtils.ServerRuntimeCallback() {
public boolean doWithRuntime(VirgoServerRuntime runtime) {
packages.addAll(getImportPackageProposalsForRuntime(runtime, project, value));
return true;
}
});
return packages;
}
/**
* Creates a {@link Repository} inventory from the given runtime.
*/
public static ArtefactRepository getRepositoryContents(IRuntime runtime) {
ArtefactRepository artifacts = new ArtefactRepository();
if (doesRuntimeSupportRepositories(runtime)) {
BundleRepository bundleRepository = ServerCorePlugin.getArtefactRepositoryManager().getBundleRepository(runtime);
for (org.eclipse.virgo.kernel.repository.BundleDefinition bundleDefinition : bundleRepository.getBundles()) {
if (bundleDefinition.getManifest() != null && bundleDefinition.getManifest().getBundleSymbolicName() != null
&& bundleDefinition.getManifest().getBundleSymbolicName().getSymbolicName() != null) {
BundleManifest manifest = bundleDefinition.getManifest();
boolean sourcefileExists = ServerUtils.getSourceFile(bundleDefinition.getLocation()) != null
&& ServerUtils.getSourceFile(bundleDefinition.getLocation()).exists();
OsgiVersion version = null;
if (manifest.getBundleVersion() != null) {
version = new OsgiVersion(manifest.getBundleVersion());
}
artifacts.addBundle(new LocalBundleArtefact(manifest.getBundleName(), manifest.getBundleSymbolicName().getSymbolicName(), version,
sourcefileExists, bundleDefinition.getLocation()));
}
}
for (org.eclipse.virgo.kernel.repository.LibraryDefinition libraryDefinition : bundleRepository.getLibraries()) {
if (libraryDefinition.getSymbolicName() != null) {
artifacts.addLibrary(new LocalLibraryArtefact(libraryDefinition.getName(), libraryDefinition.getSymbolicName(),
new OsgiVersion(libraryDefinition.getVersion()), libraryDefinition.getLocation()));
}
}
}
return artifacts;
}
public static String getRepositoryUrl(IArtefact artefact) {
StringBuilder url = new StringBuilder(BRITS_BASE);
if (artefact instanceof BundleArtefact) {
url.append("/bundle/version/detail?name=");
} else if (artefact instanceof LibraryArtefact) {
url.append("/library/version/detail?name=");
}
url.append(artefact.getSymbolicName());
url.append("&version=");
url.append(artefact.getVersion().toString());
return url.toString();
}
public static String getResourceUrl(BundleArtefact bundle, String downloadType) {
StringBuffer url = new StringBuffer(DOWNLOAD_BASE);
url.append("/bundles");
url.append(getCategory(bundle));
if (DOWNLOAD_TYPE_SOURCE.equals(downloadType)) {
url.append(bundle.getRelativeSourceUrlPath());
} else if (DOWNLOAD_TYPE_SOURCE_HASH.equals(downloadType)) {
url.append(bundle.getRelativeSourceUrlPath()).append(".sha1");
} else if (DOWNLOAD_TYPE_LICENSE.equals(downloadType)) {
url.append(bundle.getRelativeLicenseUrlPath());
} else if (DOWNLOAD_TYPE_BINARY_HASH.equals(downloadType)) {
url.append(bundle.getRelativeUrlPath()).append(".sha1");
} else {
url.append(bundle.getRelativeUrlPath());
}
return url.toString();
}
public static String getResourceUrl(LibraryArtefact library, String downloadType) {
StringBuffer url = new StringBuffer(DOWNLOAD_BASE);
url.append("/libraries");
url.append(getCategory(library));
if (DOWNLOAD_TYPE_LICENSE.equals(downloadType)) {
url.append(library.getRelativeLicenseUrlPath());
} else if (DOWNLOAD_TYPE_LIBRARY_HASH.equals(downloadType)) {
url.append(library.getRelativeUrlPath()).append(".sha1");
} else {
url.append(library.getRelativeUrlPath());
}
return url.toString();
}
/**
* Returns proposals for version content assist requests. 2.5.4 -> 2.5.4 [2.5.4,2.6.0) [2.5.4,2.5.4] [2.5.4,3.0.0)
*/
@SuppressWarnings("unchecked")
public static List<String> getVersionProposals(Set<String> versionStrings) {
// First order the version so that the highest appears first
List<Version> versions = new ArrayList<Version>();
for (String versionString : versionStrings) {
versions.add(Version.parseVersion(versionString));
}
Collections.sort(versions);
Collections.reverse(versions);
// Now add version ranges to the version
List<String> versionRanges = new ArrayList<String>();
for (Version version : versions) {
// 2.5.4 - removed as we don't want to make people use the
// completion
// versionRanges.add(version.toString());
// [2.5.4,2.6.0)
versionRanges.add(new VersionRange(version, true, new Version(version.getMajor(), version.getMinor() + 1, 0, null), false).toString());
// [2.5.4,2.5.4]
versionRanges.add(new VersionRange(version, true, version, true).toString());
// [2.5.4,3.0.0)
versionRanges.add(new VersionRange(version, true, new Version(version.getMajor() + 1, 0, 0, null), false).toString());
}
return versionRanges;
}
/**
* Resolves dependencies of given <code>artefacts</code>. Currently this implementation only resolves direct bundle
* dependencies of {@link LibraryArtefact}s.
*/
public static Set<Artefact> resolveDependencies(Set<Artefact> artifacts, boolean includeOptional) {
Set<Artefact> resolvedArtefacts = new HashSet<Artefact>(artifacts);
// resolve library dependencies
for (IArtefactTyped artefact : artifacts) {
if (artefact instanceof LibraryArtefact) {
resolvedArtefacts.addAll(
ServerCorePlugin.getArtefactRepositoryManager().findLibraryDependencies((LibraryArtefact) artefact, includeOptional));
}
}
return resolvedArtefacts;
}
/**
* Searches the remote bundle repository for matches of a given search string.
*/
public static ArtefactRepository searchForArtifacts(final String search) {
return searchForArtifacts(search, true, true);
}
/**
* Searches the remote bundle repository for matches of a given search string.
*/
public static ArtefactRepository searchForArtifacts(final String search, boolean includeBundles, boolean includesLibraries) {
StringMatcher matcher = new StringMatcher("*" + search + "*", true, false);
ArtefactRepository repository = new ArtefactRepository();
if (includeBundles) {
for (IArtefactTyped artefact : ServerCorePlugin.getArtefactRepositoryManager().getArtefactRepository().getBundles()) {
BundleArtefact bundle = (BundleArtefact) artefact;
// check symbolic name and name
if (matcher.match(bundle.getSymbolicName()) || matcher.match(bundle.getName())) {
repository.addBundle(bundle);
}
// check export packages
else {
for (org.eclipse.virgo.ide.bundlerepository.domain.PackageExport pe : bundle.getExports()) {
if (matcher.match(pe.getName())) {
repository.addBundle(bundle);
break;
}
for (PackageMember pm : pe.getExports()) {
if (matcher.match(pm.getName())) {
repository.addBundle(bundle);
break;
}
}
}
}
}
}
if (includesLibraries) {
for (IArtefact library : ServerCorePlugin.getArtefactRepositoryManager().getArtefactRepository().getLibraries()) {
// check symbolic name and name
if (matcher.match(library.getSymbolicName()) || matcher.match(library.getName())) {
repository.addLibrary((LibraryArtefact) library);
}
}
}
return repository;
}
private static void addImportBundleProposalsFromManifest(Set<BundleArtefact> bundles, BundleManifest manifest, String value) {
if (manifest != null && manifest.getBundleSymbolicName() != null && manifest.getBundleSymbolicName().getSymbolicName() != null
&& manifest.getBundleSymbolicName().getSymbolicName().startsWith(value)) {
OsgiVersion version = null;
if (manifest.getBundleVersion() != null) {
version = new OsgiVersion(manifest.getBundleVersion());
}
bundles.add(new LocalBundleArtefact(manifest.getBundleName(), manifest.getBundleSymbolicName().getSymbolicName(), version, false, null));
}
}
private static void addImportPackageProposalsFromManifest(String value, Set<org.eclipse.virgo.ide.bundlerepository.domain.PackageExport> packages,
BundleManifest manifest) {
if (manifest != null && manifest.getExportPackage() != null) {
for (ExportedPackage export : manifest.getExportPackage().getExportedPackages()) {
Object version = export.getAttributes().get("version");
String packageName = export.getPackageName();
if (packageName.startsWith(value)) {
OsgiVersion v = null;
if (version != null) {
v = new OsgiVersion(version.toString());
} else {
v = new OsgiVersion(Version.emptyVersion);
}
packages.add(new org.eclipse.virgo.ide.bundlerepository.domain.PackageExport(null, packageName, v));
}
}
}
}
private static String getCategory(IArtefact artefact) {
if (artefact.getOrganisationName() != null
&& (artefact.getOrganisationName().startsWith("com.springsource") || artefact.getOrganisationName().startsWith("org.springframework"))) {
return "/release";
} else {
return "/external";
}
}
private static Set<BundleArtefact> getImportBundleProposalsForRuntime(VirgoServerRuntime runtime, IProject project, String value) {
if (value == null) {
value = "";
}
Set<BundleArtefact> bundles = new HashSet<BundleArtefact>();
BundleRepository bundleRepository = ServerCorePlugin.getArtefactRepositoryManager().getBundleRepository(runtime.getRuntime());
for (org.eclipse.virgo.kernel.repository.BundleDefinition definition : bundleRepository.getBundles()) {
if (definition.getManifest() != null) {
BundleManifest manifest = definition.getManifest();
addImportBundleProposalsFromManifest(bundles, manifest, value);
}
}
// Add workspace bundles
for (IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
if (FacetUtils.isBundleProject(p) && !p.equals(project)) {
BundleManifest manifest = BundleManifestCorePlugin.getBundleManifestManager().getBundleManifest(JavaCore.create(p));
addImportBundleProposalsFromManifest(bundles, manifest, value);
}
}
return bundles;
}
private static Set<LibraryArtefact> getImportLibraryProposalsForRuntime(VirgoServerRuntime runtime, IProject project, String value) {
if (value == null) {
value = "";
}
Set<LibraryArtefact> libraries = new HashSet<LibraryArtefact>();
BundleRepository bundleRepository = ServerCorePlugin.getArtefactRepositoryManager().getBundleRepository(runtime.getRuntime());
for (org.eclipse.virgo.kernel.repository.LibraryDefinition definition : bundleRepository.getLibraries()) {
if (definition.getSymbolicName() != null && definition.getSymbolicName().startsWith(value)) {
libraries.add(new LibraryArtefact(definition.getName(), definition.getSymbolicName(), new OsgiVersion(definition.getVersion()),
definition.getSymbolicName(), definition.getSymbolicName()));
}
}
return libraries;
}
private static Set<org.eclipse.virgo.ide.bundlerepository.domain.PackageExport> getImportPackageProposalsForRuntime(VirgoServerRuntime runtime,
IProject project, String value) {
if (value == null) {
value = "";
}
Set<org.eclipse.virgo.ide.bundlerepository.domain.PackageExport> packages = new HashSet<org.eclipse.virgo.ide.bundlerepository.domain.PackageExport>();
BundleRepository bundleRepository = ServerCorePlugin.getArtefactRepositoryManager().getBundleRepository(runtime.getRuntime());
for (org.eclipse.virgo.kernel.repository.BundleDefinition definition : bundleRepository.getBundles()) {
if (definition.getManifest() != null) {
BundleManifest manifest = definition.getManifest();
addImportPackageProposalsFromManifest(value, packages, manifest);
}
}
// Add workspace bundles
for (IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
if (FacetUtils.isBundleProject(p) && !p.equals(project)) {
BundleManifest manifest = BundleManifestCorePlugin.getBundleManifestManager().getBundleManifest(JavaCore.create(p));
addImportPackageProposalsFromManifest(value, packages, manifest);
}
}
return packages;
}
}