Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.tcf.rse/src/org/eclipse/tcf/internal/rse/TCFConnectorService.java')
-rw-r--r--plugins/org.eclipse.tcf.rse/src/org/eclipse/tcf/internal/rse/TCFConnectorService.java390
1 files changed, 390 insertions, 0 deletions
diff --git a/plugins/org.eclipse.tcf.rse/src/org/eclipse/tcf/internal/rse/TCFConnectorService.java b/plugins/org.eclipse.tcf.rse/src/org/eclipse/tcf/internal/rse/TCFConnectorService.java
new file mode 100644
index 000000000..905ca1563
--- /dev/null
+++ b/plugins/org.eclipse.tcf.rse/src/org/eclipse/tcf/internal/rse/TCFConnectorService.java
@@ -0,0 +1,390 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 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
+ * Martin Oberhuber (Wind River) - [269682] Get port from RSE Property
+ * Uwe Stieber (Wind River) - [271227] Fix compiler warnings in org.eclipse.tm.tcf.rse
+ * Anna Dushistova (MontaVista) - [285373] TCFConnectorService should send CommunicationsEvent.BEFORE_CONNECT and CommunicationsEvent.BEFORE_DISCONNECT
+ * Liping Ke (Intel Corp.)- [326490] Add authentication to the TCF Connector Service and attach stream subs/unsubs method
+ * Jeff Johnston (RedHat) - [350752] TCFConnectorService doesn't recognize connections with SSL transport
+ *******************************************************************************/
+package org.eclipse.tm.internal.tcf.rse;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.rse.core.model.IHost;
+import org.eclipse.rse.core.model.IPropertySet;
+import org.eclipse.rse.core.model.PropertyType;
+import org.eclipse.rse.core.model.SystemSignonInformation;
+import org.eclipse.rse.core.subsystems.CommunicationsEvent;
+import org.eclipse.rse.services.files.RemoteFileException;
+import org.eclipse.rse.ui.subsystems.StandardConnectorService;
+import org.eclipse.tm.tcf.core.AbstractPeer;
+import org.eclipse.tm.tcf.protocol.IChannel;
+import org.eclipse.tm.tcf.protocol.IPeer;
+import org.eclipse.tm.tcf.protocol.IService;
+import org.eclipse.tm.tcf.protocol.IToken;
+import org.eclipse.tm.tcf.protocol.Protocol;
+import org.eclipse.tm.tcf.services.IFileSystem;
+import org.eclipse.tm.tcf.services.ILocator;
+import org.eclipse.tm.tcf.services.IStreams;
+import org.eclipse.tm.tcf.services.ISysMonitor;
+import org.eclipse.tm.tcf.services.ITerminals;
+import org.eclipse.tm.tcf.util.TCFTask;
+
+
+public class TCFConnectorService extends StandardConnectorService implements ITCFSessionProvider{
+
+ public static final String PROPERTY_SET_NAME = "TCF Connection Settings"; //$NON-NLS-1$
+ public static final String PROPERTY_LOGIN_REQUIRED = "Login.Required"; //$NON-NLS-1$
+ public static final String PROPERTY_PWD_REQUIRED="Pwd.Required"; //$NON-NLS-1$
+ public static final String PROPERTY_LOGIN_PROMPT = "Login.Prompt"; //$NON-NLS-1$
+ public static final String PROPERTY_PASSWORD_PROMPT = "Password.Prompt"; //$NON-NLS-1$
+ public static final String PROPERTY_COMMAND_PROMPT = "Command.Prompt"; //$NON-NLS-1$
+
+ private IChannel channel;
+ private Throwable channel_error;
+ private final List<Runnable> wait_list = new ArrayList<Runnable>();
+
+ private boolean poll_timer_started;
+
+ private boolean bSubscribed = false;
+
+ /* subscribe the stream service on this TCP connection */
+ private IStreams.StreamsListener streamListener = new IStreams.StreamsListener() {
+ public void created(String stream_type, String stream_id,
+ String context_id) {
+ }
+ /**
+ * Called when a stream is disposed.
+ *
+ * @param stream_type
+ * - source type of the stream.
+ * @param stream_id
+ * - ID of the stream.
+ */
+ public void disposed(String stream_type, String stream_id) {
+ }
+ };
+
+
+ public TCFConnectorService(IHost host, int port) {
+ super(Messages.TCFConnectorService_Name,
+ Messages.TCFConnectorService_Description, host,
+ port);
+ getTCFPropertySet();
+ }
+
+ public IPropertySet getTCFPropertySet() {
+ IPropertySet tcfSet = getPropertySet(PROPERTY_SET_NAME);
+ if (tcfSet == null) {
+ tcfSet = createPropertySet(PROPERTY_SET_NAME, Messages.PropertySet_Description);
+ //add default values if not set
+ tcfSet.addProperty(PROPERTY_LOGIN_REQUIRED, "false", PropertyType.getEnumPropertyType(new String[] {"true", "false"})); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ tcfSet.addProperty(PROPERTY_PWD_REQUIRED, "false", PropertyType.getEnumPropertyType(new String[] {"true", "false"})); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ tcfSet.addProperty(PROPERTY_LOGIN_PROMPT, "ogin: ", PropertyType.getStringPropertyType()); //$NON-NLS-1$
+ tcfSet.addProperty(PROPERTY_PASSWORD_PROMPT, "assword: ", PropertyType.getStringPropertyType()); //$NON-NLS-1$
+ tcfSet.addProperty(PROPERTY_COMMAND_PROMPT, "#", PropertyType.getStringPropertyType()); //$NON-NLS-1$
+ }
+ return tcfSet;
+ }
+
+ /**
+ * @return true if the associated connector service requires a password.
+ */
+
+ public final boolean requiresPassword() {
+ return false;
+ }
+
+ @Override
+ protected void internalConnect(final IProgressMonitor monitor) throws Exception {
+ assert !Protocol.isDispatchThread();
+ final Exception[] res = new Exception[1];
+ // Fire comm event to signal state about to change
+ fireCommunicationsEvent(CommunicationsEvent.BEFORE_CONNECT);
+ monitor.beginTask("Connecting " + getHostName(), 1); //$NON-NLS-1$
+ synchronized (res) {
+ Protocol.invokeLater(new Runnable() {
+ public void run() {
+ if (!connectTCFChannel(res, monitor))
+ add_to_wait_list(this);
+ }
+ });
+ res.wait();
+ }
+ if (res[0] != null) throw res[0];
+ monitor.done();
+ }
+
+ @Override
+ protected void internalDisconnect(final IProgressMonitor monitor)
+ throws Exception {
+ assert !Protocol.isDispatchThread();
+ final Exception[] res = new Exception[1];
+ // Fire comm event to signal state about to change
+ fireCommunicationsEvent(CommunicationsEvent.BEFORE_DISCONNECT);
+ monitor.beginTask("Disconnecting " + getHostName(), 1); //$NON-NLS-1$
+ try {
+ /* First UnSubscribe TCP channel */
+ unsubscribe();
+ /* Disconnecting TCP channel */
+ synchronized (res) {
+ Protocol.invokeLater(new Runnable() {
+ public void run() {
+ if (!disconnectTCFChannel(res, monitor))
+ add_to_wait_list(this);
+ }
+ });
+ res.wait();
+ }
+ if (res[0] != null) throw res[0];
+
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ throw new RemoteFileException("Error creating Terminal", e); //$NON-NLS-1$
+ }
+ finally {
+ monitor.done();
+ }
+ }
+
+ public boolean isConnected() {
+ final boolean res[] = new boolean[1];
+ Protocol.invokeAndWait(new Runnable() {
+ public void run() {
+ res[0] = channel != null && channel.getState() == IChannel.STATE_OPEN;
+ }
+ });
+ return res[0];
+ }
+
+ private void add_to_wait_list(Runnable cb) {
+ wait_list.add(cb);
+ if (poll_timer_started) return;
+ Protocol.invokeLater(1000, new Runnable() {
+ public void run() {
+ poll_timer_started = false;
+ run_wait_list();
+ }
+ });
+ poll_timer_started = true;
+ }
+
+ private void run_wait_list() {
+ if (wait_list.isEmpty()) return;
+ Runnable[] r = wait_list.toArray(new Runnable[wait_list.size()]);
+ wait_list.clear();
+ for (int i = 0; i < r.length; i++) r[i].run();
+ }
+
+ private boolean connectTCFChannel(Exception[] res, IProgressMonitor monitor) {
+ if (channel != null) {
+ switch (channel.getState()) {
+ case IChannel.STATE_OPEN:
+ case IChannel.STATE_CLOSED:
+ synchronized (res) {
+ if (channel_error instanceof Exception) res[0] = (Exception)channel_error;
+ else if (channel_error != null) res[0] = new Exception(channel_error);
+ else res[0] = null;
+ res.notify();
+ return true;
+ }
+ }
+ }
+ if (monitor.isCanceled()) {
+ synchronized (res) {
+ res[0] = new Exception("Canceled"); //$NON-NLS-1$
+ if (channel != null) channel.terminate(res[0]);
+ res.notify();
+ return true;
+ }
+ }
+ if (channel == null) {
+ String host = getHostName().toLowerCase();
+ int port = getConnectPort();
+ if (port <= 0) {
+ //Default fallback
+ port = TCFConnectorServiceManager.TCF_PORT;
+ }
+ IPeer peer = null;
+ String port_str = Integer.toString(port);
+ ILocator locator = Protocol.getLocator();
+ for (IPeer p : locator.getPeers().values()) {
+ Map<String, String> attrs = p.getAttributes();
+ if (("TCP".equals(attrs.get(IPeer.ATTR_TRANSPORT_NAME)) || //$NON-NLS-1$
+ "SSL".equals(attrs.get(IPeer.ATTR_TRANSPORT_NAME)))&& //$NON-NLS-1$
+ host.equalsIgnoreCase(attrs.get(IPeer.ATTR_IP_HOST)) &&
+ port_str.equals(attrs.get(IPeer.ATTR_IP_PORT))) {
+ peer = p;
+ break;
+ }
+ }
+ if (peer == null) {
+ Map<String, String> attrs = new HashMap<String, String>();
+ attrs.put(IPeer.ATTR_ID, "RSE:" + host + ":" + port_str); //$NON-NLS-1$ //$NON-NLS-2$
+ attrs.put(IPeer.ATTR_NAME, getName());
+ attrs.put(IPeer.ATTR_TRANSPORT_NAME, "TCP"); //$NON-NLS-1$
+ attrs.put(IPeer.ATTR_IP_HOST, host);
+ attrs.put(IPeer.ATTR_IP_PORT, port_str);
+ peer = new AbstractPeer(attrs);
+ }
+ channel = peer.openChannel();
+ channel.addChannelListener(new IChannel.IChannelListener() {
+
+ public void onChannelOpened() {
+ assert channel != null;
+ run_wait_list();
+ }
+
+ public void congestionLevel(int level) {
+ }
+
+ public void onChannelClosed(Throwable error) {
+ assert channel != null;
+ channel.removeChannelListener(this);
+ channel_error = error;
+ if (wait_list.isEmpty()) {
+ fireCommunicationsEvent(CommunicationsEvent.CONNECTION_ERROR);
+ }
+ else {
+ run_wait_list();
+ }
+ bSubscribed = false;
+ channel = null;
+ channel_error = null;
+ }
+
+ });
+ assert channel.getState() == IChannel.STATE_OPENING;
+ }
+ return false;
+ }
+
+ private boolean disconnectTCFChannel(Exception[] res, IProgressMonitor monitor) {
+ if (channel == null || channel.getState() == IChannel.STATE_CLOSED) {
+ synchronized (res) {
+ res[0] = null;
+ res.notify();
+ return true;
+ }
+ }
+ if (monitor.isCanceled()) {
+ synchronized (res) {
+ res[0] = new Exception("Canceled"); //$NON-NLS-1$
+ res.notify();
+ return true;
+ }
+ }
+ if (channel.getState() == IChannel.STATE_OPEN) channel.close();
+ return false;
+ }
+
+ public <V extends IService> V getService(Class<V> service_interface) {
+ if (channel == null || channel.getState() != IChannel.STATE_OPEN) throw new Error("Not connected"); //$NON-NLS-1$
+ V m = channel.getRemoteService(service_interface);
+ if (m == null) throw new Error("Remote peer does not support " + service_interface.getName() + " service"); //$NON-NLS-1$ //$NON-NLS-2$
+ return m;
+ }
+
+ public ISysMonitor getSysMonitorService() {
+ return getService(ISysMonitor.class);
+ }
+
+ public IFileSystem getFileSystemService() {
+ return getService(IFileSystem.class);
+ }
+
+ public IChannel getChannel() {
+ return channel;
+ }
+
+ public String getSessionHostName() {
+ String hostName = "";
+ IHost host = getHost();
+ if (host != null) hostName = host.getHostName();
+ return hostName;
+ }
+
+ public String getSessionUserId() {
+ return getUserId();
+ }
+
+ public String getSessionPassword() {
+ String password = "";
+ SystemSignonInformation ssi = getSignonInformation();
+ if (ssi != null) {
+ password = ssi.getPassword();
+ }
+ return password;
+ }
+
+ public boolean isSubscribed() {
+ return bSubscribed;
+ }
+
+ public void unsubscribe() throws IOException {
+ if (bSubscribed) {
+ new TCFTask<Object>() {
+ public void run() {
+ IStreams streams = getService(IStreams.class);
+ streams.unsubscribe(ITerminals.NAME, streamListener,
+ new IStreams.DoneUnsubscribe() {
+ public void doneUnsubscribe(IToken token,
+ Exception error) {
+ done(this);
+ }
+ });
+ }
+ }.getIO();
+ bSubscribed = false;
+ }
+
+ }
+
+ public void subscribe() throws RemoteFileException {
+ try {
+ new TCFTask<Object>() {
+ public void run() {
+ if (bSubscribed) {
+ done(this);
+ }
+ else {
+ bSubscribed = true;
+ IStreams streams = getService(IStreams.class);
+ streams.subscribe(ITerminals.NAME, streamListener,
+ new IStreams.DoneSubscribe() {
+ public void doneSubscribe(IToken token,
+ Exception error) {
+ if (error != null) {
+ bSubscribed = false;
+ error(error);
+ }
+ else
+ done(this);
+ }
+
+ });
+ }}
+ }.getIO();
+
+ }
+ catch (Exception e) {
+ e.printStackTrace();//$NON-NLS-1$
+ throw new RemoteFileException(
+ "Error When Subscribe Terminal streams!", e); //$NON-NLS-1$
+ }
+
+ }
+}

Back to the top