From 27a497f83e683d384d379ee75570f8c25a7aa624 Mon Sep 17 00:00:00 2001
From: "Shawn O. Pearce" <spearce@spearce.org>
Date: Sat, 31 Oct 2009 19:42:01 -0700
Subject: [PATCH] Move AWT based SSH authenticator to ui bundle

This way SWT based applications don't wind up loading this AWT
based code when using SSH.

Change-Id: I9080f3dd029c2a087e6b687480018997cc5c5d23
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../src/org/eclipse/jgit/pgm/Main.java        |   2 +
 org.eclipse.jgit.ui/META-INF/MANIFEST.MF      |   7 +-
 .../jgit/awtui/AwtSshSessionFactory.java      | 185 ++++++++++++++++++
 .../transport/DefaultSshSessionFactory.java   | 120 +-----------
 4 files changed, 197 insertions(+), 117 deletions(-)
 create mode 100644 org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/AwtSshSessionFactory.java

diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
index 7c74ee548..3579b65e3 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
@@ -51,6 +51,7 @@
 import java.util.List;
 
 import org.eclipse.jgit.awtui.AwtAuthenticator;
+import org.eclipse.jgit.awtui.AwtSshSessionFactory;
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.pgm.opt.CmdLineParser;
@@ -88,6 +89,7 @@ public static void main(final String[] argv) {
 		final Main me = new Main();
 		try {
 			AwtAuthenticator.install();
+			AwtSshSessionFactory.install();
 			configureHttpProxy();
 			me.execute(argv);
 		} catch (Die err) {
diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
index a2c17a6a2..a6710cd52 100644
--- a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
@@ -7,6 +7,9 @@ Bundle-Version: 0.6.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Export-Package: org.eclipse.jgit.awtui;version="0.6.0"
-Import-Package: org.eclipse.jgit.lib,
+Import-Package: com.jcraft.jsch,
+ org.eclipse.jgit.lib;version="0.6.0",
+ org.eclipse.jgit.transport,
  org.eclipse.jgit.revplot,
- org.eclipse.jgit.revwalk;version="0.6.0"
+ org.eclipse.jgit.revwalk,
+ org.eclipse.jgit.util
diff --git a/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/AwtSshSessionFactory.java b/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/AwtSshSessionFactory.java
new file mode 100644
index 000000000..f6710854b
--- /dev/null
+++ b/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/AwtSshSessionFactory.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.awtui;
+
+import java.awt.Container;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+
+import org.eclipse.jgit.transport.OpenSshConfig;
+import org.eclipse.jgit.transport.SshConfigSessionFactory;
+import org.eclipse.jgit.transport.SshSessionFactory;
+
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.UIKeyboardInteractive;
+import com.jcraft.jsch.UserInfo;
+
+/**
+ * Loads known hosts and private keys from <code>$HOME/.ssh</code>.
+ * <p>
+ * This is the default implementation used by JGit and provides most of the
+ * compatibility necessary to match OpenSSH, a popular implementation of SSH
+ * used by C Git.
+ * <p>
+ * If user interactivity is required by SSH (e.g. to obtain a password) AWT is
+ * used to display a password input field to the end-user.
+ */
+public class AwtSshSessionFactory extends SshConfigSessionFactory {
+	/** Install this session factory implementation into the JVM. */
+	public static void install() {
+		SshSessionFactory.setInstance(new AwtSshSessionFactory());
+	}
+
+	@Override
+	protected void configure(final OpenSshConfig.Host hc, final Session session) {
+		if (!hc.isBatchMode())
+			session.setUserInfo(new AWT_UserInfo());
+	}
+
+	private static class AWT_UserInfo implements UserInfo,
+			UIKeyboardInteractive {
+		private String passwd;
+
+		private String passphrase;
+
+		public void showMessage(final String msg) {
+			JOptionPane.showMessageDialog(null, msg);
+		}
+
+		public boolean promptYesNo(final String msg) {
+			return JOptionPane.showConfirmDialog(null, msg, "Warning",
+					JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
+		}
+
+		public boolean promptPassword(final String msg) {
+			passwd = null;
+			final JPasswordField passwordField = new JPasswordField(20);
+			final int result = JOptionPane.showConfirmDialog(null,
+					new Object[] { passwordField }, msg,
+					JOptionPane.OK_CANCEL_OPTION);
+			if (result == JOptionPane.OK_OPTION) {
+				passwd = new String(passwordField.getPassword());
+				return true;
+			}
+			return false;
+		}
+
+		public boolean promptPassphrase(final String msg) {
+			passphrase = null;
+			final JPasswordField passwordField = new JPasswordField(20);
+			final int result = JOptionPane.showConfirmDialog(null,
+					new Object[] { passwordField }, msg,
+					JOptionPane.OK_CANCEL_OPTION);
+			if (result == JOptionPane.OK_OPTION) {
+				passphrase = new String(passwordField.getPassword());
+				return true;
+			}
+			return false;
+		}
+
+		public String getPassword() {
+			return passwd;
+		}
+
+		public String getPassphrase() {
+			return passphrase;
+		}
+
+		public String[] promptKeyboardInteractive(final String destination,
+				final String name, final String instruction,
+				final String[] prompt, final boolean[] echo) {
+			final GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1,
+					1, 1, GridBagConstraints.NORTHWEST,
+					GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0);
+			final Container panel = new JPanel();
+			panel.setLayout(new GridBagLayout());
+
+			gbc.weightx = 1.0;
+			gbc.gridwidth = GridBagConstraints.REMAINDER;
+			gbc.gridx = 0;
+			panel.add(new JLabel(instruction), gbc);
+			gbc.gridy++;
+
+			gbc.gridwidth = GridBagConstraints.RELATIVE;
+
+			final JTextField[] texts = new JTextField[prompt.length];
+			for (int i = 0; i < prompt.length; i++) {
+				gbc.fill = GridBagConstraints.NONE;
+				gbc.gridx = 0;
+				gbc.weightx = 1;
+				panel.add(new JLabel(prompt[i]), gbc);
+
+				gbc.gridx = 1;
+				gbc.fill = GridBagConstraints.HORIZONTAL;
+				gbc.weighty = 1;
+				if (echo[i]) {
+					texts[i] = new JTextField(20);
+				} else {
+					texts[i] = new JPasswordField(20);
+				}
+				panel.add(texts[i], gbc);
+				gbc.gridy++;
+			}
+
+			if (JOptionPane.showConfirmDialog(null, panel, destination + ": "
+					+ name, JOptionPane.OK_CANCEL_OPTION,
+					JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION) {
+				String[] response = new String[prompt.length];
+				for (int i = 0; i < prompt.length; i++) {
+					response[i] = texts[i].getText();
+				}
+				return response;
+			}
+			return null; // cancel
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/DefaultSshSessionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/DefaultSshSessionFactory.java
index 6ff3d4b2f..53c1a2ce3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/DefaultSshSessionFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/DefaultSshSessionFactory.java
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
+ * Copyright (C) 2009, Google Inc.
  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
  * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
  * and other copyright owners as documented in the project's IP log.
@@ -44,20 +46,7 @@
 
 package org.eclipse.jgit.transport;
 
-import java.awt.Container;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JPasswordField;
-import javax.swing.JTextField;
-
 import com.jcraft.jsch.Session;
-import com.jcraft.jsch.UIKeyboardInteractive;
-import com.jcraft.jsch.UserInfo;
 
 /**
  * Loads known hosts and private keys from <code>$HOME/.ssh</code>.
@@ -66,110 +55,11 @@
  * compatibility necessary to match OpenSSH, a popular implementation of SSH
  * used by C Git.
  * <p>
- * If user interactivity is required by SSH (e.g. to obtain a password) AWT is
- * used to display a password input field to the end-user.
+ * If user interactivity is required by SSH (e.g. to obtain a password), the
+ * connection will immediately fail.
  */
 class DefaultSshSessionFactory extends SshConfigSessionFactory {
 	protected void configure(final OpenSshConfig.Host hc, final Session session) {
-		if (!hc.isBatchMode())
-			session.setUserInfo(new AWT_UserInfo());
-	}
-
-	private static class AWT_UserInfo implements UserInfo,
-			UIKeyboardInteractive {
-		private String passwd;
-
-		private String passphrase;
-
-		public void showMessage(final String msg) {
-			JOptionPane.showMessageDialog(null, msg);
-		}
-
-		public boolean promptYesNo(final String msg) {
-			return JOptionPane.showConfirmDialog(null, msg, "Warning",
-					JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
-		}
-
-		public boolean promptPassword(final String msg) {
-			passwd = null;
-			final JPasswordField passwordField = new JPasswordField(20);
-			final int result = JOptionPane.showConfirmDialog(null,
-					new Object[] { passwordField }, msg,
-					JOptionPane.OK_CANCEL_OPTION);
-			if (result == JOptionPane.OK_OPTION) {
-				passwd = new String(passwordField.getPassword());
-				return true;
-			}
-			return false;
-		}
-
-		public boolean promptPassphrase(final String msg) {
-			passphrase = null;
-			final JPasswordField passwordField = new JPasswordField(20);
-			final int result = JOptionPane.showConfirmDialog(null,
-					new Object[] { passwordField }, msg,
-					JOptionPane.OK_CANCEL_OPTION);
-			if (result == JOptionPane.OK_OPTION) {
-				passphrase = new String(passwordField.getPassword());
-				return true;
-			}
-			return false;
-		}
-
-		public String getPassword() {
-			return passwd;
-		}
-
-		public String getPassphrase() {
-			return passphrase;
-		}
-
-		public String[] promptKeyboardInteractive(final String destination,
-				final String name, final String instruction,
-				final String[] prompt, final boolean[] echo) {
-			final GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1,
-					1, 1, GridBagConstraints.NORTHWEST,
-					GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0);
-			final Container panel = new JPanel();
-			panel.setLayout(new GridBagLayout());
-
-			gbc.weightx = 1.0;
-			gbc.gridwidth = GridBagConstraints.REMAINDER;
-			gbc.gridx = 0;
-			panel.add(new JLabel(instruction), gbc);
-			gbc.gridy++;
-
-			gbc.gridwidth = GridBagConstraints.RELATIVE;
-
-			final JTextField[] texts = new JTextField[prompt.length];
-			for (int i = 0; i < prompt.length; i++) {
-				gbc.fill = GridBagConstraints.NONE;
-				gbc.gridx = 0;
-				gbc.weightx = 1;
-				panel.add(new JLabel(prompt[i]), gbc);
-
-				gbc.gridx = 1;
-				gbc.fill = GridBagConstraints.HORIZONTAL;
-				gbc.weighty = 1;
-				if (echo[i]) {
-					texts[i] = new JTextField(20);
-				} else {
-					texts[i] = new JPasswordField(20);
-				}
-				panel.add(texts[i], gbc);
-				gbc.gridy++;
-			}
-
-			if (JOptionPane.showConfirmDialog(null, panel, destination + ": "
-					+ name, JOptionPane.OK_CANCEL_OPTION,
-					JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION) {
-				String[] response = new String[prompt.length];
-				for (int i = 0; i < prompt.length; i++) {
-					response[i] = texts[i].getText();
-				}
-				return response;
-			}
-			return null; // cancel
-		}
+		// No additional configuration required.
 	}
 }
-- 
GitLab