blob: c2595134353ed18f39d6374c99791310f583fa9f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2018 Ericsson
*
* All rights reserved. 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:
* Francois Chouinard - Initial API and implementation
* Bernd Hufmann - Added project creation utility
* Patrick Tasse - Refactor resource change listener
*******************************************************************************/
package org.eclipse.tracecompass.tmf.ui.project.model;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.Set;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ICoreRunnable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.tracecompass.internal.tmf.ui.Activator;
import org.eclipse.tracecompass.internal.tmf.ui.ITmfUIPreferences;
import org.eclipse.tracecompass.internal.tmf.ui.project.model.TmfProjectModelHelper;
import org.eclipse.tracecompass.tmf.core.TmfProjectNature;
import org.eclipse.tracecompass.tmf.core.io.ResourceUtil;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
/**
* Factory class storing TMF tracing projects and creating TMF project model elements.
* <p>
* @version 1.0
* @author Francois Chouinard
*/
public class TmfProjectRegistry implements IResourceChangeListener {
// Create the singleton instance
private static final TmfProjectRegistry INSTANCE = new TmfProjectRegistry();
// The map of project resource to project model elements
private static final Map<IProject, TmfProjectElement> registry = new HashMap<>();
private static final Queue<TmfTraceElement> promptQueue = new ArrayDeque<>();
private TmfProjectRegistry() {
ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
TmfSignalManager.register(this);
}
/**
* Initializes the project registry
*
* @since 3.3
*/
public static void init() {
/* static variables are initialized */
}
/**
* Disposes the project registry
*
* @since 2.3
*/
public static void dispose() {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(INSTANCE);
TmfSignalManager.deregister(INSTANCE);
registry.values().forEach(TmfProjectElement::dispose);
}
/**
* Get the project model element for a project resource
* @param project the project resource
* @return the project model element or null if it does not exist
*/
public static synchronized TmfProjectElement getProject(IProject project) {
try {
if (project.hasNature(TmfProjectNature.ID)) {
return getProject(project, true);
}
} catch (CoreException e) {
/* ignore */
}
return null;
}
/**
* Get the project model element for a project resource
* @param aProject the project resource
* @param force a flag controlling whether a new project should be created if it doesn't exist
* @return the project model element
*/
public static synchronized TmfProjectElement getProject(IProject aProject, boolean force) {
IProject project = aProject;
if (TmfProjectElement.showProjectRoot(project)) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IProject shadowProject = workspace.getRoot().getProject(TmfProjectModelHelper.getShadowProjectName(project.getName()));
if (shadowProject.exists()) {
project = shadowProject;
}
}
TmfProjectElement element = registry.get(project);
if (element == null && force) {
element = new TmfProjectElement(project.getName(), project, null);
registry.put(project, element);
// force the model to be populated
element.refreshChildren();
}
return element;
}
/**
* Utility method to create a tracing project.
*
* @param projectName
* - A project name
* @param projectLocation
* - A project location URI. Use null for default location (which is workspace).
* @param monitor
* - A progress monitor
* @return the IProject object or null
*/
public static IProject createProject(String projectName, final URI projectLocation, IProgressMonitor monitor) {
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
final IProject project = root.getProject(projectName);
WorkspaceModifyOperation action = new WorkspaceModifyOperation() {
@Override
protected void execute(IProgressMonitor progressMonitor) throws CoreException, InvocationTargetException, InterruptedException {
if (!project.exists()) {
IProjectDescription description = workspace.newProjectDescription(project.getName());
if (projectLocation != null) {
description.setLocationURI(projectLocation);
}
project.create(description, progressMonitor);
}
if (!project.isOpen()) {
project.open(progressMonitor);
}
IProjectDescription description = project.getDescription();
description.setNatureIds(new String[] { TmfProjectNature.ID });
project.setDescription(description, null);
TmfProjectElement.createFolderStructure(project);
}
};
try {
action.run(monitor);
} catch (InvocationTargetException e) {
Activator.getDefault().logError("Error creating TMF project " + project.getName(), e); //$NON-NLS-1$
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return project;
}
/**
* Add a the tracing nature to the given project resource
*
* @param project
* the project resource
* @param monitor
* - A progress monitor
* @since 3.2
*/
public static void addTracingNature(IProject project, IProgressMonitor monitor) {
WorkspaceModifyOperation action = new WorkspaceModifyOperation() {
@Override
protected void execute(IProgressMonitor progressMonitor) throws CoreException, InvocationTargetException, InterruptedException {
if (!project.exists()) {
return;
}
if (!project.isOpen()) {
project.open(progressMonitor);
}
IProjectDescription description = project.getDescription();
boolean hasNature = description.hasNature(TmfProjectNature.ID);
String[] natures = description.getNatureIds();
IWorkspace workspace = ResourcesPlugin.getWorkspace();
if (workspace == null) {
return;
}
if (!hasNature && natures.length > 0) {
// Only add nature if project doesn't have the tracing nature
String[] newNatures = new String[natures.length + 1];
System.arraycopy(natures, 0, newNatures, 0, natures.length);
// add the tracing nature ID
newNatures[natures.length] = TmfProjectNature.ID;
// validate the natures
IStatus status = workspace.validateNatureSet(newNatures);
// only apply new nature, if the status is ok
if (status.isOK()) {
description.setNatureIds(newNatures);
project.setDescription(description, null);
} else {
Activator.getDefault().getLog().log(status);
}
}
// Create shadow project
description = project.getDescription();
hasNature = description.hasNature(TmfProjectNature.ID);
natures = description.getNatureIds();
if (hasNature && natures.length > 1) {
String shadowProjectName = TmfProjectModelHelper.getShadowProjectName(project.getName());
IProject shadowProject = workspace.getRoot().getProject(shadowProjectName);
if (shadowProject.exists() && !shadowProject.isAccessible()) {
/*
* If a shadow project is not accessible, i.e. closed or deleted from file
* system while not being removed from the workspace, then remove the project
* from workspace in order to be able to successfully re-create the shadow
* project afterwards.
*/
shadowProject.delete(false, true, progressMonitor);
}
if (!shadowProject.exists()) {
// Get or create shadow project
IFolder shadowProjectFolder = TmfProjectElement.createFolderStructure(project, null);
shadowProject = createProject(shadowProjectName, shadowProjectFolder.getLocationURI(), progressMonitor);
shadowProjectFolder.refreshLocal(IResource.DEPTH_INFINITE, progressMonitor);
}
if (!shadowProject.isOpen()) {
shadowProject.open(progressMonitor);
}
// Create project directory in shadow project
TmfProjectElement.createFolderStructure(project, shadowProject);
// If the traces or experiment or supplementary folder is null
// then refresh children to make sure that the created folder(s) are
// available
TmfProjectElement tmfProject = TmfProjectRegistry.getProject(project, false);
if ((tmfProject != null) &&
((tmfProject.getTracesFolder() == null) || (tmfProject.getExperimentsFolder() == null) || (tmfProject.getSupplementaryFolder() == null))) {
tmfProject.refreshChildren();
}
}
}
};
try {
action.run(monitor);
} catch (InvocationTargetException e) {
Activator.getDefault().logError("Error adding tracing nature to project " + project.getName(), e); //$NON-NLS-1$
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// ------------------------------------------------------------------------
// IResourceChangeListener
// ------------------------------------------------------------------------
@Override
public void resourceChanged(IResourceChangeEvent event) {
if (event.getType() == IResourceChangeEvent.PRE_DELETE || event.getType() == IResourceChangeEvent.PRE_CLOSE) {
if (event.getResource() instanceof IProject) {
IProject aProject = (IProject) event.getResource();
try {
boolean isShadowProject = TmfProjectModelHelper.isShadowProject(Objects.requireNonNull(aProject));
if (aProject.isAccessible() && aProject.hasNature(TmfProjectNature.ID)) {
// A tracing project is being deleted.
IProject project = aProject;
if (!isShadowProject) {
// If a shadow project exists, use the shadow project.
IProject shadowProject = TmfProjectModelHelper.getShadowProject(project);
if (shadowProject.exists()) {
project = shadowProject;
}
}
TmfProjectElement tmfProjectElement = registry.get(project);
if (tmfProjectElement != null) {
// Close all traces editors
TmfTraceFolder tracesFolder = tmfProjectElement.getTracesFolder();
if (tracesFolder != null) {
final List<TmfTraceElement> traces = tracesFolder.getTraces();
if (!traces.isEmpty()) {
// Close editors in UI Thread
Display.getDefault().syncExec(() -> traces.forEach(TmfTraceElement::closeEditors));
}
}
}
boolean removeProjectElement = (event.getType() == IResourceChangeEvent.PRE_CLOSE);
// If parent project was deleted and a shadow project exists,
if (!isShadowProject) {
final IProject shadowProject = TmfProjectModelHelper.getShadowProject(aProject);
if (shadowProject.exists()) {
if (event.getType() == IResourceChangeEvent.PRE_DELETE) {
Display.getDefault().asyncExec(() -> {
try {
shadowProject.delete(false, true, null);
} catch (CoreException e) {
Activator.getDefault().logError("Error deleting shadow project when is parent project being deleted " + shadowProject.getName(), e); //$NON-NLS-1$
}
});
} else {
Display.getDefault().asyncExec(() -> {
try {
shadowProject.close(null);
} catch (CoreException e) {
Activator.getDefault().logError("Error removing shadow project when is parent project being closed " + shadowProject.getName(), e); //$NON-NLS-1$
}
});
}
removeProjectElement = false;
}
}
if (removeProjectElement) {
// IResourceChangeEvent.PRE_CLOSE of a non-shadow project
TmfProjectElement projectElement = registry.remove(project);
if (projectElement != null) {
projectElement.dispose();
}
}
}
} catch (CoreException e) {
Activator.getDefault().logError("Error handling resource change event for " + aProject.getName(), e); //$NON-NLS-1$
}
}
} else if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
for (IResourceDelta delta : event.getDelta().getAffectedChildren()) {
if (delta.getResource() instanceof IProject) {
IProject project = (IProject) delta.getResource();
try {
if (delta.getKind() == IResourceDelta.REMOVED) {
// Handle project deleted (it is also closed)
TmfProjectElement projectElement = registry.remove(project);
if (projectElement != null) {
projectElement.dispose();
}
// Refresh viewer for parent project
IProject parentProject = TmfProjectModelHelper.getProjectFromShadowProject(project);
if (parentProject != null) {
new TmfProjectElement(parentProject.getName(), parentProject, null).refreshViewer();
}
} else if (!project.isOpen() || !project.hasNature(TmfProjectNature.ID)) {
// Project is closed or does not have tracing nature, skip it
continue;
} else if ((delta.getKind() == IResourceDelta.ADDED) && (delta.getFlags() & IResourceDelta.MOVED_FROM) != 0 ) {
// Handle project moved - it covers only if it's not shadow project
handleProjectMoved(project);
} else if (delta.getKind() == IResourceDelta.CHANGED) {
// If shadow project exists, handle resource change in the shadow project
if (TmfProjectModelHelper.shadowProjectAccessible(project)) {
handleParentProjectRefresh(project);
continue;
} else if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
handleParentProjectOpen(project);
continue;
}
// Handle resource change in the relevant project
IProject parentProject = TmfProjectModelHelper.getProjectFromShadowProject(project);
Set<IResource> resourcesToRefresh = new HashSet<>();
Map<IResource, Integer> resourceFlags = new HashMap<>();
delta.accept(visited -> {
resourceFlags.put(visited.getResource(), visited.getFlags());
if ((visited.getFlags() & (IResourceDelta.CONTENT | IResourceDelta.LOCAL_CHANGED)) != 0) {
// visited resource content has changed, refresh it
resourcesToRefresh.add(visited.getResource());
} else if ((visited.getKind() != IResourceDelta.CHANGED)) {
IResource parent = visited.getResource().getParent();
if (((visited.getFlags() & (IResourceDelta.MOVED_FROM | IResourceDelta.MOVED_TO)) == 0)) {
// visited resource is added or removed, refresh it and its parent
resourcesToRefresh.add(visited.getResource());
resourcesToRefresh.add(parent);
} else {
Integer parentFlags = resourceFlags.get(parent);
if (parentFlags != null && ((parentFlags & (IResourceDelta.MOVED_FROM | IResourceDelta.MOVED_TO)) == 0)) {
// visited resource is moved, refresh its parent if not moved itself
resourcesToRefresh.add(parent);
}
}
}
return true;
});
Set<ITmfProjectModelElement> elementsToRefresh = new HashSet<>();
for (IResource resource : resourcesToRefresh) {
ITmfProjectModelElement element = findElement(resource, false);
if (element != null) {
elementsToRefresh.add(element);
}
}
Set<TmfTraceElement> deletedTraces = new HashSet<>();
Set<TmfTraceElement> changedTraces = new HashSet<>();
Iterator<ITmfProjectModelElement> iterator = elementsToRefresh.iterator();
while (iterator.hasNext()) {
ITmfProjectModelElement element = iterator.next();
if (element instanceof TmfTraceElement) {
TmfTraceElement trace = (TmfTraceElement) element;
IResource resource = trace.getResource();
if (isHandleDeleted(resource, parentProject)) {
deletedTraces.add(trace);
} else {
changedTraces.add(trace);
}
}
for (ITmfProjectModelElement parent : elementsToRefresh) {
// remove element if any of its parents is included
if (parent.getPath().isPrefixOf(element.getPath()) && !parent.equals(element)) {
iterator.remove();
break;
}
}
}
if (!deletedTraces.isEmpty() || !changedTraces.isEmpty()) {
Job.createSystem("TmfProjectRegistry.resourceChanged Job", monitor -> { //$NON-NLS-1$
try {
if (!deletedTraces.isEmpty()) {
Display.getDefault().syncExec(() -> {
for (TmfTraceElement deletedTrace : deletedTraces) {
deletedTrace.closeEditors();
}
});
}
ResourcesPlugin.getWorkspace().run((ICoreRunnable) (mon -> {
for (TmfTraceElement deletedTrace : deletedTraces) {
handleTraceDeleted(deletedTrace);
}
for (TmfTraceElement changedTrace : changedTraces) {
handleTraceContentChanged(changedTrace);
}
}), project, IWorkspace.AVOID_UPDATE, null);
} catch (CoreException e) {
Activator.getDefault().logError("Error handling resource change event for " + project.getName(), e); //$NON-NLS-1$
}
if (parentProject != null && parentProject.exists()) {
new TmfProjectElement(parentProject.getName(), parentProject, null).refreshViewer();
}
}).schedule();
}
for (ITmfProjectModelElement element : elementsToRefresh) {
element.refresh();
}
TmfProjectElement projectElement = registry.get(project);
if (projectElement != null) {
// refresh only the viewer for the affected project
projectElement.refreshViewer();
}
}
} catch (CoreException e) {
Activator.getDefault().logError("Error handling resource change event for " + project.getName(), e); //$NON-NLS-1$
}
}
}
}
}
private static boolean isHandleDeleted(IResource resource, IProject parentProject) {
IPath path = ResourceUtil.getLocation(resource);
if (path == null) {
return false;
}
return ((parentProject != null && parentProject.getLocation().isPrefixOf(path)) // link from shadow project to parent project
|| resource.getWorkspace().getRoot().getLocation().isPrefixOf(path)) && // link within the workspace
!path.toFile().exists();
}
// -------------------------------------------------------
// Signal handlers
// -------------------------------------------------------
/**
* Handler for the Trace Opened signal
*
* @param signal
* The incoming signal
* @since 3.1
*/
@TmfSignalHandler
public void traceOpened(TmfTraceOpenedSignal signal) {
ITmfProjectModelElement element = findElement(signal.getTrace().getResource(), true);
if (element != null) {
element.refresh();
if (element instanceof TmfExperimentElement) {
TmfExperimentElement experiment = (TmfExperimentElement) element;
for (TmfTraceElement trace : experiment.getTraces()) {
trace.getElementUnderTraceFolder().refresh();
}
}
}
}
// -------------------------------------------------------
// Helper methods
// -------------------------------------------------------
/**
* Finds an existing project model element that matches the given resource.
* Elements are not created if they do not already exist. If an exact match is
* not found and <code>exact</code> is false, returns the nearest existing
* parent element.
*
* @param resource
* the resource
* @param exact
* if an exact match is not found, returns <code>null</code> if true,
* or the nearest parent if false
* @return the element, or <code>null</code>
* @since 3.1
*/
public static ITmfProjectModelElement findElement(IResource resource, boolean exact) {
if ((resource == null) || (resource.getProject() == null)) {
return null;
}
ITmfProjectModelElement element = getProject(resource.getProject());
if (element == null) {
return null;
}
for (String segment : resource.getProjectRelativePath().segments()) {
List<ITmfProjectModelElement> children = element.getChildren();
boolean match = false;
for (ITmfProjectModelElement child : children) {
IResource childResource = child.getResource();
if (resource.equals(childResource)) {
return child;
}
if (childResource != null && segment.equals(childResource.getName())) {
element = child;
match = true;
break;
}
}
if (!match) {
/* do not return project as nearest parent */
return exact ? null : element instanceof TmfProjectElement ? null : element;
}
}
return element;
}
private static void handleTraceContentChanged(TmfTraceElement traceElement) {
boolean opened = false;
for (ITmfTrace openedTrace : TmfTraceManager.getInstance().getOpenedTraces()) {
for (ITmfTrace trace : TmfTraceManager.getTraceSet(openedTrace)) {
if (traceElement.getResource().equals(trace.getResource())) {
opened = true;
break;
}
}
}
if (!opened) {
traceElement.deleteSupplementaryResources();
return;
}
synchronized (promptQueue) {
if (!promptQueue.isEmpty()) {
/* already prompting the user */
if (!promptQueue.contains(traceElement)) {
promptQueue.add(traceElement);
}
return;
}
promptQueue.add(traceElement);
}
Display.getDefault().asyncExec(() -> {
TmfTraceElement prompting = traceElement;
while (prompting != null) {
boolean always = Activator.getDefault().getPreferenceStore().getBoolean(ITmfUIPreferences.ALWAYS_CLOSE_ON_RESOURCE_CHANGE);
if (always) {
prompting.closeEditors();
deleteSupplementaryResources(prompting);
} else {
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
MessageDialog messageDialog = new MessageDialog(shell,
Messages.TmfProjectRegistry_TraceChangedDialogTitle,
null,
NLS.bind(Messages.TmfProjectRegistry_TraceChangedDialogMessage, prompting.getElementPath()),
MessageDialog.QUESTION,
2, // Always is the default.
IDialogConstants.NO_LABEL,
IDialogConstants.YES_LABEL,
Messages.TmfProjectRegistry_Always);
int returnCode = messageDialog.open();
if (returnCode >= 1) {
// yes or always.
prompting.closeEditors();
deleteSupplementaryResources(prompting);
}
if (returnCode == 2) {
// remember to always delete supplementary files and close editors
Activator.getDefault().getPreferenceStore().setValue(ITmfUIPreferences.ALWAYS_CLOSE_ON_RESOURCE_CHANGE, true);
}
}
/*
* Poll at end of the loop: The element must remain in the queue while prompting
* the user, so that another element being handled will be added to the queue
* instead of opening another dialog, and also to prevent the user from being
* prompted twice for the same element.
*/
synchronized (promptQueue) {
promptQueue.remove();
prompting = promptQueue.peek();
}
}
});
}
private static void deleteSupplementaryResources(TmfTraceElement trace) {
/*
* Delete supplementary resources as an atomic workspace operation. To ensure no
* dialog is shown to the user, run it in a job outside of the UI thread.
*/
Job.createSystem("TmfProjectRegistry.deleteSupplementaryResources Job", monitor -> { //$NON-NLS-1$
try {
ResourcesPlugin.getWorkspace().run((ICoreRunnable) (mon -> {
trace.deleteSupplementaryResources();
}), trace.getProject().getResource(), IWorkspace.AVOID_UPDATE, monitor);
} catch (CoreException e) {
Activator.getDefault().logError("Error deleting supplementary resources for " + trace.getName(), e); //$NON-NLS-1$
}
}).schedule();
}
private static void handleTraceDeleted(TmfTraceElement trace) {
try {
trace.preDelete(new NullProgressMonitor(), false);
ResourceUtil.deleteIfBrokenSymbolicLink(trace.getResource());
} catch (CoreException e) {
Activator.getDefault().logError("Error deleting trace " + trace.getName(), e); //$NON-NLS-1$
}
}
private static void handleParentProjectOpen(IProject project) {
Job job = Job.createSystem("TmfProjectRegistry.handleParentProjectOpen Job", monitor -> { //$NON-NLS-1$
if (!project.exists() || !project.isOpen()) {
return;
}
IProject shadowProject = TmfProjectModelHelper.getShadowProject(project);
if (shadowProject != null && shadowProject.exists() && !shadowProject.isOpen()) {
try {
shadowProject.open(new NullProgressMonitor());
} catch (CoreException e) {
// Do nothing ... addTracingNature() will handle this
}
}
addTracingNature(project, monitor);
});
job.schedule();
}
private static void handleParentProjectRefresh(IProject project) {
Job job = Job.createSystem("TmfProjectRegistry.handleParentProjectRefresh Job", monitor -> { //$NON-NLS-1$
if (!project.exists() || !project.isOpen()) {
return;
}
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IProject shadowProject = workspace.getRoot().getProject(TmfProjectModelHelper.getShadowProjectName(project.getName()));
if (shadowProject.exists()) {
try {
shadowProject.refreshLocal(IResource.DEPTH_INFINITE, monitor);
} catch (CoreException e) {
Activator.getDefault().logError("Error refeshing shadow project " + shadowProject.getName(), e); //$NON-NLS-1$
}
}
});
job.schedule();
}
private static void handleProjectMoved(IProject newProject) {
Job job = Job.createSystem("TmfProjectRegistry.handleProjectMoved Job", monitor -> { //$NON-NLS-1$
if (!newProject.exists() || !newProject.isOpen()) {
return;
}
addTracingNature(newProject, monitor);
IProject shadowProject = TmfProjectModelHelper.getShadowProject(newProject);
String newShadowProjectName = TmfProjectModelHelper.getShadowProjectName(newProject.getName());
try {
if (shadowProject.exists()) {
IProjectDescription desc = shadowProject.getDescription();
desc.setName(newShadowProjectName);
shadowProject.move(desc, true, monitor);
}
} catch (CoreException e) {
Activator.getDefault().logError("Error renaming shadow project " + shadowProject.getName() + " to " + newShadowProjectName, e); //$NON-NLS-1$ //$NON-NLS-2$
}
});
job.schedule();
}
}