JarPlugin.groovy
001 /*
002  * SPDX-License-Identifier: Apache-2.0
003  *
004  * Copyright 2018-2019 Andres Almiray.
005  *
006  * Licensed under the Apache License, Version 2.0 (the "License");
007  * you may not use this file except in compliance with the License.
008  * You may obtain a copy of the License at
009  *
010  *     http://www.apache.org/licenses/LICENSE-2.0
011  *
012  * Unless required by applicable law or agreed to in writing, software
013  * distributed under the License is distributed on an "AS IS" BASIS,
014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015  * See the License for the specific language governing permissions and
016  * limitations under the License.
017  */
018 package org.kordamp.gradle.plugin.jar
019 
020 import groovy.transform.CompileDynamic
021 import groovy.transform.CompileStatic
022 import org.gradle.BuildAdapter
023 import org.gradle.api.Project
024 import org.gradle.api.Task
025 import org.gradle.api.invocation.Gradle
026 import org.gradle.api.plugins.JavaBasePlugin
027 import org.gradle.api.tasks.bundling.Jar
028 import org.kordamp.gradle.plugin.AbstractKordampPlugin
029 import org.kordamp.gradle.plugin.base.BasePlugin
030 import org.kordamp.gradle.plugin.base.ProjectConfigurationExtension
031 import org.kordamp.gradle.plugin.base.plugins.BuildInfo
032 import org.kordamp.gradle.plugin.buildinfo.BuildInfoPlugin
033 import org.kordamp.gradle.plugin.minpom.MinPomPlugin
034 
035 import static org.kordamp.gradle.PluginUtils.resolveEffectiveConfig
036 import static org.kordamp.gradle.StringUtils.isNotBlank
037 import static org.kordamp.gradle.plugin.base.BasePlugin.isRootProject
038 
039 /**
040  * Configures a {@code jar} task.
041  * Configures Manifest and MetaInf entries if the {@code config.release} is enabled.
042  *
043  @author Andres Almiray
044  @since 0.1.0
045  */
046 @CompileStatic
047 class JarPlugin extends AbstractKordampPlugin {
048     Project project
049 
050     void apply(Project project) {
051         this.project = project
052 
053         if (isRootProject(project)) {
054             if (project.childProjects.size()) {
055                 project.childProjects.values().each {
056                     configureProject(it)
057                 }
058             else {
059                 configureProject(project)
060             }
061         else {
062             configureProject(project)
063         }
064     }
065 
066     static void applyIfMissing(Project project) {
067         if (!project.plugins.findPlugin(JarPlugin)) {
068             project.plugins.apply(JarPlugin)
069         }
070     }
071 
072     private void configureProject(Project project) {
073         if (hasBeenVisited(project)) {
074             return
075         }
076         setVisited(project, true)
077 
078         BasePlugin.applyIfMissing(project)
079         BuildInfoPlugin.applyIfMissing(project)
080         MinPomPlugin.applyIfMissing(project)
081 
082         project.afterEvaluate {
083             project.plugins.withType(JavaBasePlugin) {
084                 createJarTaskIfNeeded(project)
085             }
086         }
087 
088         project.rootProject.gradle.addBuildListener(new BuildAdapter() {
089             @Override
090             void projectsEvaluated(Gradle gradle) {
091                 project.tasks.withType(Jar) { Jar jarTask ->
092                     if (jarTask.name == 'jar') configureJarMetainf(project, jarTask)
093                     configureJarManifest(project, jarTask)
094                 }
095             }
096         })
097     }
098 
099     @CompileDynamic
100     private void createJarTaskIfNeeded(Project project) {
101         if (!project.sourceSets.findByName('main')) return
102 
103         String taskName = 'jar'
104 
105         Task jarTask = project.tasks.findByName(taskName)
106 
107         if (!jarTask) {
108             jarTask = project.tasks.create(taskName, Jar) {
109                 dependsOn project.sourceSets.main.output
110                 group org.gradle.api.plugins.BasePlugin.BUILD_GROUP
111                 description 'Assembles a jar archive'
112                 from project.sourceSets.main.output
113                 destinationDir project.file("${project.buildDir}/libs")
114             }
115         }
116 
117         jarTask.configure {
118             metaInf {
119                 from(project.rootProject.file('.')) {
120                     include 'LICENSE*'
121                 }
122             }
123         }
124     }
125 
126     @CompileDynamic
127     private void configureJarMetainf(Project project, Jar jarTask) {
128         ProjectConfigurationExtension effectiveConfig = resolveEffectiveConfig(project.rootProject)
129         setEnabled(effectiveConfig.minpom.enabled)
130 
131         if (enabled) {
132             jarTask.configure {
133                 dependsOn MinPomPlugin.MINPOM_TASK_NAME
134                 metaInf {
135                     from(MinPomPlugin.resolveMinPomDestinationDir(project)) {
136                         into "maven/${project.group}/${project.name}"
137                     }
138                 }
139             }
140         }
141     }
142 
143     @CompileDynamic
144     private void configureJarManifest(Project project, Jar jarTask) {
145         ProjectConfigurationExtension effectiveConfig = resolveEffectiveConfig(project.rootProject)
146 
147         if (effectiveConfig.release) {
148             Map<String, String> attributesMap = [:]
149 
150             checkBuildInfoAttribute(effectiveConfig.buildInfo, 'buildCreatedBy', attributesMap, 'Created-By')
151             checkBuildInfoAttribute(effectiveConfig.buildInfo, 'buildBy', attributesMap, 'Build-By')
152             checkBuildInfoAttribute(effectiveConfig.buildInfo, 'buildJdk', attributesMap, 'Build-Jdk')
153             checkBuildInfoAttribute(effectiveConfig.buildInfo, 'buildDate', attributesMap, 'Build-Date')
154             checkBuildInfoAttribute(effectiveConfig.buildInfo, 'buildTime', attributesMap, 'Build-Time')
155             checkBuildInfoAttribute(effectiveConfig.buildInfo, 'buildRevision', attributesMap, 'Build-Revision')
156 
157             if (effectiveConfig.info.specification.enabled) {
158                 attributesMap.'Specification-Title' = effectiveConfig.info.specification.title
159                 attributesMap.'Specification-Version' = effectiveConfig.info.specification.version
160                 if (isNotBlank(effectiveConfig.info.specification.vendor)) attributesMap.'Specification-Vendor' = effectiveConfig.info.specification.vendor
161             }
162 
163             if (effectiveConfig.info.implementation.enabled) {
164                 attributesMap.'Implementation-Title' = effectiveConfig.info.implementation.title
165                 attributesMap.'Implementation-Version' = effectiveConfig.info.implementation.version
166                 if (isNotBlank(effectiveConfig.info.implementation.vendor)) attributesMap.'Implementation-Vendor' = effectiveConfig.info.implementation.vendor
167             }
168 
169             jarTask.configure {
170                 manifest {
171                     attributes(attributesMap)
172                 }
173             }
174         }
175     }
176 
177     @CompileDynamic
178     private static void checkBuildInfoAttribute(BuildInfo buildInfo, String key, Map map, String manifestKey) {
179         if (!buildInfo."skip${key.capitalize()}") {
180             map[manifestKey= buildInfo[key]
181         }
182     }
183 }