├── LICENSE
├── pom.xml
├── src
└── main
│ └── java
│ └── com
│ └── github
│ └── chrisdchristo
│ └── capsule
│ ├── Mojo.java
│ └── CapsuleMojo.java
└── README.md
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | com.github.chrisdchristo
5 | capsule-maven-plugin
6 | 1.5.2-SNAPSHOT
7 | maven-plugin
8 |
9 |
10 | org.sonatype.oss
11 | oss-parent
12 | 9
13 |
14 |
15 |
16 |
17 | chrisdchristo
18 | https://github.com/chrisdchristo
19 |
20 |
21 |
22 |
23 | https://github.com/chrisdchristo/capsule-maven-plugin
24 | scm:git:https://github.com/chrisdchristo/capsule-maven-plugin.git
25 | scm:git:https://github.com/chrisdchristo/capsule-maven-plugin.git
26 |
27 |
28 | Capsule Maven Plugin
29 | The maven plugin to build capsules of your jars.
30 | https://github.com/chrisdchristo/capsule-maven-plugin
31 |
32 |
33 |
34 | MIT License
35 | http://www.opensource.org/licenses/mit-license.php
36 | repo
37 |
38 |
39 |
40 |
41 |
42 | ossrh
43 | https://oss.sonatype.org/content/repositories/snapshots/
44 |
45 |
46 | ossrh
47 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
48 |
49 |
50 |
51 |
52 | UTF-8
53 | 1.7
54 |
55 | 3.0.1
56 | 3.6.1
57 | 3.0-alpha-2
58 | 3.5
59 | 3.3.9
60 | 3.5
61 | 1.6
62 | 1.1.0
63 |
64 |
65 |
66 |
67 | org.apache.maven
68 | maven-plugin-api
69 | ${maven.plugin.api.version}
70 |
71 |
72 | org.apache.maven.plugin-tools
73 | maven-plugin-annotations
74 | ${maven.plugin.annotations.version}
75 | provided
76 |
77 |
78 | org.apache.maven
79 | maven-project
80 | ${maven.project.version}
81 |
82 |
83 | org.eclipse.aether
84 | aether-api
85 | ${aether.api.version}
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | org.apache.maven.plugins
95 | maven-source-plugin
96 | ${maven.source.plugin.version}
97 |
98 |
99 | attach-sources
100 |
101 | jar
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | org.apache.maven.plugins
110 | maven-compiler-plugin
111 | ${maven.compiler.plugin.version}
112 |
113 | ${java.version}
114 | ${java.version}
115 |
116 |
117 |
118 |
119 |
120 | org.apache.maven.plugins
121 | maven-plugin-plugin
122 | ${maven.plugin.plugin.version}
123 |
124 | capsule
125 | true
126 |
127 |
128 |
129 | mojo-descriptor
130 |
131 | descriptor
132 |
133 |
134 |
135 | help-goal
136 |
137 | helpmojo
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 | release-sign-artifacts
149 |
150 |
151 | performRelease
152 | true
153 |
154 |
155 |
156 |
157 |
158 |
159 | org.apache.maven.plugins
160 | maven-gpg-plugin
161 | ${maven.gpg.plugin.version}
162 |
163 |
164 | sign-artifacts
165 | verify
166 |
167 | sign
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
--------------------------------------------------------------------------------
/src/main/java/com/github/chrisdchristo/capsule/Mojo.java:
--------------------------------------------------------------------------------
1 | package com.github.chrisdchristo.capsule;
2 |
3 | import org.apache.maven.artifact.Artifact;
4 | import org.apache.maven.model.Dependency;
5 | import org.apache.maven.model.Exclusion;
6 | import org.apache.maven.model.Plugin;
7 | import org.apache.maven.plugin.AbstractMojo;
8 | import org.apache.maven.plugins.annotations.Component;
9 | import org.apache.maven.plugins.annotations.Parameter;
10 | import org.apache.maven.project.DefaultMavenProjectHelper;
11 | import org.apache.maven.project.MavenProject;
12 | import org.apache.maven.project.MavenProjectHelper;
13 | import org.codehaus.plexus.util.IOUtil;
14 | import org.eclipse.aether.RepositorySystem;
15 | import org.eclipse.aether.RepositorySystemSession;
16 | import org.eclipse.aether.artifact.DefaultArtifact;
17 | import org.eclipse.aether.collection.CollectRequest;
18 | import org.eclipse.aether.repository.RemoteRepository;
19 | import org.eclipse.aether.resolution.*;
20 |
21 | import java.io.File;
22 | import java.io.IOException;
23 | import java.io.InputStream;
24 | import java.util.*;
25 | import java.util.jar.Attributes;
26 | import java.util.jar.JarOutputStream;
27 | import java.util.jar.Manifest;
28 | import java.util.zip.ZipEntry;
29 | import java.util.zip.ZipException;
30 |
31 | /**
32 | * Super class with generic methods
33 | */
34 | public abstract class Mojo extends AbstractMojo {
35 |
36 | /**
37 | * AETHER REPO LINK
38 | */
39 | @Component
40 | RepositorySystem repoSystem = null;
41 | @Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
42 | RepositorySystemSession repoSession = null;
43 | @Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly = true)
44 | List remoteRepos = null;
45 | @Parameter(defaultValue = "${project.build.finalName}", readonly = true)
46 | String finalName = null;
47 | @Parameter(defaultValue = "${project.build.directory}")
48 | File buildDir = null;
49 | @Parameter(defaultValue = "${project.basedir}")
50 | File baseDir = null;
51 |
52 |
53 | /**
54 | * Project
55 | */
56 | @Parameter(defaultValue = "${project}", readonly = true)
57 | MavenProject project = null;
58 |
59 | final MavenProjectHelper helper = new DefaultMavenProjectHelper();
60 |
61 | abstract String pluginKey();
62 | abstract String logPrefix();
63 |
64 | // DEPENDENCIES
65 |
66 | Set appDependencies() { return set(project.getTestDependencies()); }
67 | Set appDirectDependencies() { return set(project.getDependencies()); }
68 | Set appDependencyArtifacts() { return project.getArtifacts(); }
69 | Set appDirectDependencyArtifacts() { return project.getDependencyArtifacts(); }
70 |
71 | Set pluginDependencies() { return getDependenciesOf(set(plugin().getDependencies()), true); }
72 | Set pluginDirectDependencies() { return set(plugin().getDependencies()); }
73 | Set pluginDependencyArtifacts() { return getDependencyArtifactsOf(set(plugin().getDependencies()), true); }
74 | Set pluginDirectDependencyArtifacts() { return toArtifacts(set(plugin().getDependencies())); }
75 |
76 |
77 | // RESOLVERS
78 |
79 | private Plugin plugin() {
80 | return project.getPlugin(pluginKey());
81 | }
82 |
83 | private ArtifactResult resolve(final Dependency dependency) {
84 | return resolve(dependency.getGroupId(), dependency.getArtifactId(), dependency.getClassifier(), dependency.getVersion());
85 | }
86 |
87 | ArtifactResult resolve(final String groupId, final String artifactId, final String classifier, final String version) {
88 | return resolve(coords(groupId, artifactId, classifier, version));
89 | }
90 |
91 | ArtifactResult resolve(final String coords) {
92 | try {
93 | return repoSystem.resolveArtifact(repoSession, new ArtifactRequest(new DefaultArtifact(coords), remoteRepos, null));
94 | } catch (final ArtifactResolutionException e) {
95 | warn("\t\t[Resolve] Failed to resolve: [" + coords + "]");
96 | return null;
97 | }
98 | }
99 |
100 | private Set resolveDependencies(final Dependency dependency) {
101 | try {
102 | final CollectRequest collectRequest = new CollectRequest(new org.eclipse.aether.graph.Dependency(resolve(dependency).getArtifact(), ""), remoteRepos);
103 | return set(repoSystem.resolveDependencies(repoSession, new DependencyRequest(collectRequest, null)).getArtifactResults());
104 | } catch (final DependencyResolutionException e) {
105 | warn("\t\t[Resolve] Failed to resolve: [" + coords(dependency) + "]");
106 | return new HashSet<>();
107 | }
108 | }
109 |
110 | Artifact toArtifact(final ArtifactResult ar) {
111 | if (ar == null) return null;
112 | final Artifact artifact = new org.apache.maven.artifact.DefaultArtifact(
113 | ar.getArtifact().getGroupId(),
114 | ar.getArtifact().getArtifactId(),
115 | ar.getArtifact().getVersion(),
116 | null,
117 | "jar",
118 | ar.getArtifact().getClassifier(),
119 | null);
120 | if (ar.getRequest().getDependencyNode() != null && ar.getRequest().getDependencyNode().getDependency() != null) {
121 | artifact.setScope(ar.getRequest().getDependencyNode().getDependency().getScope());
122 | artifact.setOptional(ar.getRequest().getDependencyNode().getDependency().isOptional());
123 | }
124 | if (artifact.getScope() == null || artifact.getScope().isEmpty()) artifact.setScope("compile");
125 | artifact.setFile(ar.getArtifact().getFile());
126 | return artifact;
127 | }
128 |
129 | private Artifact toArtifact(final Dependency dependency) {
130 | if (dependency == null) return null;
131 | final Artifact artifact = toArtifact(resolve(dependency));
132 | artifact.setScope(dependency.getScope());
133 | if (artifact.getScope() == null || artifact.getScope().isEmpty()) artifact.setScope("compile");
134 | return artifact;
135 | }
136 |
137 | private Dependency toDependency(final Artifact artifact) {
138 | if (artifact == null) return null;
139 | final Dependency dependency = new Dependency();
140 | dependency.setGroupId(artifact.getGroupId());
141 | dependency.setArtifactId(artifact.getArtifactId());
142 | dependency.setVersion(artifact.getVersion());
143 | dependency.setScope(artifact.getScope());
144 | dependency.setClassifier(artifact.getClassifier());
145 | dependency.setOptional(artifact.isOptional());
146 | if (dependency.getScope() == null || dependency.getScope().isEmpty()) dependency.setScope("compile");
147 | return dependency;
148 | }
149 |
150 | private Dependency toDependency(final ArtifactResult ar) {
151 | return toDependency(toArtifact(ar));
152 | }
153 |
154 | private Set getDependencyArtifactsOf(final Dependency dependency, final boolean includeRoot) {
155 | final Set artifacts = new HashSet<>();
156 | if (includeRoot) artifacts.add(toArtifact(dependency));
157 | for (final ArtifactResult ar : resolveDependencies(dependency)) {
158 | final Artifact artifact = toArtifact(ar);
159 |
160 | // if null set to default compile
161 | if (artifact.getScope() == null || artifact.getScope().isEmpty()) artifact.setScope("compile");
162 |
163 | // skip any deps that aren't compile or runtime
164 | if (!artifact.getScope().equals("compile") && !artifact.getScope().equals("runtime")) continue;
165 |
166 | // set direct-scope on transitive deps
167 | if (dependency.getScope().equals("provided")) artifact.setScope("provided");
168 | if (dependency.getScope().equals("system")) artifact.setScope("system");
169 | if (dependency.getScope().equals("test")) artifact.setScope("test");
170 |
171 | artifacts.add(toArtifact(ar));
172 | }
173 | return cleanArtifacts(artifacts);
174 | }
175 |
176 | private Set getDependencyArtifactsOf(final Set dependencies, final boolean includeRoot) {
177 | final Set artifacts = new HashSet<>();
178 | for (final Dependency dependency : dependencies) {
179 | artifacts.addAll(getDependencyArtifactsOf(dependency, includeRoot));
180 | }
181 | return cleanArtifacts(artifacts);
182 | }
183 |
184 | private Set getDependenciesOf(final Dependency dependency, final boolean includeRoot) {
185 | final Set dependencies = new HashSet<>();
186 | if (includeRoot) dependencies.add(dependency);
187 | for (final ArtifactResult ar : resolveDependencies(dependency)) {
188 | dependencies.add(toDependency(ar));
189 | }
190 | return cleanDependencies(dependencies);
191 | }
192 |
193 | private Set getDependenciesOf(final Set dependencies, final boolean includeRoot) {
194 | final Set dependenciesAll = new HashSet<>();
195 | for (final Dependency dependency : dependencies) {
196 | dependenciesAll.addAll(getDependenciesOf(dependency, includeRoot));
197 | }
198 | return cleanDependencies(dependenciesAll);
199 | }
200 |
201 | private Set toArtifacts(final Set dependencies) {
202 | final Set artifacts = new HashSet<>();
203 | for (final Dependency dependency : dependencies) {
204 | artifacts.add(toArtifact(dependency));
205 | }
206 | return cleanArtifacts(artifacts);
207 | }
208 |
209 | // JAR & FILE HELPERS
210 |
211 | String addDirectoryToJar(final JarOutputStream jar, final String outputDirectory) throws IOException {
212 |
213 | // format the output directory
214 | String formattedOutputDirectory = "";
215 | if (outputDirectory != null && !outputDirectory.isEmpty()) {
216 | if (!outputDirectory.endsWith("/")) {
217 | formattedOutputDirectory = outputDirectory + File.separatorChar;
218 | } else {
219 | formattedOutputDirectory = outputDirectory;
220 | }
221 | }
222 |
223 | if (!formattedOutputDirectory.isEmpty()) {
224 | try {
225 | jar.putNextEntry(new ZipEntry(formattedOutputDirectory));
226 | jar.closeEntry();
227 | } catch (final ZipException ignore) {} // ignore duplicate entries and other errors
228 | }
229 | return formattedOutputDirectory;
230 | }
231 |
232 | JarOutputStream addToJar(final String name, final InputStream input, final JarOutputStream jar) throws IOException {
233 | try {
234 | debug("\t[Added to Jar]: " + name);
235 | jar.putNextEntry(new ZipEntry(name));
236 | IOUtil.copy(input, jar);
237 | jar.closeEntry();
238 | } catch (final ZipException ignore) {} // ignore duplicate entries and other errors
239 | IOUtil.close(input);
240 | return jar;
241 | }
242 |
243 |
244 | // LOG
245 |
246 | void debug(final String message) { getLog().debug(logPrefix() + message); }
247 | void info(final String message) { getLog().info(logPrefix() + message); }
248 | void warn(final String message) { getLog().warn(logPrefix() + message); }
249 | void printManifest(final Manifest manifest) {
250 | info("\t[Manifest]:");
251 | for (final Map.Entry