diff --git a/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformDefaultJavadocImpl.java b/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformDefaultJavadocImpl.java index 29049601eb51..15d4d65e9463 100644 --- a/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformDefaultJavadocImpl.java +++ b/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformDefaultJavadocImpl.java @@ -24,7 +24,7 @@ import java.net.URL; import java.time.LocalDate; import java.time.Month; -import java.time.Period; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -34,6 +34,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Pattern; +import javax.lang.model.SourceVersion; import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.java.platform.JavaPlatform; import org.netbeans.modules.java.j2seplatform.spi.J2SEPlatformDefaultJavadoc; @@ -42,70 +43,30 @@ import org.openide.util.lookup.ServiceProvider; /** - * Default Javadoc for J2SE. + * Default Javadoc for Java. * @author Tomas Zezula */ -@ServiceProvider(service =J2SEPlatformDefaultJavadoc.class, position = 100, path = "org-netbeans-api-java/platform/j2seplatform/defaultJavadocProviders") +@ServiceProvider(service = J2SEPlatformDefaultJavadoc.class, position = 100, path = "org-netbeans-api-java/platform/j2seplatform/defaultJavadocProviders") public final class J2SEPlatformDefaultJavadocImpl implements J2SEPlatformDefaultJavadoc { private static final Logger LOG = Logger.getLogger(J2SEPlatformDefaultJavadocImpl.class.getName()); - private static final Map OFFICIAL_JAVADOC = new HashMap<>(); - static { - OFFICIAL_JAVADOC.put("1.0", null); // NOI18N - OFFICIAL_JAVADOC.put("1.1", null); // NOI18N - OFFICIAL_JAVADOC.put("1.2", null); // NOI18N - OFFICIAL_JAVADOC.put("1.3", null); // NOI18N - OFFICIAL_JAVADOC.put("1.4", null); // NOI18N - OFFICIAL_JAVADOC.put("1.5", "https://docs.oracle.com/javase/1.5.0/docs/api/"); // NOI18N - OFFICIAL_JAVADOC.put("1.6", "https://docs.oracle.com/javase/6/docs/api/"); // NOI18N - OFFICIAL_JAVADOC.put("1.7", "https://docs.oracle.com/javase/7/docs/api/"); // NOI18N - OFFICIAL_JAVADOC.put("1.8", "https://docs.oracle.com/javase/8/docs/api/"); // NOI18N - - // timezone shouldn't matter since the accuracy is worse than a day - LocalDate jdk9 = LocalDate.of(2017, Month.SEPTEMBER, 21); // start of 6 month schedule - LocalDate now = LocalDate.now(); - - if (now.isAfter(jdk9)) { // time traveler -> only java 8 doc for you - int jdk = 9; - LocalDate jdkEarly = jdk9; - for (LocalDate t = jdk9 ; t.isBefore(now); t = t.plusMonths(6)) { - OFFICIAL_JAVADOC.put(String.valueOf(jdk), "https://docs.oracle.com/en/java/javase/" + jdk + "/docs/api/"); // NOI18N - jdkEarly = t; - jdk++; - } - - jdkEarly = jdkEarly.minusDays(12); - - if (now.isAfter(jdkEarly)) { - OFFICIAL_JAVADOC.put(String.valueOf(jdk), "https://download.java.net/java/early_access/jdk" + jdk + "/docs/api/"); // NOI18N Early access - jdkEarly = jdkEarly.plusMonths(3); - jdk++; - } - // there is a 2nd jdk early release after 3 months - if (now.isAfter(jdkEarly)) { - OFFICIAL_JAVADOC.put(String.valueOf(jdk), "https://download.java.net/java/early_access/jdk" + jdk + "/docs/api/"); // NOI18N Early access - } - } - } @Override public Collection getDefaultJavadoc(@NonNull final JavaPlatform platform) { + // local final List result = new ArrayList<>(); final JavadocFilter filter = new JavadocFilter(); for (FileObject folder : platform.getInstallFolders()) { for (FileObject file : folder.getChildren()) { - final Collection roots = filter.accept(file); - result.addAll(roots); + result.addAll(filter.accept(file)); } } if (!result.isEmpty()) { return Collections.unmodifiableList(result); } + // remote String version = platform.getSpecification().getVersion().toString(); - if (!OFFICIAL_JAVADOC.containsKey(version)) { - LOG.log(Level.WARNING, "unrecognized Java spec version: {0}", version); - } - String location = OFFICIAL_JAVADOC.get(version); + String location = computeJavaDocURL(version); if (location != null) { try { return Collections.singletonList(new URI(location)); @@ -116,6 +77,43 @@ public Collection getDefaultJavadoc(@NonNull final JavaPlatform platform) { return Collections.emptyList(); } + private static String computeJavaDocURL(String version) { + switch (version) { + case "1.0": // NOI18N + case "1.1": // NOI18N + case "1.2": // NOI18N + case "1.3": // NOI18N + case "1.4": return null; // NOI18N + case "1.5": return "https://docs.oracle.com/javase/1.5.0/docs/api/"; // NOI18N + case "1.6": return "https://docs.oracle.com/javase/6/docs/api/"; // NOI18N + case "1.7": return "https://docs.oracle.com/javase/7/docs/api/"; // NOI18N + case "1.8": return "https://docs.oracle.com/javase/8/docs/api/"; // NOI18N + } + try { + int feature = Integer.parseInt(version); + if (feature >= 9) { + int latestGA = computeLatestGAVersion(); + if (feature <= latestGA) { + return "https://docs.oracle.com/en/java/javase/" + feature + "/docs/api/"; // NOI18N + } else if (feature <= latestGA + 3) { + return "https://download.java.net/java/early_access/jdk" + feature + "/docs/api/"; // NOI18N + } + } + } catch (IllegalArgumentException ignore) {} + LOG.log(Level.WARNING, "unrecognized Java spec version: {0}", version); // NOI18N + return null; + } + + /** + * Computes the feature version of the latest generally available JDK release. + */ + private static int computeLatestGAVersion() { + // timezone shouldn't matter since the accuracy is worse than a day + LocalDate jdk9 = LocalDate.of(2017, Month.SEPTEMBER, 21); // start of 6 month schedule + int latest = 9 + (int) (ChronoUnit.MONTHS.between(jdk9, LocalDate.now()) / 6); + return Math.max(latest, SourceVersion.latest().ordinal()); // in case system time is wrong, use nb-javac version as lower bound + } + private static final class JavadocFilter { private static final Pattern DOCS_FILE_PATTERN = Pattern.compile(".*docs.*\\.(zip|jar)",Pattern.CASE_INSENSITIVE); //NOI18N private static final Pattern JAVAFX_FILE_PATTERN = Pattern.compile(".*j(ava)?fx.*", Pattern.CASE_INSENSITIVE); //NOI18N