blob: db1f054bb37c3cfcb1d2d86c079a6d7292acd19e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.team.examples.filesystem;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.sync.IRemoteResource;
import org.eclipse.team.internal.core.simpleAccess.SimpleAccessOperations;
/**
* SimpleAccessOperations is not part of the Team API. We use it here because it provides
* a reasonable set of operation commonly implemented by repository providers.
* Note: This class is not to be interpreted as an example of how a repository
* provider is to do its work. It is only here because we needed to have some operations
* to perform. In the future, we may update this class to illustrate the use of the workspace
* synchronizer (<code>ISynchronizer</code>).
*/
public class FileSystemSimpleAccessOperations implements SimpleAccessOperations {
// A reference to the provider
private FileSystemProvider provider;
/**
* Constructor
* @param provider
*/
FileSystemSimpleAccessOperations(FileSystemProvider provider) {
this.provider = provider;
}
/**
* Given a local resource, finds the remote counterpart.
* @param resource The local resource to lookup
* @return FileSystemRemoteResource The remote counterpart to the given local resource
*/
public FileSystemRemoteResource getRemoteResourceFor(IResource resource) {
return new FileSystemRemoteResource(provider.getRoot().append(resource.getProjectRelativePath()));
}
/**
* @see SimpleAccessOperations#get(IResource[], int, IProgressMonitor)
*/
public void get(IResource[] resources, int depth, IProgressMonitor progress) throws TeamException {
// ensure the progress monitor is not null
progress = Policy.monitorFor(progress);
progress.beginTask(Policy.bind("GetAction.working"), resources.length);
for (int i = 0; i < resources.length; i++) {
Policy.checkCanceled(progress);
IPath rootdir = provider.getRoot();
FileSystemRemoteResource remote = getRemoteResourceFor(resources[i]);
if (resources[i].getType() == IResource.FILE) {
//Copy the resource over to the other side:
IFile localFile = (IFile) resources[i]; //since we know the local resource is a file.
if (localFile.getModificationStamp() != remote.getLastModified()) {
//Only do this if the timestamps are different
try {
//Copy from the local file to the remote file:
InputStream source = null;
try {
// Get the remote file content.
source = remote.getContents(progress);
// Set the local file content to be the same as the remote file.
if (localFile.exists())
localFile.setContents(source, false, false, progress);
else
localFile.create(source, false, progress);
} finally {
if (source != null)
source.close();
}
} catch (IOException e) {
throw FileSystemPlugin.wrapException(e);
} catch (CoreException e) {
throw FileSystemPlugin.wrapException(e);
}
}
} else if (depth > 0) { //Assume that resources are either files or containers.
//If the resource is a container, copy its children over.
IRemoteResource[] estranged = remote.members(progress);
IResource[] children = new IResource[estranged.length];
if (resources[i].getType() == IResource.PROJECT) {
for (int j = 0; j < estranged.length; j++) {
if (estranged[j].isContainer())
children[j] = provider.getProject().getFolder(estranged[j].getName());
else
children[j] = provider.getProject().getFile(estranged[j].getName());
}
} else if (resources[i].getType() == IResource.FOLDER) {
//Make sure that the folder exists before trying to put anything into it:
IFolder localFolder = (IFolder) resources[i];
if (!localFolder.exists()) {
try {
localFolder.create(false, true, progress);
} catch (CoreException e) {
throw FileSystemPlugin.wrapException(e);
}
}
//Create placeholder local resources to place data into:
for (int j = 0; j < estranged.length; j++) {
if (estranged[j].isContainer())
children[j] = provider.getProject().getFolder(resources[i].getProjectRelativePath().append(estranged[j].getName()));
else
children[j] = provider.getProject().getFile(resources[i].getProjectRelativePath().append(estranged[j].getName()));
}
}
//Recurse into children:
if (children.length > 0)
get(children, depth - 1, null);
}
progress.worked(1);
}
progress.done();
}
/**
* Simply make sure that the local resource is not read only.
*
* @see SimpleAccessOperations#checkout(IResource[], int, IProgressMonitor)
*/
public void checkout(IResource[] resources, int depth, IProgressMonitor progress) throws TeamException {
progress = Policy.monitorFor(progress);
progress.beginTask("Checking resources out...", resources.length);
IPath rootdir = provider.getRoot();
for (int i = 0; i < resources.length; i++) {
Policy.checkCanceled(progress);
//Do the actual file locking:
FileSystemRemoteResource remote = getRemoteResourceFor(resources[i]);
File diskFile = new File(rootdir.append(resources[i].getProjectRelativePath()).toOSString());
if (resources[i].getType() == IResource.FILE) {
//TODO: lock the file on the 'server'.
resources[i].setReadOnly(false);
} else if (depth > 0) {
diskFile.mkdirs();
//Recursively checkout children too:
try {
IResource[] children;
if (resources[i].getType() == IResource.PROJECT)
children = provider.getProject().members();
else
children = provider.getProject().getFolder(resources[i].getName()).members();
if (children.length > 0)
checkout(children, depth - 1, null);
} catch (CoreException e) {
throw FileSystemPlugin.wrapException(e);
}
}
progress.worked(1);
}
progress.done();
}
/**
* Checkin the resources to the given depth. Mark all checked in resources as read only.
*
* @see org.eclipse.team.internal.core.simpleAccess.SimpleAccessOperations#checkin(IResource[], int, IProgressMonitor)
*/
public void checkin(IResource[] resources, int depth, IProgressMonitor progress) throws TeamException {
// ensure the progress monitor is not null
progress = Policy.monitorFor(progress);
progress.beginTask(Policy.bind("PutAction.working"), resources.length);
for (int i = 0; i < resources.length; i++) {
Policy.checkCanceled(progress);
IPath rootdir = provider.getRoot();
// Verify that the resources are checked out:
if (!isCheckedOut(resources[i]))
return;
File diskFile = new File(rootdir.append(resources[i].getProjectRelativePath()).toOSString());
if (resources[i].getType() == IResource.FILE) {
//Copy the resource over to the other side:
IFile localFile = (IFile) resources[i]; //since we know the local resource is a file.
if (localFile.getModificationStamp() != diskFile.lastModified()) {
//Only do this if the timestamps are different
try {
diskFile.getParentFile().mkdirs();
//Copy from the local file to the remote file:
InputStream in = null;
FileOutputStream out = null;
try {
in = localFile.getContents();
out = new FileOutputStream(diskFile);
//Copy the contents of the local file to the remote file:
StreamUtil.pipe(in, out, diskFile.length(), progress, diskFile.getName());
} finally {
if (in != null)
in.close();
if (out != null)
out.close();
}
} catch (IOException e) {
throw FileSystemPlugin.wrapException(e);
} catch (CoreException e) {
throw FileSystemPlugin.wrapException(e);
}
}
} else if (depth > 0) { //Assume that resources are either files or containers.
diskFile.mkdirs();
//Recursively copy children, if any, over as well:
try {
IResource[] children;
if (resources[i].getType() == IResource.PROJECT)
children = provider.getProject().members();
else
children = provider.getProject().getFolder(resources[i].getName()).members();
if (children.length > 0)
checkin(children, depth - 1, null);
} catch (CoreException e) {
throw FileSystemPlugin.wrapException(e);
}
}
progress.worked(1);
}
uncheckout(resources, depth, progress);
progress.done();
}
/**
* Mark all checked in resources as read only.
*
* @see org.eclipse.team.internal.core.simpleAccess.SimpleAccessOperations#uncheckout(IResource[], int, IProgressMonitor)
*/
public void uncheckout(IResource[] resources, int depth, IProgressMonitor progress) throws TeamException {
progress = Policy.monitorFor(progress);
progress.beginTask("Re-locking resources...", resources.length);
IPath rootdir = provider.getRoot();
for (int i = 0; i < resources.length; i++) {
Policy.checkCanceled(progress);
//Do the actual file unlocking:
FileSystemRemoteResource remote = getRemoteResourceFor(resources[i]);
File diskFile = new File(rootdir.append(resources[i].getProjectRelativePath()).toOSString());
if (resources[i].getType() == IResource.FILE) {
//TODO: unlock the file on the 'server'.
resources[i].setReadOnly(true);
} else if (depth > 0) {
diskFile.mkdirs();
//Recursively uncheckout children too:
try {
IResource[] children;
if (resources[i].getType() == IResource.PROJECT)
children = provider.getProject().members();
else
children = provider.getProject().getFolder(resources[i].getName()).members();
if (children.length > 0)
uncheckout(children, depth - 1, null);
} catch (CoreException e) {
throw FileSystemPlugin.wrapException(e);
}
}
progress.worked(1);
}
progress.done();
}
/**
* @see org.eclipse.team.internal.core.simpleAccess.SimpleAccessOperations#delete(IResource[], IProgressMonitor)
*/
public void delete(IResource[] resources, IProgressMonitor progress) throws TeamException {}
/**
* @see org.eclipse.team.internal.core.simpleAccess.SimpleAccessOperations#moved(IPath, IResource, IProgressMonitor)
*/
public void moved(IPath source, IResource target, IProgressMonitor progress) throws TeamException {}
/**
* A resource is checked out if it is not read only.
*
* @see org.eclipse.team.internal.core.simpleAccess.SimpleAccessOperations#isCheckedOut(IResource)
*/
public boolean isCheckedOut(IResource resource) {
return !resource.isReadOnly();
}
/**
* @see org.eclipse.team.internal.core.simpleAccess.SimpleAccessOperations#hasRemote(IResource)
*/
public boolean hasRemote(IResource resource) {
return false;
}
/**
* @see org.eclipse.team.internal.core.simpleAccess.SimpleAccessOperations#isDirty(IResource)
*/
public boolean isDirty(IResource resource) {
return false;
}
}