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; |
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 } |