[doc] Fix more external links

This commit is contained in:
Andreas Dangel 2024-03-14 16:53:48 +01:00
parent 9f862f9ac9
commit 274497bbf4
No known key found for this signature in database
GPG Key ID: 93450DF2DF9A3FA3
12 changed files with 85 additions and 57 deletions

View File

@ -16,6 +16,6 @@ There are numerous ways of getting help:
* You can also ask questions on [github discussions](https://github.com/pmd/pmd/discussions).
* Or you can join the [Mailing List](https://lists.sourceforge.net/lists/listinfo/pmd-devel) or browse
through the archives ([archive1](http://java-pmd.30631.n5.nabble.com/), [archive2](http://web.archive.org/web/20160715035623/http://blog.gmane.org:80/gmane.comp.java.audit.pmd.devel)).
through the [mailing list archive](https://sourceforge.net/p/pmd/mailman/pmd-devel/).
* Of course, you can also directly jump to our [source code on github](https://github.com/pmd/pmd).

View File

@ -2,13 +2,12 @@
title: Developer Resources
tags: [devdocs]
permalink: pmd_devdocs_development.html
last_updated: August 2017
last_updated: March 2024
---
The next version of PMD will be developed in parallel with this release. We will release additional bugfix versions as needed.
## Source Code
The complete source code can be found on github:
The complete source code can be found on Github:
* [github.com/pmd/pmd](https://github.com/pmd/pmd) - main PMD repository. Includes all the code to support all languages, including this documentation.
* [github.com/pmd/pmd.github.io](https://github.com/pmd/pmd.github.io) - Contains the landing page [https://pmd.github.io](https://pmd.github.io)
@ -18,7 +17,7 @@ The complete source code can be found on github:
## Continuous Integration
We use [Travis CI](https://travis-ci.com/pmd) as our ci service. The main repo and the eclipse plugin are built for
We use [GitHub Actions](https://github.com/pmd/pmd/actions) as our ci service. The main repo and the eclipse plugin are built for
every push. Each pull request is built as well.
The maven snapshot artifacts are deployed at [Sonatypes OSS snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/net/sourceforge/pmd/pmd/).
@ -27,7 +26,11 @@ Ready-to-use binary packages are uploaded to sourceforge at <https://sourceforge
## Documentation and Webpages
A [snapshot](http://pmd.sourceforge.net/snapshot) of the web site for the new version is generated travis-ci as well.
Main documentation server is [docs.pmd-code.org](https://docs.pmd-code.org).
A [snapshot](http://docs.pmd-code.org/snapshot/) of the web site for the new version is generated by the ci job as well.
The latest release documentation is always available under [docs.pmd-code.org/latest](https://docs.pmd-code.org/latest/)
## Contributing

View File

@ -6,6 +6,6 @@ tags: [languages, PmdCapableLanguage, CpdCapableLanguage]
summary: "Modelica-specific features and guidance"
---
[Modelica](https://modelica.org/modelicalanguage) is a language to model complex physical systems.
[Modelica](https://modelica.org/language/) is a language to model complex physical systems.
{% include language_info.html name='Modelica' id='modelica' implementation='modelica::lang.modelica.ModelicaLanguageModule' supports_pmd=true supports_cpd=true since='6.21.0' %}

View File

@ -78,7 +78,7 @@ author: Tom Copeland <tom@infoether.org>
mentions both PMD and CPD as useful code-checking tools.
* October 2005 - Levent Gurses' article "Improving Code Quality with PMD and Eclipse" in
[EclipseZone](http://www.eclipsezone.com/articles/pmd/) talks about the PMD Eclipse plugin and explains many
[EclipseZone](https://web.archive.org/web/20080807160502/http://www.eclipsezone.com/articles/pmd/) talks about the PMD Eclipse plugin and explains many
different facets of PMD - XPath, writing rules, the AST, all that. Good stuff!
* June 2005 - Amit Chaturvedi's article "Java & Static Analysis" in
@ -103,7 +103,7 @@ author: Tom Copeland <tom@infoether.org>
* June 2004 - [Open Source-Perlen](http://tinyurl.com/3dgpe) - A German article on PMD in Java Magazin
* June 2004 - [Improving Project Quality with PMD](http://jnb.ociweb.com/jnb/jnbJun2004.html) - Tom Wheeler's
* June 2004 - [Improving Project Quality with PMD](https://web.archive.org/web/20211203041417/http://jnb.ociweb.com/jnb/jnbJun2004.html) - Tom Wheeler's
"Java News Brief", June 2004 issue
* February 2004 - [Software Development](http://www.drdobbs.com/free-as-in-freedom/184415103) - Listed as one of

View File

@ -180,7 +180,7 @@ The tool comes with a rather extensive help text, simply running with `--help`!
## Additional Java Runtime Options
PMD is executed via a Java runtime. In some cases, you might need to set additional runtime options, e.g.
if you want to analyze a project, that uses one of OpenJDK's [Preview Language Features](http://openjdk.java.net/jeps/12).
if you want to analyze a project, that uses one of OpenJDK's [JEP 12: Preview Language Features](https://openjdk.org/jeps/12).
Just set the environment variable `PMD_JAVA_OPTS` before executing PMD, e.g.

View File

@ -529,7 +529,7 @@ CPD has been through three major incarnations:
[here](http://www.onjava.com/pub/a/onjava/2003/03/12/pmd_cpd.html)).
* Then it was completely rewritten by Brian Ewins using the
[Burrows-Wheeler transform](http://dogma.net/markn/articles/bwt/bwt.htm).
[Burrows-Wheeler transform](https://en.wikipedia.org/wiki/Burrows%E2%80%93Wheeler_transform).
* Finally, it was rewritten by Steve Hawkins to use the
[Karp-Rabin](http://www.nist.gov/dads/HTML/karpRabin.html) string matching algorithm.

View File

@ -20,7 +20,7 @@ sidebar: pmd_sidebar
* For Windows: [Winzip](http://winzip.com) or the free [7-zip](http://www.7-zip.org/)
* For Linux / Unix: [InfoZip](http://infozip.sourceforge.net/)
{% include note.html content="For executing the Designer (`pmd designer`) using [OpenJDK](http://jdk.java.net) or Java 11+, you need additionally [JavaFX](https://gluonhq.com/products/javafx/). Download it, extract it and set the environment variable JAVAFX_HOME pointing at that directory." %}
{% include note.html content="For executing the Designer (`pmd designer`) using [OpenJDK](https://jdk.java.net) or Java 11+, you need additionally [JavaFX](https://gluonhq.com/products/javafx/). Download it, extract it and set the environment variable JAVAFX_HOME pointing at that directory." %}
### Installation

View File

@ -57,8 +57,8 @@ pmd {
Source code for Gradles PMD Plugin is available here:
* [gradle/gradle code-quality](https://github.com/gradle/gradle/tree/master/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality)
* [Pmd.java](https://github.com/gradle/gradle/blob/master/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/Pmd.java)
* [PmdExtension.java](https://github.com/gradle/gradle/blob/master/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdExtension.java)
* [PmdPlugin.java](https://github.com/gradle/gradle/blob/master/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdPlugin.java)
* The default PMD version used by gradle: [DEFAULT_PMD_VERSION](https://github.com/gradle/gradle/blob/5e8d7b6b2eadf314767a4b3426db24e841b86ece/platforms/jvm/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdPlugin.java#L67)
* [gradle/gradle code-quality](https://github.com/gradle/gradle/tree/master/platforms/jvm/code-quality/src/main/groovy/org/gradle/api/plugins/quality)
* [Pmd.java](https://github.com/gradle/gradle/blob/master/platforms/jvm/code-quality/src/main/groovy/org/gradle/api/plugins/quality/Pmd.java)
* [PmdExtension.java](https://github.com/gradle/gradle/blob/master/platforms/jvm/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdExtension.java)
* [PmdPlugin.java](https://github.com/gradle/gradle/blob/master/platforms/jvm/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdPlugin.java)
* The default PMD version used by gradle: [DEFAULT_PMD_VERSION](https://github.com/gradle/gradle/blob/d6daeeb446e6a966c33efea5f3f5f1a2d96f6b8f/platforms/jvm/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdPlugin.java#L66)

View File

@ -398,7 +398,7 @@ The rules have been moved into categories with PMD 6.
#### API Changes
See [Detailed Release Notes for PMD 7.0.0]({{ baseurl }}pmd_release_notes_pmd7.html#700).
See [Detailed Release Notes for PMD 7]({{ baseurl }}pmd_release_notes_pmd7.html#700).
#### External Contributions
* [#4093](https://github.com/pmd/pmd/pull/4093): \[apex] Summit-AST Apex module - Part 1 - [Edward Klimoshenko](https://github.com/eklimo) (@eklimo)

View File

@ -31,6 +31,9 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -66,20 +69,22 @@ public class DeadLinksChecker {
// the link is actually pointing to a file in the pmd project
private static final String LOCAL_FILE_PREFIX = "https://github.com/pmd/pmd/blob/master/";
// don't check links to PMD bugs/issues/pull-requests (performance optimization)
// don't check links to PMD bugs/issues/pull-requests and some other sites (performance optimization)
private static final List<String> IGNORED_URL_PREFIXES = Collections.unmodifiableList(Arrays.asList(
"https://github.com/pmd/pmd/issues/",
"https://github.com/pmd/pmd/pull/",
"https://sourceforge.net/p/pmd/bugs/"
"https://sourceforge.net/p/pmd/bugs/",
"https://pmd.github.io/",
"https://openjdk.org/jeps" // very slow...
));
// prevent checking the same link multiple times
private final Map<String, CompletableFuture<Integer>> urlResponseCache = new ConcurrentHashMap<>();
private final Map<String, CompletableFuture<String>> urlResponseCache = new ConcurrentHashMap<>();
private final ExecutorService executorService = Executors.newCachedThreadPool();
public void checkDeadLinks(Path rootDirectory) {
public void checkDeadLinks(Path rootDirectory) throws InterruptedException {
final Path pagesDirectory = rootDirectory.resolve("docs/pages");
final Path docsDirectory = rootDirectory.resolve("docs");
@ -156,10 +161,7 @@ public class DeadLinksChecker {
Future<String> futureMessage =
getCachedFutureResponse(linkTarget)
.thenApply(c -> c >= 400)
// It's important not to use the matcher in this mapper!
// It may be exhausted at the time of execution
.thenApply(dead -> dead ? String.format("%8d: %s", lineNo, linkText) : null);
.thenApply(errorMessage -> errorMessage != null ? String.format("%8d: %s (%s)", lineNo, linkText, errorMessage) : null);
addDeadLink(fileToDeadLinks, mdFile, futureMessage);
@ -200,6 +202,8 @@ public class DeadLinksChecker {
}
executorService.shutdown();
LOG.info("Checking {} external links now...", checkedExternalLinks);
Map<Path, List<String>> joined = joinFutures(fileToDeadLinks);
LOG.info("Scanned {} files for dead links.", scannedFiles);
LOG.info(" Found {} external links, {} of those where checked.", foundExternalLinks, checkedExternalLinks);
@ -208,15 +212,13 @@ public class DeadLinksChecker {
LOG.info("External links weren't checked, set -D" + CHECK_EXTERNAL_LINKS_PROPERTY + "=true to enable it.");
}
Map<Path, List<String>> joined = joinFutures(fileToDeadLinks);
if (joined.isEmpty()) {
LOG.info("No errors found!");
} else {
LOG.warn("Found dead link(s):");
for (Path file : joined.keySet()) {
System.err.println(rootDirectory.relativize(file).toString());
joined.get(file).forEach(LOG::warn);
System.err.println(rootDirectory.relativize(file));
joined.get(file).forEach(System.err::println);
}
throw new AssertionError("Dead links detected");
}
@ -276,9 +278,8 @@ public class DeadLinksChecker {
while (captionMatcher.find()) {
final String anchor = captionMatcher.group(1)
.toLowerCase(Locale.ROOT)
.replaceAll("'", "") // remove all apostrophes
.replaceAll("[^a-z0-9_]+", "-") // replace all non-alphanumeric characters with dashes
.replaceAll("^-+|-+$", ""); // trim leading or trailing dashes
.replaceAll("'|\\.", "") // remove all apostrophes and dots
.replaceAll("[^a-z0-9_]+", "-"); // replace all non-alphanumeric characters with dashes
htmlPages.add(pageUrl + "#" + anchor);
}
@ -308,46 +309,70 @@ public class DeadLinksChecker {
}
private CompletableFuture<Integer> getCachedFutureResponse(String url) {
private CompletableFuture<String> getCachedFutureResponse(String url) {
if (urlResponseCache.containsKey(url)) {
LOG.info("response: HTTP {} (CACHED) on {}", urlResponseCache.get(url), url);
return urlResponseCache.get(url);
CompletableFuture<String> cachedFuture = urlResponseCache.get(url);
if (cachedFuture.isDone()) {
try {
LOG.debug("response: HTTP {} (CACHED) on {}", cachedFuture.get(100, TimeUnit.MILLISECONDS), url);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
LOG.info("response failed: (CACHED) on {}", url);
} catch (TimeoutException e) {
// actually, this shouldn't happen, as we checked with isDone() before
LOG.info("response future timeout: (CACHED) on {}", url);
}
}
return cachedFuture;
} else {
// process asynchronously
CompletableFuture<Integer> futureResponse = CompletableFuture.supplyAsync(() -> computeHttpResponse(url), executorService);
CompletableFuture<String> futureResponse = CompletableFuture.supplyAsync(() -> computeHttpResponse(url), executorService);
urlResponseCache.put(url, futureResponse);
return futureResponse;
}
}
// limit parallel requests to avoid 429 Too Many Requests
private Semaphore semaphore = new Semaphore(3);
private int computeHttpResponse(String url) {
private String computeHttpResponse(String url) {
try {
final HttpURLConnection httpURLConnection = (HttpURLConnection) new URL(url).openConnection();
httpURLConnection.setRequestMethod("HEAD");
httpURLConnection.setConnectTimeout(5000);
httpURLConnection.setReadTimeout(15000);
httpURLConnection.connect();
final int responseCode = httpURLConnection.getResponseCode();
semaphore.acquire();
// logging to see something is going on...
LOG.info("Checking {} now...", url);
final HttpURLConnection httpUrlConnection = (HttpURLConnection) new URL(url).openConnection();
httpUrlConnection.setRequestMethod("HEAD");
httpUrlConnection.setConnectTimeout((int) TimeUnit.SECONDS.toMillis(60));
httpUrlConnection.setReadTimeout((int) TimeUnit.SECONDS.toMillis(60));
httpUrlConnection.connect();
int responseCode = httpUrlConnection.getResponseCode();
String response = "HTTP " + responseCode;
if (httpURLConnection.getHeaderField("Location") != null) {
response += ", Location: " + httpURLConnection.getHeaderField("Location");
if (httpUrlConnection.getHeaderField("Location") != null) {
response += ", Location: " + httpUrlConnection.getHeaderField("Location");
}
LOG.debug("response: {} on {}", response, url);
// success (HTTP 2xx) or redirection (HTTP 3xx)
return responseCode;
// everything above 400 is an error
if (responseCode >= 400) {
LOG.debug("response failure: {} on {}", responseCode, url);
return "HTTP " + responseCode + " " + httpUrlConnection.getResponseMessage();
}
} catch (IOException ex) {
// success (HTTP 2xx) or redirection (HTTP 3xx) is ok
return null; // no error
} catch (IOException | InterruptedException ex) {
LOG.debug("response: {} on {} : {}", ex.getClass().getName(), url, ex.getMessage());
return 599;
return ex.getClass().getName() + ": " + ex.getMessage();
} finally {
semaphore.release();
}
}
public static void main(String[] args) throws IOException {
public static void main(String[] args) throws IOException, InterruptedException {
if (args.length != 1) {
System.err.println("Wrong arguments!");
System.err.println();

View File

@ -69,7 +69,7 @@ If the call to `setAccessible` is wrapped within a `PrivilegedAction`, then the
is assumed to be deliberate and is not reported.
Note that with Java 17 the Security Manager, which is used for `PrivilegedAction` execution,
is deprecated: [JEP 411: Deprecate the Security Manager for Removal](https://openjdk.java.net/jeps/411).
is deprecated: [JEP 411: Deprecate the Security Manager for Removal](https://openjdk.org/jeps/411).
For future-proof code, deliberate access alteration should be suppressed using the usual
suppression methods (e.g. by using `@SuppressWarnings` annotation).
</description>

View File

@ -236,7 +236,7 @@ public class DateStuff {
<description>
The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbage
collection pauses.
See [JDK-8080225](https://bugs.openjdk.java.net/browse/JDK-8080225) for details.
See [JDK-8080225](https://bugs.openjdk.org/browse/JDK-8080225) for details.
The FileReader and FileWriter constructors instantiate FileInputStream and FileOutputStream,
again causing garbage collection issues while finalizer methods are called.
@ -777,11 +777,11 @@ if (s.indexOf('d') {}
typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#useiostreamswithapachecommonsfileitem">
<description>
Problem: Use of [FileItem.get()](https://commons.apache.org/proper/commons-fileupload/apidocs/org/apache/commons/fileupload/FileItem.html#get--)
and [FileItem.getString()](https://commons.apache.org/proper/commons-fileupload/apidocs/org/apache/commons/fileupload/FileItem.html#getString--)
Problem: Use of [FileItem.get()](https://javadoc.io/static/commons-fileupload/commons-fileupload/1.5/org/apache/commons/fileupload/FileItem.html#get--)
and [FileItem.getString()](https://javadoc.io/static/commons-fileupload/commons-fileupload/1.5/org/apache/commons/fileupload/FileItem.html#getString--)
could exhaust memory since they load the entire file into memory.
Solution: Use [FileItem.getInputStream()](https://commons.apache.org/proper/commons-fileupload/apidocs/org/apache/commons/fileupload/FileItem.html#getInputStream--)
Solution: Use [FileItem.getInputStream()](https://javadoc.io/static/commons-fileupload/commons-fileupload/1.5/org/apache/commons/fileupload/FileItem.html#getInputStream--)
and buffering.
</description>
<priority>3</priority>