| /****************************************************************************** |
| * 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; |
| } |
| } |
| |
| } |