1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.jclouds.scriptbuilder;
20
21 import static com.google.common.base.Preconditions.checkNotNull;
22
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Map.Entry;
26
27 import org.jclouds.scriptbuilder.domain.AcceptsStatementVisitor;
28 import org.jclouds.scriptbuilder.domain.OsFamily;
29 import org.jclouds.scriptbuilder.domain.ShellToken;
30 import org.jclouds.scriptbuilder.domain.Statement;
31 import org.jclouds.scriptbuilder.domain.StatementVisitor;
32 import org.jclouds.scriptbuilder.util.Utils;
33
34 import com.google.common.annotations.VisibleForTesting;
35 import com.google.common.base.Function;
36 import com.google.common.collect.ImmutableSet;
37 import com.google.common.collect.Iterables;
38 import com.google.common.collect.Lists;
39 import com.google.common.collect.Maps;
40
41
42
43
44
45
46 public class ScriptBuilder implements Statement, AcceptsStatementVisitor {
47
48 @VisibleForTesting
49 List<Statement> statements = Lists.newArrayList();
50
51 @VisibleForTesting
52 Map<String, Map<String, String>> variableScopes = Maps.newLinkedHashMap();
53
54 @VisibleForTesting
55 List<String> variablesToUnset = Lists.newArrayList("path", "javaHome", "libraryPath");
56
57 public ScriptBuilder addStatement(Statement statement) {
58 statements.add(checkNotNull(statement, "statement"));
59 return this;
60 }
61
62
63
64
65 public ScriptBuilder unsetEnvironmentVariable(String name) {
66 variablesToUnset.add(checkNotNull(name, "name"));
67 return this;
68 }
69
70
71
72
73 public ScriptBuilder addEnvironmentVariableScope(String scopeName, Map<String, String> variables) {
74 variableScopes.put(checkNotNull(scopeName, "scopeName"), checkNotNull(variables, "variables"));
75 return this;
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89
90 @Override
91 public String render(OsFamily osFamily) {
92 Map<String, String> functions = Maps.newLinkedHashMap();
93 functions.put("abort", Utils.writeFunctionFromResource("abort", osFamily));
94
95 for (Entry<String, Map<String, String>> entry : variableScopes.entrySet()) {
96 functions.put(entry.getKey(), Utils.writeFunction(entry.getKey(), Utils.writeVariableExporters(entry
97 .getValue())));
98 }
99 final Map<String, String> tokenValueMap = ShellToken.tokenValueMap(osFamily);
100 StringBuilder builder = new StringBuilder();
101 builder.append(ShellToken.BEGIN_SCRIPT.to(osFamily));
102 builder.append(Utils.writeUnsetVariables(Lists.newArrayList(Iterables.transform(variablesToUnset,
103 new Function<String, String>() {
104 @Override
105 public String apply(String from) {
106 if (tokenValueMap.containsKey(from + "Variable"))
107 return Utils.FUNCTION_UPPER_UNDERSCORE_TO_LOWER_CAMEL.apply(tokenValueMap
108 .get(from + "Variable"));
109 return from;
110 }
111
112 })), osFamily));
113 resolveFunctionDependencies(functions, osFamily);
114 if (functions.size() > 0) {
115 builder.append(ShellToken.BEGIN_FUNCTIONS.to(osFamily));
116 for (String function : functions.values()) {
117 builder.append(Utils.replaceTokens(function, tokenValueMap));
118 }
119 builder.append(ShellToken.END_FUNCTIONS.to(osFamily));
120 }
121 builder.append(Utils.writeZeroPath(osFamily));
122 StringBuilder statementBuilder = new StringBuilder();
123 for (Statement statement : statements) {
124 statementBuilder.append(statement.render(osFamily));
125 }
126 builder.append(statementBuilder.toString().replaceAll(ShellToken.RETURN.to(osFamily),
127 ShellToken.EXIT.to(osFamily)));
128 builder.append(ShellToken.END_SCRIPT.to(osFamily));
129 return builder.toString();
130 }
131
132 @VisibleForTesting
133 void resolveFunctionDependencies(Map<String, String> functions, final OsFamily osFamily) {
134 Iterable<String> dependentFunctions = Iterables.concat(Iterables.transform(statements,
135 new Function<Statement, Iterable<String>>() {
136 @Override
137 public Iterable<String> apply(Statement from) {
138 return from.functionDependencies(osFamily);
139 }
140 }));
141 List<String> unresolvedFunctions = Lists.newArrayList(dependentFunctions);
142 Iterables.removeAll(unresolvedFunctions, functions.keySet());
143 for (String functionName : unresolvedFunctions) {
144 functions.put(functionName, Utils.writeFunctionFromResource(functionName, osFamily));
145 }
146 }
147
148 @Override
149 public Iterable<String> functionDependencies(OsFamily family) {
150 return ImmutableSet.<String> of();
151 }
152
153 @Override
154 public void accept(StatementVisitor visitor) {
155 for (Statement statement : statements) {
156 visitor.visit(statement);
157 }
158 }
159 }