1 package fr.jayasoft.ivy.repository.ssh; 2 3 4 import java.io.BufferedReader ; 5 import java.io.ByteArrayInputStream ; 6 import java.io.ByteArrayOutputStream ; 7 import java.io.File ; 8 import java.io.IOException ; 9 import java.io.InputStream ; 10 import java.io.StringReader ; 11 import java.net.URI ; 12 import java.net.URISyntaxException ; 13 import java.util.ArrayList ; 14 import java.util.List ; 15 16 import com.jcraft.jsch.ChannelExec; 17 import com.jcraft.jsch.JSchException; 18 import com.jcraft.jsch.Session; 19 20 import fr.jayasoft.ivy.repository.Resource; 21 import fr.jayasoft.ivy.util.Message; 22 23 26 public class SshRepository extends AbstractSshBasedRepository { 27 28 private char fileSeparator = '/'; 29 private String listCommand = "ls -1"; 30 private String existCommand = "ls"; 31 private String createDirCommand = "mkdir"; 32 private final static String ARGUMENT_PLACEHOLDER = "%arg"; 33 private final static int POLL_SLEEP_TIME = 500; 34 37 public Resource getResource(String source) { 38 Message.debug("SShRepository:getResource called: "+source); 39 return new SshResource(this,source); 40 } 41 42 49 public SshResource resolveResource(String source) { 50 Message.debug("SShRepository:resolveResource called: "+source); 51 SshResource result = null; 52 Session session = null; 53 try { 54 session = getSession(source); 55 Scp myCopy = new Scp(session); 56 Scp.FileInfo fileInfo = myCopy.getFileinfo(new URI (source).getPath()); 57 result = new SshResource(this, 58 source, 59 true, 60 fileInfo.getLength(), 61 fileInfo.getLastModified()); 62 } catch (IOException e) { 63 if(session != null) 64 releaseSession(session,source); 65 result = new SshResource(); 66 } catch (URISyntaxException e) { 67 if(session != null) 68 releaseSession(session,source); 69 result = new SshResource(); 70 } catch (RemoteScpException e) { 71 result = new SshResource(); 72 } 73 Message.debug("SShRepository:resolveResource end."); 74 return result; 75 } 76 77 84 private void readSessionOutput(ChannelExec channel, StringBuffer strStdout, StringBuffer strStderr) throws IOException { 85 InputStream stdout = channel.getInputStream(); 86 InputStream stderr = channel.getErrStream(); 87 88 try { 89 channel.connect(); 90 } catch (JSchException e1) { 91 throw (IOException ) new IOException ("Channel connection problems").initCause(e1); 92 } 93 94 byte[] buffer = new byte[8192]; 95 while(true){ 96 int avail = 0; 97 while ((avail = stdout.available()) > 0) { 98 int len = stdout.read(buffer,0,(avail > 8191 ? 8192 : avail)); 99 strStdout.append(new String (buffer,0,len)); 100 } 101 while ((avail = stderr.available()) > 0) { 102 int len = stderr.read(buffer,0,(avail > 8191 ? 8192 : avail)); 103 strStderr.append(new String (buffer, 0, len)); 104 } 105 if(channel.isClosed()){ 106 break; 107 } 108 try{Thread.sleep(POLL_SLEEP_TIME);}catch(Exception ee){} 109 } 110 int avail = 0; 111 while ((avail = stdout.available()) > 0) { 112 int len = stdout.read(buffer,0,(avail > 8191 ? 8192 : avail)); 113 strStdout.append(new String (buffer,0,len)); 114 } 115 while ((avail = stderr.available()) > 0) { 116 int len = stderr.read(buffer,0,(avail > 8191 ? 8192 : avail)); 117 strStderr.append(new String (buffer, 0, len)); 118 } 119 } 120 121 124 public List list(String parent) throws IOException { 125 Message.debug("SShRepository:list called: "+parent); 126 ArrayList result = new ArrayList (); 127 Session session = null; 128 ChannelExec channel = null; 129 session = getSession(parent); 130 channel = getExecChannel(session); 131 URI parentUri = null; 132 try { 133 parentUri = new URI (parent); 134 } catch (URISyntaxException e1) { 135 } 137 String fullCmd = replaceArgument(listCommand,parentUri.getPath()); 138 channel.setCommand(fullCmd); 139 StringBuffer stdOut = new StringBuffer (); 140 StringBuffer stdErr = new StringBuffer (); 141 readSessionOutput(channel,stdOut,stdErr); 142 if(channel.getExitStatus() != 0) { 143 Message.error("Ssh ListCommand exited with status != 0"); 144 Message.error(stdErr.toString()); 145 return null; 146 } else { 147 BufferedReader br = new BufferedReader (new StringReader (stdOut.toString())); 148 String line = null; 149 while((line = br.readLine()) != null) { 150 result.add(line); 151 } 152 } 153 return result; 154 } 155 156 161 private ChannelExec getExecChannel(Session session) throws IOException { 162 ChannelExec channel; 163 try { 164 channel = (ChannelExec)session.openChannel("exec"); 165 } catch (JSchException e) { 166 throw new IOException (); 167 } 168 return channel; 169 } 170 171 178 private String replaceArgument(String command, String argument) { 179 String fullCmd; 180 if(command.indexOf(ARGUMENT_PLACEHOLDER) == -1) { 181 fullCmd = command + " " + argument; 182 } else { 183 fullCmd = command.replaceAll(ARGUMENT_PLACEHOLDER,argument); 184 } 185 return fullCmd; 186 } 187 188 191 public void put(File source, String destination, boolean overwrite) throws IOException { 192 Message.debug("SShRepository:put called: "+destination); 193 Session session = getSession(destination); 194 try { 195 URI destinationUri = null; 196 try { 197 destinationUri = new URI (destination); 198 } catch (URISyntaxException e) { 199 } 201 String filePath = destinationUri.getPath(); 202 int lastSep = filePath.lastIndexOf(fileSeparator); 203 String path; 204 String name; 205 if(lastSep == -1) { 206 name = filePath; 207 path = null; 208 } else { 209 name = filePath.substring(lastSep+1); 210 path = filePath.substring(0,lastSep); 211 } 212 if (!overwrite) { 213 if(checkExistence(filePath,session)) { 214 throw new IOException ("destination file exists and overwrite == true"); 215 } 216 } 217 if(path != null) { 218 makePath(path,session); 219 } 220 Scp myCopy = new Scp(session); 221 myCopy.put(source.getCanonicalPath(),path,name); 222 } catch (IOException e) { 223 if(session != null) 224 releaseSession(session,destination); 225 throw e; 226 } catch (RemoteScpException e) { 227 throw new IOException (e.getMessage()); 228 } 229 } 230 231 236 private void makePath(String path, Session session) throws IOException { 237 ChannelExec channel = null; 238 String trimmed = path; 239 try { 240 while(trimmed.length() > 0 && trimmed.charAt(trimmed.length()-1) == fileSeparator) 241 trimmed = trimmed.substring(0,trimmed.length()-1); 242 if(trimmed.length() == 0 || checkExistence(trimmed,session)) { 243 return; 244 } 245 int nextSlash = trimmed.lastIndexOf(fileSeparator); 246 if(nextSlash > 0) { 247 String parent = trimmed.substring(0,nextSlash); 248 makePath(parent,session); 249 } 250 channel = getExecChannel(session); 251 String mkdir = replaceArgument( createDirCommand, trimmed); 252 Message.debug("SShRepository: trying to create path: " + mkdir); 253 channel.setCommand(mkdir); 254 StringBuffer stdOut = new StringBuffer (); 255 StringBuffer stdErr = new StringBuffer (); 256 readSessionOutput(channel,stdOut,stdErr); 257 } finally { 258 if(channel != null) 259 channel.disconnect(); 260 } 261 } 262 263 269 private boolean checkExistence(String filePath, Session session) throws IOException { 270 Message.debug("SShRepository: checkExistence called: " + filePath); 271 ChannelExec channel = null; 272 channel = getExecChannel(session); 273 String fullCmd = replaceArgument( existCommand, filePath); 274 channel.setCommand(fullCmd); 275 StringBuffer stdOut = new StringBuffer (); 276 StringBuffer stdErr = new StringBuffer (); 277 readSessionOutput(channel,stdOut,stdErr); 278 return channel.getExitStatus() == 0; 279 } 280 281 284 public void get(String source, File destination) throws IOException { 285 Message.debug("SShRepository:get called: "+source+" to "+destination.getCanonicalPath()); 286 if (destination.getParentFile() != null) { 287 destination.getParentFile().mkdirs(); 288 } 289 Session session = getSession(source); 290 try { 291 URI sourceUri = null; 292 try { 293 sourceUri = new URI (source); 294 } catch (URISyntaxException e) { 295 } 297 if(sourceUri == null) { 298 Message.error("could not parse URI "+source); 299 return; 300 } 301 Scp myCopy = new Scp(session); 302 myCopy.get(sourceUri.getPath(),destination.getCanonicalPath()); 303 } catch (IOException e) { 304 if(session != null) 305 releaseSession(session,source); 306 throw e; 307 } catch (RemoteScpException e) { 308 throw new IOException (e.getMessage()); 309 } 310 } 311 312 317 public void setListCommand(String cmd) { 318 this.listCommand = cmd.trim(); 319 } 320 321 324 public String getListCommand() { 325 return listCommand; 326 } 327 328 331 public String getCreateDirCommand() { 332 return createDirCommand; 333 } 334 335 338 public void setCreateDirCommand(String createDirCommand) { 339 this.createDirCommand = createDirCommand; 340 } 341 342 345 public String getExistCommand() { 346 return existCommand; 347 } 348 349 352 public void setExistCommand(String existCommand) { 353 this.existCommand = existCommand; 354 } 355 356 362 public void setFileSeparator(char fileSeparator) { 363 this.fileSeparator = fileSeparator; 364 } 365 366 371 protected String getRepositoryScheme() { 372 return "ssh"; 373 } 374 375 380 public InputStream openStream(SshResource resource) throws IOException { 381 Session session = getSession(resource.getName()); 382 Scp scp = new Scp(session); 383 ByteArrayOutputStream os = new ByteArrayOutputStream (); 384 try { 385 scp.get(resource.getName(),os); 386 } catch (IOException e) { 387 if(session != null) 388 releaseSession(session,resource.getName()); 389 throw e; 390 } catch (RemoteScpException e) { 391 throw new IOException (e.getMessage()); 392 } 393 return new ByteArrayInputStream (os.toByteArray()); 394 } 395 } 396 | Popular Tags |