blob: 525ceccc1bab72e2c37668d3164415bd5304fdcb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2015 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.p2.touchpoint.eclipse.actions;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.equinox.internal.p2.touchpoint.eclipse.Util;
import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent;
import org.eclipse.equinox.p2.core.IAgentLocation;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.engine.spi.ProvisioningAction;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.IRepositoryManager;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.osgi.util.NLS;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
/**
* Helper base class for dealing with repositories associated with profiles. Repositories
* are associated with a profile by encoding the repository locations in a comma-delimited
* list in a profile property.
* @see AddRepositoryAction
* @see RemoveRepositoryAction
*/
abstract class RepositoryAction extends ProvisioningAction {
private static final String METADATA_REPOSITORY = "org.eclipse.equinox.p2.metadata.repository"; //$NON-NLS-1$
private static final String ARTIFACT_REPOSITORY = "org.eclipse.equinox.p2.artifact.repository"; //$NON-NLS-1$
private static final String NODE_REPOSITORIES = "repositories"; //$NON-NLS-1$
private static final String REPOSITORY_COUNT = "count"; //$NON-NLS-1$
private static final String KEY_URI = "uri"; //$NON-NLS-1$
private static final String KEY_ENABLED = "enabled"; //$NON-NLS-1$
private static final String KEY_NICKNAME = "nickname"; //$NON-NLS-1$
/**
* Returns the repository manager of the given type, or <code>null</code>
* if not available.
*/
private static IRepositoryManager<?> getRepositoryManager(IProvisioningAgent agent, int type) {
if (type == IRepository.TYPE_METADATA) {
return (IRepositoryManager<?>) agent.getService(IMetadataRepositoryManager.SERVICE_NAME);
} else if (type == IRepository.TYPE_ARTIFACT) {
return (IRepositoryManager<?>) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);
}
return null;
}
/**
* Associates the repository described by the given event with the given profile.
* Has no effect if the repository is already associated with this profile.
*/
protected void addRepositoryToProfile(IAgentLocation agentLocation, IProfile profile, URI location, String nickname, int type, boolean enabled) {
Preferences node = getRepositoryPreferenceNode(agentLocation, profile, location, type);
int count = 0;
if (repositoryExists(node)) {
count = getRepositoryCount(node);
// If a user has added a repository we need to set the initial count manually
if (count == 0)
count = 1;
}
node.put(KEY_URI, location.toString());
node.put(KEY_ENABLED, Boolean.toString(enabled));
if (nickname != null)
node.put(KEY_NICKNAME, nickname);
count++;
setRepositoryCount(node, count);
try {
node.flush();
} catch (BackingStoreException e) {
// TODO: perhaps an Exception should be passed backwards and associated with State
}
}
/**
* Adds the repository corresponding to the given event to the currently running instance.
*/
protected void addToSelf(IProvisioningAgent agent, IAgentLocation agentLocation, RepositoryEvent event) {
IRepositoryManager<?> manager = getRepositoryManager(agent, event.getRepositoryType());
final URI location = event.getRepositoryLocation();
Preferences node = getRepositoryPreferenceNode(agentLocation, null, location, event.getRepositoryType());
int count = getRepositoryCount(node);
if (manager.contains(location)) {
// If a user as added a repository we need to set the initial count manually
if (count == 0)
count = 1;
} else {
if (manager != null)
manager.addRepository(location);
}
// increment the counter & send to preferences
count++;
setRepositoryCount(node, count);
if (!event.isRepositoryEnabled())
manager.setEnabled(location, false);
final String name = event.getRepositoryNickname();
if (name != null)
manager.setRepositoryProperty(location, IRepository.PROP_NICKNAME, name);
}
protected RepositoryEvent createEvent(Map<String, Object> parameters) throws CoreException {
String parm = (String) parameters.get(ActionConstants.PARM_REPOSITORY_LOCATION);
if (parm == null)
throw new CoreException(Util.createError(NLS.bind(Messages.parameter_not_set, ActionConstants.PARM_REPOSITORY_LOCATION, getId())));
URI location = null;
try {
location = new URI(parm);
} catch (URISyntaxException e) {
throw new CoreException(Util.createError(NLS.bind(Messages.parameter_not_set, ActionConstants.PARM_REPOSITORY_LOCATION, getId()), e));
}
parm = (String) parameters.get(ActionConstants.PARM_REPOSITORY_TYPE);
if (parm == null)
throw new CoreException(Util.createError(NLS.bind(Messages.parameter_not_set, ActionConstants.PARM_REPOSITORY_TYPE, getId())));
int type = 0;
try {
type = Integer.parseInt(parm);
} catch (NumberFormatException e) {
throw new CoreException(Util.createError(NLS.bind(Messages.parameter_not_set, ActionConstants.PARM_REPOSITORY_TYPE, getId()), e));
}
String name = (String) parameters.get(ActionConstants.PARM_REPOSITORY_NICKNAME);
//default is to be enabled
String enablement = (String) parameters.get(ActionConstants.PARM_REPOSITORY_ENABLEMENT);
boolean enabled = enablement == null ? true : Boolean.parseBoolean(enablement);
return RepositoryEvent.newDiscoveryEvent(location, name, type, enabled);
}
/**
* Returns the id of this action.
*/
protected abstract String getId();
/**
* Return <code>true</code> if the given profile is the currently running profile,
* and <code>false</code> otherwise.
*/
protected boolean isSelfProfile(IProfileRegistry registry, IProfile profile) {
//if we can't determine the current profile, assume we are running on self
if (profile == null)
return true;
if (registry == null)
return false;
final IProfile selfProfile = registry.getProfile(IProfileRegistry.SELF);
//if we can't determine the self profile, assume we are running on self
if (selfProfile == null)
return true;
return profile.getProfileId().equals(selfProfile.getProfileId());
}
/**
* Removes the repository corresponding to the given event from the currently running instance.
*/
protected void removeFromSelf(IProvisioningAgent agent, IAgentLocation agentLocation, RepositoryEvent event) {
IRepositoryManager<?> manager = getRepositoryManager(agent, event.getRepositoryType());
Preferences node = getRepositoryPreferenceNode(agentLocation, null, event.getRepositoryLocation(), event.getRepositoryType());
int count = getRepositoryCount(node);
// modify the repository count before (potentially) removing the preference node
setRepositoryCount(node, --count);
if (count < 1 && manager != null)
manager.removeRepository(event.getRepositoryLocation());
}
/**
* Removes the association between the repository described by the given event
* and the given profile. Has no effect if the location is not already associated with
* this profile.
*/
protected void removeRepositoryFromProfile(IAgentLocation agentLocation, IProfile profile, URI location, int type) {
Preferences node = getRepositoryPreferenceNode(agentLocation, profile, location, type);
int count = getRepositoryCount(node);
if (--count < 1) {
// TODO: Remove all associated values
try {
String[] keys = node.keys();
for (int i = 0; i < keys.length; i++)
node.remove(keys[i]);
} catch (BackingStoreException e) {
// TODO: Should this be passed back to be associated with State?
}
} else
setRepositoryCount(node, count);
try {
node.flush();
} catch (BackingStoreException e) {
// TODO: perhaps an Exception should be passed backwards and associated with State
}
}
/*
* Get the counter associated with a repository
*/
protected int getRepositoryCount(Preferences node) {
return node.getInt(REPOSITORY_COUNT, 0);
}
/*
* Sets the counter associated with this repository to a specific value
*/
protected void setRepositoryCount(Preferences node, int count) {
if (count < 1)
node.remove(REPOSITORY_COUNT);
else
node.putInt(REPOSITORY_COUNT, count);
}
/*
* Determine if a repository is already known
*/
protected boolean repositoryExists(Preferences node) {
if (node.get(KEY_URI, null) == null)
return false;
return true;
}
/*
* Get the preference node associated with profile & location
*/
protected Preferences getRepositoryPreferenceNode(IAgentLocation agentLocation, IProfile profile, URI location, int type) {
String key = type == IRepository.TYPE_METADATA ? METADATA_REPOSITORY : ARTIFACT_REPOSITORY;
String profileId = profile == null ? IProfileRegistry.SELF : profile.getProfileId();
return new ProfileScope(agentLocation, profileId).getNode(key + '/' + NODE_REPOSITORIES + '/' + getKey(location));
}
/*
* Copied from AbstractRepositoryManager
*/
private String getKey(URI location) {
String key = location.toString().replace('/', '_');
//remove trailing slash
if (key.endsWith("_")) //$NON-NLS-1$
key = key.substring(0, key.length() - 1);
return key;
}
protected IProvisioningAgent getAgent(Map<String, Object> parameters) throws CoreException {
//We shouldn't really know about the session parameter
IProvisioningAgent agent = (IProvisioningAgent) parameters.get("agent"); //$NON-NLS-1$
if (agent == null)
throw new CoreException(Util.createError(NLS.bind(Messages.parameter_not_set, "agent", getId()))); //$NON-NLS-1$
return agent;
}
}