Skip to content

Commit

Permalink
Issue #12 Add native winrs
Browse files Browse the repository at this point in the history
  • Loading branch information
Benoit Moussaud committed Sep 22, 2011
1 parent 9db71e9 commit c1a27ef
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.xebialabs.overthere.OverthereConnection;
import com.xebialabs.overthere.cifs.telnet.CifsTelnetConnection;
import com.xebialabs.overthere.cifs.winrm.CifsWinRmConnection;
import com.xebialabs.overthere.cifs.winrs.CifsWinRsConnection;
import com.xebialabs.overthere.spi.OverthereConnectionBuilder;
import com.xebialabs.overthere.spi.Protocol;

Expand Down Expand Up @@ -76,6 +77,10 @@ public CifsConnectionBuilder(String type, ConnectionOptions options) {
case WINRM_HTTPS:
connection = new CifsWinRmConnection(type, options);
break;
case WINRS_HTTP:
case WINRS_HTTPS:
connection = new CifsWinRsConnection(type, options);
break;
default:
throw new IllegalArgumentException("Unknown CIFS connection type " + cifsConnectionType);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ public enum CifsConnectionType {
/**
* A CIFS connection that uses WinRM over HTTPS to execute commands.
*/
WINRM_HTTPS
WINRM_HTTPS,

/**
* A CIFS connection that uses WinRS client over HTTP to execute commands.
*/
WINRS_HTTP,

/**
* A CIFS connection that uses WinRS client over HTTPS to execute commands.
*/
WINRS_HTTPS

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.xebialabs.overthere.cifs.winrs;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.xebialabs.overthere.*;
import com.xebialabs.overthere.cifs.CifsConnection;
import com.xebialabs.overthere.cifs.CifsConnectionBuilder;
import com.xebialabs.overthere.cifs.CifsConnectionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.MalformedURLException;
import java.net.URL;

import static com.google.common.collect.Iterables.transform;
import static com.xebialabs.overthere.ConnectionOptions.PORT;
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.CONNECTION_TYPE;
import static java.lang.String.format;

public class CifsWinRsConnection extends CifsConnection {

private String winrsExecFile = "C:\\WINDOWS\\system32\\winrs.exe";
private CifsConnectionType winrsConnectionType;
private URL targetURL;

// Dirty hack to make super-class constructor happy with the value of CONNECTION_TYPE property
// TODO : refactor to make this hack unnecessary
private static ConnectionOptions workAroundConnectionTypeClash(ConnectionOptions options) {
ConnectionOptions newOptions = new ConnectionOptions(options);
newOptions.set(CONNECTION_TYPE, CifsConnectionType.WINRM_HTTP); // super class constructor needs a CifsConnectionType value
return newOptions;
}

public CifsWinRsConnection(String type, ConnectionOptions options) {
super(type, workAroundConnectionTypeClash(options), false);
this.winrsConnectionType = options.get(CONNECTION_TYPE);
this.port = options.get(PORT, getDefaultPort());
this.targetURL = getTargetURL(options);
}

@Override
public OverthereProcess startProcess(CmdLine commandLine) {
logger.debug("startProcess : {} ", commandLine.toCommandLine(os, true));

/*
* winrs -remote:https://host:port
* -username:[domain\]username -password:passwd -directory:temporaryDirectoryPath script_to_execute
*/
final ImmutableList<String> fullCommandLine = new ImmutableList.Builder<String>()
.add(winrsExecFile)
.add(format("-remote:%s", targetURL.toString()))
.add(format("-username:%s", username))
.add(format("-password:%s", password))
.add(format("-directory:%s", temporaryDirectoryPath))
.addAll(transform(commandLine.getArguments(), new Function<CmdLineArgument, String>() {
public String apply(CmdLineArgument input) {
return input.getArg();
}
})).build();

logger.debug("winrs base command line {}", Joiner.on(" ").join(fullCommandLine));
return new WinrsOverthereProcess(fullCommandLine);
}

private Integer getDefaultPort() {
switch (winrsConnectionType) {
case WINRS_HTTP:
return CifsConnectionBuilder.DEFAULT_WINRM_HTTP_PORT;
case WINRS_HTTPS:
return CifsConnectionBuilder.DEFAULT_WINRM_HTTPS_PORT;
default:
throw new IllegalArgumentException("Unknown Winrs connection type " + winrsConnectionType);
}
}

private URL getTargetURL(ConnectionOptions options) {
String scheme = winrsConnectionType == CifsConnectionType.WINRS_HTTP ? "http" : "https";
try {
return new URL(scheme, address, port, "");
} catch (MalformedURLException e) {
throw new RuntimeIOException("Cannot build a new URL for " + this, e);
}
}

@Override
public String toString() {
return "winrs:" + winrsConnectionType + "://" + username + "@" + address + ":" + port;
}

private static Logger logger = LoggerFactory.getLogger(CifsConnection.class);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.xebialabs.overthere.cifs.winrs;

import com.google.common.base.Joiner;
import com.xebialabs.overthere.OverthereProcess;
import com.xebialabs.overthere.RuntimeIOException;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

public class WinrsOverthereProcess implements OverthereProcess {

private final ProcessBuilder processBuilder;
private final Process process;

public WinrsOverthereProcess(List<String> fullCommandLine) {
processBuilder = new ProcessBuilder(fullCommandLine);
try {
process = processBuilder.start();
process.getOutputStream().close(); // this is necessary to close the outputStream for winrs
// otherwise Winrs doesn't end the process
// => Closing this stream soo early forced me to disable getStdin() below
} catch (IOException e) {
throw new RuntimeIOException("Winrs command start fails to start {}" + Joiner.on(" ").join(fullCommandLine), e);
}
}

public OutputStream getStdin() {
throw new UnsupportedOperationException("This protocol doesn't support stdin");
}

public InputStream getStdout() {
return process.getInputStream();
}

public InputStream getStderr() {
return process.getErrorStream();
}

public int waitFor() throws InterruptedException {
return process.waitFor();
}

public void destroy() {
process.destroy();
}
}

0 comments on commit c1a27ef

Please sign in to comment.