Adding support for persistant properties
diff --git a/bundles/org.eclipse.team.core/plugin.properties b/bundles/org.eclipse.team.core/plugin.properties
index 30766f0..539fdfd 100644
--- a/bundles/org.eclipse.team.core/plugin.properties
+++ b/bundles/org.eclipse.team.core/plugin.properties
@@ -3,4 +3,5 @@
FileTypesRegistry=File Types Registry
GlobalIgnoreRegistry=Global Ignore Registry
TeamProjectSets=Team Project Sets
-Targets=Target Provider and Location Factories
\ No newline at end of file
+Targets=Target Provider and Location Factories
+Repository=Repository Provider Factories
\ No newline at end of file
diff --git a/bundles/org.eclipse.team.core/plugin.xml b/bundles/org.eclipse.team.core/plugin.xml
index 194ebe0..f8fa850 100644
--- a/bundles/org.eclipse.team.core/plugin.xml
+++ b/bundles/org.eclipse.team.core/plugin.xml
@@ -20,6 +20,7 @@
<extension-point id="fileTypes" name="%FileTypesRegistry"/>
<extension-point id="ignore" name="%GlobalIgnoreRegistry"/>
<extension-point id="projectSets" name="%TeamProjectSets"/>
+<extension-point id="repository" name="%Repository"/>
<extension-point id="targets" name="%Targets"/>
<!-- Define common known file types -->
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/RepositoryProvider.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/RepositoryProvider.java
index f8ec745..509d698 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/RepositoryProvider.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/RepositoryProvider.java
@@ -22,7 +22,12 @@
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.team.IMoveDeleteHook;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.team.internal.core.*;
import org.eclipse.team.internal.core.Policy;
@@ -66,16 +71,118 @@
private final static String TEAM_SETID = "org.eclipse.team.repository-provider"; //$NON-NLS-1$
+ private final static QualifiedName PROVIDER_PROP_KEY =
+ new QualifiedName("org.eclipse.team.core", "repository"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ private final static List AllProviderTypeIds = initializeAllProviderTypes();
+
// the project instance that this nature is assigned to
private IProject project;
/**
+ * Instantiate a new RepositoryProvider with concrete class by given providerID
+ * and associate it with project.
+ * @throws TeamException
+ * <ul>
+ * <li>There is no provider by that ID.</li>
+ * <li>The project is already associated with a repository provider.</li>
+ * </ul>
+ * @see unmap(IProject)
+ */
+ public static void map(IProject project, String id) throws TeamException {
+ try {
+ RepositoryProvider existingProvider = null;
+
+ if(project.getPersistentProperty(PROVIDER_PROP_KEY) != null)
+ existingProvider = getProvider(project); // get the real one, not the nature one
+
+ //if we already have a provider, and its the same ID, we're ok
+ //if the ID's differ, unmap the existing.
+ if(existingProvider != null) {
+ if(existingProvider.getID().equals(id))
+ return; //nothing to do
+ else
+ unmap(project);
+ }
+
+ RepositoryProvider provider = mapNewProvider(project, id);
+ project.setPersistentProperty(PROVIDER_PROP_KEY, id);
+
+ try {
+ provider.configureProject(); //xxx not sure if needed since they control with wiz page and can configure all they want
+ } catch (CoreException e) {
+ project.setPersistentProperty(PROVIDER_PROP_KEY, null);
+ throw e;
+ }
+ //and mark it with the persistent ID for filtering and session persistence
+ } catch (CoreException e) {
+ throw TeamPlugin.wrapException(e);
+ }
+ }
+
+ /*
+ * Instantiate the provider denoted by ID and store it in the session property.
+ * Return the new provider instance.
+ * @throws TeamException if the we can't instantiate the provider,
+ * or if the set session property fails from core
+ */
+ private static RepositoryProvider mapNewProvider(IProject project, String id) throws TeamException {
+ RepositoryProvider provider = newProvider(id); // instantiate via extension point
+
+ if(provider == null)
+ throw new TeamException(Policy.bind("RepositoryProvider.couldNotInstantiateProvider", project.getName(), id));
+
+ provider.setProject(project);
+ //store provider instance as session property
+ try {
+ project.setSessionProperty(PROVIDER_PROP_KEY, provider);
+ } catch (CoreException e) {
+ throw TeamPlugin.wrapException(e);
+ }
+ return provider;
+ }
+
+ /**
+ * Disassoociates project with the repository provider its currently mapped to.
+ * @throws TeamException The project isn't associated with any repository provider.
+ */
+ public static void unmap(IProject project) throws TeamException {
+ try{
+ boolean hasProviderAssociated = project.getPersistentProperty(PROVIDER_PROP_KEY) != null;
+
+ //If you tried to remove a non-existance nature it would fail, so we need to as well with the persistent prop
+ if(! hasProviderAssociated)
+ throw new TeamException(Policy.bind("RepositoryProvider.No_Provider_Registered", project.getName())); //$NON-NLS-1$
+
+ //This will instantiate one if it didn't already exist,
+ //which is ok since we need to call deconfigure() on it for proper lifecycle
+ getProvider(project).deconfigure();
+
+ project.setSessionProperty(PROVIDER_PROP_KEY, null);
+ project.setPersistentProperty(PROVIDER_PROP_KEY, null);
+
+ //removing the nature would've caused project description delta, so trigger one
+ project.setDescription(project.getDescription(), null);
+ } catch (CoreException e) {
+ throw TeamPlugin.wrapException(e);
+ }
+ }
+
+ /*
+ * Return the provider mapped to project, or null if none;
+ */
+ private static RepositoryProvider lookupProviderProp(IProject project) throws CoreException {
+ return (RepositoryProvider) project.getSessionProperty(PROVIDER_PROP_KEY);
+ }
+
+
+ /**
* Default constructor required for the resources plugin to instantiate this class from
* the nature extension definition.
*/
public RepositoryProvider() {
}
-
+
/**
* Configures the nature for the given project. This method is called after <code>setProject</code>
* and before the nature is added to the project. If an exception is generated during configuration
@@ -99,7 +206,7 @@
configureProject();
} catch(CoreException e) {
try {
- Team.removeNatureFromProject(getProject(), getID(), null);
+ RepositoryProvider.unmap(getProject());
} catch(TeamException e2) {
throw new CoreException(new Status(IStatus.ERROR, TeamPlugin.ID, 0, Policy.bind("RepositoryProvider_Error_removing_nature_from_project___1") + getID(), e2)); //$NON-NLS-1$
}
@@ -151,7 +258,7 @@
* @return a string description of this provider
*/
public String toString() {
- return getProject().getName() + ":" + getID(); //$NON-NLS-1$
+ return Policy.bind("RepositoryProvider.toString", getProject().getName(), getID()); //$NON-NLS-1$
}
/**
@@ -162,6 +269,10 @@
final public static String[] getAllProviderTypeIds() {
IProjectNatureDescriptor[] desc = ResourcesPlugin.getWorkspace().getNatureDescriptors();
List teamSet = new ArrayList();
+
+ teamSet.addAll(AllProviderTypeIds); // add in all the ones we know via extension point
+
+ //fall back to old method of nature ID to find any for backwards compatibility
for (int i = 0; i < desc.length; i++) {
String[] setIds = desc[i].getNatureSetIds();
for (int j = 0; j < setIds.length; j++) {
@@ -183,8 +294,34 @@
* @return the repository provider associated with the project
*/
final public static RepositoryProvider getProvider(IProject project) {
- try {
+ try {
if(project.isAccessible()) {
+
+ //-----------------------------
+ //First check if we are using the persistent property to tag the project with provider
+
+ //
+ String id = project.getPersistentProperty(PROVIDER_PROP_KEY);
+ RepositoryProvider provider = lookupProviderProp(project); //throws core, we will reuse the catching already here
+
+ //If we have the session but not the persistent, we have a problem
+ //because we somehow got only halfway through mapping before
+ if(id == null && provider != null) {
+ TeamPlugin.log(IStatus.ERROR, Policy.bind("RepositoryProvider.propertyMismatch", project.getName()), null);
+ project.setSessionProperty(PROVIDER_PROP_KEY, null); //clears it
+ return null;
+ }
+
+ if(provider != null)
+ return provider;
+
+ //check if it has the ID as a persistent property, if yes then instantiate provider
+ if(id != null)
+ return mapNewProvider(project, id);
+
+ //Couldn't find using new method, fall back to lookup using natures for backwards compatibility
+ //-----------------------------
+
IProjectDescription projectDesc = project.getDescription();
String[] natureIds = projectDesc.getNatureIds();
IWorkspace workspace = ResourcesPlugin.getWorkspace();
@@ -204,7 +341,9 @@
}
}
} catch(CoreException e) {
- TeamPlugin.log(new Status(IStatus.ERROR, TeamPlugin.ID, 0, Policy.bind(""), e)); //$NON-NLS-1$
+ TeamPlugin.log(e.getStatus());
+ } catch(TeamException e) {
+ TeamPlugin.log(e.getStatus());
}
return null;
}
@@ -221,9 +360,27 @@
final public static RepositoryProvider getProvider(IProject project, String id) {
try {
if(project.isAccessible()) {
+ String existingID = project.getPersistentProperty(PROVIDER_PROP_KEY);
+
+ if(id.equals(existingID)) {
+ //if the IDs are the same then they were previously mapped
+ //see if we already instantiated one
+ RepositoryProvider provider = lookupProviderProp(project); //throws core, we will reuse the catching already here
+ if(provider != null)
+ return provider;
+ //otherwise instantiate and map a new one
+ return mapNewProvider(project, id);
+ }
+
+ //couldn't find using new method, fall back to lookup using natures for backwards compatibility
+ //-----------------------------
+
// if the nature id given is not in the team set then return
// null.
IProjectNatureDescriptor desc = ResourcesPlugin.getWorkspace().getNatureDescriptor(id);
+ if(desc == null) //for backwards compat., may not have any nature by that ID
+ return null;
+
String[] setIds = desc.getNatureSetIds();
for (int i = 0; i < setIds.length; i++) {
if(setIds[i].equals(TEAM_SETID)) {
@@ -231,9 +388,11 @@
}
}
}
- } catch(CoreException ex) {
+ } catch(CoreException e) {
// would happen if provider nature id is not registered with the resources plugin
- TeamPlugin.log(new Status(IStatus.WARNING, TeamPlugin.ID, 0, Policy.bind("RepositoryProviderTypeRepositoryProvider_not_registered_as_a_nature_id___3") + id, ex)); //$NON-NLS-1$
+ TeamPlugin.log(new Status(IStatus.WARNING, TeamPlugin.ID, 0, Policy.bind("RepositoryProviderTypeRepositoryProvider_not_registered_as_a_nature_id___3", id), e)); //$NON-NLS-1$
+ } catch(TeamException e) {
+ TeamPlugin.log(e.getStatus());
}
return null;
}
@@ -264,4 +423,68 @@
public void setProject(IProject project) {
this.project = project;
}
+
+ private static List initializeAllProviderTypes() {
+ List allIDs = new ArrayList();
+
+ TeamPlugin plugin = TeamPlugin.getPlugin();
+ if (plugin != null) {
+ IExtensionPoint extension = plugin.getDescriptor().getExtensionPoint(TeamPlugin.REPOSITORY_EXTENSION);
+ if (extension != null) {
+ IExtension[] extensions = extension.getExtensions();
+ for (int i = 0; i < extensions.length; i++) {
+ IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
+ for (int j = 0; j < configElements.length; j++) {
+ String extensionId = configElements[j].getAttribute("id"); //$NON-NLS-1$
+ allIDs.add(extensionId);
+ }
+ }
+ }
+ }
+ return allIDs;
+ }
+
+ private static RepositoryProvider newProvider(String id) {
+ TeamPlugin plugin = TeamPlugin.getPlugin();
+ if (plugin != null) {
+ IExtensionPoint extension = plugin.getDescriptor().getExtensionPoint(TeamPlugin.REPOSITORY_EXTENSION);
+ if (extension != null) {
+ IExtension[] extensions = extension.getExtensions();
+ for (int i = 0; i < extensions.length; i++) {
+ IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
+ for (int j = 0; j < configElements.length; j++) {
+ String extensionId = configElements[j].getAttribute("id"); //$NON-NLS-1$
+ if (extensionId != null && extensionId.equals(id)) {
+ try {
+ return (RepositoryProvider) configElements[j].createExecutableExtension("class"); //$NON-NLS-1$
+ } catch (CoreException e) {
+ TeamPlugin.log(e.getStatus());
+ return null;
+ }
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * Convert a project that are using natures to mark them as Team projects
+ * to instead use persistent properties. Optionally remove the nature from the project.
+ * Do nothing if the project has no Team nature.
+ * Assume that the same ID is used for both the nature and the persistent property.
+ */
+ public static void convertNatureToProperty(IProject project, boolean removeNature) throws TeamException {
+ RepositoryProvider provider = RepositoryProvider.getProvider(project);
+ if(provider == null)
+ return;
+
+ String providerId = provider.getID();
+
+ RepositoryProvider.map(project, providerId);
+ if(removeNature) {
+ Team.removeNatureFromProject(project, providerId, new NullProgressMonitor());
+ }
+ }
}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/TeamPlugin.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/TeamPlugin.java
index e5c69b1..9f0785f 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/TeamPlugin.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/TeamPlugin.java
@@ -45,6 +45,8 @@
// The id of the project set extension point
public static final String PROJECT_SET_EXTENSION = "projectSets"; //$NON-NLS-1$
// The id of the targets extension point
+ public static final String REPOSITORY_EXTENSION = "repository"; //$NON-NLS-1$
+ // The id of the targets extension point
public static final String TARGETS_EXTENSION = "targets"; //$NON-NLS-1$
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties
index 0e99a25..f1df48b 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties
@@ -27,9 +27,11 @@
RepositoryProvider_Too_many_providers_associated_with_project___2=Too many providers associated with project:
RepositoryProviderTypeduplicate_provider_found_in_plugin.xml___1=duplicate provider found in plugin.xml:
RepositoryProviderTypeRepositoryProvider_assigned_to_the_project_must_be_a_subclass_of_RepositoryProvider___2=RepositoryProvider assigned to the project must be a subclass of RepositoryProvider:
-RepositoryProviderTypeRepositoryProvider_not_registered_as_a_nature_id___3=RepositoryProvider not registered as a nature id:
-
+RepositoryProviderTypeRepositoryProvider_not_registered_as_a_nature_id___3=RepositoryProvider not registered as a nature id: {1}.
RepositoryProvider_providerTypeIdNotRegistered=Error configuring the RepositoryProvider the nature id is not registered as a valid RepositoryProviderType id.
+RepositoryProvider.couldNotInstantiateProvider=Could not instantiate provider {1} for project {0}.
+RepositoryProvider.No_Provider_Registered=No provider registered for {0}.
+RepositoryProvider.propertyMismatch=Inconsistent session/persistent property state looking up provider {1}.
TeamPlugin_setting_global_ignore_7=setting global ignore
TeamPlugin_renaming_21=renaming
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/NatureToPropertyAction.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/NatureToPropertyAction.java
new file mode 100644
index 0000000..8d8fbdb
--- /dev/null
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/NatureToPropertyAction.java
@@ -0,0 +1,51 @@
+package org.eclipse.team.internal.ui;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.team.core.RepositoryProvider;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.internal.ui.actions.TeamAction;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+
+/**
+ * @author Administrator
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class NatureToPropertyAction extends TeamAction {
+
+ /**
+ * @see org.eclipse.team.internal.ui.actions.TeamAction#isEnabled()
+ */
+ protected boolean isEnabled() throws TeamException {
+ return true;
+ }
+
+ /**
+ * @see org.eclipse.ui.IActionDelegate#run(IAction)
+ */
+ public void run(IAction action) {
+ run(new WorkspaceModifyOperation() {
+ public void execute(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException {
+ try {
+ IProject[] projects = getSelectedProjects();
+ for (int i = 0; i < projects.length; i++) {
+ RepositoryProvider.convertNatureToProperty(projects[i], true);
+ }
+ } catch (TeamException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ }
+ }, Policy.bind("NatureToPropertyAction.label"), this.PROGRESS_DIALOG); //$NON-NLS-1$
+ }
+
+}
+
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties
index 0cc4034..83065d1 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties
@@ -124,6 +124,8 @@
TeamPreferencePage.General_settings_for_Team_support_1=General settings for Team support
TeamPreferencePage.&Use_Incoming/Outgoing_mode_when_synchronizing_2=&Use Incoming/Outgoing mode when synchronizing
+NatureToPropertyAction.label=Convert Nature
+
###############################################
# Target Management Messages
###############################################