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); return new StatementList(statements);
} }
public static Statement switchOn(String variable, Map<String, Statement> valueToActions) { public static Statement switchArg(int arg, Map<String, Statement> valueToActions) {
return new Switch(variable, valueToActions); return new SwitchArg(arg, valueToActions);
} }
public static Statement call(String function, String... args) { 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 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.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -41,10 +42,10 @@ import com.google.common.collect.Lists;
* *
* @author Adrian Cole * @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, 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( public static final Map<OsFamily, String> OS_TO_END_SWITCH_PATTERN = ImmutableMap.of(
OsFamily.UNIX, "esac\n", OsFamily.WINDOWS, ":END_SWITCH\r\n"); 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, "{value})\n{action} ;;\n", OsFamily.WINDOWS,
":CASE_{value}\r\n{action} GOTO END_SWITCH\r\n"); ":CASE_{value}\r\n{action} GOTO END_SWITCH\r\n");
private final String variable; private final int arg;
private final Map<String, Statement> valueToActions; 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. * {@code valueToActions}, the corresponding action is invoked.
* *
* <p/> * <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/> * and valueToActions is {"start" -> "echo hello", "stop" -> "echo goodbye"}<br/>
* the script created will respond accordingly:<br/> * the script created will respond accordingly:<br/>
* {@code ./script start }<br/> * {@code ./script start }<br/>
@ -70,21 +71,22 @@ public class Switch implements Statement {
* {@code ./script stop }<br/> * {@code ./script stop }<br/>
* << returns goodbye<br/> * << returns goodbye<br/>
* *
* @param variable * @param arg
* - shell variable to switch on * - shell arg to switch on
* @param valueToActions * @param valueToActions
* - case statements, if the value of the variable matches a key, the corresponding * - case statements, if the value of the arg matches a key, the corresponding value
* value will be invoked. * will be invoked.
*/ */
public Switch(String variable, Map<String, Statement> valueToActions) { public SwitchArg(int arg, Map<String, Statement> valueToActions) {
this.variable = checkNotNull(variable, "variable"); this.arg = arg;
this.valueToActions = checkNotNull(valueToActions, "valueToActions"); this.valueToActions = checkNotNull(valueToActions, "valueToActions");
} }
public String render(OsFamily family) { public String render(OsFamily family) {
StringBuilder switchClause = new StringBuilder(); StringBuilder switchClause = new StringBuilder();
addArgValidation(switchClause, family);
switchClause.append(Utils.replaceTokens(OS_TO_SWITCH_PATTERN.get(family), ImmutableMap.of( 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()) { for (Entry<String, Statement> entry : valueToActions.entrySet()) {
switchClause.append(Utils.replaceTokens(OS_TO_CASE_PATTERN.get(family), ImmutableMap.of( switchClause.append(Utils.replaceTokens(OS_TO_CASE_PATTERN.get(family), ImmutableMap.of(
@ -96,12 +98,35 @@ public class Switch implements Statement {
return switchClause.toString(); 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 @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + arg;
result = prime * result + ((valueToActions == null) ? 0 : valueToActions.hashCode()); result = prime * result + ((valueToActions == null) ? 0 : valueToActions.hashCode());
result = prime * result + ((variable == null) ? 0 : variable.hashCode());
return result; return result;
} }
@ -113,26 +138,14 @@ public class Switch implements Statement {
return false; return false;
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
Switch other = (Switch) obj; SwitchArg other = (SwitchArg) obj;
if (arg != other.arg)
return false;
if (valueToActions == null) { if (valueToActions == null) {
if (other.valueToActions != null) if (other.valueToActions != null)
return false; return false;
} else if (!valueToActions.equals(other.valueToActions)) } else if (!valueToActions.equals(other.valueToActions))
return false; return false;
if (variable == null) {
if (other.variable != null)
return false;
} else if (!variable.equals(other.variable))
return false;
return true; 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.interpret;
import static org.jclouds.scriptbuilder.domain.Statements.kill; import static org.jclouds.scriptbuilder.domain.Statements.kill;
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList; 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 static org.testng.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
@ -13,7 +13,7 @@ import java.net.MalformedURLException;
import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.ShellToken; import org.jclouds.scriptbuilder.domain.ShellToken;
import org.jclouds.scriptbuilder.domain.Switch; import org.jclouds.scriptbuilder.domain.SwitchArg;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
@ -30,10 +30,11 @@ import com.google.common.io.Resources;
public class ScriptBuilderTest { public class ScriptBuilderTest {
ScriptBuilder testScriptBuilder = new ScriptBuilder() ScriptBuilder testScriptBuilder = new ScriptBuilder()
.unsetEnvironmentVariable("runtime")
.addEnvironmentVariableScope("default", ImmutableMap.of("runtime", "Moo")) .addEnvironmentVariableScope("default", ImmutableMap.of("runtime", "Moo"))
.addStatement( .addStatement(
switchOn( switchArg(
"1", 1,
ImmutableMap ImmutableMap
.of( .of(
"start", "start",
@ -45,7 +46,7 @@ public class ScriptBuilderTest {
call("default"), call("default"),
interpret("echo stop {varl}RUNTIME{varr}{lf}")), interpret("echo stop {varl}RUNTIME{varr}{lf}")),
"status", "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 @Test
public void testBuildSimpleWindows() throws MalformedURLException, IOException { public void testBuildSimpleWindows() throws MalformedURLException, IOException {
@ -98,9 +99,9 @@ public class ScriptBuilderTest {
@Test @Test
public void testSwitchOn() { public void testSwitchOn() {
ScriptBuilder builder = new ScriptBuilder(); 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}")))); "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}"))))); interpret("echo started{lf}"), "stop", interpret("echo stopped{lf}")))));
} }
@ -109,20 +110,20 @@ public class ScriptBuilderTest {
ScriptBuilder builder = new ScriptBuilder(); ScriptBuilder builder = new ScriptBuilder();
assertEquals(builder.statements.size(), 0); assertEquals(builder.statements.size(), 0);
} }
//
// @Test @Test
// public void testExport() { public void testExport() {
// ScriptBuilder builder = new ScriptBuilder(); ScriptBuilder builder = new ScriptBuilder();
// builder.addEnvironmentVariableScope("default", ImmutableMap.of("javaHome", "/apps/jdk1.6")); builder.addEnvironmentVariableScope("default", ImmutableMap.of("javaHome", "/apps/jdk1.6"));
// assertEquals(builder.functions, ImmutableMap.of("default", assertEquals(builder.variableScopes, ImmutableMap.of("default", ImmutableMap.of("javaHome",
// "{fncl}default{fncr} {export} JAVA_HOME={vq}/apps/jdk1.6{vq}{lf}{fnce}")); "/apps/jdk1.6")));
// } }
//
// @Test @Test
// public void testNoExport() { public void testNoExport() {
// ScriptBuilder builder = new ScriptBuilder(); ScriptBuilder builder = new ScriptBuilder();
// assertEquals(builder.functions.size(), 0); assertEquals(builder.variableScopes.size(), 0);
// } }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testExportNPE() { public void testExportNPE() {

View File

@ -32,19 +32,19 @@ import com.google.common.collect.ImmutableMap;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "scriptbuilder.SwitchTest") @Test(groups = "unit", testName = "scriptbuilder.SwitchArgTest")
public class SwitchTest { public class SwitchArgTest {
public void testSwitchUNIX() { public void testSwitchArgUNIX() {
assertEquals(new Switch("i", ImmutableMap.of("0", interpret("echo hello zero{lf}"), "1", assertEquals(new SwitchArg(1, ImmutableMap.of("0", interpret("echo hello zero{lf}"), "1",
interpret("echo hello one{lf}"))).render(OsFamily.UNIX), 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( 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), 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 PATH=
set JAVA_HOME= set JAVA_HOME=
set PATH= set PATH=
set RUNTIME=
GOTO FUNCTION_END GOTO FUNCTION_END
:abort :abort
echo aborting: %EXCEPTION% echo aborting: %EXCEPTION%
@ -11,7 +12,11 @@ GOTO FUNCTION_END
exit /b 0 exit /b 0
:FUNCTION_END :FUNCTION_END
set PATH=c:\windows\;C:\windows\system32;c:\windows\system32\wbem 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 :CASE_start
call :default call :default
if errorlevel 1 goto abort if errorlevel 1 goto abort
@ -23,7 +28,7 @@ if errorlevel 1 goto abort
echo stop %RUNTIME% echo stop %RUNTIME%
GOTO END_SWITCH GOTO END_SWITCH
:CASE_status :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 GOTO END_SWITCH
:END_SWITCH :END_SWITCH
exit /b 0 exit /b 0

View File

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