sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 01/01: Partial compatibility with JDK9 in root pom.xml, NetBeans configuration and doclet.
Date Wed, 20 Jun 2018 14:16:01 GMT
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch JDK9
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 6e2dfa0fd1e83f9f3b67df7932484e80ca161c33
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Wed Jun 20 16:13:58 2018 +0200

     Partial compatibility with JDK9 in root pom.xml, NetBeans configuration and doclet.
---
 core/sis-build-helper/pom.xml                      |  55 +-
 .../org/apache/sis/internal/doclet/Doclet.java     | 105 ++-
 .../sis/internal/{taglet => doclet}/Include.java   |  42 +-
 .../apache/sis/internal/doclet/InlineTaglet.java   | 158 ++++
 .../org/apache/sis/internal/doclet/Module.java     | 113 +++
 .../sis/internal/{taglet => doclet}/Preformat.java |  50 +-
 .../apache/sis/internal/doclet/package-info.java   |   5 +-
 .../apache/sis/internal/taglet/InlineTaglet.java   | 170 -----
 .../org/apache/sis/internal/taglet/Module.java     | 182 -----
 .../apache/sis/internal/taglet/package-info.java   |  27 -
 .../org/apache/sis/measure/RangeFormatTest.java    |  18 +-
 .../src/test/java/org/apache/sis/test/Assert.java  |   6 +-
 ide-project/NetBeans/nbproject/build-impl.xml      | 818 ++++++++++++++-------
 ide-project/NetBeans/nbproject/genfiles.properties |   4 +-
 ide-project/NetBeans/nbproject/project.properties  |  22 +-
 pom.xml                                            |  34 +-
 16 files changed, 990 insertions(+), 819 deletions(-)

diff --git a/core/sis-build-helper/pom.xml b/core/sis-build-helper/pom.xml
index f3b6e97..03f10de 100644
--- a/core/sis-build-helper/pom.xml
+++ b/core/sis-build-helper/pom.xml
@@ -88,6 +88,14 @@
   <build>
     <plugins>
       <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <compilerArgs>
+            <arg>--add-modules</arg> <arg>jdk.javadoc</arg>
+          </compilerArgs>
+        </configuration>
+      </plugin>
+      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-plugin-plugin</artifactId>
         <version>3.5</version>
@@ -133,51 +141,4 @@
     </dependency>
   </dependencies>
 
-
-  <!-- ===========================================================
-           Sun's tools dependency   (from Maven FAQ)
-       =========================================================== -->
-  <profiles>
-    <profile>
-      <id>default-tools.jar</id>
-      <activation>
-        <property>
-          <name>java.vendor</name>
-          <value>Sun Microsystems Inc.</value>
-        </property>
-      </activation>
-      <dependencies>
-        <dependency>
-          <groupId>com.sun</groupId>
-          <artifactId>tools</artifactId>
-          <version>${java.version}</version>
-          <scope>system</scope>
-          <systemPath>${java.home}/../lib/tools.jar</systemPath>
-        </dependency>
-      </dependencies>
-    </profile>
-
-    <!-- Following is a copy of the above profile with only the Java vendor name changed.
-         This copy will not be needed anymore if http://jira.codehaus.org/browse/MNG-3328
-         get fixed. -->
-    <profile>
-      <id>jdk8-tools.jar</id>
-      <activation>
-        <property>
-          <name>java.vendor</name>
-          <value>Oracle Corporation</value>
-        </property>
-      </activation>
-      <dependencies>
-        <dependency>
-          <groupId>com.sun</groupId>
-          <artifactId>tools</artifactId>
-          <version>${java.version}</version>
-          <scope>system</scope>
-          <systemPath>${java.home}/../lib/tools.jar</systemPath>
-        </dependency>
-      </dependencies>
-    </profile>
-  </profiles>
-
 </project>
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java
index 654f694..24a0478 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java
@@ -16,6 +16,10 @@
  */
 package org.apache.sis.internal.doclet;
 
+import java.util.Set;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -29,8 +33,11 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.nio.file.FileSystemException;
 import java.nio.file.Files;
-import com.sun.javadoc.RootDoc;
-import com.sun.tools.doclets.formats.html.HtmlDoclet;
+import javax.tools.Diagnostic;
+import jdk.javadoc.doclet.Reporter;
+import jdk.javadoc.doclet.Doclet.Option;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.doclet.StandardDoclet;
 
 
 /**
@@ -50,11 +57,11 @@ import com.sun.tools.doclets.formats.html.HtmlDoclet;
  * <p>This class presumes that all CSS files are encoded in UTF-8.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 0.8
  * @since   0.5
  * @module
  */
-public final class Doclet extends HtmlDoclet {
+public final class Doclet extends StandardDoclet {
     /**
      * The name of the standard stylesheet file generated by Javadoc.
      */
@@ -76,27 +83,81 @@ public final class Doclet extends HtmlDoclet {
     private static final String ENCODING = "UTF-8";
 
     /**
-     * Invoked by reflection for creating the doclet.
+     * The directory where HTML pages will be written.
+     */
+    private String outputDirectory;
+
+    /**
+     * Where to report warnings, or {@code null} if unknown.
+     */
+    Reporter reporter;
+
+    /**
+     * Invoked by the Javadoc tools for instantiating the custom doclet.
      */
     public Doclet() {
     }
 
     /**
-     * Invoked by Javadoc for starting the doclet.
+     * Invoked by the Javadoc tools for initializing the doclet.
      *
-     * @param  root  the root document.
-     * @return {@code true} on success, or {@code false} on failure.
+     * @param locale    the locale to use for formatting HTML content.
+     * @param reporter  where to report warnings and errors.
      */
-    public static boolean start(final RootDoc root) {
-        String outputDirectory = null;
-        for (final String[] option : root.options()) {
-            if (option.length == 2) {
-                if ("-d".equals(option[0])) {
-                    outputDirectory = option[1];
-                }
+    @Override
+    public void init(final Locale locale, final Reporter reporter) {
+        super.init(locale, reporter);
+        this.reporter = reporter;
+    }
+
+    /**
+     * Returns the options supported by the standard doclet.
+     *
+     * @return all the supported options.
+     */
+    @Override
+    public Set<Option> getSupportedOptions() {
+        final Set<Option> options = new LinkedHashSet<>();
+        for (final Option op : super.getSupportedOptions()) {
+            if (op.getNames().contains("-d")) {
+                options.add(new Option() {
+                    @Override public int          getArgumentCount() {return op.getArgumentCount();}
+                    @Override public String       getDescription()   {return op.getDescription();}
+                    @Override public Option.Kind  getKind()          {return op.getKind();}
+                    @Override public List<String> getNames()         {return op.getNames();}
+                    @Override public String       getParameters()    {return op.getParameters();}
+                    @Override public boolean process(final String option, final List<String> arguments) {
+                        outputDirectory = arguments.get(0);
+                        return op.process(option, arguments);
+                    }
+                });
+            } else {
+                options.add(op);
             }
         }
-        final boolean success = HtmlDoclet.start(root);
+        return options;
+    }
+
+    /**
+     * Returns a name identifying this doclet.
+     *
+     * @return "ApacheSIS".
+     */
+    @Override
+    public String getName() {
+        return "ApacheSIS";
+    }
+
+    /**
+     * Invoked by Javadoc for starting the doclet.
+     *
+     * @param  environment  the Javadoc environment.
+     * @return {@code true} on success, or {@code false} on failure.
+     */
+    @Override
+    @SuppressWarnings("CallToPrintStackTrace")
+    public boolean run(final DocletEnvironment environment) {
+        final boolean success = super.run(environment);
         if (success && outputDirectory != null) try {
             final File output = new File(outputDirectory);
             final File customCSS = customCSS(output);
@@ -109,10 +170,14 @@ public final class Doclet extends HtmlDoclet {
                 }
             }
         } catch (IOException e) {
-            final StringWriter buffer = new StringWriter();
-            final PrintWriter p = new PrintWriter(buffer);
-            e.printStackTrace(p);
-            root.printError(buffer.toString());
+            if (reporter != null) {
+                final StringWriter buffer = new StringWriter();
+                final PrintWriter p = new PrintWriter(buffer);
+                e.printStackTrace(p);
+                reporter.print(Diagnostic.Kind.ERROR, buffer.toString());
+            } else {
+                e.printStackTrace();            // This fallback should not be needed, but we are paranoiac.
+            }
             return false;
         }
         return success;
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/Include.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Include.java
similarity index 75%
rename from core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/Include.java
rename to core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Include.java
index 03c0a30..3c6cc6a 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/Include.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Include.java
@@ -14,13 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.taglet;
+package org.apache.sis.internal.doclet;
 
 import java.io.*;
-import java.util.Map;
-import com.sun.javadoc.Tag;
-import com.sun.javadoc.SourcePosition;
-import com.sun.tools.doclets.Taglet;
+import com.sun.source.doctree.DocTree;
 
 
 /**
@@ -36,7 +33,7 @@ import com.sun.tools.doclets.Taglet;
  * just before the parts to copy in the javadoc.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.5
+ * @version 0.8
  * @since   0.5
  * @module
  */
@@ -52,26 +49,16 @@ public final class Include extends InlineTaglet {
     private static final String DOCUMENT_END = "</body>";
 
     /**
-     * Register this taglet.
-     *
-     * @param  tagletMap  the map to register this tag to.
-     */
-    public static void register(final Map<String,Taglet> tagletMap) {
-       final Include tag = new Include();
-       tagletMap.put(tag.getName(), tag);
-    }
-
-    /**
-     * Constructs a default <code>@include</code> taglet.
+     * Constructs an <code>@include</code> taglet.
      */
-    private Include() {
+    public Include() {
         super();
     }
 
     /**
      * Returns the name of this custom tag.
      *
-     * @return the tag name.
+     * @return "include".
      */
     @Override
     public String getName() {
@@ -79,21 +66,20 @@ public final class Include extends InlineTaglet {
     }
 
     /**
-     * Given the <code>Tag</code> representation of this custom tag, return its string representation.
+     * Given the <code>DocTree</code> representation of this custom tag, return its string representation.
      *
      * @param  tag  the tag to format.
      * @return a string representation of the given tag.
      */
     @Override
-    public String toString(final Tag tag) {
-        final SourcePosition position = tag.position();
-        final String reference = tag.text();
+    protected String toString(final DocTree tag) {
+        final String reference = text(tag);
         final int sep = reference.indexOf('#');
         if (sep < 0) {
-            printWarning(position, "@include expected a reference like \"filename#anchor\" but got \"" + reference + "\".");
+            printWarning(tag, "@include expected a reference like \"filename#anchor\" but got \"" + reference + "\".");
             return reference;
         }
-        File file = position.file();
+        File file = file(tag);
         file = new File(file.getParentFile(), reference.substring(0, sep));
         final String anchor = reference.substring(sep + 1);
         final StringBuilder buffer = new StringBuilder();
@@ -104,7 +90,7 @@ public final class Include extends InlineTaglet {
             String line;
             int start, end;
             do if ((line = in.readLine()) == null) {
-                printWarning(position, "Header \"" + anchor + "\" not found in file " + file);
+                printWarning(tag, "Header \"" + anchor + "\" not found in file " + file);
                 return reference;
             }
             while ((start = line.indexOf(ANCHOR_START)) < 0 ||
@@ -117,7 +103,7 @@ public final class Include extends InlineTaglet {
             while (true) {
                 line = in.readLine();
                 if (line == null) {
-                    printWarning(position, "Unexpected end of file in " + file);
+                    printWarning(tag, "Unexpected end of file in " + file);
                     return reference;
                 }
                 start = line.indexOf(ANCHOR_START);
@@ -130,7 +116,7 @@ public final class Include extends InlineTaglet {
                 buffer.append(line).append('\n');
             }
         } catch (IOException e) {
-            printError(position, "Error reading " + file + ":\n" + e);
+            printError(tag, "Error reading " + file + ":\n" + e);
         }
         return buffer.toString();
     }
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/InlineTaglet.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/InlineTaglet.java
new file mode 100644
index 0000000..7d220f6
--- /dev/null
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/InlineTaglet.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.doclet;
+
+import java.io.File;
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.List;
+import javax.tools.Diagnostic;
+import javax.lang.model.element.Element;
+import jdk.javadoc.doclet.Reporter;
+import jdk.javadoc.doclet.Taglet;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.doctree.TextTree;
+import com.sun.source.doctree.UnknownInlineTagTree;
+import com.sun.source.tree.CompilationUnitTree;
+import jdk.javadoc.doclet.DocletEnvironment;
+
+
+/**
+ * Base class of inline taglets.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since   0.3
+ * @module
+ */
+abstract class InlineTaglet implements Taglet {
+    /**
+     * Where to report warnings, or {@code null} if unknown.
+     */
+    private Reporter reporter;
+
+    /**
+     * Constructs a default inline taglet.
+     */
+    InlineTaglet() {
+    }
+
+    /**
+     * Initializes this taglet with the given doclet environment and doclet.
+     *
+     * @param env     the environment in which the taglet is running.
+     * @param doclet  the doclet that instantiated this taglet.
+     */
+    @Override
+    public void init(final DocletEnvironment env, final jdk.javadoc.doclet.Doclet doclet) {
+        reporter = ((Doclet) doclet).reporter;
+    }
+
+    /**
+     * Returns the set of locations in which this taglet may be used.
+     * By default the taglet can be used everywhere.
+     *
+     * @return the set of locations in which this taglet may be used.
+     */
+    @Override
+    public Set<Taglet.Location> getAllowedLocations() {
+        return EnumSet.allOf(Taglet.Location.class);
+    }
+
+    /**
+     * Returns {@code true} since this base class is all about inline tags.
+     *
+     * @return always {@code true}.
+     */
+    @Override
+    public final boolean isInlineTag() {
+        return true;
+    }
+
+    /**
+     * Returns the text contained in the given inline tag.
+     */
+    static String text(final DocTree tag) {
+        for (final DocTree node : ((UnknownInlineTagTree) tag).getContent()) {
+            if (node.getKind() == DocTree.Kind.TEXT) {
+                return ((TextTree) node).getBody().trim();
+            }
+        }
+        return "";
+    }
+
+    /**
+     * Returns the file that contains the given tag.
+     */
+    static File file(final DocTree tag) {
+        return new File(getCompilationUnitTree(tag).getSourceFile().getName());
+    }
+
+    private static CompilationUnitTree getCompilationUnitTree(final DocTree tree) {
+        throw new UnsupportedOperationException("We have not yet found how to get the compilation unit."); // TODO
+    }
+
+    /**
+     * Given a list of {@code DocTree}s representing this custom tag, returns its string representation.
+     * This method will be invoked once for each instance of the tag in parsed Javadoc.
+     *
+     * @param  tags     the tags to format.
+     * @param  element  the element to which the enclosing comment belongs.
+     * @return a string representation of the given tags.
+     */
+    @Override
+    public final String toString(final List<? extends DocTree> tags, final Element element) {
+        final StringBuilder buffer = new StringBuilder(64);
+        for (final DocTree tag : tags) {
+            buffer.append(toString(tag));
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Given a single {@code DocTree}s representing this custom tag, returns its string representation.
+     * This method will be invoked once for each instance of the tag in parsed Javadoc.
+     *
+     * @param  tag  the tag to format.
+     * @return a string representation of the given tag.
+     */
+    protected abstract String toString(DocTree tag);
+
+    /**
+     * Prints a warning message.
+     */
+    @SuppressWarnings("UseOfSystemOutOrSystemErr")
+    final void printWarning(final DocTree tag, final String message) {
+        if (reporter != null) {
+            reporter.print(Diagnostic.Kind.WARNING, message);
+        } else {
+            System.err.println(message);
+        }
+    }
+
+    /**
+     * Prints an error message.
+     */
+    @SuppressWarnings("UseOfSystemOutOrSystemErr")
+    final void printError(final DocTree tag, final String message) {
+        if (reporter != null) {
+            reporter.print(Diagnostic.Kind.ERROR, message);
+        } else {
+            System.err.println(message);
+        }
+    }
+}
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Module.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Module.java
new file mode 100644
index 0000000..276e09a
--- /dev/null
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Module.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.doclet;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+import java.util.EnumSet;
+import jdk.javadoc.doclet.Taglet;
+import com.sun.source.doctree.DocTree;
+import javax.lang.model.element.Element;
+
+
+/**
+ * The <code>@module</code> tag. This tag expects no argument.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @version 0.8
+ * @since   0.3
+ * @module
+ */
+public final class Module implements Taglet {
+    /**
+     * The SIS module in which the <code>@module</code> taglet has been found.
+     */
+    private String module;
+
+    /**
+     * Constructs a <code>@module</code> taglet.
+     */
+    public Module() {
+        super();
+    }
+
+    /**
+     * Returns the name of this custom tag.
+     *
+     * @return "module".
+     */
+    @Override
+    public String getName() {
+        return "module";
+    }
+
+    /**
+     * Returns the set of locations in which this taglet may be used.
+     *
+     * @return the set of locations in which this taglet may be used.
+     */
+    @Override
+    public Set<Taglet.Location> getAllowedLocations() {
+        return EnumSet.of(Taglet.Location.PACKAGE,
+                          Taglet.Location.TYPE);
+    }
+
+    /**
+     * Returns {@code false} since <code>@module</code> is not an inline tag.
+     *
+     * @return always {@code false}.
+     */
+    @Override
+    public boolean isInlineTag() {
+        return false;
+    }
+
+    /**
+     * Given a list of {@code DocTree}s representing this custom tag, returns its string representation.
+     *
+     * @param  tags     the tags to format.
+     * @param  element  the element to which the enclosing comment belongs.
+     * @return a string representation of the given tags.
+     */
+    @Override
+    public String toString(final List<? extends DocTree> tags, final Element element) {
+        if (tags == null || tags.isEmpty()) {
+            return "";
+        }
+        final StringBuilder buffer = new StringBuilder(128);
+        buffer.append("\n<p><font size=\"-1\">");
+        for (final DocTree tag : tags) {
+            File file = InlineTaglet.file(tag);
+            module = file.getName();
+            while ((file = file.getParentFile()) != null) {
+                if (file.getName().equals("src")) {
+                    file = file.getParentFile();
+                    if (file != null) {
+                        module = file.getName();
+                    }
+                    break;
+                }
+            }
+            /*
+             * Appends the module link.
+             */
+            buffer.append("Defined in the <code>").append(module).append("</code> module");
+        }
+        return buffer.append("</font></p>\n").toString();
+    }
+}
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/Preformat.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Preformat.java
similarity index 86%
rename from core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/Preformat.java
rename to core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Preformat.java
index 335e6fe..c370054 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/Preformat.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Preformat.java
@@ -14,12 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.taglet;
+package org.apache.sis.internal.doclet;
 
-import java.util.Map;
 import java.util.StringTokenizer;
-import com.sun.javadoc.Tag;
-import com.sun.tools.doclets.Taglet;
+import com.sun.source.doctree.DocTree;
 import org.apache.sis.internal.book.CodeColorizer;
 
 
@@ -31,10 +29,10 @@ import org.apache.sis.internal.book.CodeColorizer;
  *
  * <p>This taglet will automatically replace {@code &}, {@code <} and {@code >} by their HTML entities.
  * The only exception is {@code &#64;}, which is converted to the original {@code @} character because
- * we can't use that character directly inside this taglet.</p>
+ * we can not use that character directly inside this taglet.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.3
+ * @version 0.8
  * @since   0.3
  * @module
  */
@@ -59,26 +57,16 @@ public final class Preformat extends InlineTaglet {
     };
 
     /**
-     * Register this taglet.
-     *
-     * @param tagletMap the map to register this tag to.
-     */
-    public static void register(final Map<String,Taglet> tagletMap) {
-       final Preformat tag = new Preformat();
-       tagletMap.put(tag.getName(), tag);
-    }
-
-    /**
-     * Constructs a default <code>@preformat</code> taglet.
+     * Constructs a <code>@preformat</code> taglet.
      */
-    private Preformat() {
+    public Preformat() {
         super();
     }
 
     /**
      * Returns the name of this custom tag.
      *
-     * @return the tag name.
+     * @return "preformat".
      */
     @Override
     public String getName() {
@@ -86,24 +74,14 @@ public final class Preformat extends InlineTaglet {
     }
 
     /**
-     * Returns {@code false} since <code>@preformat</code> can not be used in overview.
-     *
-     * @return always {@code false}.
-     */
-    @Override
-    public boolean inOverview() {
-        return false;
-    }
-
-    /**
-     * Given the <code>Tag</code> representation of this custom tag, return its string representation.
+     * Given the <code>DocTree</code> representation of this custom tag, return its string representation.
      *
-     * @param tag The tag to format.
+     * @param  tag  the tag to format.
      * @return a string representation of the given tag.
      */
     @Override
-    public String toString(final Tag tag) {
-        String text = tag.text().trim().replace("\r\n", "\n").replace('\r', '\n');
+    protected String toString(final DocTree tag) {
+        String text = text(tag).replace("\r\n", "\n").replace('\r', '\n');
         String format = "<unspecified>";
         /*
          * Extracts the first word, which is expected to be the format name.
@@ -119,7 +97,7 @@ public final class Preformat extends InlineTaglet {
         try {
             style = Style.valueOf(format);
         } catch (IllegalArgumentException e) {
-            printWarning(tag.position(), "Unknown format: " + format);
+            printWarning(tag, "Unknown format: " + format);
             style = Style.text;
         }
         /*
@@ -148,7 +126,7 @@ all:    while (tk.hasMoreTokens()) {
         /*
          * Nows inserts each line.
          */
-        final StringBuilder buffer = new StringBuilder("<pre class=\"code-sample\">");
+        final StringBuilder buffer = new StringBuilder("<blockquote><pre>");
         tk = new StringTokenizer(text, "\r\n", true);
         while (tk.hasMoreTokens()) {
             String line = tk.nextToken();
@@ -166,7 +144,7 @@ all:    while (tk.hasMoreTokens()) {
             }
             buffer.append(line);
         }
-        return buffer.append("</pre>").toString();
+        return buffer.append("</pre></blockquote>").toString();
     }
 
     /**
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/package-info.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/package-info.java
index 179291e..22a22e4 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/package-info.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/package-info.java
@@ -17,10 +17,11 @@
 
 
 /**
- * Doclet performing post-processing after Javadoc generation.
+ * Javadoc taglets for processing custom tags in SIS source code comments,
+ * together with doclet performing post-processing after Javadoc generation.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 0.8
  * @since   0.5
  * @module
  */
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/InlineTaglet.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/InlineTaglet.java
deleted file mode 100644
index cc95022..0000000
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/InlineTaglet.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.internal.taglet;
-
-import com.sun.javadoc.Tag;
-import com.sun.javadoc.RootDoc;
-import com.sun.javadoc.SourcePosition;
-import com.sun.tools.doclets.Taglet;
-import com.sun.tools.doclets.internal.toolkit.Configuration;
-import com.sun.tools.doclets.formats.html.ConfigurationImpl;
-
-
-/**
- * Base class of inline taglets.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.3
- * @since   0.3
- * @module
- */
-abstract class InlineTaglet implements Taglet {
-    /**
-     * The doclet configuration, created when first needed for reporting warnings.
-     */
-    private static Configuration configuration;
-
-    /**
-     * Returns the root document, or {@code null} if none.
-     */
-    private static synchronized RootDoc getRootDoc() {
-        if (configuration == null) {
-            configuration = new ConfigurationImpl();
-        }
-        return configuration.root;
-    }
-
-    /**
-     * Constructs a default inline taglet.
-     */
-    InlineTaglet() {
-    }
-
-    /**
-     * Returns {@code true} since SIS taglets can be used in overview.
-     *
-     * @return default to {@code true}.
-     */
-    @Override
-    public boolean inOverview() {
-        return true;
-    }
-
-    /**
-     * Returns {@code true} since SIS taglets can be used in package documentation.
-     *
-     * @return default to {@code true}.
-     */
-    @Override
-    public boolean inPackage() {
-        return true;
-    }
-
-    /**
-     * Returns {@code true} since SIS taglets can be used in type documentation
-     * (classes or interfaces).
-     *
-     * @return default to {@code true}.
-     */
-    @Override
-    public boolean inType() {
-        return true;
-    }
-
-    /**
-     * Returns {@code true} since SIS taglets can be used in constructor
-     *
-     * @return default to {@code true}.
-     */
-    @Override
-    public boolean inConstructor() {
-        return true;
-    }
-
-    /**
-     * Returns {@code true} since SIS taglets can be used in method documentation.
-     *
-     * @return default to {@code true}.
-     */
-    @Override
-    public boolean inMethod() {
-        return true;
-    }
-
-    /**
-     * Returns {@code true} since SIS taglets can be used in field documentation.
-     *
-     * @return default to {@code true}.
-     */
-    @Override
-    public boolean inField() {
-        return true;
-    }
-
-    /**
-     * Returns {@code true} since this base class is all about inline tags.
-     *
-     * @return always {@code true}.
-     */
-    @Override
-    public final boolean isInlineTag() {
-        return true;
-    }
-
-    /**
-     * Given an array of {@code Tag}s representing this custom tag, return its string
-     * representation. This method should not be called since arrays of inline tags do
-     * not exist. However we define it as a matter of principle.
-     *
-     * @param  tags  the tags to format.
-     * @return a string representation of the given tags.
-     */
-    @Override
-    public final String toString(final Tag[] tags) {
-        final StringBuilder buffer = new StringBuilder(64);
-        for (int i=0; i<tags.length; i++) {
-            buffer.append(toString(tags[i]));
-        }
-        return buffer.toString();
-    }
-
-    /**
-     * Prints a warning message.
-     */
-    @SuppressWarnings("UseOfSystemOutOrSystemErr")
-    static void printWarning(final SourcePosition position, final String message) {
-        final RootDoc root = getRootDoc();
-        if (root != null) {
-            root.printWarning(position, message);
-        } else {
-            System.err.println(message);
-        }
-    }
-
-    /**
-     * Prints an error message.
-     */
-    @SuppressWarnings("UseOfSystemOutOrSystemErr")
-    static void printError(final SourcePosition position, final String message) {
-        final RootDoc root = getRootDoc();
-        if (root != null) {
-            root.printError(position, message);
-        } else {
-            System.err.println(message);
-        }
-    }
-}
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/Module.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/Module.java
deleted file mode 100644
index 536258d..0000000
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/Module.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.internal.taglet;
-
-import java.io.File;
-import java.util.Map;
-import com.sun.javadoc.Tag;
-import com.sun.tools.doclets.Taglet;
-
-
-/**
- * The <code>@module</code> tag. This tag expects no argument.
- *
- * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.4
- * @since   0.3
- * @module
- */
-public final class Module implements Taglet {
-    /**
-     * Register this taglet.
-     *
-     * @param  tagletMap  the map to register this tag to.
-     */
-    public static void register(final Map<String,Taglet> tagletMap) {
-       final Module tag = new Module();
-       tagletMap.put(tag.getName(), tag);
-    }
-
-    /**
-     * The SIS module in which the <code>@module</code> taglet has been found.
-     */
-    private String module;
-
-    /**
-     * Constructs a default <code>@module</code> taglet.
-     */
-    private Module() {
-        super();
-    }
-
-    /**
-     * Returns the name of this custom tag.
-     *
-     * @return the tag name.
-     */
-    @Override
-    public String getName() {
-        return "module";
-    }
-
-    /**
-     * Returns {@code false} since <code>@module</code> can not be used in overview.
-     *
-     * @return always {@code false}.
-     */
-    @Override
-    public boolean inOverview() {
-        return false;
-    }
-
-    /**
-     * Returns {@code true} since <code>@module</code> can be used in package documentation.
-     *
-     * @return always {@code true}.
-     */
-    @Override
-    public boolean inPackage() {
-        return true;
-    }
-
-    /**
-     * Returns {@code true} since <code>@module</code> can be used in type documentation
-     * (classes or interfaces). This is actually its main target.
-     *
-     * @return always {@code true}.
-     */
-    @Override
-    public boolean inType() {
-        return true;
-    }
-
-    /**
-     * Returns {@code false} since <code>@module</code> can not be used in constructor.
-     *
-     * @return always {@code false}.
-     */
-    @Override
-    public boolean inConstructor() {
-        return false;
-    }
-
-    /**
-     * Returns {@code false} since <code>@module</code> can not be used in method documentation.
-     *
-     * @return always {@code false}.
-     */
-    @Override
-    public boolean inMethod() {
-        return false;
-    }
-
-    /**
-     * Returns {@code false} since <code>@module</code> can not be used in field documentation.
-     *
-     * @return always {@code false}.
-     */
-    @Override
-    public boolean inField() {
-        return false;
-    }
-
-    /**
-     * Returns {@code false} since <code>@module</code> is not an inline tag.
-     *
-     * @return always {@code false}.
-     */
-    @Override
-    public boolean isInlineTag() {
-        return false;
-    }
-
-    /**
-     * Given the <code>Tag</code> representation of this custom tag, return its string representation.
-     * The default implementation invokes the array variant of this method.
-     *
-     * @param  tag  the tag to format.
-     * @return a string representation of the given tag.
-     */
-    @Override
-    public String toString(final Tag tag) {
-        return toString(new Tag[] {tag});
-    }
-
-    /**
-     * Given an array of {@code Tag}s representing this custom tag, return its string
-     * representation.
-     *
-     * @param  tags  the tags to format.
-     * @return a string representation of the given tags.
-     */
-    @Override
-    public String toString(final Tag[] tags) {
-        if (tags == null || tags.length == 0) {
-            return "";
-        }
-        final StringBuilder buffer = new StringBuilder(128);
-        buffer.append("\n<p><font size=\"-1\">");
-        for (final Tag tag : tags) {
-            File file = tag.position().file();
-            module = file.getName();
-            while ((file = file.getParentFile()) != null) {
-                if (file.getName().equals("src")) {
-                    file = file.getParentFile();
-                    if (file != null) {
-                        module = file.getName();
-                    }
-                    break;
-                }
-            }
-            /*
-             * Appends the module link.
-             */
-            buffer.append("Defined in the <code>").append(module).append("</code> module");
-        }
-        return buffer.append("</font></p>\n").toString();
-    }
-}
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/package-info.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/package-info.java
deleted file mode 100644
index e8857ed..0000000
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/taglet/package-info.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-/**
- * Javadoc taglets for processing custom tags in SIS source code comments.
- *
- * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.3
- * @since   0.3
- * @module
- */
-package org.apache.sis.internal.taglet;
diff --git a/core/sis-utility/src/test/java/org/apache/sis/measure/RangeFormatTest.java b/core/sis-utility/src/test/java/org/apache/sis/measure/RangeFormatTest.java
index b87c675..0226cf2 100644
--- a/core/sis-utility/src/test/java/org/apache/sis/measure/RangeFormatTest.java
+++ b/core/sis-utility/src/test/java/org/apache/sis/measure/RangeFormatTest.java
@@ -322,11 +322,11 @@ public final strictfp class RangeFormatTest extends TestCase {
         String text = it.toString();
         findYears(it, RangeFormat.Field.MIN_VALUE, minPos);
         findYears(it, RangeFormat.Field.MAX_VALUE, maxPos);
-        assertEquals("[16/01/70 18:00 … 16/01/90 09:00]", text);
+        assertEquals("[16/01/1970 18:00 … 16/01/1990 09:00]", text);
         assertEquals( 7, minPos.getBeginIndex());
-        assertEquals( 9, minPos.getEndIndex());
-        assertEquals(24, maxPos.getBeginIndex());
-        assertEquals(26, maxPos.getEndIndex());
+        assertEquals(11, minPos.getEndIndex());
+        assertEquals(26, maxPos.getBeginIndex());
+        assertEquals(30, maxPos.getEndIndex());
         assertEquals(range, parse(text));
         /*
          * Try again with the infinity symbol in one endpoint.
@@ -335,18 +335,18 @@ public final strictfp class RangeFormatTest extends TestCase {
         it    = format.formatToCharacterIterator(range);
         text  = it.toString();
         findYears(it, RangeFormat.Field.MAX_VALUE, maxPos);
-        assertEquals("(−∞ … 01/01/90 00:00]", text);
+        assertEquals("(−∞ … 01/01/1990 00:00]", text);
         assertEquals(12, maxPos.getBeginIndex());
-        assertEquals(14, maxPos.getEndIndex());
+        assertEquals(16, maxPos.getEndIndex());
         assertEquals(range, parse(text));
 
         range = new Range<>(Date.class, new Date(20*YEAR), true, (Date) null, true);
         it    = format.formatToCharacterIterator(range);
         text  = it.toString();
         findYears(it, RangeFormat.Field.MIN_VALUE, minPos);
-        assertEquals("[01/01/90 00:00 … ∞)", text);
-        assertEquals(7, minPos.getBeginIndex());
-        assertEquals(9, minPos.getEndIndex());
+        assertEquals("[01/01/1990 00:00 … ∞)", text);
+        assertEquals( 7, minPos.getBeginIndex());
+        assertEquals(11, minPos.getEndIndex());
         assertEquals(range, parse(text));
     }
 
diff --git a/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java b/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java
index 34f9ce4..670f9a4 100644
--- a/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java
+++ b/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java
@@ -363,6 +363,7 @@ public strictfp class Assert extends org.opengis.test.Assert {
      * @return the deserialized object.
      */
     public static <T> T assertSerializedEquals(final T object) {
+        Objects.requireNonNull(object);
         final Object deserialized;
         try {
             final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
@@ -381,7 +382,10 @@ public strictfp class Assert extends org.opengis.test.Assert {
         } catch (IOException e) {
             throw new AssertionError(e.toString(), e);
         }
-        // Compares with the original object and returns it.
+        assertNotNull("Deserialized object shall not be null.", deserialized);
+        /*
+         * Compare with the original object and return it.
+         */
         @SuppressWarnings("unchecked")
         final Class<? extends T> type = (Class<? extends T>) object.getClass();
         assertEquals("Deserialized object not equal to the original one.", object, deserialized);
diff --git a/ide-project/NetBeans/nbproject/build-impl.xml b/ide-project/NetBeans/nbproject/build-impl.xml
index 1f0a2f8..1fdcce1 100644
--- a/ide-project/NetBeans/nbproject/build-impl.xml
+++ b/ide-project/NetBeans/nbproject/build-impl.xml
@@ -19,7 +19,7 @@ is divided into following sections:
   - cleanup
 
         -->
-<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="Apache_SIS_on_GeoAPI_4.0-impl">
+<project xmlns:if="ant:if" xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" xmlns:unless="ant:unless" basedir=".." default="default" name="Apache_SIS_on_GeoAPI_4.0-impl">
     <fail message="Please build using Ant 1.8.0 or higher.">
         <condition>
             <not>
@@ -53,7 +53,72 @@ is divided into following sections:
         <property file="nbproject/configs/${config}.properties"/>
         <property file="nbproject/project.properties"/>
     </target>
-    <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
+    <target name="-init-modules-supported">
+        <condition property="modules.supported.internal" value="true">
+            <not>
+                <matches pattern="1\.[0-8](\..*)?" string="${javac.source}"/>
+            </not>
+        </condition>
+    </target>
+    <target depends="-init-modules-supported" if="modules.supported.internal" name="-init-macrodef-modulename">
+        <macrodef name="modulename" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute name="property"/>
+            <attribute name="sourcepath"/>
+            <sequential>
+                <loadresource property="@{property}" quiet="true">
+                    <javaresource classpath="@{sourcepath}" name="module-info.java" parentFirst="false"/>
+                    <filterchain>
+                        <stripjavacomments/>
+                        <linecontainsregexp>
+                            <regexp pattern="module .* \{"/>
+                        </linecontainsregexp>
+                        <tokenfilter>
+                            <linetokenizer/>
+                            <replaceregex flags="s" pattern="(\s*module\s+)(\S*)(\s*\{.*)" replace="\2"/>
+                        </tokenfilter>
+                        <striplinebreaks/>
+                    </filterchain>
+                </loadresource>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-modules-supported,-init-macrodef-modulename" if="modules.supported.internal" name="-init-source-module-properties">
+        <fail message="Java 9 support requires Ant 1.10.0 or higher.">
+            <condition>
+                <not>
+                    <antversion atleast="1.10.0"/>
+                </not>
+            </condition>
+        </fail>
+        <j2seproject3:modulename property="module.name" sourcepath="${src.local-src.dir}:${src.webapp.dir}:${src.javafx.dir}:${src.console.dir}:${src.portrayal.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.sql.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}"/>
+        <condition property="named.module.internal">
+            <and>
+                <isset property="module.name"/>
+                <length length="0" string="${module.name}" when="greater"/>
+            </and>
+        </condition>
+        <condition property="unnamed.module.internal">
+            <not>
+                <isset property="named.module.internal"/>
+            </not>
+        </condition>
+        <property name="javac.modulepath" value=""/>
+        <property name="run.modulepath" value="${javac.modulepath}"/>
+        <property name="module.build.classes.dir" value="${build.classes.dir}"/>
+        <property name="debug.modulepath" value="${run.modulepath}"/>
+        <property name="javac.upgrademodulepath" value=""/>
+        <property name="run.upgrademodulepath" value="${javac.upgrademodulepath}"/>
+        <condition else="" property="javac.systemmodulepath.cmd.line.arg" value="--system '${javac.systemmodulepath}'">
+            <and>
+                <isset property="javac.systemmodulepath"/>
+                <length length="0" string="${javac.systemmodulepath}" when="greater"/>
+            </and>
+        </condition>
+        <property name="dist.jlink.dir" value="${dist.dir}/jlink"/>
+        <property name="dist.jlink.output" value="${dist.jlink.dir}/${application.title}"/>
+        <property name="module.name" value=""/>
+    </target>
+    <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property,-init-modules-supported" name="-do-init">
         <property name="platform.java" value="${java.home}/bin/java"/>
         <available file="${manifest.file}" property="manifest.available"/>
         <condition property="splashscreen.available">
@@ -76,7 +141,9 @@ is divided into following sections:
             <and>
                 <isset property="javac.profile"/>
                 <length length="0" string="${javac.profile}" when="greater"/>
-                <matches pattern="((1\.[89])|9)(\..*)?" string="${javac.source}"/>
+                <not>
+                    <matches pattern="1\.[0-7](\..*)?" string="${javac.source}"/>
+                </not>
             </and>
         </condition>
         <condition property="do.archive">
@@ -94,6 +161,9 @@ is divided into following sections:
                 <not>
                     <istrue value="${mkdist.disabled}"/>
                 </not>
+                <not>
+                    <istrue value="${modules.supported.internal}"/>
+                </not>
             </and>
         </condition>
         <condition property="do.archive+manifest.available">
@@ -326,11 +396,80 @@ is divided into following sections:
             </sequential>
         </macrodef>
     </target>
-    <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors">
+    <target depends="-init-ap-cmdline-properties,-init-source-module-properties" if="modules.supported.internal" name="-init-macrodef-javac-with-module">
+        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${src.local-src.dir}:${src.webapp.dir}:${src.javafx.dir}:${src.console.dir}:${src.portrayal.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.sql.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}" name="srcdir"/>
+            <attribute default="${build.classes.dir}" name="destdir"/>
+            <attribute default="${javac.classpath}" name="classpath"/>
+            <attribute default="${javac.modulepath}" name="modulepath"/>
+            <attribute default="${javac.upgrademodulepath}" name="upgrademodulepath"/>
+            <attribute default="${javac.processorpath}" name="processorpath"/>
+            <attribute default="${javac.processormodulepath}" name="processormodulepath"/>
+            <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="${javac.debug}" name="debug"/>
+            <attribute default="${empty.dir}" name="sourcepath" unless:set="named.module.internal"/>
+            <attribute default="${src.local-src.dir}:${src.webapp.dir}:${src.javafx.dir}:${src.console.dir}:${src.portrayal.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.sql.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}" if:set="named.module.internal" name="sourcepath"/>
+            <attribute default="${empty.dir}" name="gensrcdir"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <condition property="warn.excludes.internal">
+                    <and>
+                        <isset property="named.module.internal"/>
+                        <length length="0" string="@{excludes}" trim="true" when="greater"/>
+                    </and>
+                </condition>
+                <echo if:set="warn.excludes.internal" level="warning" message="The javac excludes are not supported in the JDK 9 Named Module."/>
+                <property location="${build.dir}/empty" name="empty.dir"/>
+                <mkdir dir="${empty.dir}"/>
+                <mkdir dir="@{apgeneratedsrcdir}"/>
+                <condition property="processormodulepath.set">
+                    <resourcecount count="0" when="greater">
+                        <path>
+                            <pathelement path="@{processormodulepath}"/>
+                        </path>
+                    </resourcecount>
+                </condition>
+                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+                    <src>
+                        <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+                            <include name="*"/>
+                        </dirset>
+                    </src>
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <modulepath>
+                        <path path="@{modulepath}"/>
+                    </modulepath>
+                    <upgrademodulepath>
+                        <path path="@{upgrademodulepath}"/>
+                    </upgrademodulepath>
+                    <compilerarg line="${javac.systemmodulepath.cmd.line.arg}"/>
+                    <compilerarg line="${javac.profile.cmd.line.arg}"/>
+                    <compilerarg line="${javac.compilerargs}"/>
+                    <compilerarg if:set="processormodulepath.set" value="--processor-module-path"/>
+                    <compilerarg if:set="processormodulepath.set" path="@{processormodulepath}"/>
+                    <compilerarg unless:set="processormodulepath.set" value="-processorpath"/>
+                    <compilerarg path="@{processorpath}:${empty.dir}" unless:set="processormodulepath.set"/>
+                    <compilerarg line="${ap.processors.internal}"/>
+                    <compilerarg line="${annotation.processing.processor.options}"/>
+                    <compilerarg value="-s"/>
+                    <compilerarg path="@{apgeneratedsrcdir}"/>
+                    <compilerarg line="${ap.proc.none.internal}"/>
+                    <customize/>
+                </javac>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-ap-cmdline-properties,-init-source-module-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors" unless="modules.supported.internal">
         <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
             <attribute default="${src.local-src.dir}:${src.webapp.dir}:${src.javafx.dir}:${src.console.dir}:${src.portrayal.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.sql.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}" name="srcdir"/>
             <attribute default="${build.classes.dir}" name="destdir"/>
             <attribute default="${javac.classpath}" name="classpath"/>
+            <attribute default="${javac.modulepath}" name="modulepath"/>
+            <attribute default="${javac.upgrademodulepath}" name="upgrademodulepath"/>
             <attribute default="${javac.processorpath}" name="processorpath"/>
             <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
             <attribute default="${includes}" name="includes"/>
@@ -367,11 +506,13 @@ is divided into following sections:
             </sequential>
         </macrodef>
     </target>
-    <target depends="-init-ap-cmdline-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">
+    <target depends="-init-ap-cmdline-properties,-init-source-module-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">
         <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
             <attribute default="${src.local-src.dir}:${src.webapp.dir}:${src.javafx.dir}:${src.console.dir}:${src.portrayal.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.sql.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}" name="srcdir"/>
             <attribute default="${build.classes.dir}" name="destdir"/>
             <attribute default="${javac.classpath}" name="classpath"/>
+            <attribute default="${javac.modulepath}" name="modulepath"/>
+            <attribute default="${javac.upgrademodulepath}" name="upgrademodulepath"/>
             <attribute default="${javac.processorpath}" name="processorpath"/>
             <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
             <attribute default="${includes}" name="includes"/>
@@ -400,7 +541,7 @@ is divided into following sections:
             </sequential>
         </macrodef>
     </target>
-    <target depends="-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">
+    <target depends="-init-macrodef-javac-with-module,-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">
         <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
             <attribute default="${src.local-src.dir}:${src.webapp.dir}:${src.javafx.dir}:${src.console.dir}:${src.portrayal.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.sql.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}" name="srcdir"/>
             <attribute default="${build.classes.dir}" name="destdir"/>
@@ -455,113 +596,153 @@ is divided into following sections:
         <property name="test.binarytestincludes" value=""/>
         <property name="test.binaryexcludes" value=""/>
     </target>
-    <target if="${nb.junit.single}" name="-init-macrodef-junit-single" unless="${nb.junit.batch}">
-        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+    <target depends="-init-modules-supported" if="modules.supported.internal" name="-init-macrodef-junit-prototype-with-module">
+        <macrodef name="junit-prototype" uri="http://www.netbeans.org/ns/j2se-project/3">
             <attribute default="${includes}" name="includes"/>
             <attribute default="${excludes}" name="excludes"/>
-            <attribute default="**" name="testincludes"/>
-            <attribute default="" name="testmethods"/>
-            <element name="customize" optional="true"/>
+            <element name="customizePrototype" optional="true"/>
             <sequential>
                 <property name="junit.forkmode" value="perTest"/>
                 <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
-                    <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
                     <syspropertyset>
                         <propertyref prefix="test-sys-prop."/>
                         <mapper from="test-sys-prop.*" to="*" type="glob"/>
                     </syspropertyset>
+                    <classpath>
+                        <path path="${run.test.classpath}"/>
+                    </classpath>
+                    <modulepath>
+                        <path path="${run.test.modulepath}"/>
+                    </modulepath>
                     <formatter type="brief" usefile="false"/>
                     <formatter type="xml"/>
+                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                     <jvmarg value="-ea"/>
-                    <customize/>
+                    <jvmarg line="${run.test.jvmargs}"/>
+                    <customizePrototype/>
                 </junit>
             </sequential>
         </macrodef>
     </target>
-    <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-batch" unless="${nb.junit.single}">
-        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+    <target depends="-init-modules-supported" name="-init-macrodef-junit-prototype-without-module" unless="modules.supported.internal">
+        <macrodef name="junit-prototype" uri="http://www.netbeans.org/ns/j2se-project/3">
             <attribute default="${includes}" name="includes"/>
             <attribute default="${excludes}" name="excludes"/>
-            <attribute default="**" name="testincludes"/>
-            <attribute default="" name="testmethods"/>
-            <element name="customize" optional="true"/>
+            <element name="customizePrototype" optional="true"/>
             <sequential>
                 <property name="junit.forkmode" value="perTest"/>
                 <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
-                    <batchtest todir="${build.test.results.dir}">
-                        <fileset dir="${test.webapp.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.javafx.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.console.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.portrayal.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.earth-obs.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.geotiff.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.netcdf.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.shapefile.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.sql.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.xmlstore.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.storage.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.feature.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.raster.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.referencing.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.ref-by-id.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.metadata.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.utility.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.fra-profile.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.gdal.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
-                            <filename name="${test.binarytestincludes}"/>
-                        </fileset>
-                    </batchtest>
                     <syspropertyset>
                         <propertyref prefix="test-sys-prop."/>
                         <mapper from="test-sys-prop.*" to="*" type="glob"/>
                     </syspropertyset>
+                    <classpath>
+                        <path path="${run.test.classpath}"/>
+                    </classpath>
                     <formatter type="brief" usefile="false"/>
                     <formatter type="xml"/>
+                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                     <jvmarg value="-ea"/>
-                    <customize/>
+                    <customizePrototype/>
                 </junit>
             </sequential>
         </macrodef>
     </target>
+    <target depends="-init-test-properties,-init-macrodef-junit-prototype-with-module,-init-macrodef-junit-prototype-without-module" if="${nb.junit.single}" name="-init-macrodef-junit-single" unless="${nb.junit.batch}">
+        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <j2seproject3:junit-prototype>
+                    <customizePrototype>
+                        <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
+                        <customize/>
+                    </customizePrototype>
+                </j2seproject3:junit-prototype>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-test-properties,-init-macrodef-junit-prototype-with-module,-init-macrodef-junit-prototype-without-module" if="${nb.junit.batch}" name="-init-macrodef-junit-batch" unless="${nb.junit.single}">
+        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <j2seproject3:junit-prototype>
+                    <customizePrototype>
+                        <batchtest todir="${build.test.results.dir}">
+                            <fileset dir="${test.webapp.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.javafx.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.console.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.portrayal.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.earth-obs.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.geotiff.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.netcdf.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.shapefile.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.sql.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.xmlstore.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.storage.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.feature.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.raster.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.referencing.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.ref-by-id.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.metadata.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.utility.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.fra-profile.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${test.gdal.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
+                                <filename name="${test.binarytestincludes}"/>
+                            </fileset>
+                        </batchtest>
+                        <customize/>
+                    </customizePrototype>
+                </j2seproject3:junit-prototype>
+            </sequential>
+        </macrodef>
+    </target>
     <target depends="-init-macrodef-junit-init,-init-macrodef-junit-single, -init-macrodef-junit-batch" if="${junit.available}" name="-init-macrodef-junit"/>
     <target if="${testng.available}" name="-init-macrodef-testng">
         <macrodef name="testng" uri="http://www.netbeans.org/ns/j2se-project/3">
@@ -640,6 +821,10 @@ is divided into following sections:
                         <propertyref prefix="test-sys-prop."/>
                         <mapper from="test-sys-prop.*" to="*" type="glob"/>
                     </propertyset>
+                    <classpath>
+                        <path path="${run.test.classpath}"/>
+                    </classpath>
+                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                     <customize/>
                 </testng>
             </sequential>
@@ -694,10 +879,6 @@ is divided into following sections:
             <sequential>
                 <j2seproject3:test-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
                     <customize>
-                        <classpath>
-                            <path path="${run.test.classpath}"/>
-                        </classpath>
-                        <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                         <jvmarg line="${run.jvmargs}"/>
                         <jvmarg line="${run.jvmargs.ide}"/>
                     </customize>
@@ -705,128 +886,20 @@ is divided into following sections:
             </sequential>
         </macrodef>
     </target>
-    <target if="${junit.available}" name="-init-macrodef-junit-debug" unless="${nb.junit.batch}">
-        <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${includes}" name="includes"/>
-            <attribute default="${excludes}" name="excludes"/>
-            <attribute default="**" name="testincludes"/>
-            <attribute default="" name="testmethods"/>
-            <element name="customize" optional="true"/>
-            <sequential>
-                <property name="junit.forkmode" value="perTest"/>
-                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
-                    <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
-                    <syspropertyset>
-                        <propertyref prefix="test-sys-prop."/>
-                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
-                    </syspropertyset>
-                    <formatter type="brief" usefile="false"/>
-                    <formatter type="xml"/>
-                    <jvmarg value="-ea"/>
-                    <jvmarg line="${debug-args-line}"/>
-                    <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
-                    <customize/>
-                </junit>
-            </sequential>
-        </macrodef>
-    </target>
-    <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-debug-batch">
-        <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${includes}" name="includes"/>
-            <attribute default="${excludes}" name="excludes"/>
-            <attribute default="**" name="testincludes"/>
-            <attribute default="" name="testmethods"/>
-            <element name="customize" optional="true"/>
-            <sequential>
-                <property name="junit.forkmode" value="perTest"/>
-                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
-                    <batchtest todir="${build.test.results.dir}">
-                        <fileset dir="${test.webapp.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.javafx.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.console.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.portrayal.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.earth-obs.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.geotiff.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.netcdf.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.shapefile.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.sql.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.xmlstore.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.storage.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.feature.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.raster.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.referencing.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.ref-by-id.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.metadata.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.utility.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.fra-profile.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${test.gdal.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                        <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
-                            <filename name="${test.binarytestincludes}"/>
-                        </fileset>
-                    </batchtest>
-                    <syspropertyset>
-                        <propertyref prefix="test-sys-prop."/>
-                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
-                    </syspropertyset>
-                    <formatter type="brief" usefile="false"/>
-                    <formatter type="xml"/>
-                    <jvmarg value="-ea"/>
-                    <jvmarg line="${debug-args-line}"/>
-                    <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
-                    <customize/>
-                </junit>
-            </sequential>
-        </macrodef>
-    </target>
-    <target depends="-init-macrodef-junit-debug,-init-macrodef-junit-debug-batch" if="${junit.available}" name="-init-macrodef-junit-debug-impl">
+    <target depends="-init-macrodef-junit" if="${junit.available}" name="-init-macrodef-junit-debug-impl">
         <macrodef name="test-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
             <attribute default="${includes}" name="includes"/>
             <attribute default="${excludes}" name="excludes"/>
             <attribute default="**" name="testincludes"/>
             <attribute default="" name="testmethods"/>
-            <element implicit="true" name="customize" optional="true"/>
+            <element name="customizeDebuggee" optional="true"/>
             <sequential>
-                <j2seproject3:junit-debug excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
-                    <customize/>
-                </j2seproject3:junit-debug>
+                <j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+                    <customize>
+                        <jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/>
+                        <customizeDebuggee/>
+                    </customize>
+                </j2seproject3:junit>
             </sequential>
         </macrodef>
     </target>
@@ -845,14 +918,14 @@ is divided into following sections:
                 <delete dir="${build.test.results.dir}" quiet="true"/>
                 <mkdir dir="${build.test.results.dir}"/>
                 <j2seproject3:debug classname="org.testng.TestNG" classpath="${debug.test.classpath}">
-                    <customize>
+                    <customizeDebuggee>
                         <customize2/>
                         <jvmarg value="-ea"/>
                         <arg line="${testng.debug.mode}"/>
                         <arg line="-d ${build.test.results.dir}"/>
                         <arg line="-listener org.testng.reporters.VerboseReporter"/>
                         <arg line="${testng.cmd.args}"/>
-                    </customize>
+                    </customizeDebuggee>
                 </j2seproject3:debug>
             </sequential>
         </macrodef>
@@ -879,14 +952,10 @@ is divided into following sections:
             <attribute default="" name="testMethod"/>
             <sequential>
                 <j2seproject3:test-debug-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
-                    <customize>
-                        <classpath>
-                            <path path="${run.test.classpath}"/>
-                        </classpath>
-                        <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+                    <customizeDebuggee>
                         <jvmarg line="${run.jvmargs}"/>
                         <jvmarg line="${run.jvmargs.ide}"/>
-                    </customize>
+                    </customizeDebuggee>
                 </j2seproject3:test-debug-impl>
             </sequential>
         </macrodef>
@@ -966,10 +1035,14 @@ is divided into following sections:
     <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
         <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
             <attribute default="${main.class}" name="name"/>
+            <attribute default="${debug.modulepath}" name="modulepath"/>
             <attribute default="${debug.classpath}" name="classpath"/>
             <attribute default="" name="stopclassname"/>
             <sequential>
                 <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
+                    <modulepath>
+                        <path path="@{modulepath}"/>
+                    </modulepath>
                     <classpath>
                         <path path="@{classpath}"/>
                     </classpath>
@@ -988,18 +1061,6 @@ is divided into following sections:
         </macrodef>
     </target>
     <target name="-init-debug-args">
-        <property name="version-output" value="java version &quot;${ant.java.version}"/>
-        <condition property="have-jdk-older-than-1.4">
-            <or>
-                <contains string="${version-output}" substring="java version &quot;1.0"/>
-                <contains string="${version-output}" substring="java version &quot;1.1"/>
-                <contains string="${version-output}" substring="java version &quot;1.2"/>
-                <contains string="${version-output}" substring="java version &quot;1.3"/>
-            </or>
-        </condition>
-        <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
-            <istrue value="${have-jdk-older-than-1.4}"/>
-        </condition>
         <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
             <os family="windows"/>
         </condition>
@@ -1009,21 +1070,79 @@ is divided into following sections:
     </target>
     <target depends="-init-debug-args" name="-init-macrodef-debug">
         <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${module.name}" name="modulename"/>
             <attribute default="${main.class}" name="classname"/>
+            <attribute default="${debug.modulepath}" name="modulepath"/>
             <attribute default="${debug.classpath}" name="classpath"/>
+            <element name="customizeDebuggee" optional="true"/>
+            <sequential>
+                <j2seproject1:java classname="@{classname}" classpath="@{classpath}" modulename="@{modulename}" modulepath="@{modulepath}">
+                    <customize>
+                        <jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/>
+                        <customizeDebuggee/>
+                    </customize>
+                </j2seproject1:java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-source-module-properties" if="named.module.internal" name="-init-macrodef-java-with-module">
+        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute default="${module.name}" name="modulename"/>
+            <attribute default="${main.class}" name="classname"/>
+            <attribute default="${run.modulepath}" name="modulepath"/>
+            <attribute default="${run.upgrademodulepath}" name="upgrademodulepath"/>
+            <attribute default="${run.classpath}" name="classpath"/>
+            <attribute default="jvm" name="jvm"/>
             <element name="customize" optional="true"/>
             <sequential>
-                <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
-                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
-                    <jvmarg line="${debug-args-line}"/>
-                    <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+                <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true" module="@{modulename}">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <modulepath>
+                        <pathelement path="@{modulepath}"/>
+                        <pathelement location="${module.build.classes.dir}"/>
+                    </modulepath>
+                    <upgrademodulepath>
+                        <path path="@{upgrademodulepath}"/>
+                    </upgrademodulepath>
                     <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
                     <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
                     <jvmarg line="${run.jvmargs}"/>
                     <jvmarg line="${run.jvmargs.ide}"/>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-source-module-properties" if="unnamed.module.internal" name="-init-macrodef-java-with-unnamed-module">
+        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute default="" name="modulename"/>
+            <attribute default="${main.class}" name="classname"/>
+            <attribute default="${run.modulepath}" name="modulepath"/>
+            <attribute default="${run.upgrademodulepath}" name="upgrademodulepath"/>
+            <attribute default="${run.classpath}" name="classpath"/>
+            <attribute default="jvm" name="jvm"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
                     <classpath>
                         <path path="@{classpath}"/>
                     </classpath>
+                    <modulepath>
+                        <path path="@{modulepath}"/>
+                    </modulepath>
+                    <upgrademodulepath>
+                        <path path="@{upgrademodulepath}"/>
+                    </upgrademodulepath>
+                    <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+                    <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                    <jvmarg line="${run.jvmargs.ide}"/>
                     <syspropertyset>
                         <propertyref prefix="run-sys-prop."/>
                         <mapper from="run-sys-prop.*" to="*" type="glob"/>
@@ -1033,9 +1152,11 @@ is divided into following sections:
             </sequential>
         </macrodef>
     </target>
-    <target name="-init-macrodef-java">
+    <target depends="-init-source-module-properties" name="-init-macrodef-java-without-module" unless="modules.supported.internal">
         <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute default="" name="modulename"/>
             <attribute default="${main.class}" name="classname"/>
+            <attribute default="" name="modulepath"/>
             <attribute default="${run.classpath}" name="classpath"/>
             <attribute default="jvm" name="jvm"/>
             <element name="customize" optional="true"/>
@@ -1058,6 +1179,7 @@ is divided into following sections:
             </sequential>
         </macrodef>
     </target>
+    <target depends="-init-macrodef-java-with-module, -init-macrodef-java-with-unnamed-module, -init-macrodef-java-without-module" name="-init-macrodef-java"/>
     <target name="-init-macrodef-copylibs">
         <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
             <attribute default="${manifest.file}" name="manifest"/>
@@ -1148,6 +1270,7 @@ is divided into following sections:
             <param name="call.target" value="jar"/>
             <param name="transfer.built-jar.properties" value="${built-jar.properties}"/>
             <param name="transfer.not.archive.disabled" value="true"/>
+            <param name="transfer.do.jlink" value="false"/>
         </antcall>
     </target>
     <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
@@ -1155,7 +1278,9 @@ is divided into following sections:
         <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
     </target>
     <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
-        <antcall target="clean"/>
+        <antcall target="clean">
+            <param name="no.dependencies" value="true"/>
+        </antcall>
     </target>
     <target depends="init,deps-jar" name="-pre-pre-compile">
         <mkdir dir="${build.classes.dir}"/>
@@ -1216,7 +1341,7 @@ is divided into following sections:
     <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
         <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
         <j2seproject3:force-recompile/>
-        <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.local-src.dir}:${src.webapp.dir}:${src.javafx.dir}:${src.console.dir}:${src.portrayal.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.sql.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile. [...]
+        <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}, module-info.java" sourcepath="${src.local-src.dir}:${src.webapp.dir}:${src.javafx.dir}:${src.console.dir}:${src.portrayal.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.sql.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}: [...]
     </target>
     <target name="-post-compile-single">
         <!-- Empty placeholder for easier customization. -->
@@ -1236,6 +1361,25 @@ is divided into following sections:
         <!-- Empty placeholder for easier customization. -->
         <!-- You can override this target in the ../build.xml file. -->
     </target>
+    <target depends="init,compile" name="-check-module-main-class">
+        <pathconvert property="main.class.file">
+            <string value="${main.class}"/>
+            <unpackagemapper from="*" to="*.class"/>
+        </pathconvert>
+        <condition property="do.module.main.class">
+            <and>
+                <isset property="main.class.available"/>
+                <available file="${build.classes.dir}/module-info.class"/>
+                <available file="${build.classes.dir}/${main.class.file}"/>
+                <isset property="libs.CopyLibs.classpath"/>
+                <available classname="org.netbeans.modules.java.j2seproject.moduletask.ModuleMainClass" classpath="${libs.CopyLibs.classpath}"/>
+            </and>
+        </condition>
+    </target>
+    <target depends="-check-module-main-class" if="do.module.main.class" name="-set-module-main-class">
+        <taskdef classname="org.netbeans.modules.java.j2seproject.moduletask.ModuleMainClass" classpath="${libs.CopyLibs.classpath}" name="modulemainclass"/>
+        <modulemainclass failonerror="false" mainclass="${main.class}" moduleinfo="${build.classes.dir}/module-info.class"/>
+    </target>
     <target depends="init" if="do.archive" name="-do-jar-create-manifest" unless="manifest.available">
         <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
         <touch file="${tmp.manifest.file}" verbose="false"/>
@@ -1272,11 +1416,37 @@ is divided into following sections:
         <j2seproject1:jar manifest="${tmp.manifest.file}"/>
         <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
         <property location="${dist.jar}" name="dist.jar.resolved"/>
+        <condition else="${dist.jar.resolved}" property="jar.usage.message.class.path.replacement" value="">
+            <isset property="named.module.internal"/>
+        </condition>
         <pathconvert property="run.classpath.with.dist.jar">
             <path path="${run.classpath}"/>
+            <map from="${build.classes.dir.resolved}" to="${jar.usage.message.class.path.replacement}"/>
+        </pathconvert>
+        <pathconvert property="run.modulepath.with.dist.jar">
+            <path location="${dist.jar.resolved}"/>
+            <path path="${run.modulepath}"/>
             <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
         </pathconvert>
-        <condition else="" property="jar.usage.message" value="To run this application from the command line without Ant, try:${line.separator}${platform.java} -cp ${run.classpath.with.dist.jar} ${main.class}">
+        <condition else="${run.modulepath}" property="jar.usage.message.run.modulepath.with.dist.jar" value="${run.modulepath.with.dist.jar}">
+            <isset property="named.module.internal"/>
+        </condition>
+        <condition else="" property="jar.usage.message.module.path" value=" -p ${jar.usage.message.run.modulepath.with.dist.jar}">
+            <and>
+                <isset property="modules.supported.internal"/>
+                <length length="0" string="${jar.usage.message.run.modulepath.with.dist.jar}" when="greater"/>
+            </and>
+        </condition>
+        <condition else="" property="jar.usage.message.class.path" value=" -cp ${run.classpath.with.dist.jar}">
+            <length length="0" string="${run.classpath.with.dist.jar}" when="greater"/>
+        </condition>
+        <condition else="/${main.class}" property="jar.usage.message.main.class.class.selector" value="">
+            <isset property="do.module.main.class"/>
+        </condition>
+        <condition else=" ${main.class}" property="jar.usage.message.main.class" value=" -m ${module.name}${jar.usage.message.main.class.class.selector}">
+            <isset property="named.module.internal"/>
+        </condition>
+        <condition else="" property="jar.usage.message" value="To run this application from the command line without Ant, try:${line.separator}${platform.java}${jar.usage.message.module.path}${jar.usage.message.class.path}${jar.usage.message.main.class}">
             <isset property="main.class.available"/>
         </condition>
         <condition else="debug" property="jar.usage.level" value="info">
@@ -1295,8 +1465,73 @@ is divided into following sections:
         <!-- Empty placeholder for easier customization. -->
         <!-- You can override this target in the ../build.xml file. -->
     </target>
-    <target depends="init,compile,-pre-jar,-do-jar-without-libraries,-do-jar-with-libraries,-post-jar" name="-do-jar"/>
-    <target depends="init,compile,-pre-jar,-do-jar,-post-jar" description="Build JAR." name="jar"/>
+    <target depends="init,compile,-pre-jar,-set-module-main-class,-do-jar-without-libraries,-do-jar-with-libraries,-post-jar" name="-do-jar"/>
+    <target depends="init,compile,-pre-jar,-do-jar,-post-jar,deploy" description="Build JAR." name="jar"/>
+    <!--
+                =================
+                DEPLOY SECTION
+                =================
+            -->
+    <target name="-pre-deploy">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init" name="-check-jlink">
+        <condition property="do.jlink.internal">
+            <and>
+                <istrue value="${do.jlink}"/>
+                <isset property="do.archive"/>
+                <isset property="named.module.internal"/>
+            </and>
+        </condition>
+    </target>
+    <target depends="init,-do-jar,-post-jar,-pre-deploy,-check-jlink" if="do.jlink.internal" name="-do-deploy">
+        <delete dir="${dist.jlink.dir}" failonerror="false" quiet="true"/>
+        <property name="jlink.launcher.name" value="${application.title}"/>
+        <condition else="${module.name}" property="jlink.add.modules" value="${module.name},${jlink.additionalmodules}">
+            <and>
+                <isset property="jlink.additionalmodules"/>
+                <length length="0" string="${jlink.additionalmodules}" when="greater"/>
+            </and>
+        </condition>
+        <condition property="jlink.do.strip.internal">
+            <and>
+                <isset property="jlink.strip"/>
+                <istrue value="${jlink.strip}"/>
+            </and>
+        </condition>
+        <condition property="jlink.do.additionalparam.internal">
+            <and>
+                <isset property="jlink.additionalparam"/>
+                <length length="0" string="${jlink.additionalparam}" when="greater"/>
+            </and>
+        </condition>
+        <condition property="jlink.do.launcher.internal">
+            <and>
+                <istrue value="${jlink.launcher}"/>
+                <isset property="main.class.available"/>
+            </and>
+        </condition>
+        <property name="platform.jlink" value="${jdk.home}/bin/jlink"/>
+        <property name="jlink.systemmodules.internal" value="${jdk.home}/jmods"/>
+        <exec executable="${platform.jlink}">
+            <arg value="--module-path"/>
+            <arg path="${jlink.systemmodules.internal}:${run.modulepath}:${dist.jar}"/>
+            <arg value="--add-modules"/>
+            <arg value="${jlink.add.modules}"/>
+            <arg if:set="jlink.do.strip.internal" value="--strip-debug"/>
+            <arg if:set="jlink.do.launcher.internal" value="--launcher"/>
+            <arg if:set="jlink.do.launcher.internal" value="${jlink.launcher.name}=${module.name}/${main.class}"/>
+            <arg if:set="jlink.do.additionalparam.internal" line="${jlink.additionalparam}"/>
+            <arg value="--output"/>
+            <arg value="${dist.jlink.output}"/>
+        </exec>
+    </target>
+    <target name="-post-deploy">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="-do-jar,-post-jar,-pre-deploy,-do-deploy,-post-deploy" name="deploy"/>
     <!--
                 =================
                 EXECUTION SECTION
@@ -1333,9 +1568,9 @@ is divided into following sections:
     </target>
     <target depends="init,compile" name="-debug-start-debuggee">
         <j2seproject3:debug>
-            <customize>
+            <customizeDebuggee>
                 <arg line="${application.args}"/>
-            </customize>
+            </customizeDebuggee>
         </j2seproject3:debug>
     </target>
     <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
@@ -1401,28 +1636,24 @@ is divided into following sections:
             </customize>
         </profile>
     </target>
-    <target depends="profile-init,compile-test-single" if="profiler.info.jvmargs.agent" name="-profile-test-single-pre72">
+    <target depends="-init-macrodef-junit,profile-init,compile-test-single" if="profiler.info.jvmargs.agent" name="-profile-test-single-pre72">
         <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
         <nbprofiledirect>
             <classpath>
                 <path path="${run.test.classpath}"/>
             </classpath>
         </nbprofiledirect>
-        <junit dir="${profiler.info.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" jvm="${profiler.info.jvm}" showoutput="true">
-            <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
-            <jvmarg value="${profiler.info.jvmargs.agent}"/>
-            <jvmarg line="${profiler.info.jvmargs}"/>
-            <test name="${profile.class}"/>
-            <classpath>
-                <path path="${run.test.classpath}"/>
-            </classpath>
-            <syspropertyset>
-                <propertyref prefix="test-sys-prop."/>
-                <mapper from="test-sys-prop.*" to="*" type="glob"/>
-            </syspropertyset>
-            <formatter type="brief" usefile="false"/>
-            <formatter type="xml"/>
-        </junit>
+        <j2seproject3:junit excludes="${excludes}" includes="${includes}" testincludes="${profile.class}" testmethods="">
+            <customize>
+                <jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/>
+                <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
+                <jvmarg value="${profiler.info.jvmargs.agent}"/>
+                <jvmarg line="${profiler.info.jvmargs}"/>
+                <classpath>
+                    <path path="${run.test.classpath}"/>
+                </classpath>
+            </customize>
+        </j2seproject3:junit>
     </target>
     <!--
                 end of pre NB72 profiling section
@@ -1478,6 +1709,12 @@ is divided into following sections:
         <condition else="" property="bug5101868workaround" value="*.java">
             <matches pattern="1\.[56](\..*)?" string="${java.version}"/>
         </condition>
+        <condition else="" property="javadoc.html5.cmd.line.arg" value="-html5">
+            <and>
+                <isset property="javadoc.html5"/>
+                <available file="${jdk.home}${file.separator}lib${file.separator}jrt-fs.jar"/>
+            </and>
+        </condition>
         <javadoc additionalparam="-J-Dfile.encoding=${file.encoding} ${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version} [...]
             <classpath>
                 <path path="${javac.classpath}"/>
@@ -1550,6 +1787,7 @@ is divided into following sections:
                 <exclude name="*.java"/>
             </fileset>
             <arg line="${javadoc.endorsed.classpath.cmd.line.arg}"/>
+            <arg line="${javadoc.html5.cmd.line.arg}"/>
         </javadoc>
         <copy todir="${dist.javadoc.dir}">
             <fileset dir="${src.local-src.dir}" excludes="${excludes}" includes="${includes}">
@@ -1636,11 +1874,63 @@ is divided into following sections:
         <!-- Empty placeholder for easier customization. -->
         <!-- You can override this target in the ../build.xml file. -->
     </target>
+    <target depends="-init-source-module-properties" if="named.module.internal" name="-init-test-javac-module-properties-with-module">
+        <j2seproject3:modulename property="test.module.name" sourcepath="${test.webapp.dir}:${test.javafx.dir}:${test.console.dir}:${test.portrayal.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.shapefile.dir}:${test.sql.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.dir}:${test.raster.dir}:${test.referencing.dir}:${test.ref-by-id.dir}:${test.metadata.dir}:${test.utility.dir}:${test.fra-profile.dir}:${test.gdal.dir}"/>
+        <condition else="${empty.dir}" property="javac.test.sourcepath" value="${test.webapp.dir}:${test.javafx.dir}:${test.console.dir}:${test.portrayal.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.shapefile.dir}:${test.sql.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.dir}:${test.raster.dir}:${test.referencing.dir}:${test.ref-by-id.dir}:${test.metadata.dir}:${test.utility.dir}:${test.fra-profile.dir}:${test.gdal.dir}">
+            <and>
+                <isset property="test.module.name"/>
+                <length length="0" string="${test.module.name}" when="greater"/>
+            </and>
+        </condition>
+        <condition else="--patch-module ${module.name}=${test.webapp.dir}:${test.javafx.dir}:${test.console.dir}:${test.portrayal.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.shapefile.dir}:${test.sql.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.dir}:${test.raster.dir}:${test.referencing.dir}:${test.ref-by-id.dir}:${test.metadata.dir}:${test.utility.dir}:${test.fra-profile.dir}:${test.gdal.dir} --add-reads ${module.name}=ALL-UNNAMED" property=" [...]
+            <and>
+                <isset property="test.module.name"/>
+                <length length="0" string="${test.module.name}" when="greater"/>
+            </and>
+        </condition>
+    </target>
+    <target depends="-init-source-module-properties" if="named.module.internal" name="-init-test-run-module-properties">
+        <condition else="${module.name}" property="run.test.addexport.source.module.internal" value="${test.module.name}">
+            <and>
+                <isset property="test.module.name"/>
+                <length length="0" string="${test.module.name}" when="greater"/>
+            </and>
+        </condition>
+        <fileset dir="${build.test.classes.dir}" id="run.test.packages.internal" includes="**/*.class"/>
+        <property location="${build.test.classes.dir}" name="build.test.classes.dir.abs.internal"/>
+        <pathconvert pathsep=" " property="run.test.addexports.internal" refid="run.test.packages.internal">
+            <chainedmapper>
+                <regexpmapper from="^(.*)\Q${file.separator}\E.*\.class$$" to="\1"/>
+                <filtermapper>
+                    <uniqfilter/>
+                    <replacestring from="${build.test.classes.dir.abs.internal}" to=""/>
+                </filtermapper>
+                <cutdirsmapper dirs="1"/>
+                <packagemapper from="*" to="--add-exports ${run.test.addexport.source.module.internal}/*=ALL-UNNAMED"/>
+            </chainedmapper>
+        </pathconvert>
+        <condition else="--patch-module ${module.name}=${build.test.classes.dir} --add-modules ${module.name} --add-reads ${module.name}=ALL-UNNAMED ${run.test.addexports.internal}" property="run.test.jvmargs" value="--add-modules ${test.module.name} --add-reads ${test.module.name}=ALL-UNNAMED ${run.test.addexports.internal}">
+            <and>
+                <isset property="test.module.name"/>
+                <length length="0" string="${test.module.name}" when="greater"/>
+            </and>
+        </condition>
+    </target>
+    <target depends="-init-source-module-properties" name="-init-test-module-properties-without-module" unless="named.module.internal">
+        <property name="javac.test.sourcepath" value="${empty.dir}"/>
+        <property name="javac.test.compilerargs" value=""/>
+        <property name="run.test.jvmargs" value=""/>
+    </target>
+    <target depends="-init-test-javac-module-properties-with-module,-init-test-module-properties-without-module" name="-init-test-module-properties"/>
     <target if="do.depend.true" name="-compile-test-depend">
         <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.webapp.dir}:${test.javafx.dir}:${test.console.dir}:${test.portrayal.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.shapefile.dir}:${test.sql.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.dir}:${test.raster.dir}:${test.referencing.dir}:${test.ref-by-id.dir}:${test.metadata.dir}:${test.utility.dir}:${test.fra-profile.dir}:${test.gdal.dir}"/>
     </target>
-    <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
-        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" processorpath="${javac.test.processorpath}" srcdir="${test.webapp.dir}:${test.javafx.dir}:${test.console.dir}:${test.portrayal.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.shapefile.dir}:${test.sql.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.dir}:${test.raster.dir}:${test.referencing.dir [...]
+    <target depends="init,deps-jar,compile,-init-test-module-properties,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
+        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" modulepath="${javac.test.modulepath}" processorpath="${javac.test.processorpath}" sourcepath="${javac.test.sourcepath}" srcdir="${test.webapp.dir}:${test.javafx.dir}:${test.console.dir}:${test.portrayal.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.shapefile.dir}:${test.sql.dir}:${test.xmlstore.dir}:${tes [...]
+            <customize>
+                <compilerarg line="${javac.test.compilerargs}"/>
+            </customize>
+        </j2seproject3:javac>
         <copy todir="${build.test.classes.dir}">
             <fileset dir="${test.webapp.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.javafx.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
@@ -1672,10 +1962,14 @@ is divided into following sections:
         <!-- Empty placeholder for easier customization. -->
         <!-- You can override this target in the ../build.xml file. -->
     </target>
-    <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
+    <target depends="init,deps-jar,compile,-init-test-module-properties,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
         <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
         <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
-        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" processorpath="${javac.test.processorpath}" sourcepath="${test.webapp.dir}:${test.javafx.dir}:${test.console.dir}:${test.portrayal.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.shapefile.dir}:${test.sql.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.d [...]
+        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}, module-info.java" modulepath="${javac.test.modulepath}" processorpath="${javac.test.processorpath}" sourcepath="${test.webapp.dir}:${test.javafx.dir}:${test.console.dir}:${test.portrayal.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.shapefile.dir}:${test.sql.dir}:$ [...]
+            <customize>
+                <compilerarg line="${javac.test.compilerargs}"/>
+            </customize>
+        </j2seproject3:javac>
         <copy todir="${build.test.classes.dir}">
             <fileset dir="${test.webapp.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.javafx.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
@@ -1711,7 +2005,7 @@ is divided into following sections:
     <target depends="init" if="have.tests" name="-pre-test-run">
         <mkdir dir="${build.test.results.dir}"/>
     </target>
-    <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
+    <target depends="init,compile-test,-init-test-run-module-properties,-pre-test-run" if="have.tests" name="-do-test-run">
         <j2seproject3:test includes="${includes}" testincludes="**/*Test.java"/>
     </target>
     <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
@@ -1723,14 +2017,14 @@ is divided into following sections:
     <target depends="init" if="have.tests" name="-pre-test-run-single">
         <mkdir dir="${build.test.results.dir}"/>
     </target>
-    <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
+    <target depends="init,compile-test-single,-init-test-run-module-properties,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
         <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
         <j2seproject3:test excludes="" includes="${test.includes}" testincludes="${test.includes}"/>
     </target>
     <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
         <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
     </target>
-    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
+    <target depends="init,compile-test-single,-init-test-run-module-properties,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
     <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single-method">
         <fail unless="test.class">Must select some files in the IDE or set test.class</fail>
         <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
@@ -1739,7 +2033,7 @@ is divided into following sections:
     <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method" if="have.tests" name="-post-test-run-single-method">
         <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
     </target>
-    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method,-post-test-run-single-method" description="Run single unit test." name="test-single-method"/>
+    <target depends="init,compile-test-single,-init-test-run-module-properties,-pre-test-run-single,-do-test-run-single-method,-post-test-run-single-method" description="Run single unit test." name="test-single-method"/>
     <!--
                 =======================
                 TEST DEBUGGING SECTION
@@ -1757,8 +2051,8 @@ is divided into following sections:
     <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
         <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
     </target>
-    <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
-    <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-test-method"/>
+    <target depends="init,compile-test-single,-init-test-run-module-properties,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
+    <target depends="init,compile-test-single,-init-test-run-module-properties,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-test-method"/>
     <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
         <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
     </target>
@@ -1784,9 +2078,9 @@ is divided into following sections:
     <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
         <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
         <j2seproject3:debug classname="sun.applet.AppletViewer">
-            <customize>
+            <customizeDebuggee>
                 <arg value="${applet.url}"/>
-            </customize>
+            </customizeDebuggee>
         </j2seproject3:debug>
     </target>
     <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
@@ -1817,10 +2111,12 @@ is divided into following sections:
             <param name="call.target" value="clean"/>
             <param name="transfer.built-clean.properties" value="${built-clean.properties}"/>
             <param name="transfer.not.archive.disabled" value="true"/>
+            <param name="transfer.do.jlink" value="false"/>
         </antcall>
     </target>
     <target depends="init" name="-do-clean">
         <delete dir="${build.dir}"/>
+        <delete dir="${dist.jlink.output}"/>
         <delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/>
     </target>
     <target name="-post-clean">
diff --git a/ide-project/NetBeans/nbproject/genfiles.properties b/ide-project/NetBeans/nbproject/genfiles.properties
index ec32b8a..af88b83 100644
--- a/ide-project/NetBeans/nbproject/genfiles.properties
+++ b/ide-project/NetBeans/nbproject/genfiles.properties
@@ -4,5 +4,5 @@ build.xml.data.CRC32=58e6b21c
 build.xml.script.CRC32=462eaba0
 build.xml.stylesheet.CRC32=28e38971@1.53.1.46
 nbproject/build-impl.xml.data.CRC32=40d83d59
-nbproject/build-impl.xml.script.CRC32=b7ab89c5
-nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48
+nbproject/build-impl.xml.script.CRC32=a7689f96
+nbproject/build-impl.xml.stylesheet.CRC32=3a2fa800@1.88.0.48
diff --git a/ide-project/NetBeans/nbproject/project.properties b/ide-project/NetBeans/nbproject/project.properties
index e3f775c..953d168 100644
--- a/ide-project/NetBeans/nbproject/project.properties
+++ b/ide-project/NetBeans/nbproject/project.properties
@@ -35,8 +35,8 @@ project.license      = apache20
 project.licensePath  = ../LicenseHeader.txt
 no.dependencies      = true
 source.encoding      = UTF-8
-javac.source         = 1.8
-javac.target         = 1.8
+javac.source         = 9
+javac.target         = 9
 platform.active      = default_platform
 junit.forkmode       = once
 run.jvmargs          = -ea -Dorg.apache.sis.test.verbose=true -Dorg.apache.sis.test.extensive=true
@@ -142,6 +142,7 @@ javac.classpath=\
     ${maven.repository}/org/osgi/org.osgi.core/${osgi.version}/org.osgi.core-${osgi.version}.jar:\
     ${maven.repository}/org/postgresql/postgresql/${postgresql.version}/postgresql-${postgresql.version}.jar:\
     ${maven.repository}/com/googlecode/jaxb-namespaceprefixmapper-interfaces/JAXBNamespacePrefixMapper/${jaxb-ns-mapper}/JAXBNamespacePrefixMapper-${jaxb-ns-mapper}.jar
+javac.modulepath=
 javac.processorpath=\
     ${javac.classpath}
 javac.test.classpath=\
@@ -156,11 +157,17 @@ javac.test.classpath=\
     ${build.classes.dir}
 javac.test.processorpath=\
     ${javac.test.classpath}
+javac.processormodulepath=\
+    ${javac.modulepath}
+javac.test.modulepath=\
+    ${javac.modulepath}
 run.classpath=\
     ${javac.classpath}:\
     ${build.classes.dir}:\
     ${maven.repository}/org/apache/derby/derby/${derby.version}/derby-${derby.version}.jar:\
     ${maven.repository}/org/webjars/material-design-icons/${icons.version}/material-design-icons-${icons.version}.jar
+run.modulepath=\
+    ${javac.modulepath}
 run.test.classpath=\
     ${javac.test.classpath}:\
     ${build.test.classes.dir}:\
@@ -173,10 +180,16 @@ run.test.classpath=\
     ${maven.repository}/org/apache/httpcomponents/httpclient/${httpclient.version}/httpclient-${httpclient.version}.jar:\
     ${maven.repository}/org/slf4j/slf4j-api/${slf4j.version}/slf4j-api-${slf4j.version}.jar:\
     ${maven.repository}/org/slf4j/slf4j-jdk14/${slf4j.version}/slf4j-jdk14-${slf4j.version}.jar
+run.test.modulepath=\
+    ${javac.test.modulepath}
 debug.classpath=\
     ${run.classpath}
+debug.modulepath=\
+    ${run.modulepath}
 debug.test.classpath=\
     ${run.test.classpath}
+debug.test.modulepath=\
+    ${run.test.modulepath}
 
 #
 # Module paths (can be used as a replacement for classpaths on JDK 9).
@@ -197,7 +210,8 @@ debug.test.modulepath=\
 #
 # Build configuration and destination directories.
 #
-javac.compilerargs                       = -Xdoclint:syntax,html,reference,missing/protected,accessibility/protected
+javac.compilerargs                       = --add-modules java.xml.bind,java.xml.ws.annotation,javafx.graphics \
+                                           -Xdoclint:syntax,html,reference,missing/protected,accessibility/protected
 javac.deprecation                        = true
 javac.external.vm                        = false
 javadoc.html5                            = true
@@ -244,6 +258,8 @@ dist.dir                                 = dist
 dist.jar                                 = ${dist.dir}/SIS.jar
 dist.javadoc.dir                         = ${dist.dir}/javadoc
 mkdist.disabled                          = true
+jlink.launcher                           = false
+jlink.launcher.name                      = ApacheSIS
 
 #
 # Editor
diff --git a/pom.xml b/pom.xml
index e8558c9..e50191e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -510,8 +510,8 @@
     <website.locale>en</website.locale>
 
     <!-- Following properties are branch-specific -->
-    <maven.compile.source>1.8</maven.compile.source>
-    <maven.compile.target>1.8</maven.compile.target>
+    <maven.compile.source>9</maven.compile.source>
+    <maven.compile.target>9</maven.compile.target>
     <sis.plugin.version>${project.version}</sis.plugin.version>
     <sis.non-free.version>0.8</sis.non-free.version>
     <geoapi.version>4.0-SNAPSHOT</geoapi.version>
@@ -527,35 +527,6 @@
       </properties>
     </profile>
 
-    <!-- Cross-version compilation (to be removed with JDK9). -->
-    <profile>
-      <id>bootclasspath</id>
-      <activation>
-        <property>
-          <name>bootclasspath</name>
-        </property>
-      </activation>
-      <build>
-        <plugins>
-          <plugin>
-            <artifactId>maven-compiler-plugin</artifactId>
-            <configuration>
-              <compilerArgs>
-                <arg>-bootclasspath</arg>
-                <arg>${bootclasspath}</arg>
-              </compilerArgs>
-            </configuration>
-          </plugin>
-          <plugin>
-            <artifactId>maven-javadoc-plugin</artifactId>
-            <configuration>
-              <bootclasspath>${bootclasspath}</bootclasspath>
-            </configuration>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-
     <!-- ===================================================================
            If the user has not set the SIS_DATA environment variable, set a
            default value where we can create a minimalist database.
@@ -603,6 +574,7 @@
           <compilerArgs>
             <arg>-Xlint:all</arg>
             <arg>-Xdoclint:syntax,html,missing/protected,accessibility/protected</arg>
+            <arg>--add-modules</arg> <arg>java.xml.bind,java.xml.ws.annotation,javafx.graphics</arg>
             <arg>-h</arg> <arg>${project.build.sourceDirectory}/../c</arg>
           </compilerArgs>
         </configuration>


Mime
View raw message