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