diff options
Diffstat (limited to 'Master/texmf-dist/source/support/arara/src/main/java/com/github')
62 files changed, 9344 insertions, 4711 deletions
diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/Arara.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/Arara.java deleted file mode 100644 index 48335eaf879..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/Arara.java +++ /dev/null @@ -1,196 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * Arara: The main class. Basically, this class will get the file name from the - * arguments list and call the proper methods from the other helper classes. - */ -// package definition -package com.github.arara; - -// needed imports -import com.github.arara.model.AraraDirective; -import com.github.arara.utils.*; -import java.io.File; -import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The main arara class. The code logic is encapsulated in the helper class, so - * if something goes wrong, the generic exception catch here will simply print - * it. I tried to make the code as easier as possible. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 1.0 - */ -public class Arara { - - // the logger - final static Logger logger = LoggerFactory.getLogger(Arara.class); - // the localization class - final static AraraLocalization localization = AraraLocalization.getInstance(); - - /** - * The main method. The idea is to provide to arara only the supported file - * name and let it handle. The application will remove the file extension - * (if any) and call the other helper classes. - * - * @param args The command line arguments. In fact, arara supports a lot of - * flags, all listed in the CommandLineAnalyzer. - */ - public static void main(String[] args) { - - // the application status, zero for a normal execution, - // or nonzero for an abnormal execution - int exitStatus; - - // trying to have a normal execution - try { - - // print the application header - AraraUtils.printHeader(); - - // create a configuration instance and load - // the proper settings, if any - ConfigurationLoader configuration = new ConfigurationLoader(); - configuration.load(); - - // create a new analyzer - CommandLineAnalyzer commandLine = new CommandLineAnalyzer(args, configuration); - - // if the minimum parameters are not satisfied or it's a simple - // help or version request - if (!commandLine.parse()) { - - // simply return - exitStatus = 0; - - // exit right now, good job - System.exit(exitStatus); - } - - // it's a normal workflow, let's define the main file - File file; - - // create a new file reference - file = new File(commandLine.getFile()); - - // welcome message - logger.info(localization.getMessage("Log_WelcomeMessage")); - - // process file - logger.info(localization.getMessage("Log_ProcessingFile", file.getName())); - - // file exists, let's proceed with the directive extractor - DirectiveExtractor dirExtractor = new DirectiveExtractor(file, configuration); - - // extract all directives from the file - dirExtractor.extract(); - - // get all directives found - List<AraraDirective> directives = dirExtractor.getDirectives(); - - // set the overall result flag - boolean overallResult = true; - - // check if any directive was found - if (!directives.isEmpty()) { - - // now let's parse the directives - DirectiveParser dirParser = new DirectiveParser(directives); - - // set the file - dirParser.setFile(file); - - // parse the directives - TaskDeployer taskDeployer = new TaskDeployer(dirParser.parse(), configuration); - - // deploy the tasks through a command trigger - CommandTrigger commandTrigger = new CommandTrigger(taskDeployer.deploy()); - - // set verbose option, if enabled - commandTrigger.setVerbose(commandLine.isVerbose()); - - // set an execution timeout, if set - commandTrigger.setExecutionTimeout(commandLine.getExecutionTimeout()); - - // execute the tasks - overallResult = commandTrigger.execute(); - } - else { - - // no directives found, add message to the log - logger.info(localization.getMessage("Log_NoDirectivesFound", file.getName())); - - // print message - System.out.println(AraraUtils.wrap(localization.getMessage("Msg_NoDirectivesFound", file.getName()))); - } - - // final message - logger.info(localization.getMessage("Log_Done")); - - // if everything was ok, that is, every command in the command list - // returned with an exit status of zero - if (overallResult) { - - // everything fine - exitStatus = 0; - - } else { - - // something wrong happened, so let's consider the whole - // execution as abnormal - exitStatus = 1; - } - - } catch (Exception exception) { - - // something bad happened, print the error message - System.out.println(AraraUtils.wrap(exception.getMessage())); - - // catch error in the log - logger.error(localization.getMessage("Log_ExceptionRaised")); - logger.error(exception.getMessage()); - - // error, set status to an abnormal execution - exitStatus = 1; - - } - - // send the exit code to the terminal, and we are done - System.exit(exitStatus); - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraConfiguration.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraConfiguration.java deleted file mode 100644 index f65c36e447b..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraConfiguration.java +++ /dev/null @@ -1,221 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * AraraConfiguration: This class holds the model for the arara configuration - * file. - */ -// package definition -package com.github.arara.model; - -// needed imports -import com.github.arara.exception.AraraException; -import com.github.arara.utils.AraraUtils; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import org.apache.commons.lang3.SystemUtils; -import org.mvel2.templates.TemplateRuntime; - -/** - * Holds the model for the arara configuration file. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 - */ -public class AraraConfiguration { - - // the application language - private String language; - // the list of search paths - private List<String> paths; - // the list of filetypes - private List<AraraFilePattern> filetypes; - // the path runtime exception - private RuntimeException pathRuntimeException; - // the path IO exception - private IOException pathIOException; - - /** - * Getter for the search paths. - * - * @return The search paths. - */ - public List<String> getPaths() { - return paths; - } - - /** - * Getter for the language. - * - * @return The language. - */ - public String getLanguage() { - return language; - } - - /** - * Setter for the language. - * - * @param language The language. - */ - public void setLanguage(String language) { - this.language = language; - } - - /** - * Setter for the search paths. - * - * @param rules The search paths. - */ - public void setPaths(List<String> rules) throws AraraException, Exception { - this.paths = rules; - - // refresh paths - refreshPaths(); - } - - /** - * Getter for the filetypes. - * - * @return The filetypes. - */ - public List<AraraFilePattern> getFiletypes() { - return filetypes; - } - - /** - * Setter for the filetypes. - * - * @param filetypes The filetypes. - */ - public void setFiletypes(List<AraraFilePattern> filetypes) { - this.filetypes = filetypes; - } - - /** - * Constructor. - */ - public AraraConfiguration() { - - // creates both lists - paths = new ArrayList<String>(); - filetypes = new ArrayList<AraraFilePattern>(); - pathRuntimeException = null; - } - - /** - * Refreshes all paths, replacing possible variables in the template - */ - private void refreshPaths() throws AraraException, Exception { - - // create a map - HashMap map = new HashMap(); - - // add the variables - map.put("userhome", SystemUtils.USER_HOME); - - // for every path in the list - for (int i = 0; i < paths.size(); i++) { - - try { - - // remove the keyword - String fullPath = AraraUtils.removeKeyword(paths.get(i)); - - // apply the template - fullPath = (String) TemplateRuntime.eval(fullPath, map); - - try { - - // attempt to create a file reference and - // get the canonical path, if the operation - // succeeds, it's a valid path - File validFile = new File(fullPath); - validFile.getCanonicalPath(); - - // sanitize the path in order to be displayed correctly - fullPath = new File(new File(fullPath).toURI()).getPath(); - - // set the path in the list - paths.set(i, fullPath); - - } catch (IOException ioException) { - - // the path is terribly invalid, get the exception, - // if null - if (pathIOException == null) { - - // set the path IO exception - pathIOException = ioException; - } - } - - } catch (RuntimeException runtimeException) { - - // an error has occurred, register the exception for - // later access - - // if there isn't an exception yet - if (pathRuntimeException == null) { - - // set the exception - pathRuntimeException = runtimeException; - } - - } - } - } - - /** - * Getter for the path runtime exception. - * - * @return The path runtime exception. - */ - public RuntimeException getPathRuntimeException() { - return pathRuntimeException; - } - - /** - * Getter for the path IO exception. - * - * @return The path IO exception. - */ - public IOException getPathIOException() { - return pathIOException; - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraDirective.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraDirective.java deleted file mode 100644 index 5dc8842456b..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraDirective.java +++ /dev/null @@ -1,148 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * AraraDirective: This class provides the model for representing the arara - * directives found in the source file. It's a plain old Java object. - */ -// package definition -package com.github.arara.model; - -// needed imports -import java.util.Map; - -/** - * Provides the model for representing the arara directives found in the source - * file. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 1.0 - */ -public class AraraDirective { - - // the directive name - private String name; - // the configuration - private Map config; - // the line number - private int lineNumber = 0; - - /** - * Constructor. - * - * @param name The directive name. - * @param config The configuration. - */ - public AraraDirective(String name, Map config) { - - // set the name - this.name = name; - - // set the configuration - this.config = config; - } - - /** - * Constructor. - */ - public AraraDirective() { - } - - /** - * Getter for configuration. - * - * @return The configuration. - */ - public Map getConfig() { - - // return it - return config; - } - - /** - * Setter for configuration. - * - * @param config The configuration. - */ - public void setConfig(Map config) { - - // set the configuration - this.config = config; - } - - /** - * Getter for the directive name. - * - * @return The directive name. - */ - public String getName() { - - // return it - return name; - } - - /** - * Setter for the directive name. - * - * @param name The directive name. - */ - public void setName(String name) { - - // set it - this.name = name; - } - - /** - * Getter for the line number. - * - * @return The line number. - */ - public int getLineNumber() { - - // return it - return lineNumber; - } - - /** - * Setter for the line number. - * - * @param lineNumber The line number. - */ - public void setLineNumber(int lineNumber) { - - // set it - this.lineNumber = lineNumber; - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraLanguage.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraLanguage.java deleted file mode 100644 index b04e9850236..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraLanguage.java +++ /dev/null @@ -1,137 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * AraraLanguage: This class holds the data model for the arara language - * specification. - */ -// package definition. -package com.github.arara.model; - -// needed import -import java.util.Locale; - -/** - * Holds the data model for the arara language specification. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 - */ -public class AraraLanguage { - - // language name - private String name; - // language code - private String code; - // language locale - private Locale locale; - - /** - * Getter for the language name. - * - * @return The language name. - */ - public String getName() { - return name; - } - - /** - * Setter for the language name. - * - * @param name The language name. - */ - public void setName(String name) { - this.name = name; - } - - /** - * Getter for the language code. - * - * @return The language code. - */ - public String getCode() { - return code; - } - - /** - * Setter for the language code. - * - * @param code The language code. - */ - public void setCode(String code) { - this.code = code; - } - - /** - * Getter for the language locale. - * - * @return The language locale. - */ - public Locale getLocale() { - return locale; - } - - /** - * Setter for the language locale. - * - * @param locale The language locale. - */ - public void setLocale(Locale locale) { - this.locale = locale; - } - - /** - * Constructor. - * - * @param name The language name. - * @param code The language code. - * @param locale The language locale. - */ - public AraraLanguage(String name, String code, Locale locale) { - this.name = name; - this.code = code; - this.locale = locale; - } - - /** - * Returns a string representation of the object. - * - * @return The string representation of the object. - */ - @Override - public String toString() { - return name.concat(" [").concat(code).concat("]"); - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraRuleConfig.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraRuleConfig.java deleted file mode 100644 index 5ebe9382bf0..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraRuleConfig.java +++ /dev/null @@ -1,223 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * PlainAraraRuleConfig: This class provides the model for representing a plain - * Arara rule configuration based on the YAML files. It's a plain old Java - * object. - */ -// package definition -package com.github.arara.model; - -// needed imports -import com.github.arara.utils.AraraUtils; -import java.util.ArrayList; -import java.util.List; - -/** - * Provides the model for representing a plain Arara rule configuration based on - * the YAML files. This class will be used to map YAML rules into Java objects. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 1.0 - */ -public class AraraRuleConfig { - - // the rule identifier - private String identifier; - // the rule name - private String name; - // the rule command - private String command; - // the rule commands - private List<String> commands; - // the arguments list - private List<AraraRuleArgument> arguments; - - public List<String> getCommands() { - return commands; - } - - /** - * Setter for the rule commands. - * - * @param commands A list containing the rule commands. - */ - public void setCommands(List<String> commands) { - this.commands = commands; - - // for every entry - for (int i = 0; i < commands.size(); i++) { - - // remove keyword and reinsert into the list - String currentCommand = AraraUtils.removeKeyword(commands.get(i)); - commands.set(i, currentCommand); - } - } - - /** - * Getter for the rule identifier. - * - * @return The rule identifier. - */ - public String getIdentifier() { - - // return it - return identifier; - } - - /** - * Setter for the rule identifier. - * - * @param identifier The rule identifier. - */ - public void setIdentifier(String identifier) { - - // set the identifier - this.identifier = identifier; - } - - /** - * Getter for the rule name. - * - * @return The rule name. - */ - public String getName() { - - // return it - return name; - } - - /** - * Setter for the rule name. - * - * @param name The rule name. - */ - public void setName(String name) { - - // set the rule name - this.name = name; - } - - /** - * Getter for the rule command. - * - * @return The rule command. - */ - public String getCommand() { - - // return it - return command; - } - - /** - * Setter for the rule command. - * - * @param command The rule command. - */ - public void setCommand(String command) { - - // set the command - this.command = AraraUtils.removeKeyword(command); - } - - /** - * Getter for the arguments list. - * - * @return The arguments list. - */ - public List<AraraRuleArgument> getArguments() { - - // return the list - return arguments; - } - - /** - * Setter for the arguments list. - * - * @param arguments The arguments list. - */ - public void setArguments(List<AraraRuleArgument> arguments) { - - // set the list - this.arguments = arguments; - } - - /** - * Returns a list containing all argument identifiers. - * - * @return A list containing all argument identifiers. - */ - public List<String> getIdentifiersList() { - - // create a new list - List<String> result = new ArrayList<String>(); - - // for every argument - for (AraraRuleArgument argument : getArguments()) { - - // add identifier - result.add(argument.getIdentifier()); - } - - // return list - return result; - } - - /** - * Returns the forbidden identifier, if any. - * - * @return The forbidden identifier, if any. - */ - public String checkForForbiddenIdentifiers() { - - // for every argument - for (AraraRuleArgument argument : getArguments()) { - - // get the current argument value - String value = argument.getIdentifier().toLowerCase(); - - // check if it's a forbidden argument identifier - if ((value.equals("file")) || (value.equals("files")) || (value.equals("item")) || (value.equals("items"))) { - - // return the value - return value; - } - } - - // nothing wrong was found - return null; - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraConstants.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraConstants.java deleted file mode 100644 index 38a931f1119..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraConstants.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * AraraConstants: This class contains all the constants used in the main - * application. - */ -// package definition -package com.github.arara.utils; - -/** - * Contains all the constants used in the main application. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 - */ -public class AraraConstants { - - /** - * The arara version. - */ - public static final String VERSION = "3.0a"; - /** - * The number of characters per line in messages. - */ - public static final int WRAPLENGTH = 65; - /** - * The name of the default configuration file. - */ - public static final String ARARACONFIG = "araraconfig.yaml"; - /** - * The directive prefix for the pattern matching method. - */ - public static final String DIRECTIVEPREFIX = "arara:\\s"; - /** - * The rule pattern for string reference. - */ - public static final String RULEPATTERN = "^(\\s)*<arara>\\s"; - /** - * The name of the log file generated by arara. - */ - public static final String LOGNAME = "arara"; - /** - * The copyright year. - */ - public static final String COPYRIGHTYEAR = "2012"; - /** - * The variable exception matching pattern. - */ - public static final String VAREXCEPTIONPATTERN = "^\\[Error: could not access: (.*);"; - /** - * The method exception matching pattern. - */ - public static final String METHODEXCEPTIONPATTERN = "^\\[Error: unable to access property \\((.*)\\): (.*)\\]"; - /** - * The full directive matching pattern. - */ - public static final String FULLDIRECTIVEPATTERN = "^\\s*(\\w+)\\s*:\\s*\\{.*\\}\\s*$"; - /** - * The empty directive matching pattern. - */ - public static final String EMPTYDIRECTIVEPATTERN = "^\\s*(\\w+)\\s*$"; - -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraLocalization.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraLocalization.java deleted file mode 100644 index 1b3f093699f..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraLocalization.java +++ /dev/null @@ -1,126 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * AraraLocalization: This class contains a few helper methods in order to ease - * the localization process during the execution. This class is a singleton - * reference. - */ -// package definition -package com.github.arara.utils; - -// needed imports -import java.text.MessageFormat; -import java.util.Locale; -import java.util.ResourceBundle; - -/** - * Contains a few helper methods in order to ease the localization process - * during the execution. This class is a singleton reference. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 - */ -public class AraraLocalization { - - // the singleton reference - private static AraraLocalization selfRef; - // the resource bundle for the whole application - private ResourceBundle resources; - - /** - * Constructs the singleton instance. - */ - private AraraLocalization() { - - // set the self-reference - selfRef = this; - - // instead of relying in the default locale from the - // operating system, always fallback to english - Locale.setDefault(Locale.ENGLISH); - - // get the resource bundle - resources = ResourceBundle.getBundle("com.github.arara.localization.Messages"); - } - - /** - * Provides reference to the singleton object. - * - * @return The singleton instance. - */ - public static final AraraLocalization getInstance() { - - // if there's no current object, call the private constructor - if (selfRef == null) { - selfRef = new AraraLocalization(); - } - - // return the actual object - return selfRef; - } - - /** - * Returns a simple message from the resource bundle. - * - * @param message The message identifier. - * @return A string from the resource bundle. - */ - public String getMessage(String message) { - return resources.getString(message); - } - - /** - * Returns a message containing parameters from the resource bundle. - * - * @param message The message identifier. - * @param parameters A list of parameters to be replaced in the message. - * @return A string from the resource bundle, with the correct parameters. - */ - public String getMessage(String message, Object... parameters) { - return MessageFormat.format(resources.getString(message), parameters); - } - - /** - * Refresh the resource bundle reference, if by any chance, the application - * language is changed in runtime. - */ - public void refresh() { - - // clear cache and reload the resource bundle - // ResourceBundle.clearCache(); // not supported by Java 5 - resources = ResourceBundle.getBundle("com.github.arara.localization.Messages"); - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraLogging.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraLogging.java deleted file mode 100644 index 3cbad2a970c..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraLogging.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * AraraLogging: This class configures the logging features. - */ -// package definition -package com.github.arara.utils; - -// needed imports -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import org.slf4j.LoggerFactory; - -/** - * Configures the logging features. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 - */ -public class AraraLogging { - - public static void enableLogging(boolean enable) { - - // get the context - LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); - - try { - - // create a new configurator - JoranConfigurator configurator = new JoranConfigurator(); - - // set context and reset it - configurator.setContext(loggerContext); - loggerContext.reset(); - - // if logging should be enabled - if (enable) { - - // add the correct properties and load the XML file - loggerContext.putProperty("araraLogName", AraraConstants.LOGNAME); - configurator.doConfigure(AraraLogging.class.getResourceAsStream("/com/github/arara/conf/logback.xml")); - } - - } catch (JoranException joranException) { - // do nothing - } - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraMethods.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraMethods.java deleted file mode 100644 index 239dd4bf7cf..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraMethods.java +++ /dev/null @@ -1,481 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * AraraMethods: This class contains methods for the MVEL expression language to - * be used in the rules. - */ -// package definition -package com.github.arara.utils; - -// needed import -import java.io.File; -import org.apache.commons.lang3.SystemUtils; - -/** - * Contains methods for the MVEL expression language to be used in the rules. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 - */ -public class AraraMethods { - - /** - * Holds the original filename. - */ - private static String originalFile; - - /** - * Setter for the original filename. - * - * @param originalFile The original filename. - */ - public static void setOriginalFile(String originalFile) { - AraraMethods.originalFile = originalFile; - } - - /** - * Getter for the original filename. - * - * @return A string containing the original filename. - */ - public static String getOriginalFile() { - return originalFile; - } - - /** - * Checks if string is empty. - * - * @param string The string. - * @return A logical value according to the condition. - */ - public static boolean isEmpty(String string) { - return "".equals(string); - } - - /** - * Checks if string is not empty. - * - * @param string The string. - * @return A logical value according to the condition. - */ - public static boolean isNotEmpty(String string) { - return !"".equals(string); - } - - /** - * Checks if string is empty. - * - * @param string The string. - * @param ifTrue Value if true. - * @return A string according the condition. - */ - public static String isEmpty(String string, String ifTrue) { - return ("".equals(string) ? ifTrue : string); - } - - /** - * Checks if string is not empty. - * - * @param string The string. - * @param ifTrue Value if true. - * @return A string according the condition. - */ - public static String isNotEmpty(String string, String ifTrue) { - return (!"".equals(string) ? ifTrue : string); - } - - /** - * Checks if string is empty. - * - * @param string The string. - * @param ifTrue Value if true. - * @param ifFalse Value if false. - * @return A string according the condition. - */ - public static String isEmpty(String string, String ifTrue, String ifFalse) { - return ("".equals(string) ? ifTrue : ifFalse); - } - - /** - * Checks if string is not empty. - * - * @param string The string. - * @param ifTrue Value if true. - * @param ifFalse Value if false. - * @return A string according the condition. - */ - public static String isNotEmpty(String string, String ifTrue, String ifFalse) { - return (!"".equals(string) ? ifTrue : ifFalse); - } - - /** - * Checks if string resolves to a logic value representing true. - * - * @param string The string. - * @return A string according the condition. - */ - public static boolean isTrue(String string) { - string = string.toLowerCase(); - if ((string.equals("yes")) || (string.equals("on")) || (string.equals("true")) || (string.equals("y")) || (string.equals("1"))) { - return true; - } else { - return false; - } - } - - /** - * Checks if string resolves to a logic value representing false. - * - * @param string The string. - * @return A string according the condition. - */ - public static boolean isFalse(String string) { - string = string.toLowerCase(); - if ((string.equals("no")) || (string.equals("off")) || (string.equals("false")) || (string.equals("n")) || (string.equals("0"))) { - return true; - } else { - return false; - } - } - - /** - * Checks if string resolves to a logic value representing true. - * - * @param string The string. - * @param ifTrue Value if true. - * @return A string according the condition. - */ - public static String isTrue(String string, String ifTrue) { - return (isTrue(string) ? ifTrue : ""); - } - - /** - * Checks if string resolves to a logic value representing false. - * - * @param string The string. - * @param ifTrue Value if true. - * @return A string according the condition. - */ - public static String isFalse(String string, String ifTrue) { - return (isFalse(string) ? ifTrue : ""); - } - - /** - * Checks if string resolves to a logic value representing true. - * - * @param string The string. - * @param ifTrue Value if true. - * @param ifFalse Value if false. - * @return A string according the condition. - */ - public static String isTrue(String string, String ifTrue, String ifFalse) { - return (isTrue(string) ? ifTrue : ifFalse); - } - - /** - * Checks if string resolves to a logic value representing false. - * - * @param string The string. - * @param ifTrue Value if true. - * @param ifFalse Value if false. - * @return A string according the condition. - */ - public static String isFalse(String string, String ifTrue, String ifFalse) { - return (isFalse(string) ? ifTrue : ifFalse); - } - - /** - * Checks if string resolves to a logic value representing true. - * - * @param string The string. - * @param ifTrue Value if true. - * @param ifFalse Value if false. - * @param defaultValue Value if the string is neither true or false. - * @return A string according the condition. - */ - public static String isTrue(String string, String ifTrue, String ifFalse, String defaultValue) { - if (isTrue(string)) { - return ifTrue; - } - if (isFalse(string)) { - return ifFalse; - } - return defaultValue; - } - - /** - * Checks if string resolves to a logic value representing false. - * - * @param string The string. - * @param ifTrue Value if true. - * @param ifFalse Value if false. - * @param defaultValue Value if the string is neither true or false. - * @return A string according the condition. - */ - public static String isFalse(String string, String ifTrue, String ifFalse, String defaultValue) { - if (isFalse(string)) { - return ifTrue; - } - if (isTrue(string)) { - return ifFalse; - } - return defaultValue; - } - - /** - * Trim spaces from the string. - * - * @param string The string. - * @return The string with the trailing and leading spaces trimmed. - */ - public static String trimSpaces(String string) { - return string.trim(); - } - - /** - * Returns the filename. - * - * @param f The string. - * @return The filename. - */ - public static String getFilename(String f) { - try { - return (new File(f)).getName(); - } catch (Exception exception) { - return ""; - } - } - - /** - * Returns the base name. - * - * @param f The string. - * @return The base name. - */ - public static String getBasename(String f) { - try { - f = (new File(f)).getName(); - int i = f.lastIndexOf(".") != -1 ? f.lastIndexOf(".") : f.length(); - return f.substring(0, i); - } catch (Exception exception) { - return ""; - } - } - - /** - * Returns the filetype. - * - * @param f The string. - * @return The filetype. - */ - public static String getFiletype(String f) { - try { - f = (new File(f)).getName(); - if (f.lastIndexOf(".") != -1) { - return f.substring(f.lastIndexOf(".") + 1, f.length()); - } - return ""; - } catch (Exception exception) { - return ""; - } - } - - /** - * Returns the directory name. - * - * @param f The string. - * @return The directory name. - */ - public static String getDirname(String f) { - try { - return (new File(f)).getParent(); - } catch (Exception exception) { - return ""; - } - } - - /** - * Checks if the string is a valid existing file. - * - * @param f The string. - * @return A logic value indicating if the string is a valid existing file. - */ - public static boolean isFile(String f) { - try { - return (new File(f)).isFile(); - } catch (Exception exception) { - return false; - } - } - - /** - * Checks if the string is a valid existing directory. - * - * @param f The string. - * @return A logic value indicating if the string is a valid existing - * directory. - */ - public static boolean isDir(String f) { - try { - return (new File(f)).isDirectory(); - } catch (Exception exception) { - return false; - } - } - - /** - * Checks if the operating system is Windows. - * - * @param ifTrue The value if true. - * @param ifFalse The value if false. - * @return A string according the condition. - */ - public static String isWindows(String ifTrue, String ifFalse) { - if (SystemUtils.IS_OS_WINDOWS) { - return ifTrue; - } - else { - return ifFalse; - } - } - - /** - * Checks if the operating system is Linux. - * - * @param ifTrue The value if true. - * @param ifFalse The value if false. - * @return A string according the condition. - */ - public static String isLinux(String ifTrue, String ifFalse) { - if (SystemUtils.IS_OS_LINUX) { - return ifTrue; - } - else { - return ifFalse; - } - } - - /** - * Checks if the operating system is Unix. - * - * @param ifTrue The value if true. - * @param ifFalse The value if false. - * @return A string according the condition. - */ - public static String isUnix(String ifTrue, String ifFalse) { - if (SystemUtils.IS_OS_UNIX) { - return ifTrue; - } - else { - return ifFalse; - } - } - - /** - * Checks if the operating system is Mac. - * - * @param ifTrue The value if true. - * @param ifFalse The value if false. - * @return A string according the condition. - */ - public static String isMac(String ifTrue, String ifFalse) { - if (SystemUtils.IS_OS_MAC) { - return ifTrue; - } - else { - return ifFalse; - } - } - - /** - * Checks if the logic condition is true. - * - * @param value Logic condition to be evaluated. - * @param ifTrue The value if true. - * @return A string according the condition. - */ - public static String isTrue(boolean value, String ifTrue) { - if (value) { - return ifTrue; - } - return ""; - } - - /** - * Checks if the logic condition is true. - * - * @param value Logic condition to be evaluated. - * @param ifTrue The value if true. - * @param ifFalse The value if false. - * @return A string according the condition. - */ - public static String isTrue(boolean value, String ifTrue, String ifFalse) { - if (value) { - return ifTrue; - } - return ifFalse; - } - - /** - * Checks if the logic condition is false. - * - * @param value Logic condition to be evaluated. - * @param ifTrue The value if true. - * @return A string according the condition. - */ - public static String isFalse(boolean value, String ifTrue) { - if (!value) { - return ifTrue; - } - return ""; - } - - /** - * Checks if the logic condition is false. - * - * @param value Logic condition to be evaluated. - * @param ifTrue The value if true. - * @param ifFalse The value if false. - * @return A string according the condition. - */ - public static String isFalse(boolean value, String ifTrue, String ifFalse) { - if (!value) { - return ifTrue; - } - return ifFalse; - } - -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraUtils.java deleted file mode 100644 index 42eaa6c44a2..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraUtils.java +++ /dev/null @@ -1,224 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * AraraUtils: This class contains some helper methods used for general purpose. - */ -// package definition -package com.github.arara.utils; - -// needed imports -import java.util.StringTokenizer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.apache.commons.lang3.text.WordUtils; -import org.yaml.snakeyaml.error.MarkedYAMLException; - -/** - * Contains some helper methods used for general purpose. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 - */ -public class AraraUtils { - - // the localization class - final static AraraLocalization localization = AraraLocalization.getInstance(); - - /** - * Removes the reserved keyword in the strings to be analyzed by the MVEL - * template engine. The keyword is set in AraraConstants. - * - * @param line The line to be analyzed. - * @return The new line without the keyword. - */ - public static String removeKeyword(String line) { - - // set a new pattern and matcher - Pattern pattern = Pattern.compile(AraraConstants.RULEPATTERN); - Matcher matcher = pattern.matcher(line); - - // if the keyword is found - if (matcher.find()) { - - // remove the keyword - line = (line.substring(matcher.end(), line.length())).trim(); - } - - // and return it - return line; - } - - /** - * Prints the arara ASCII header. - */ - public static void printHeader() { - - // print the ASCII art - System.out.println(" __ _ _ __ __ _ _ __ __ _ "); - System.out.println(" / _` | '__/ _` | '__/ _` |"); - System.out.println("| (_| | | | (_| | | | (_| |"); - System.out.println(" \\__,_|_| \\__,_|_| \\__,_|\n"); - - } - - /** - * Wraps the string to several lines, according to the wrap length set in - * the AraraConstants class. - * - * @param message The message to be wrapped. - * @return A new message. - */ - public static String wrap(String message) { - - // create a new tokenizer in order to allow line breaks, so - // every line is processed individually - StringTokenizer tokens = new StringTokenizer(message, "\n", true); - String result = ""; - - // iterate through tokens - while (tokens.hasMoreTokens()) { - - // wrap line according to the wrap length - result = result.concat(WordUtils.wrap(tokens.nextToken(), AraraConstants.WRAPLENGTH)); - } - - // return the result - return result; - } - - /** - * Gets the variable reference from a RuntimeException object. - * @param runtimeException The RuntimeException object. - * - * @return The variable reference name. - */ - public static String getVariableFromException(RuntimeException runtimeException) { - - // set pattern and matcher - Pattern pattern = Pattern.compile(AraraConstants.VAREXCEPTIONPATTERN); - Matcher matcher = pattern.matcher(runtimeException.getMessage()); - - // if the variable is found - if (matcher.find()) { - - // check if it's a valid reference - if (matcher.groupCount() != 0) { - - // return the variable name - return matcher.group(1); - } - - } else { - - // maybe it's a method call, let's investigate - pattern = Pattern.compile(AraraConstants.METHODEXCEPTIONPATTERN); - matcher = pattern.matcher(runtimeException.getMessage()); - - if (matcher.find()) { - - // check if it's a valid reference - if (matcher.groupCount() > 1) { - - // return the method name - return matcher.group(2); - } - - } - - } - - // nothing is found, so return an unknown reference - return "<unknown>"; - } - - /** - * Extracts information from a MarkedYAMLException object. - * - * @param yamlException The exception object. - * @return A string containing all the available information from the - * exception object. - */ - public static String extractInformationFromYAMLException(MarkedYAMLException yamlException) { - StringBuilder stringBuilder = new StringBuilder(); - if (yamlException.getContext() != null) { - stringBuilder.append(localization.getMessage("YamlError_Context", yamlException.getContext())).append("\n"); - } - if (yamlException.getProblem() != null) { - stringBuilder.append(localization.getMessage("YamlError_Problem", yamlException.getProblem())).append("\n"); - } - if (yamlException.getProblemMark() != null) { - stringBuilder.append(localization.getMessage("YamlError_ErrorLocation", yamlException.getProblemMark().getLine(), yamlException.getProblemMark().getColumn())).append("\n"); - } - if (yamlException.getProblemMark().get_snippet() != null) { - stringBuilder.append(yamlException.getProblemMark().get_snippet()); - } - return stringBuilder.toString(); - } - - /** - * Checks if the line contains a valid full directive. - * - * @param line The current line. - * @return A logic value indicating if a valid directive was found. - */ - public static boolean checkForFullDirective(String line) { - Pattern pattern = Pattern.compile(AraraConstants.FULLDIRECTIVEPATTERN); - Matcher m = pattern.matcher(line); - if (m.find()) { - return true; - } - else { - return false; - } - } - - /** - * Checks if the line contains a valid empty directive. - * - * @param line The current line. - * @return A logic value indicating if a valid directive was found. - */ - public static boolean checkForEmptyDirective(String line) { - Pattern pattern = Pattern.compile(AraraConstants.EMPTYDIRECTIVEPATTERN); - Matcher m = pattern.matcher(line); - if (m.find()) { - return true; - } - else { - return false; - } - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/CommandLineAnalyzer.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/CommandLineAnalyzer.java deleted file mode 100644 index 8cf0d2e9122..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/CommandLineAnalyzer.java +++ /dev/null @@ -1,488 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * CommandLineAnalyzer: This class implements a command line parser to provide - * better control of flags and files to process. - */ -// package definition -package com.github.arara.utils; - -// needed import -import java.io.File; -import org.apache.commons.cli.*; - -/** - * Implements a command line parser to provide better control of flags and files - * to process. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 1.0 - */ -public class CommandLineAnalyzer { - - // the file to process - private String theFile; - // the command line arguments - private String[] theArgs; - // the command line options - private Options commandLineOptions; - // the verbose option - private boolean showVerboseOutput; - // the execution timeout, - // in milliseconds - private long executionTimeout; - // the configuration - private ConfigurationLoader configuration; - // the localization class - final static AraraLocalization localization = AraraLocalization.getInstance(); - - /** - * Constructor. - * - * @param theArgs The command line arguments. - * @param configuration The current configuration. - */ - public CommandLineAnalyzer(String[] theArgs, ConfigurationLoader configuration) { - - // set the array - this.theArgs = theArgs; - - // set the configuration - this.configuration = configuration; - - // create new options - commandLineOptions = new Options(); - - // set the default value to the output - showVerboseOutput = false; - - } - - /** - * Parses the command line arguments and provides feedback to the main - * class. - * - * @return A boolean value if there is a file to be processed by Arara. - */ - public boolean parse() { - - // create the version option - Option optVersion = new Option("V", "version", false, localization.getMessage("Help_Version")); - - // create the help option - Option optHelp = new Option("h", "help", false, localization.getMessage("Help_Help")); - - // create the log option - Option optLog = new Option("l", "log", false, localization.getMessage("Help_Log")); - - // create the verbose option - Option optVerbose = new Option("v", "verbose", false, localization.getMessage("Help_Verbose")); - - // create the timeout option - Option optTimeout = new Option("t", "timeout", true, localization.getMessage("Help_Timeout")); - - // create the language option - Option optLanguage = new Option("L", "language", true, localization.getMessage("Help_Language")); - - // add version - commandLineOptions.addOption(optVersion); - - // add help - commandLineOptions.addOption(optHelp); - - // add log - commandLineOptions.addOption(optLog); - - // add verbose - commandLineOptions.addOption(optVerbose); - - // add timeout - commandLineOptions.addOption(optTimeout); - - // add language - commandLineOptions.addOption(optLanguage); - - // create a new basic parser - CommandLineParser parser = new BasicParser(); - - // lets try to parse everthing - try { - - // parse the arguments - CommandLine line = parser.parse(commandLineOptions, theArgs); - - // if -L or --language found - if (line.hasOption("language")) { - - // create a new language controler - LanguageController language = new LanguageController(); - - // if the attempt to set the language according to the command - // line has failed - if (!language.setLanguage(line.getOptionValue("language"))) { - - // print the list of available languages - language.printLanguageHelp(); - - // print the usage - printUsage(); - - // and simply return - return false; - } - else { - - // new language, refresh the options - optVersion.setDescription(localization.getMessage("Help_Version")); - optHelp.setDescription(localization.getMessage("Help_Help")); - optLog.setDescription(localization.getMessage("Help_Log")); - optVerbose.setDescription(localization.getMessage("Help_Verbose")); - optTimeout.setDescription(localization.getMessage("Help_Timeout")); - optLanguage.setDescription(localization.getMessage("Help_Language")); - } - } - - // if -h or --help found - if (line.hasOption("help")) { - - // print version - printVersion(); - - // and usage - printUsage(); - - // return - return false; - - } else { - - // if -v or --version found - if (line.hasOption("version")) { - - // print version - printVersion(); - - printSpecialThanks(); - - // and return - return false; - - } else { - - // get the list of files - String[] files = line.getArgs(); - - // we only expect one file - if (files.length != 1) { - - // print version - printVersion(); - - // usage - printUsage(); - - // and return - return false; - - } else { - - // if -t or --timeout found - if (line.hasOption("timeout")) { - - // try to convert the argument to a number - try { - - // parse the long value - executionTimeout = Long.parseLong(line.getOptionValue("timeout")); - - // if it's not a valid number - if (executionTimeout <= 0) { - - // print version - printVersion(); - - // usage - printUsage(); - - // and return - return false; - - } - } catch (NumberFormatException numberFormatException) { - - // we have a bad conversion - - // print version - printVersion(); - - // usage - printUsage(); - - // and return - return false; - } - } else { - - // fallback to the default value, that is, - // timeout is disabled - executionTimeout = 0; - } - - // active logging - AraraLogging.enableLogging(line.hasOption("log")); - - // set verbose flag - showVerboseOutput = line.hasOption("verbose"); - - // everything is fine, set - // the file - theFile = files[0]; - - // check if file exists - if (!checkFile(theFile, configuration.getValidExtensions())) { - - // file not found, return false - return false; - - } - - // and return - return true; - } - } - } - - } catch (ParseException parseException) { - - // something happened, in the last case print version - printVersion(); - - // and usage - printUsage(); - - // and simply return - return false; - - } - } - - /** - * Prints the usage message. - */ - private void printUsage() { - - // new formatter - HelpFormatter formatter = new HelpFormatter(); - - // add the text and print - formatter.printHelp("arara [file [--log] [--verbose] [--timeout N] [--language L] | --help | --version]", commandLineOptions); - } - - /** - * Prints the application version. - */ - private void printVersion() { - - // print the version - System.out.println("arara ".concat(AraraConstants.VERSION).concat(" - ").concat(localization.getMessage("Header_Slogan"))); - System.out.println("Copyright (c) ".concat(AraraConstants.COPYRIGHTYEAR).concat(", Paulo Roberto Massa Cereda")); - System.out.println(localization.getMessage("Header_AllRightsReserved").concat("\n")); - } - - /** - * Getter for file obtained from the command line. - * - * @return The file. - */ - public String getFile() { - - // return it - return theFile; - } - - /** - * Checks if file is valid. - * - * @param filename The file name. - * @param extensions A priority list of allowed extensions. - * @return A boolean value to determine if the file is valid. - */ - private boolean checkFile(String filename, String[] extensions) { - - // flag to indicate the file was found - boolean foundFile = false; - - // iterate through all the extensions - for (String currentExtension : extensions) { - - // check if the file has the current extension - if (filename.toLowerCase().endsWith(currentExtension)) { - - // set flag - foundFile = true; - - // set configuration - configuration.setChosenFilePattern(currentExtension); - - // break iteration - break; - } - } - - // create a new file status - File fileStatus = null; - - // check if a reference was found - if (foundFile) { - - // create new instance - fileStatus = new File(filename); - - // check if exists - if (fileStatus.exists()) { - - // add file - theFile = filename; - - // found it! - return true; - } else { - - // print message about it - System.out.println(localization.getMessage("Error_FileDoesNotExist", filename)); - - // not found - return false; - } - - } else { - - // there's no extension, we will add them and see if something - // is found - for (String currentExtension : extensions) { - - // new file with extension - fileStatus = new File(filename + currentExtension); - - // let's check it - if (fileStatus.exists()) { - - // add file - theFile = filename + currentExtension; - - // add reference - configuration.setChosenFilePattern(currentExtension); - - // found it! - return true; - - } - - } - - // print message about it - System.out.println(AraraUtils.wrap(localization.getMessage("Error_FileDoesNotExistWithExtensionsList", filename, getExtensionsList(extensions)))); - - // file not found - return false; - - } - - } - - /** - * Returns a string with the extensions list. - * - * @param extensions The extensions list. - * @return A string with the extensions list. - */ - private String getExtensionsList(String[] extensions) { - - // if it's an empty vector - if (extensions.length == 0) { - - // return an empty string - return ""; - - } else { - - // get first element - String result = "[".concat(extensions[0]); - - // iterate through the other values - for (int i = 1; i < extensions.length; i++) { - - // add the current extension - result = result.concat(", ").concat(extensions[i]); - } - - // close the list - result = result.concat("]"); - - // return it - return result; - } - } - - /** - * Checks if the output must be verbose. - * - * @return A boolean value. - */ - public boolean isVerbose() { - - // return it - return showVerboseOutput; - } - - /** - * Getter for the execution timeout. - * - * @return The execution timeout. - */ - public long getExecutionTimeout() { - - // return it - return executionTimeout; - } - - /** - * Prints the special thanks message. - */ - private void printSpecialThanks() { - System.out.println(AraraUtils.wrap(localization.getMessage("Msg_SpecialThanks"))); - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/CommandTrigger.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/CommandTrigger.java deleted file mode 100644 index 67b4ff98e9f..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/CommandTrigger.java +++ /dev/null @@ -1,285 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * CommandTrigger: This class is responsible for running the arara commands. - */ -// package definition -package com.github.arara.utils; - -// needed imports -import com.github.arara.exception.AraraException; -import com.github.arara.model.AraraCommand; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.List; -import org.apache.commons.exec.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Implements an environment for running the arara commands. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 - */ -public class CommandTrigger { - - // the logger - final static Logger logger = LoggerFactory.getLogger(CommandTrigger.class); - // the localization class - final static AraraLocalization localization = AraraLocalization.getInstance(); - // the commands list - private List<AraraCommand> commands; - // flag to determine verbose output - private boolean showVerboseOutput; - // value for the execution timeout - private long executionTimeout; - - /** - * Constructor. - * - * @param commands The commands list. - */ - public CommandTrigger(List<AraraCommand> commands) { - - // set the list - this.commands = commands; - } - - /** - * Setter for the execution timeout. - * - * @param executionTimeout The execution timeout. - */ - public void setExecutionTimeout(long executionTimeout) { - - // set the value - this.executionTimeout = executionTimeout; - } - - /** - * Setter for the verbose mode. - * - * @param verbose A flag to indicate the verbose mode. - */ - public void setVerbose(boolean verbose) { - - // set the flag - showVerboseOutput = verbose; - } - - /** - * Executes the arara commands provided in the list. - * - * @return A boolean value about the execution. To be honest, I don't think - * it's necessary to return an actual value, but I kept it for possible - * future use. - * @throws AraraException Raised when the command is not found in the - * underlying system. - */ - public boolean execute() throws AraraException { - - // log action - logger.info(localization.getMessage("Log_ReadyToRunCommands")); - - // for every command in the list - for (AraraCommand currentAraraCommand : commands) { - - // print a message - System.out.print(localization.getMessage("Msg_RunningCommand", currentAraraCommand.getName()).concat(" ")); - - // if verbose - if (showVerboseOutput) { - - // add two lines - System.out.println("\n"); - } - - // log action - logger.info(localization.getMessage("Log_CommandName", currentAraraCommand.getName())); - - // log command - logger.trace(localization.getMessage("Log_Command", currentAraraCommand.getCommand())); - - // if the execution was ok - //if (runCommand(currentAraraCommand)) { - if (runCommand(currentAraraCommand)) { - - // print a message - System.out.println(localization.getMessage("Msg_Success")); - - // log action - logger.info(localization.getMessage("Log_CommandSuccess", currentAraraCommand.getName())); - - } else { - - // something bad happened, print message - System.out.println(localization.getMessage("Msg_Failure")); - - // log action - logger.warn(localization.getMessage("Log_CommandFailure", currentAraraCommand.getName())); - - // and return false - return false; - - } - - // if verbose - if (showVerboseOutput) { - - // add one line to the output - System.out.println(""); - } - - } - - // log action - logger.info(localization.getMessage("Log_AllCommandsSuccess")); - - // everything went ok, simply return true - return true; - - } - - /** - * Run the arara command. - * - * @param command The Arara command. - * @return A boolean indicating if the execution was successful. - * @throws AraraException Throws an exception in case the command was not - * found. - */ - private boolean runCommand(AraraCommand command) throws AraraException { - - // create a new byte array for the output logger - ByteArrayOutputStream stringLogger = new ByteArrayOutputStream(); - - // let's try - try { - - // set a query - String query = command.getCommand(); - - // create a new command line from the query - CommandLine commandLine = CommandLine.parse(query); - - // create a new tee - TeeOutputStream tee; - - // create a new execution handler - PumpStreamHandler streamHandler; - - // if verbose - if (showVerboseOutput) { - - // the new tee should include the normal output - // and the log - tee = new TeeOutputStream(System.out, stringLogger); - - // verbose mode enables input mode as well - streamHandler = new PumpStreamHandler(tee, tee, System.in); - - } else { - - // no verbose, so include only the log output - tee = new TeeOutputStream(stringLogger); - - // define the handler only with the log output - streamHandler = new PumpStreamHandler(tee); - } - - // create a new executor - DefaultExecutor executor = new DefaultExecutor(); - - // set the handler - executor.setStreamHandler(streamHandler); - - // check if there should be an execution timeout - if (executionTimeout > 0) { - - // create a new watch dog - ExecuteWatchdog watchDog = new ExecuteWatchdog(executionTimeout); - - // add it to the execution - executor.setWatchdog(watchDog); - } - - // set the shutdown hook - ShutdownHookProcessDestroyer processDestroyer = new ShutdownHookProcessDestroyer(); - - // add it to the executor - executor.setProcessDestroyer(processDestroyer); - - // execute the command and get the exit code - int exitValue = executor.execute(commandLine); - - // if we are in verbose mode - if (showVerboseOutput) { - - // print the output status - System.out.print(localization.getMessage("Msg_Status").concat(" ")); - - } - - // add the output to the logger - logger.trace(localization.getMessage("Log_OutputLogging")); - logger.trace(stringLogger.toString()); - - // return the status as a boolean - return (exitValue == 0 ? true : false); - - } catch (ExecuteException executeException) { - - // in case of an error, or the watchdog in action, - // the logger addition is not reached, so we need - // to replicate it here - logger.trace(localization.getMessage("Log_OutputLogging")); - logger.trace(stringLogger.toString()); - - // something bad happened, return false - return false; - - } catch (IOException ioException) { - - // log error - logger.error(localization.getMessage("Log_CommandNotFound", command.getName(), command.getCommand())); - - // command not found, throw exception - throw new AraraException(localization.getMessage("Error_CommandNotFound", command.getName(), command.getCommand())); - - } - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/ConfigurationLoader.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/ConfigurationLoader.java deleted file mode 100644 index db743c2e61f..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/ConfigurationLoader.java +++ /dev/null @@ -1,394 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * ConfigurationLoader: This class provides an object handler for the arara - * configuration file. - */ -// package definition -package com.github.arara.utils; - -// needed imports -import com.github.arara.Arara; -import com.github.arara.exception.AraraException; -import com.github.arara.model.AraraConfiguration; -import com.github.arara.model.AraraFilePattern; -import java.io.File; -import java.io.FileReader; -import java.net.URLDecoder; -import java.util.ArrayList; -import java.util.List; -import org.apache.commons.lang3.SystemUtils; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.Constructor; -import org.yaml.snakeyaml.error.MarkedYAMLException; -import org.yaml.snakeyaml.nodes.Tag; -import org.yaml.snakeyaml.representer.Representer; - -/** - * Provides an object handler for the arara configuration file. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 - */ -public class ConfigurationLoader { - - // list of search paths - private List<String> paths; - // the application path, that is, where arara is located - private String applicationPath; - // list of file patterns - private List<AraraFilePattern> filePatterns; - // list of valid extensions - private String[] validExtensions; - // the chosen pattern - private AraraFilePattern chosenFilePattern; - // the localization class - final static AraraLocalization localization = AraraLocalization.getInstance(); - - /** - * Constructor. - */ - public ConfigurationLoader() { - - // create a new list of paths - paths = new ArrayList<String>(); - - // try to obtain the application path - try { - applicationPath = Arara.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - applicationPath = URLDecoder.decode(applicationPath, "UTF-8"); - applicationPath = new File(applicationPath).getParentFile().getPath(); - } catch (Exception exception) { - applicationPath = ""; - } - } - - /** - * Loads the configuration settings, either the default setup or through the - * configuration file. - * - * @throws Exception An exception is thrown if something unexpected happens - * during the execution of this method. - */ - public void load() throws Exception { - - // create the default patterns - - // for .tex files - AraraFilePattern texPattern = new AraraFilePattern(); - texPattern.setExtension("tex"); - texPattern.setPattern("^(\\s)*%\\s+"); - - // for .dtx files - AraraFilePattern dtxPattern = new AraraFilePattern(); - dtxPattern.setExtension("dtx"); - dtxPattern.setPattern("^(\\s)*%\\s+"); - - // for .ltx files - AraraFilePattern ltxPattern = new AraraFilePattern(); - ltxPattern.setExtension("ltx"); - ltxPattern.setPattern("^(\\s)*%\\s+"); - - // create a list of default patterns - List<AraraFilePattern> defaultPatterns = new ArrayList<AraraFilePattern>(); - - // add the default ones - defaultPatterns.add(texPattern); - defaultPatterns.add(dtxPattern); - defaultPatterns.add(ltxPattern); - - // create a list of file patterns - filePatterns = new ArrayList<AraraFilePattern>(); - - // create a file reference - File configurationFile = new File(SystemUtils.USER_HOME + File.separator + AraraConstants.ARARACONFIG); - - // if there is not a configuration file - if (!configurationFile.exists()) { - - // there's only one path to look for rules - paths.add(applicationPath + File.separator + "rules"); - - // the only file patterns are the default ones - filePatterns.addAll(defaultPatterns); - - // create an array of valid extensions - validExtensions = new String[filePatterns.size()]; - - // add them according to the file patterns - for (int i = 0; i < filePatterns.size(); i++) { - validExtensions[i] = ".".concat(filePatterns.get(i).getExtension()); - } - - // simply return, there's nothing more to do - return; - } - - // create the YAML representer - Representer representer = new Representer(); - representer.addClassTag(AraraConfiguration.class, new Tag("!config")); - representer.addClassTag(AraraFilePattern.class, new Tag("!pattern")); - - // create the YAML parser - Yaml yaml = new Yaml(new Constructor(AraraConfiguration.class), representer); - - // create the file reader - FileReader fileReader = new FileReader(configurationFile); - - // set the new configuration object - AraraConfiguration configuration = null; - - try { - - // try to read the configuration object - configuration = (AraraConfiguration) yaml.load(fileReader); - - } catch (MarkedYAMLException yamlException) { - - // there's an error with the YAML file, so an exception is thrown - AraraLogging.enableLogging(false); - throw new AraraException(localization.getMessage("Error_InvalidYAMLConfigurationFile").concat("\n\n").concat(AraraUtils.extractInformationFromYAMLException(yamlException))); - } - catch (Exception e) { - System.out.println(e.getMessage()); - } - - // close the file reader - fileReader.close(); - - // check if the configuration is invalid - if (configuration == null) { - - // it's invalid, raise an exception - AraraLogging.enableLogging(false); - throw new AraraException(localization.getMessage("Error_InvalidConfigurationFile")); - } - - // check if there's an available language - if (configuration.getLanguage() != null) { - - // create a new language control - LanguageController languageController = new LanguageController(); - - // if the language is not valid - if (languageController.setLanguage(configuration.getLanguage()) == false) { - - // it's invalid, raise an exception - AraraLogging.enableLogging(false); - throw new AraraException(localization.getMessage("Error_InvalidLanguageConfigurationFile", languageController.getLanguagesList())); - } - } - - // check if there are new paths - if (configuration.getPaths() != null) { - - // a runtime exception happened when resolving some - // path names - if (configuration.getPathRuntimeException() != null) { - - // raise an exception - AraraLogging.enableLogging(false); - throw new AraraException(localization.getMessage("Error_PathRuntimeErrorConfigurationFile", AraraUtils.getVariableFromException(configuration.getPathRuntimeException()))); - } - - // a IO exception happened when checking if it was - // a valid path entry - if (configuration.getPathIOException() != null) { - - // raise an exception - AraraLogging.enableLogging(false); - throw new AraraException(localization.getMessage("Error_PathIOErrorConfigurationFile")); - } - - // for every path set - for (String currentPath : configuration.getPaths()) { - - // add it to the paths list - paths.add(currentPath); - } - } - - // the last path to be added is the application path - paths.add(applicationPath + File.separator + "rules"); - - // check if there are new file patterns - if (configuration.getFiletypes() != null) { - - // get all file patterns - List<AraraFilePattern> filetypes = configuration.getFiletypes(); - - // reorder the list of filetypes - for (int i = 0; i < defaultPatterns.size(); i++) { - - // if the filetype is not in the default list - if (!isAlreadyDefined(defaultPatterns.get(i), filetypes)) { - - // simply add it - filePatterns.add(defaultPatterns.get(i)); - } - } - - // merge the two lists - filePatterns.addAll(filetypes); - - // create a new array of valid extensions - validExtensions = new String[filePatterns.size()]; - int counter = 0; - - // sanity check, if there are valid extensions and patterns - for (AraraFilePattern currentPattern : filePatterns) { - - // check if either of those fields is missing - if ((currentPattern.getPattern() == null) || (currentPattern.getExtension() == null)) { - - // it's invalid, raise an exception - AraraLogging.enableLogging(false); - throw new AraraException(localization.getMessage("Error_InvalidFiletypesConfigurationFile")); - - } - - // add the dot to the extension - validExtensions[counter] = ".".concat(currentPattern.getExtension()); - counter++; - } - } else { - - // no new filetypes, simply merge the lists - filePatterns.addAll(defaultPatterns); - - // create a new array for extensions - validExtensions = new String[filePatterns.size()]; - - // iterate through all filetypes and add the extension to the array - for (int i = 0; i < filePatterns.size(); i++) { - validExtensions[i] = ".".concat(filePatterns.get(i).getExtension()); - } - } - - } - - /** - * Checks if the filetype is already defined in the list, and updates the - * latter if needed. - * - * @param filePattern The filetype object. - * @param list The list to be inspected. - * @return A boolean indicating if the filetype is already defined in the - * list. - */ - private boolean isAlreadyDefined(AraraFilePattern filePattern, List<AraraFilePattern> list) { - - // iterate through all elements - for (int i = 0; i < list.size(); i++) { - - // check if it already exists - if (filePattern.getExtension().equalsIgnoreCase(list.get(i).getExtension())) { - - // update the element if needed - if (list.get(i).getPattern() == null) { - list.set(i, filePattern); - } - - // already defined - return true; - } - } - - // not found - return false; - } - - /** - * Getter for the paths. - * - * @return The paths. - */ - public List<String> getPaths() { - return paths; - } - - /** - * Getter for the file patterns. - * - * @return The file patterns. - */ - public List<AraraFilePattern> getFilePatterns() { - return filePatterns; - } - - /** - * Getter for the valid extensions available. - * - * @return An array containing the valid extensions. - */ - public String[] getValidExtensions() { - return validExtensions; - } - - /** - * Setter for the chosen file pattern. - * - * @param extension A string containing a reference for the file extension. - */ - public void setChosenFilePattern(String extension) { - - // for every file pattern - for (AraraFilePattern currentPattern : filePatterns) { - - // if the extension matches - if (".".concat(currentPattern.getExtension()).equals(extension)) { - - // we found our pattern - chosenFilePattern = currentPattern; - - // return - return; - } - } - - // nothing found - chosenFilePattern = null; - } - - /** - * Getter for the chosen file pattern. - * - * @return The chosen file pattern. - */ - public AraraFilePattern getChosenFilePattern() { - return chosenFilePattern; - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/DirectiveExtractor.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/DirectiveExtractor.java deleted file mode 100644 index 0614fcf4306..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/DirectiveExtractor.java +++ /dev/null @@ -1,287 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * DirectiveExtractor: This class reads the file and extracts all the directives - * it could find. - */ -// package definition -package com.github.arara.utils; - -// needed imports -import com.github.arara.exception.AraraException; -import com.github.arara.model.AraraDirective; -import java.io.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.Constructor; -import org.yaml.snakeyaml.error.MarkedYAMLException; -import org.yaml.snakeyaml.representer.Representer; - -/** - * Reads the file and extracts all the directives it could find. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 1.0 - */ -public class DirectiveExtractor { - - // the logger - final static Logger logger = LoggerFactory.getLogger(DirectiveExtractor.class); - // the list of directives - private List<AraraDirective> directives; - // the file - private File file; - // the current line number - private int currentLineNumber; - // the configuration object - private ConfigurationLoader configuration; - // the localization class - final static AraraLocalization localization = AraraLocalization.getInstance(); - - /** - * Constructor. - */ - public DirectiveExtractor() { - - // create new list - directives = new ArrayList<AraraDirective>(); - - // set file to null - file = null; - } - - /** - * Constructor. - * - * @param file The file. - */ - public DirectiveExtractor(File file, ConfigurationLoader configuration) { - - // create a new list - directives = new ArrayList<AraraDirective>(); - - this.configuration = configuration; - - // set file - this.file = file; - } - - /** - * Setter for file. - * - * @param file The file. - */ - public void setFile(File file) { - - // set the file - this.file = file; - } - - /** - * Getter for Arara directives. - * - * @return A list containing all Arara directives. - */ - public List<AraraDirective> getDirectives() { - - // return the list - return directives; - } - - /** - * Extracts the directives from the file. - * - * @throws FileNotFoundException Raised when file not found. - * @throws IOException Raised when an IO error happened. - * @throws AraraException Raised when there's a problem with the directive. - */ - public void extract() throws FileNotFoundException, IOException, AraraException { - - // create a new file reader - FileReader fileReader = new FileReader(file); - - // create a new buffer - BufferedReader bufferedReader = new BufferedReader(fileReader); - - // variable to hold the current line - String currentLine; - - // the line count - currentLineNumber = 0; - - // log directives - logger.info("Reading directives from {}.", file.getName()); - - // while not EOF - while ((currentLine = bufferedReader.readLine()) != null) { - - // increment the current line number - currentLineNumber++; - - // extract directive - extractDirective(currentLine); - } - - // close the buffer - bufferedReader.close(); - - // close the reader - fileReader.close(); - - } - - /** - * Extracts the Arara directives from the current line. - * - * @param currentLine The current line. - * @throws AraraException Raised when there is a problem with the directive. - */ - private void extractDirective(String currentLine) throws AraraException { - - // get the pattern for the chosen filetype - Pattern linePattern = Pattern.compile(configuration.getChosenFilePattern().getPattern()); - - // create the matcher according to the pattern - Matcher matcher = linePattern.matcher(currentLine); - - // if the pattern is found - if (matcher.find()) { - - // get the substring - currentLine = (currentLine.substring(matcher.end(), currentLine.length())).trim(); - - // there is actually something after the keyword - if (!"".equals(currentLine)) { - - // log directive - logger.trace(localization.getMessage("Log_DirectiveFound", currentLineNumber, currentLine)); - - // look for a full directive - if (AraraUtils.checkForFullDirective(currentLine)) { - - // add it - addAraraDirective(currentLine); - } - else { - - // look for an empty directive - if (AraraUtils.checkForEmptyDirective(currentLine)) { - - // add it - addEmptyAraraDirective(currentLine.trim()); - } - else { - - // an invalid directive was found, throw error - throw new AraraException(localization.getMessage("Error_InvalidDirective", currentLineNumber)); - } - } - - } - } - } - - /** - * Extracts an empty Arara directive. - * - * @param currentLine The current line. - */ - private void addEmptyAraraDirective(String currentLine) { - - // create a new directive - AraraDirective araraDirective = new AraraDirective(); - - // set the name - araraDirective.setName(currentLine); - - // set the config - araraDirective.setConfig(new HashMap()); - - // set the line number, in case of error - araraDirective.setLineNumber(currentLineNumber); - - // add the directive to the list - directives.add(araraDirective); - - } - - /** - * Extracts am Arara directive. - * - * @param currentLine The current line. - * @throws AraraException Raised when there is a problem with the directive. - */ - private void addAraraDirective(String currentLine) throws AraraException { - - // lets try - try { - - // create a new YAML parser - Yaml yaml = new Yaml(new Constructor(), new Representer(), new DumperOptions(), new AraraResolver()); - - // create a new map and load the current line - Map config = (Map) yaml.load(currentLine); - - // create a new directive - AraraDirective ad = new AraraDirective(); - - // set the name - ad.setName(currentLine); - - // set the config - ad.setConfig(config); - - // set line number. in case of error - ad.setLineNumber(currentLineNumber); - - // add the directive to the list - directives.add(ad); - - } catch (MarkedYAMLException yamlException) { - - // malformed directive, throw exception - throw new AraraException(localization.getMessage("Error_InvalidYAMLDirective", currentLineNumber).concat("\n\n").concat(AraraUtils.extractInformationFromYAMLException(yamlException))); - } - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/DirectiveParser.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/DirectiveParser.java deleted file mode 100644 index b79a3741bd8..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/DirectiveParser.java +++ /dev/null @@ -1,321 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * DirectiveParser: This class analyzes the list of directives and converts them - * to a list of arara tasks. - */ -// package definition -package com.github.arara.utils; - -// needed imports -import com.github.arara.exception.AraraException; -import com.github.arara.model.AraraDirective; -import com.github.arara.model.AraraTask; -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Analyzes the list of directives and converts them to a list of arara tasks. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 1.0 - */ -public class DirectiveParser { - - // the logger - final static Logger logger = LoggerFactory.getLogger(DirectiveParser.class); - // the list of directives - private List<AraraDirective> directives; - // the list of tasks - private List<AraraTask> tasks; - // the list of file names, to use as a temporary variable - private List<String> fileNames; - // the list of items - private List<String> items; - // the current file reference - private File file; - // the localization class - final static AraraLocalization localization = AraraLocalization.getInstance(); - - /** - * Constructor - */ - public DirectiveParser() { - } - - /** - * Constructor. - * - * @param directives The Arara directives. - */ - public DirectiveParser(List<AraraDirective> directives) { - - // set the directives - this.directives = directives; - - // create a new list of tasks - this.tasks = new ArrayList<AraraTask>(); - - // create a new list of file names - this.fileNames = new ArrayList<String>(); - - // create a new list of items - this.items = new ArrayList<String>(); - } - - /** - * Setter for file. - * - * @param file The file. - */ - public void setFile(File file) { - - // set the file - this.file = file; - } - - /** - * Setter for the list of Arara directives. - * - * @param directives The list of Arara directives. - */ - public void setDirectives(List<AraraDirective> directives) { - - // set the list - this.directives = directives; - } - - /** - * Parses the list of Arara directives. - * - * @return A list of Arara tasks based on the directives. - * @throws AraraMalformedDirective Raised when a malformed directive is - * found. - */ - public List<AraraTask> parse() throws AraraException { - - // log message - logger.info("Parsing directives."); - - // for every directive - for (AraraDirective currentDirective : directives) { - - // clear the list of files - fileNames.clear(); - - // clear the task name - String taskName = ""; - - // create a new map - Map taskConfig = new HashMap(); - - // if there's no configuration - if (currentDirective.getConfig().isEmpty()) { - - // set the name - taskName = currentDirective.getName(); - - } else { - - // get the current config - Map currentConfig = currentDirective.getConfig(); - - // and get the directive name - String directiveName = (String) currentConfig.keySet().iterator().next(); - - // set the name to the task - taskName = directiveName; - - // get the parameters - Object currentConfigParameters = currentConfig.get(directiveName); - - // if it is a map - if (currentConfigParameters instanceof Map) { - - // get the map - Map currentParameters = (Map) currentConfigParameters; - - // if it is empty, error - if (currentParameters.isEmpty()) { - - // raise an error - throw new AraraException(localization.getMessage("Error_DirectiveEmptyCurlyBrackets", directiveName, currentDirective.getLineNumber())); - - } else { - - // for every parameter - for (Object currentParameterKey : currentParameters.keySet()) { - - // if the parameter is a string - if (currentParameters.get(currentParameterKey) instanceof String) { - - // if it is a file reference, error - if (((String) currentParameterKey).equals("files")) { - - // raise an error - throw new AraraException(localization.getMessage("Error_DirectiveInvalidArgumentList", directiveName, currentDirective.getLineNumber(), "files")); - } - - if (((String) currentParameterKey).equals("items")) { - - // raise an error - throw new AraraException(localization.getMessage("Error_DirectiveInvalidArgumentList", directiveName, currentDirective.getLineNumber(), "items")); - } - - // if it is a file reference, error - if (((String) currentParameterKey).equals("file")) { - - // raise an error - throw new AraraException(localization.getMessage("Error_DirectiveReservedKeyword", directiveName, currentDirective.getLineNumber(), "file", "files")); - } - - if (((String) currentParameterKey).equals("item")) { - - // raise an error - throw new AraraException(localization.getMessage("Error_DirectiveReservedKeyword", directiveName, currentDirective.getLineNumber(), "item", "items")); - } - - - // add the parameter to the configuration - taskConfig.put(currentParameterKey, (String) currentParameters.get(currentParameterKey)); - - } else { - - // if it is a list - if (currentParameters.get(currentParameterKey) instanceof List) { - - // if it is a file reference - if (((String) currentParameterKey).equals("files")) { - - // get the list - for (Object currentListValue : ((List) currentParameters.get(currentParameterKey))) { - - // add the file names - fileNames.add(currentListValue.toString()); - } - } else { - - if (((String) currentParameterKey).equals("items")) { - - // get the list - for (Object currentListValue : ((List) currentParameters.get(currentParameterKey))) { - - // add the file names - items.add(currentListValue.toString()); - } - } else { - - // raise error - throw new AraraException(localization.getMessage("Error_DirectiveListError", directiveName, currentDirective.getLineNumber())); - } - } - } else { - - // raise error - throw new AraraException(localization.getMessage("Error_DirectiveGenericError", directiveName, currentDirective.getLineNumber())); - } - } - } - } - } else { - - // raise error - throw new AraraException(localization.getMessage("Error_DirectiveGenericError", directiveName, currentDirective.getLineNumber())); - } - } - - // set original file name - AraraMethods.setOriginalFile(file.getName()); - - // if there is not a list of filenames - if (fileNames.isEmpty()) { - - // add the only filename available - fileNames.add(file.getName()); - } - - // if there are no items available - if (items.isEmpty()) { - - // simply add an empty entry - items.add(""); - } - - // for every filename - for (String filename : fileNames) { - - // and for every item - for (String item : items) { - - // create a new task - AraraTask araraTask = new AraraTask(); - - // set the name - araraTask.setName(taskName); - - // create a new map based on the current configuration - HashMap currentTaskConfig = new HashMap(taskConfig); - - // add the current file - currentTaskConfig.put("file", filename); - currentTaskConfig.put("item", item); - - // set the parameters - araraTask.setParameters(currentTaskConfig); - - // and add the task to the list - tasks.add(araraTask); - - // the current task is now null - araraTask = null; - } - } - - // clear the list of files and items - fileNames.clear(); - items.clear(); - - } - - // return the list of tasks - return tasks; - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/LanguageController.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/LanguageController.java deleted file mode 100644 index ea3468c0443..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/LanguageController.java +++ /dev/null @@ -1,159 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * LanguageController: This class holds the language model controller for arara. - */ -// package definition -package com.github.arara.utils; - -// needed imports -import com.github.arara.model.AraraLanguage; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -/** - * Holds the language model controller for arara. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 - */ -public class LanguageController { - - // list of available languages - private List<AraraLanguage> languages; - // the localization singleton instance - final static AraraLocalization localization = AraraLocalization.getInstance(); - - /** - * Constructor. - */ - public LanguageController() { - - // create a new list of languages - languages = new ArrayList<AraraLanguage>(); - - // add the resources - languages.add(new AraraLanguage("English", "en", new Locale("en"))); - languages.add(new AraraLanguage("Brazilian Portuguese", "ptbr", new Locale("pt", "BR"))); - languages.add(new AraraLanguage("Italian", "it", new Locale("it"))); - languages.add(new AraraLanguage("French", "fr", new Locale("fr"))); - languages.add(new AraraLanguage("Spanish", "es", new Locale("es"))); - languages.add(new AraraLanguage("German", "de", new Locale("de"))); - languages.add(new AraraLanguage("Turkish", "tr", new Locale("tr", "TR"))); - languages.add(new AraraLanguage("Russian", "ru", new Locale("ru"))); - - } - - /** - * Sets the current language according to the provided country code. - * - * @param code The country code. - * @return A boolean value indicating if the new language was properly - * applied. - */ - public boolean setLanguage(String code) { - - // get the index of the language - int i = getIndex(code); - - // if it's valid - if (i != -1) { - - // set locale and refresh the resource bundle - Locale.setDefault(languages.get(i).getLocale()); - localization.refresh(); - - // everything went fine - return true; - } - - // the country code is invalid - return false; - } - - /** - * Returns a string containing the list of available languages. - * - * @return A string containing the list of available languages. - */ - public String getLanguagesList() { - - // get the first one in the list - String result = languages.get(0).toString(); - - // iterate through the rest - for (int i = 1; i < languages.size(); i++) { - - // separate them by commas - result = result.concat(", ").concat(languages.get(i).toString()); - } - - // return the string - return result; - } - - /** - * Prints the language help. - */ - public void printLanguageHelp() { - - // print message - System.out.println(AraraUtils.wrap(localization.getMessage("Error_InvalidLanguage").concat("\n\n").concat(getLanguagesList()).concat("\n"))); - } - - /** - * Gets the index for the country code. - * @param code The country code. - * @return An integer representing the index. - */ - private int getIndex(String code) { - - // for every language - for (int i = 0; i < languages.size(); i++) { - - // if the codes are equal - if (languages.get(i).getCode().equalsIgnoreCase(code)) { - - // return the current counter - return i; - } - } - - // nothing was found, return a negative value - return -1; - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/TaskDeployer.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/TaskDeployer.java deleted file mode 100644 index 2a5a9c462e5..00000000000 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/TaskDeployer.java +++ /dev/null @@ -1,532 +0,0 @@ -/** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, 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. - * \endcond - * - * TaskDeployer: This class is responsible for taking the tasks and turning them - * into rara commands. - */ -// package definition -package com.github.arara.utils; - -// needed imports -import com.github.arara.exception.AraraException; -import com.github.arara.model.AraraCommand; -import com.github.arara.model.AraraRuleArgument; -import com.github.arara.model.AraraRuleConfig; -import com.github.arara.model.AraraTask; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.*; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.SystemUtils; -import org.mvel2.templates.TemplateRuntime; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.Constructor; -import org.yaml.snakeyaml.error.MarkedYAMLException; -import org.yaml.snakeyaml.nodes.Tag; -import org.yaml.snakeyaml.representer.Representer; - -/** - * Class responsible for taking the tasks and turning them into Arara commands. - * - * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 1.0 - */ -public class TaskDeployer { - - // the logger - final static Logger logger = LoggerFactory.getLogger(TaskDeployer.class); - // the localization class - final static AraraLocalization localization = AraraLocalization.getInstance(); - // the tasks list - private List<AraraTask> tasks; - //the output list with the proper commands - private List<AraraCommand> commands; - // the configuration - private ConfigurationLoader configuration; - - /** - * Constructor. - * - * @param tasks The Arara tasks. - */ - public TaskDeployer(List<AraraTask> tasks, ConfigurationLoader configuration) { - - // set everything - this.tasks = tasks; - - // set the configuration - this.configuration = configuration; - - // create the list - commands = new ArrayList<AraraCommand>(); - - } - - /** - * Deploys the tasks and returns the commands list. - * - * @return The Arara commands list. - * @throws Exception Raised if something bad happened. - */ - public List<AraraCommand> deploy() throws Exception { - - // log message - logger.info("Deploying tasks into commands."); - - // for each task - for (AraraTask currentTask : tasks) { - - // get the index where the rule is located - int pathIndex = findRule(currentTask); - - // if it's not a negative index, that is, the rule was found - if (pathIndex != -1) { - - // deploy plain rule - deployRule(currentTask, pathIndex); - - } else { - - // not found, throw exception - throw new AraraException(localization.getMessage("Error_RuleNotFound", currentTask.getName())); - } - } - - // return the commands - return commands; - - } - - /** - * Finds the rule in the rules directory. - * - * @param task The task to find. - * @return The rule location. - */ - private int findRule(AraraTask task) { - - // get the search path - List<String> paths = configuration.getPaths(); - - // for every entry in the search path - for (int i = 0; i < paths.size(); i++) { - - // if the current task is found in the current path - if (new File(paths.get(i).concat(File.separator).concat(task.getName()).concat(".yaml")).exists()) { - - // add an entry to the logger - logger.trace(localization.getMessage("Log_RuleFound", task.getName(), paths.get(i))); - - // return the index of the current path - return i; - } - } - - // nothing was found, return a negative value - return -1; - - } - - /** - * Deploys plain rule. - * - * @param task The task. - * @throws Exception The rule has a bad definition. - */ - private void deployRule(AraraTask task, int pathIndex) throws Exception { - - // create a representer - Representer representer = new Representer(); - - // add a class tag - representer.addClassTag(AraraRuleConfig.class, new Tag("!config")); - representer.addClassTag(AraraRuleArgument.class, new Tag("!argument")); - - // create a new YAML parser - Yaml yaml = new Yaml(new Constructor(AraraRuleConfig.class), representer); - - FileReader fileReader = null; - - // new file reader - fileReader = new FileReader(configuration.getPaths().get(pathIndex).concat(File.separator).concat(task.getName()).concat(".yaml")); - - // load rule - AraraRuleConfig plainRule = null; - - try { - - // try to load the rule - plainRule = (AraraRuleConfig) yaml.load(fileReader); - - } catch (MarkedYAMLException yamlException) { - - // YAML syntax error, throw exception - throw new AraraException(localization.getMessage("Error_InvalidYAMLRule", task.getName(), configuration.getPaths().get(pathIndex)).concat("\n\n").concat(AraraUtils.extractInformationFromYAMLException(yamlException))); - } - - try { - - // close reader - fileReader.close(); - - } catch (IOException ioException) { - // do nothing here - } - - // check if the rule is invalid - if (plainRule == null) { - - // raise an error - throw new AraraException(localization.getMessage("Error_InvalidRule", task.getName(), configuration.getPaths().get(pathIndex))); - } - - // verify if the identifier is empty - if (plainRule.getIdentifier() == null) { - - // raise error - throw new AraraException(localization.getMessage("Error_EmptyIdentifierRule", task.getName(), configuration.getPaths().get(pathIndex))); - - } else { - - // check if the rule has a proper name - if (plainRule.getName() == null) { - - // raise error - throw new AraraException(localization.getMessage("Error_EmptyNameRule", task.getName(), configuration.getPaths().get(pathIndex))); - - } else { - - // check if the rule has a proper list of arguments - if (plainRule.getArguments() == null) { - - // raise error - throw new AraraException(localization.getMessage("Error_EmptyArgumentsListRule", task.getName(), configuration.getPaths().get(pathIndex))); - - } - } - } - - // if the rule name doesn't match with the file name - if (!task.getName().equals(plainRule.getIdentifier())) { - - // throw exception - throw new AraraException(localization.getMessage("Error_WrongIdentifierRule", task.getName(), configuration.getPaths().get(pathIndex), plainRule.getIdentifier())); - } - - // check if the rule has any forbidden identifier - if (plainRule.checkForForbiddenIdentifiers() != null) { - - // raise error - throw new AraraException(localization.getMessage("Error_ForbiddenIdentifierRule", task.getName(), configuration.getPaths().get(pathIndex), plainRule.checkForForbiddenIdentifiers())); - } - - // get the list of all arguments available in the rule - List<String> availableArgumentsInRule = plainRule.getIdentifiersList(); - - // add the two reserved keywords - availableArgumentsInRule.add("file"); - availableArgumentsInRule.add("item"); - - // get the parameters for the task - HashMap directiveMap = task.getParameters(); - - // for every entry in the parameters map of the task, add it to the - // list of available parameters in the directive - List<String> availableArgumentsInDirective = new ArrayList<String>(); - for (Object theKey : directiveMap.keySet()) { - availableArgumentsInDirective.add((String) theKey); - } - - // find out which arguments are not defined in the directive and in - // the rule - List<String> argumentsNotDefinedInDirective = (List<String>) CollectionUtils.subtract(availableArgumentsInRule, availableArgumentsInDirective); - List<String> argumentsNotDefinedInRule = (List<String>) CollectionUtils.subtract(availableArgumentsInDirective, availableArgumentsInRule); - - // if there are invalid arguments in the directive - if (!argumentsNotDefinedInRule.isEmpty()) { - - // raise error - throw new AraraException(localization.getMessage("Error_ArgumentsNotDefinedInRule", task.getName(), configuration.getPaths().get(pathIndex), argumentsNotDefinedInRule.toString())); - } - - // for all arguments in the rule not mapped in the directive, set - // their default value to an empty string - for (String currentKey : argumentsNotDefinedInDirective) { - directiveMap.put(currentKey, ""); - } - - // add entries in the arguments map - HashMap argumentMap = new HashMap(); - argumentMap.put("file", directiveMap.get("file")); - argumentMap.put("item", directiveMap.get("item")); - directiveMap.remove("file"); - directiveMap.remove("item"); - argumentMap.put("parameters", directiveMap); - - // helper functions added - argumentMap.put("SystemUtils", SystemUtils.class); - argumentMap.put("isEmpty", AraraMethods.class.getMethod("isEmpty", String.class)); - argumentMap.put("isNotEmpty", AraraMethods.class.getMethod("isNotEmpty", String.class)); - argumentMap.put("isEmpty", AraraMethods.class.getMethod("isEmpty", String.class, String.class)); - argumentMap.put("isNotEmpty", AraraMethods.class.getMethod("isNotEmpty", String.class, String.class)); - argumentMap.put("isEmpty", AraraMethods.class.getMethod("isEmpty", String.class, String.class, String.class)); - argumentMap.put("isNotEmpty", AraraMethods.class.getMethod("isNotEmpty", String.class, String.class, String.class)); - argumentMap.put("isTrue", AraraMethods.class.getMethod("isTrue", String.class)); - argumentMap.put("isFalse", AraraMethods.class.getMethod("isFalse", String.class)); - argumentMap.put("isTrue", AraraMethods.class.getMethod("isTrue", String.class, String.class)); - argumentMap.put("isFalse", AraraMethods.class.getMethod("isFalse", String.class, String.class)); - argumentMap.put("isTrue", AraraMethods.class.getMethod("isTrue", String.class, String.class, String.class)); - argumentMap.put("isFalse", AraraMethods.class.getMethod("isFalse", String.class, String.class, String.class)); - argumentMap.put("isTrue", AraraMethods.class.getMethod("isTrue", String.class, String.class, String.class, String.class)); - argumentMap.put("isFalse", AraraMethods.class.getMethod("isFalse", String.class, String.class, String.class, String.class)); - argumentMap.put("trimSpaces", AraraMethods.class.getMethod("trimSpaces", String.class)); - argumentMap.put("getFilename", AraraMethods.class.getMethod("getFilename", String.class)); - argumentMap.put("getBasename", AraraMethods.class.getMethod("getBasename", String.class)); - argumentMap.put("getFiletype", AraraMethods.class.getMethod("getFiletype", String.class)); - argumentMap.put("getDirname", AraraMethods.class.getMethod("getDirname", String.class)); - argumentMap.put("isFile", AraraMethods.class.getMethod("isFile", String.class)); - argumentMap.put("isDir", AraraMethods.class.getMethod("isDir", String.class)); - argumentMap.put("isWindows", AraraMethods.class.getMethod("isWindows", String.class, String.class)); - argumentMap.put("isLinux", AraraMethods.class.getMethod("isLinux", String.class, String.class)); - argumentMap.put("isUnix", AraraMethods.class.getMethod("isUnix", String.class, String.class)); - argumentMap.put("isMac", AraraMethods.class.getMethod("isMac", String.class, String.class)); - - argumentMap.put("isTrue", AraraMethods.class.getMethod("isTrue", boolean.class, String.class)); - argumentMap.put("isTrue", AraraMethods.class.getMethod("isTrue", boolean.class, String.class, String.class)); - argumentMap.put("isFalse", AraraMethods.class.getMethod("isFalse", boolean.class, String.class)); - argumentMap.put("isFalse", AraraMethods.class.getMethod("isFalse", boolean.class, String.class, String.class)); - - argumentMap.put("getOriginalFile", AraraMethods.class.getMethod("getOriginalFile")); - - // create a rule map - HashMap ruleMap = new HashMap(); - - // for every argument in the rule - for (AraraRuleArgument currentArgument : plainRule.getArguments()) { - - // if there's not a default value - if (currentArgument.getDefault() == null) { - - // set the default to an empty string - ruleMap.put(currentArgument.getIdentifier(), ""); - - } else { - - // there's actually a default value - try { - - // get the default value and apply the template - String defaultValue = (String) TemplateRuntime.eval(currentArgument.getDefault(), argumentMap); - - // put the new default value into the rule map - ruleMap.put(currentArgument.getIdentifier(), defaultValue); - - } catch (RuntimeException runtimeException) { - - // an error occurred, throw exception - throw new AraraException(localization.getMessage("Error_DefaultValueRuntimeErrorRule", currentArgument.getIdentifier(), task.getName(), configuration.getPaths().get(pathIndex), AraraUtils.getVariableFromException(runtimeException))); - - } - } - } - - // after setting the default values into the rule map, let's add - // the directive parameters and both file and item references - ruleMap.put("parameters", directiveMap); - ruleMap.put("file", argumentMap.get("file")); - ruleMap.put("item", argumentMap.get("item")); - - // helper classes - ruleMap.put("SystemUtils", SystemUtils.class); - ruleMap.put("isEmpty", AraraMethods.class.getMethod("isEmpty", String.class)); - ruleMap.put("isNotEmpty", AraraMethods.class.getMethod("isNotEmpty", String.class)); - ruleMap.put("isEmpty", AraraMethods.class.getMethod("isEmpty", String.class, String.class)); - ruleMap.put("isNotEmpty", AraraMethods.class.getMethod("isNotEmpty", String.class, String.class)); - ruleMap.put("isEmpty", AraraMethods.class.getMethod("isEmpty", String.class, String.class, String.class)); - ruleMap.put("isNotEmpty", AraraMethods.class.getMethod("isNotEmpty", String.class, String.class, String.class)); - ruleMap.put("isTrue", AraraMethods.class.getMethod("isTrue", String.class)); - ruleMap.put("isFalse", AraraMethods.class.getMethod("isFalse", String.class)); - ruleMap.put("isTrue", AraraMethods.class.getMethod("isTrue", String.class, String.class)); - ruleMap.put("isFalse", AraraMethods.class.getMethod("isFalse", String.class, String.class)); - ruleMap.put("isTrue", AraraMethods.class.getMethod("isTrue", String.class, String.class, String.class)); - ruleMap.put("isFalse", AraraMethods.class.getMethod("isFalse", String.class, String.class, String.class)); - ruleMap.put("isTrue", AraraMethods.class.getMethod("isTrue", String.class, String.class, String.class, String.class)); - ruleMap.put("isFalse", AraraMethods.class.getMethod("isFalse", String.class, String.class, String.class, String.class)); - ruleMap.put("trimSpaces", AraraMethods.class.getMethod("trimSpaces", String.class)); - ruleMap.put("getFilename", AraraMethods.class.getMethod("getFilename", String.class)); - ruleMap.put("getBasename", AraraMethods.class.getMethod("getBasename", String.class)); - ruleMap.put("getFiletype", AraraMethods.class.getMethod("getFiletype", String.class)); - ruleMap.put("getDirname", AraraMethods.class.getMethod("getDirname", String.class)); - ruleMap.put("isFile", AraraMethods.class.getMethod("isFile", String.class)); - ruleMap.put("isDir", AraraMethods.class.getMethod("isDir", String.class)); - ruleMap.put("isWindows", AraraMethods.class.getMethod("isWindows", String.class, String.class)); - ruleMap.put("isLinux", AraraMethods.class.getMethod("isLinux", String.class, String.class)); - ruleMap.put("isUnix", AraraMethods.class.getMethod("isUnix", String.class, String.class)); - ruleMap.put("isMac", AraraMethods.class.getMethod("isMac", String.class, String.class)); - - ruleMap.put("isTrue", AraraMethods.class.getMethod("isTrue", boolean.class, String.class)); - ruleMap.put("isTrue", AraraMethods.class.getMethod("isTrue", boolean.class, String.class, String.class)); - ruleMap.put("isFalse", AraraMethods.class.getMethod("isFalse", boolean.class, String.class)); - ruleMap.put("isFalse", AraraMethods.class.getMethod("isFalse", boolean.class, String.class, String.class)); - - ruleMap.put("getOriginalFile", AraraMethods.class.getMethod("getOriginalFile")); - - // remove references to file and item - availableArgumentsInDirective.remove("file"); - availableArgumentsInDirective.remove("item"); - - // for all arguments in the rule - for (AraraRuleArgument currentArgument : plainRule.getArguments()) { - - // if the current argument is defined in the directive - if (isArgumentDefinedInDirective(availableArgumentsInDirective, currentArgument)) { - - // if there is a valid flag - if (currentArgument.getFlag() != null) { - - try { - - // get the flag and apply template - String defaultFlag = (String) TemplateRuntime.eval(currentArgument.getFlag(), ruleMap); - - // put the new flag reference into the rule map - ruleMap.put(currentArgument.getIdentifier(), defaultFlag); - } catch (RuntimeException runtimeException) { - - // an error occurred, throw exception - throw new AraraException(localization.getMessage("Error_FlagRuntimeErrorRule", currentArgument.getIdentifier(), task.getName(), configuration.getPaths().get(pathIndex), AraraUtils.getVariableFromException(runtimeException))); - - } - } - } - } - - // create a new list of commands to be executed by the current task - List<String> commandsList = new ArrayList<String>(); - - // if there is a command element in the rule - if (plainRule.getCommand() != null) { - - // and if there isn't a list of commands - if (plainRule.getCommands() == null) { - - // add the current command to the list of commands to - // be executed - commandsList.add(plainRule.getCommand()); - - } else { - - // both are defined, throw an error - throw new AraraException(localization.getMessage("Error_DuplicatedCommandElementsRule", task.getName(), configuration.getPaths().get(pathIndex))); - - } - } else { - - // none of the fields is defined - if (plainRule.getCommands() == null) { - - // neither of the elements is defined, throw an error - throw new AraraException(localization.getMessage("Error_MissingCommandElementsRule", task.getName(), configuration.getPaths().get(pathIndex))); - - } else { - - // there's a list of commands, add them to the list - commandsList.addAll(plainRule.getCommands()); - } - } - - // for every command to be processed - for (String commandTemplate : commandsList) { - - try { - // get the current command and apply template - commandTemplate = (String) TemplateRuntime.eval(commandTemplate, ruleMap); - - } catch (RuntimeException runtimeException) { - - // an error occurred, throw exception - throw new AraraException(localization.getMessage("Error_CommandRuntimeErrorRule", task.getName(), configuration.getPaths().get(pathIndex), AraraUtils.getVariableFromException(runtimeException))); - - } - - // check if it's a valid command - if (!"".equals(commandTemplate.trim())) { - - // create a new command - AraraCommand araraCommand = new AraraCommand(); - - // add the command - araraCommand.setCommand(commandTemplate); - - // add the name - araraCommand.setName(plainRule.getName()); - - // add to the list - commands.add(araraCommand); - - } - } - } - - /** - * Checks if the current argument is included in the list of arguments from - * the directive. - * - * @param arguments List of arguments from the directive. - * @param argument The current argument to be analyzed. - * @return A logic value indicating if the current argument is included in - * the list of arguments from the directive. - */ - private boolean isArgumentDefinedInDirective(List<String> arguments, AraraRuleArgument argument) { - - // for every argument in the list - for (String current : arguments) { - - // if the identifiers match - if (current.equalsIgnoreCase(argument.getIdentifier())) { - - // found it - return true; - } - } - - // not found - return false; - } -} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/Arara.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/Arara.java new file mode 100644 index 00000000000..c644978c93b --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/Arara.java @@ -0,0 +1,205 @@ +/** + * 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; + +import com.github.cereda.arara.controller.LanguageController; +import com.github.cereda.arara.controller.LoggingController; +import com.github.cereda.arara.model.AraraException; +import com.github.cereda.arara.model.Configuration; +import com.github.cereda.arara.model.Directive; +import com.github.cereda.arara.model.Extractor; +import com.github.cereda.arara.model.Interpreter; +import com.github.cereda.arara.model.Parser; +import com.github.cereda.arara.model.StopWatch; +import com.github.cereda.arara.utils.CommonUtils; +import com.github.cereda.arara.utils.DirectiveUtils; +import com.github.cereda.arara.utils.DisplayUtils; +import java.util.List; + +/** + * Main class. This class wraps all classes from the application model as well + * as utilitary classes in order to provide modularity. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Arara { + + /** + * Main method. This is the application entry point. + * @param args A string array containing all command line arguments. + */ + public static void main(String[] args) { + + // the first component to be initialized is the + // language controller; note that init() actually + // has no body at all, but it's a dirty maneuver to + // trigger the static class startup + LanguageController.init(); + + // the second component to be initalized is the + // logging controller; note init() actually disables + // the logging, so early exceptions won't generate + // a lot of noise in the terminal + LoggingController.init(); + + // print the arara logo in the terminal; I just + // hope people use this tool in a good terminal with + // fixed-width fonts, otherwise the logo will be messed + DisplayUtils.printLogo(); + + try { + + // first of all, let's try to load a potential + // configuration file located at the current + // user's home directory; if there's a bad + // configuration file, arara will panic and + // end the execution + Configuration.load(); + + // if we are here, either there was no configuration + // file at all or we managed to load the settings; now, + // it's time to properly parse the command line arguments; + // this is done by creating a brand new instance of arara's + // command line parser and providing the string array to it + Parser parser = new Parser(args); + + // now let's see if we are good to go; parse() will return + // a boolean value indicating if the provided arguments + // allow the tool to continue (we might reach some special + // flags as well, like --help or --version, which simply + // do their jobs and return false, since there's no point + // of continuing processing with such flags) + if (parser.parse()) { + + // let's print the current file information; it is a + // basic display, just the file name, the size properly + // formatted as a human readable format, and the last + // modification date; also, in this point, the logging + // feature starts to collect data (of course, if enabled + // either through the configuration file or manually + // in the command line) + DisplayUtils.printFileInformation(); + + // time to read the file and try to extract the directives; + // this class does a pretty good job on finding directives, + // including the multiline ones; it was a long awaited + // feature people were asking me to implement, so here + // it is! + Extractor extractor = new Extractor(); + + // extract() brings us a list of directives properly parsed + // and almost ready to be handled; note that no directives + // in the provided file will raise an exception; this is + // by design and I opted to not include a default fallback + // (although it wouldn't be so difficult to write one, + // I decided not to take the risk) + List<Directive> directives = extractor.extract(); + + // once we have our nice list of directives, it is time to + // actually validate them (for example, we have a couple of + // keywords that cannot be used as directive parameters); + // another interesting feature of the validate() method is + // to replicate a directive that has the 'files' keyword on + // it, since it's the whole point of having 'files' in the + // first place; if you check the log file, you will see + // that the list of extracted directives might differ from + // the final list of directives to be effectively processed + // by arara + directives = DirectiveUtils.validate(directives); + + // arara features now a cool stopwatch, so we can see how + // much time has passed since everything started; start(), + // for obvious reasons, starts the stopwatch and keeps track + // of time for us; internally, this class makes use of + // nano time, so we might get an interesting precision here + // (although timing is not a serious business in here, it's + // just a cool addition) + StopWatch.start(); + + // this is surely the golden heart of arara; this class + // implements a powerful interpreter that will handle all + // rules and their corresponding tasks + Interpreter interpreter = new Interpreter(); + + // once we have this bad boy ready, let's provide the list + // of directives previously extracted and validated; it is + // like loading a cannon, I guess + interpreter.setDirectives(directives); + + // time to shine, now the interpreter class will interpret + // one directive at a time, get the corresponding rule, + // set the parameters, evaluate it, get the tasks, run them, + // evaluate the result and print the status; note that + // arara, from this version on, will try to evaluate things + // progressively, so in case of an error, the previous tasks + // were already processed and potentially executed + interpreter.execute(); + } + + } catch (AraraException exception) { + + // something bad just happened, so arara will print the proper + // exception and provide details on it, if available; the idea + // here is to propagate an exception throughout the whole + // application and catch it here instead of a local treatment + DisplayUtils.printException(exception); + } + + // we are done here (with or without errors, that makes no difference + // at this point), so let's stop our stopwatch; now it's just an easy + // subtraction to be made (note that the values are internally + // represented as nanoseconds, but the result is printed as seconds) + StopWatch.stop(); + + // this is the last command from arara; once the execution time is + // available, print it; note that this notification is suppressed + // when the command line parsing returns false as result (it makes + // no sense to print the execution time for a help message, I guess) + DisplayUtils.printTime(); + + // gets the application exit status; the rule here is: + // 0 : everything went just fine (note that the dry-run mode always + // makes arara exit with 0, unless it is an error in the directive + // builder itself). + // 1 : one of the tasks failed, so the execution ended abruptly. This + // means the error relies on the command line call, not with arara. + // 2 : arara just handled an exception, meaning that something bad + // just happened and might require user intervention. + System.exit(CommonUtils.getExitStatus()); + + // I owe David Carlisle $10 + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/ConfigurationController.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/ConfigurationController.java new file mode 100644 index 00000000000..f3868b488f5 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/ConfigurationController.java @@ -0,0 +1,106 @@ +/** + * 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.controller; + +import java.util.HashMap; +import java.util.Map; + +/** + * Implements the configuration controller. The idea here is to provide a map + * that holds all configuration settings used by model and utilitary classes + * throughout the execution. This controller is implemented as a singleton. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class ConfigurationController { + + // the controller itself, since we have a singleton; + // this is the reference instance, instantiated once + private static final ConfigurationController instance = + new ConfigurationController(); + + // the configuration settings are stored in a map; + // pretty much everything can be stored in this map, + // as long as you know what to retrieve later on + private final Map<String, Object> map; + + /** + * Private constructor. Called once for creating the proper singleton. + */ + private ConfigurationController() { + map = new HashMap<String, Object>(); + } + + /** + * Gets the current configuration controller. Since this class is + * implemented as a singleton, you will get the same controller every + * single time, and that's good. + * @return The configuration controller, which hold the settings map. + */ + public static ConfigurationController getInstance() { + return instance; + } + + /** + * Returns the object indexed by the provided key. This method provides an + * easy access to the underlying map. + * @param key A string representing the key. + * @return An object indexed by the provided key. + */ + public Object get(String key) { + return map.get(key); + } + + /** + * Puts the object in the map and indexes it in the provided key. This + * method provides an easy access to the underlying map. + * @param key A string representing the key. + * @param value The object to be indexed by the provided key. + */ + public void put(String key, Object value) { + map.put(key, value); + } + + /** + * Checks if the map contains the provided key. This is actually a wrapper + * to the private map's method of the same name. + * @param key The key to be checked. + * @return A boolean value indicating if the map contains the provided key. + */ + public boolean contains(String key) { + return map.containsKey(key); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/LanguageController.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/LanguageController.java new file mode 100644 index 00000000000..a0ccc2a9586 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/LanguageController.java @@ -0,0 +1,120 @@ +/** + * 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.controller; + +import ch.qos.cal10n.IMessageConveyor; +import ch.qos.cal10n.MessageConveyor; +import java.util.Locale; + +/** + * Implements the language controller. This controller provides a singleton + * object that holds the application messages, easily available to all model + * and utilitary classes. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class LanguageController { + + // the controller itself, since we have a singleton; + // this is the reference instance, instantiated once + private static final LanguageController instance = + new LanguageController(); + + // the message conveyor helps us to get localized messages + // according to the provided locale + private IMessageConveyor conveyor; + + /** + * Private constructor. The fallback language is set to English for all + * messages in arara. + */ + private LanguageController() { + conveyor = new MessageConveyor(new Locale("en")); + } + + /** + * Initializes the class. This method actually does nothing, it just + * triggers the static attributions. Dirty, isn't it? + */ + public static void init() { + // quack, quack, quack! + } + + /** + * Gets the singleton reference. Since this class is implemented as a + * singleton, you will get the same controller every single time. + * @return The language controller which holds the conveyor. + */ + public static LanguageController getInstance() { + return instance; + } + + /** + * Sets the current locale. This method actually resets the language + * conveyor in order to use the new locale. It's quite simple. + * @param locale The new locale for localized messages through the language + * conveyor. + */ + public void setLocale(Locale locale) { + conveyor = new MessageConveyor(locale); + } + + /** + * Gets the localized message indexed by the provided enumeration key, + * applying an array of objects as parameters. This method is a wrapper to + * the conveyor's method of the same name. + * @param <E> Enumeration type that represents the conveyor messages. + * @param key Key set in the provided enumeration type. + * @param parameters Array of objects to be used as parameters. + * @return A string containing a localized message indexed by the provided + * enumeration key and applied the array of objects as parameters. + */ + public <E extends Enum<?>> String getMessage(E key, Object... parameters) { + return conveyor.getMessage(key, parameters); + } + + /** + * Gets the localized message indexed by the provided enumeration key. This + * method is a wrapper to the conveyor's method of the same name. + * @param <E> Enumeration type that represents the conveyor messages. + * @param key Key set in the provided enumeration type. + * @return A string containing a localized message indexed by the provided + * enumeration key. + */ + public <E extends Enum<?>> String getMessage(E key) { + return conveyor.getMessage(key); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/LoggingController.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/LoggingController.java new file mode 100644 index 00000000000..193726fcc42 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/LoggingController.java @@ -0,0 +1,109 @@ +/** + * 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.controller; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import java.io.InputStream; +import org.slf4j.LoggerFactory; + +/** + * Implements the logging controller. This class actually sets the logging + * configuration in order to allow appending results to a file. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class LoggingController { + + /** + * Sets the logging configuration according to the provided boolean value. + * If the value is set to true, the log entries will be appended to a file, + * otherwise the logging feature will keep silent. + * @param enable A boolean value that indicates the logging behaviour + * throughout the application. + */ + public static void enableLogging(boolean enable) { + + // get the logger context from a factory, set a + // new context and reset it + LoggerContext loggerContext = + (LoggerContext) LoggerFactory.getILoggerFactory(); + + try { + + // get a new configuration and set + // the context + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(loggerContext); + loggerContext.reset(); + + // if enabled, the log entries will be + // appended to a file, otherwise it will + // remain silent + if (enable) { + + // set the file name and configure + // the logging controller to append + // entries to the file + String name = (String) ConfigurationController. + getInstance().get("execution.log.name"); + loggerContext.putProperty("name", name); + configurator.doConfigure(getResource()); + } + } catch (JoranException exception) { + // quack, quack, quack! + } + } + + /** + * Get the configuration resource as an input stream. The configuration + * is actually a XML file. + * @return An input stream of the provided configuration XML resource. + */ + private static InputStream getResource() { + String resource = "/com/github/cereda/arara/configuration/logback.xml"; + return LoggingController.class.getResourceAsStream(resource); + } + + /** + * Initializes the logging controller by disabling it. I don't want an odd + * behaviour out of the box. + */ + public static void init() { + enableLogging(false); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/SessionController.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/SessionController.java new file mode 100644 index 00000000000..ac5a45d2b3e --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/SessionController.java @@ -0,0 +1,124 @@ +/** + * 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.controller; + +import java.util.HashMap; +import java.util.Map; + +/** + * Implements a session controller. This class wraps a map that holds the + * execution session, that is, a dirty maneuver to exchange pretty much any + * data between commands and even rules. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class SessionController { + + // the controller itself, since we have a singleton; + // this is the reference instance, instantiated once + private static final SessionController instance = + new SessionController(); + + // the session map which holds the execution session; + // the idea here is to provide wrappers to the map + // methods, so it could be easily manipulated + private final Map<String, Object> map; + + /** + * Private constructor. Called once when the singleton is created. + */ + private SessionController() { + map = new HashMap<String, Object>(); + } + + /** + * Gets the singleton reference. Since this class is implemented as a + * singleton, you will get the same controller every single time. + * @return The session controller which holds the session map. + */ + public static SessionController getInstance() { + return instance; + } + + /** + * Gets the object indexed by the provided key. This method actually holds + * the map method of the very same name. + * @param key The provided map key. + * @return The object indexed by the provided map key. + */ + public Object get(String key) { + return map.get(key); + } + + /** + * Puts the object in the session map and indexes it under the provided + * key. This method actually holds the map method of the very same name. + * @param key The provided map key. + * @param value The object to be indexed under the provided key. + */ + public void put(String key, Object value) { + map.put(key, value); + } + + /** + * Checks if the session map contains the provided key. This method holds + * the map method of the very same name. + * @param key The key to be checked. + * @return A boolean value indicating if the session map contains the + * provided key. + */ + public boolean contains(String key) { + return map.containsKey(key); + } + + /** + * Remove an entry from the map according to the provided key. This method + * holds the map method of the same name. + * @param key The provided key to indicate which session map entry should + * be removed. + */ + public void remove(String key) { + map.remove(key); + } + + /** + * Clears the session map. This method, as usual, holds the map method of + * the same name. + */ + public void clear() { + map.clear(); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/SystemCallController.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/SystemCallController.java new file mode 100644 index 00000000000..9a592853f69 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/controller/SystemCallController.java @@ -0,0 +1,153 @@ +/** + * 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.controller; + +import java.util.HashMap; +import java.util.Map; +import org.zeroturnaround.exec.ProcessExecutor; + +/** + * Implements a system call controller. This class wraps a map that holds the + * result of system specific variables not directly available at runtime. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class SystemCallController { + + /** + * Implements a private command interface. + */ + private interface Command { + + /** + * Executes the command body. + * @return An object. + */ + public Object execute(); + } + + // the controller itself, since we have a singleton; + // this is the reference instance, instantiated once + private static final SystemCallController instance = + new SystemCallController(); + + // the system call map which holds the result of + // system specific variables not directly available + // at runtime; the idea here is to provide wrappers + // to the map getter, so it could be easily manipulated + private final Map<String, Object> map; + + // the commands map will allow the system call map being + // populated only on demand, that is, if the key is not + // found, this map will provide the corresponding method + // and update the value + private final Map<String, Command> commands; + + /** + * Private constructor. Called once when the singleton is created. + */ + private SystemCallController() { + + // create the new map instance to be + // populated on demand + map = new HashMap<String, Object>(); + + // create the new map of commands and + // add the corresponding system calls + commands = new HashMap<String, Command>(); + + // add the check for a Cygwin + // environment in here + commands.put("cygwin", new Command() { + + /** + * Implements the body of the command. In this particular + * instance, it checks if we are inside a Cygwin environment. + * @return A boolean value indicating if we are inside a Cygwin + * environment. + */ + public Object execute() { + try { + + // execute a new system call to 'uname -s', read the output + // as an UTF-8 string, lowercase it and check if it starts + // with the 'cygwin' string; if so, we are inside Cygwin + return ( + new ProcessExecutor().command("uname", "-s"). + readOutput(true).execute().outputUTF8() + ).toLowerCase().startsWith("cygwin"); + + } catch (Exception exception) { + + // gracefully fallback in case of any nasty and evil + // exception, e.g, if the command is unavailable + return false; + } + } + }); + } + + /** + * Gets the singleton reference. Since this class is implemented as a + * singleton, you will get the same controller every single time. + * @return The system call controller which holds the system call map. + */ + public static SystemCallController getInstance() { + return instance; + } + + /** + * Gets the object indexed by the provided key. This method actually holds + * the map method of the very same name. + * @param key The provided map key. + * @return The object indexed by the provided map key. + */ + public Object get(String key) { + + // if key is not found, meaning that + // the value wasn't required before + if (!map.containsKey(key)) { + + // perform the system call and + // populate the corresponding value + map.put(key, commands.get(key).execute()); + } + + // simply return the corresponding + // value based on the provided key + return map.get(key); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/exception/AraraException.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/AraraException.java index daa1b4ac48a..f2a340fd01f 100644 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/exception/AraraException.java +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/AraraException.java @@ -1,7 +1,6 @@ /** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, Paulo Roberto Massa Cereda + * 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 @@ -31,57 +30,59 @@ * 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. - * \endcond - * - * AraraException: This class aims at reducing every exception that happens in the - * whole application to a single self-contained exception. */ -// package definition -package com.github.arara.exception; +package com.github.cereda.arara.model; /** - * Aims at reducing every exception that happens in the whole application to a - * single self-contained exception. - * + * Implements the specific exception model for arara. * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 + * @version 4.0 + * @since 4.0 */ public class AraraException extends Exception { + // the underlying exception, + // used to hold more details + // on what really happened + private Exception exception; + /** - * Constructor. + * Constructor. Takes the exception message. + * @param message The exception message. */ - public AraraException() { - super(); + public AraraException(String message) { + super(message); } /** - * Constructor with a message. - * - * @param message A message containing the cause of the exception thrown. + * Constructor. Takes the exception message and the underlying exception. + * @param message The exception message. + * @param exception The underlying exception object. */ - public AraraException(String message) { + public AraraException(String message, Exception exception) { super(message); + this.exception = exception; } /** - * Constructor with both message and the cause of the exception. - * - * @param message A message containing the cause of the exception thrown. - * @param cause The throwable cause. + * Gets the underlying exception. + * @return The underlying message. */ - public AraraException(String message, Throwable cause) { - super(message, cause); + public Exception getException() { + return exception; } /** - * Constructor with the cause of the exception. - * - * @param cause The throwable cause. + * Checks if there is an underlying exception defined in the current object. + * @return A boolean value indicating if the current object has an + * underlying exception. */ - public AraraException(Throwable cause) { - super(cause); + public boolean hasException() { + if (exception != null) { + return (exception.getMessage() != null); + } else { + return false; + } } } diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraRuleArgument.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Argument.java index 5f38418060a..0b15baf9d70 100644 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraRuleArgument.java +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Argument.java @@ -1,7 +1,6 @@ /** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, Paulo Roberto Massa Cereda + * 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 @@ -31,94 +30,96 @@ * 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. - * \endcond - * - * PlainAraraRuleArgument: This class provides the model for representing a - * plain Arara rule argument based on the YAML files. It's a plain old Java - * object. */ -// package definition -package com.github.arara.model; +package com.github.cereda.arara.model; -// needed import -import com.github.arara.utils.AraraUtils; +import com.github.cereda.arara.utils.CommonUtils; /** - * Provides the model for representing a plain Arara rule argument based on the - * YAML files. This class will be used to map YAML rules into Java objects. - * + * The rule argument model. * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 1.0 + * @version 4.0 + * @since 4.0 */ -public class AraraRuleArgument { +public class Argument { - // the rule argument identifier + // the argument identifier private String identifier; - // the command flag + + // a boolean indicating if the + // current argument is required + private boolean required; + + // the flag to hold the argument + // value manipulation private String flag; - // the default value - private String defaultValue; + + // the argument fallback if it is + // not defined in the directive + private String fallback; /** - * Getter for the default value. - * - * @return The default value. + * Gets the identifier. + * @return The identifier. */ - public String getDefault() { - return defaultValue; + public String getIdentifier() { + return CommonUtils.removeKeyword(identifier); } /** - * Setter for the default value. - * - * @param defaultValue The default value. + * Sets the identifier. + * @param identifier The identifier. */ - public void setDefault(String defaultValue) { - this.defaultValue = AraraUtils.removeKeyword(defaultValue); + public void setIdentifier(String identifier) { + this.identifier = identifier; } /** - * Getter for flag. - * - * @return The command flag. + * Checks if the argument is required. + * @return A boolean value indicating if the argument is required. */ - public String getFlag() { - - // return it - return flag; + public boolean isRequired() { + return required; } /** - * Setter for flag. - * - * @param flag The command flag. + * Sets the argument requirement. + * @param required A boolean value. */ - public void setFlag(String flag) { - - // set the flag - this.flag = AraraUtils.removeKeyword(flag); + public void setRequired(boolean required) { + this.required = required; } /** - * Getter for the argument identifier. - * - * @return The argument identifier. + * Gets the argument flag. + * @return The flag. */ - public String getIdentifier() { + public String getFlag() { + return CommonUtils.removeKeyword(flag); + } - // return it - return identifier; + /** + * Sets the argument flag. + * @param flag The argument flag. + */ + public void setFlag(String flag) { + this.flag = flag; } /** - * Setter for the argument identifier. - * - * @param identifier The argument identifier. + * Gets the argument fallback. + * @return The argument fallback. */ - public void setIdentifier(String identifier) { + public String getDefault() { + return CommonUtils.removeKeyword(fallback); + } - // set the identifier - this.identifier = identifier; + /** + * Sets the argument fallback. + * @param fallback The argument fallback. + */ + public void setDefault(String fallback) { + this.fallback = fallback; } + } diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Command.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Command.java new file mode 100644 index 00000000000..30583898327 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Command.java @@ -0,0 +1,122 @@ +/** + * 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.utils.CommonUtils; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Implements a command model, containing a list of strings. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Command { + + // a list of elements which are components + // of a command and represented as strings + private final List<String> elements; + + // an optional file acting as a reference + // for the default working directory + private File workingDirectory; + + /** + * Constructor. + * @param values An array of objects. + */ + public Command(Object... values) { + elements = new ArrayList<String>(); + List result = CommonUtils.flatten(Arrays.asList(values)); + for (Object value : result) { + String element = String.valueOf(value); + if (!CommonUtils.checkEmptyString(element)) { + elements.add(element); + } + } + } + + /** + * Constructor. + * @param elements A list of strings. + */ + public Command(List<String> elements) { + this.elements = elements; + } + + /** + * Gets the list of strings representing each element of a command. + * @return A list of strings. + */ + public List<String> getElements() { + return elements; + } + + /** + * Sets the working directory. + * @param workingDirectory A file representing the working directory. + */ + public void setWorkingDirectory(File workingDirectory) { + this.workingDirectory = workingDirectory; + } + + /** + * Gets the working directory, if any. + * @return A file representing the working directory. + */ + public File getWorkingDirectory() { + return workingDirectory; + } + + /** + * Checks if a working directory was defined. + * @return A logic value indicating if a working directory was defined. + */ + public boolean hasWorkingDirectory() { + return workingDirectory != null; + } + + /** + * Provides a textual representation of the current command. + * @return A string representing the current command. + */ + @Override + public String toString() { + return CommonUtils.getCollectionElements(elements, "[ ", " ]", ", "); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Conditional.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Conditional.java new file mode 100644 index 00000000000..4c830f0a1b6 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Conditional.java @@ -0,0 +1,139 @@ +/** + * 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; + +/** + * The conditional class, it represents the type of conditional available + * for a directive and its corresponding expression to be evaluated. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Conditional { + + // these are all types of conditionals arara + // is able to recognize; personally, I believe + // they are more than sufficient to cover the + // majority of test cases + public enum ConditionalType { + + // evaluated beforehand, directive is interpreted + // if and only if the result is true + IF, + + // there is no evaluation, directive is interpreted, + // no extra effort is needed + NONE, + + // evaluated beforehand, directive is interpreted + // if and only if the result is false + UNLESS, + + // directive is interpreted the first time, then the + // evaluation is done; while the result is false, + // the directive is interpreted again and again + UNTIL, + + // evaluated beforehand, directive is interpreted if + // and oly if the result is true, and the process is + // repeated while the result still holds true + WHILE + } + + // the conditional type, specified above; the + // default fallback, as seen in the constructor, + // is set to NONE, that is, no conditional at all + private ConditionalType type; + + // the expression to be evaluated according to its + // type; the default fallback, as seen in the + // constructor, is set to an empty string + private String condition; + + /** + * Constructor. + */ + public Conditional() { + type = ConditionalType.NONE; + condition = ""; + } + + /** + * Gets the conditional type. + * @return The conditional type. + */ + public ConditionalType getType() { + return type; + } + + /** + * Sets the conditional type. + * @param type The conditional type. + */ + public void setType(ConditionalType type) { + this.type = type; + } + + /** + * Gets the condition, that is, the expression to be evaluated. + * @return A string representing the condition. + */ + public String getCondition() { + return condition; + } + + /** + * Sets the condition, that is, the expression to be evaluated. + * @param condition A string representing the condition. + */ + public void setCondition(String condition) { + this.condition = condition; + } + + /** + * Provides a textual representation of the conditional object. + * @return A string representation of this object. + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("{ ").append(type); + if (type != ConditionalType.NONE) { + builder.append(", expression: ").append(condition.trim()); + } + builder.append(" }"); + return builder.toString(); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Configuration.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Configuration.java new file mode 100644 index 00000000000..0c2c2949586 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Configuration.java @@ -0,0 +1,246 @@ +/** + * 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.ConfigurationUtils; +import java.io.File; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * Implements the configuration model, which holds the default settings and can + * load the configuration file. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Configuration { + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Loads the application configuration. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static void load() throws AraraException { + + // initialize both file type and language models, + // since we can track errors from there instead + // of relying on a check on this level + FileType.init(); + Language.init(); + + // reset everything + reset(); + + // get the configuration file, if any + File file = ConfigurationUtils.getConfigFile(); + if (file != null) { + + // set the configuration file name for + // logging purposes + ConfigurationController.getInstance(). + put("execution.configuration.name", + CommonUtils.getCanonicalPath(file) + ); + + // then validate it and update the + // configuration accordingly + Resource resource = ConfigurationUtils.validateConfiguration(file); + update(resource); + } + + // just to be sure, update the + // current locale in order to + // display localized messages + Locale locale = ((Language) ConfigurationController. + getInstance().get("execution.language")).getLocale(); + LanguageController.getInstance().setLocale(locale); + } + + /** + * Resets the configuration to initial settings. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + private static void reset() throws AraraException { + + // put everything in a map to be + // later assigned to the configuration + // controller, which holds the settings + Map<String, Object> mapping = new HashMap<String, Object>(); + + mapping.put("execution.loops", 10L); + mapping.put("directives.charset", Charset.forName("UTF-8")); + mapping.put("execution.errors.halt", true); + mapping.put("execution.timeout", false); + mapping.put("execution.timeout.value", 0L); + mapping.put("execution.timeout.unit", TimeUnit.MILLISECONDS); + mapping.put("application.version", "4.0"); + mapping.put("application.revision", "1"); + mapping.put("directives.linebreak.pattern", "^\\s*-->\\s(.*)$"); + + String directive = "^\\s*(\\w+)\\s*(:\\s*(\\{.*\\})\\s*)?"; + String pattern = "(\\s+(if|while|until|unless)\\s+(\\S.*))?$"; + + mapping.put("directives.pattern", directive.concat(pattern)); + mapping.put("application.pattern", "arara:\\s"); + mapping.put("application.width", 65); + mapping.put("execution.database.name", "arara"); + mapping.put("execution.log.name", "arara"); + mapping.put("execution.verbose", false); + + mapping.put("trigger.halt", false); + mapping.put("execution.language", new Language("en")); + mapping.put("execution.logging", false); + mapping.put("execution.dryrun", false); + mapping.put("execution.status", 0); + mapping.put("application.copyright.year", "2012-2018"); + mapping.put("execution.filetypes", ConfigurationUtils. + getDefaultFileTypes()); + mapping.put("execution.rule.paths", + Arrays.asList( + CommonUtils.buildPath( + ConfigurationUtils.getApplicationPath(), + "rules" + ) + ) + ); + + mapping.put("execution.preambles", new HashMap<String, String>()); + mapping.put("execution.preamble.active", false); + mapping.put("execution.configuration.name", "[none]"); + mapping.put("execution.header", false); + mapping.put("ui.lookandfeel", "none"); + + // get the configuration controller and + // set every map key to it + ConfigurationController controller = + ConfigurationController.getInstance(); + for (String key : mapping.keySet()) { + controller.put(key, mapping.get(key)); + } + } + + /** + * Update the configuration based on the provided map. + * @param data Map containing the new configuration settings. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + private static void update(Resource resource) throws AraraException { + + ConfigurationController controller = + ConfigurationController.getInstance(); + + if (resource.getPaths() != null) { + List<String> paths = resource.getPaths(); + paths = ConfigurationUtils.normalizePaths(paths); + controller.put("execution.rule.paths", paths); + } + + if (resource.getFiletypes() != null) { + List<FileTypeResource> resources = resource.getFiletypes(); + List<FileType> filetypes = new ArrayList<FileType>(); + for (FileTypeResource type : resources) { + if (type.getPattern() != null) { + filetypes.add( + new FileType(type.getExtension(), type.getPattern()) + ); + } else { + filetypes.add(new FileType(type.getExtension())); + } + } + filetypes = ConfigurationUtils.normalizeFileTypes(filetypes); + controller.put("execution.filetypes", filetypes); + } + + controller.put("execution.verbose", resource.isVerbose()); + controller.put("execution.logging", resource.isLogging()); + controller.put("execution.header", resource.isHeader()); + + if (resource.getDbname() != null) { + controller.put("execution.database.name", + ConfigurationUtils.cleanFileName(resource.getDbname())); + } + + if (resource.getLogname() != null) { + controller.put("execution.log.name", + ConfigurationUtils.cleanFileName(resource.getLogname())); + } + + if (resource.getLanguage() != null) { + controller.put("execution.language", + new Language(resource.getLanguage())); + } + + long loops = resource.getLoops(); + if (loops > 0) { + controller.put("execution.loops", loops); + } else { + if (loops < 0) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_CONFIGURATION_LOOPS_INVALID_RANGE + ) + ); + } + } + + if (resource.getPreambles() != null) { + controller.put("execution.preambles", + resource.getPreambles()); + } + + if (resource.getLaf() != null) { + controller.put("ui.lookandfeel", + resource.getLaf()); + } + + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Database.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Database.java new file mode 100644 index 00000000000..66d360fdc08 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Database.java @@ -0,0 +1,80 @@ +/** + * 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 java.util.HashMap; +import org.simpleframework.xml.ElementMap; +import org.simpleframework.xml.Root; + +/** + * The XML database model, which keeps track on file changes. I am using the + * Simple framework to marshall and unmarshall objects and XML files. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +@Root(name = "status") +public class Database { + + // the whole database is implemented as a map, where + // the key is the absolute canonical file and the value + // is its corresponding CRC32 hash; the XML map is done + // inline, so it does not clutter the output a lot + @ElementMap(entry = "hash", key = "file", attribute = true, inline = true) + private HashMap<String, String> map; + + /** + * Constructor. It creates a new map. + */ + public Database() { + map = new HashMap<String, String>(); + } + + /** + * Gets the map. + * @return The map. + */ + public HashMap<String, String> getMap() { + return map; + } + + /** + * Sets the map. + * @param map The map. + */ + public void setMap(HashMap<String, String> map) { + this.map = map; + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Directive.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Directive.java new file mode 100644 index 00000000000..e311477125c --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Directive.java @@ -0,0 +1,146 @@ +/** + * 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 java.util.List; +import java.util.Map; + +/** + * Implements the directive model. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Directive { + + // the directive identifier, it is resolved + // to the rule identifier later on + private String identifier; + + // a map containing the parameters; they + // are validated later on in order to + // ensure they are valid + private Map<String, Object> parameters; + + // a conditional containing the type and + // the expression to be evaluated later on + private Conditional conditional; + + // a list contained all line numbers from + // the main file which built the current + // directive + private List<Integer> lineNumbers; + + /** + * Gets the directive identifier. + * @return A string representing the directive identifier. + */ + public String getIdentifier() { + return identifier; + } + + /** + * Sets the directive identifier. + * @param identifier A string representing the directive identifier. + */ + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + * Gets the directive parameters. + * @return A map containing the directive parameters. + */ + public Map<String, Object> getParameters() { + return parameters; + } + + /** + * Sets the directive parameters. + * @param parameters A map containing the directive parameters. + */ + public void setParameters(Map<String, Object> parameters) { + this.parameters = parameters; + } + + /** + * Gets the conditional object from the current directive. + * @return The conditional object from the current directive. + */ + public Conditional getConditional() { + return conditional; + } + + /** + * Sets the conditional object from the current directive. + * @param conditional The conditional object from the current directive. + */ + public void setConditional(Conditional conditional) { + this.conditional = conditional; + } + + /** + * Gets the list containing all line numbers from the current directive. + * @return A list containing all line numbers from the current directive. + */ + public List<Integer> getLineNumbers() { + return lineNumbers; + } + + /** + * Sets the list containing all line numbers from the current directive. + * @param lineNumbers A list containing all line numbers from the current + * directive. + */ + public void setLineNumbers(List<Integer> lineNumbers) { + this.lineNumbers = lineNumbers; + } + + /** + * Provides a textual representation of the current directive. + * @return A string containing a textual representation of the current + * directive. + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Directive: { "); + builder.append("identifier: ").append(identifier).append(", "); + builder.append("parameters: ").append(parameters).append(", "); + builder.append("conditional: ").append(conditional).append(", "); + builder.append("lines: ").append(lineNumbers).append(" }"); + return builder.toString(); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Evaluator.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Evaluator.java new file mode 100644 index 00000000000..41f8d099430 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Evaluator.java @@ -0,0 +1,158 @@ +/** + * 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.Methods; +import java.util.HashMap; +import java.util.Map; +import org.mvel2.templates.TemplateRuntime; + +/** + * Implements the evaluator model, on which a conditional can be analyzed and + * processed. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Evaluator { + + // this attribute holds the maximum number of + // loops arara will accept; it's like + // reaching infinity + private final long loops; + + // the counter for the current execution, it + // helps us keep track of the number of times + // this evaluation has happened, and also to + // prevent potential infinite loops + private long counter; + + // a flag that indicates the + // evaluation to halt regardless + // of the the result + private boolean halt; + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Constructor. It gets the application maximum number of loops and reset + * all counters. + */ + public Evaluator() { + loops = (Long) ConfigurationController.getInstance(). + get("execution.loops"); + counter = 0; + halt = false; + } + + /** + * Evaluate the provided conditional. + * @param conditional The conditional object. + * @return A boolean value indicating if the conditional holds. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public boolean evaluate(Conditional conditional) throws AraraException { + + // when in dry-run mode, arara + // always ignore conditional evaluations + if (((Boolean) ConfigurationController. + getInstance().get("execution.dryrun")) == true) { + return false; + } + + switch (conditional.getType()) { + case NONE: + return false; + case IF: + case UNLESS: + if (!halt) { + halt = true; + } else { + return false; + } + break; + } + + // check counters and see if the execution + // has reached our concept of infinity, + // thus breaking the cycles + counter++; + if (((conditional.getType() == Conditional.ConditionalType.WHILE) && + (counter > loops)) || + ((conditional.getType() == Conditional.ConditionalType.UNTIL) && + (counter >= loops))) { + return false; + } else { + + Map<String, Object> context = new HashMap<String, Object>(); + Methods.addConditionalMethods(context); + + try { + Object result = TemplateRuntime.eval("@{ ".concat( + conditional.getCondition()).concat(" }"), context); + if (!CommonUtils.checkClass(Boolean.class, result)) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_EVALUATE_NOT_BOOLEAN_VALUE + ) + ); + } else { + boolean value = (Boolean) result; + switch (conditional.getType()) { + case UNLESS: + case UNTIL: + value = !value; + break; + } + return value; + } + } catch (RuntimeException exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_EVALUATE_COMPILATION_FAILED + ), + exception + ); + } + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Extractor.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Extractor.java new file mode 100644 index 00000000000..84edef1eb05 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Extractor.java @@ -0,0 +1,88 @@ +/** + * 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.DirectiveUtils; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.List; +import org.apache.commons.io.FileUtils; + +/** + * It extracts directives from the provided main file. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Extractor { + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Extracts a list of directives from the provided main file, obtained from + * the configuration controller. + * @return A list of directives. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public List<Directive> extract() throws AraraException { + + File file = (File) ConfigurationController. + getInstance().get("execution.reference"); + Charset charset = (Charset) ConfigurationController. + getInstance().get("directives.charset"); + + try { + List<String> content = CommonUtils.getPreambleContent(); + List<String> lines = FileUtils.readLines(file, charset.name()); + content.addAll(lines); + return DirectiveUtils.extractDirectives(content); + } catch (IOException ioexception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_EXTRACTOR_IO_ERROR + ), + ioexception + ); + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/FileType.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/FileType.java new file mode 100644 index 00000000000..b9f2a01e032 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/FileType.java @@ -0,0 +1,170 @@ +/** + * 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.LanguageController; +import com.github.cereda.arara.utils.CommonUtils; +import java.util.HashMap; +import java.util.Map; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Implements the file type model. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class FileType { + + // string representing the + // file extension + private String extension; + + // string representing the + // file pattern to be used + // as directive lookup + private String pattern; + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + // a map containing all file + // types that arara accepts + private static final Map<String, String> types = + new HashMap<String, String>(); + + /** + * Initializes the file type class by setting the default file types and + * their corresponding patterns. + */ + public static void init() { + types.put("tex", "^\\s*%\\s+"); + types.put("dtx", "^\\s*%\\s+"); + types.put("ltx", "^\\s*%\\s+"); + types.put("drv", "^\\s*%\\s+"); + types.put("ins", "^\\s*%\\s+"); + } + + /** + * Constructor. It takes both file extension and pattern lookup. + * @param extension The file extension. + * @param pattern The file pattern. + */ + public FileType(String extension, String pattern) { + this.extension = extension; + this.pattern = pattern; + } + + /** + * Constructor. It takes the extension, but it might raise an exception if + * the extension is unknown. This constructor is used when you just want + * to reorganize the file lookup priority without the need of changing the + * default extensions. + * @param extension The file extension. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public FileType(String extension) throws AraraException { + if (types.containsKey(extension)) { + this.extension = extension; + this.pattern = types.get(extension); + } else { + throw new AraraException( + messages.getMessage( + Messages.ERROR_FILETYPE_UNKNOWN_EXTENSION, + extension, + CommonUtils.getFileTypesList() + ) + ); + } + } + + /** + * Implements the file type hash code. Note that only the file extension is + * considered. + * @return An integer representing the file type hash code. + */ + @Override + public int hashCode() { + return new HashCodeBuilder().append(extension).toHashCode(); + } + + /** + * Implements the file type equals method, checking if one file type is + * equal to another. Note that only the file extension is considered. + * @param object The object to be analyzed. + * @return A boolean value indicating if those two objects are equal. + */ + @Override + public boolean equals(Object object) { + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + final FileType reference = (FileType) object; + return new EqualsBuilder().append(extension, reference.extension).isEquals(); + } + + /** + * Gets the file type extension. + * @return String representing the file type extension. + */ + public String getExtension() { + return extension; + } + + /** + * Gets the file type pattern. + * @return String representing the file type pattern. + */ + public String getPattern() { + return pattern; + } + + /** + * Provides a textual representation of the current file type object. + * @return A string containing a textual representation of the current file + * type object. + */ + @Override + public String toString() { + return ".".concat(extension); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraFilePattern.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/FileTypeResource.java index 91e1e4759f9..29340358581 100644 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraFilePattern.java +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/FileTypeResource.java @@ -1,7 +1,6 @@ /** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, Paulo Roberto Massa Cereda + * 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 @@ -31,63 +30,55 @@ * 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. - * \endcond - * - * AraraFilePattern: This class maps the supported filetypes. */ -// package definition -package com.github.arara.model; +package com.github.cereda.arara.model; -// needed imports -import com.github.arara.utils.AraraConstants; +import com.github.cereda.arara.utils.CommonUtils; /** - * Maps the supported filetypes. - * + * Implements the file type resource model. * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 3.0 + * @version 4.0 + * @since 4.0 */ -public class AraraFilePattern { +public class FileTypeResource { - // file extension + // the file extension private String extension; - // file pattern + + // the file pattern private String pattern; /** - * Getter for the file extension. - * - * @return The file extension. + * Gets the extension. + * @return The extension. */ public String getExtension() { - return extension; + return CommonUtils.removeKeyword(extension); } /** - * Setter for the file extension. - * - * @param extension The file extension. + * Sets the extension. + * @param extension The extension. */ public void setExtension(String extension) { this.extension = extension; } /** - * Getter for the file pattern. - * - * @return The file pattern. + * Gets the pattern. + * @return The pattern. */ public String getPattern() { - return pattern; + return CommonUtils.removeKeyword(pattern); } /** - * Setter for the file pattern. - * - * @param pattern The file pattern. + * Sets the pattern. + * @param pattern The pattern. */ public void setPattern(String pattern) { - this.pattern = pattern.concat(AraraConstants.DIRECTIVEPREFIX); + this.pattern = pattern; } + } 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; + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Language.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Language.java new file mode 100644 index 00000000000..2b0fc8266e8 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Language.java @@ -0,0 +1,148 @@ +/** + * 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.LanguageController; +import com.github.cereda.arara.utils.CommonUtils; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * Implements the language model. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Language { + + // the language code, based on + // ISO 639-1 and language variants + private final String code; + + // map containing all languages + // supported by nightingale + private static final Map<String, Pair<String, Locale>> languages = + new HashMap<String, Pair<String, Locale>>(); + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Initialize the language model. All supported languages are added in here. + */ + public static void init() { + languages.put("en", new Pair<String, Locale>( + "English", + new Locale("en") + )); + languages.put("de", new Pair<String, Locale>( + "German", + new Locale("de") + )); + languages.put("nl", new Pair<String, Locale>( + "Dutch", + new Locale("nl") + )); + languages.put("qn", new Pair<String, Locale>( + "Broad Norfolk", + new Locale("en", "QN") + )); + languages.put("ptbr", new Pair<String, Locale>( + "Brazilian Portuguese", + new Locale("pt", "BR") + )); + languages.put("it", new Pair<String, Locale>( + "Italian", + new Locale("it") + )); + } + + /** + * Creates a new language object. It might raise an exception if the + * provided language does not exist in the map. + * @param code The language code, based on ISO 639-1 and language variants. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public Language(String code) throws AraraException { + if (languages.containsKey(code)) { + this.code = code; + } else { + throw new AraraException( + messages.getMessage( + Messages.ERROR_LANGUAGE_INVALID_CODE, + getLanguagesList() + ) + ); + } + } + + /** + * Gets the language name. + * @return A string representing the language name. + */ + public String getName() { + return languages.get(code).getFirstElement(); + } + + /** + * Gets the language locale. + * @return The language locale. + */ + public Locale getLocale() { + return languages.get(code).getSecondElement(); + } + + /** + * Gets a string representing the list of available languages. + * @return String representing the list of available languages. + */ + public static String getLanguagesList() { + List<String> entries = new ArrayList<String>(); + for (String key : languages.keySet()) { + entries.add(languages.get(key). + getFirstElement(). + concat(": "). + concat(key) + ); + } + return CommonUtils.getCollectionElements(entries, "(", ")", ", "); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Messages.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Messages.java new file mode 100644 index 00000000000..9916c3c145b --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Messages.java @@ -0,0 +1,170 @@ +/** + * 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 ch.qos.cal10n.BaseName; +import ch.qos.cal10n.Locale; +import ch.qos.cal10n.LocaleData; + +/** + * This enumeration contains all application messages. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +@BaseName("com.github.cereda.arara.localization.messages") +@LocaleData({ + @Locale(value = "de", charset = "UTF-8"), + @Locale(value = "en", charset = "UTF-8"), + @Locale(value = "en_QN", charset = "UTF-8"), + @Locale(value = "it", charset = "UTF-8"), + @Locale(value = "nl", charset = "UTF-8"), + @Locale(value = "pt_BR", charset = "UTF-8") +}) +public enum Messages { + + ERROR_BASENAME_NOT_A_FILE, + ERROR_CALCULATEHASH_IO_EXCEPTION, + ERROR_CHECKBOOLEAN_NOT_VALID_BOOLEAN, + ERROR_CHECKOS_INVALID_OPERATING_SYSTEM, + ERROR_CHECKREGEX_IO_EXCEPTION, + ERROR_CONFIGURATION_GENERIC_ERROR, + ERROR_CONFIGURATION_INVALID_YAML, + ERROR_CONFIGURATION_LOOPS_INVALID_RANGE, + ERROR_DISCOVERFILE_FILE_NOT_FOUND, + ERROR_EVALUATE_COMPILATION_FAILED, + ERROR_EVALUATE_NOT_BOOLEAN_VALUE, + ERROR_EXTRACTOR_IO_ERROR, + ERROR_FILETYPE_NOT_A_FILE, + ERROR_FILETYPE_UNKNOWN_EXTENSION, + ERROR_GETAPPLICATIONPATH_ENCODING_EXCEPTION, + ERROR_GETCANONICALFILE_IO_EXCEPTION, + ERROR_GETCANONICALPATH_IO_EXCEPTION, + ERROR_GETPARENTCANONICALPATH_IO_EXCEPTION, + ERROR_INTERPRETER_ARGUMENT_IS_REQUIRED, + ERROR_INTERPRETER_COMMAND_RUNTIME_ERROR, + ERROR_INTERPRETER_DEFAULT_VALUE_RUNTIME_ERROR, + ERROR_INTERPRETER_EXIT_RUNTIME_ERROR, + ERROR_INTERPRETER_FLAG_RUNTIME_EXCEPTION, + ERROR_INTERPRETER_NULL_COMMAND, + ERROR_INTERPRETER_RULE_NOT_FOUND, + ERROR_INTERPRETER_UNKNOWN_KEYS, + ERROR_INTERPRETER_WRONG_EXIT_CLOSURE_RETURN, + ERROR_LANGUAGE_INVALID_CODE, + ERROR_LOAD_COULD_NOT_LOAD_XML, + ERROR_PARSER_INVALID_PREAMBLE, + ERROR_PARSER_LOOPS_INVALID_RANGE, + ERROR_PARSER_LOOPS_NAN, + ERROR_PARSER_TIMEOUT_INVALID_RANGE, + ERROR_PARSER_TIMEOUT_NAN, + ERROR_PARSERULE_GENERIC_ERROR, + ERROR_PARSERULE_INVALID_YAML, + ERROR_REPLICATELIST_MISSING_FORMAT_ARGUMENTS_EXCEPTION, + ERROR_RULE_IDENTIFIER_AND_PATH, + ERROR_RUN_GENERIC_EXCEPTION, + ERROR_RUN_INTERRUPTED_EXCEPTION, + ERROR_RUN_INVALID_EXIT_VALUE_EXCEPTION, + ERROR_RUN_IO_EXCEPTION, + ERROR_RUN_TIMEOUT_EXCEPTION, + ERROR_RUN_TIMEOUT_INVALID_RANGE, + ERROR_SAVE_COULD_NOT_SAVE_XML, + ERROR_SESSION_OBTAIN_UNKNOWN_KEY, + ERROR_SESSION_REMOVE_UNKNOWN_KEY, + ERROR_TRIGGER_ACTION_NOT_FOUND, + ERROR_TRIGGER_CALL_EXCEPTION, + ERROR_VALIDATE_EMPTY_FILES_LIST, + ERROR_VALIDATE_FILE_IS_RESERVED, + ERROR_VALIDATE_FILES_IS_NOT_A_LIST, + ERROR_VALIDATE_INVALID_DIRECTIVE_FORMAT, + ERROR_VALIDATE_NO_DIRECTIVES_FOUND, + ERROR_VALIDATE_ORPHAN_LINEBREAK, + ERROR_VALIDATE_REFERENCE_IS_RESERVED, + ERROR_VALIDATE_YAML_EXCEPTION, + ERROR_VALIDATEBODY_ARGUMENT_ID_IS_RESERVED, + ERROR_VALIDATEBODY_ARGUMENTS_LIST, + ERROR_VALIDATEBODY_DUPLICATE_ARGUMENT_IDENTIFIERS, + ERROR_VALIDATEBODY_MISSING_KEYS, + ERROR_VALIDATEBODY_NULL_ARGUMENT_ID, + ERROR_VALIDATEBODY_NULL_COMMAND, + ERROR_VALIDATEBODY_NULL_COMMANDS_LIST, + ERROR_VALIDATEHEADER_NULL_ID, + ERROR_VALIDATEHEADER_NULL_NAME, + ERROR_VALIDATEHEADER_WRONG_IDENTIFIER, + ERROR_VELOCITY_FILE_NOT_FOUND, + ERROR_VELOCITY_PARSE_EXCEPTION, + ERROR_VELOCITY_METHOD_INVOCATION_EXCEPTION, + ERROR_VELOCITY_IO_EXCEPTION, + INFO_DISPLAY_EXCEPTION_MORE_DETAILS, + INFO_DISPLAY_EXECUTION_TIME, + INFO_DISPLAY_FILE_INFORMATION, + INFO_INTERPRETER_DRYRUN_MODE_SYSTEM_COMMAND, + INFO_INTERPRETER_DRYRUN_MODE_TRIGGER_MODE, + INFO_INTERPRETER_VERBOSE_MODE_TRIGGER_MODE, + INFO_LABEL_AUTHOR, + INFO_LABEL_AUTHORS, + INFO_LABEL_CONDITIONAL, + INFO_LABEL_NO_AUTHORS, + INFO_LABEL_ON_DETAILS, + INFO_LABEL_ON_ERROR, + INFO_LABEL_ON_FAILURE, + INFO_LABEL_ON_SUCCESS, + INFO_LABEL_UNNAMED_TASK, + INFO_PARSER_ALL_RIGHTS_RESERVED, + INFO_PARSER_DRYRUN_MODE_DESCRIPTION, + INFO_PARSER_HELP_DESCRIPTION, + INFO_PARSER_LANGUAGE_DESCRIPTION, + INFO_PARSER_LOG_DESCRIPTION, + INFO_PARSER_LOOPS_DESCRIPTION, + INFO_PARSER_NOTES, + INFO_PARSER_ONLY_HEADER, + INFO_PARSER_PREAMBLE_DESCRIPTION, + INFO_PARSER_SILENT_MODE_DESCRIPTION, + INFO_PARSER_TIMEOUT_DESCRIPTION, + INFO_PARSER_VERBOSE_MODE_DESCRIPTION, + INFO_PARSER_VERSION_DESCRIPTION, + LOG_INFO_BEGIN_BUFFER, + LOG_INFO_DIRECTIVES_BLOCK, + LOG_INFO_END_BUFFER, + LOG_INFO_INTERPRET_RULE, + LOG_INFO_INTERPRET_TASK, + LOG_INFO_POTENTIAL_DIRECTIVE_FOUND, + LOG_INFO_POTENTIAL_PATTERN_FOUND, + LOG_INFO_RULE_LOCATION, + LOG_INFO_SYSTEM_COMMAND, + LOG_INFO_TASK_RESULT, + LOG_INFO_VALIDATED_DIRECTIVES, + LOG_INFO_WELCOME_MESSAGE, + ERROR_CONFIGURATION_FILETYPE_MISSING_EXTENSION + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Pair.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Pair.java new file mode 100644 index 00000000000..d8591b6ef75 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Pair.java @@ -0,0 +1,92 @@ +/** + * 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; + +/** + * Implements a pair of objects. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Pair<T, V> { + + // first element of the pair + private final T firstElement; + + // second element of the pair + private final V secondElement; + + /** + * Constructor. + * @param firstElement The first element. + * @param secondElement The second element. + */ + public Pair(T firstElement, V secondElement) { + this.firstElement = firstElement; + this.secondElement = secondElement; + } + + /** + * Gets the first element. + * @return The first element. + */ + public T getFirstElement() { + return firstElement; + } + + /** + * Gets the second element. + * @return The second element. + */ + public V getSecondElement() { + return secondElement; + } + + /** + * A shorter version for getting the first element. + * @return The first element. + */ + public T first() { + return getFirstElement(); + } + + /** + * A shorter version for getting the second element. + * @return The second element. + */ + public V second() { + return getSecondElement(); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Parser.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Parser.java new file mode 100644 index 00000000000..723e24e76e4 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Parser.java @@ -0,0 +1,410 @@ +/** + * 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.controller.LoggingController; +import com.github.cereda.arara.utils.CommonUtils; +import com.github.cereda.arara.utils.DisplayUtils; +import java.util.Locale; +import java.util.Map; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; + +/** + * Implements the command line parser. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Parser { + + // command line arguments to be + // processed by this parser + private final String[] arguments; + + // command line options, it will + // group each option available + // in arara + private Options options; + + // each option available in + // arara + private Option version; + private Option help; + private Option log; + private Option verbose; + private Option silent; + private Option dryrun; + private Option timeout; + private Option language; + private Option loops; + private Option preamble; + private Option onlyheader; + + public Parser() { + this.arguments = null; + } + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Constructor. + * @param arguments Array of strings representing the command line + * arguments. + */ + public Parser(String[] arguments) { + this.arguments = arguments; + } + + /** + * Parses the command line arguments. + * @return A boolean value indicating if the parsing should allow the + * application to look for directives in the provided main file. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public boolean parse() throws AraraException { + + // create new instances of the + // command line options, including + // the ones that require arguments + version = new Option("V", "version", false, ""); + help = new Option("h", "help", false, ""); + log = new Option("l", "log", false, ""); + verbose = new Option("v", "verbose", false, ""); + silent = new Option("s", "silent", false, ""); + dryrun = new Option("n", "dry-run", false, ""); + timeout = new Option("t", "timeout", true, ""); + timeout.setArgName("number"); + language = new Option("L", "language", true, ""); + language.setArgName("code"); + loops = new Option("m", "max-loops", true, ""); + loops.setArgName("number"); + preamble = new Option("p", "preamble", true, ""); + preamble.setArgName("name"); + onlyheader = new Option("H", "header", false, ""); + + // add all options to the options + // group, so they are recognized + // by the command line parser + options = new Options(); + options.addOption(version); + options.addOption(help); + options.addOption(log); + options.addOption(verbose); + options.addOption(silent); + options.addOption(dryrun); + options.addOption(timeout); + options.addOption(language); + options.addOption(loops); + options.addOption(preamble); + options.addOption(onlyheader); + + // update all descriptions based + // on the localized messages + updateDescriptions(); + + // a new default command line + // parser is created and the + // arguments are parsed + CommandLineParser parser = new DefaultParser(); + + try { + + CommandLine line = parser.parse(options, arguments); + + String reference; + if (line.hasOption("language")) { + ConfigurationController.getInstance(). + put("execution.language", + new Language(line.getOptionValue("language")) + ); + Locale locale = ((Language) ConfigurationController. + getInstance().get("execution.language")).getLocale(); + messages.setLocale(locale); + updateDescriptions(); + } + + if (line.hasOption("help")) { + printVersion(); + printUsage(); + return false; + } + + if (line.hasOption("version")) { + printVersion(); + printNotes(); + return false; + } + + if (line.getArgs().length != 1) { + printVersion(); + printUsage(); + return false; + } else { + reference = line.getArgs()[0]; + } + + if (line.hasOption("timeout")) { + try { + long value = Long.parseLong(line.getOptionValue("timeout")); + if (value <= 0) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_PARSER_TIMEOUT_INVALID_RANGE + ) + ); + } else { + ConfigurationController.getInstance(). + put("execution.timeout", true); + ConfigurationController.getInstance(). + put("execution.timeout.value", value); + } + } catch (NumberFormatException nfexception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_PARSER_TIMEOUT_NAN + ) + ); + } + } + + if (line.hasOption("max-loops")) { + try { + long value = Long.parseLong( + line.getOptionValue("max-loops") + ); + if (value <= 0) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_PARSER_LOOPS_INVALID_RANGE + ) + ); + } else { + ConfigurationController.getInstance(). + put("execution.loops", value); + } + } catch (NumberFormatException nfexception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_PARSER_LOOPS_NAN + ) + ); + } + } + + if (line.hasOption("verbose")) { + ConfigurationController.getInstance(). + put("execution.verbose", true); + } + + if (line.hasOption("silent")) { + ConfigurationController.getInstance(). + put("execution.verbose", false); + } + + if (line.hasOption("dry-run")) { + ConfigurationController.getInstance(). + put("execution.dryrun", true); + ConfigurationController.getInstance(). + put("execution.errors.halt", false); + } + + if (line.hasOption("log")) { + ConfigurationController.getInstance(). + put("execution.logging", true); + } + + if (line.hasOption("preamble")) { + @SuppressWarnings("unchecked") + Map<String, String> preambles = (Map<String, String>) + ConfigurationController.getInstance(). + get("execution.preambles"); + if (preambles.containsKey(line.getOptionValue("preamble"))) { + ConfigurationController.getInstance(). + put("execution.preamble.active", true); + ConfigurationController.getInstance(). + put("execution.preamble.content", + preambles.get(line.getOptionValue("preamble")) + ); + } + else { + throw new AraraException( + messages.getMessage( + Messages.ERROR_PARSER_INVALID_PREAMBLE, + line.getOptionValue("preamble") + ) + ); + } + } + + if (line.hasOption("header")) { + ConfigurationController.getInstance(). + put("execution.header", true); + } + + CommonUtils.discoverFile(reference); + LoggingController.enableLogging((Boolean) ConfigurationController. + getInstance().get("execution.logging")); + ConfigurationController.getInstance().put("display.time", true); + + return true; + + } catch (ParseException pexception) { + printVersion(); + printUsage(); + return false; + } + } + + /** + * Prints the application usage. + */ + private void printUsage() { + HelpFormatter formatter = new HelpFormatter(); + StringBuilder builder = new StringBuilder(); + builder.append("arara [file [--dry-run] [--log] "); + builder.append("[--verbose | --silent] [--timeout N] "); + builder.append("[--max-loops N] [--language L] "); + builder.append("[ --preamble P ] [--header] | --help | --version]"); + formatter.printHelp(builder.toString(), options); + } + + /** + * Prints the application version. + */ + private void printVersion() { + String year = (String) ConfigurationController.getInstance(). + get("application.copyright.year"); + String number = (String) ConfigurationController.getInstance(). + get("application.version"); + String revision = (String) ConfigurationController.getInstance(). + get("application.revision"); + StringBuilder builder = new StringBuilder(); + builder.append("arara "); + builder.append(number); + builder.append(" (revision "); + builder.append(revision); + builder.append(")"); + builder.append("\n"); + builder.append("Copyright (c) ").append(year).append(", "); + builder.append("Paulo Roberto Massa Cereda"); + builder.append("\n"); + builder.append(messages.getMessage( + Messages.INFO_PARSER_ALL_RIGHTS_RESERVED) + ); + builder.append("\n"); + System.out.println(builder.toString()); + } + + /** + * Print the application notes. + */ + private void printNotes() { + DisplayUtils.wrapText(messages.getMessage(Messages.INFO_PARSER_NOTES)); + } + + /** + * Updates all the descriptions in order to make them reflect the current + * language setting. + */ + private void updateDescriptions() { + version.setDescription( + messages.getMessage( + Messages.INFO_PARSER_VERSION_DESCRIPTION + ) + ); + help.setDescription( + messages.getMessage( + Messages.INFO_PARSER_HELP_DESCRIPTION + ) + ); + log.setDescription( + messages.getMessage( + Messages.INFO_PARSER_LOG_DESCRIPTION + ) + ); + verbose.setDescription( + messages.getMessage( + Messages.INFO_PARSER_VERBOSE_MODE_DESCRIPTION + ) + ); + silent.setDescription( + messages.getMessage( + Messages.INFO_PARSER_SILENT_MODE_DESCRIPTION + ) + ); + dryrun.setDescription( + messages.getMessage( + Messages.INFO_PARSER_DRYRUN_MODE_DESCRIPTION + ) + ); + timeout.setDescription( + messages.getMessage( + Messages.INFO_PARSER_TIMEOUT_DESCRIPTION + ) + ); + language.setDescription( + messages.getMessage( + Messages.INFO_PARSER_LANGUAGE_DESCRIPTION + ) + ); + loops.setDescription( + messages.getMessage( + Messages.INFO_PARSER_LOOPS_DESCRIPTION + ) + ); + preamble.setDescription( + messages.getMessage( + Messages.INFO_PARSER_PREAMBLE_DESCRIPTION + ) + ); + onlyheader.setDescription( + messages.getMessage( + Messages.INFO_PARSER_ONLY_HEADER + ) + ); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Resource.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Resource.java new file mode 100644 index 00000000000..2994a4d6912 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Resource.java @@ -0,0 +1,291 @@ +/** + * 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.utils.CommonUtils; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Transformer; +import org.apache.commons.lang.SystemUtils; +import org.mvel2.templates.TemplateRuntime; + +/** + * Implements the configuration resource model. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Resource { + + // rule paths + private List<String> paths; + + // file types + private List<FileTypeResource> filetypes; + + // the application language + private String language; + + // maximum number of loops + private long loops; + + // verbose flag + private boolean verbose; + + // logging flag + private boolean logging; + + // database name + private String dbname; + + // log name + private String logname; + + // header flag + private boolean header; + + // map of preambles + private Map<String, String> preambles; + + // look and feel + private String laf; + + /** + * Gets the rule paths. + * @return The rule paths. + */ + public List<String> getPaths() { + if (paths != null) { + + final Map<String, Object> map = new HashMap<String, Object>(); + Map<String, Object> user = new HashMap<String, Object>(); + user.put("home", SystemUtils.USER_HOME); + user.put("dir", SystemUtils.USER_DIR); + user.put("name", SystemUtils.USER_NAME); + map.put("user", user); + + Collection<String> result = CollectionUtils.collect( + paths, new Transformer<String, String>() { + public String transform(String input) { + String path = CommonUtils.removeKeyword(input); + try { + path = (String) TemplateRuntime.eval(path, map); + } + catch (RuntimeException nothandled) { + // do nothing, gracefully fallback to + // the default, unparsed path + } + return path; + } + }); + paths = new ArrayList<String>(result); + } + return paths; + } + + /** + * Sets the rule paths. + * @param paths The rule paths. + */ + public void setPaths(List<String> paths) { + this.paths = paths; + } + + /** + * Gets the list of file types. + * @return The list of file types. + */ + public List<FileTypeResource> getFiletypes() { + return filetypes; + } + + /** + * Sets the list of file types. + * @param filetypes The list of file types. + */ + public void setFiletypes(List<FileTypeResource> filetypes) { + this.filetypes = filetypes; + } + + /** + * Gets the language. + * @return The language. + */ + public String getLanguage() { + return CommonUtils.removeKeyword(language); + } + + /** + * Sets the language. + * @param language The language. + */ + public void setLanguage(String language) { + this.language = language; + } + + /** + * Get the maximum number of loops. + * @return The maximum number of loops. + */ + public long getLoops() { + return loops; + } + + /** + * Sets the maximum number of loops. + * @param loops The maximum number of loops. + */ + public void setLoops(long loops) { + this.loops = loops; + } + + /** + * Checks if verbose mode is active. + * @return A boolean value. + */ + public boolean isVerbose() { + return verbose; + } + + /** + * Sets the verbose mode. + * @param verbose A boolean value. + */ + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + /** + * Checks if logging mode is active. + * @return A boolean value. + */ + public boolean isLogging() { + return logging; + } + + /** + * Sets the logging mode. + * @param logging A boolean value. + */ + public void setLogging(boolean logging) { + this.logging = logging; + } + + /** + * Gets the database name. + * @return The database name. + */ + public String getDbname() { + return CommonUtils.removeKeyword(dbname); + } + + /** + * Sets the database name. + * @param dbname The database name. + */ + public void setDbname(String dbname) { + this.dbname = dbname; + } + + /** + * Gets the log name. + * @return The log name. + */ + public String getLogname() { + return CommonUtils.removeKeyword(logname); + } + + /** + * Sets the log name. + * @param logname The log name. + */ + public void setLogname(String logname) { + this.logname = logname; + } + + /** + * Gets the map of preambles. + * @return Map of preambles. + */ + public Map<String, String> getPreambles() { + return preambles; + } + + /** + * Sets the map of preambles. + * @param preambles Map of preambles. + */ + public void setPreambles(Map<String, String> preambles) { + this.preambles = preambles; + } + + /** + * Gets the logical value of the header flag. + * @return Logical value of the header flag. + */ + public boolean isHeader() { + return header; + } + + /** + * Sets the logical value of the header flag. + * @param header The header flag. + */ + public void setHeader(boolean header) { + this.header = header; + } + + /** + * Gets the look and feel reference. + * @return The look and feel reference. + */ + public String getLaf() { + return CommonUtils.removeKeyword(laf); + } + + /** + * Sets the look and feel reference. + * @param laf The look and feel reference. + */ + public void setLaf(String laf) { + this.laf = laf; + } + + + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Rule.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Rule.java new file mode 100644 index 00000000000..af3ad199506 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Rule.java @@ -0,0 +1,155 @@ +/** + * 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.utils.CommonUtils; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Transformer; + +/** + * Implements the rule model. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Rule { + + // the rule identifier + private String identifier; + + // the rule name + private String name; + + // the list of authors + private List<String> authors; + + // the list of commands + private List<RuleCommand> commands; + + // the list of arguments + private List<Argument> arguments; + + /** + * Gets the rule identifier. + * @return The rule identifier. + */ + public String getIdentifier() { + return CommonUtils.removeKeyword(identifier); + } + + /** + * Sets the rule identifier. + * @param identifier The rule identifier. + */ + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + * Gets the rule identifier. + * @return The rule identifier. + */ + public String getName() { + return CommonUtils.removeKeyword(name); + } + + /** + * Sets the rule name. + * @param name The rule name. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Gets the list of authors. + * @return A list of authors. + */ + public List<String> getAuthors() { + if (authors != null) { + Collection<String> result = CollectionUtils.collect( + authors, new Transformer<String, String>() { + public String transform(String input) { + return CommonUtils.removeKeyword(input); + } + }); + authors = new ArrayList<String>(result); + } + return authors; + } + + /** + * Sets the list of authors. + * @param authors The list of authors. + */ + public void setAuthors(List<String> authors) { + this.authors = authors; + } + + /** + * Gets the list of commands. + * @return The list of commands. + */ + public List<RuleCommand> getCommands() { + return commands; + } + + /** + * Sets the list of commands. + * @param commands The list of commands. + */ + public void setCommands(List<RuleCommand> commands) { + this.commands = commands; + } + + /** + * Gets the list of arguments. + * @return The list of arguments. + */ + public List<Argument> getArguments() { + return arguments; + } + + /** + * Sets the list of arguments. + * @param arguments The list of arguments. + */ + public void setArguments(List<Argument> arguments) { + this.arguments = arguments; + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraCommand.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/RuleCommand.java index 80da972003d..b209d19bcb0 100644 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraCommand.java +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/RuleCommand.java @@ -1,7 +1,6 @@ /** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, Paulo Roberto Massa Cereda + * 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 @@ -31,69 +30,74 @@ * 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. - * \endcond - * - * AraraCommand: This class provides the model for commands to be executed by - * the runtime. It's a plain old Java object. */ -// package definition -package com.github.arara.model; +package com.github.cereda.arara.model; + +import com.github.cereda.arara.utils.CommonUtils; /** - * Provides the model for commands to be executed by the runtime. - * + * Implements the rule command model. * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 1.0 + * @version 4.0 + * @since 4.0 */ -public class AraraCommand { +public class RuleCommand { - // the name to be displayed in the command line + // the command name private String name; - // the command itself + + // the command instruction private String command; + + // the exit status expression + private String exit; /** - * Getter for command. - * - * @return The command to be executed by the runtime. + * Gets the command name. + * @return The command name. */ - public String getCommand() { + public String getName() { + return CommonUtils.removeKeyword(name); + } - // return it - return command; + /** + * Sets the command name. + * @param name The command name. + */ + public void setName(String name) { + this.name = name; } /** - * Setter for command. - * - * @param command The command, already expanded. + * Gets the command instruction. + * @return The command instruction. */ - public void setCommand(String command) { + public String getCommand() { + return CommonUtils.removeKeyword(command); + } - // set the command + /** + * Sets the command instruction. + * @param command The command instruction. + */ + public void setCommand(String command) { this.command = command; } /** - * Getter for the command name. - * - * @return The command name, provided by the rule. + * Gets the exit status expression. + * @return The exit status expression. */ - public String getName() { - - // return it - return name; + public String getExit() { + return CommonUtils.removeKeyword(exit); } /** - * Setter for the command name. - * - * @param name The command name. + * Sets the exit status expression. + * @param exit The exit status expression. */ - public void setName(String name) { - - // set the name - this.name = name; + public void setExit(String exit) { + this.exit = exit; } + } diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Session.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Session.java new file mode 100644 index 00000000000..c756ae4550e --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Session.java @@ -0,0 +1,122 @@ +/** + * 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.LanguageController; +import com.github.cereda.arara.controller.SessionController; + +/** + * Implements the session model. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Session { + + // get the current instance from the + // session controller + private static final SessionController session = + SessionController.getInstance(); + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Inserts the object into the session, indexed by the provided key. + * @param key The provided key. + * @param value The value to be inserted. + */ + public void insert(String key, Object value) { + session.put(key, value); + } + + /** + * Removes the entry indexed by the provided key from the session. + * @param key The provided key. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public void remove(String key) throws AraraException { + if (session.contains(key)) { + session.remove(key); + } else { + throw new AraraException( + messages.getMessage( + Messages.ERROR_SESSION_REMOVE_UNKNOWN_KEY, + key + ) + ); + } + } + + /** + * Checks if the provided key exists in the session. + * @param key The provided key. + * @return A boolean value indicating if the provided key exists in the + * session. + */ + public boolean exists(String key) { + return session.contains(key); + } + + /** + * Clears the session. + */ + public void forget() { + session.clear(); + } + + /** + * Gets the object indexed by the provided key from the session. + * @param key The provided key. + * @return The object indexed by the provided key. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public Object obtain(String key) throws AraraException { + if (session.contains(key)) { + return session.get(key); + } else { + throw new AraraException( + messages.getMessage( + Messages.ERROR_SESSION_OBTAIN_UNKNOWN_KEY, + key + ) + ); + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/StopWatch.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/StopWatch.java new file mode 100644 index 00000000000..45e0969d0b7 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/StopWatch.java @@ -0,0 +1,84 @@ +/** + * 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; + +/** + * Implements a stopwatch. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class StopWatch { + + // two variables indicating the + // times the stopwatch started + // and stopped + private static long beginning = 0; + private static long end = 0; + + // a variable to indicate the + // stopwatch is enabled; so far, + // it hasn't started, then it is + // not enabled + private static boolean enabled = false; + + /** + * Starts the stopwatch. + */ + public static void start() { + beginning = System.nanoTime(); + enabled = true; + } + + /** + * Stops the stopwatch. + */ + public static void stop() { + end = System.nanoTime(); + } + + /** + * Gets the string representation of the elapsed time. + * @return A string representation of the elapsed time. + */ + public static String getTime() { + Language language = (Language) ConfigurationController. + getInstance().get("execution.language"); + double result = enabled ? (double) (end - beginning) / 1000000000 : 0.0; + return String.format(language.getLocale(), "%1.2f", result); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Trigger.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Trigger.java new file mode 100644 index 00000000000..11da04bfcb9 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/model/Trigger.java @@ -0,0 +1,135 @@ +/** + * 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 java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +/** + * Implements the trigger model. The tool provides triggers, which are a way + * to alter its internal behaviour according to a list of parameters. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Trigger { + + // the action name and its + // list of parameters + private final String action; + private final List<Object> parameters; + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Constructor. + * @param action The action name. + * @param parameters The list of parameters. + */ + public Trigger(String action, List<Object> parameters) { + this.action = action; + this.parameters = parameters; + } + + /** + * Gets the action name. + * @return The action name. + */ + public String getAction() { + return action; + } + + /** + * Gets the list of parameters. + * @return The list of parameters. + */ + public List<Object> getParameters() { + return parameters; + } + + /** + * Returns a textual representation of the current trigger. + * @return A string containing a textual representation of the current + * trigger. + */ + @Override + public String toString() { + return "trigger"; + } + + /** + * Processes the current trigger. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public void process() throws AraraException { + + Map<String, Callable<Object>> mapping = + new HashMap<String, Callable<Object>>(); + mapping.put("halt", new Callable<Object>() { + public Object call() { + ConfigurationController.getInstance().put("trigger.halt", true); + return null; + } + }); + if (mapping.containsKey(action)) { + try { + mapping.get(action).call(); + } catch (Exception exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_TRIGGER_CALL_EXCEPTION, + action + ), + exception + ); + } + } else { + throw new AraraException( + messages.getMessage( + Messages.ERROR_TRIGGER_ACTION_NOT_FOUND, + action + ) + ); + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/ClassLoadingUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/ClassLoadingUtils.java new file mode 100644 index 00000000000..c40536ce08f --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/ClassLoadingUtils.java @@ -0,0 +1,166 @@ +/** + * 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.utils; + +import com.github.cereda.arara.model.Pair; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; + +/** + * Implements utilitary methods for classloading and object instantiation. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class ClassLoadingUtils { + + /** + * Loads a class from the provided file, potentially a Java archive. + * @param file File containing the Java bytecode (namely, a JAR). + * @param name The canonical name of the class. + * @return A pair representing the status and the class. + */ + public static Pair<Integer, Class> loadClass(File file, String name) { + + // status and class to be returned, + // it defaults to an object class + int status = 0; + Class value = Object.class; + + // if file does not exist, nothing + // can be done, status is changed + if (!file.exists()) { + status = 1; + } else { + + // classloading involves defining + // a classloader and fetching the + // desired class from it, based on + // the provided file archive + try { + + // creates a new classloader with + // the provided file (potentially + // a JAR file) + URLClassLoader classloader = new URLClassLoader( + new URL[]{ + file.toURI().toURL() + }, + ClassLoadingUtils.class.getClassLoader() + ); + + // fetches the class from the + // instantiated classloader + value = Class.forName(name, true, classloader); + + } catch (MalformedURLException nothandled1) { + + // the file URL is incorrect, + // update status accordingly + status = 2; + + } catch (ClassNotFoundException nothandled2) { + + // the class was not found, + // update status accordingly + status = 3; + + } + } + + // return a new pair based on the + // current status and class holder + return new Pair<Integer, Class>(status, value); + } + + /** + * Loads a class from the provided file, instantiating it. + * @param file File containing the Java bytecode (namely, a JAR). + * @param name The canonical name of the class. + * @return A pair representing the status and the class object. + */ + public static Pair<Integer, Object> loadObject(File file, String name) { + + // load the corresponding class + // based on the qualified name + Pair<Integer, Class> pair = loadClass(file, name); + + // status and object to be returned, + // it defaults to an object + int status = pair.getFirstElement(); + Object value = new Object(); + + // checks if the class actually + // exists, otherwise simply + // ignore instantiation + if (status == 0) { + + // object instantiation relies + // on the default constructor + // (without arguments), class + // must implement it + + // OBS: constructors with arguments + // must be invoked through reflection + try { + + // get the class reference from + // the pair and instantiate it + // by invoking the default + // constructor (without arguments) + value = pair.getSecondElement().newInstance(); + + } catch (IllegalAccessException nothandled1) { + + // the object instantiation violated + // an access policy, status is updated + status = 4; + + } catch (InstantiationException nothandled2) { + + // an instantiation exception has + // occurred, status is updated + status = 5; + + } + } + + // return a new pair based on the + // current status and object holder + return new Pair<Integer, Object>(status, value); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/CommonUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/CommonUtils.java new file mode 100644 index 00000000000..621634749ef --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/CommonUtils.java @@ -0,0 +1,929 @@ +/** + * 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.utils; + +import com.github.cereda.arara.controller.ConfigurationController; +import com.github.cereda.arara.controller.LanguageController; +import com.github.cereda.arara.controller.SystemCallController; +import com.github.cereda.arara.model.AraraException; +import com.github.cereda.arara.model.Argument; +import com.github.cereda.arara.model.Database; +import com.github.cereda.arara.model.FileType; +import com.github.cereda.arara.model.Messages; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.MissingFormatArgumentException; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Transformer; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.filefilter.NameFileFilter; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.SystemUtils; + +/** + * Implements common utilitary methods. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class CommonUtils { + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Checks if the input string is equal to a valid boolean value. + * @param value The input string. + * @return A boolean value represented by the provided string. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean checkBoolean(String value) throws AraraException { + List<String> yes = Arrays.asList( + new String[]{"yes", "true", "1", "on"} + ); + List<String> no = Arrays.asList( + new String[]{"no", "false", "0", "off"} + ); + if (!union(yes, no).contains(value.toLowerCase())) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_CHECKBOOLEAN_NOT_VALID_BOOLEAN, + value + ) + ); + } else { + return yes.contains(value.toLowerCase()); + } + } + + /** + * Provides a union set operation between two lists. + * @param <T> The list type. + * @param list1 The first list. + * @param list2 The second list. + * @return The union of those two lists. + */ + private static <T> List<T> union(List<T> list1, List<T> list2) { + Set<T> elements = new HashSet<T>(); + elements.addAll(list1); + elements.addAll(list2); + return new ArrayList<T>(elements); + } + + /** + * Build a system-dependant path based on the path and the file. + * @param path A string representing the path to be prepended. + * @param file A string representing the file to be appended. + * @return The full path as a string. + */ + public static String buildPath(String path, String file) { + return path.endsWith(File.separator) ? + path.concat(file) : path.concat(File.separator).concat(file); + } + + /** + * Checks if the provided string is empty. It does not handle a null value. + * @param string A string. + * @return A boolean value indicating if the string is empty. + */ + public static boolean checkEmptyString(String string) { + return "".equals(string); + } + + /** + * Removes the keyword from the beginning of the provided string. + * @param line A string to be analyzed. + * @return The provided string without the keyword. + */ + public static String removeKeyword(String line) { + if (line != null) { + Pattern pattern = Pattern.compile("^(\\s)*<arara>\\s"); + Matcher matcher = pattern.matcher(line); + if (matcher.find()) { + line = (line.substring(matcher.end(), line.length())); + } + line = line.trim(); + } + return line; + } + + /** + * Discovers the file through string reference lookup and sets the + * configuration accordingly. + * @param reference The string reference. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static void discoverFile(String reference) throws AraraException { + File file = lookupFile(reference); + if (file == null) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_DISCOVERFILE_FILE_NOT_FOUND, + reference, + getFileTypesList() + ) + ); + } + } + + /** + * Performs a file lookup based on a string reference. + * @param reference The file reference as a string. + * @return The file as result of the lookup operation. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + private static File lookupFile(String reference) throws AraraException { + @SuppressWarnings("unchecked") + List<FileType> types = (List<FileType>) ConfigurationController. + getInstance().get("execution.filetypes"); + File file = new File(reference); + String name = file.getName(); + String parent = getParentCanonicalPath(file); + String path = buildPath(parent, name); + + // direct search, so we are considering + // the reference as a complete name + for (FileType type : types) { + if (path.endsWith(".".concat(type.getExtension()))) { + file = new File(path); + if (file.exists()) { + if (file.isFile()) { + ConfigurationController. + getInstance(). + put("execution.file.pattern", + type.getPattern()); + ConfigurationController. + getInstance(). + put("execution.reference", file); + return file; + } + } + } + } + + // indirect search; in this case, we are considering + // that the file reference has an implict extension, + // so we need to add it and look again + for (FileType type : types) { + path = buildPath(parent, name.concat("."). + concat(type.getExtension())); + file = new File(path); + if (file.exists()) { + if (file.isFile()) { + ConfigurationController.getInstance(). + put("execution.file.pattern", type.getPattern()); + ConfigurationController.getInstance(). + put("execution.reference", file); + return file; + } + } + } + return null; + } + + /** + * Gets the parent canonical path of a file. + * @param file The file. + * @return The parent canonical path of a file. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static String getParentCanonicalPath(File file) + throws AraraException { + try { + String path = file.getCanonicalFile().getParent(); + return path; + } catch (IOException exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_GETPARENTCANONICALPATH_IO_EXCEPTION + ), + exception + ); + } + } + + /** + * Gets the canonical file from a file. + * @param file The file. + * @return The canonical file. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static File getCanonicalFile(String file) throws AraraException { + try { + return (new File(file)).getCanonicalFile(); + } catch (IOException exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_GETCANONICALFILE_IO_EXCEPTION + ), + exception + ); + } + } + + /** + * Checks if the provided object is from a certain class. + * @param clazz The class. + * @param object The object. + * @return A boolean value indicating if the provided object is from a + * certain class. + */ + public static boolean checkClass(Class clazz, Object object) { + return clazz.isInstance(object); + } + + /** + * Helper method to flatten a potential list of lists into a list of + * objects. + * @param list First list. + * @param flat Second list. + */ + private static void flatten(List<?> list, List<Object> flat) { + for (Object item : list) { + if (item instanceof List<?>) { + flatten((List<?>) item, flat); + } else { + flat.add(item); + } + } + } + + /** + * Flattens a potential list of lists into a list of objects. + * @param list The list to be flattened. + * @return The flattened list. + */ + public static List<Object> flatten(List<?> list) { + List<Object> result = new ArrayList<Object>(); + flatten(list, result); + return result; + } + + /** + * Gets the list of file types, in order. + * @return A string representation of the list of file types, in order. + */ + public static String getFileTypesList() { + @SuppressWarnings("unchecked") + List<FileType> types = (List<FileType>) ConfigurationController. + getInstance().get("execution.filetypes"); + return getCollectionElements(types, "[ ", " ]", " | "); + } + + /** + * Gets a string representation of a collection. + * @param collection The collection. + * @param open The opening string. + * @param close The closing string. + * @param separator The element separator. + * @return A string representation of the provided collection. + */ + public static String getCollectionElements(Collection collection, + String open, String close, String separator) { + StringBuilder builder = new StringBuilder(); + builder.append(open); + builder.append(StringUtils.join(collection, separator)); + builder.append(close); + return builder.toString(); + } + + /** + * Gets a set of strings containing unknown keys from a map and a list. It + * is a set difference from the keys in the map and the entries in the list. + * @param parameters The map of parameters. + * @param arguments The list of arguments. + * @return A set of strings representing unknown keys from a map and a list. + */ + public static Set<String> getUnknownKeys(Map<String, Object> parameters, + List<Argument> arguments) { + Collection<String> found = parameters.keySet(); + Collection<String> expected = CollectionUtils.collect( + arguments, new Transformer<Argument, String>() { + public String transform(Argument argument) { + return argument.getIdentifier(); + } + }); + Collection<String> difference = CollectionUtils. + subtract(found, expected); + return new HashSet<String>(difference); + } + + /** + * Gets the rule error header, containing the identifier and the path, if + * any. + * @return A string representation of the rule error header, containing the + * identifier and the path, if any. + */ + public static String getRuleErrorHeader() { + if ((ConfigurationController.getInstance(). + contains("execution.info.rule.id")) && + (ConfigurationController.getInstance(). + contains("execution.info.rule.path"))) { + String id = (String) ConfigurationController.getInstance(). + get("execution.info.rule.id"); + String path = (String) ConfigurationController.getInstance(). + get("execution.info.rule.path"); + return messages.getMessage( + Messages.ERROR_RULE_IDENTIFIER_AND_PATH, + id, + path + ).concat(" "); + } else { + return ""; + } + } + + /** + * Trims spaces from every string of a list of strings. + * @param input The list of strings. + * @return A new list of strings, with each element trimmed. + */ + public static List<String> trimSpaces(List<String> input) { + Collection<String> result = CollectionUtils.collect( + input, new Transformer<String, String>() { + public String transform(String input) { + return input.trim(); + } + }); + return new ArrayList<String>(result); + } + + /** + * Gets a human readable representation of a file size. + * @param file The file. + * @return A string representation of the file size. + */ + public static String calculateFileSize(File file) { + return FileUtils.byteCountToDisplaySize(file.length()); + } + + /** + * Gets the date the provided file was last modified. + * @param file The file. + * @return A string representation of the date the provided file was last + * modified. + */ + public static String getLastModifiedInformation(File file) { + SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); + return format.format(file.lastModified()); + } + + /** + * Gets a list of all rule paths. + * @return A list of all rule paths. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static List<String> getAllRulePaths() throws AraraException { + @SuppressWarnings("unchecked") + List<String> paths = (List<String>) ConfigurationController. + getInstance().get("execution.rule.paths"); + List<String> result = new ArrayList<String>(); + for (String path : paths) { + File location = new File(InterpreterUtils.construct(path, "quack")); + result.add(getParentCanonicalPath(location)); + } + return result; + } + + /** + * Gets the reference of the current file in execution. Note that this + * method might return a value different than the main file provided in + * the command line. + * @return A reference of the current file in execution. Might be different + * than the main file provided in the command line. + */ + private static File getCurrentReference() { + return (File) ConfigurationController.getInstance(). + get("execution.file"); + } + + /** + * Calculates the CRC32 checksum of the provided file. + * @param file The file. + * @return A string containing the CRC32 checksum of the provided file. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static String calculateHash(File file) throws AraraException { + try { + long result = FileUtils.checksumCRC32(file); + return String.format("%08x", result); + } catch (IOException exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_CALCULATEHASH_IO_EXCEPTION + ), + exception + ); + } + } + + /** + * Gets the file type of a file. + * @param file The file. + * @return The corresponding file type. + */ + public static String getFiletype(File file) { + return getFiletype(file.getName()); + } + + /** + * Gets the file type of a string representing the file. + * @param name A string representing the file. + * @return The corresponding file type. + */ + public static String getFiletype(String name) { + name = name.lastIndexOf(".") != -1 ? + name.substring(name.lastIndexOf(".") + 1, name.length()) : ""; + return name; + } + + /** + * Gets the base name of a file. + * @param file The file. + * @return The corresponding base name. + */ + public static String getBasename(File file) { + return getBasename(file.getName()); + } + + /** + * Gets the base name of a string representing the file. + * @param name A string representing the file. + * @return The corresponding base name. + */ + public static String getBasename(String name) { + int index = name.lastIndexOf(".") != -1 ? + name.lastIndexOf(".") : name.length(); + return name.substring(0, index); + } + + /** + * Encloses the provided object in double quotes. + * @param object The object. + * @return A string representation of the provided object enclosed in double + * quotes. + */ + public static String addQuotes(Object object) { + return "\"".concat(String.valueOf(object)).concat("\""); + } + + /** + * Generates a string based on a list of objects, separating each one of + * them by one space. + * @param objects A list of objects. + * @return A string based on the list of objects, separating each one of + * them by one space. Empty values are not considered. + */ + public static String generateString(Object... objects) { + List<String> values = new ArrayList<String>(); + for (Object object : objects) { + if (!CommonUtils.checkEmptyString(String.valueOf(object))) { + values.add(String.valueOf(object)); + } + } + return StringUtils.join(values, " "); + } + + /** + * Checks if a file exists. + * @param file The file. + * @return A boolean value indicating if the file exists. + */ + public static boolean exists(File file) { + return file.exists(); + } + + /** + * Checks if a file exists based on its extension. + * @param extension The extension. + * @return A boolean value indicating if the file exists. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean exists(String extension) throws AraraException { + File file = new File(getPath(extension)); + return file.exists(); + } + + /** + * Checks if a file has changed since the last verification. + * @param file The file. + * @return A boolean value indicating if the file has changed since the last + * verification. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean hasChanged(File file) throws AraraException { + Database database = DatabaseUtils.load(); + HashMap<String, String> map = database.getMap(); + String path = getCanonicalPath(file); + if (!file.exists()) { + if (map.containsKey(path)) { + map.remove(path); + database.setMap(map); + DatabaseUtils.save(database); + return true; + } else { + return false; + } + } else { + String hash = calculateHash(file); + if (map.containsKey(path)) { + String value = map.get(path); + if (hash.equals(value)) { + return false; + } else { + map.put(path, hash); + database.setMap(map); + DatabaseUtils.save(database); + return true; + } + } else { + map.put(path, hash); + database.setMap(map); + DatabaseUtils.save(database); + return true; + } + } + } + + /** + * Checks if the file has changed since the last verification based on the + * provided extension. + * @param extension The provided extension. + * @return A boolean value indicating if the file has changed since the last + * verification. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean hasChanged(String extension) throws AraraException { + File file = new File(getPath(extension)); + return hasChanged(file); + } + + /** + * Gets the full file path based on the provided extension. + * @param extension The extension. + * @return A string containing the full file path. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + private static String getPath(String extension) throws AraraException { + String name = getBasename(getCurrentReference()); + String path = getParentCanonicalPath(getCurrentReference()); + name = name.concat(".").concat(extension); + return buildPath(path, name); + } + + /** + * Gets the canonical path from the provided file. + * @param file The file. + * @return The canonical path from the provided file. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static String getCanonicalPath(File file) throws AraraException { + try { + return file.getCanonicalPath(); + } catch (IOException exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_GETCANONICALPATH_IO_EXCEPTION + ), + exception + ); + } + } + + /** + * Checks if the file based on the provided extension contains the provided + * regex. + * @param extension The file extension. + * @param regex The regex. + * @return A boolean value indicating if the file contains the provided + * regex. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean checkRegex(String extension, String regex) + throws AraraException { + File file = new File(getPath(extension)); + return checkRegex(file, regex); + } + + /** + * Checks if the file contains the provided regex. + * @param file The file. + * @param regex The regex. + * @return A boolean value indicating if the file contains the provided + * regex. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean checkRegex(File file, String regex) + throws AraraException { + Charset charset = (Charset) ConfigurationController. + getInstance().get("directives.charset"); + try { + String text = FileUtils.readFileToString(file, charset.name()); + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(text); + return matcher.find(); + } catch (IOException exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_CHECKREGEX_IO_EXCEPTION, + file.getName() + ), + exception + ); + } + } + + /** + * Replicates a string pattern based on a list of objects, generating a list + * as result. + * @param pattern The string pattern. + * @param values The list of objects to be merged with the pattern. + * @return A list containing the string pattern replicated to each object + * from the list. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static List<Object> replicateList(String pattern, + List<Object> values) throws AraraException { + List<Object> result = new ArrayList<Object>(); + for (Object value : values) { + try { + result.add(String.format(pattern, value)); + } catch (MissingFormatArgumentException exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_REPLICATELIST_MISSING_FORMAT_ARGUMENTS_EXCEPTION + ), + exception + ); + } + } + return result; + } + + /** + * Checks if the provided operating system string holds according to the + * underlying operating system. + * @param value A string representing an operating system. + * @return A boolean value indicating if the provided string refers to the + * underlying operating system. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean checkOS(String value) throws AraraException { + Map<String, Boolean> values = new HashMap<String, Boolean>(); + values.put("windows", SystemUtils.IS_OS_WINDOWS); + values.put("linux", SystemUtils.IS_OS_LINUX); + values.put("mac", SystemUtils.IS_OS_MAC_OSX); + values.put("unix", SystemUtils.IS_OS_UNIX); + values.put("aix", SystemUtils.IS_OS_AIX); + values.put("irix", SystemUtils.IS_OS_IRIX); + values.put("os2", SystemUtils.IS_OS_OS2); + values.put("solaris", SystemUtils.IS_OS_SOLARIS); + values.put("cygwin", (Boolean) SystemCallController. + getInstance().get("cygwin")); + if (!values.containsKey(value.toLowerCase())) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_CHECKOS_INVALID_OPERATING_SYSTEM, + value + ) + ); + } + return values.get(value.toLowerCase()); + } + + /** + * Returns the exit status of the application. + * @return An integer representing the exit status of the application. + */ + public static int getExitStatus() { + return (Integer) ConfigurationController. + getInstance().get("execution.status"); + } + + /** + * Gets the system property according to the provided key, or resort to the + * fallback value if an exception is thrown or if the key is invalid. + * @param key The system property key. + * @param fallback The fallback value. + * @return A string containing the system property value or the fallback. + */ + public static String getSystemProperty(String key, String fallback) { + try { + String result = System.getProperty(key, fallback); + return result.equals("") ? fallback : result; + } catch (Exception exception) { + return fallback; + } + } + + /** + * Gets the preamble content, converting a single string into a list of + * strings, based on new lines. + * @return A list of strings representing the preamble content. + */ + public static List<String> getPreambleContent() { + if (((Boolean) ConfigurationController. + getInstance().get("execution.preamble.active")) == true) { + return new ArrayList<String>( + Arrays.asList( + ((String) ConfigurationController.getInstance(). + get("execution.preamble.content") + ).split("\n")) + ); + } + else { + return new ArrayList<String>(); + } + } + + /** + * Generates a list of filenames from the provided command based on a list + * of extensions for each underlying operating system. + * @param command A string representing the command. + * @return A list of filenames. + */ + private static List<String> appendExtensions(String command) { + + // the resulting list, to hold the + // filenames generated from the + // provided command + List<String> result = new ArrayList<String>(); + + // list of extensions, specific for + // each operating system (in fact, it + // is more Windows specific) + List<String> extensions; + + // the application is running on + // Windows, so let's look for the + // following extensions in order + if (SystemUtils.IS_OS_WINDOWS) { + + // this list is actually a sublist from + // the original Windows PATHEXT environment + // variable which holds the list of executable + // extensions that Windows supports + extensions = Arrays.asList(".com", ".exe", ".bat", ".cmd"); + } + else { + + // no Windows, so the default + // extension will be just an + // empty string + extensions = Arrays.asList(""); + } + + // for each and every extension in the + // list, let's build the corresponding + // filename and add to the result + for (String extension : extensions) { + result.add(command.concat(extension)); + } + + // return the resulting list + // holding the filenames + return result; + } + + /** + * Checks if the provided command name is reachable from the system path. + * @param command A string representing the command. + * @return A logic value. + */ + public static boolean isOnPath(String command) { + try { + + // first and foremost, let's build the list + // of filenames based on the underlying + // operating system + List<String> filenames = appendExtensions(command); + + // break the path into several parts + // based on the path separator symbol + StringTokenizer tokenizer = new StringTokenizer( + System.getenv("PATH"), + File.pathSeparator + ); + + // iterate through every part of the + // path looking for each filename + while (tokenizer.hasMoreTokens()) { + + // if the search does not return an empty + // list, one of the filenames got a match, + // and the command is available somewhere + // in the system path + if ( + !FileUtils.listFiles( + new File(tokenizer.nextToken()), + new NameFileFilter(filenames), + null + ).isEmpty()) { + + // command is found somewhere, + // so it is on path + return true; + } + } + + // nothing was found, + // command is not on path + return false; + } + catch (Exception exception) { + + // an exception was raised, simply + // return and forget about it + return false; + } + } + + /** + * Gets the full base name of a file. + * @param file The file. + * @return The corresponding full base name. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static String getFullBasename(File file) throws AraraException { + + // if the provided file does not contain a + // file separator, fallback to the usual + // base name lookup + if (!file.toString().contains(File.separator)) { + return getBasename(file); + } + else { + + // we need to get the parent file, get the + // canonical path and build the corresponding + // full base name path + File parent = file.getParentFile(); + String path = getCanonicalPath(parent == null ? file : parent); + return buildPath(path, getBasename(file)); + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/ConfigurationUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/ConfigurationUtils.java new file mode 100644 index 00000000000..0b7d3b8a5b4 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/ConfigurationUtils.java @@ -0,0 +1,239 @@ +/** + * 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.utils; + +import com.github.cereda.arara.Arara; +import com.github.cereda.arara.controller.LanguageController; +import com.github.cereda.arara.model.AraraException; +import com.github.cereda.arara.model.FileType; +import com.github.cereda.arara.model.FileTypeResource; +import com.github.cereda.arara.model.Messages; +import com.github.cereda.arara.model.Resource; +import java.io.File; +import java.io.FileReader; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.lang.SystemUtils; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.error.MarkedYAMLException; +import org.yaml.snakeyaml.nodes.Tag; +import org.yaml.snakeyaml.representer.Representer; + +/** + * Implements configuration utilitary methods. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class ConfigurationUtils { + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Gets the list of default file types provided by nightingale, in order. + * @return The list of default file types, in order. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static List<FileType> getDefaultFileTypes() throws AraraException { + return Arrays.asList( + new FileType("tex"), + new FileType("dtx"), + new FileType("ltx"), + new FileType("drv"), + new FileType("ins") + ); + } + + /** + * Gets the configuration file located at the user home directory, if any. + * @return The file reference to the external configuration, if any. + */ + public static File getConfigFile() { + List<String> names = Arrays.asList( + ".araraconfig.yaml", + "araraconfig.yaml", + ".arararc.yaml", + "arararc.yaml" + ); + + // look for configuration files in the user's working directory first + for (String name : names) { + String path = CommonUtils.buildPath(SystemUtils.USER_DIR, name); + File file = new File(path); + if (file.exists()) { + return file; + } + } + + // if no configuration files are found in the user's working directory, + // try to look up in a global directory, that is, the user home + for (String name : names) { + String path = CommonUtils.buildPath(SystemUtils.USER_HOME, name); + File file = new File(path); + if (file.exists()) { + return file; + } + } + return null; + } + + /** + * Validates the configuration file. + * @param file The configuration file. + * @return The configuration file as a resource. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Resource validateConfiguration(File file) + throws AraraException { + + Representer representer = new Representer(); + representer.addClassTag(Resource.class, new Tag("!config")); + Yaml yaml = new Yaml(new Constructor(Resource.class), representer); + try { + Resource resource = yaml.loadAs(new FileReader(file), + Resource.class); + if (resource.getFiletypes() != null) { + List<FileTypeResource> filetypes = resource.getFiletypes(); + if (CollectionUtils.exists(filetypes, + new Predicate<FileTypeResource>() { + public boolean evaluate(FileTypeResource filetype) { + return (filetype.getExtension() == null); + } + })) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_CONFIGURATION_FILETYPE_MISSING_EXTENSION + ) + ); + } + } + return resource; + } catch (MarkedYAMLException yamlException) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_CONFIGURATION_INVALID_YAML + ), + yamlException + ); + } catch (Exception exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_CONFIGURATION_GENERIC_ERROR + ) + ); + } + } + + /** + * Normalize a list of rule paths, removing all duplicates. + * @param paths The list of rule paths. + * @return A list of normalized paths, without duplicates. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static List<String> normalizePaths(List<String> paths) + throws AraraException { + paths.add(CommonUtils.buildPath(getApplicationPath(), "rules")); + Set<String> set = new LinkedHashSet<String>(paths); + List<String> result = new ArrayList<String>(set); + return result; + } + + /** + * Normalize a list of file types, removing all duplicates. + * @param types The list of file types. + * @return A list of normalized file types, without duplicates. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static List<FileType> normalizeFileTypes(List<FileType> types) + throws AraraException { + types.addAll(getDefaultFileTypes()); + Set<FileType> set = new LinkedHashSet<FileType>(types); + List<FileType> result = new ArrayList<FileType>(set); + return result; + } + + /** + * Gets the canonical absolute application path. + * @return The string representation of the canonical absolute application + * path. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static String getApplicationPath() throws AraraException { + try { + String path = Arara.class.getProtectionDomain(). + getCodeSource().getLocation().getPath(); + path = URLDecoder.decode(path, "UTF-8"); + path = new File(path).getParentFile().getPath(); + return path; + } catch (UnsupportedEncodingException exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_GETAPPLICATIONPATH_ENCODING_EXCEPTION + ), + exception + ); + } + } + + /** + * Cleans the file name to avoid invalid entries. + * @param name The file name. + * @return A cleaned file name. + */ + public static String cleanFileName(String name) { + String result = (new File(name)).getName().trim(); + if (CommonUtils.checkEmptyString(result)) { + return "arara"; + } else { + return result.trim(); + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DatabaseUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DatabaseUtils.java new file mode 100644 index 00000000000..8861ff7e5ee --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DatabaseUtils.java @@ -0,0 +1,140 @@ +/** + * 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.utils; + +import com.github.cereda.arara.controller.ConfigurationController; +import com.github.cereda.arara.controller.LanguageController; +import com.github.cereda.arara.model.AraraException; +import com.github.cereda.arara.model.Database; +import com.github.cereda.arara.model.Messages; +import java.io.File; +import org.simpleframework.xml.Serializer; +import org.simpleframework.xml.core.Persister; + +/** + * Implements database utilitary methods. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class DatabaseUtils { + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Loads the XML file representing the database. + * @return The database object. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Database load() throws AraraException { + if (!exists()) { + return new Database(); + } else { + File file = new File(getPath()); + try { + Serializer serializer = new Persister(); + Database database = serializer.read(Database.class, file); + return database; + } catch (Exception exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_LOAD_COULD_NOT_LOAD_XML, + file.getName() + ), + exception + ); + } + } + } + + /** + * Saves the database on a XML file. + * @param database The database object. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static void save(Database database) throws AraraException { + File file = new File(getPath()); + try { + Serializer serializer = new Persister(); + serializer.write(database, file); + } catch (Exception exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_SAVE_COULD_NOT_SAVE_XML, + file.getName() + ), + exception + ); + } + } + + /** + * Checks if the XML file representing the database exists. + * @return A boolean value indicating if the XML file exists. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + private static boolean exists() throws AraraException { + File file = new File(getPath()); + return file.exists(); + } + + /** + * Gets the path to the XML file representing the database. + * @return A string representing the path to the XML file. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + private static String getPath() throws AraraException { + String name = ((String) ConfigurationController. + getInstance().get("execution.database.name")).concat(".xml"); + String path = CommonUtils.getParentCanonicalPath(getReference()); + return CommonUtils.buildPath(path, name); + } + + /** + * Gets the main file reference. + * @return The main file reference. + */ + private static File getReference() { + return (File) ConfigurationController. + getInstance().get("execution.reference"); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraTask.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DirectiveAssembler.java index cd8c8d674b0..d2dd5889967 100644 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/model/AraraTask.java +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DirectiveAssembler.java @@ -1,7 +1,6 @@ /** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, Paulo Roberto Massa Cereda + * 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 @@ -31,79 +30,77 @@ * 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. - * \endcond - * - * AraraTask: This class provides the model for representing the Arara tasks - * based on the directives and rules. It's a plain old Java object. */ -// package definition -package com.github.arara.model; +package com.github.cereda.arara.utils; -// needed import -import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; /** - * Provides the model for representing the Arara tasks based on the directives - * and rules. - * + * Implements a directive assembler in order to help build a directive from a + * list of strings. * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 1.0 + * @version 4.0 + * @since 4.0 */ -public class AraraTask { +public class DirectiveAssembler { - // the task name - private String name; - // a map to hold the tasks parameters - private HashMap parameters; + // this variable holds a list of + // line numbers indicating which + // lines composed the resulting + // potential directive + private final List<Integer> lineNumbers; + + // this variable holds the textual + // representation of the directive + private String text; /** - * Empty constructor. + * Constructor. */ - public AraraTask() { + public DirectiveAssembler() { + lineNumbers = new ArrayList<Integer>(); + text = ""; } - /** - * Getter for name. - * - * @return The task name. + /** + * Checks if an append operation is allowed. + * @return A boolean value indicating if an append operation is allowed. */ - public String getName() { - - // return it - return name; + public boolean isAppendAllowed() { + return !lineNumbers.isEmpty(); } /** - * Setter for name. - * - * @param name The task name. + * Adds a line number to the assembler. + * @param line An integer representing the line number. */ - public void setName(String name) { - - // set the name - this.name = name; + public void addLineNumber(int line) { + lineNumbers.add(line); } /** - * Getter for parameters. - * - * @return A map containing all the task parameters. + * Appends the provided line to the assembler text. + * @param line The provided line. */ - public HashMap getParameters() { - - // return it - return parameters; + public void appendLine(String line) { + text = text.concat(" ").concat(line.trim()); } /** - * Setter for parameters. - * - * @param parameters The task parameters as a map. + * Gets the list of line numbers. + * @return The list of line numbers. */ - public void setParameters(HashMap parameters) { + public List<Integer> getLineNumbers() { + return lineNumbers; + } - // set parameters - this.parameters = parameters; + /** + * Gets the text. + * @return The assembler text, properly trimmed. + */ + public String getText() { + return text.trim(); } + } diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraResolver.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DirectiveResolver.java index 6ac807f6564..6ea18e31ba5 100644 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/AraraResolver.java +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DirectiveResolver.java @@ -1,7 +1,6 @@ /** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, Paulo Roberto Massa Cereda + * 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 @@ -31,44 +30,30 @@ * 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. - * \endcond - * - * AraraResolver: This class extends a Resolver class to disable mapping of - * numeric times, as arara works better with text. */ -// package definition -package com.github.arara.utils; +package com.github.cereda.arara.utils; -// needed import import org.yaml.snakeyaml.nodes.Tag; import org.yaml.snakeyaml.resolver.Resolver; /** - * Extends a Resolver class to disable mapping of numeric times, as Arara works - * better with text. - * + * This class implements a directive resolver. * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 1.0 + * @version 4.0 + * @since 4.0 */ -public class AraraResolver extends Resolver { +public class DirectiveResolver extends Resolver { /** - * Adds the implicit resolvers to the Yaml mechanism. + * Adds implicit resolvers to the YAML model. For arara, I disabled + * boolean and numeric values to be automatically parsed. They still can + * be used through an explicit conversion in the rule context. */ @Override protected void addImplicitResolvers() { - - // for merges addImplicitResolver(Tag.MERGE, MERGE, "<"); - - // for null values addImplicitResolver(Tag.NULL, NULL, "~nN\0"); - - // for empty values addImplicitResolver(Tag.NULL, EMPTY, null); - - // for values - addImplicitResolver(Tag.VALUE, VALUE, "="); } + } diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DirectiveUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DirectiveUtils.java new file mode 100644 index 00000000000..d4d2a88ac7e --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DirectiveUtils.java @@ -0,0 +1,438 @@ +/** + * 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.utils; + +import com.github.cereda.arara.controller.ConfigurationController; +import com.github.cereda.arara.controller.LanguageController; +import com.github.cereda.arara.model.AraraException; +import com.github.cereda.arara.model.Conditional; +import com.github.cereda.arara.model.Directive; +import com.github.cereda.arara.model.Messages; +import com.github.cereda.arara.model.Pair; +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.error.MarkedYAMLException; +import org.yaml.snakeyaml.representer.Representer; + +/** + * Implements directive utilitary methods. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class DirectiveUtils { + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + // get the logger context from a factory + private static final Logger logger = + LoggerFactory.getLogger(DirectiveUtils.class); + + /** + * Extracts a list of directives from a list of strings. + * @param lines List of strings. + * @return A list of directives. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static List<Directive> extractDirectives(List<String> lines) + throws AraraException { + + boolean header = (Boolean) ConfigurationController. + getInstance().get("execution.header"); + String regex = (String) ConfigurationController. + getInstance().get("execution.file.pattern"); + Pattern linecheck = Pattern.compile(regex); + regex = regex.concat((String) ConfigurationController. + getInstance().get("application.pattern")); + Pattern pattern = Pattern.compile(regex); + List<Pair<Integer, String>> pairs = + new ArrayList<Pair<Integer, String>>(); + Matcher matcher; + for (int i = 0; i < lines.size(); i++) { + matcher = pattern.matcher(lines.get(i)); + if (matcher.find()) { + String line = lines.get(i).substring( + matcher.end(), + lines.get(i).length() + ); + Pair<Integer, String> pair = + new Pair<Integer, String>(i + 1, line); + pairs.add(pair); + + logger.info( + messages.getMessage( + Messages.LOG_INFO_POTENTIAL_PATTERN_FOUND, + (i + 1), + line.trim() + ) + ); + } + else { + if (header) { + if (!checkLinePattern(linecheck, lines.get(i))) { + break; + } + } + } + } + + if (pairs.isEmpty()) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VALIDATE_NO_DIRECTIVES_FOUND + ) + ); + } + + List<DirectiveAssembler> assemblers + = new ArrayList<DirectiveAssembler>(); + DirectiveAssembler assembler = new DirectiveAssembler(); + regex = (String) ConfigurationController.getInstance(). + get("directives.linebreak.pattern"); + pattern = Pattern.compile(regex); + for (Pair<Integer, String> pair : pairs) { + matcher = pattern.matcher(pair.getSecondElement()); + if (matcher.find()) { + if (!assembler.isAppendAllowed()) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VALIDATE_ORPHAN_LINEBREAK, + pair.getFirstElement() + ) + ); + } else { + assembler.addLineNumber(pair.getFirstElement()); + assembler.appendLine(matcher.group(1)); + } + } else { + if (assembler.isAppendAllowed()) { + assemblers.add(assembler); + } + assembler = new DirectiveAssembler(); + assembler.addLineNumber(pair.getFirstElement()); + assembler.appendLine(pair.getSecondElement()); + } + } + if (assembler.isAppendAllowed()) { + assemblers.add(assembler); + } + + List<Directive> directives = new ArrayList<Directive>(); + for (DirectiveAssembler current : assemblers) { + directives.add(generateDirective(current)); + } + return directives; + + } + + /** + * Generates a directive from a directive assembler. + * @param assembler The directive assembler. + * @return The corresponding directive. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Directive generateDirective(DirectiveAssembler assembler) + throws AraraException { + String regex = (String) ConfigurationController.getInstance(). + get("directives.pattern"); + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(assembler.getText()); + if (matcher.find()) { + Directive directive = new Directive(); + directive.setIdentifier(matcher.group(1)); + directive.setParameters( + getParameters(matcher.group(3), assembler.getLineNumbers()) + ); + Conditional conditional = new Conditional(); + conditional.setType(getType(matcher.group(5))); + conditional.setCondition(getCondition(matcher.group(6))); + directive.setConditional(conditional); + directive.setLineNumbers(assembler.getLineNumbers()); + + logger.info( + messages.getMessage( + Messages.LOG_INFO_POTENTIAL_DIRECTIVE_FOUND, + directive + ) + ); + + return directive; + } else { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VALIDATE_INVALID_DIRECTIVE_FORMAT, + CommonUtils.getCollectionElements( + assembler.getLineNumbers(), + "(", + ")", + ", " + ) + ) + ); + } + } + + /** + * Gets the conditional type based on the input string. + * @param text The input string. + * @return The conditional type. + */ + private static Conditional.ConditionalType getType(String text) { + if (text == null) { + return Conditional.ConditionalType.NONE; + } else { + if (text.equals("if")) { + return Conditional.ConditionalType.IF; + } else { + if (text.equals("while")) { + return Conditional.ConditionalType.WHILE; + } else { + if (text.equals("until")) { + return Conditional.ConditionalType.UNTIL; + } else { + return Conditional.ConditionalType.UNLESS; + } + } + } + } + } + + /** + * Gets the condition from the input string. + * @param text The input string. + * @return A string representing the condition. + */ + private static String getCondition(String text) { + return text == null ? "" : text; + } + + /** + * Gets the parameters from the input string. + * @param text The input string. + * @param numbers The list of line numbers. + * @return A map containing the directive parameters. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + private static Map<String, Object> getParameters(String text, + List<Integer> numbers) throws AraraException { + + if (text == null) { + return new HashMap<String, Object>(); + } + + Yaml yaml = new Yaml( + new Constructor(), + new Representer(), + new DumperOptions(), + new DirectiveResolver() + ); + try { + @SuppressWarnings("unchecked") + HashMap<String, Object> map = yaml.loadAs(text, HashMap.class); + return map; + } catch (MarkedYAMLException exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VALIDATE_YAML_EXCEPTION, + CommonUtils.getCollectionElements( + numbers, + "(", + ")", + ", " + ) + ), + exception + ); + } + } + + /** + * Validates the list of directives, returning a new list. + * @param directives The list of directives. + * @return A new list of directives. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static List<Directive> validate(List<Directive> directives) + throws AraraException { + + ArrayList<Directive> result = new ArrayList<Directive>(); + for (Directive directive : directives) { + Map<String, Object> parameters = directive.getParameters(); + + if (parameters.containsKey("file")) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VALIDATE_FILE_IS_RESERVED, + CommonUtils.getCollectionElements( + directive.getLineNumbers(), + "(", + ")", + ", " + ) + ) + ); + } + + if (parameters.containsKey("reference")) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VALIDATE_REFERENCE_IS_RESERVED, + CommonUtils.getCollectionElements( + directive.getLineNumbers(), + "(", + ")", + ", " + ) + ) + ); + } + + if (parameters.containsKey("files")) { + + Object holder = parameters.get("files"); + if (holder instanceof List) { + @SuppressWarnings("unchecked") + List<Object> files = (List<Object>) holder; + parameters.remove("files"); + if (files.isEmpty()) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VALIDATE_EMPTY_FILES_LIST, + CommonUtils.getCollectionElements( + directive.getLineNumbers(), + "(", + ")", + ", " + ) + ) + ); + } + for (Object file : files) { + Map<String, Object> map = new HashMap<String, Object>(); + for (String key : parameters.keySet()) { + map.put(key, parameters.get(key)); + } + File representation = CommonUtils. + getCanonicalFile(String.valueOf(file)); + + map.put("reference", representation); + map.put("file", representation.getName()); + + Directive addition = new Directive(); + Conditional conditional = new Conditional(); + conditional.setCondition(directive.getConditional(). + getCondition() + ); + conditional.setType(directive.getConditional(). + getType() + ); + addition.setIdentifier(directive.getIdentifier()); + addition.setConditional(conditional); + addition.setParameters(map); + addition.setLineNumbers(directive.getLineNumbers()); + result.add(addition); + } + } else { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VALIDATE_FILES_IS_NOT_A_LIST, + CommonUtils.getCollectionElements( + directive.getLineNumbers(), + "(", + ")", + ", " + ) + ) + ); + } + } else { + File representation = (File) ConfigurationController. + getInstance().get("execution.reference"); + parameters.put("file", representation.getName()); + parameters.put("reference", representation); + directive.setParameters(parameters); + result.add(directive); + } + } + + logger.info( + messages.getMessage( + Messages.LOG_INFO_VALIDATED_DIRECTIVES + ) + ); + logger.info(DisplayUtils.displayOutputSeparator( + messages.getMessage( + Messages.LOG_INFO_DIRECTIVES_BLOCK + ) + )); + for (Directive directive : result) { + logger.info(directive.toString()); + } + + logger.info(DisplayUtils.displaySeparator()); + + return result; + } + + /** + * Checks if the provided line contains the corresponding pattern, based on + * the file type, or an empty line. + * @param pattern Pattern to be matched, based on the file type. + * @param line Provided line. + * @return Logical value indicating if the provided line contains the + * corresponding pattern, based on the file type, or an empty line. + */ + private static boolean checkLinePattern(Pattern pattern, String line) { + return CommonUtils.checkEmptyString(line.trim()) || + pattern.matcher(line).find(); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DisplayUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DisplayUtils.java new file mode 100644 index 00000000000..879119e60e2 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/DisplayUtils.java @@ -0,0 +1,502 @@ +/** + * 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.utils; + +import com.github.cereda.arara.controller.ConfigurationController; +import com.github.cereda.arara.controller.LanguageController; +import com.github.cereda.arara.model.AraraException; +import com.github.cereda.arara.model.Conditional; +import com.github.cereda.arara.model.Messages; +import com.github.cereda.arara.model.StopWatch; +import java.io.File; +import java.util.List; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.WordUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implements display utilitary methods. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class DisplayUtils { + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + // get the logger context from a factory + private static final Logger logger = + LoggerFactory.getLogger(DisplayUtils.class); + + /** + * Displays the short version of the current entry in the terminal. + * @param name Rule name. + * @param task Task name. + */ + private static void buildShortEntry(String name, String task) { + int width = getWidth(); + int result = getLongestMatch(); + if (result >= width) { + result = 10; + } + int space = width - result - 1; + StringBuilder entry = new StringBuilder(); + entry.append("(").append(name).append(") "); + entry.append(task).append(" "); + String line = StringUtils.abbreviate(entry.toString(), space - 4); + entry = new StringBuilder(); + entry.append(StringUtils.rightPad(line, space, ".")).append(" "); + System.out.print(entry); + } + + /** + * Displays the short version of the current entry result in the terminal. + * @param value The boolean value to be displayed. + */ + private static void buildShortResult(boolean value) { + int result = getLongestMatch(); + System.out.println(StringUtils.leftPad(getResult(value), result)); + } + + /** + * Displays the current entry result in the terminal. + * @param value The boolean value to be displayed. + */ + public static void printEntryResult(boolean value) { + ConfigurationController.getInstance().put("display.line", false); + ConfigurationController.getInstance().put("display.result", true); + ConfigurationController.getInstance() + .put("execution.status", value ? 0 : 1); + logger.info( + messages.getMessage( + Messages.LOG_INFO_TASK_RESULT + ).concat(" ").concat(getResult(value)) + ); + if (!isDryRunMode()) { + if (!isVerboseMode()) { + buildShortResult(value); + } else { + buildLongResult(value); + } + } + } + + /** + * Displays a long version of the current entry result in the terminal. + * @param value The boolean value to be displayed + */ + private static void buildLongResult(boolean value) { + int width = getWidth(); + System.out.println("\n".concat(StringUtils.leftPad( + " ".concat(getResult(value)), width, "-" + ))); + } + + /** + * Displays the current entry in the terminal. + * @param name The rule name. + * @param task The task name. + */ + public static void printEntry(String name, String task) { + logger.info( + messages.getMessage( + Messages.LOG_INFO_INTERPRET_TASK, + task, + name + ) + ); + ConfigurationController.getInstance().put("display.line", true); + ConfigurationController.getInstance().put("display.result", false); + if (!isDryRunMode()) { + if (!isVerboseMode()) { + buildShortEntry(name, task); + } else { + buildLongEntry(name, task); + } + } else { + buildDryRunEntry(name, task); + } + } + + /** + * Gets the length of the longest result match. + * @return An integer value representing the longest result match. + */ + private static int getLongestMatch() { + String[] values = new String[]{ + messages.getMessage(Messages.INFO_LABEL_ON_SUCCESS), + messages.getMessage(Messages.INFO_LABEL_ON_FAILURE), + messages.getMessage(Messages.INFO_LABEL_ON_ERROR) + }; + int max = values[0].length(); + for (String value : values) { + if (max < value.length()) { + max = value.length(); + } + } + return max; + } + + /** + * Displays a long version of the current entry in the terminal. + * @param name Rule name. + * @param task Task name. + */ + private static void buildLongEntry(String name, String task) { + if (ConfigurationController.getInstance().contains("display.rolling")) { + addNewLine(); + } else { + ConfigurationController.getInstance().put("display.rolling", true); + } + StringBuilder line = new StringBuilder(); + line.append("(").append(name).append(") "); + line.append(task); + System.out.println(displaySeparator()); + System.out.println(StringUtils.abbreviate(line.toString(), getWidth())); + System.out.println(displaySeparator()); + } + + /** + * Displays a dry-run version of the current entry in the terminal. + * @param name The rule name. + * @param task The task name. + */ + private static void buildDryRunEntry(String name, String task) { + if (ConfigurationController.getInstance().contains("display.rolling")) { + addNewLine(); + } else { + ConfigurationController.getInstance().put("display.rolling", true); + } + StringBuilder line = new StringBuilder(); + line.append("[DR] (").append(name).append(") "); + line.append(task); + System.out.println(StringUtils.abbreviate(line.toString(), getWidth())); + System.out.println(displaySeparator()); + } + + /** + * Displays the exception in the terminal. + * @param exception The exception object. + */ + public static void printException(AraraException exception) { + ConfigurationController.getInstance().put("display.exception", true); + ConfigurationController.getInstance().put("execution.status", 2); + boolean display = false; + if (ConfigurationController.getInstance().contains("display.line")) { + display = (Boolean) ConfigurationController. + getInstance().get("display.line"); + } + if (ConfigurationController.getInstance().contains("display.result")) { + if (((Boolean) ConfigurationController. + getInstance().get("display.result")) == true) { + addNewLine(); + } + } + if (display) { + if (!isDryRunMode()) { + if (!isVerboseMode()) { + buildShortError(); + } else { + buildLongError(); + } + addNewLine(); + } + } + String text = exception.hasException() ? + exception.getMessage().concat(" ").concat( + messages.getMessage( + Messages.INFO_DISPLAY_EXCEPTION_MORE_DETAILS + ) + ) + : exception.getMessage(); + logger.error(text); + wrapText(text); + if (exception.hasException()) { + addNewLine(); + displayDetailsLine(); + String details = exception.getException().getMessage(); + logger.error(details); + wrapText(details); + } + } + + /** + * Gets the string representation of the provided boolean value. + * @param value The boolean value. + * @return The string representation. + */ + private static String getResult(boolean value) { + return (value == true ? + messages.getMessage( + Messages.INFO_LABEL_ON_SUCCESS + ) + : messages.getMessage(Messages.INFO_LABEL_ON_FAILURE)); + } + + /** + * Displays the short version of an error in the terminal. + */ + private static void buildShortError() { + int result = getLongestMatch(); + System.out.println(StringUtils.leftPad( + messages.getMessage( + Messages.INFO_LABEL_ON_ERROR + ), + result + )); + } + + /** + * Displays the long version of an error in the terminal. + */ + private static void buildLongError() { + String line = StringUtils.leftPad( + " ".concat(messages.getMessage(Messages.INFO_LABEL_ON_ERROR)), + getWidth(), "-"); + System.out.println(line); + } + + /** + * Gets the default terminal width defined in the settings. + * @return An integer representing the terminal width. + */ + private static int getWidth() { + return (Integer) ConfigurationController. + getInstance().get("application.width"); + } + + /** + * Displays the provided text wrapped nicely according to the default + * terminal width. + * @param text The text to be displayed. + */ + public static void wrapText(String text) { + System.out.println(WordUtils.wrap(text, getWidth())); + } + + /** + * Checks if the execution is in dry-run mode. + * @return A boolean value indicating if the execution is in dry-run mode. + */ + private static boolean isDryRunMode() { + return (Boolean) ConfigurationController. + getInstance().get("execution.dryrun"); + } + + /** + * Checks if the execution is in verbose mode. + * @return A boolean value indicating if the execution is in verbose mode. + */ + private static boolean isVerboseMode() { + return (Boolean) ConfigurationController. + getInstance().get("execution.verbose"); + } + + /** + * Displays the rule authors in the terminal. + * @param authors The list of authors. + */ + public static void printAuthors(List<String> authors) { + StringBuilder line = new StringBuilder(); + line.append(authors.size() == 1 ? + messages.getMessage(Messages.INFO_LABEL_AUTHOR) + : messages.getMessage(Messages.INFO_LABEL_AUTHORS)); + String text = authors.isEmpty() ? + messages.getMessage(Messages.INFO_LABEL_NO_AUTHORS) + : CommonUtils.getCollectionElements( + CommonUtils.trimSpaces(authors), "", "", ", "); + line.append(" ").append(text); + wrapText(line.toString()); + } + + /** + * Displays the current conditional in the terminal. + * @param conditional The conditional object. + */ + public static void printConditional(Conditional conditional) { + if (conditional.getType() != Conditional.ConditionalType.NONE) { + StringBuilder line = new StringBuilder(); + line.append(messages.getMessage(Messages.INFO_LABEL_CONDITIONAL)); + line.append(" ("); + line.append(String.valueOf(conditional.getType())); + line.append(") ").append(conditional.getCondition()); + wrapText(line.toString()); + } + } + + /** + * Displays the file information in the terminal. + */ + public static void printFileInformation() { + File file = (File) ConfigurationController. + getInstance().get("execution.reference"); + String version = (String) ConfigurationController. + getInstance().get("application.version"); + String revision = (String) ConfigurationController. + getInstance().get("application.revision"); + String line = messages.getMessage( + Messages.INFO_DISPLAY_FILE_INFORMATION, + file.getName(), + CommonUtils.calculateFileSize(file), + CommonUtils.getLastModifiedInformation(file) + ); + logger.info(messages.getMessage( + Messages.LOG_INFO_WELCOME_MESSAGE, + version, + revision + )); + logger.info(displaySeparator()); + logger.info(String.format("::: arara @ %s", + getApplicationPath() + )); + logger.info(String.format("::: Java %s, %s", + CommonUtils.getSystemProperty("java.version", + "[unknown version]"), + CommonUtils.getSystemProperty("java.vendor", + "[unknown vendor]") + )); + logger.info(String.format("::: %s", + CommonUtils.getSystemProperty("java.home", + "[unknown location]") + )); + logger.info(String.format("::: %s, %s, %s", + CommonUtils.getSystemProperty("os.name", + "[unknown OS name]"), + CommonUtils.getSystemProperty("os.arch", + "[unknown OS arch]"), + CommonUtils.getSystemProperty("os.version", + "[unknown OS version]") + )); + logger.info(String.format("::: user.home @ %s", + CommonUtils.getSystemProperty("user.home", + "[unknown user's home directory]") + )); + logger.info(String.format("::: user.dir @ %s", + CommonUtils.getSystemProperty("user.dir", + "[unknown user's working directory]") + )); + logger.info(String.format("::: CF @ %s", + (String) ConfigurationController. + getInstance().get("execution.configuration.name") + )); + logger.info(displaySeparator()); + logger.info(line); + wrapText(line); + addNewLine(); + } + + /** + * Displays the elapsed time in the terminal. + */ + public static void printTime() { + if (ConfigurationController.getInstance().contains("display.time")) { + if ((ConfigurationController.getInstance().contains("display.line")) + || (ConfigurationController.getInstance(). + contains("display.exception"))) { + addNewLine(); + } + String text = messages.getMessage( + Messages.INFO_DISPLAY_EXECUTION_TIME, StopWatch.getTime()); + logger.info(text); + wrapText(text); + } + } + + /** + * Displays the application logo in the terminal. + */ + public static void printLogo() { + StringBuilder builder = new StringBuilder(); + builder.append(" __ _ _ __ __ _ _ __ __ _ ").append("\n"); + builder.append(" / _` | '__/ _` | '__/ _` |").append("\n"); + builder.append("| (_| | | | (_| | | | (_| |").append("\n"); + builder.append(" \\__,_|_| \\__,_|_| \\__,_|"); + System.out.println(builder.toString()); + addNewLine(); + } + + /** + * Adds a new line in the terminal. + */ + private static void addNewLine() { + System.out.println(); + } + + /** + * Displays a line containing details. + */ + private static void displayDetailsLine() { + String line = messages.getMessage( + Messages.INFO_LABEL_ON_DETAILS).concat(" "); + line = StringUtils.rightPad( + StringUtils.abbreviate(line, getWidth()), getWidth(), "-"); + System.out.println(line); + } + + /** + * Gets the output separator with the provided text. + * @param message The provided text. + * @return A string containing the output separator with the provided text. + */ + public static String displayOutputSeparator(String message) { + return StringUtils.center(" ".concat(message).concat(" "), + getWidth(), "-"); + } + + /** + * Gets the line separator. + * @return A string containing the line separator. + */ + public static String displaySeparator() { + return StringUtils.repeat("-", getWidth()); + } + + /** + * Gets the application path. + * @return A string containing the application path. + */ + private static String getApplicationPath() { + try { + return ConfigurationUtils.getApplicationPath(); + } + catch (AraraException ae) { + return "[unknown application path]"; + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/FileHandlingUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/FileHandlingUtils.java new file mode 100644 index 00000000000..9f56c92f5d9 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/FileHandlingUtils.java @@ -0,0 +1,124 @@ +/** + * 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.utils; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.io.FileUtils; + +/** + * Implements file handling utilitary methods. + * + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class FileHandlingUtils { + + /** + * Writes the string to a file, using UTF-8 as default encoding. + * @param file The file. + * @param text The string to be written. + * @param append A flag whether to append the content. + * @return A logical value indicating whether it was successful. + */ + public static boolean writeToFile(File file, String text, boolean append) { + try { + + // try to write the provided + // string to the file, with + // UTF-8 as encoding + FileUtils.writeStringToFile(file, text, "UTF-8", append); + return true; + + } catch (IOException nothandled) { + + // if something bad happens, + // gracefully fallback to + // reporting the failure + return false; + } + } + + /** + * Writes the string list to a file, using UTF-8 as default encoding. + * @param file The file. + * @param lines The string list to be written. + * @param append A flag whether to append the content. + * @return A logical value indicating whether it was successful. + */ + public static boolean writeToFile(File file, List<String> lines, + boolean append) { + try { + + // try to write the provided + // string lists to the file, + // with UTF-8 as encoding + FileUtils.writeLines(file, "UTF-8", lines, append); + return true; + + } catch (IOException nothandled) { + + // if something bad happens, + // gracefully fallback to + // reporting the failure + return false; + } + } + + /** + * Reads the provided file into a list of strings. + * @param file The file. + * @return A list of strings. + */ + public static List<String> readFromFile(File file) { + try { + + // returns the contents of + // the provided file as + // a list of strings + return FileUtils.readLines(file, "UTF-8"); + + } catch (IOException nothandled) { + + // if something bad happens, + // gracefully fallback to + // an empty file list + return new ArrayList<String>(); + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/FileSearchingUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/FileSearchingUtils.java new file mode 100644 index 00000000000..473674cbc50 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/FileSearchingUtils.java @@ -0,0 +1,117 @@ +/** + * 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.utils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.filefilter.FalseFileFilter; +import org.apache.commons.io.filefilter.TrueFileFilter; +import org.apache.commons.io.filefilter.WildcardFileFilter; + +/** + * Implements file searching utilitary methods. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class FileSearchingUtils { + + /** + * List all files from the provided directory according to the list of + * extensions. The leading dot must be omitted, unless it is part of the + * extension. + * @param directory The provided directory. + * @param extensions The list of extensions. + * @param recursive A flag indicating whether the search is recursive. + * @return A list of files. + */ + public static List<File> listFilesByExtensions(File directory, + List<String> extensions, boolean recursive) { + try { + + // convert the provided extension + // list to an extension array + String[] array = new String[extensions.size()]; + array = extensions.toArray(array); + + // return the result of the + // provided search + return new ArrayList<File>( + FileUtils.listFiles(directory, array, recursive) + ); + } catch (Exception nothandled) { + + // if something bad happens, + // gracefully fallback to + // an empty file list + return new ArrayList<File>(); + } + } + + /** + * List all files from the provided directory matching the list of file + * name patterns. Such list can contain wildcards. + * @param directory The provided directory. + * @param patterns The list of file name patterns. + * @param recursive A flag indicating whether the search is recursive. + * @return A list of files. + */ + public static List<File> listFilesByPatterns(File directory, + List<String> patterns, boolean recursive) { + try { + + // return the result of the provided + // search, with the wildcard filter + // and a potential recursive search + return new ArrayList<File>( + FileUtils.listFiles( + directory, + new WildcardFileFilter(patterns), + recursive + ? TrueFileFilter.INSTANCE + : FalseFileFilter.INSTANCE + ) + ); + } catch (Exception nothandled) { + + // if something bad happens, + // gracefully fallback to + // an empty file list + return new ArrayList<File>(); + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/InterpreterUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/InterpreterUtils.java new file mode 100644 index 00000000000..978cb07374f --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/InterpreterUtils.java @@ -0,0 +1,257 @@ +/** + * 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.utils; + +import com.github.cereda.arara.controller.ConfigurationController; +import com.github.cereda.arara.controller.LanguageController; +import com.github.cereda.arara.model.AraraException; +import com.github.cereda.arara.model.Argument; +import com.github.cereda.arara.model.Command; +import com.github.cereda.arara.model.Conditional; +import com.github.cereda.arara.model.Messages; +import com.github.cereda.arara.model.Rule; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Transformer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.zeroturnaround.exec.InvalidExitValueException; +import org.zeroturnaround.exec.ProcessExecutor; +import org.zeroturnaround.exec.listener.ShutdownHookProcessDestroyer; + +/** + * Implements interpreter utilitary methods. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class InterpreterUtils { + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + // get the logger context from a factory + private static final Logger logger = + LoggerFactory.getLogger(InterpreterUtils.class); + + /** + * Gets a list of all rule arguments. + * @param rule The provided rule. + * @return A list of strings containing all rule arguments. + */ + public static List<String> getRuleArguments(Rule rule) { + Collection<String> result = CollectionUtils.collect( + rule.getArguments(), new Transformer<Argument, String>() { + public String transform(Argument input) { + return input.getIdentifier(); + } + }); + return new ArrayList<String>(result); + } + + /** + * Checks if the current conditional has a prior evaluation. + * @param conditional The current conditional object. + * @return A boolean value indicating if the current conditional has a prior + * evaluation. + */ + public static boolean runPriorEvaluation(Conditional conditional) { + if (((Boolean) ConfigurationController.getInstance(). + get("execution.dryrun")) == true) { + return false; + } + switch (conditional.getType()) { + case IF: + case WHILE: + case UNLESS: + return true; + default: + return false; + } + } + + /** + * Runs the command in the underlying operating system. + * @param command An object representing the command. + * @return An integer value representing the exit code. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static int run(Object command) throws AraraException { + boolean verbose = (Boolean) ConfigurationController. + getInstance().get("execution.verbose"); + boolean timeout = (Boolean) ConfigurationController. + getInstance().get("execution.timeout"); + long value = (Long) ConfigurationController. + getInstance().get("execution.timeout.value"); + TimeUnit unit = (TimeUnit) ConfigurationController. + getInstance().get("execution.timeout.unit"); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + ProcessExecutor executor = new ProcessExecutor(); + if (CommonUtils.checkClass(Command.class, command)) { + executor = executor.command(((Command) command).getElements()); + if (((Command) command).hasWorkingDirectory()) { + executor = executor.directory( + ((Command) command).getWorkingDirectory() + ); + } + } else { + executor = executor.commandSplit((String) command); + } + if (timeout) { + if (value == 0) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_RUN_TIMEOUT_INVALID_RANGE + ) + ); + } + executor = executor.timeout(value, unit); + } + TeeOutputStream tee; + if (verbose) { + tee = new TeeOutputStream(System.out, buffer); + executor = executor.redirectInput(System.in); + } else { + tee = new TeeOutputStream(buffer); + } + executor = executor.redirectOutput(tee).redirectError(tee); + ShutdownHookProcessDestroyer hook = new ShutdownHookProcessDestroyer(); + executor = executor.addDestroyer(hook); + try { + int exit = executor.execute().getExitValue(); + logger.info(DisplayUtils.displayOutputSeparator( + messages.getMessage( + Messages.LOG_INFO_BEGIN_BUFFER + ) + )); + logger.info(buffer.toString()); + logger.info(DisplayUtils.displayOutputSeparator( + messages.getMessage( + Messages.LOG_INFO_END_BUFFER + ) + )); + return exit; + } catch (IOException ioexception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_RUN_IO_EXCEPTION + ), + ioexception + ); + } catch (InterruptedException iexception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_RUN_INTERRUPTED_EXCEPTION + ), + iexception + ); + } catch (InvalidExitValueException ievexception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_RUN_INVALID_EXIT_VALUE_EXCEPTION + ), + ievexception + ); + } catch (TimeoutException texception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_RUN_TIMEOUT_EXCEPTION + ), + texception + ); + } catch (Exception exception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_RUN_GENERIC_EXCEPTION + ), + exception + ); + } + } + + /** + * Builds the rule path based on the rule name and returns the corresponding + * file location. + * @param name The rule name. + * @return The rule file. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static File buildRulePath(String name) throws AraraException { + @SuppressWarnings("unchecked") + List<String> paths = (List<String>) ConfigurationController. + getInstance().get("execution.rule.paths"); + for (String path : paths) { + File location = new File(construct(path, name)); + if (location.exists()) { + return location; + } + } + return null; + } + + /** + * Constructs the path given the current path and the rule name. + * @param path The current path. + * @param name The rule name. + * @return The constructed path. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static String construct(String path, String name) + throws AraraException { + name = name.concat(".yaml"); + File location = new File(path); + if (location.isAbsolute()) { + return CommonUtils.buildPath(path, name); + } else { + File reference = (File) ConfigurationController. + getInstance().get("execution.reference"); + String parent = CommonUtils.buildPath( + CommonUtils.getParentCanonicalPath(reference), path); + return CommonUtils.buildPath(parent, name); + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/MessageUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/MessageUtils.java new file mode 100644 index 00000000000..52a5d095a8e --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/MessageUtils.java @@ -0,0 +1,313 @@ +/** + * 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.utils; + +import com.github.cereda.arara.controller.ConfigurationController; +import javax.swing.JOptionPane; +import javax.swing.UIManager; + +/** + * Implements utilitary methods for displaying messages. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class MessageUtils { + + // holds the default width for the + // message body, in pixels + private static final int WIDTH = 250; + + // let's start the UI manager and set + // the default look and feel to be as + // close as possible to the system + static { + + // get the current look and feel + String laf = (String) ConfigurationController. + getInstance().get("ui.lookandfeel"); + + // check if one is actually set + if (!laf.equals("none")) { + + // use a special keyword to indicate + // the use of a system look and feel + if (laf.equals("system")) { + laf = UIManager.getSystemLookAndFeelClassName(); + } + + // let's try it, in case it fails, + // rely to the default look and feel + try { + + // get the system look and feel name + // and try to set it as default + UIManager.setLookAndFeel(laf); + } + catch (Exception exception) { + // quack, quack, quack + } + + } + } + + /** + * Normalizes the icon type to one of the five available icons. + * @param value An integer value. + * @return The normalized integer value. + */ + private static int normalizeIconType(int value) { + + // do the normalization according to the available + // icons in the underlying message implementation + switch (value) { + case 1: + value = JOptionPane.ERROR_MESSAGE; + break; + case 2: + value = JOptionPane.INFORMATION_MESSAGE; + break; + case 3: + value = JOptionPane.WARNING_MESSAGE; + break; + case 4: + value = JOptionPane.QUESTION_MESSAGE; + break; + default: + value = JOptionPane.PLAIN_MESSAGE; + break; + } + return value; + } + + /** + * Normalizes the message width, so only valid nonzero values are accepted. + * @param value An integer value corresponding to the message width. + * @return The normalized width. + */ + private static int normalizeMessageWidth(int value) { + return (value > 0 ? value : WIDTH); + } + + /** + * Shows the message. + * @param width Integer value, in pixels. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + */ + public static void showMessage(int width, int type, + String title, String text) { + + // effectively shows the message based + // on the provided parameters + JOptionPane.showMessageDialog( + null, + String.format( + "<html><body style=\"width:%dpx\">%s</body></html>", + normalizeMessageWidth(width), + text + ), + title, + normalizeIconType(type) + ); + } + + /** + * Shows the message. It relies on the default width. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + */ + public static void showMessage(int type, String title, String text) { + showMessage(WIDTH, type, title, text); + } + + /** + * Shows a message with options presented as an array of buttons. + * @param width Integer value, in pixels. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @param buttons An array of objects to be presented as buttons. + * @return The index of the selected button, starting from 1. + */ + public static int showOptions(int width, int type, String title, + String text, Object... buttons) { + + // returns the index of the selected button, + // zero if nothing is selected + return JOptionPane.showOptionDialog( + null, + String.format( + "<html><body style=\"width:%dpx\">%s</body></html>", + normalizeMessageWidth(width), + text + ), + title, + JOptionPane.DEFAULT_OPTION, + normalizeIconType(type), + null, + buttons, + buttons[0] + ) + 1; + } + + /** + * Shows a message with options presented as an array of buttons. It relies + * on the default width. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @param buttons An array of objects to be presented as buttons. + * @return The index of the selected button, starting from 1. + */ + public static int showOptions(int type, String title, + String text, Object... buttons) { + return showOptions(WIDTH, type, title, text, buttons); + } + + /** + * Shows a message with a text input. + * @param width Integer value, in pixels. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @return The string representing the input text. + */ + public static String showInput(int width, int type, + String title, String text) { + + // get the string from the + // input text, if any + String input = JOptionPane.showInputDialog( + null, + String.format( + "<html><body style=\"width:%dpx\">%s</body></html>", + normalizeMessageWidth(width), + text + ), + title, + normalizeIconType(type) + ); + + // if the input is not null, that is, + // the user actually typed something + if (input != null) { + + // return the trimmed string + return input.trim(); + } + + // nothing was typed, so let's + // return an empty string + return ""; + } + + /** + * Shows a message with a text input. It relies on the default width. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @return The string representing the input text. + */ + public static String showInput(int type, String title, String text) { + return showInput(WIDTH, type, title, text); + } + + /** + * Shows a message with options presented as a dropdown list of elements. + * @param width Integer value, in pixels. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @param elements An array of objects representing the elements. + * @return The index of the selected element, starting from 1. + */ + public static int showDropdown(int width, int type, String title, + String text, Object... elements) { + + // show the dropdown list and get + // the selected object, if any + Object index = JOptionPane.showInputDialog( + null, + String.format( + "<html><body style=\"width:%dpx\">%s</body></html>", + normalizeMessageWidth(width), + text + ), + title, + normalizeIconType(type), + null, + elements, + elements[0] + ); + + // if it's not a null object, let's + // find the corresponding index + if (index != null) { + + // iterate through the array of elements + for (int i = 0; i < elements.length; i++) { + + // if the element is found, simply + // return the index plus 1, as zero + // corresponds to no selection at all + if (elements[i].equals(index)) { + return i + 1; + } + + } + } + + // nothing was selected, + // simply return zero + return 0; + } + + /** + * Shows a message with options presented as a dropdown list of elements. It + * relies on the default width. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @param elements An array of objects representing the elements. + * @return The index of the selected element, starting from 1. + */ + public static int showDropdown(int type, String title, + String text, Object... elements) { + return showDropdown(WIDTH, type, title, text, elements); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/Methods.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/Methods.java new file mode 100644 index 00000000000..15c66049342 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/Methods.java @@ -0,0 +1,1356 @@ +/** + * 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.utils; + +import com.github.cereda.arara.controller.ConfigurationController; +import com.github.cereda.arara.controller.LanguageController; +import com.github.cereda.arara.model.AraraException; +import com.github.cereda.arara.model.Command; +import com.github.cereda.arara.model.Messages; +import com.github.cereda.arara.model.Pair; +import com.github.cereda.arara.model.Session; +import com.github.cereda.arara.model.Trigger; +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * Implements some auxiliary methods for runtime evaluation. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class Methods { + + // the language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + // the session controller + private static final Session session = new Session(); + + /** + * Adds the rule methods to the provided map. + * @param map The map. + */ + public static void addRuleMethods(Map<String, Object> map) { + addConditionalMethods(map); + try { + map.put("getOriginalFile", Methods.class.getMethod("getOriginalFile")); + map.put("getOriginalReference", Methods.class.getMethod("getOriginalReference")); + map.put("isEmpty", Methods.class.getMethod("isEmpty", String.class)); + map.put("isNotEmpty", Methods.class.getMethod("isNotEmpty", String.class)); + map.put("isEmpty", Methods.class.getMethod("isEmpty", String.class, Object.class)); + map.put("isNotEmpty", Methods.class.getMethod("isNotEmpty", String.class, Object.class)); + map.put("isEmpty", Methods.class.getMethod("isEmpty", String.class, Object.class, Object.class)); + map.put("isNotEmpty", Methods.class.getMethod("isNotEmpty", String.class, Object.class, Object.class)); + map.put("isTrue", Methods.class.getMethod("isTrue", String.class)); + map.put("isFalse", Methods.class.getMethod("isFalse", String.class)); + map.put("isTrue", Methods.class.getMethod("isTrue", String.class, Object.class)); + map.put("isFalse", Methods.class.getMethod("isFalse", String.class, Object.class)); + map.put("isTrue", Methods.class.getMethod("isTrue", String.class, Object.class, Object.class)); + map.put("isFalse", Methods.class.getMethod("isFalse", String.class, Object.class, Object.class)); + map.put("isTrue", Methods.class.getMethod("isTrue", String.class, Object.class, Object.class, Object.class)); + map.put("isFalse", Methods.class.getMethod("isFalse", String.class, Object.class, Object.class, Object.class)); + map.put("trimSpaces", Methods.class.getMethod("trimSpaces", String.class)); + map.put("isTrue", Methods.class.getMethod("isTrue", boolean.class, Object.class)); + map.put("isFalse", Methods.class.getMethod("isFalse", boolean.class, Object.class)); + map.put("isTrue", Methods.class.getMethod("isTrue", boolean.class, Object.class, Object.class)); + map.put("isFalse", Methods.class.getMethod("isFalse", boolean.class, Object.class, Object.class)); + map.put("getBasename", Methods.class.getMethod("getBasename", File.class)); + map.put("getBasename", Methods.class.getMethod("getBasename", String.class)); + map.put("getFullBasename", Methods.class.getMethod("getFullBasename", File.class)); + map.put("getFullBasename", Methods.class.getMethod("getFullBasename", String.class)); + map.put("getFiletype", Methods.class.getMethod("getFiletype", File.class)); + map.put("getFiletype", Methods.class.getMethod("getFiletype", String.class)); + map.put("throwError", Methods.class.getMethod("throwError", String.class)); + map.put("getSession", Methods.class.getMethod("getSession")); + map.put("isWindows", Methods.class.getMethod("isWindows")); + map.put("isLinux", Methods.class.getMethod("isLinux")); + map.put("isMac", Methods.class.getMethod("isMac")); + map.put("isUnix", Methods.class.getMethod("isUnix")); + map.put("isAIX", Methods.class.getMethod("isAIX")); + map.put("isIrix", Methods.class.getMethod("isIrix")); + map.put("isOS2", Methods.class.getMethod("isOS2")); + map.put("isSolaris", Methods.class.getMethod("isSolaris")); + map.put("isCygwin", Methods.class.getMethod("isCygwin")); + map.put("isWindows", Methods.class.getMethod("isWindows", Object.class, Object.class)); + map.put("isLinux", Methods.class.getMethod("isLinux", Object.class, Object.class)); + map.put("isMac", Methods.class.getMethod("isMac", Object.class, Object.class)); + map.put("isUnix", Methods.class.getMethod("isUnix", Object.class, Object.class)); + map.put("isAIX", Methods.class.getMethod("isAIX", Object.class, Object.class)); + map.put("isIrix", Methods.class.getMethod("isIrix", Object.class, Object.class)); + map.put("isOS2", Methods.class.getMethod("isOS2", Object.class, Object.class)); + map.put("isSolaris", Methods.class.getMethod("isSolaris", Object.class, Object.class)); + map.put("isCygwin", Methods.class.getMethod("isCygwin", Object.class, Object.class)); + map.put("replicatePattern", Methods.class.getMethod("replicatePattern", String.class, List.class)); + map.put("buildString", Methods.class.getMethod("buildString", Object[].class)); + map.put("addQuotes", Methods.class.getMethod("addQuotes", Object.class)); + map.put("getCommand", Methods.class.getMethod("getCommand", List.class)); + map.put("getCommand", Methods.class.getMethod("getCommand", Object[].class)); + map.put("getTrigger", Methods.class.getMethod("getTrigger", String.class)); + map.put("getTrigger", Methods.class.getMethod("getTrigger", String.class, Object[].class)); + map.put("checkClass", Methods.class.getMethod("checkClass", Class.class, Object.class)); + map.put("isString", Methods.class.getMethod("isString", Object.class)); + map.put("isList", Methods.class.getMethod("isList", Object.class)); + map.put("isMap", Methods.class.getMethod("isMap", Object.class)); + map.put("isBoolean", Methods.class.getMethod("isBoolean", Object.class)); + map.put("isVerboseMode", Methods.class.getMethod("isVerboseMode")); + map.put("showMessage", Methods.class.getMethod("showMessage", int.class, String.class, String.class)); + map.put("showMessage", Methods.class.getMethod("showMessage", int.class, int.class, String.class, String.class)); + map.put("isOnPath", Methods.class.getMethod("isOnPath", String.class)); + map.put("unsafelyExecuteSystemCommand", Methods.class.getMethod("unsafelyExecuteSystemCommand", Command.class)); + map.put("mergeVelocityTemplate", Methods.class.getMethod("mergeVelocityTemplate", File.class, File.class, Map.class)); + map.put("getCommandWithWorkingDirectory", Methods.class.getMethod("getCommandWithWorkingDirectory", String.class, List.class)); + map.put("getCommandWithWorkingDirectory", Methods.class.getMethod("getCommandWithWorkingDirectory", String.class, Object[].class)); + map.put("getCommandWithWorkingDirectory", Methods.class.getMethod("getCommandWithWorkingDirectory", File.class, List.class)); + map.put("getCommandWithWorkingDirectory", Methods.class.getMethod("getCommandWithWorkingDirectory", File.class, Object[].class)); + map.put("listFilesByExtensions", Methods.class.getMethod("listFilesByExtensions", File.class, List.class, boolean.class)); + map.put("listFilesByExtensions", Methods.class.getMethod("listFilesByExtensions", String.class, List.class, boolean.class)); + map.put("listFilesByPatterns", Methods.class.getMethod("listFilesByPatterns", File.class, List.class, boolean.class)); + map.put("listFilesByPatterns", Methods.class.getMethod("listFilesByPatterns", String.class, List.class, boolean.class)); + map.put("writeToFile", Methods.class.getMethod("writeToFile", File.class, String.class, boolean.class)); + map.put("writeToFile", Methods.class.getMethod("writeToFile", File.class, List.class, boolean.class)); + map.put("writeToFile", Methods.class.getMethod("writeToFile", String.class, String.class, boolean.class)); + map.put("writeToFile", Methods.class.getMethod("writeToFile", String.class, List.class, boolean.class)); + map.put("readFromFile", Methods.class.getMethod("readFromFile", File.class)); + map.put("readFromFile", Methods.class.getMethod("readFromFile", String.class)); + } catch (Exception exception) { + // quack, quack, quack + } + } + + /** + * Adds conditional methods to the provided map. + * @param map The map. + */ + public static void addConditionalMethods(Map<String, Object> map) { + try { + map.put("exists", Methods.class.getMethod("exists", String.class)); + map.put("exists", Methods.class.getMethod("exists", File.class)); + map.put("missing", Methods.class.getMethod("missing", String.class)); + map.put("missing", Methods.class.getMethod("missing", File.class)); + map.put("changed", Methods.class.getMethod("changed", String.class)); + map.put("changed", Methods.class.getMethod("changed", File.class)); + map.put("unchanged", Methods.class.getMethod("unchanged", String.class)); + map.put("unchanged", Methods.class.getMethod("unchanged", File.class)); + map.put("found", Methods.class.getMethod("found", String.class, String.class)); + map.put("found", Methods.class.getMethod("found", File.class, String.class)); + map.put("toFile", Methods.class.getMethod("toFile", String.class)); + map.put("showDropdown", Methods.class.getMethod("showDropdown", int.class, String.class, String.class, Object[].class)); + map.put("showDropdown", Methods.class.getMethod("showDropdown", int.class, int.class, String.class, String.class, Object[].class)); + map.put("showInput", Methods.class.getMethod("showInput", int.class, String.class, String.class)); + map.put("showInput", Methods.class.getMethod("showInput", int.class, int.class, String.class, String.class)); + map.put("showOptions", Methods.class.getMethod("showOptions", int.class, String.class, String.class, Object[].class)); + map.put("showOptions", Methods.class.getMethod("showOptions", int.class, int.class, String.class, String.class, Object[].class)); + map.put("currentFile", Methods.class.getMethod("currentFile")); + map.put("loadClass", Methods.class.getMethod("loadClass", File.class, String.class)); + map.put("loadClass", Methods.class.getMethod("loadClass", String.class, String.class)); + map.put("loadObject", Methods.class.getMethod("loadObject", File.class, String.class)); + map.put("loadObject", Methods.class.getMethod("loadObject", String.class, String.class)); + } catch (Exception exception) { + // quack, quack, quack + } + } + + /** + * Gets the original file. + * @return The original file. + */ + public static String getOriginalFile() { + File file = (File) ConfigurationController.getInstance().get("execution.reference"); + return file.getName(); + } + + /** + * Gets the original reference. + * @return The original reference. + */ + public static File getOriginalReference() { + return (File) ConfigurationController.getInstance().get("execution.reference"); + } + + /** + * Checks if the string is empty. + * @param string The string. + * @return A boolean value. + */ + public static boolean isEmpty(String string) { + return CommonUtils.checkEmptyString(string); + } + + /** + * Checks if the string is not empty. + * @param string The string. + * @return A boolean value. + */ + public static boolean isNotEmpty(String string) { + return !isEmpty(string); + } + + /** + * Checks if the string is empty. + * @param string The string. + * @param yes Object to return if true. + * @return An object or empty string. + */ + public static Object isEmpty(String string, Object yes) { + return isEmpty(string) ? yes : ""; + } + + /** + * Checks if the string is not empty. + * @param string The string. + * @param yes Object to return if true. + * @return An object or empty string. + */ + public static Object isNotEmpty(String string, Object yes) { + return isNotEmpty(string) ? yes : ""; + } + + /** + * Checks if the string is empty. + * @param string The string. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + */ + public static Object isEmpty(String string, Object yes, Object no) { + return isEmpty(string) ? yes : no; + } + + /** + * Checks if the string is not empty. + * @param string The string. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + */ + public static Object isNotEmpty(String string, Object yes, Object no) { + return isNotEmpty(string) ? yes : no; + } + + /** + * Checks if the string holds a true value. + * @param string The string. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean isTrue(String string) throws AraraException { + return isEmpty(string) ? false : CommonUtils.checkBoolean(string); + } + + /** + * Checks if the string holds a false value. + * @param string The string. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean isFalse(String string) throws AraraException { + return isEmpty(string) ? false : !CommonUtils.checkBoolean(string); + } + + /** + * Checks if the string holds a true value. + * @param string The string. + * @param yes Object to return if true. + * @return An object or an empty string. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isTrue(String string, Object yes) + throws AraraException { + return isTrue(string) ? yes : ""; + } + + /** + * Checks if the string holds a false value. + * @param string The string. + * @param yes Object to return if true. + * @return An object or an empty string. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isFalse(String string, Object yes) + throws AraraException { + return (isFalse(string) ? yes : ""); + } + + /** + * Checks if the string holds a true value. + * @param string The string. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isTrue(String string, Object yes, Object no) + throws AraraException { + return (isTrue(string) ? yes : no); + } + + /** + * Checks if the string holds a false value. + * @param string The string. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isFalse(String string, Object yes, Object no) + throws AraraException { + return (isFalse(string) ? yes : no); + } + + /** + * Checks if the string holds a true value. + * @param string The string. + * @param yes Object to return if true. + * @param no Object to return if false. + * @param fallback Object to return if string is empty. + * @return One of the three options. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isTrue(String string, Object yes, Object no, + Object fallback) throws AraraException { + return isEmpty(string) ? fallback : (isTrue(string) ? yes : no); + } + + /** + * Checks if the string holds a false value. + * @param string The string. + * @param yes Object to return if true. + * @param no Object to return if false. + * @param fallback Object to return if string is empty. + * @return One of the three options. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isFalse(String string, Object yes, Object no, + Object fallback) throws AraraException { + return isEmpty(string) ? fallback : (isFalse(string) ? yes : no); + } + + /** + * Trim spaces from the string. + * @param string The string. + * @return A trimmed string. + */ + public static String trimSpaces(String string) { + return string.trim(); + } + + /** + * Checks if the expression resolves to true. + * @param value The expression. + * @param yes Object to return if true. + * @return An object or an empty string. + */ + public static Object isTrue(boolean value, Object yes) { + return value ? yes : ""; + } + + /** + * Checks if the expression resolves to false. + * @param value The expression. + * @param yes Object to return if true. + * @return An object or an empty string. + */ + public static Object isFalse(boolean value, Object yes) { + return !value ? yes : ""; + } + + /** + * Checks if the expression resolves to true. + * @param value The expression. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + */ + public static Object isTrue(boolean value, Object yes, Object no) { + return value ? yes : no; + } + + /** + * Checks if the expression resolves to false. + * @param value The expression. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + */ + public static Object isFalse(boolean value, Object yes, Object no) { + return !value ? yes : no; + } + + /** + * Gets the basename. + * @param file The file. + * @return The basename of the provided file. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static String getBasename(File file) throws AraraException { + if (file.isFile()) { + return CommonUtils.getBasename(file); + } else { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_BASENAME_NOT_A_FILE, + file.getName() + ) + ) + ); + } + } + + /** + * Gets the basename. + * @param filename The string. + * @return The basename. + */ + public static String getBasename(String filename) { + return CommonUtils.getBasename(filename); + } + + /** + * Gets the file type. + * @param file The provided file. + * @return The file type. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static String getFiletype(File file) throws AraraException { + if (file.isFile()) { + return CommonUtils.getFiletype(file); + } else { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_FILETYPE_NOT_A_FILE, + file.getName() + ) + ) + ); + } + } + + /** + * Gets the file type. + * @param filename The provided string. + * @return The file type. + */ + public static String getFiletype(String filename) { + return CommonUtils.getFiletype(filename); + } + + /** + * Replicates the pattern to each element of a list. + * @param pattern The pattern. + * @param values The list. + * @return A list of strings containing the pattern applied to the list. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static List<Object> replicatePattern(String pattern, + List<Object> values) throws AraraException { + return CommonUtils.replicateList(pattern, values); + } + + /** + * Throws an exception. + * @param text The text to be thrown as the exception message. + * @throws AraraException The exception to be thrown by this method. + */ + public static void throwError(String text) throws AraraException { + throw new AraraException(text); + } + + /** + * Gets the session. + * @return The session. + */ + public static Session getSession() { + return session; + } + + /** + * Checks if Windows is the underlying operating system. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean isWindows() throws AraraException { + return CommonUtils.checkOS("windows"); + } + + /** + * Checks if we are inside a Cygwin environment. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean isCygwin() throws AraraException { + return CommonUtils.checkOS("cygwin"); + } + + /** + * Checks if Linux is the underlying operating system. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean isLinux() throws AraraException { + return CommonUtils.checkOS("linux"); + } + + /** + * Checks if Mac is the underlying operating system. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean isMac() throws AraraException { + return CommonUtils.checkOS("mac"); + } + + /** + * Checks if Unix is the underlying operating system. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean isUnix() throws AraraException { + return CommonUtils.checkOS("unix"); + } + + /** + * Checks if AIX is the underlying operating system. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean isAIX() throws AraraException { + return CommonUtils.checkOS("aix"); + } + + /** + * Checks if Irix is the underlying operating system. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean isIrix() throws AraraException { + return CommonUtils.checkOS("irix"); + } + + /** + * Checks if OS2 is the underlying operating system. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean isOS2() throws AraraException { + return CommonUtils.checkOS("os2"); + } + + /** + * Checks if Solaris is the underlying operating system. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean isSolaris() throws AraraException { + return CommonUtils.checkOS("solaris"); + } + + /** + * Checks if Windows is the underlying operating system. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isWindows(Object yes, Object no) + throws AraraException { + return CommonUtils.checkOS("windows") ? yes : no; + } + + /** + * Checks if we are inside a Cygwin environment. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isCygwin(Object yes, Object no) throws AraraException { + return CommonUtils.checkOS("cygwin") ? yes : no; + } + + /** + * Checks if Linux is the underlying operating system. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isLinux(Object yes, Object no) throws AraraException { + return CommonUtils.checkOS("linux") ? yes : no; + } + + /** + * Checks if Mac is the underlying operating system. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isMac(Object yes, Object no) throws AraraException { + return CommonUtils.checkOS("mac") ? yes : no; + } + + /** + * Checks if Unix is the underlying operating system. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isUnix(Object yes, Object no) throws AraraException { + return CommonUtils.checkOS("unix") ? yes : no; + } + + /** + * Checks if AIX is the underlying operating system. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isAIX(Object yes, Object no) throws AraraException { + return CommonUtils.checkOS("aix") ? yes : no; + } + + /** + * Checks if Irix is the underlying operating system. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isIrix(Object yes, Object no) throws AraraException { + return CommonUtils.checkOS("irix") ? yes : no; + } + + /** + * Checks if OS2 is the underlying operating system. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isOS2(Object yes, Object no) throws AraraException { + return CommonUtils.checkOS("os2") ? yes : no; + } + + /** + * Checks if Solaris is the underlying operating system. + * @param yes Object to return if true. + * @param no Object to return if false. + * @return One of the two objects. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Object isSolaris(Object yes, Object no) throws AraraException { + return CommonUtils.checkOS("solaris") ? yes : no; + } + + /** + * Checks if the file exists according to its extension. + * @param extension The extension. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean exists(String extension) throws AraraException { + return CommonUtils.exists(extension); + } + + /** + * Checks if the file is missing according to its extension. + * @param extension The extension. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean missing(String extension) throws AraraException { + return !exists(extension); + } + + /** + * Checks if the file has changed, according to its extension. + * @param extension The extension. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean changed(String extension) throws AraraException { + return CommonUtils.hasChanged(extension); + } + + /** + * Checks if the file is unchanged according to its extension. + * @param extension The extension. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean unchanged(String extension) throws AraraException { + return !changed(extension); + } + + /** + * Checks if the file exists. + * @param filename The file. + * @return A boolean value. + */ + public static boolean exists(File filename) { + return CommonUtils.exists(filename); + } + + /** + * Checks if the file is missing. + * @param filename The file. + * @return A boolean value. + */ + public static boolean missing(File filename) { + return !exists(filename); + } + + /** + * Checks if the file has changed. + * @param filename The file. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean changed(File filename) throws AraraException { + return CommonUtils.hasChanged(filename); + } + + /** + * Checks if the file is unchanged. + * @param filename The file. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean unchanged(File filename) throws AraraException { + return !changed(filename); + } + + /** + * Build a string based on an array of objects. + * @param objects Array of objects. + * @return A string built from the array. + */ + public static String buildString(Object... objects) { + return CommonUtils.generateString(objects); + } + + /** + * Encloses the provided object into double quotes. + * @param object The object. + * @return The object enclosed in double quotes. + */ + public static String addQuotes(Object object) { + return CommonUtils.addQuotes(object); + } + + /** + * Checks if the file contains the regex, based on its extension. + * @param extension The extension. + * @param regex The regex. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean found(String extension, String regex) + throws AraraException { + return CommonUtils.checkRegex(extension, regex); + } + + /** + * Checks if the file contains the provided regex. + * @param file The file. + * @param regex The regex. + * @return A boolean value. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static boolean found(File file, String regex) + throws AraraException { + return CommonUtils.checkRegex(file, regex); + } + + /** + * Gets the command based on a list of strings. + * @param elements The list of strings. + * @return A command. + */ + public static Command getCommand(List<String> elements) { + return new Command(elements); + } + + /** + * Gets the command based on an array of objects. + * @param elements Array of objects. + * @return A command. + */ + public static Command getCommand(Object... elements) { + return new Command(elements); + } + + /** + * Gets the command based on an array of objects and with the provided + * working directory as string. + * @param path String path representing the working directory. + * @param elements Array of elements. + * @return A command. + */ + public static Command getCommandWithWorkingDirectory(String path, + Object... elements) { + Command command = new Command(elements); + command.setWorkingDirectory(new File(path)); + return command; + } + + /** + * Gets the command based on an array of objects and with the provided + * working directory as file. + * @param file File representing the working directory. + * @param elements Array of elements. + * @return A command. + */ + public static Command getCommandWithWorkingDirectory(File file, + Object... elements) { + Command command = new Command(elements); + command.setWorkingDirectory(file); + return command; + } + + /** + * Gets the command based on a list of strings and with the provided + * working directory as string. + * @param path String path representing the working directory. + * @param elements List of strings. + * @return A command. + */ + public static Command getCommandWithWorkingDirectory(String path, + List<String> elements) { + Command command = new Command(elements); + command.setWorkingDirectory(new File(path)); + return command; + } + + /** + * Gets the command based on a list of strings and with the provided + * working directory as file. + * @param file File representing the working directory. + * @param elements List of strings. + * @return A command. + */ + public static Command getCommandWithWorkingDirectory(File file, + List<String> elements) { + Command command = new Command(elements); + command.setWorkingDirectory(file); + return command; + } + + /** + * Gets the trigger. + * @param action The action name. + * @return The trigger. + */ + public static Trigger getTrigger(String action) { + return new Trigger(action, null); + } + + /** + * Gets the trigger. + * @param action The action name. + * @param parameters The trigger parameters. + * @return A trigger. + */ + public static Trigger getTrigger(String action, Object... parameters) { + return new Trigger(action, Arrays.asList(parameters)); + } + + /** + * Checks if the object is an intance of the provided class. + * @param clazz The class. + * @param object The object. + * @return A boolean value. + */ + public static boolean checkClass(Class clazz, Object object) { + return CommonUtils.checkClass(clazz, object); + } + + /** + * Checks if the object is a string. + * @param object The object. + * @return A boolean value. + */ + public static boolean isString(Object object) { + return checkClass(String.class, object); + } + + /** + * Checks if the object is a list. + * @param object The object. + * @return A boolean value. + */ + public static boolean isList(Object object) { + return checkClass(List.class, object); + } + + /** + * Checks if the object is a map. + * @param object The object. + * @return A boolean value. + */ + public static boolean isMap(Object object) { + return checkClass(Map.class, object); + } + + /** + * Checks if the object is a boolean. + * @param object The object. + * @return A boolean value. + */ + public static boolean isBoolean(Object object) { + return checkClass(Boolean.class, object); + } + + /** + * Checks if the execution is in verbose mode. + * @return A boolean value indicating if the execution is in verbose mode. + */ + public static boolean isVerboseMode() { + return (Boolean) ConfigurationController. + getInstance().get("execution.verbose"); + } + + /** + * Returns a file object based on the provided name. + * @param name The file name. + * @return A file object. + */ + public static File toFile(String name) { + return new File(name); + } + + /** + * Shows the message. + * @param width Integer value, in pixels. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + */ + public static void showMessage(int width, int type, + String title, String text) { + MessageUtils.showMessage(width, type, title, text); + } + + /** + * Shows the message. It relies on the default width. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + */ + public static void showMessage(int type, String title, String text) { + MessageUtils.showMessage(type, title, text); + } + + /** + * Shows a message with options presented as an array of buttons. + * @param width Integer value, in pixels. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @param buttons An array of objects to be presented as buttons. + * @return The index of the selected button, starting from 1. + */ + public static int showOptions(int width, int type, String title, + String text, Object... buttons) { + return MessageUtils.showOptions(width, type, title, text, buttons); + } + + /** + * Shows a message with options presented as an array of buttons. It relies + * on the default width. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @param buttons An array of objects to be presented as buttons. + * @return The index of the selected button, starting from 1. + */ + public static int showOptions(int type, String title, + String text, Object... buttons) { + return MessageUtils.showOptions(type, title, text, buttons); + } + + /** + * Shows a message with a text input. + * @param width Integer value, in pixels. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @return The string representing the input text. + */ + public static String showInput(int width, int type, + String title, String text) { + return MessageUtils.showInput(width, type, title, text); + } + + /** + * Shows a message with a text input. It relies on the default width. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @return The string representing the input text. + */ + public static String showInput(int type, String title, String text) { + return MessageUtils.showInput(type, title, text); + } + + /** + * Shows a message with options presented as a dropdown list of elements. + * @param width Integer value, in pixels. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @param elements An array of objects representing the elements. + * @return The index of the selected element, starting from 1. + */ + public static int showDropdown(int width, int type, String title, + String text, Object... elements) { + return MessageUtils.showDropdown(width, type, title, text, elements); + } + + /** + * Shows a message with options presented as a dropdown list of elements. It + * relies on the default width. + * @param type Type of message. + * @param title Title of the message. + * @param text Text of the message. + * @param elements An array of objects representing the elements. + * @return The index of the selected element, starting from 1. + */ + public static int showDropdown(int type, String title, + String text, Object... elements) { + return MessageUtils.showDropdown(type, title, text, elements); + } + + /** + * Checks if the provided command name is reachable from the system path. + * @param command A string representing the command. + * @return A logic value. + */ + public static boolean isOnPath(String command) { + return CommonUtils.isOnPath(command); + } + + /** + * Gets the full basename. + * @param file The file. + * @return The full basename of the provided file. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static String getFullBasename(File file) throws AraraException { + if (file.isFile()) { + return CommonUtils.getFullBasename(file); + } else { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_BASENAME_NOT_A_FILE, + file.getName() + ) + ) + ); + } + } + + /** + * Gets the full basename. + * @param name The string. + * @return The full basename. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static String getFullBasename(String name) throws AraraException { + return getFullBasename(new File(name)); + } + + /** + * Unsafely executes a system command from the underlying operating system + * and returns a pair containing the exit status and the command output as a + * string. + * @param command The system command to be executed. + * @return A pair containing the exit status and the system command output + * as a string. + */ + public static Pair<Integer, String> + unsafelyExecuteSystemCommand(Command command) { + return UnsafeUtils.executeSystemCommand(command); + } + + /** + * Merges the provided template with a context map and writes the result in + * an output file. This method relies on Apache Velocity. + * @param input The input file. + * @param output The output file. + * @param map The context map. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static void mergeVelocityTemplate(File input, File output, + Map<String, Object> map) throws AraraException { + VelocityUtils.mergeVelocityTemplate(input, output, map); + } + + /** + * Gets the file reference for the current directive. It is important to + * observe that version 4.0 of arara replicates the directive when 'files' + * is detected amongst the parameters, so each instance will have a + * different reference. + * @return A file reference for the current directive. + */ + public static File currentFile() { + return (File) ConfigurationController.getInstance(). + get("execution.directive.reference"); + } + + /** + * Loads a class from the provided file, potentially a Java archive. + * @param file File containing the Java bytecode (namely, a JAR). + * @param name The canonical name of the class. + * @return A pair representing the status and the class. + */ + public static Pair<Integer, Class> loadClass(File file, String name) { + return ClassLoadingUtils.loadClass(file, name); + } + + /** + * Loads a class from the provided string reference, representing a file. + * @param ref String reference representing a file. + * @param name The canonical name of the class. + * @return A pair representing the status and the class. + */ + public static Pair<Integer, Class> loadClass(String ref, String name) { + return ClassLoadingUtils.loadClass(new File(ref), name); + } + + /** + * Loads a class from the provided file, instantiating it. + * @param file File containing the Java bytecode (namely, a JAR). + * @param name The canonical name of the class. + * @return A pair representing the status and the class object. + */ + public static Pair<Integer, Object> loadObject(File file, String name) { + return ClassLoadingUtils.loadObject(file, name); + } + + /** + * Loads a class from the provided string reference, instantiating it. + * @param ref String reference representing a file. + * @param name The canonical name of the class. + * @return A pair representing the status and the class object. + */ + public static Pair<Integer, Object> loadObject(String ref, String name) { + return ClassLoadingUtils.loadObject(new File(ref), name); + } + + /** + * List all files from the provided directory according to the list of + * extensions. The leading dot must be omitted, unless it is part of the + * extension. + * @param directory The provided directory. + * @param extensions The list of extensions. + * @param recursive A flag indicating whether the search is recursive. + * @return A list of files. + */ + public static List<File> listFilesByExtensions(File directory, + List<String> extensions, boolean recursive) { + return FileSearchingUtils.listFilesByExtensions( + directory, + extensions, + recursive + ); + } + + /** + * List all files from the provided string path according to the list of + * extensions. The leading dot must be omitted, unless it is part of the + * extension. + * @param path The provided path as plain string. + * @param extensions The list of extensions. + * @param recursive A flag indicating whether the search is recursive. + * @return A list of files. + */ + public static List<File> listFilesByExtensions(String path, + List<String> extensions, boolean recursive) { + return FileSearchingUtils.listFilesByExtensions( + new File(path), + extensions, + recursive + ); + } + + /** + * List all files from the provided directory matching the list of file + * name patterns. Such list can contain wildcards. + * @param directory The provided directory. + * @param patterns The list of file name patterns. + * @param recursive A flag indicating whether the search is recursive. + * @return A list of files. + */ + public static List<File> listFilesByPatterns(File directory, + List<String> patterns, boolean recursive) { + return FileSearchingUtils.listFilesByPatterns( + directory, + patterns, + recursive + ); + } + + /** + * List all files from the provided path matching the list of file + * name patterns. Such list can contain wildcards. + * @param path The provided path as plain string. + * @param patterns The list of file name patterns. + * @param recursive A flag indicating whether the search is recursive. + * @return A list of files. + */ + public static List<File> listFilesByPatterns(String path, + List<String> patterns, boolean recursive) { + return FileSearchingUtils.listFilesByPatterns( + new File(path), + patterns, + recursive + ); + } + + /** + * Writes the string to a file, using UTF-8 as default encoding. + * @param file The file. + * @param text The string to be written. + * @param append A flag whether to append the content. + * @return A logical value indicating whether it was successful. + */ + public static boolean writeToFile(File file, String text, boolean append) { + return FileHandlingUtils.writeToFile(file, text, append); + } + + /** + * Writes the string to a file, using UTF-8 as default encoding. + * @param path The path. + * @param text The string to be written. + * @param append A flag whether to append the content. + * @return A logical value indicating whether it was successful. + */ + public static boolean writeToFile(String path, String text, + boolean append) { + return FileHandlingUtils.writeToFile(new File(path), text, append); + } + + /** + * Writes the string list to a file, using UTF-8 as default encoding. + * @param file The file. + * @param lines The string list to be written. + * @param append A flag whether to append the content. + * @return A logical value indicating whether it was successful. + */ + public static boolean writeToFile(File file, List<String> lines, + boolean append) { + return FileHandlingUtils.writeToFile(file, lines, append); + } + + /** + * Writes the string list to a file, using UTF-8 as default encoding. + * @param path The path. + * @param lines The string list to be written. + * @param append A flag whether to append the content. + * @return A logical value indicating whether it was successful. + */ + public static boolean writeToFile(String path, List<String> lines, + boolean append) { + return FileHandlingUtils.writeToFile(new File(path), lines, append); + } + + /** + * Reads the provided file into a list of strings. + * @param file The file. + * @return A list of strings. + */ + public static List<String> readFromFile(File file) { + return FileHandlingUtils.readFromFile(file); + } + + /** + * Reads the provided file into a list of strings. + * @param path The path. + * @return A list of strings. + */ + public static List<String> readFromFile(String path) { + return FileHandlingUtils.readFromFile(new File(path)); + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/RuleUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/RuleUtils.java new file mode 100644 index 00000000000..d855344762d --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/RuleUtils.java @@ -0,0 +1,244 @@ +/** + * 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.utils; + +import com.github.cereda.arara.controller.LanguageController; +import com.github.cereda.arara.model.AraraException; +import com.github.cereda.arara.model.Argument; +import com.github.cereda.arara.model.Messages; +import com.github.cereda.arara.model.RuleCommand; +import com.github.cereda.arara.model.Rule; +import java.io.File; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Predicate; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.error.MarkedYAMLException; +import org.yaml.snakeyaml.nodes.Tag; +import org.yaml.snakeyaml.representer.Representer; + +/** + * Implements rule utilitary methods. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class RuleUtils { + + // the application messages obtained from the + // language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Parses the provided file, checks the identifier and returns a rule + * representation. + * @param file The rule file. + * @param identifier The directive identifier. + * @return The rule object. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + public static Rule parseRule(File file, String identifier) + throws AraraException { + Representer representer = new Representer(); + representer.addClassTag(Rule.class, new Tag("!config")); + Yaml yaml = new Yaml(new Constructor(Rule.class), representer); + Rule rule = null; + try { + rule = yaml.loadAs(new FileReader(file), Rule.class); + } catch (MarkedYAMLException yamlException) { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_PARSERULE_INVALID_YAML + ) + ), + yamlException + ); + } catch (Exception exception) { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_PARSERULE_GENERIC_ERROR + ) + ) + ); + } + validateHeader(rule, identifier); + validateBody(rule); + return rule; + } + + /** + * Validates the rule header according to the directive identifier. + * @param rule The rule object. + * @param identifier The directive identifier. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + private static void validateHeader(Rule rule, String identifier) + throws AraraException { + if (rule.getIdentifier() != null) { + if (!rule.getIdentifier().equals(identifier)) { + throw new AraraException(CommonUtils.getRuleErrorHeader(). + concat( + messages.getMessage( + Messages.ERROR_VALIDATEHEADER_WRONG_IDENTIFIER, + rule.getIdentifier(), + identifier + ) + ) + ); + } + } else { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_VALIDATEHEADER_NULL_ID + ) + ) + ); + } + if (rule.getName() == null) { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_VALIDATEHEADER_NULL_NAME + ) + ) + ); + } + } + + /** + * Validates the rule body. + * @param rule The rule object. + * @throws AraraException Something wrong happened, to be caught in the + * higher levels. + */ + private static void validateBody(Rule rule) throws AraraException { + if (rule.getCommands() == null) { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_VALIDATEBODY_NULL_COMMANDS_LIST + ) + ) + ); + } else { + if (CollectionUtils.exists(rule.getCommands(), + new Predicate<RuleCommand>() { + public boolean evaluate(RuleCommand command) { + return (command.getCommand() == null); + } + })) { + throw new AraraException(CommonUtils.getRuleErrorHeader(). + concat( + messages.getMessage( + Messages.ERROR_VALIDATEBODY_NULL_COMMAND + ) + ) + ); + } + } + if (rule.getArguments() == null) { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_VALIDATEBODY_ARGUMENTS_LIST + ) + ) + ); + } else { + String[] keywords = new String[]{"file", "files", "reference"}; + + List<String> arguments = new ArrayList<String>(); + for (Argument argument : rule.getArguments()) { + if (argument.getIdentifier() != null) { + if ((argument.getFlag() != null) || + (argument.getDefault() != null)) { + arguments.add(argument.getIdentifier()); + } else { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_VALIDATEBODY_MISSING_KEYS + ) + ) + ); + } + } else { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_VALIDATEBODY_NULL_ARGUMENT_ID + ) + ) + ); + } + } + + for (String keyword : keywords) { + if (arguments.contains(keyword)) { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_VALIDATEBODY_ARGUMENT_ID_IS_RESERVED, + keyword + ) + ) + ); + } + } + + int expected = arguments.size(); + int found = (new HashSet<String>(arguments)).size(); + if (expected != found) { + throw new AraraException( + CommonUtils.getRuleErrorHeader().concat( + messages.getMessage( + Messages.ERROR_VALIDATEBODY_DUPLICATE_ARGUMENT_IDENTIFIERS + ) + ) + ); + } + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/TeeOutputStream.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/TeeOutputStream.java index 36b5df82f59..65d3d58ffba 100644 --- a/Master/texmf-dist/source/support/arara/src/main/java/com/github/arara/utils/TeeOutputStream.java +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/TeeOutputStream.java @@ -1,7 +1,6 @@ /** - * \cond LICENSE - * Arara -- the cool TeX automation tool - * Copyright (c) 2012, Paulo Roberto Massa Cereda + * 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 @@ -31,125 +30,80 @@ * 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. - * \endcond - * - * TeeOutputStream: This class implements an output stream that handles other - * streams, so the flow is propagated to all of them in an easy way. */ -// package definition -package com.github.arara.utils; +package com.github.cereda.arara.utils; -// needed importa import java.io.IOException; import java.io.OutputStream; +import org.apache.commons.io.IOUtils; /** - * Implements an output stream that handles other streams, so the flow is - * propagated to all of them in an easy way. - * + * Implements a stream splitter. * @author Paulo Roberto Massa Cereda - * @version 3.0a - * @since 2.0 + * @version 4.0 + * @since 4.0 */ public class TeeOutputStream extends OutputStream { - // the list of the output streams + // an array of streams in which + // an object of this class will + // split data private final OutputStream[] streams; /** * Constructor. - * - * @param outputStreams An array containing the output streams. + * @param outputStreams An array of output streams. */ public TeeOutputStream(OutputStream... outputStreams) { - - // set the array streams = outputStreams; } /** - * Writes the byte to all the output streams. - * - * @param b The byte to write. - * @throws IOException Exception if an error ocurred. + * Writes the provided integer to each stream. + * @param b The provided integer + * @throws IOException An IO exception. */ @Override public void write(int b) throws IOException { - - // for every stream for (OutputStream ostream : streams) { - - // write the byte ostream.write(b); } } /** - * Writes an array of bytes to all the output streams. - * - * @param b The bytes to write. + * Writes the provided byte array to each stream, with the provided offset + * and length. + * @param b The byte array. * @param offset The offset. - * @param length Number of bytes. - * @throws IOException Exception if an error ocurred. + * @param length The length. + * @throws IOException An IO exception. */ @Override public void write(byte[] b, int offset, int length) throws IOException { - - // for every stream for (OutputStream ostream : streams) { - - // write the array ostream.write(b, offset, length); } } /** - * Flushes the stream. - * - * @throws IOException Exception if an error ocurred. + * Flushes every stream. + * @throws IOException An IO exception. */ @Override public void flush() throws IOException { - - // for every stream for (OutputStream ostream : streams) { - - // flush the stream ostream.flush(); } } /** - * Closes the stream. - * - * @throws IOException Exception if an error ocurred. + * Closes every stream silently. */ @Override - public void close() throws IOException { - - // for every stream + public void close() { for (OutputStream ostream : streams) { - - // try to close the stream - forceClose(ostream); - } - } - - /** - * Forces the stream to close without raising exceptions. - * - * @param ostream The stream. - */ - private void forceClose(OutputStream ostream) { - - // try to close - try { - - // close it - ostream.close(); - - } catch (IOException exception) { - // do nothing + IOUtils.closeQuietly(ostream); } } + } diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/UnsafeUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/UnsafeUtils.java new file mode 100644 index 00000000000..b989e074c8f --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/UnsafeUtils.java @@ -0,0 +1,87 @@ +/** + * 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.utils; + +import com.github.cereda.arara.model.Command; +import com.github.cereda.arara.model.Pair; +import org.zeroturnaround.exec.ProcessExecutor; +import org.zeroturnaround.exec.ProcessResult; + +/** + * Implements unsafe utilitary methods. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class UnsafeUtils { + + /** + * Executes a system command from the underlying operating system and + * returns a pair containing the exit status and the command output as a + * string. + * @param command The system command to be executed. + * @return A pair containing the exit status and the system command output + * as a string. + */ + public static Pair<Integer, String> executeSystemCommand(Command command) { + + try { + + // create a process result with the provided + // command, capturing the output + ProcessResult result = new ProcessExecutor( + command.getElements() + ).readOutput(true).execute(); + + // return the pair containing the exit status + // and the output string as UTF-8 + return new Pair<Integer, String>( + result.getExitValue(), + result.outputUTF8() + ); + + } catch (Exception exception) { + + // quack, quack, do nothing, just + // return a default error code + + // if something goes wrong, the default + // error branch returns an exit status of + // -99 and an empty string + return new Pair<Integer, String>(-99, ""); + + } + } + +} diff --git a/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/VelocityUtils.java b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/VelocityUtils.java new file mode 100644 index 00000000000..2040b671b70 --- /dev/null +++ b/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/utils/VelocityUtils.java @@ -0,0 +1,157 @@ +/** + * 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.utils; + +import com.github.cereda.arara.controller.LanguageController; +import com.github.cereda.arara.model.AraraException; +import com.github.cereda.arara.model.Messages; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.Map; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.exception.MethodInvocationException; +import org.apache.velocity.exception.ParseErrorException; +import org.apache.velocity.exception.ResourceNotFoundException; +import org.apache.velocity.runtime.RuntimeConstants; + +/** + * Implements the template merging from Apache Velocity. + * @author Paulo Roberto Massa Cereda + * @version 4.0 + * @since 4.0 + */ +public class VelocityUtils { + + // the language controller + private static final LanguageController messages = + LanguageController.getInstance(); + + /** + * Merges the provided template with the context map and writes the result + * in an output file. The operation relies on the Apache Velocity project. + * @param input The input file. + * @param output The output file. + * @param map The context map. + * @throws AraraException Something terribly wrong happened, to be caught + * in the higher levels. + */ + public static void mergeVelocityTemplate(File input, File output, + Map<String, Object> map) throws AraraException { + + // let us try + try { + + // create the template engine instance + VelocityEngine engine = new VelocityEngine(); + + // use the resource path trick: set the default + // location to the input file's parent directory, + // so our file is easily located + engine.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, + input.getCanonicalFile().getParent()); + + // set the logging feature of Apache Velocity to + // register the occurrences in a null provider + // (we do not want unnecessary verbose output) + engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, + "org.apache.velocity.runtime.log.NullLogSystem"); + + // init the engine with the + // provided settings + engine.init(); + + // create a context for Apache Velocity, + // based on the provided map + VelocityContext context = new VelocityContext(map); + + // get the template from the engine and + // read it as an UTF-8 file + Template template = engine.getTemplate(input.getName(), "UTF-8"); + + // create an output stream from + // the file output reference + FileOutputStream stream = new FileOutputStream(output); + + // create a writer based on the + // previously created stream + Writer writer = new OutputStreamWriter(stream, "UTF-8"); + + // merge the context map with the + // template file and write the result + // to the output stream writer + template.merge(context, writer); + + // close both writer + // and output stream + writer.close(); + stream.close(); + + } catch(ResourceNotFoundException rnfexception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VELOCITY_FILE_NOT_FOUND + ), + rnfexception + ); + } catch(ParseErrorException peexception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VELOCITY_PARSE_EXCEPTION + ), + peexception + ); + } catch(MethodInvocationException miexception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VELOCITY_METHOD_INVOCATION_EXCEPTION + ), + miexception + ); + } catch (IOException ioexception) { + throw new AraraException( + messages.getMessage( + Messages.ERROR_VELOCITY_FILE_NOT_FOUND + ), + ioexception + ); + } + + } + +} |