blob: df87089792e23651d975895c31e10a0adca127d8 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2008, 2009 Versant 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:
* Remy Chi Jian Suen (Versant Corporation) - initial API and implementation
******************************************************************************/
package org.eclipse.team.internal.ecf.core;
import java.io.*;
import java.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.ecf.core.identity.ID;
import org.eclipse.ecf.core.util.ECFException;
import org.eclipse.ecf.datashare.AbstractShare;
import org.eclipse.ecf.datashare.IChannelContainerAdapter;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.internal.ecf.core.messages.*;
import org.eclipse.team.internal.ecf.core.variants.RemoteResourceVariant;
public class RemoteShare extends AbstractShare {
private Map participants = new HashMap();
private Object returnValue;
public RemoteShare(IChannelContainerAdapter adapter) throws ECFException {
super(adapter);
}
public synchronized boolean sendShareRequest(ID localId, ID remoteId, IResource[] resources, IProgressMonitor monitor) throws ECFException, InterruptedException {
Assert.isNotNull(localId);
Assert.isNotNull(remoteId);
Assert.isNotNull(resources);
sendMessage(remoteId, serialize(new ShareRequest(localId, resources)));
while (returnValue == null) {
Thread.sleep(100);
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
}
Object tmpValue = returnValue;
returnValue = null;
return ((Boolean) tmpValue).booleanValue();
}
public synchronized IResourceVariant[] fetchMembers(ID ownId, ID remoteId, IResourceVariant variant, IProgressMonitor monitor) throws TeamException {
RemoteResourceVariant remoteVariant = (RemoteResourceVariant) variant;
if (!remoteVariant.hasMembers()) {
// we've predetermined that this resource will not have any valid
// members, just return an empty array
return new IResourceVariant[0];
}
monitor.subTask(NLS.bind(Messages.RemoteShare_FetchingVariant, variant.getName()));
sendMessage(remoteId, new FetchVariantsRequest(ownId, remoteVariant.getPath(), remoteVariant.getType()));
while (returnValue == null) {
try {
Thread.sleep(100);
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
} catch (InterruptedException e) {
// TODO: do we want to handle this differently...?
Thread.interrupted();
throw new TeamException("Interrupted whilst fetching members"); //$NON-NLS-1$
}
}
monitor.done();
Object tmpValue = returnValue;
returnValue = null;
return (IResourceVariant[]) tmpValue;
}
public synchronized IResourceVariant fetchVariant(ID ownId, ID remoteId, IResource resource, IProgressMonitor monitor) throws TeamException {
monitor.subTask(NLS.bind(Messages.RemoteShare_FetchingVariant, resource.getFullPath().toString().substring(1)));
sendMessage(remoteId, new FetchVariantRequest(ownId, resource.getFullPath().toString(), resource.getType()));
while (returnValue == null) {
try {
Thread.sleep(100);
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
} catch (InterruptedException e) {
// TODO: do we want to handle this differently...?
Thread.interrupted();
throw new TeamException("Interrupted whilst fetching variant"); //$NON-NLS-1$
}
}
monitor.done();
Object tmpValue = returnValue;
returnValue = null;
return ((IResourceVariant[]) tmpValue)[0];
}
public synchronized IResourceVariant getResourceVariant(ID ownId, ID remoteId, IResource resource) throws TeamException {
sendMessage(remoteId, new FetchVariantRequest(ownId, resource.getFullPath().toString(), resource.getType()));
// FIXME: no progress monitor is available for this method, a timeout
// needs to be implemented at the preferences layer
while (returnValue == null) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO: do we want to handle this differently...?
Thread.interrupted();
throw new TeamException("Interrupted whilst getting variant"); //$NON-NLS-1$
}
}
Object tmpValue = returnValue;
returnValue = null;
return ((IResourceVariant[]) tmpValue)[0];
}
private void sendMessage(ID id, Serializable serializable) {
try {
sendMessage(id, serialize(serializable));
} catch (ECFException e) {
TeamSynchronization.log("Could not send message to peer " + id, e); //$NON-NLS-1$
}
}
protected void handleMessage(ID fromContainerId, byte[] data) {
Object message = deserialize(data);
if (message instanceof FetchVariantsRequest) {
FetchVariantRequest msg = (FetchVariantRequest) message;
String path = msg.getPath();
IContainer container = null;
switch (msg.getType()) {
case IResource.FILE :
// this shouldn't happen as the fetch request should not have
// been sent for files in the first place
TeamSynchronization.log("Files should not have any variants to request for"); //$NON-NLS-1$
break;
case IResource.PROJECT :
container = ResourcesPlugin.getWorkspace().getRoot().getProject(new Path(path).lastSegment());
break;
case IResource.FOLDER :
container = ResourcesPlugin.getWorkspace().getRoot().getFolder(new Path(path));
break;
default :
TeamSynchronization.log("Unsupported resource type specified: " //$NON-NLS-1$
+ msg.getType());
break;
}
sendFetchVariantsResponse(msg.getFromId(), container);
} else if (message instanceof FetchVariantRequest) {
FetchVariantRequest msg = (FetchVariantRequest) message;
IResource resource = null;
IPath path = new Path(msg.getPath());
switch (msg.getType()) {
case IResource.PROJECT :
resource = ResourcesPlugin.getWorkspace().getRoot().getProject(path.lastSegment());
break;
case IResource.FOLDER :
resource = ResourcesPlugin.getWorkspace().getRoot().getFolder(path);
break;
case IResource.FILE :
resource = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
break;
default :
TeamSynchronization.log("Unsupported resource type specified: " //$NON-NLS-1$
+ msg.getType());
break;
}
sendFetchVariantResponse(msg.getFromId(), resource);
} else if (message instanceof ShareRequest) {
ShareRequest request = (ShareRequest) message;
boolean response = prompt(request.getFromId(), request.getPaths());
if (response) {
response = false;
String[] paths = request.getPaths();
int[] types = request.getTypes();
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
resourceLoop: for (int i = 0; i < paths.length; i++) {
switch (types[i]) {
case IResource.PROJECT :
if (workspaceRoot.getProject(new Path(paths[i]).lastSegment()).exists()) {
response = true;
break resourceLoop;
}
break;
case IResource.FOLDER :
if (workspaceRoot.getFolder(new Path(paths[i])).exists()) {
response = true;
break resourceLoop;
}
break;
case IResource.FILE :
if (workspaceRoot.getFile(new Path(paths[i])).exists()) {
response = true;
break resourceLoop;
}
break;
}
}
}
sendMessage(request.getFromId(), new ShareResponse(response));
} else if (message instanceof IResponse) {
returnValue = ((IResponse) message).getResponse();
}
}
protected boolean prompt(ID fromId, String[] paths) {
return false;
}
private void sendFetchVariantsResponse(ID fromId, IContainer container) {
// the container will be null if an invalid resource type was provided
if (container == null) {
sendMessage(fromId, new FetchResponse());
return;
}
try {
IResource[] members = container.members();
List variants = new ArrayList();
for (int i = 0; i < members.length; i++) {
if (!members[i].isDerived()) {
variants.add(new RemoteResourceVariant(members[i]));
}
}
IResourceVariant[] variantsArray = (IResourceVariant[]) variants.toArray(new IResourceVariant[variants.size()]);
sendMessage(fromId, new FetchResponse(variantsArray));
} catch (CoreException e) {
TeamSynchronization.log("Could not retrieve container members: " //$NON-NLS-1$
+ container.getFullPath(), e);
}
}
private void sendFetchVariantResponse(ID fromId, IResource resource) {
// resource will be null if an invalid resource type was provided
if (resource != null && resource.exists()) {
sendMessage(fromId, new FetchResponse(new RemoteResourceVariant(resource)));
} else {
sendMessage(fromId, new FetchResponse((IResourceVariant) null));
}
}
public synchronized void dispose() {
participants.clear();
super.dispose();
}
private static Object deserialize(byte[] data) {
try {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
ObjectInputStream inputStream = new ObjectInputStream(bais);
return inputStream.readObject();
} catch (IOException e) {
TeamSynchronization.log("Could not read deserialize data", e); //$NON-NLS-1$
return null;
} catch (ClassNotFoundException e) {
TeamSynchronization.log("Could not find class for deserialization", //$NON-NLS-1$
e);
return null;
}
}
private static byte[] serialize(Serializable serializable) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream outputStream = new ObjectOutputStream(baos);
outputStream.writeObject(serializable);
return baos.toByteArray();
} catch (IOException e) {
TeamSynchronization.log("Could not read serialize object", e); //$NON-NLS-1$
return null;
}
}
}