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 = null;
151 try
152 {
153 zos = new ZipOutputStream( new FileOutputStream( zipName ) );
154
155 for ( String file : files )
156 {
157 file = file.replace( '\\', '/' );
158
159 writeZipEntry( zos, new File( basedir, file ), file );
160 }
161
162 zos.close();
163 zos = null;
164 }
165 finally
166 {
167 IOUtil.close( zos );
168 }
169 }
170
171 private static void writeZipEntry( ZipOutputStream jar, File source, String entryName )
172 throws IOException
173 {
174 byte[] buffer = new byte[1024];
175
176 int bytesRead;
177
178 FileInputStream is = new FileInputStream( source );
179
180 try
181 {
182 ZipEntry entry = new ZipEntry( entryName );
183
184 jar.putNextEntry( entry );
185
186 while ( ( bytesRead = is.read( buffer ) ) != -1 )
187 {
188 jar.write( buffer, 0, bytesRead );
189 }
190 }
191 finally
192 {
193 is.close();
194 }
195 }
196
197 protected static String getPath( String basedir, String dir )
198 {
199 String path;
200 path = basedir;
201 if ( !basedir.endsWith( "/" ) && !dir.startsWith( "/" ) )
202 {
203 path += "/";
204 }
205 path += dir;
206 return path;
207 }
208
209
210
211
212
213 public void putDirectory( Wagon wagon, File sourceDirectory, String destinationDirectory )
214 throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
215 {
216 Repository repository = wagon.getRepository();
217
218 String basedir = repository.getBasedir();
219
220 String destDir = StringUtils.replace( destinationDirectory, "\\", "/" );
221
222 String path = getPath( basedir, destDir );
223 try
224 {
225 if ( repository.getPermissions() != null )
226 {
227 String dirPerms = repository.getPermissions().getDirectoryMode();
228
229 if ( dirPerms != null )
230 {
231 String umaskCmd = "umask " + PermissionModeUtils.getUserMaskFor( dirPerms );
232 executor.executeCommand( umaskCmd );
233 }
234 }
235
236
237 String mkdirCmd = "mkdir -p \"" + path + "\"";
238
239 executor.executeCommand( mkdirCmd );
240 }
241 catch ( CommandExecutionException e )
242 {
243 throw new TransferFailedException( "Error performing commands for file transfer", e );
244 }
245
246 File zipFile;
247 try
248 {
249 zipFile = File.createTempFile( "wagon", ".zip" );
250 zipFile.deleteOnExit();
251
252 List<String> files = FileUtils.getFileNames( sourceDirectory, "**/**", "", false );
253
254 createZip( files, zipFile, sourceDirectory );
255 }
256 catch ( IOException e )
257 {
258 throw new TransferFailedException( "Unable to create ZIP archive of directory", e );
259 }
260
261 wagon.put( zipFile, getPath( destDir, zipFile.getName() ) );
262
263 try
264 {
265
266
267 executor.executeCommand( "cd \"" + path + "\"; unzip -q -o \"" + zipFile.getName() + "\"; rm -f \""
268 + zipFile.getName() + "\"" );
269
270 zipFile.delete();
271
272 RepositoryPermissions permissions = repository.getPermissions();
273
274 if ( permissions != null && permissions.getGroup() != null )
275 {
276
277 executor.executeCommand( "chgrp -Rf " + permissions.getGroup() + " \"" + path + "\"" );
278 }
279
280 if ( permissions != null && permissions.getFileMode() != null )
281 {
282
283 executor.executeCommand( "chmod -Rf " + permissions.getFileMode() + " \"" + path + "\"" );
284 }
285 }
286 catch ( CommandExecutionException e )
287 {
288 throw new TransferFailedException( "Error performing commands for file transfer", e );
289 }
290 }
291
292 public List<String> getFileList( String destinationDirectory, Repository repository )
293 throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
294 {
295 try
296 {
297 String path = getPath( repository.getBasedir(), destinationDirectory );
298
299 Streams streams = executor.executeCommand( "ls -FlA \"" + path + "\"", false );
300
301 return new LSParser().parseFiles( streams.getOut() );
302 }
303 catch ( CommandExecutionException e )
304 {
305 if ( e.getMessage().trim().endsWith( "No such file or directory" ) )
306 {
307 throw new ResourceDoesNotExistException( e.getMessage().trim(), e );
308 }
309 else if ( e.getMessage().trim().endsWith( "Not a directory" ) )
310 {
311 throw new ResourceDoesNotExistException( e.getMessage().trim(), e );
312 }
313 else
314 {
315 throw new TransferFailedException( "Error performing file listing.", e );
316 }
317 }
318 }
319
320 public boolean resourceExists( String resourceName, Repository repository )
321 throws TransferFailedException, AuthorizationException
322 {
323 try
324 {
325 String path = getPath( repository.getBasedir(), resourceName );
326
327 executor.executeCommand( "ls \"" + path + "\"" );
328
329
330
331
332 return true;
333 }
334 catch ( CommandExecutionException e )
335 {
336
337 return false;
338 }
339 }
340
341 public void createRemoteDirectories( String path, RepositoryPermissions permissions )
342 throws CommandExecutionException
343 {
344 String umaskCmd = null;
345 if ( permissions != null )
346 {
347 String dirPerms = permissions.getDirectoryMode();
348
349 if ( dirPerms != null )
350 {
351 umaskCmd = "umask " + PermissionModeUtils.getUserMaskFor( dirPerms );
352 }
353 }
354
355
356 String mkdirCmd = "mkdir -p \"" + path + "\"";
357
358 if ( umaskCmd != null )
359 {
360 mkdirCmd = umaskCmd + "; " + mkdirCmd;
361 }
362
363 executor.executeCommand( mkdirCmd );
364 }
365 }