summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/support/arara/src/main/java/com/github/cereda/arara/Arara.java
blob: c644978c93b17c0c4185cb3fd975c1b9a252fb88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
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
    }

}