Version 1.1.0
authorNiki Roo <niki@nikiroo.be>
Sat, 18 Feb 2017 16:15:30 +0000 (17:15 +0100)
committerNiki Roo <niki@nikiroo.be>
Sat, 18 Feb 2017 16:15:30 +0000 (17:15 +0100)
- new Progress reporting system (currently only in CLI mode)
- fix on e621 for "pending" pools, which were not downloaded before
- unit tests system added (but no test yet, as all tests were moved into
  nikiroo-utils before release)

14 files changed:
VERSION
changelog.md [new file with mode: 0644]
configure.sh
libs/nikiroo-utils-1.1.0-sources.jar [moved from libs/nikiroo-utils-1.0.0-sources.jar with 70% similarity]
src/be/nikiroo/fanfix/Library.java
src/be/nikiroo/fanfix/Main.java
src/be/nikiroo/fanfix/reader/BasicReader.java
src/be/nikiroo/fanfix/reader/LocalReader.java
src/be/nikiroo/fanfix/reader/LocalReaderBook.java
src/be/nikiroo/fanfix/reader/LocalReaderFrame.java
src/be/nikiroo/fanfix/supported/BasicSupport.java
src/be/nikiroo/fanfix/supported/Cbz.java
src/be/nikiroo/fanfix/supported/E621.java
src/be/nikiroo/fanfix/test/Test.java [new file with mode: 0644]

diff --git a/VERSION b/VERSION
index 3eefcb9dd5b38e2c1dc061052455dd97bcd51e6c..9084fa2f716a7117829f3f32a5f4cef400e02903 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.0
+1.1.0
diff --git a/changelog.md b/changelog.md
new file mode 100644 (file)
index 0000000..a22be0e
--- /dev/null
@@ -0,0 +1,43 @@
+# Fanfix
+
+## Version 1.1.0
+
+- new Progress reporting system (currently only in CLI mode)
+- fix on e621 for "pending" pools, which were not downloaded before
+- unit tests system added (but no test yet, as all tests were moved into nikiroo-utils)
+
+## Version 1.0.0
+
+The GUI is now good enough to be released (export is still CLI-only though).
+
+- bugs fixed
+- GUI improved (a lot)
+- should be good enough for 1.0.0
+
+## Version 0.9.5
+
+- bugs fixed
+- WIN32 compatibility (tested on Windows 10)
+
+## Version 0.9.4
+
+- bugs fixed (lots of)
+- perf improved
+- use less cache files
+- GUI improvement (still not really OK, but OK enough I guess)
+
+## Version 0.9.3
+
+- bugs fixed (lots of)
+- first GUI implementation (which is ugly and buggy -- the buggly GUI)
+
+## Version 0.9.2
+
+Minimum JVM version: Java 1.6 (all binary JAR files will be released in 1.6).
+
+- bugs fixed
+
+## Version 0.9.1
+
+Initial version
+
index 1da9835fa5a4c402432551f4ae832c06d36dee04..ffdf498562370acd1224d82030662ec7ac6d0bb1 100755 (executable)
@@ -44,7 +44,7 @@ else
 fi;
 
 echo "MAIN = be/nikiroo/fanfix/Main" > Makefile
-echo "TEST = " >> Makefile
+echo "TEST = be/nikiroo/fanfix/test/Test" >> Makefile
 echo "TEST_PARAMS = $cols $ok $ko" >> Makefile
 echo "NAME = fanfix" >> Makefile
 echo "PREFIX = $PREFIX" >> Makefile
similarity index 70%
rename from libs/nikiroo-utils-1.0.0-sources.jar
rename to libs/nikiroo-utils-1.1.0-sources.jar
index ab8360ec257451dcbf8b6647bf76043c506d5de7..63466abeaaeb3febce5e9fbe97e58746c2a12297 100644 (file)
Binary files a/libs/nikiroo-utils-1.0.0-sources.jar and b/libs/nikiroo-utils-1.1.0-sources.jar differ
index 0d9e067f30dcb6c24fe2e3a1e48fa098464f04e9..03b584cf760849ec9fcaccc84529db806318ce87 100644 (file)
@@ -14,6 +14,7 @@ import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.fanfix.output.BasicOutput;
 import be.nikiroo.fanfix.output.BasicOutput.OutputType;
 import be.nikiroo.fanfix.supported.BasicSupport;
+import be.nikiroo.utils.ui.Progress;
 import be.nikiroo.fanfix.supported.BasicSupport.SupportType;
 import be.nikiroo.fanfix.supported.InfoReader;
 
@@ -135,10 +136,12 @@ public class Library {
         * 
         * @param luid
         *            the Library UID of the story
+        * @param pg
+        *            the optional progress reporter
         * 
         * @return the corresponding {@link Story} or NULL if not found
         */
-       public Story getStory(String luid) {
+       public Story getStory(String luid, Progress pg) {
                if (luid != null) {
                        for (Entry<MetaData, File> entry : getStories().entrySet()) {
                                if (luid.equals(entry.getKey().getLuid())) {
@@ -147,7 +150,8 @@ public class Library {
                                                                .getKey().getType());
                                                URL url = entry.getValue().toURI().toURL();
                                                if (type != null) {
-                                                       return BasicSupport.getSupport(type).process(url);
+                                                       return BasicSupport.getSupport(type).process(url,
+                                                                       pg);
                                                } else {
                                                        throw new IOException("Unknown type: "
                                                                        + entry.getKey().getType());
@@ -163,6 +167,11 @@ public class Library {
                        }
                }
 
+               if (pg != null) {
+                       pg.setMinMax(0, 1);
+                       pg.setProgress(1);
+               }
+
                return null;
        }
 
@@ -172,19 +181,21 @@ public class Library {
         * 
         * @param url
         *            the {@link URL} to import
+        * @param pg
+        *            the optional progress reporter
         * 
         * @return the imported {@link Story}
         * 
         * @throws IOException
         *             in case of I/O error
         */
-       public Story imprt(URL url) throws IOException {
+       public Story imprt(URL url, Progress pg) throws IOException {
                BasicSupport support = BasicSupport.getSupport(url);
                if (support == null) {
                        throw new IOException("URL not supported: " + url.toString());
                }
 
-               return save(support.process(url), null);
+               return save(support.process(url, pg), null);
        }
 
        /**
@@ -196,25 +207,27 @@ public class Library {
         *            the {@link OutputType} to transform it to
         * @param target
         *            the target to save to
+        * @param pg
+        *            the optional progress reporter
         * 
         * @return the saved resource (the main saved {@link File})
         * 
         * @throws IOException
         *             in case of I/O error
         */
-       public File export(String luid, OutputType type, String target)
+       public File export(String luid, OutputType type, String target, Progress pg)
                        throws IOException {
                BasicOutput out = BasicOutput.getOutput(type, true);
                if (out == null) {
                        throw new IOException("Output type not supported: " + type);
                }
 
-               Story story = getStory(luid);
+               Story story = getStory(luid, pg);
                if (story == null) {
                        throw new IOException("Cannot find story to export: " + luid);
                }
 
-               return out.process(getStory(luid), target);
+               return out.process(story, target);
        }
 
        /**
index f51071d5c82faffd10e7bedd9d5b81c1b593f96f..ed5664a7f1a41236f72d6c05658b144df2054cc0 100644 (file)
@@ -15,6 +15,7 @@ import be.nikiroo.fanfix.reader.BasicReader.ReaderType;
 import be.nikiroo.fanfix.supported.BasicSupport;
 import be.nikiroo.fanfix.supported.BasicSupport.SupportType;
 import be.nikiroo.utils.UIUtils;
+import be.nikiroo.utils.ui.Progress;
 
 /**
  * Main program entry point.
@@ -161,17 +162,40 @@ public class Main {
                        }
                }
 
+               final Progress mainProgress = new Progress(0, 80);
+               mainProgress.addProgressListener(new Progress.ProgressListener() {
+                       private int current = mainProgress.getMin();
+
+                       public void progress(Progress progress, String name) {
+                               int diff = progress.getProgress() - current;
+                               current += diff;
+
+                               StringBuilder builder = new StringBuilder();
+                               for (int i = 0; i < diff; i++) {
+                                       builder.append('.');
+                               }
+
+                               System.err.print(builder.toString());
+
+                               if (progress.isDone()) {
+                                       System.err.println("");
+                               }
+                       }
+               });
+               Progress pg = new Progress();
+               mainProgress.addProgress(pg, mainProgress.getMax());
+
                if (exitCode != 255) {
                        switch (action) {
                        case IMPORT:
-                               exitCode = imprt(urlString);
+                               exitCode = imprt(urlString, pg);
                                break;
                        case EXPORT:
-                               exitCode = export(luid, typeString, target);
+                               exitCode = export(luid, typeString, target, pg);
                                break;
                        case CONVERT:
                                exitCode = convert(urlString, typeString, target,
-                                               plusInfo == null ? false : plusInfo);
+                                               plusInfo == null ? false : plusInfo, pg);
                                break;
                        case LIST:
                                exitCode = list(typeString);
@@ -238,12 +262,14 @@ public class Main {
         * 
         * @param urlString
         *            the resource to import
+        * @param pg
+        *            the optional progress reporter
         * 
         * @return the exit return code (0 = success)
         */
-       public static int imprt(String urlString) {
+       public static int imprt(String urlString, Progress pg) {
                try {
-                       Story story = Instance.getLibrary().imprt(getUrl(urlString));
+                       Story story = Instance.getLibrary().imprt(getUrl(urlString), pg);
                        System.out.println(story.getMeta().getLuid() + ": \""
                                        + story.getMeta().getTitle() + "\" imported.");
                } catch (IOException e) {
@@ -263,10 +289,13 @@ public class Main {
         *            the {@link OutputType} to use
         * @param target
         *            the target
+        * @param pg
+        *            the optional progress reporter
         * 
         * @return the exit return code (0 = success)
         */
-       public static int export(String luid, String typeString, String target) {
+       public static int export(String luid, String typeString, String target,
+                       Progress pg) {
                OutputType type = OutputType.valueOfNullOkUC(typeString);
                if (type == null) {
                        Instance.syserr(new Exception(trans(StringId.OUTPUT_DESC,
@@ -275,7 +304,7 @@ public class Main {
                }
 
                try {
-                       Instance.getLibrary().export(luid, type, target);
+                       Instance.getLibrary().export(luid, type, target, pg);
                } catch (IOException e) {
                        Instance.syserr(e);
                        return 4;
@@ -318,9 +347,9 @@ public class Main {
                try {
                        BasicReader reader = BasicReader.getReader();
                        if (library) {
-                               reader.setStory(story);
+                               reader.setStory(story, null);
                        } else {
-                               reader.setStory(getUrl(story));
+                               reader.setStory(getUrl(story), null);
                        }
 
                        if (chapString != null) {
@@ -354,11 +383,13 @@ public class Main {
         * @param infoCover
         *            TRUE to also export the cover and info file, even if the given
         *            {@link OutputType} does not usually save them
+        * @param pg
+        *            the optional progress reporter
         * 
         * @return the exit return code (0 = success)
         */
        private static int convert(String urlString, String typeString,
-                       String target, boolean infoCover) {
+                       String target, boolean infoCover, Progress pg) {
                int exitCode = 0;
 
                String sourceName = urlString;
@@ -380,7 +411,7 @@ public class Main {
                                        BasicSupport support = BasicSupport.getSupport(source);
 
                                        if (support != null) {
-                                               Story story = support.process(source);
+                                               Story story = support.process(source, pg);
 
                                                try {
                                                        target = new File(target).getAbsolutePath();
index eabbe7e4408ddf758c623fd65c835e1a3643a95a..bc3bf72f2ab7f3c576daddac33b39d4a2bfa8052 100644 (file)
@@ -8,6 +8,7 @@ import be.nikiroo.fanfix.Library;
 import be.nikiroo.fanfix.bundles.Config;
 import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.fanfix.supported.BasicSupport;
+import be.nikiroo.utils.ui.Progress;
 
 /**
  * The class that handles the different {@link Story} readers you can use.
@@ -78,23 +79,16 @@ public abstract class BasicReader {
         * 
         * @param luid
         *            the {@link Story} ID
+        * @param pg
+        *            the optional progress reporter
+        * 
         * @throws IOException
         *             in case of I/O error
         */
-       public void setStory(String luid) throws IOException {
-               story = Instance.getLibrary().getStory(luid);
+       public void setStory(String luid, Progress pg) throws IOException {
+               story = Instance.getLibrary().getStory(luid, pg);
                if (story == null) {
-                       // if the LUID is wrong and < 3, pad it to 3 chars with "0" then
-                       // retry (since LUIDs are %03d)
-                       if (luid != null && luid.length() < 3) {
-                               while (luid.length() < 3) {
-                                       luid = "0" + luid;
-                               }
-                               setStory(luid);
-                       } else {
-                               throw new IOException("Cannot retrieve story from library: "
-                                               + luid);
-                       }
+                       throw new IOException("Cannot retrieve story from library: " + luid);
                }
        }
 
@@ -103,16 +97,19 @@ public abstract class BasicReader {
         * 
         * @param source
         *            the {@link Story} {@link URL}
+        * @param pg
+        *            the optional progress reporter
+        * 
         * @throws IOException
         *             in case of I/O error
         */
-       public void setStory(URL source) throws IOException {
+       public void setStory(URL source, Progress pg) throws IOException {
                BasicSupport support = BasicSupport.getSupport(source);
                if (support == null) {
                        throw new IOException("URL not supported: " + source.toString());
                }
 
-               story = support.process(source);
+               story = support.process(source, pg);
                if (story == null) {
                        throw new IOException(
                                        "Cannot retrieve story from external source: "
index c17e83eaa097531eb423473d544c60eabff92a64..88ffc5d42d534dbbfbf1fa7d89c8de310ec4d79a 100644 (file)
@@ -9,6 +9,7 @@ import be.nikiroo.fanfix.Library;
 import be.nikiroo.fanfix.bundles.UiConfig;
 import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.fanfix.output.BasicOutput.OutputType;
+import be.nikiroo.utils.ui.Progress;
 
 class LocalReader extends BasicReader {
        private Library lib;
@@ -46,10 +47,20 @@ class LocalReader extends BasicReader {
        public void read(int chapter) {
        }
 
-       // keep same luid
-       public void imprt(String luid) throws IOException {
+       /**
+        * Import the story into the local reader library, and keep the same LUID.
+        * 
+        * @param luid
+        *            the Library UID
+        * @param pg
+        *            the optional progress reporter
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public void imprt(String luid, Progress pg) throws IOException {
                try {
-                       Story story = Instance.getLibrary().getStory(luid);
+                       Story story = Instance.getLibrary().getStory(luid, pg);
                        if (story != null) {
                                story = lib.save(story, luid);
                        } else {
@@ -62,10 +73,23 @@ class LocalReader extends BasicReader {
                }
        }
 
-       public File getTarget(String luid) throws IOException {
+       /**
+        * Get the target file related to this {@link Story}.
+        * 
+        * @param luid
+        *            the LUID of the {@link Story}
+        * @param pg
+        *            the optional progress reporter
+        * 
+        * @return the target file
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public File getTarget(String luid, Progress pg) throws IOException {
                File file = lib.getFile(luid);
                if (file == null) {
-                       imprt(luid);
+                       imprt(luid, pg);
                        file = lib.getFile(luid);
                }
 
index 8e353d91472cb3b738490ca3c108a92a7de8bc55..e7bea6aa5c80736661cc7a852000c57743030b8a 100644 (file)
@@ -31,7 +31,7 @@ class LocalReaderBook extends JPanel {
         * 
         * @author niki
         */
-       interface BookActionListner extends EventListener {
+       interface BookActionListener extends EventListener {
                /**
                 * The book was selected (single click).
                 * 
@@ -67,7 +67,7 @@ class LocalReaderBook extends JPanel {
        private boolean hovered;
        private Date lastClick;
        private long doubleClickDelay = 200; // in ms
-       private List<BookActionListner> listeners;
+       private List<BookActionListener> listeners;
 
        public LocalReaderBook(MetaData meta) {
                if (meta.getCover() != null) {
@@ -134,7 +134,7 @@ class LocalReaderBook extends JPanel {
        }
 
        private void setupListeners() {
-               listeners = new ArrayList<LocalReaderBook.BookActionListner>();
+               listeners = new ArrayList<LocalReaderBook.BookActionListener>();
                addMouseListener(new MouseListener() {
                        public void mouseReleased(MouseEvent e) {
                        }
@@ -164,7 +164,7 @@ class LocalReaderBook extends JPanel {
        }
 
        private void click(boolean doubleClick) {
-               for (BookActionListner listener : listeners) {
+               for (BookActionListener listener : listeners) {
                        if (doubleClick) {
                                listener.action(this);
                        } else {
@@ -173,7 +173,7 @@ class LocalReaderBook extends JPanel {
                }
        }
 
-       public void addActionListener(BookActionListner listener) {
+       public void addActionListener(BookActionListener listener) {
                listeners.add(listener);
        }
 
index a7c743cf82858e6af475f25cda6e4b1f244880c2..d431d8e452ff821a375b07dd2a1ac19c4173344f 100644 (file)
@@ -24,7 +24,7 @@ import be.nikiroo.fanfix.Instance;
 import be.nikiroo.fanfix.Main;
 import be.nikiroo.fanfix.bundles.UiConfig;
 import be.nikiroo.fanfix.data.MetaData;
-import be.nikiroo.fanfix.reader.LocalReaderBook.BookActionListner;
+import be.nikiroo.fanfix.reader.LocalReaderBook.BookActionListener;
 import be.nikiroo.utils.WrapLayout;
 
 class LocalReaderFrame extends JFrame {
@@ -89,7 +89,7 @@ class LocalReaderFrame extends JFrame {
 
                        books.add(book);
                        final String luid = meta.getLuid();
-                       book.addActionListener(new BookActionListner() {
+                       book.addActionListener(new BookActionListener() {
                                public void select(LocalReaderBook book) {
                                        for (LocalReaderBook abook : books) {
                                                abook.setSelected(abook == book);
@@ -98,8 +98,8 @@ class LocalReaderFrame extends JFrame {
 
                                public void action(LocalReaderBook book) {
                                        try {
-                                               File target = LocalReaderFrame.this.reader
-                                                               .getTarget(luid);
+                                               File target = LocalReaderFrame.this.reader.getTarget(
+                                                               luid, null);
                                                Desktop.getDesktop().browse(target.toURI());
                                        } catch (IOException e) {
                                                Instance.syserr(e);
@@ -128,7 +128,7 @@ class LocalReaderFrame extends JFrame {
                                                                + "unresponsive until it is downloaded...",
                                                "Importing from URL", JOptionPane.QUESTION_MESSAGE);
                                if (url != null && !url.isEmpty()) {
-                                       if (Main.imprt(url) != 0) {
+                                       if (Main.imprt(url, null) != 0) {
                                                JOptionPane.showMessageDialog(LocalReaderFrame.this,
                                                                "Cannot import: " + url, "Imort error",
                                                                JOptionPane.ERROR_MESSAGE);
index 93155961eaea1ff36957553e102d420181a93b7c..c47d05e608dd43de574aa69cc96ee677168eccee 100644 (file)
@@ -24,6 +24,7 @@ import be.nikiroo.fanfix.data.Paragraph.ParagraphType;
 import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.utils.IOUtils;
 import be.nikiroo.utils.StringUtils;
+import be.nikiroo.utils.ui.Progress;
 
 /**
  * This class is the base class used by the other support classes. It can be
@@ -328,26 +329,42 @@ public abstract class BasicSupport {
         * 
         * @param url
         *            the story resource
+        * @param pg
+        *            the optional progress reporter
         * 
         * @return the {@link Story}
         * 
         * @throws IOException
         *             in case of I/O error
         */
-       public Story process(URL url) throws IOException {
+       public Story process(URL url, Progress pg) throws IOException {
+               if (pg == null) {
+                       pg = new Progress();
+               } else {
+                       pg.setMinMax(0, 100);
+               }
+
                setCurrentReferer(url);
 
+               pg.setProgress(1);
                try {
                        Story story = processMeta(url, false, true);
+                       pg.setProgress(10);
                        if (story == null) {
+                               pg.setProgress(100);
                                return null;
                        }
 
                        story.setChapters(new ArrayList<Chapter>());
 
                        List<Entry<String, URL>> chapters = getChapters(url, getInput());
+                       pg.setProgress(20);
+
                        int i = 1;
                        if (chapters != null) {
+                               Progress pgChaps = new Progress(0, chapters.size());
+                               pg.addProgress(pgChaps, 80);
+
                                for (Entry<String, URL> chap : chapters) {
                                        setCurrentReferer(chap.getValue());
                                        InputStream chapIn = Instance.getCache().open(
@@ -360,8 +377,11 @@ public abstract class BasicSupport {
                                                chapIn.close();
                                        }
 
+                                       pgChaps.setProgress(i);
                                        i++;
                                }
+                       } else {
+                               pg.setProgress(100);
                        }
 
                        return story;
index 1080ad2755adebb174ad7a3e04f4053c9e0b35f4..295dc15a92ddc699792fdd4914c7a05f14056918 100644 (file)
@@ -14,6 +14,7 @@ import be.nikiroo.fanfix.Instance;
 import be.nikiroo.fanfix.data.Chapter;
 import be.nikiroo.fanfix.data.Paragraph;
 import be.nikiroo.fanfix.data.Story;
+import be.nikiroo.utils.ui.Progress;
 
 /**
  * Support class for CBZ files (works better with CBZ created with this program,
@@ -54,7 +55,13 @@ class Cbz extends Epub {
        }
 
        @Override
-       public Story process(URL url) throws IOException {
+       public Story process(URL url, Progress pg) throws IOException {
+               if (pg == null) {
+                       pg = new Progress();
+               } else {
+                       pg.setMinMax(0, 100);
+               }
+
                Story story = processMeta(url, false, true);
                story.setChapters(new ArrayList<Chapter>());
                Chapter chap = new Chapter(1, null);
@@ -62,6 +69,7 @@ class Cbz extends Epub {
 
                ZipInputStream zipIn = new ZipInputStream(getInput());
 
+               pg.setProgress(10);
                List<String> images = new ArrayList<String>();
                for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn
                                .getNextEntry()) {
@@ -87,8 +95,11 @@ class Cbz extends Epub {
                        }
                }
 
+               pg.setProgress(80);
+
                // ZIP order is not sure
                Collections.sort(images);
+               pg.setProgress(90);
 
                for (String uuid : images) {
                        try {
@@ -99,6 +110,7 @@ class Cbz extends Epub {
                        }
                }
 
+               pg.setProgress(100);
                return story;
        }
 }
index 665bdd5100cb0e7ef2b10ebc972a0c0729dca607..5ebd6b317661cf0ff2b1ff0cf357559df469b380 100644 (file)
@@ -14,6 +14,7 @@ import be.nikiroo.fanfix.data.Chapter;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.utils.StringUtils;
+import be.nikiroo.utils.ui.Progress;
 
 /**
  * Support class for <a href="http://e621.net/">e621.net</a> and <a
@@ -54,9 +55,9 @@ class E621 extends BasicSupport {
        }
 
        @Override
-       public Story process(URL url) throws IOException {
+       public Story process(URL url, Progress pg) throws IOException {
                // There is no chapters on e621, just pagination...
-               Story story = super.process(url);
+               Story story = super.process(url, pg);
 
                Chapter only = new Chapter(1, null);
                for (Chapter chap : story) {
diff --git a/src/be/nikiroo/fanfix/test/Test.java b/src/be/nikiroo/fanfix/test/Test.java
new file mode 100644 (file)
index 0000000..2eaeff0
--- /dev/null
@@ -0,0 +1,24 @@
+package be.nikiroo.fanfix.test;
+
+import be.nikiroo.utils.test.TestLauncher;
+
+/**
+ * Tests for Fanfix.
+ * 
+ * @author niki
+ */
+public class Test extends TestLauncher {
+       public Test(String[] args) {
+               super("Fanfix (empty: all tests were moved to nikiroo-utils...)", args);
+       }
+
+       /**
+        * Main entry point of the program.
+        * 
+        * @param args
+        *            the arguments passed to the {@link TestLauncher}s.
+        */
+       static public void main(String[] args) {
+               System.exit(new Test(args).launch());
+       }
+}