BasePlugin.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  *     https://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.base
019 
020 import groovy.transform.CompileStatic
021 import org.gradle.api.Action
022 import org.gradle.api.GradleException
023 import org.gradle.api.Project
024 import org.gradle.api.plugins.AppliedPlugin
025 import org.gradle.api.tasks.JavaExec
026 import org.kordamp.gradle.PluginUtils
027 import org.kordamp.gradle.plugin.AbstractKordampPlugin
028 import org.kordamp.gradle.plugin.base.tasks.ConfigurationSettingsTask
029 import org.kordamp.gradle.plugin.base.tasks.ConfigurationsTask
030 import org.kordamp.gradle.plugin.base.tasks.EffectiveSettingsTask
031 import org.kordamp.gradle.plugin.base.tasks.ExtensionsTask
032 import org.kordamp.gradle.plugin.base.tasks.GroovyCompilerSettingsTask
033 import org.kordamp.gradle.plugin.base.tasks.JavaCompilerSettingsTask
034 import org.kordamp.gradle.plugin.base.tasks.JavaExecSettingsTask
035 import org.kordamp.gradle.plugin.base.tasks.ListIncludedBuildsTask
036 import org.kordamp.gradle.plugin.base.tasks.ListProjectsTask
037 import org.kordamp.gradle.plugin.base.tasks.PluginsTask
038 import org.kordamp.gradle.plugin.base.tasks.ProjectPropertiesTask
039 import org.kordamp.gradle.plugin.base.tasks.RepositoriesTask
040 import org.kordamp.gradle.plugin.base.tasks.SourceSetSettingsTask
041 import org.kordamp.gradle.plugin.base.tasks.SourceSetsTask
042 import org.kordamp.gradle.plugin.base.tasks.TestSettingsTask
043 
044 import static org.kordamp.gradle.PluginUtils.isAndroidProject
045 
046 /**
047  *
048  @author Andres Almiray
049  @since 0.1.0
050  */
051 @CompileStatic
052 class BasePlugin extends AbstractKordampPlugin {
053     static final String ORG_KORDAMP_GRADLE_BASE_VALIDATE = 'org.kordamp.gradle.base.validate'
054 
055     Project project
056 
057     void apply(Project project) {
058         this.project = project
059 
060         if (hasBeenVisited(project)) {
061             return
062         }
063         setVisited(project, true)
064 
065         if (!project.plugins.findPlugin(org.gradle.api.plugins.BasePlugin)) {
066             project.pluginManager.apply(org.gradle.api.plugins.BasePlugin)
067         }
068 
069         if (!project.extensions.findByType(ProjectConfigurationExtension)) {
070             project.extensions.create(ProjectConfigurationExtension.CONFIG_NAME, ProjectConfigurationExtension, project)
071         }
072 
073         project.tasks.register('effectiveSettings', EffectiveSettingsTask,
074             new Action<EffectiveSettingsTask>() {
075                 @Override
076                 void execute(EffectiveSettingsTask t) {
077                     t.group = 'Insight'
078                     t.description = "Displays resolved settings for project '$project.name'."
079                 }
080             })
081 
082         project.tasks.register('repositories', RepositoriesTask,
083             new Action<RepositoriesTask>() {
084                 @Override
085                 void execute(RepositoriesTask t) {
086                     t.group = 'Insight'
087                     t.description = "Displays all repositories for project '$project.name'."
088                 }
089             })
090 
091         project.tasks.register('plugins', PluginsTask,
092             new Action<PluginsTask>() {
093                 @Override
094                 void execute(PluginsTask t) {
095                     t.group = 'Insight'
096                     t.description = "Displays all plugins applied to project '$project.name'."
097                 }
098             })
099 
100         project.tasks.register('extensions', ExtensionsTask,
101             new Action<ExtensionsTask>() {
102                 @Override
103                 void execute(ExtensionsTask t) {
104                     t.group = 'Insight'
105                     t.description = "Displays all extensions applied to project '$project.name'."
106                 }
107             })
108 
109         project.tasks.register('configurations', ConfigurationsTask,
110             new Action<ConfigurationsTask>() {
111                 @Override
112                 void execute(ConfigurationsTask t) {
113                     t.group = 'Insight'
114                     t.description = "Displays all configurations available in project '$project.name'."
115                 }
116             })
117 
118         project.tasks.register('projectProperties', ProjectPropertiesTask,
119             new Action<ProjectPropertiesTask>() {
120                 @Override
121                 void execute(ProjectPropertiesTask t) {
122                     t.group = 'Insight'
123                     t.description = "Displays all properties found in project '$project.name'."
124                 }
125             })
126 
127         project.tasks.register('configurationSettings', ConfigurationSettingsTask,
128             new Action<ConfigurationSettingsTask>() {
129                 @Override
130                 void execute(ConfigurationSettingsTask t) {
131                     t.group = 'Insight'
132                     t.description = 'Display the settings of a Configuration.'
133                 }
134             })
135 
136         project.tasks.addRule('Pattern: <ConfigurationName>ConfigurationSettings: Displays the settings of a Configuration.', new Action<String>() {
137             @Override
138             void execute(String configurationName) {
139                 if (configurationName.endsWith('ConfigurationSettings')) {
140                     String resolvedConfigurationName = configurationName - 'ConfigurationSettings'
141                     project.tasks.register(configurationName, ConfigurationSettingsTask,
142                         new Action<ConfigurationSettingsTask>() {
143                             @Override
144                             void execute(ConfigurationSettingsTask t) {
145                                 t.group = 'Insight'
146                                 t.configuration = resolvedConfigurationName
147                                 t.description = "Display the settings of the '${resolvedConfigurationName}' Configuration."
148                             }
149                         })
150                 }
151             }
152         })
153 
154         project.pluginManager.withPlugin('java-base', new Action<AppliedPlugin>() {
155             @Override
156             void execute(AppliedPlugin appliedPlugin) {
157                 if (!isAndroidProject(project)) {
158                     project.tasks.register('sourceSets', SourceSetsTask,
159                         new Action<SourceSetsTask>() {
160                             @Override
161                             void execute(SourceSetsTask t) {
162                                 t.group = 'Insight'
163                                 t.description = "Displays all sourceSets available in project '$project.name'."
164                             }
165                         })
166 
167                     project.tasks.register('sourceSetSettings', SourceSetSettingsTask,
168                         new Action<SourceSetSettingsTask>() {
169                             @Override
170                             void execute(SourceSetSettingsTask t) {
171                                 t.group = 'Insight'
172                                 t.description = 'Display the settings of a SourceSet.'
173                             }
174                         })
175 
176                     project.tasks.addRule('Pattern: <SourceSetName>SourceSetSettings: Displays the settings of a SourceSet.', new Action<String>() {
177                         @Override
178                         void execute(String sourceSetName) {
179                             if (sourceSetName.endsWith('SourceSetSettings')) {
180                                 String resolvedSourceSetName = sourceSetName - 'SourceSetSettings'
181                                 project.tasks.register(sourceSetName, SourceSetSettingsTask,
182                                     new Action<SourceSetSettingsTask>() {
183                                         @Override
184                                         void execute(SourceSetSettingsTask t) {
185                                             t.group = 'Insight'
186                                             t.sourceSet = resolvedSourceSetName
187                                             t.description = "Display the settings of the '${resolvedSourceSetName}' sourceSet."
188                                         }
189                                     })
190                             }
191                         }
192                     })
193                 }
194 
195                 project.tasks.register('javaCompilerSettings', JavaCompilerSettingsTask,
196                     new Action<JavaCompilerSettingsTask>() {
197                         @Override
198                         void execute(JavaCompilerSettingsTask t) {
199                             t.group = 'Insight'
200                             t.description = 'Display Java compiler settings.'
201                         }
202                     })
203 
204                 project.tasks.addRule('Pattern: compile<SourceSetName>JavaSettings: Displays compiler settings of a JavaCompile task.', new Action<String>() {
205                     @Override
206                     void execute(String taskName) {
207                         if (taskName.startsWith('compile') && taskName.endsWith('JavaSettings')) {
208                             String resolvedTaskName = taskName - 'Settings'
209                             project.tasks.register(taskName, JavaCompilerSettingsTask,
210                                 new Action<JavaCompilerSettingsTask>() {
211                                     @Override
212                                     void execute(JavaCompilerSettingsTask t) {
213                                         t.group = 'Insight'
214                                         t.task = resolvedTaskName
215                                         t.description = "Display Java compiler settings of the '${resolvedTaskName}' task."
216                                     }
217                                 })
218                         }
219                     }
220                 })
221 
222                 project.tasks.register('testSettings', TestSettingsTask,
223                     new Action<TestSettingsTask>() {
224                         @Override
225                         void execute(TestSettingsTask t) {
226                             t.group = 'Insight'
227                             t.description = 'Display test task settings.'
228                         }
229                     })
230 
231                 project.tasks.addRule('Pattern: <SourceSetName>TestSettings: Displays settings of a Test task.', new Action<String>() {
232                     @Override
233                     void execute(String taskName) {
234                         if (taskName.endsWith('TestSettings')) {
235                             String resolvedTaskName = taskName - 'Settings'
236                             project.tasks.register(taskName, TestSettingsTask,
237                                 new Action<TestSettingsTask>() {
238                                     @Override
239                                     void execute(TestSettingsTask t) {
240                                         t.group = 'Insight'
241                                         t.task = resolvedTaskName
242                                         t.description = "Display settings of the '${resolvedTaskName}' task."
243                                     }
244                                 })
245                         }
246                     }
247                 })
248             }
249         })
250 
251         if (isRootProject(project)) {
252             project.tasks.register('listProjects', ListProjectsTask,
253                 new Action<ListProjectsTask>() {
254                     @Override
255                     void execute(ListProjectsTask t) {
256                         t.group = 'Insight'
257                         t.description = 'List all projects.'
258                     }
259                 })
260 
261             project.tasks.register('listIncludedBuilds', ListIncludedBuildsTask,
262                 new Action<ListIncludedBuildsTask>() {
263                     @Override
264                     void execute(ListIncludedBuildsTask t) {
265                         t.group = 'Insight'
266                         t.description = 'List all included builds.'
267                     }
268                 })
269 
270             /*
271             project.gradle.addBuildListener(new BuildAdapter() {
272                 @Override
273                 void projectsEvaluated(Gradle gradle) {
274                     project.subprojects.each { Project subproject ->
275                         PluginUtils.resolveEffectiveConfig(subproject).rootReady()
276                     }
277                     PluginUtils.resolveEffectiveConfig(project).rootReady()
278                 }
279             })
280             */
281         }
282 
283         project.pluginManager.withPlugin('groovy-base', new Action<AppliedPlugin>() {
284             @Override
285             void execute(AppliedPlugin appliedPlugin) {
286                 if (project.plugins.findPlugin('groovy')) {
287                     project.tasks.register('groovyCompilerSettings', GroovyCompilerSettingsTask,
288                         new Action<GroovyCompilerSettingsTask>() {
289                             @Override
290                             void execute(GroovyCompilerSettingsTask t) {
291                                 t.group = 'Insight'
292                                 t.description = 'Display Groovy compiler settings.'
293                             }
294                         })
295 
296                     project.tasks.addRule('Pattern: compile<SourceSetName>GroovySettings: Displays compiler settings of a GroovyCompile task.', new Action<String>() {
297                         @Override
298                         void execute(String taskName) {
299                             if (taskName.startsWith('compile') && taskName.endsWith('GroovySettings')) {
300                                 String resolvedTaskName = taskName - 'Settings'
301                                 project.tasks.register(taskName, GroovyCompilerSettingsTask,
302                                     new Action<GroovyCompilerSettingsTask>() {
303                                         @Override
304                                         void execute(GroovyCompilerSettingsTask t) {
305                                             t.group = 'Insight'
306                                             t.task = resolvedTaskName
307                                             t.description = "Display Groovy compiler settings of the '${resolvedTaskName}' task."
308                                         }
309                                     })
310                             }
311                         }
312                     })
313                 }
314             }
315         })
316 
317         project.afterEvaluate {
318             project.tasks.withType(JavaExec, new Action<JavaExec>() {
319                 @Override
320                 void execute(JavaExec t) {
321                     String resolvedTaskName = t.name
322                     project.tasks.register(t.name + 'Settings', JavaExecSettingsTask,
323                         new Action<JavaExecSettingsTask>() {
324                             @Override
325                             void execute(JavaExecSettingsTask s) {
326                                 s.group = 'Insight'
327                                 s.task = resolvedTaskName
328                                 s.description = "Display settings of the '${resolvedTaskName}' task."
329                             }
330                         })
331                 }
332             })
333 
334             ProjectConfigurationExtension rootExtension = project.rootProject.extensions.findByType(ProjectConfigurationExtension)
335             ProjectConfigurationExtension extension = project.extensions.findByType(ProjectConfigurationExtension)
336             extension.normalize()
337 
338             boolean validate = PluginUtils.checkFlag(ORG_KORDAMP_GRADLE_BASE_VALIDATE, true)
339 
340             List<String> errors = []
341             if (isRootProject(project)) {
342                 // extension == rootExtension
343                 ProjectConfigurationExtension merged = extension.postMerge()
344                 if (validateerrors.addAll(merged.validate())
345                 project.extensions.create(ProjectConfigurationExtension.EFFECTIVE_CONFIG_NAME, ProjectConfigurationExtension, merged)
346             else {
347                 // parent project may not have applied kordamp.base
348                 if (rootExtension) {
349                     ProjectConfigurationExtension merged = extension.merge(rootExtension)
350                     if (validateerrors.addAll(merged.validate())
351                     project.extensions.create(ProjectConfigurationExtension.EFFECTIVE_CONFIG_NAME, ProjectConfigurationExtension, merged)
352                 else {
353                     extension = extension.postMerge()
354                     if (validateerrors.addAll(extension.validate())
355                     project.extensions.create(ProjectConfigurationExtension.EFFECTIVE_CONFIG_NAME, ProjectConfigurationExtension, extension)
356                 }
357             }
358 
359             if (validate && errors) {
360                 errors.each project.logger.error(it) }
361                 throw new GradleException("Project ${project.name} has not been properly configured")
362             }
363         }
364     }
365 
366     static void applyIfMissing(Project project) {
367         if (!project.plugins.findPlugin(BasePlugin)) {
368             project.pluginManager.apply(BasePlugin)
369         }
370     }
371 
372     static boolean isRootProject(Project project) {
373         project == project.rootProject
374     }
375 }