KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > Ssh


1 /*
2  * Ssh.java
3  *
4  * Copyright (C) 2002-2004 Peter Graves
5  * $Id: Ssh.java,v 1.5 2004/09/13 00:47:16 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 import java.io.IOException JavaDoc;
25 import java.io.InputStreamReader JavaDoc;
26 import java.io.OutputStreamWriter JavaDoc;
27 import java.util.ArrayList JavaDoc;
28
29 public final class Ssh
30 {
31     private InputStreamReader JavaDoc reader;
32     private OutputStreamWriter JavaDoc writer;
33     private String JavaDoc[] cmdarray;
34     private String JavaDoc password;
35     private String JavaDoc errorText;
36     private boolean succeeded;
37
38     public Ssh()
39     {
40     }
41
42     public final String JavaDoc getErrorText()
43     {
44         return errorText;
45     }
46
47     public boolean copy(File source, File destination)
48     {
49         SshFile remote = null;
50         if (source instanceof SshFile)
51             remote = (SshFile) source;
52         else if (destination instanceof SshFile)
53             remote = (SshFile) destination;
54         if (remote == null) {
55             Debug.bug("Ssh.copy no remote file");
56             return false;
57         }
58         String JavaDoc userName = remote.getUserName();
59         password = remote.getPassword();
60         ArrayList JavaDoc list = new ArrayList JavaDoc();
61         list.add("jpty");
62         list.add("scp");
63         list.add("-q");
64         if (remote.getPort() != SshFile.DEFAULT_PORT) {
65             list.add("-P");
66             list.add(String.valueOf(remote.getPort()));
67         }
68         FastStringBuffer sb = new FastStringBuffer();
69         if (source instanceof SshFile) {
70             if (userName != null) {
71                 sb.append(userName);
72                 sb.append('@');
73             }
74             sb.append(source.getHostName());
75             sb.append(':');
76         }
77         sb.append(escape(source.canonicalPath()));
78         list.add(sb.toString());
79         sb.setLength(0);
80         if (destination instanceof SshFile) {
81             if (userName != null) {
82                 sb.append(userName);
83                 sb.append('@');
84             }
85             sb.append(destination.getHostName());
86             sb.append(':');
87         }
88         sb.append(escape(destination.canonicalPath()));
89         list.add(sb.toString());
90         String JavaDoc[] array = new String JavaDoc[list.size()];
91         cmdarray = (String JavaDoc[]) list.toArray(array);
92         run();
93         return succeeded;
94     }
95
96     private static final String JavaDoc safeChars =
97         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-./\\";
98
99     // Escapes unsafe characters.
100
private static final String JavaDoc escape(String JavaDoc s)
101     {
102         final int length = s.length();
103         FastStringBuffer sb = new FastStringBuffer(length * 2);
104         for (int i = 0; i < length; i++) {
105             char c = s.charAt(i);
106             if (safeChars.indexOf(c) < 0)
107                 sb.append('\\');
108             sb.append(c);
109         }
110         return sb.toString();
111     }
112
113     public void run()
114     {
115         Process JavaDoc process = null;
116         int result = -1; // Assume error.
117
try {
118             process = Runtime.getRuntime().exec(cmdarray);
119         }
120         catch (Throwable JavaDoc t) {
121             Log.error(t);
122             return;
123         }
124         writer = new OutputStreamWriter JavaDoc(process.getOutputStream());
125         reader = new InputStreamReader JavaDoc(process.getInputStream());
126         SshReaderThread thread = new SshReaderThread();
127         thread.start();
128         try {
129             thread.join();
130             result = process.waitFor();
131         }
132         catch (InterruptedException JavaDoc e) {
133             Log.error(e);
134         }
135         if (result == 0) {
136             errorText = thread.getResponse();
137             if (errorText == null) {
138                 succeeded = true;
139             } else {
140                 errorText = errorText.trim();
141                 if (errorText.length() == 0) {
142                     succeeded = true;
143                 } else {
144                     // No error if response is a single line starting with
145
// "warning:".
146
if (errorText.toLowerCase().startsWith("warning:"))
147                         if (errorText.indexOf('\n') < 0)
148                             succeeded = true;
149                 }
150             }
151         }
152     }
153
154     private void sendPassword()
155     {
156         if (password != null) {
157             try {
158                 writer.write(password);
159                 writer.write("\n");
160                 writer.flush();
161             }
162             catch (IOException JavaDoc e) {
163                 Log.error(e);
164             }
165         } else
166             Debug.bug();
167     }
168
169     private class SshReaderThread extends Thread JavaDoc
170     {
171         private char[] buf = new char[4096];
172         private boolean done = false;
173         private String JavaDoc response;
174
175         // If this constructor is private, we run into jikes 1.15 bug #2256.
176
/*private*/ SshReaderThread()
177         {
178         }
179
180         public final String JavaDoc getResponse()
181         {
182             return response;
183         }
184
185         public void run()
186         {
187             FastStringBuffer sb = new FastStringBuffer();
188             while (true) {
189                 final String JavaDoc s = read();
190                 if (s == null) {
191                     response = sb.toString();
192                     return;
193                 }
194                 if (done) {
195                     if (s.length() > 0)
196                         sb.append(s);
197                     response = sb.toString();
198                     return;
199                 }
200                 if (isPasswordPrompt(s)) {
201                     sendPassword();
202                     sb.setLength(0);
203                 } else
204                     sb.append(s);
205             }
206         }
207
208         private String JavaDoc read()
209         {
210             FastStringBuffer sb = new FastStringBuffer();
211             try {
212                 do {
213                     int numChars = reader.read(buf, 0, buf.length); // Blocks.
214
if (numChars < 0) {
215                         done = true;
216                         break;
217                     }
218                     if (numChars > 0)
219                         sb.append(buf, 0, numChars);
220                 } while (reader.ready());
221             }
222             catch (Exception JavaDoc e) {
223                 Log.error(e);
224                 return null;
225             }
226             return sb.toString();
227         }
228     }
229
230     private boolean isPasswordPrompt(String JavaDoc s)
231     {
232         String JavaDoc trim = s.trim().toLowerCase();
233         if (trim.endsWith("password:"))
234             return true;
235         if (trim.endsWith("response:"))
236             return true;
237         if (trim.startsWith("enter passphrase ") && trim.endsWith(":"))
238             return true;
239         return false;
240     }
241 }
242
Popular Tags