summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Interpreter.java
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Interpreter.java')
-rw-r--r--Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Interpreter.java458
1 files changed, 458 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Interpreter.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Interpreter.java
new file mode 100644
index 00000000000..7c8f6e3928a
--- /dev/null
+++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Interpreter.java
@@ -0,0 +1,458 @@
+/**
+ * Arara, the cool TeX automation tool
+ * Copyright (c) 2012 -- 2018, Paulo Roberto Massa Cereda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the project's author nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.github.cereda.arara.model;
+
+import com.github.cereda.arara.controller.ConfigurationController;
+import com.github.cereda.arara.controller.LanguageController;
+import com.github.cereda.arara.utils.CommonUtils;
+import com.github.cereda.arara.utils.DisplayUtils;
+import com.github.cereda.arara.utils.InterpreterUtils;
+import com.github.cereda.arara.utils.Methods;
+import com.github.cereda.arara.utils.RuleUtils;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.mvel2.templates.TemplateRuntime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Interprets the list of directives.
+ * @author Paulo Roberto Massa Cereda
+ * @version 4.0
+ * @since 4.0
+ */
+public class Interpreter {
+
+ // the application messages obtained from the
+ // language controller
+ private static final LanguageController messages =
+ LanguageController.getInstance();
+
+ // the class logger obtained from
+ // the logger factory
+ private static final Logger logger =
+ LoggerFactory.getLogger(Interpreter.class);
+
+ // list of directives to be
+ // interpreted in here
+ private List<Directive> directives;
+
+ /**
+ * Sets the list of directives.
+ * @param directives The list of directives.
+ */
+ public void setDirectives(List<Directive> directives) {
+ this.directives = directives;
+ }
+
+ /**
+ * Executes each directive, throwing an exception if something bad has
+ * happened.
+ * @throws AraraException Something wrong happened, to be caught in the
+ * higher levels.
+ */
+ public void execute() throws AraraException {
+
+ for (Directive directive : directives) {
+
+ logger.info(
+ messages.getMessage(
+ Messages.LOG_INFO_INTERPRET_RULE,
+ directive.getIdentifier()
+ )
+ );
+
+ ConfigurationController.getInstance().
+ put("execution.file",
+ directive.getParameters().get("reference")
+ );
+ File file = getRule(directive);
+
+ logger.info(
+ messages.getMessage(
+ Messages.LOG_INFO_RULE_LOCATION,
+ file.getParent()
+ )
+ );
+
+ ConfigurationController.getInstance().
+ put("execution.info.rule.id", directive.getIdentifier());
+ ConfigurationController.getInstance().
+ put("execution.info.rule.path", file.getParent());
+ ConfigurationController.getInstance().
+ put("execution.directive.lines",
+ directive.getLineNumbers()
+ );
+ ConfigurationController.getInstance().
+ put("execution.directive.reference",
+ directive.getParameters().get("reference")
+ );
+
+ Rule rule = parseRule(file, directive);
+ Map<String, Object> parameters = parseArguments(rule, directive);
+ Methods.addRuleMethods(parameters);
+
+ String name = rule.getName();
+ List<String> authors = rule.getAuthors() == null ?
+ new ArrayList<String>() : rule.getAuthors();
+ ConfigurationController.getInstance().
+ put("execution.rule.arguments",
+ InterpreterUtils.getRuleArguments(rule)
+ );
+
+ Evaluator evaluator = new Evaluator();
+
+ boolean available = true;
+ if (InterpreterUtils.
+ runPriorEvaluation(directive.getConditional())) {
+ available = evaluator.evaluate(directive.getConditional());
+ }
+
+ if (available) {
+
+ do {
+
+ List<RuleCommand> commands = rule.getCommands();
+ for (RuleCommand command : commands) {
+ String closure = command.getCommand();
+ Object result = null;
+ try {
+ result = TemplateRuntime.eval(closure, parameters);
+ } catch (RuntimeException exception) {
+ throw new AraraException(
+ CommonUtils.getRuleErrorHeader().concat(
+ messages.getMessage(
+ Messages.ERROR_INTERPRETER_COMMAND_RUNTIME_ERROR
+ )
+ ),
+ exception
+ );
+ }
+
+ List<Object> execution = new ArrayList<Object>();
+ if (CommonUtils.checkClass(List.class, result)) {
+ execution = CommonUtils.flatten((List<?>) result);
+ } else {
+ execution.add(result);
+ }
+
+ for (Object current : execution) {
+
+ if (current == null) {
+ throw new AraraException(
+ CommonUtils.getRuleErrorHeader().concat(
+ messages.getMessage(
+ Messages.ERROR_INTERPRETER_NULL_COMMAND
+ )
+ )
+ );
+ } else {
+
+ if (!CommonUtils.checkEmptyString(
+ String.valueOf(current))) {
+
+ DisplayUtils.printEntry(name,
+ command.getName() == null ?
+ messages.getMessage(
+ Messages.INFO_LABEL_UNNAMED_TASK
+ )
+ : command.getName()
+ );
+ boolean success = true;
+
+ if (CommonUtils.checkClass(
+ Trigger.class, current)) {
+ if (((Boolean) ConfigurationController.
+ getInstance().
+ get("execution.dryrun")) == false) {
+ if (((Boolean) ConfigurationController.
+ getInstance().
+ get("execution.verbose")) == true) {
+ DisplayUtils.wrapText(
+ messages.getMessage(
+ Messages.INFO_INTERPRETER_VERBOSE_MODE_TRIGGER_MODE
+ )
+ );
+ }
+ } else {
+ DisplayUtils.printAuthors(authors);
+ DisplayUtils.wrapText(
+ messages.getMessage(
+ Messages.INFO_INTERPRETER_DRYRUN_MODE_TRIGGER_MODE
+ )
+ );
+ DisplayUtils.printConditional(
+ directive.getConditional()
+ );
+ }
+ Trigger trigger = (Trigger) current;
+ trigger.process();
+ } else {
+ Object representation =
+ CommonUtils.checkClass(
+ Command.class,
+ current
+ ) ?
+ current
+ : String.valueOf(current);
+ logger.info(
+ messages.getMessage(
+ Messages.LOG_INFO_SYSTEM_COMMAND,
+ representation
+ )
+ );
+
+ if (((Boolean) ConfigurationController.
+ getInstance().
+ get("execution.dryrun")) == false) {
+ int code = InterpreterUtils.
+ run(representation);
+ Object check = null;
+ try {
+ Map<String, Object> context =
+ new HashMap<String, Object>();
+ context.put("value", code);
+ check = TemplateRuntime.eval(
+ "@{ ".concat(
+ command.getExit() == null ?
+ "value == 0"
+ : command.getExit()).concat(" }"),
+ context);
+ } catch (RuntimeException exception) {
+ throw new AraraException(
+ CommonUtils.getRuleErrorHeader().
+ concat(
+ messages.getMessage(
+ Messages.ERROR_INTERPRETER_EXIT_RUNTIME_ERROR
+ )
+ ),
+ exception
+ );
+ }
+ if (CommonUtils.
+ checkClass(
+ Boolean.class,
+ check)) {
+ success = (Boolean) check;
+ } else {
+ throw new AraraException(
+ CommonUtils.getRuleErrorHeader().concat(
+ messages.getMessage(
+ Messages.ERROR_INTERPRETER_WRONG_EXIT_CLOSURE_RETURN
+ )
+ )
+ );
+ }
+ } else {
+ DisplayUtils.printAuthors(authors);
+ DisplayUtils.wrapText(
+ messages.getMessage(
+ Messages.INFO_INTERPRETER_DRYRUN_MODE_SYSTEM_COMMAND,
+ representation
+ )
+ );
+ DisplayUtils.printConditional(
+ directive.getConditional()
+ );
+ }
+ }
+
+ DisplayUtils.printEntryResult(success);
+
+ if (((Boolean) ConfigurationController.
+ getInstance().get("trigger.halt"))
+ || (((Boolean) ConfigurationController.
+ getInstance().
+ get("execution.errors.halt")
+ && !success))) {
+ return;
+ }
+ }
+ }
+ }
+ }
+ } while (evaluator.evaluate(directive.getConditional()));
+ }
+ }
+ }
+
+ /**
+ * Gets the rule according to the provided directive.
+ * @param directive The provided directive.
+ * @return The absolute canonical path of the rule, given the provided
+ * directive.
+ * @throws AraraException Something wrong happened, to be caught in the
+ * higher levels.
+ */
+ private File getRule(Directive directive) throws AraraException {
+ File file = InterpreterUtils.buildRulePath(directive.getIdentifier());
+ if (file == null) {
+ throw new AraraException(
+ messages.getMessage(
+ Messages.ERROR_INTERPRETER_RULE_NOT_FOUND,
+ directive.getIdentifier(),
+ CommonUtils.getCollectionElements(
+ CommonUtils.getAllRulePaths(),
+ "(",
+ ")",
+ "; "
+ )
+ )
+ );
+ } else {
+ return file;
+ }
+ }
+
+ /**
+ * Parses the rule against the provided directive.
+ * @param file The file representing the rule.
+ * @param directive The directive to be analyzed.
+ * @return A rule object.
+ * @throws AraraException Something wrong happened, to be caught in the
+ * higher levels.
+ */
+ private Rule parseRule(File file, Directive directive)
+ throws AraraException {
+ return RuleUtils.parseRule(file, directive.getIdentifier());
+ }
+
+ /**
+ * Parses the rule arguments against the provided directive.
+ * @param rule The rule object.
+ * @param directive The directive.
+ * @return A map containing all arguments resolved according to the
+ * directive parameters.
+ * @throws AraraException Something wrong happened, to be caught in the
+ * higher levels.
+ */
+ private Map<String, Object> parseArguments(Rule rule, Directive directive)
+ throws AraraException {
+
+ List<Argument> arguments = rule.getArguments();
+
+ Set<String> unknown = CommonUtils.
+ getUnknownKeys(directive.getParameters(), arguments);
+ unknown.remove("file");
+ unknown.remove("reference");
+ if (!unknown.isEmpty()) {
+ throw new AraraException(
+ CommonUtils.getRuleErrorHeader().concat(
+ messages.getMessage(
+ Messages.ERROR_INTERPRETER_UNKNOWN_KEYS,
+ CommonUtils.getCollectionElements(
+ unknown,
+ "(",
+ ")",
+ ", "
+ )
+ )
+ )
+ );
+ }
+
+ Map<String, Object> mapping = new HashMap<String, Object>();
+ mapping.put("file", directive.getParameters().get("file"));
+ mapping.put("reference", directive.getParameters().get("reference"));
+
+ Map<String, Object> context = new HashMap<String, Object>();
+ context.put("parameters", directive.getParameters());
+ context.put("file", directive.getParameters().get("file"));
+ context.put("reference", directive.getParameters().get("reference"));
+ Methods.addRuleMethods(context);
+
+ for (Argument argument : arguments) {
+ if ((argument.isRequired()) &&
+ (!directive.getParameters().containsKey(
+ argument.getIdentifier()))) {
+ throw new AraraException(
+ CommonUtils.getRuleErrorHeader().concat(
+ messages.getMessage(
+ Messages.ERROR_INTERPRETER_ARGUMENT_IS_REQUIRED,
+ argument.getIdentifier()
+ )
+ )
+ );
+ }
+
+ if (argument.getDefault() != null) {
+ try {
+ Object result = TemplateRuntime.
+ eval(argument.getDefault(), context);
+ mapping.put(argument.getIdentifier(), result);
+ } catch (RuntimeException exception) {
+ throw new AraraException(
+ CommonUtils.getRuleErrorHeader().
+ concat(messages.getMessage(
+ Messages.ERROR_INTERPRETER_DEFAULT_VALUE_RUNTIME_ERROR
+ )
+ ),
+ exception
+ );
+ }
+ } else {
+ mapping.put(argument.getIdentifier(), "");
+ }
+
+ if ((argument.getFlag() != null) &&
+ (directive.getParameters().containsKey(
+ argument.getIdentifier()))) {
+
+ try {
+ Object result = TemplateRuntime.eval(
+ argument.getFlag(),
+ context
+ );
+ mapping.put(argument.getIdentifier(), result);
+ } catch (RuntimeException exception) {
+ throw new AraraException(CommonUtils.getRuleErrorHeader().
+ concat(
+ messages.getMessage(
+ Messages.ERROR_INTERPRETER_FLAG_RUNTIME_EXCEPTION
+ )
+ ),
+ exception
+ );
+ }
+ }
+ }
+
+ return mapping;
+ }
+
+}