blob: 8074469c6dccaaa6e65f652a739d4ed250238518 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2015 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Red Hat Incorporated - fix for bug 225145
* Code 9 - ongoing development
* Pascal Rapicault - Support for bundled macosx http://bugs.eclipse.org/57349
* Ericsson AB (Pascal Rapicault) - Support to reuse bundles in place
* Red Hat Inc. - Bug 460967
*******************************************************************************/
package org.eclipse.equinox.internal.p2.touchpoint.eclipse;
import java.io.File;
import java.net.*;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
import org.eclipse.equinox.internal.p2.core.helpers.*;
import org.eclipse.equinox.internal.p2.metadata.IRequiredCapability;
import org.eclipse.equinox.internal.provisional.frameworkadmin.ConfigData;
import org.eclipse.equinox.p2.core.*;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.IRepositoryManager;
import org.eclipse.equinox.p2.repository.artifact.*;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.service.environment.EnvironmentInfo;
import org.eclipse.osgi.util.NLS;
public class Util {
/**
* TODO "cache" is probably not the right term for this location
*/
private static final String REPOSITORY_TYPE = IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY;
private static final String CACHE_EXTENSIONS = "org.eclipse.equinox.p2.cache.extensions"; //$NON-NLS-1$
private static final String PIPE = "|"; //$NON-NLS-1$
/**
* Bit-mask value representing this profile's bundle pool
*/
public static final int AGGREGATE_CACHE = 0x01;
/**
* Bit-mask value representing the shared profile's bundle pool in a shared
* install
*/
public static final int AGGREGATE_SHARED_CACHE = 0x02;
/**
* Bit-mask value representing the extension locations, such as the dropins
* folder.
*/
public static final int AGGREGATE_CACHE_EXTENSIONS = 0x04;
public static IAgentLocation getAgentLocation(IProvisioningAgent agent) {
return agent.getService(IAgentLocation.class);
}
public static IArtifactRepositoryManager getArtifactRepositoryManager(IProvisioningAgent agent) {
return agent.getService(IArtifactRepositoryManager.class);
}
public static URI getBundlePoolLocation(IProvisioningAgent agent, IProfile profile) {
String path = profile.getProperty(IProfile.PROP_CACHE);
if (path != null)
return new File(path).toURI();
IAgentLocation location = getAgentLocation(agent);
if (location == null)
return null;
return location.getDataArea(Activator.ID);
}
public static synchronized IFileArtifactRepository getBundlePoolRepository(IProvisioningAgent agent,
IProfile profile) {
URI location = getBundlePoolLocation(agent, profile);
if (location == null)
return null;
IArtifactRepositoryManager manager = getArtifactRepositoryManager(agent);
try {
IArtifactRepository repository = manager.loadRepository(location, null);
if (repository instanceof IFileArtifactRepository) {
return (IFileArtifactRepository) repository;
}
// update site repository
return null;
} catch (ProvisionException e) {
// the repository doesn't exist, so fall through and create a new one
}
try {
String repositoryName = Messages.BundlePool;
Map<String, String> properties = new HashMap<>(1);
properties.put(IRepository.PROP_SYSTEM, Boolean.TRUE.toString());
return (IFileArtifactRepository) manager.createRepository(location, repositoryName, REPOSITORY_TYPE,
properties);
} catch (ProvisionException e) {
LogHelper.log(e);
throw new IllegalArgumentException(NLS.bind(Messages.bundle_pool_not_writeable, location));
}
}
public static IFileArtifactRepository getAggregatedBundleRepository(IProvisioningAgent agent, IProfile profile) {
return getAggregatedBundleRepository(agent, profile,
AGGREGATE_CACHE | AGGREGATE_SHARED_CACHE | AGGREGATE_CACHE_EXTENSIONS);
}
public static IFileArtifactRepository getAggregatedBundleRepository(IProvisioningAgent agent, IProfile profile,
int repoFilter) {
List<IFileArtifactRepository> bundleRepositories = new ArrayList<>();
// we check for a shared bundle pool first as it should be preferred over the
// user bundle pool in a shared install
IArtifactRepositoryManager manager = getArtifactRepositoryManager(agent);
if ((repoFilter & AGGREGATE_SHARED_CACHE) != 0) {
String sharedCache = profile.getProperty(IProfile.PROP_SHARED_CACHE);
if (sharedCache != null) {
try {
URI repoLocation = new File(sharedCache).toURI();
IArtifactRepository repository = manager.loadRepository(repoLocation, null);
if (repository != null && repository instanceof IFileArtifactRepository
&& !bundleRepositories.contains(repository))
bundleRepositories.add((IFileArtifactRepository) repository);
} catch (ProvisionException e) {
// skip repository if it could not be read
}
}
}
if ((repoFilter & AGGREGATE_CACHE) != 0) {
IFileArtifactRepository bundlePool = Util.getBundlePoolRepository(agent, profile);
if (bundlePool != null)
bundleRepositories.add(bundlePool);
}
if ((repoFilter & AGGREGATE_CACHE_EXTENSIONS) != 0) {
List<String> repos = getListProfileProperty(profile, CACHE_EXTENSIONS);
for (String repo : repos) {
try {
URI repoLocation;
try {
repoLocation = new URI(repo);
} catch (URISyntaxException e) {
// in 1.0 we wrote unencoded URL strings, so try as an unencoded string
repoLocation = URIUtil.fromString(repo);
}
IArtifactRepository repository = manager.loadRepository(repoLocation, null);
if (repository != null && repository instanceof IFileArtifactRepository
&& !bundleRepositories.contains(repository))
bundleRepositories.add((IFileArtifactRepository) repository);
} catch (ProvisionException e) {
// skip repositories that could not be read
} catch (URISyntaxException e) {
// unexpected, URLs should be pre-checked
LogHelper.log(new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e));
}
}
}
getRunnableRepositories(manager, bundleRepositories);
return new AggregatedBundleRepository(agent, bundleRepositories);
}
private static void getRunnableRepositories(IArtifactRepositoryManager manager,
List<IFileArtifactRepository> bundleRepositories) {
URI[] localURLs = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_LOCAL);
for (int i = 0; i < localURLs.length; i++) {
try {
IArtifactRepository candidate = manager.loadRepository(localURLs[i], new NullProgressMonitor());
if (Boolean.parseBoolean(candidate.getProperty(IArtifactRepository.PROP_RUNNABLE))) {
if (candidate != null && candidate instanceof IFileArtifactRepository
&& !bundleRepositories.contains(candidate))
bundleRepositories.add((IFileArtifactRepository) candidate);
}
} catch (ProvisionException e) {
// skip repositories that could not be read
}
}
}
private static List<String> getListProfileProperty(IProfile profile, String key) {
List<String> listProperty = new ArrayList<>();
String dropinRepositories = profile.getProperty(key);
if (dropinRepositories != null) {
StringTokenizer tokenizer = new StringTokenizer(dropinRepositories, PIPE);
while (tokenizer.hasMoreTokens()) {
listProperty.add(tokenizer.nextToken());
}
}
return listProperty;
}
public static BundleInfo createBundleInfo(File bundleFile, IInstallableUnit unit) {
BundleInfo bundleInfo = new BundleInfo();
if (bundleFile != null)
bundleInfo.setLocation(bundleFile.toURI());
Collection<IProvidedCapability> capabilities = unit.getProvidedCapabilities();
for (IProvidedCapability capability : capabilities) {
String nameSpace = capability.getNamespace();
if (nameSpace.equals("osgi.bundle")) { //$NON-NLS-1$
bundleInfo.setSymbolicName(capability.getName());
bundleInfo.setVersion(capability.getVersion().toString());
} else if (nameSpace.equals("osgi.fragment")) { //$NON-NLS-1$
String fragmentName = capability.getName();
String fragmentHost = getFragmentHost(unit, fragmentName);
// shouldn't happen as long as the metadata is well-formed
if (fragmentHost == null)
LogHelper.log(createError("Unable to find fragment host for IU: " + unit)); //$NON-NLS-1$
else
bundleInfo.setFragmentHost(fragmentHost);
bundleInfo.setVersion(capability.getVersion().toString());
}
}
return bundleInfo;
}
public static BundleInfo findBundleInfo(ConfigData config, IInstallableUnit unit) {
// Construct a partial BundleInfo from the IU capabilities.
BundleInfo bundleInfo = Util.createBundleInfo(null, unit);
// Find the actual fully populated BundleInfo used by the runtime.
BundleInfo[] bundles = config.getBundles();
for (BundleInfo bundle : bundles) {
// Can't use BundleInfol.equals(), because bundleInfo is only partially
// populated.
if (bundleInfo.getSymbolicName().equals(bundle.getSymbolicName())
&& bundleInfo.getVersion().equals(bundle.getVersion())) {
return bundle;
}
}
return null;
}
private static String getFragmentHost(IInstallableUnit unit, String fragmentName) {
Collection<IRequirement> requires = unit.getRequirements();
for (IRequirement iRequirement : requires) {
if (iRequirement instanceof IRequiredCapability) {
IRequiredCapability requiredCapability = (IRequiredCapability) iRequirement;
if (fragmentName.equals(requiredCapability.getName())) {
String fragmentHost = requiredCapability.getName();
if (!requiredCapability.getRange().toString().equals("0.0.0")) { //$NON-NLS-1$
fragmentHost += ";bundle-version=\"" + requiredCapability.getRange() + '"'; //$NON-NLS-1$
}
return fragmentHost;
}
}
}
return null;
}
public static File getArtifactFile(IProvisioningAgent agent, IArtifactKey artifactKey, IProfile profile) {
IFileArtifactRepository aggregatedView = getAggregatedBundleRepository(agent, profile);
File bundleJar = aggregatedView.getArtifactFile(artifactKey);
return bundleJar;
}
public static File getConfigurationFolder(IProfile profile) {
String config = profile.getProperty(IProfile.PROP_CONFIGURATION_FOLDER);
if (config != null)
return new File(config);
return new File(getInstallFolder(profile), "configuration"); //$NON-NLS-1$
}
/*
* Do a look-up and return the OSGi install area if it is set.
*/
public static URL getOSGiInstallArea() {
Location location = ServiceHelper.getService(Activator.getContext(), Location.class, Location.INSTALL_FILTER);
if (location == null)
return null;
if (!location.isSet())
return null;
return location.getURL();
}
/*
* Helper method to return the eclipse.home location. Return null if it is
* unavailable.
*/
public static File getEclipseHome() {
Location eclipseHome = ServiceHelper.getService(Activator.getContext(), Location.class,
Location.ECLIPSE_HOME_FILTER);
if (eclipseHome == null || !eclipseHome.isSet())
return null;
URL url = eclipseHome.getURL();
if (url == null)
return null;
return URLUtil.toFile(url);
}
/**
* Returns the install folder for the profile, or <code>null</code> if no
* install folder is defined.
*/
public static File getInstallFolder(IProfile profile) {
String folder = profile.getProperty(IProfile.PROP_INSTALL_FOLDER);
return folder == null ? null : new File(folder);
}
public static File getLauncherPath(IProfile profile) {
String name = profile.getProperty(EclipseTouchpoint.PROFILE_PROP_LAUNCHER_NAME);
if (name == null || name.length() == 0)
name = "eclipse"; //$NON-NLS-1$
String relativePath = getLauncherRelativePath(name, getOSFromProfile(profile), getInstallFolder(profile));
return relativePath == null ? null : new File(getInstallFolder(profile), relativePath);
}
/**
* Returns the name of the Eclipse application launcher.
*/
private static String getLauncherRelativePath(String name, String os, File installFolder) {
if (os == null) {
EnvironmentInfo info = ServiceHelper.getService(Activator.getContext(), EnvironmentInfo.class);
if (info == null)
return null;
os = info.getOS();
}
if (os.equals(org.eclipse.osgi.service.environment.Constants.OS_WIN32)) {
IPath path = new Path(name);
if ("exe".equals(path.getFileExtension())) //$NON-NLS-1$
return name;
return name + ".exe"; //$NON-NLS-1$
}
if (os.equals(org.eclipse.osgi.service.environment.Constants.OS_MACOSX)) {
return "../MacOS/" + name; //$NON-NLS-1$
}
return name;
}
public static String getOSFromProfile(IProfile profile) {
String environments = profile.getProperty(IProfile.PROP_ENVIRONMENTS);
if (environments == null)
return null;
for (StringTokenizer tokenizer = new StringTokenizer(environments, ","); tokenizer.hasMoreElements();) { //$NON-NLS-1$
String entry = tokenizer.nextToken();
int i = entry.indexOf('=');
String key = entry.substring(0, i).trim();
if (!key.equals("osgi.os")) //$NON-NLS-1$
continue;
return entry.substring(i + 1).trim();
}
return null;
}
public static IStatus createError(String message) {
return createError(message, null);
}
public static IStatus createError(String message, Exception e) {
return new Status(IStatus.ERROR, Activator.ID, message, e);
}
public static IStatus createWarning(String message) {
return createWarning(message, null);
}
public static IStatus createWarning(String message, Exception e) {
return new Status(IStatus.WARNING, Activator.ID, message, e);
}
public static File getLauncherConfigLocation(IProfile profile) {
String launcherConfig = profile.getProperty(IProfile.PROP_LAUNCHER_CONFIGURATION);
return launcherConfig == null ? null : new File(launcherConfig);
}
public static String resolveArtifactParam(Map<String, Object> parameters) throws CoreException {
String artifactLocation = (String) parameters.get(EclipseTouchpoint.PARM_ARTIFACT_LOCATION);
if (artifactLocation != null)
return artifactLocation;
IArtifactKey artifactKey = (IArtifactKey) parameters.get(EclipseTouchpoint.PARM_ARTIFACT);
if (artifactKey == null) {
IInstallableUnit iu = (IInstallableUnit) parameters.get(EclipseTouchpoint.PARM_IU);
throw new CoreException(Util.createError(NLS.bind(Messages.iu_contains_no_arifacts, iu)));
}
throw new CoreException(Util.createError(NLS.bind(Messages.artifact_file_not_found, artifactKey)));
}
}