1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package com.rapiddweller.benerator.engine.statement;
28
29 import com.rapiddweller.benerator.StorageSystem;
30 import com.rapiddweller.benerator.engine.BeneratorContext;
31 import com.rapiddweller.benerator.engine.Statement;
32 import com.rapiddweller.common.Assert;
33 import com.rapiddweller.common.BeanUtil;
34 import com.rapiddweller.common.ConfigurationError;
35 import com.rapiddweller.common.Context;
36 import com.rapiddweller.common.ConversionException;
37 import com.rapiddweller.common.ErrorHandler;
38 import com.rapiddweller.common.IOUtil;
39 import com.rapiddweller.common.Level;
40 import com.rapiddweller.common.LogCategoriesConstants;
41 import com.rapiddweller.common.ReaderLineIterator;
42 import com.rapiddweller.common.ShellUtil;
43 import com.rapiddweller.common.StringUtil;
44 import com.rapiddweller.common.SystemInfo;
45 import com.rapiddweller.common.converter.LiteralParser;
46 import com.rapiddweller.format.script.Script;
47 import com.rapiddweller.format.script.ScriptUtil;
48 import com.rapiddweller.jdbacl.DBExecutionResult;
49 import com.rapiddweller.jdbacl.DBUtil;
50 import com.rapiddweller.platform.db.DBSystem;
51 import com.rapiddweller.script.Expression;
52 import com.rapiddweller.script.expression.ExpressionUtil;
53 import com.rapiddweller.task.TaskException;
54 import org.apache.logging.log4j.LogManager;
55 import org.apache.logging.log4j.Logger;
56
57 import java.io.IOException;
58 import java.io.StringReader;
59 import java.io.StringWriter;
60 import java.sql.Connection;
61 import java.sql.SQLException;
62 import java.util.Map;
63 import java.util.Map.Entry;
64
65
66
67
68
69
70
71
72
73 public class EvaluateStatement implements Statement {
74
75 private static final Logger logger = LogManager.getLogger(EvaluateStatement.class);
76
77 private static final String SHELL = "shell";
78
79 private static final Map<String, String> extensionMap;
80
81 static {
82 try {
83 extensionMap = IOUtil.readProperties("com/rapiddweller/benerator/engine/statement/fileTypes.properties");
84 } catch (IOException e) {
85 throw new ConfigurationError(e);
86 }
87 }
88
89
90
91
92 boolean evaluate;
93
94
95
96 Expression<String> idEx;
97
98
99
100 Expression<String> textEx;
101
102
103
104 Expression<String> uriEx;
105
106
107
108 Expression<String> typeEx;
109
110
111
112 Expression<?> targetObjectEx;
113
114
115
116 Expression<Character> separatorEx;
117
118
119
120 Expression<String> onErrorEx;
121
122
123
124 Expression<String> encodingEx;
125
126
127
128 Expression<Boolean> optimizeEx;
129
130
131
132 Expression<Boolean> invalidateEx;
133
134
135
136 Expression<?> assertionEx;
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 public EvaluateStatement(boolean evaluate, Expression<String> idEx, Expression<String> textEx,
155 Expression<String> uriEx, Expression<String> typeEx, Expression<?> targetObjectEx,
156 Expression<Character> separatorEx, Expression<String> onErrorEx, Expression<String> encodingEx,
157 Expression<Boolean> optimizeEx, Expression<Boolean> invalidateEx, Expression<?> assertionEx) {
158 this.evaluate = evaluate;
159 this.idEx = idEx;
160 this.textEx = textEx;
161 this.uriEx = uriEx;
162 this.typeEx = typeEx;
163 this.targetObjectEx = targetObjectEx;
164 this.separatorEx = separatorEx;
165 this.onErrorEx = onErrorEx;
166 this.encodingEx = encodingEx;
167 this.optimizeEx = optimizeEx;
168 this.invalidateEx = invalidateEx;
169 this.assertionEx = assertionEx;
170 }
171
172
173
174
175
176
177 public Expression<String> getTextEx() {
178 return textEx;
179 }
180
181 @Override
182 public boolean execute(BeneratorContext context) {
183 try {
184 String onErrorValue = ExpressionUtil.evaluate(onErrorEx, context);
185 if (onErrorValue == null) {
186 onErrorValue = "fatal";
187 }
188
189 String typeValue = ExpressionUtil.evaluate(typeEx, context);
190
191 String uriValue = ExpressionUtil.evaluate(uriEx, context);
192 if (typeEx == null && uriEx != null) {
193 typeValue = mapExtensionOf(uriValue);
194 if ("winshell".equals(typeValue)) {
195 if (!SystemInfo.isWindows()) {
196 throw new ConfigurationError("Need Windows to run file: " + uriValue);
197 } else {
198 typeValue = SHELL;
199 }
200 } else if ("unixshell".equals(typeValue)) {
201 if (SystemInfo.isWindows()) {
202 throw new ConfigurationError("Need Unix system to run file: " + uriValue);
203 } else {
204 typeValue = SHELL;
205 }
206 }
207 }
208 if (uriValue != null) {
209 uriValue = context.resolveRelativeUri(uriValue);
210 }
211 Object targetObject = ExpressionUtil.evaluate(targetObjectEx, context);
212 if (typeValue == null && targetObject instanceof DBSystem) {
213 typeValue = "sql";
214 }
215 if (typeValue == null && targetObject instanceof StorageSystem) {
216 typeValue = "execute";
217 }
218 String encoding = ExpressionUtil.evaluate(encodingEx, context);
219
220
221 Object result = null;
222 String text = ExpressionUtil.evaluate(textEx, context);
223 if ("sql".equals(typeValue)) {
224 Character separator = ExpressionUtil.evaluate(separatorEx, context);
225 if (separator == null) {
226 separator = ';';
227 }
228 boolean optimize = (optimizeEx != null ? optimizeEx.evaluate(context) : false);
229 Boolean invalidate = (invalidateEx != null ? invalidateEx.evaluate(context) : null);
230 DBExecutionResult executionResult = runSql(uriValue, targetObject, onErrorValue, encoding,
231 text, separator, optimize, invalidate);
232 result = (executionResult != null ? executionResult.result : null);
233 } else if (SHELL.equals(typeValue)) {
234 result = runShell(uriValue, text, onErrorValue);
235 } else if ("execute".equals(typeValue)) {
236 result = ((StorageSystem) targetObject).execute(text);
237 } else {
238 if (typeValue == null) {
239 typeValue = context.getDefaultScript();
240 }
241 if (!StringUtil.isEmpty(uriValue)) {
242 text = IOUtil.getContentOfURI(uriValue);
243 }
244 result = runScript(text, typeValue, onErrorValue, context);
245 }
246 context.setGlobal("result", result);
247 Object assertionValue = ExpressionUtil.evaluate(assertionEx, context);
248 if (assertionValue instanceof String) {
249 assertionValue = LiteralParser.parse((String) assertionValue);
250 }
251 if (assertionValue != null && !(assertionValue instanceof String && ((String) assertionValue).length() == 0)) {
252 if (assertionValue instanceof Boolean) {
253 if (!(Boolean) assertionValue) {
254 getErrorHandler(onErrorValue).handleError("Assertion failed: '" + assertionEx + "'");
255 }
256 } else {
257 if (!BeanUtil.equalsIgnoreType(assertionValue, result)) {
258 getErrorHandler(onErrorValue).handleError("Assertion failed. Expected: '" + assertionValue + "', found: '" + result + "'");
259 }
260 }
261 }
262 String idValue = ExpressionUtil.evaluate(idEx, context);
263 if (idValue != null) {
264 context.setGlobal(idValue, result);
265 }
266 return true;
267 } catch (ConversionException | IOException e) {
268 throw new ConfigurationError(e);
269 }
270 }
271
272 private static String mapExtensionOf(String uri) {
273 String lcUri = uri.toLowerCase();
274 for (Entry<String, String> entry : extensionMap.entrySet()) {
275 if (lcUri.endsWith(entry.getKey())) {
276 return entry.getValue();
277 }
278 }
279 return null;
280 }
281
282 private ErrorHandler getErrorHandler(String level) {
283 return new ErrorHandler(getClass().getName(), Level.valueOf(level));
284 }
285
286 private Object runScript(String text, String type, String onError, Context context) {
287 ErrorHandler errorHandler = new ErrorHandler(getClass().getName(),
288 Level.valueOf(onError));
289 try {
290 Script script = ScriptUtil.parseScriptText(text, type);
291 return script.evaluate(context);
292 } catch (Exception e) {
293 errorHandler.handleError("Error in script evaluation", e);
294 return null;
295 }
296 }
297
298 private Object runShell(String uri, String text, String onError) {
299 ErrorHandler errorHandler = new ErrorHandler(getClass().getName(), Level.valueOf(onError));
300 StringWriter writer = new StringWriter();
301 if (text != null) {
302 ShellUtil.runShellCommands(new ReaderLineIterator(new StringReader(text)), writer, errorHandler);
303 } else if (uri != null) {
304 ShellUtil.runShellCommand(uri, writer, errorHandler);
305 } else {
306 throw new ConfigurationError("At least uri or text must be provided in <execute> and <evaluate>");
307 }
308 String output = writer.toString();
309 System.out.println(output);
310 return LiteralParser.parse(output);
311 }
312
313 private DBExecutionResult runSql(String uri, Object targetObject, String onError,
314 String encoding, String text, char separator, boolean optimize, Boolean invalidate) {
315 if (targetObject == null) {
316 throw new ConfigurationError("Please specify the 'target' database to execute the SQL script");
317 }
318 Assert.instanceOf(targetObject, DBSystem.class, "target");
319 DBSystem="../../../../../com/rapiddweller/platform/db/DBSystem.html#DBSystem">DBSystem db = (DBSystem) targetObject;
320 if (uri != null) {
321 logger.info("Executing script " + uri);
322 } else if (text != null) {
323 logger.info("Executing inline script");
324 } else {
325 throw new TaskException("No uri or content");
326 }
327 Connection connection = null;
328 DBExecutionResult result = null;
329 ErrorHandler errorHandler = new ErrorHandler(LogCategoriesConstants.SQL, Level.valueOf(onError));
330 try {
331 connection = db.getConnection();
332 if (text != null) {
333 result = DBUtil.executeScript(text, separator, connection, optimize, errorHandler);
334 } else {
335 result = DBUtil.executeScriptFile(uri, encoding, separator, connection, optimize, errorHandler);
336 }
337 if (Boolean.TRUE.equals(invalidate) || (invalidate == null && !evaluate && result.changedStructure)) {
338 db.invalidate();
339 }
340 } catch (Exception sqle) {
341 if (connection != null) {
342 try {
343 connection.rollback();
344 } catch (SQLException e) {
345
346 }
347 }
348 errorHandler.handleError("Error in SQL script execution", sqle);
349 }
350 return result;
351 }
352
353 }