1 package org.apache.maven.wagon.providers.ssh;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.wagon.CommandExecutionException;
23 import org.apache.maven.wagon.CommandExecutor;
24 import org.apache.maven.wagon.PathUtils;
25 import org.apache.maven.wagon.PermissionModeUtils;
26 import org.apache.maven.wagon.ResourceDoesNotExistException;
27 import org.apache.maven.wagon.Streams;
28 import org.apache.maven.wagon.TransferFailedException;
29 import org.apache.maven.wagon.Wagon;
30 import org.apache.maven.wagon.authentication.AuthenticationInfo;
31 import org.apache.maven.wagon.authorization.AuthorizationException;
32 import org.apache.maven.wagon.repository.Repository;
33 import org.apache.maven.wagon.repository.RepositoryPermissions;
34 import org.apache.maven.wagon.resource.Resource;
35 import org.codehaus.plexus.util.FileUtils;
36 import org.codehaus.plexus.util.IOUtil;
37 import org.codehaus.plexus.util.StringUtils;
38
39 import java.io.File;
40 import java.io.FileInputStream;
41 import java.io.FileNotFoundException;
42 import java.io.FileOutputStream;
43 import java.io.IOException;
44 import java.util.List;
45 import java.util.zip.ZipEntry;
46 import java.util.zip.ZipOutputStream;
47
48
49
50
51
52 public class ScpHelper
53 {
54 public static final char PATH_SEPARATOR = '/';
55
56 public static final int DEFAULT_SSH_PORT = 22;
57
58 private final CommandExecutor executor;
59
60 public ScpHelper( CommandExecutor executor )
61 {
62 this.executor = executor;
63 }
64
65 public static String getResourceDirectory( String resourceName )
66 {
67 String dir = PathUtils.dirname( resourceName );
68 dir = StringUtils.replace( dir, "\\", "/" );
69 return dir;
70 }
71
72 public static String getResourceFilename( String r )
73 {
74 String filename;
75 if ( r.lastIndexOf( PATH_SEPARATOR ) > 0 )
76 {
77 filename = r.substring( r.lastIndexOf( PATH_SEPARATOR ) + 1 );
78 }
79 else
80 {
81 filename = r;
82 }
83 return filename;
84 }
85
86 public static Resource getResource( String resourceName )
87 {
88 String r = StringUtils.replace( resourceName, "\\", "/" );
89 return new Resource( r );
90 }
91
92 public static File getPrivateKey( AuthenticationInfo authenticationInfo )
93 throws FileNotFoundException
94 {
95
96 File privateKey = null;
97 if ( authenticationInfo.getPassword() == null )
98 {
99
100 if ( authenticationInfo.getPrivateKey() != null )
101 {
102 privateKey = new File( authenticationInfo.getPrivateKey() );
103 if ( !privateKey.exists() )
104 {
105 throw new FileNotFoundException( "Private key '" + privateKey + "' not found" );
106 }
107 }
108 else
109 {
110 privateKey = findPrivateKey();
111 }
112
113 if ( privateKey != null && privateKey.exists() )
114 {
115 if ( authenticationInfo.getPassphrase() == null )
116 {
117 authenticationInfo.setPassphrase( "" );
118 }
119 }
120 }
121 return privateKey;
122 }
123
124 private static File findPrivateKey()
125 {
126 String privateKeyDirectory = System.getProperty( "wagon.privateKeyDirectory" );
127
128 if ( privateKeyDirectory == null )
129 {
130 privateKeyDirectory = System.getProperty( "user.home" );
131 }
132
133 File privateKey = new File( privateKeyDirectory, ".ssh/id_dsa" );
134
135 if ( !privateKey.exists() )
136 {
137 privateKey = new File( privateKeyDirectory, ".ssh/id_rsa" );
138 if ( !privateKey.exists() )
139 {
140 privateKey = null;
141 }
142 }
143
144 return privateKey;
145 }
146
147 public static void createZip( List<String> files, File zipName, File basedir )
148 throws IOException
149 {
150 ZipOutputStream zos = new ZipOutputStream( new FileOutputStream( zipName ) );
151
152 try
153 {
154 for ( String file : files )
155 {
156 file = file.replace( '\\', '/' );
157
158 writeZipEntry( zos, new File( basedir, file ), file );
159 }
160 }
161 finally
162 {
163 IOUtil.close( zos );
164 }
165 }
166
167 private static void writeZipEntry( ZipOutputStream jar, File source, String entryName )
168 throws IOException
169 {
170 byte[] buffer = new byte[1024];
171
172 int bytesRead;
173
174 FileInputStream is = new FileInputStream( source );
175
176 try
177 {
178 ZipEntry entry = new ZipEntry( entryName );
179
180 jar.putNextEntry( entry );
181
182 while ( ( bytesRead = is.read( buffer ) ) != -1 )
183 {
184 jar.write( buffer, 0, bytesRead );
185 }
186 }
187 finally
188 {
189 is.close();
190 }
191 }
192
193 protected static String getPath( String basedir, String dir )
194 {
195 String path;
196 path = basedir;
197 if ( !basedir.endsWith( "/" ) && !dir.startsWith( "/" ) )
198 {
199 path += "/";
200 }
201 path += dir;
202 return path;
203 }
204
205
206
207
208
209 public void putDirectory( Wagon wagon, File sourceDirectory, String destinationDirectory )
210 throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
211 {
212 Repository repository = wagon.getRepository();
213
214 String basedir = repository.getBasedir();
215
216 String destDir = StringUtils.replace( destinationDirectory, "\\", "/" );
217
218 String path = getPath( basedir, destDir );
219 try
220 {
221 if ( repository.getPermissions() != null )
222 {
223 String dirPerms = repository.getPermissions().getDirectoryMode();
224
225 if ( dirPerms != null )
226 {
227 String umaskCmd = "umask " + PermissionModeUtils.getUserMaskFor( dirPerms );
228 executor.executeCommand( umaskCmd );
229 }
230 }
231
232
233 String mkdirCmd = "mkdir -p \"" + path + "\"";
234
235 executor.executeCommand( mkdirCmd );
236 }
237 catch ( CommandExecutionException e )
238 {
239 throw new TransferFailedException( "Error performing commands for file transfer", e );
240 }
241
242 File zipFile;
243 try
244 {
245 zipFile = File.createTempFile( "wagon", ".zip" );
246 zipFile.deleteOnExit();
247
248 List<String> files = FileUtils.getFileNames( sourceDirectory, "**/**", "", false );
249
250 createZip( files, zipFile, sourceDirectory );
251 }
252 catch ( IOException e )
253 {
254 throw new TransferFailedException( "Unable to create ZIP archive of directory", e );
255 }
256
257 wagon.put( zipFile, getPath( destDir, zipFile.getName() ) );
258
259 try
260 {
261
262
263 executor.executeCommand( "cd \"" + path + "\"; unzip -q -o \"" + zipFile.getName() + "\"; rm -f \""
264 + zipFile.getName() + "\"" );
265
266 zipFile.delete();
267
268 RepositoryPermissions permissions = repository.getPermissions();
269
270 if ( permissions != null && permissions.getGroup() != null )
271 {
272
273 executor.executeCommand( "chgrp -Rf " + permissions.getGroup() + " \"" + path + "\"" );
274 }
275
276 if ( permissions != null && permissions.getFileMode() != null )
277 {
278
279 executor.executeCommand( "chmod -Rf " + permissions.getFileMode() + " \"" + path + "\"" );
280 }
281 }
282 catch ( CommandExecutionException e )
283 {
284 throw new TransferFailedException( "Error performing commands for file transfer", e );
285 }
286 }
287
288 public List<String> getFileList( String destinationDirectory, Repository repository )
289 throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
290 {
291 try
292 {
293 String path = getPath( repository.getBasedir(), destinationDirectory );
294
295 Streams streams = executor.executeCommand( "ls -FlA \"" + path + "\"", false );
296
297 return new LSParser().parseFiles( streams.getOut() );
298 }
299 catch ( CommandExecutionException e )
300 {
301 if ( e.getMessage().trim().endsWith( "No such file or directory" ) )
302 {
303 throw new ResourceDoesNotExistException( e.getMessage().trim(), e );
304 }
305 else if ( e.getMessage().trim().endsWith( "Not a directory" ) )
306 {
307 throw new ResourceDoesNotExistException( e.getMessage().trim(), e );
308 }
309 else
310 {
311 throw new TransferFailedException( "Error performing file listing.", e );
312 }
313 }
314 }
315
316 public boolean resourceExists( String resourceName, Repository repository )
317 throws TransferFailedException, AuthorizationException
318 {
319 try
320 {
321 String path = getPath( repository.getBasedir(), resourceName );
322
323 executor.executeCommand( "ls \"" + path + "\"" );
324
325
326
327
328 return true;
329 }
330 catch ( CommandExecutionException e )
331 {
332
333 return false;
334 }
335 }
336
337 public void createRemoteDirectories( String path, RepositoryPermissions permissions )
338 throws CommandExecutionException
339 {
340 String umaskCmd = null;
341 if ( permissions != null )
342 {
343 String dirPerms = permissions.getDirectoryMode();
344
345 if ( dirPerms != null )
346 {
347 umaskCmd = "umask " + PermissionModeUtils.getUserMaskFor( dirPerms );
348 }
349 }
350
351
352 String mkdirCmd = "mkdir -p \"" + path + "\"";
353
354 if ( umaskCmd != null )
355 {
356 mkdirCmd = umaskCmd + "; " + mkdirCmd;
357 }
358
359 executor.executeCommand( mkdirCmd );
360 }
361 }