src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java
changeset 52687 526f5cf13972
parent 52644 43efb4ca6d6c
child 53310 8ce4083fc831
equal deleted inserted replaced
52686:00c47178ea6c 52687:526f5cf13972
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package jdk.javadoc.internal.doclets.toolkit.util;
    26 package jdk.javadoc.internal.doclets.toolkit.util;
    27 
    27 
    28 import java.io.*;
    28 import java.io.BufferedReader;
    29 import java.net.*;
    29 import java.io.IOException;
       
    30 import java.io.InputStream;
       
    31 import java.io.InputStreamReader;
       
    32 import java.net.HttpURLConnection;
       
    33 import java.net.MalformedURLException;
       
    34 import java.net.URISyntaxException;
       
    35 import java.net.URL;
       
    36 import java.net.URLConnection;
    30 import java.util.HashMap;
    37 import java.util.HashMap;
    31 import java.util.Map;
    38 import java.util.Map;
    32 import java.util.TreeMap;
    39 import java.util.TreeMap;
    33 
    40 
    34 import javax.lang.model.element.Element;
    41 import javax.lang.model.element.Element;
    35 import javax.lang.model.element.ModuleElement;
    42 import javax.lang.model.element.ModuleElement;
    36 import javax.lang.model.element.PackageElement;
    43 import javax.lang.model.element.PackageElement;
    37 import javax.tools.Diagnostic;
    44 import javax.tools.Diagnostic;
       
    45 import javax.tools.Diagnostic.Kind;
    38 import javax.tools.DocumentationTool;
    46 import javax.tools.DocumentationTool;
    39 
    47 
    40 import jdk.javadoc.doclet.Reporter;
    48 import jdk.javadoc.doclet.Reporter;
    41 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
    49 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
    42 import jdk.javadoc.internal.doclets.toolkit.Resources;
    50 import jdk.javadoc.internal.doclets.toolkit.Resources;
    83      * Stores the info for one external doc set
    91      * Stores the info for one external doc set
    84      */
    92      */
    85     private class Item {
    93     private class Item {
    86 
    94 
    87         /**
    95         /**
    88          * Element name, found in the "element-list" file in the {@link path}.
    96          * Element name, found in the "element-list" file in the {@link #path}.
    89          */
    97          */
    90         final String elementName;
    98         final String elementName;
    91 
    99 
    92         /**
   100         /**
    93          * The URL or the directory path at which the element documentation will be
   101          * The URL or the directory path at which the element documentation will be
   155      * @param elementName name of the element.
   163      * @param elementName name of the element.
   156      * @return true if the element is a module
   164      * @return true if the element is a module
   157      */
   165      */
   158     public boolean isModule(String elementName) {
   166     public boolean isModule(String elementName) {
   159         Item elem = moduleItems.get(elementName);
   167         Item elem = moduleItems.get(elementName);
   160         return (elem == null) ? false : true;
   168         return elem != null;
   161     }
   169     }
   162 
   170 
   163     /**
   171     /**
   164      * Convert a link to be an external link if appropriate.
   172      * Convert a link to be an external link if appropriate.
   165      *
   173      *
   243             reporter.print(Diagnostic.Kind.ERROR, f.getMessage());
   251             reporter.print(Diagnostic.Kind.ERROR, f.getMessage());
   244             return false;
   252             return false;
   245         }
   253         }
   246     }
   254     }
   247 
   255 
   248     private URL toURL(String url) throws Fault {
       
   249         try {
       
   250             return new URL(url);
       
   251         } catch (MalformedURLException e) {
       
   252             throw new Fault(resources.getText("doclet.MalformedURL", url), e);
       
   253         }
       
   254     }
       
   255 
       
   256     private class Fault extends Exception {
   256     private class Fault extends Exception {
   257         private static final long serialVersionUID = 0;
   257         private static final long serialVersionUID = 0;
   258 
   258 
   259         Fault(String msg, Exception cause) {
   259         Fault(String msg, Exception cause) {
   260             super(msg, cause);
   260             super(msg, cause);
   294      * @param elemlisturlpath URL or the path to the "element-list" file.
   294      * @param elemlisturlpath URL or the path to the "element-list" file.
   295      */
   295      */
   296     private void readElementListFromURL(String urlpath, URL elemlisturlpath) throws Fault {
   296     private void readElementListFromURL(String urlpath, URL elemlisturlpath) throws Fault {
   297         try {
   297         try {
   298             URL link = elemlisturlpath.toURI().resolve(DocPaths.ELEMENT_LIST.getPath()).toURL();
   298             URL link = elemlisturlpath.toURI().resolve(DocPaths.ELEMENT_LIST.getPath()).toURL();
   299             readElementList(link.openStream(), urlpath, false);
   299             try (InputStream in = open(link)) {
       
   300                 readElementList(in, urlpath, false);
       
   301             }
   300         } catch (URISyntaxException | MalformedURLException exc) {
   302         } catch (URISyntaxException | MalformedURLException exc) {
   301             throw new Fault(resources.getText("doclet.MalformedURL", elemlisturlpath.toString()), exc);
   303             throw new Fault(resources.getText("doclet.MalformedURL", elemlisturlpath.toString()), exc);
   302         } catch (IOException exc) {
   304         } catch (IOException exc) {
   303             readAlternateURL(urlpath, elemlisturlpath);
   305             readAlternateURL(urlpath, elemlisturlpath);
   304         }
   306         }
   311      * @param elemlisturlpath URL or the path to the "package-list" file.
   313      * @param elemlisturlpath URL or the path to the "package-list" file.
   312      */
   314      */
   313     private void readAlternateURL(String urlpath, URL elemlisturlpath) throws Fault {
   315     private void readAlternateURL(String urlpath, URL elemlisturlpath) throws Fault {
   314         try {
   316         try {
   315             URL link = elemlisturlpath.toURI().resolve(DocPaths.PACKAGE_LIST.getPath()).toURL();
   317             URL link = elemlisturlpath.toURI().resolve(DocPaths.PACKAGE_LIST.getPath()).toURL();
   316             readElementList(link.openStream(), urlpath, false);
   318             try (InputStream in = open(link)) {
       
   319                 readElementList(in, urlpath, false);
       
   320             }
   317         } catch (URISyntaxException | MalformedURLException exc) {
   321         } catch (URISyntaxException | MalformedURLException exc) {
   318             throw new Fault(resources.getText("doclet.MalformedURL", elemlisturlpath.toString()), exc);
   322             throw new Fault(resources.getText("doclet.MalformedURL", elemlisturlpath.toString()), exc);
   319         } catch (IOException exc) {
   323         } catch (IOException exc) {
   320             throw new Fault(resources.getText("doclet.URL_error", elemlisturlpath.toString()), exc);
   324             throw new Fault(resources.getText("doclet.URL_error", elemlisturlpath.toString()), exc);
   321         }
   325         }
   375      * @throws IOException if there is a problem reading or closing the stream
   379      * @throws IOException if there is a problem reading or closing the stream
   376      */
   380      */
   377     private void readElementList(InputStream input, String path, boolean relative)
   381     private void readElementList(InputStream input, String path, boolean relative)
   378                          throws Fault, IOException {
   382                          throws Fault, IOException {
   379         try (BufferedReader in = new BufferedReader(new InputStreamReader(input))) {
   383         try (BufferedReader in = new BufferedReader(new InputStreamReader(input))) {
   380             String elemname = null;
   384             String elemname;
       
   385             DocPath elempath;
   381             String moduleName = null;
   386             String moduleName = null;
   382             DocPath elempath = null;
       
   383             DocPath basePath  = DocPath.create(path);
   387             DocPath basePath  = DocPath.create(path);
   384             while ((elemname = in.readLine()) != null) {
   388             while ((elemname = in.readLine()) != null) {
   385                 if (elemname.length() > 0) {
   389                 if (elemname.length() > 0) {
   386                     elempath = basePath;
   390                     elempath = basePath;
   387                     if (elemname.startsWith(DocletConstants.MODULE_PREFIX)) {
   391                     if (elemname.startsWith(DocletConstants.MODULE_PREFIX)) {
   404                 }
   408                 }
   405             }
   409             }
   406         }
   410         }
   407     }
   411     }
   408 
   412 
       
   413     private void checkLinkCompatibility(String packageName, String moduleName, String path) throws Fault {
       
   414         PackageElement pe = utils.elementUtils.getPackageElement(packageName);
       
   415         if (pe != null) {
       
   416             ModuleElement me = (ModuleElement)pe.getEnclosingElement();
       
   417             if (me == null || me.isUnnamed()) {
       
   418                 if (moduleName != null) {
       
   419                     throw new Fault(resources.getText("doclet.linkMismatch_PackagedLinkedtoModule",
       
   420                             path), null);
       
   421                 }
       
   422             } else if (moduleName == null) {
       
   423                 throw new Fault(resources.getText("doclet.linkMismatch_ModuleLinkedtoPackage",
       
   424                         path), null);
       
   425             }
       
   426         }
       
   427     }
       
   428 
   409     public boolean isUrl (String urlCandidate) {
   429     public boolean isUrl (String urlCandidate) {
   410         try {
   430         try {
   411             URL ignore = new URL(urlCandidate);
   431             new URL(urlCandidate);
   412             //No exception was thrown, so this must really be a URL.
   432             //No exception was thrown, so this must really be a URL.
   413             return true;
   433             return true;
   414         } catch (MalformedURLException e) {
   434         } catch (MalformedURLException e) {
   415             //Since exception is thrown, this must be a directory path.
   435             //Since exception is thrown, this must be a directory path.
   416             return false;
   436             return false;
   417         }
   437         }
   418     }
   438     }
   419 
   439 
   420     private void checkLinkCompatibility(String packageName, String moduleName, String path) throws Fault {
   440     private URL toURL(String url) throws Fault {
   421         PackageElement pe = configuration.utils.elementUtils.getPackageElement(packageName);
   441         try {
   422         if (pe != null) {
   442             return new URL(url);
   423             ModuleElement me = (ModuleElement)pe.getEnclosingElement();
   443         } catch (MalformedURLException e) {
   424             if (me == null || me.isUnnamed()) {
   444             throw new Fault(resources.getText("doclet.MalformedURL", url), e);
   425                 if (moduleName != null)
   445         }
   426                     throw new Fault(resources.getText("doclet.linkMismatch_PackagedLinkedtoModule",
   446     }
   427                             path), null);
   447 
   428             } else if (moduleName == null)
   448     /**
   429                 throw new Fault(resources.getText("doclet.linkMismatch_ModuleLinkedtoPackage",
   449      * Open a stream to a URL, following a limited number of redirects
   430                         path), null);
   450      * if necessary.
   431         }
   451      *
       
   452      * @param url the URL
       
   453      * @return the stream
       
   454      * @throws IOException if an error occurred accessing the URL
       
   455      */
       
   456     private InputStream open(URL url) throws IOException {
       
   457         URLConnection conn = url.openConnection();
       
   458 
       
   459         boolean redir;
       
   460         int redirects = 0;
       
   461         InputStream in;
       
   462 
       
   463         do {
       
   464             // Open the input stream before getting headers,
       
   465             // because getHeaderField() et al swallow IOExceptions.
       
   466             in = conn.getInputStream();
       
   467             redir = false;
       
   468 
       
   469             if (conn instanceof HttpURLConnection) {
       
   470                 HttpURLConnection http = (HttpURLConnection)conn;
       
   471                 int stat = http.getResponseCode();
       
   472                 // See:
       
   473                 // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
       
   474                 // https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection
       
   475                 switch (stat) {
       
   476                     case 300: // Multiple Choices
       
   477                     case 301: // Moved Permanently
       
   478                     case 302: // Found (previously Moved Temporarily)
       
   479                     case 303: // See Other
       
   480                     case 307: // Temporary Redirect
       
   481                     case 308: // Permanent Redirect
       
   482                         URL base = http.getURL();
       
   483                         String loc = http.getHeaderField("Location");
       
   484                         URL target = null;
       
   485                         if (loc != null) {
       
   486                             target = new URL(base, loc);
       
   487                         }
       
   488                         http.disconnect();
       
   489                         if (target == null || redirects >= 5) {
       
   490                             throw new IOException("illegal URL redirect");
       
   491                         }
       
   492                         redir = true;
       
   493                         conn = target.openConnection();
       
   494                         redirects++;
       
   495                 }
       
   496             }
       
   497         } while (redir);
       
   498 
       
   499         if (!url.equals(conn.getURL())) {
       
   500             configuration.getReporter().print(Kind.WARNING,
       
   501                     resources.getText("doclet.urlRedirected", url, conn.getURL()));
       
   502         }
       
   503 
       
   504         return in;
   432     }
   505     }
   433 }
   506 }