ARTEMIS-3914 Document client classpath automated

This commit is contained in:
Clebert Suconic 2022-07-29 15:53:30 -04:00 committed by clebertsuconic
parent d67910f1a6
commit 0cd203c32d
8 changed files with 408 additions and 11 deletions

View File

@ -40,17 +40,17 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>3.8.2</version>
<version>3.8.5</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.0.8</version>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-api</artifactId>
<version>1.0.2.v20150114</version>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
@ -75,7 +75,7 @@
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
<version>3.6.4</version>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@ -102,7 +102,13 @@ public abstract class ArtemisAbstractPlugin extends AbstractMojo {
return artifact;
}
protected File resolveArtifact(Artifact artifact) throws MojoExecutionException, DependencyCollectionException {
protected File resolveArtifactFile(Artifact artifact) throws MojoExecutionException, DependencyCollectionException {
ArtifactResult result = resolveArtifact(artifact);
return result.getArtifact().getFile();
}
protected ArtifactResult resolveArtifact(Artifact artifact) throws MojoExecutionException {
ArtifactRequest request = new ArtifactRequest();
request.setArtifact(artifact);
request.setRepositories(remoteRepos);
@ -113,8 +119,7 @@ public abstract class ArtemisAbstractPlugin extends AbstractMojo {
} catch (ArtifactResolutionException e) {
throw new MojoExecutionException(e.getMessage(), e);
}
return result.getArtifact().getFile();
return result;
}
protected List<Artifact> explodeDependencies(Artifact artifact) throws DependencyCollectionException {
@ -164,7 +169,7 @@ public abstract class ArtemisAbstractPlugin extends AbstractMojo {
List<Artifact> artifactsList = explodeDependencies(newArtifact(lib));
for (Artifact artifact : artifactsList) {
File artifactFile = resolveArtifact(artifact);
File artifactFile = resolveArtifactFile(artifact);
filesSet.add(artifactFile);
}
}
@ -174,7 +179,7 @@ public abstract class ArtemisAbstractPlugin extends AbstractMojo {
for (String lib : individualListParameter) {
Artifact artifact = newArtifact(lib);
getLog().debug("Single dpendency resolved::" + artifact);
File artifactFile = resolveArtifact(artifact);
File artifactFile = resolveArtifactFile(artifact);
filesSet.add(artifactFile);
}
}

View File

@ -0,0 +1,257 @@
/*
* 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.activemq.artemis.maven;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactResult;
/** The following substitutions are made for each line
* X{group} with the groupID
* X{artifact} with the artifactID
* X{version} with the version
* X{classifier} with the classifier of the component
* X{package} a combination of the maven group:artifact:classifier
* X{url} with the url
* X{file} with the fileName
* X{fileMD} with the fileName on a LINK with MD style
* X{URI} with the URI
* X{detail} with the detail provided in the config */
@Mojo(name = "dependency-doc", defaultPhase = LifecyclePhase.VERIFY)
public class ArtemisDependencyDocPlugin extends ArtemisAbstractPlugin {
@Parameter
String name;
/**
* The plugin descriptor
*/
private PluginDescriptor descriptor;
@Parameter
private String[] groupOrder;
@Parameter(defaultValue = "https://repo.maven.apache.org/maven2")
private String defaultRepo = "https://repo.maven.apache.org/maven2";
@Parameter
private String header;
@Parameter
private String lib;
@Parameter
private String line;
@Parameter
private String footer;
@Parameter
private String[] detailKey;
@Parameter String[] detailValue;
@Parameter
private String[] extraRepositories;
@Parameter
private String file;
private MavenProject project;
@Override
protected boolean isIgnore() {
return false;
}
private String applyFilters(String content, Map<String, String> filters) throws IOException {
if (filters != null) {
for (Map.Entry<String, String> entry : filters.entrySet()) {
try {
content = replace(content, entry.getKey(), entry.getValue());
} catch (Throwable e) {
System.out.println("Error on " + entry.getKey());
e.printStackTrace();
}
}
}
return content;
}
private String replace(String content, String key, String value) {
return content.replaceAll(Pattern.quote(key), Matcher.quoteReplacement(value));
}
private String getPackageName(org.eclipse.aether.artifact.Artifact artifact) {
return artifact.getGroupId() + ":" + artifact.getArtifactId() + (artifact.getClassifier() != null && !artifact.getClassifier().equals("") ? ":" + artifact.getClassifier() : "");
}
private String getGroupOrder(String group) {
if (groupOrder == null) {
groupOrder = new String[] {"org.apache.activemq"};
}
int i = 0;
for (; i < groupOrder.length; i++) {
if (group.equals(groupOrder[i])) {
return Integer.toString(i);
}
}
return Integer.toString(i);
}
@Override
protected void doExecute() {
HashMap<String, String> keys = new HashMap<>();
if (detailKey != null) {
if (detailValue == null) {
throw new IllegalStateException("you need to specify all detail parameters");
}
if (detailKey.length != detailValue.length) {
throw new IllegalStateException("Illegal argument size");
}
for (int i = 0; i < detailKey.length; i++) {
keys.put(detailKey[i], detailValue[i]);
}
}
if (file == null) {
throw new IllegalStateException("you must specify the file output");
}
if (line == null) {
throw new IllegalStateException("you must specify the line");
}
try {
File javaFile = new File(file);
javaFile.getParentFile().mkdirs();
PrintStream stream = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
if (header != null) {
stream.println(header);
}
List<org.eclipse.aether.artifact.Artifact> artifacts = explodeDependencies(newArtifact(lib));
Collections.sort(artifacts, new Comparator<Artifact>() {
@Override
public int compare(Artifact o1, Artifact o2) {
String pref1 = getGroupOrder(o1.getGroupId());
String pref2 = getGroupOrder(o2.getGroupId());
return (pref1 + o1.getGroupId() + o1.getArtifactId()).compareTo(pref2 + o2.getGroupId() + o2.getArtifactId());
}
});
artifacts.forEach((art) -> {
try {
String detail = keys.get(art.getGroupId() + ":" + art.getArtifactId());
if (detail == null) {
detail = "";
}
ArtifactResult result = resolveArtifact(art);
HashMap<String, String> filter = new HashMap<>();
filter.put("X{detail}", detail);
filter.put("X{group}", art.getGroupId());
filter.put("X{artifact}", art.getArtifactId());
filter.put("X{classifier}", result.getArtifact().getClassifier());
filter.put("X{package}", getPackageName(result.getArtifact()));
filter.put("X{file}", result.getArtifact().getFile().getName());
filter.put("X{version}", result.getArtifact().getVersion());
String uri = getURI(result);
filter.put("X{uri}", uri);
if (uri.equals("")) {
filter.put("X{fileMD}", result.getArtifact().getFile().getName());
} else {
filter.put("X{fileMD}", "[" + result.getArtifact().getFile().getName() + "](" + uri + ")");
}
String output = applyFilters(line, filter);
if (getLog().isDebugEnabled()) {
filter.forEach((a, b) -> {
getLog().debug("filter.put(" + a + ", " + b + ")");
});
getLog().debug(output);
}
stream.println(output);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
});
if (footer != null) {
stream.println(footer);
}
stream.close();
} catch (Throwable e) {
getLog().error(e.getMessage(), e);
}
}
private String getURI(ArtifactResult result) {
Artifact art = result.getArtifact();
String uri = "";
if (result.getRepository() instanceof RemoteRepository) {
RemoteRepository remoteRepository = (RemoteRepository) result.getRepository();
uri = remoteRepository.getUrl();
} else {
uri = defaultRepo;
}
return uri + "/" +
art.getGroupId().replace('.', '/') + "/" +
art.getArtifactId() + "/" +
art.getVersion();
}
}

View File

@ -199,6 +199,85 @@
<skip>${skipWebsiteDocGeneration}</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-maven-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<id>doc-jms-client</id>
<phase>generate-sources</phase>
<goals>
<goal>dependency-doc</goal>
</goals>
<configuration>
<file>${scratch-dir-user-manual}/client-classpath-jms.md</file>
<groupOrder>
<arg>org.apache.activemq</arg>
<arg>jakarta.jms</arg>
<arg>org.jgroups</arg>
<arg>io.netty</arg>
</groupOrder>
<header>#Artemis JMS Client Dependencies
File | observation | package
---|---|---</header>
<line>X{fileMD}| X{detail} |X{package} </line>
<detailKey>
<arg>io.netty:netty-transport-native-epoll</arg>
<arg>io.netty:netty-transport-classes-epoll</arg>
<arg>io.netty:netty-transport-native-kqueue</arg>
<arg>io.netty:netty-transport-classes-kqueue</arg>
<arg>org.jgroups:jgroups</arg>
</detailKey>
<detailValue>
<arg>only if you want epoll on Linux</arg>
<arg>only if you want epoll on Linux</arg>
<arg>only if you want kqueue on MacOS</arg>
<arg>only if you want kqueue on MacOS</arg>
<arg>only if you want JGroups discovery from the clients</arg>
</detailValue>
<lib>org.apache.activemq:artemis-jms-client:${project.version}</lib>
</configuration>
</execution>
<execution>
<id>doc-jakarta-client</id>
<phase>generate-sources</phase>
<goals>
<goal>dependency-doc</goal>
</goals>
<configuration>
<file>${scratch-dir-user-manual}/client-classpath-jakarta.md</file>
<groupOrder>
<arg>org.apache.activemq</arg>
<arg>jakarta.jms</arg>
<arg>org.jgroups</arg>
<arg>io.netty</arg>
</groupOrder>
<header>#Artemis Jakarta Client Dependencies
File | observation | package
---|---|---</header>
<line>X{fileMD}| X{detail} |X{package} </line>
<detailKey>
<arg>io.netty:netty-transport-native-epoll</arg>
<arg>io.netty:netty-transport-classes-epoll</arg>
<arg>io.netty:netty-transport-native-kqueue</arg>
<arg>io.netty:netty-transport-classes-kqueue</arg>
<arg>org.jgroups:jgroups</arg>
</detailKey>
<detailValue>
<arg>only if you want epoll on Linux</arg>
<arg>only if you want epoll on Linux</arg>
<arg>only if you want kqueue on MacOS</arg>
<arg>only if you want kqueue on MacOS</arg>
<arg>only if you want JGroups discovery from the clients</arg>
</detailValue>
<lib>org.apache.activemq:artemis-jakarta-client:${project.version}</lib>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>

View File

@ -22,6 +22,8 @@
* [Mapping JMS Concepts to the Core API](jms-core-mapping.md)
* [Using JMS](using-jms.md)
* [The Client Classpath](client-classpath.md)
* [JMS](client-classpath-jms.md)
* [Jakarta](client-classpath-jakarta.md)
* [Examples](examples.md)
* [Routing Messages With Wild Cards](wildcard-routing.md)
* [Wildcard Syntax](wildcard-syntax.md)

View File

@ -0,0 +1 @@
This file will be generated/replaced in compile time by artemis-website

View File

@ -0,0 +1 @@
This file will be generated/replaced in compile time by artemis-website

View File

@ -10,7 +10,59 @@ Apache ActiveMQ Artemis requires just a single jar on the *client classpath*.
> jars from different Apache ActiveMQ Artemis versions. Mixing and matching
> different jar versions may cause subtle errors and failures to occur.
## Maven Packages
The best way to define a client dependency to your java application is through a maven dependency declaration.
There are two packages you can choose from, org.apache.activemq:artemis-jms-client or org.apache.activemq:artemis-jakarta-client for both JMS and Jakarta APIs.
Say you define artemis-version as '{{ config.version }}':
For JMS:
```xml
...
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client</artifactId>
<version>${artemis-version}</version>
</dependency>
...
```
For Jakarta:
```xml
...
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jakarta-client</artifactId>
<version>${artemis-version}</version>
</dependency>
...
```
## All clients
Even though it is highly recommend using maven, in case this is not a possibility the all inclusive jars could be used.
These jars will be available under ./lib/client on the main distribution:
- artemis-jakarta-client-all-{{ config.version }}.jar
- artemis-jms-client-all-{{ config.version }}.jar
Whether you are using JMS or just the Core API simply add the
`artemis-jms-client-all.jar` from the `lib/client` directory to your client
classpath. This is a "shaded" jar that contains all the Artemis code plus
dependencies (e.g. JMS spec, Netty, etc.).
classpath.
**Warning:**These jars will include all the [client's dependencies](client-classpath-jms.md). Be careful with mixing other jars in your application as they may clash with other.
## Individual dependencies
You may also choose to use the jars individually as they are all included under ./lib on the main distribution.
For more information:
- [client jms dependencies](client-classpath-jms.md )
- [client jakarta dependencies](client-classpath-jakarta.md)