/*******************************************************************************
* Copyright (c) 2011, 2015 Wind River Systems, Inc. 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.tcf.filesystem.core.services;
import java.net.ConnectException;
import java.util.concurrent.TimeoutException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.osgi.util.NLS;
import org.eclipse.tcf.protocol.IChannel;
import org.eclipse.tcf.protocol.IPeer;
import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.services.IFileSystem;
import org.eclipse.tcf.te.tcf.core.Tcf;
import org.eclipse.tcf.te.tcf.core.concurrent.Rendezvous;
import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel;
import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IOperation;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.exceptions.TCFChannelException;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.BlockingFileSystemProxy;
import org.eclipse.tcf.te.tcf.filesystem.core.nls.Messages;
/**
* Operation is the base class of file system operation classes.
* @see IOperation
*/
public class Operation {
// The default timeout waiting for blocked invocations.
public static final long DEFAULT_TIMEOUT = 60000L;
private Operation() {
}
/**
* Open a channel connected to the target represented by the peer.
*
* @return The channel or null if the operation fails.
*/
public static IChannel openChannel(final IPeer peer) throws TCFChannelException {
final TCFChannelException[] errors = new TCFChannelException[1];
final IChannel[] channels = new IChannel[1];
final Rendezvous rendezvous = new Rendezvous();
Tcf.getChannelManager().openChannel(peer, null, new DoneOpenChannel() {
@Override
public void doneOpenChannel(Throwable error, IChannel channel) {
if (error != null) {
if (error instanceof ConnectException) {
String message = NLS.bind(Messages.Operation_NotResponding, peer.getID());
errors[0] = new TCFChannelException(IStatus.ERROR, message);
}
else if(!(error instanceof OperationCanceledException)) {
String message = NLS.bind(Messages.Operation_OpeningChannelFailureMessage, peer.getID(), error.getMessage());
errors[0] = new TCFChannelException(IStatus.OK, message, error);
}
}
else {
channels[0] = channel;
}
rendezvous.arrive();
}
});
try {
rendezvous.waiting(DEFAULT_TIMEOUT);
}
catch(TimeoutException e) {
throw new TCFChannelException(IStatus.ERROR, Messages.Operation_TimeoutOpeningChannel);
}
if (errors[0] != null) {
throw errors[0];
}
return channels[0];
}
/**
* Get a blocking file system service from the channel. The
* returned file system service is a service that delegates the
* method call to the file system proxy. If the method returns
* asynchronously with a callback, it will block the call until
* the callback returns.
* <p>
* <em>Note: All the method of the returned file system
* service must be called outside of the dispatching thread.</em>
*
* @param channel The channel to get the file system service.
* @return The blocking file system service.
*/
public static IFileSystem getBlockingFileSystem(final IChannel channel) {
if(Protocol.isDispatchThread()) {
IFileSystem service = channel.getRemoteService(IFileSystem.class);
return new BlockingFileSystemProxy(service);
}
final IFileSystem[] service = new IFileSystem[1];
Protocol.invokeAndWait(new Runnable(){
@Override
public void run() {
service[0] = getBlockingFileSystem(channel);
}});
return service[0];
}
}