Issue 126: fixed switch to be more pretty in windows

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2359 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-12-01 19:04:17 +00:00
parent 1ffb7d55ab
commit df529b2592
6 changed files with 83 additions and 64 deletions

View File

@ -37,8 +37,8 @@ public class Statements {
return new StatementList(statements);
}
public static Statement switchOn(String variable, Map<String, Statement> valueToActions) {
return new Switch(variable, valueToActions);
public static Statement switchArg(int arg, Map<String, Statement> valueToActions) {
return new SwitchArg(arg, valueToActions);
}
public static Statement call(String function, String... args) {

View File

@ -31,7 +31,8 @@ import java.util.Map.Entry;
import org.jclouds.scriptbuilder.util.Utils;
import com.google.common.base.CaseFormat;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@ -41,10 +42,10 @@ import com.google.common.collect.Lists;
*
* @author Adrian Cole
*/
public class Switch implements Statement {
public class SwitchArg implements Statement {
public static final Map<OsFamily, String> OS_TO_SWITCH_PATTERN = ImmutableMap.of(OsFamily.UNIX,
"case ${variable} in\n", OsFamily.WINDOWS, "goto CASE%{variable}\r\n");
"case ${arg} in\n", OsFamily.WINDOWS, "goto CASE_%{arg}\r\n");
public static final Map<OsFamily, String> OS_TO_END_SWITCH_PATTERN = ImmutableMap.of(
OsFamily.UNIX, "esac\n", OsFamily.WINDOWS, ":END_SWITCH\r\n");
@ -53,16 +54,16 @@ public class Switch implements Statement {
"{value})\n{action} ;;\n", OsFamily.WINDOWS,
":CASE_{value}\r\n{action} GOTO END_SWITCH\r\n");
private final String variable;
private final int arg;
private final Map<String, Statement> valueToActions;
/**
* Generates a switch statement based on {@code variable}. If its value is found to be a key in
* Generates a switch statement based on {@code arg}. If its value is found to be a key in
* {@code valueToActions}, the corresponding action is invoked.
*
* <p/>
* Ex. variable is {@code 1} - the first argument to the script<br/>
* Ex. arg is {@code 1} - the first argument to the script<br/>
* and valueToActions is {"start" -> "echo hello", "stop" -> "echo goodbye"}<br/>
* the script created will respond accordingly:<br/>
* {@code ./script start }<br/>
@ -70,21 +71,22 @@ public class Switch implements Statement {
* {@code ./script stop }<br/>
* << returns goodbye<br/>
*
* @param variable
* - shell variable to switch on
* @param arg
* - shell arg to switch on
* @param valueToActions
* - case statements, if the value of the variable matches a key, the corresponding
* value will be invoked.
* - case statements, if the value of the arg matches a key, the corresponding value
* will be invoked.
*/
public Switch(String variable, Map<String, Statement> valueToActions) {
this.variable = checkNotNull(variable, "variable");
public SwitchArg(int arg, Map<String, Statement> valueToActions) {
this.arg = arg;
this.valueToActions = checkNotNull(valueToActions, "valueToActions");
}
public String render(OsFamily family) {
StringBuilder switchClause = new StringBuilder();
addArgValidation(switchClause, family);
switchClause.append(Utils.replaceTokens(OS_TO_SWITCH_PATTERN.get(family), ImmutableMap.of(
"variable", CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, variable))));
"arg", arg + "")));
for (Entry<String, Statement> entry : valueToActions.entrySet()) {
switchClause.append(Utils.replaceTokens(OS_TO_CASE_PATTERN.get(family), ImmutableMap.of(
@ -96,12 +98,35 @@ public class Switch implements Statement {
return switchClause.toString();
}
@VisibleForTesting
void addArgValidation(StringBuilder switchClause, OsFamily family) {
if (family.equals(OsFamily.WINDOWS)) {
for (String value : valueToActions.keySet()) {
switchClause.append("if not \"%").append(arg).append(
String.format("\" == \"%s\" ", value));
}
switchClause.append("(\r\n set EXCEPTION=bad argument: %").append(arg)
.append(" not in ");
switchClause.append(Joiner.on(" ").join(valueToActions.keySet()));
switchClause.append("\r\n goto abort\r\n)\r\n");
}
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
List<String> functions = Lists.newArrayList();
for (Statement statement : valueToActions.values()) {
Iterables.addAll(functions, statement.functionDependecies(family));
}
return functions;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + arg;
result = prime * result + ((valueToActions == null) ? 0 : valueToActions.hashCode());
result = prime * result + ((variable == null) ? 0 : variable.hashCode());
return result;
}
@ -113,26 +138,14 @@ public class Switch implements Statement {
return false;
if (getClass() != obj.getClass())
return false;
Switch other = (Switch) obj;
SwitchArg other = (SwitchArg) obj;
if (arg != other.arg)
return false;
if (valueToActions == null) {
if (other.valueToActions != null)
return false;
} else if (!valueToActions.equals(other.valueToActions))
return false;
if (variable == null) {
if (other.variable != null)
return false;
} else if (!variable.equals(other.variable))
return false;
return true;
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
List<String> functions = Lists.newArrayList();
for (Statement statement : valueToActions.values()) {
Iterables.addAll(functions, statement.functionDependecies(family));
}
return functions;
}
}

View File

@ -5,7 +5,7 @@ import static org.jclouds.scriptbuilder.domain.Statements.findPid;
import static org.jclouds.scriptbuilder.domain.Statements.interpret;
import static org.jclouds.scriptbuilder.domain.Statements.kill;
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
import static org.jclouds.scriptbuilder.domain.Statements.switchOn;
import static org.jclouds.scriptbuilder.domain.Statements.switchArg;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
@ -13,7 +13,7 @@ import java.net.MalformedURLException;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.ShellToken;
import org.jclouds.scriptbuilder.domain.Switch;
import org.jclouds.scriptbuilder.domain.SwitchArg;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
@ -30,10 +30,11 @@ import com.google.common.io.Resources;
public class ScriptBuilderTest {
ScriptBuilder testScriptBuilder = new ScriptBuilder()
.unsetEnvironmentVariable("runtime")
.addEnvironmentVariableScope("default", ImmutableMap.of("runtime", "Moo"))
.addStatement(
switchOn(
"1",
switchArg(
1,
ImmutableMap
.of(
"start",
@ -45,7 +46,7 @@ public class ScriptBuilderTest {
call("default"),
interpret("echo stop {varl}RUNTIME{varr}{lf}")),
"status",
newStatementList(interpret("echo status ... the following should be empty, as we haven't sourced the variable\"{varl}RUNTIME{varr}\"{lf}")))));
newStatementList(interpret("echo {vq}the following should be []: [{varl}RUNTIME{varr}]{vq}{lf}")))));
@Test
public void testBuildSimpleWindows() throws MalformedURLException, IOException {
@ -98,9 +99,9 @@ public class ScriptBuilderTest {
@Test
public void testSwitchOn() {
ScriptBuilder builder = new ScriptBuilder();
builder.addStatement(switchOn("1", ImmutableMap.of("start", interpret("echo started{lf}"),
builder.addStatement(switchArg(1, ImmutableMap.of("start", interpret("echo started{lf}"),
"stop", interpret("echo stopped{lf}"))));
assertEquals(builder.statements, ImmutableList.of(new Switch("1", ImmutableMap.of("start",
assertEquals(builder.statements, ImmutableList.of(new SwitchArg(1, ImmutableMap.of("start",
interpret("echo started{lf}"), "stop", interpret("echo stopped{lf}")))));
}
@ -109,20 +110,20 @@ public class ScriptBuilderTest {
ScriptBuilder builder = new ScriptBuilder();
assertEquals(builder.statements.size(), 0);
}
//
// @Test
// public void testExport() {
// ScriptBuilder builder = new ScriptBuilder();
// builder.addEnvironmentVariableScope("default", ImmutableMap.of("javaHome", "/apps/jdk1.6"));
// assertEquals(builder.functions, ImmutableMap.of("default",
// "{fncl}default{fncr} {export} JAVA_HOME={vq}/apps/jdk1.6{vq}{lf}{fnce}"));
// }
//
// @Test
// public void testNoExport() {
// ScriptBuilder builder = new ScriptBuilder();
// assertEquals(builder.functions.size(), 0);
// }
@Test
public void testExport() {
ScriptBuilder builder = new ScriptBuilder();
builder.addEnvironmentVariableScope("default", ImmutableMap.of("javaHome", "/apps/jdk1.6"));
assertEquals(builder.variableScopes, ImmutableMap.of("default", ImmutableMap.of("javaHome",
"/apps/jdk1.6")));
}
@Test
public void testNoExport() {
ScriptBuilder builder = new ScriptBuilder();
assertEquals(builder.variableScopes.size(), 0);
}
@Test(expectedExceptions = NullPointerException.class)
public void testExportNPE() {

View File

@ -32,19 +32,19 @@ import com.google.common.collect.ImmutableMap;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "scriptbuilder.SwitchTest")
public class SwitchTest {
@Test(groups = "unit", testName = "scriptbuilder.SwitchArgTest")
public class SwitchArgTest {
public void testSwitchUNIX() {
assertEquals(new Switch("i", ImmutableMap.of("0", interpret("echo hello zero{lf}"), "1",
public void testSwitchArgUNIX() {
assertEquals(new SwitchArg(1, ImmutableMap.of("0", interpret("echo hello zero{lf}"), "1",
interpret("echo hello one{lf}"))).render(OsFamily.UNIX),
"case $I in\n0)\n echo hello zero\n ;;\n1)\n echo hello one\n ;;\nesac\n");
"case $1 in\n0)\n echo hello zero\n ;;\n1)\n echo hello one\n ;;\nesac\n");
}
public void testSwitchWindows() {
public void testSwitchArgWindows() {
assertEquals(
new Switch("i", ImmutableMap.of("0", interpret("echo hello zero{lf}"), "1",
new SwitchArg(1, ImmutableMap.of("0", interpret("echo hello zero{lf}"), "1",
interpret("echo hello one{lf}"))).render(OsFamily.WINDOWS),
"goto CASE%I\r\n:CASE_0\r\n echo hello zero\r\n GOTO END_SWITCH\r\n:CASE_1\r\n echo hello one\r\n GOTO END_SWITCH\r\n:END_SWITCH\r\n");
"if not \"%1\" == \"0\" if not \"%1\" == \"1\" (\r\n set EXCEPTION=bad argument: %1 not in 0 1\r\n goto abort\r\n)\r\ngoto CASE_%1\r\n:CASE_0\r\n echo hello zero\r\n GOTO END_SWITCH\r\n:CASE_1\r\n echo hello one\r\n GOTO END_SWITCH\r\n:END_SWITCH\r\n");
}
}

View File

@ -2,6 +2,7 @@
set PATH=
set JAVA_HOME=
set PATH=
set RUNTIME=
GOTO FUNCTION_END
:abort
echo aborting: %EXCEPTION%
@ -11,7 +12,11 @@ GOTO FUNCTION_END
exit /b 0
:FUNCTION_END
set PATH=c:\windows\;C:\windows\system32;c:\windows\system32\wbem
goto CASE%1
if not "%1" == "start" if not "%1" == "stop" if not "%1" == "status" (
set EXCEPTION=bad argument: %1 not in start stop status
goto abort
)
goto CASE_%1
:CASE_start
call :default
if errorlevel 1 goto abort
@ -23,7 +28,7 @@ if errorlevel 1 goto abort
echo stop %RUNTIME%
GOTO END_SWITCH
:CASE_status
echo status ... the following should be empty, as we haven't sourced the variable"%RUNTIME%"
echo the following should be []: [%RUNTIME%]
GOTO END_SWITCH
:END_SWITCH
exit /b 0

View File

@ -2,7 +2,7 @@
set +u
shopt -s xpg_echo
shopt -s expand_aliases
unset PATH JAVA_HOME LD_LIBRARY_PATH
unset PATH JAVA_HOME LD_LIBRARY_PATH RUNTIME
function abort {
echo "aborting: $@" 1>&2
exit 1
@ -22,7 +22,7 @@ stop)
echo stop $RUNTIME
;;
status)
echo status ... the following should be empty, as we haven't sourced the variable"$RUNTIME"
echo "the following should be []: [$RUNTIME]"
;;
esac
exit 0