/*******************************************************************************
* Copyright (c) 2005 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.buckminster.pde.internal.dialogs;
import org.eclipse.buckminster.pde.PDEPlugin;
import org.eclipse.buckminster.runtime.MonitorUtils;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.osgi.util.NLS;
/**
* For creating folder resources that currently do not exist, along a given
* workspace path.
* <p>
* This class may be instantiated; it is not intended to be subclassed.
* </p>
* <p>
* Example usage:
*
* <pre>
* ContainerGenerator gen = new ContainerGenerator(new Path("/A/B"));
* IContainer res = null;
* try {
* res = gen.getContainer(monitor); // creates project A and folder B if
* // required
* } catch (CoreException e) {
* // handle failure
* } catch (OperationCanceledException e) {
* // handle cancelation
* }
* </pre>
*
* </p>
*/
public class ContainerGenerator {
private IPath containerFullPath;
private IContainer container;
/**
* Creates a generator for the container resource (folder or project) at the
* given workspace path. Assumes the path has already been validated.
* <p>
* Call <code>getContainer</code> to create any missing resources along the
* path.
* </p>
*
* @param containerPath
* the workspace path of the container
*/
public ContainerGenerator(IPath containerPath) {
super();
this.containerFullPath = containerPath;
}
/**
* Ensures that this generator's container resource exists. Creates any
* missing resource containers along the path; does nothing if the container
* resource already exists.
* <p>
* Note: This method should be called within a workspace modify operation
* since it may create resources.
* </p>
*
* @param monitor
* a progress monitor
* @return the container resource
* @exception CoreException
* if the operation fails
* @exception OperationCanceledException
* if the operation is canceled
*/
public IContainer generateContainer(IProgressMonitor topMonitor) throws CoreException {
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
monitor.beginTask("IDEWorkbenchMessages.ContainerGenerator_progressMessage", 1000 * containerFullPath //$NON-NLS-1$
.segmentCount());
if (container != null)
return;
// Does the container exist already?
IWorkspaceRoot root = getWorkspaceRoot();
container = (IContainer) root.findMember(containerFullPath);
if (container != null)
return;
// Create the container for the given path
container = root;
for (int i = 0; i < containerFullPath.segmentCount(); i++) {
String currentSegment = containerFullPath.segment(i);
IResource resource = container.findMember(currentSegment);
if (resource != null) {
if (resource.getType() == IResource.FILE) {
String msg = NLS.bind("IDEWorkbenchMessages.ContainerGenerator_pathOccupied", resource //$NON-NLS-1$
.getFullPath().makeRelative());
throw new CoreException(new Status(IStatus.ERROR, PDEPlugin.getPluginId(), 1, msg, null));
}
container = (IContainer) resource;
MonitorUtils.worked(monitor, 1000);
} else {
if (i == 0) {
IProject projectHandle = createProjectHandle(root, currentSegment);
container = createProject(projectHandle, MonitorUtils.subMonitor(monitor, 1000));
} else {
IFolder folderHandle = createFolderHandle(container, currentSegment);
container = createFolder(folderHandle, MonitorUtils.subMonitor(monitor, 1000));
}
}
}
}
}, null, IResource.NONE, topMonitor);
return container;
}
/**
* Creates a folder resource for the given folder handle.
*
* @param folderHandle
* the handle to create a folder resource
* @param monitor
* the progress monitor to show visual progress
* @return the folder handle (<code>folderHandle</code>)
* @throws CoreException
* if the operation fails
*/
private IFolder createFolder(IFolder folderHandle, IProgressMonitor monitor) throws CoreException {
folderHandle.create(false, true, monitor);
MonitorUtils.testCancelStatus(monitor);
return folderHandle;
}
/**
* Creates a folder resource handle for the folder with the given name. This
* method does not create the folder resource; this is the responsibility of
* <code>createFolder</code>.
*
* @param container
* the resource container
* @param folderName
* the name of the folder
* @return the new folder resource handle
*/
private IFolder createFolderHandle(IContainer resourceContainer, String folderName) {
return resourceContainer.getFolder(new Path(folderName));
}
/**
* Creates a project resource for the given project handle.
*
* @param projectHandle
* the handle to create a project resource
* @param monitor
* the progress monitor to show visual progress
* @return the project handle (<code>projectHandle</code>)
* @exception CoreException
* if the operation fails
* @exception OperationCanceledException
* if the operation is canceled
*/
private IProject createProject(IProject projectHandle, IProgressMonitor monitor) throws CoreException {
try {
monitor.beginTask("", 2000);//$NON-NLS-1$
projectHandle.create(MonitorUtils.subMonitor(monitor, 1000));
projectHandle.open(MonitorUtils.subMonitor(monitor, 1000));
} finally {
monitor.done();
}
return projectHandle;
}
/**
* Creates a project resource handle for the project with the given name.
* This method does not create the project resource; this is the
* responsibility of <code>createProject</code>.
*
* @param root
* the workspace root resource
* @param projectName
* the name of the project
* @return the new project resource handle
*/
private IProject createProjectHandle(IWorkspaceRoot root, String projectName) {
return root.getProject(projectName);
}
/**
* Returns the workspace root resource handle.
*
* @return the workspace root resource handle
*/
private IWorkspaceRoot getWorkspaceRoot() {
return ResourcesPlugin.getWorkspace().getRoot();
}
}