Merge branch 'master' into source-zip
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/SourceZip.java b/javaparser-core/src/main/java/com/github/javaparser/utils/SourceZip.java
new file mode 100644
index 0000000..ac69230
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/SourceZip.java
@@ -0,0 +1,129 @@
+/*

+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.

+ * Copyright (C) 2011, 2013-2016 The JavaParser Team.

+ *

+ * This file is part of JavaParser.

+ *

+ * JavaParser can be used either under the terms of

+ * a) the GNU Lesser General Public License as published by

+ *     the Free Software Foundation, either version 3 of the License, or

+ *     (at your option) any later version.

+ * b) the terms of the Apache License

+ *

+ * You should have received a copy of both licenses in LICENCE.LGPL and

+ * LICENCE.APACHE. Please refer to those files for details.

+ *

+ * JavaParser is distributed in the hope that it will be useful,

+ * but WITHOUT ANY WARRANTY; without even the implied warranty of

+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+ * GNU Lesser General Public License for more details.

+ */

+

+package com.github.javaparser.utils;

+

+import static com.github.javaparser.ParseStart.COMPILATION_UNIT;

+import static com.github.javaparser.Providers.provider;

+import static com.github.javaparser.utils.Utils.assertNotNull;

+

+import java.io.IOException;

+import java.nio.file.Path;

+import java.nio.file.Paths;

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.List;

+import java.util.zip.ZipEntry;

+import java.util.zip.ZipFile;

+

+import com.github.javaparser.JavaParser;

+import com.github.javaparser.ParseResult;

+import com.github.javaparser.ParserConfiguration;

+import com.github.javaparser.ast.CompilationUnit;

+

+/**

+ * A collection of Java source files and its sub-directories located in a ZIP or JAR file on the file system.

+ * Files can be parsed with a callback.

+ *

+ */

+public class SourceZip {

+

+    private final Path zipPath;

+    private JavaParser javaParser;

+

+    /**

+     * Create a new ZIP parser. An instance of {@link JavaParser} with the default {@link ParserConfiguration} will be

+     * used to parse the ZIP.

+     *

+     * @param zipPath The absolute path of ZIP file to parse.

+     */

+    public SourceZip(Path zipPath) {

+        this(zipPath, new ParserConfiguration());

+    }

+

+    /**

+     * Create a new ZIP parser. An instance of {@link JavaParser} with the given configuration will be used to parse

+     * the ZIP.

+     *

+     * @param zipPath The absolute path of ZIP file to parse.

+     * @param configuration The configuration to initiate the default parser with.

+     */

+    public SourceZip(Path zipPath, ParserConfiguration configuration) {

+        assertNotNull(zipPath);

+        assertNotNull(configuration);

+        this.zipPath = zipPath.normalize();

+        this.javaParser = new JavaParser(configuration);

+        Log.info("New source zip at \"%s\"", this.zipPath);

+    }

+

+    /**

+     * Tries to parse all '.java' files in the ZIP located at this <i>SourceZip</i>'s path and returns the parse

+     * results in a list.

+     *

+     * @return A list of path-compilation unit pairs.

+     *

+     * @throws {@link IOException} If an error occurs while trying to parse the given source.

+     */

+    public List<Pair<Path, ParseResult<CompilationUnit>>> parse() throws IOException {

+        Log.info("Parsing zip at \"%s\"", zipPath);

+        try (ZipFile zipFile = new ZipFile(zipPath.toFile())) {

+            List<Pair<Path, ParseResult<CompilationUnit>>> results = new ArrayList<>();

+            for (ZipEntry entry : Collections.list(zipFile.entries())) {

+                if (!entry.isDirectory() && entry.getName().endsWith(".java")) {

+                    Log.info("Parsing zip entry \"%s\"", entry.getName());

+                    final ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT,

+                            provider(zipFile.getInputStream(entry)));

+                    results.add(new Pair(Paths.get(entry.getName()), result));

+                }

+            }

+            return results;

+        }

+    }

+

+    /**

+     * Get the path of the ZIP file to be parsed.

+     *

+     * @return The absolute path of this ZIP file.

+     */

+    public Path getZipPath() {

+        return zipPath;

+    }

+

+    /**

+     * Get the parser used for parsing.

+     *

+     * @return The currently set parser.

+     */

+    public JavaParser getJavaParser() {

+        return javaParser;

+    }

+

+    /**

+     * Set the parser that is used for parsing.

+     *

+     * @param javaParser The parser to use.

+     */

+    public SourceZip setJavaParser(JavaParser javaParser) {

+        assertNotNull(javaParser);

+        this.javaParser = javaParser;

+        return this;

+    }

+}

diff --git a/javaparser-testing/src/test/java/com/github/javaparser/utils/SourceZipTest.java b/javaparser-testing/src/test/java/com/github/javaparser/utils/SourceZipTest.java
new file mode 100644
index 0000000..d7efa46
--- /dev/null
+++ b/javaparser-testing/src/test/java/com/github/javaparser/utils/SourceZipTest.java
@@ -0,0 +1,66 @@
+/*

+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.

+ * Copyright (C) 2011, 2013-2016 The JavaParser Team.

+ *

+ * This file is part of JavaParser.

+ *

+ * JavaParser can be used either under the terms of

+ * a) the GNU Lesser General Public License as published by

+ *     the Free Software Foundation, either version 3 of the License, or

+ *     (at your option) any later version.

+ * b) the terms of the Apache License

+ *

+ * You should have received a copy of both licenses in LICENCE.LGPL and

+ * LICENCE.APACHE. Please refer to those files for details.

+ *

+ * JavaParser is distributed in the hope that it will be useful,

+ * but WITHOUT ANY WARRANTY; without even the implied warranty of

+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+ * GNU Lesser General Public License for more details.

+ */

+

+package com.github.javaparser.utils;

+

+import static org.junit.Assert.assertEquals;

+import static org.junit.Assert.assertTrue;

+

+import java.io.IOException;

+import java.net.URISyntaxException;

+import java.nio.file.Path;

+import java.nio.file.Paths;

+import java.util.ArrayList;

+import java.util.List;

+

+import org.junit.Test;

+

+import com.github.javaparser.ParseResult;

+import com.github.javaparser.ast.CompilationUnit;

+

+public class SourceZipTest {

+

+    private final Path testDir = CodeGenerationUtils.mavenModuleRoot(SourceZipTest.class)

+            .resolve(Paths.get("..", "javaparser-testing", "src", "test", "resources", "com", "github", "javaparser",

+                    "source_zip"))

+            .normalize();

+

+    @Test

+    public void parseTestDirectory() throws URISyntaxException, IOException {

+        SourceZip sourceZip = new SourceZip(testDir.resolve("test.zip"));

+        List<Pair<Path, ParseResult<CompilationUnit>>> results = sourceZip.parse();

+        assertEquals(3, results.size());

+        List<CompilationUnit> units = new ArrayList<>();

+        for (Pair<Path, ParseResult<CompilationUnit>> pr : results)

+            units.add(pr.b.getResult().get());

+        assertTrue(units.stream().allMatch(unit -> !unit.getTypes().isEmpty()));

+    }

+

+    @Test(expected = IOException.class)

+    public void dirAsZipIsNotAllowed() throws IOException {

+        new SourceZip(testDir.resolve("test")).parse();

+    }

+

+    @Test(expected = IOException.class)

+    public void fileAsZipIsNotAllowed() throws IOException {

+        new SourceZip(testDir.resolve("test.txt")).parse();

+    }

+}

diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/source_zip/test.txt b/javaparser-testing/src/test/resources/com/github/javaparser/source_zip/test.txt
new file mode 100644
index 0000000..487e034
--- /dev/null
+++ b/javaparser-testing/src/test/resources/com/github/javaparser/source_zip/test.txt
@@ -0,0 +1 @@
+foo bar qux
\ No newline at end of file
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/source_zip/test.zip b/javaparser-testing/src/test/resources/com/github/javaparser/source_zip/test.zip
new file mode 100644
index 0000000..dd9b18a
--- /dev/null
+++ b/javaparser-testing/src/test/resources/com/github/javaparser/source_zip/test.zip
Binary files differ