1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.util;
11
12 import java.io.IOException;
13 import java.text.MessageFormat;
14 import java.util.concurrent.TimeUnit;
15
16 import org.eclipse.jgit.annotations.Nullable;
17 import org.eclipse.jgit.errors.CommandFailedException;
18 import org.eclipse.jgit.internal.JGitText;
19 import org.eclipse.jgit.transport.CredentialsProvider;
20 import org.eclipse.jgit.transport.RemoteSession;
21 import org.eclipse.jgit.transport.SshSessionFactory;
22 import org.eclipse.jgit.transport.URIish;
23 import org.eclipse.jgit.util.io.MessageWriter;
24 import org.eclipse.jgit.util.io.StreamCopyThread;
25
26
27
28
29
30
31 public class SshSupport {
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public static String runSshCommand(URIish sshUri,
56 @Nullable CredentialsProvider provider, FS fs, String command,
57 int timeout) throws IOException, CommandFailedException {
58 RemoteSession session = null;
59 Process process = null;
60 StreamCopyThread errorThread = null;
61 StreamCopyThread outThread = null;
62 CommandFailedException failure = null;
63 @SuppressWarnings("resource")
64 MessageWriter stderr = new MessageWriter();
65 @SuppressWarnings("resource")
66 MessageWriter stdout = new MessageWriter();
67 String out;
68 try {
69 long start = System.nanoTime();
70 session = SshSessionFactory.getInstance().getSession(sshUri,
71 provider, fs, 1000 * timeout);
72 int commandTimeout = timeout;
73 if (timeout > 0) {
74 commandTimeout = checkTimeout(command, timeout, start);
75 }
76 process = session.exec(command, commandTimeout);
77 if (timeout > 0) {
78 commandTimeout = checkTimeout(command, timeout, start);
79 }
80 errorThread = new StreamCopyThread(process.getErrorStream(),
81 stderr.getRawStream());
82 errorThread.start();
83 outThread = new StreamCopyThread(process.getInputStream(),
84 stdout.getRawStream());
85 outThread.start();
86 try {
87 boolean finished = false;
88 if (timeout <= 0) {
89 process.waitFor();
90 finished = true;
91 } else {
92 finished = process.waitFor(commandTimeout,
93 TimeUnit.SECONDS);
94 }
95 if (finished) {
96 out = stdout.toString();
97 } else {
98 out = null;
99 }
100 } catch (InterruptedException e) {
101 out = null;
102 }
103 } finally {
104 if (errorThread != null) {
105 try {
106 errorThread.halt();
107 } catch (InterruptedException e) {
108
109 } finally {
110 errorThread = null;
111 }
112 }
113 if (outThread != null) {
114 try {
115 outThread.halt();
116 } catch (InterruptedException e) {
117
118 } finally {
119 outThread = null;
120 }
121 }
122 if (process != null) {
123 try {
124 if (process.exitValue() != 0) {
125 failure = new CommandFailedException(
126 process.exitValue(),
127 MessageFormat.format(
128 JGitText.get().sshCommandFailed,
129 command, stderr.toString()));
130 }
131
132 out = stdout.toString();
133 } catch (IllegalThreadStateException e) {
134 failure = new CommandFailedException(0,
135 MessageFormat.format(
136 JGitText.get().sshCommandTimeout, command,
137 Integer.valueOf(timeout)));
138 }
139 process.destroy();
140 }
141 stderr.close();
142 stdout.close();
143 if (session != null) {
144 SshSessionFactory.getInstance().releaseSession(session);
145 }
146 }
147 if (failure != null) {
148 throw failure;
149 }
150 return out;
151 }
152
153 private static int checkTimeout(String command, int timeout, long since)
154 throws CommandFailedException {
155 long elapsed = System.nanoTime() - since;
156 int newTimeout = timeout
157 - (int) TimeUnit.NANOSECONDS.toSeconds(elapsed);
158 if (newTimeout <= 0) {
159
160 throw new CommandFailedException(0,
161 MessageFormat.format(JGitText.get().sshCommandTimeout,
162 command, Integer.valueOf(timeout)));
163 }
164 return newTimeout;
165 }
166 }