Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
b1c4af40
Commit
b1c4af40
authored
Oct 13, 2020
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update bootJar and bootWar to use new main class resolution mechanism
See gh-22922
parent
c078a480
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
152 additions
and
295 deletions
+152
-295
JavaPluginAction.java
.../springframework/boot/gradle/plugin/JavaPluginAction.java
+25
-81
MainClassConvention.java
...ringframework/boot/gradle/plugin/MainClassConvention.java
+0
-109
ResolveMainClassName.java
...ingframework/boot/gradle/plugin/ResolveMainClassName.java
+66
-5
WarPluginAction.java
...g/springframework/boot/gradle/plugin/WarPluginAction.java
+28
-17
GradleCompatibilityExtension.java
...ework/boot/gradle/junit/GradleCompatibilityExtension.java
+1
-2
MainClassConventionTests.java
...ramework/boot/gradle/plugin/MainClassConventionTests.java
+0
-81
AbstractBootArchiveIntegrationTests.java
...e/tasks/bundling/AbstractBootArchiveIntegrationTests.java
+22
-0
BootJarIntegrationTests-startClassIsSetByResolvingTheMainClass.gradle
...rationTests-startClassIsSetByResolvingTheMainClass.gradle
+5
-0
BootWarIntegrationTests-startClassIsSetByResolvingTheMainClass.gradle
...rationTests-startClassIsSetByResolvingTheMainClass.gradle
+5
-0
No files found.
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/JavaPluginAction.java
View file @
b1c4af40
...
...
@@ -17,15 +17,10 @@
package
org
.
springframework
.
boot
.
gradle
.
plugin
;
import
java.io.File
;
import
java.io.IOException
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Optional
;
import
java.util.Set
;
import
java.util.concurrent.Callable
;
import
org.gradle.api.Action
;
import
org.gradle.api.Plugin
;
...
...
@@ -37,13 +32,10 @@ import org.gradle.api.attributes.Bundling;
import
org.gradle.api.attributes.LibraryElements
;
import
org.gradle.api.attributes.Usage
;
import
org.gradle.api.file.FileCollection
;
import
org.gradle.api.file.RegularFileProperty
;
import
org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact
;
import
org.gradle.api.model.ObjectFactory
;
import
org.gradle.api.plugins.ApplicationPlugin
;
import
org.gradle.api.plugins.BasePlugin
;
import
org.gradle.api.plugins.Convention
;
import
org.gradle.api.plugins.JavaApplication
;
import
org.gradle.api.plugins.JavaPlugin
;
import
org.gradle.api.plugins.JavaPluginConvention
;
import
org.gradle.api.provider.Provider
;
...
...
@@ -51,7 +43,6 @@ import org.gradle.api.tasks.SourceSet;
import
org.gradle.api.tasks.TaskProvider
;
import
org.gradle.api.tasks.compile.JavaCompile
;
import
org.springframework.boot.gradle.dsl.SpringBootExtension
;
import
org.springframework.boot.gradle.tasks.bundling.BootBuildImage
;
import
org.springframework.boot.gradle.tasks.bundling.BootJar
;
import
org.springframework.boot.gradle.tasks.run.BootRun
;
...
...
@@ -86,8 +77,7 @@ final class JavaPluginAction implements PluginApplicationAction {
TaskProvider
<
BootJar
>
bootJar
=
configureBootJarTask
(
project
);
configureBootBuildImageTask
(
project
,
bootJar
);
configureArtifactPublication
(
bootJar
);
TaskProvider
<
ResolveMainClassName
>
resolveMainClassName
=
configureResolveMainClassNameTask
(
project
);
configureBootRunTask
(
project
,
resolveMainClassName
);
configureBootRunTask
(
project
);
configureUtf8Encoding
(
project
);
configureParametersCompilerArg
(
project
);
configureAdditionalMetadataLocations
(
project
);
...
...
@@ -102,59 +92,26 @@ final class JavaPluginAction implements PluginApplicationAction {
.
configure
((
task
)
->
task
.
dependsOn
(
this
.
singlePublishedArtifact
));
}
private
TaskProvider
<
ResolveMainClassName
>
configureResolveMainClassNameTask
(
Project
project
)
{
Convention
convention
=
project
.
getConvention
();
return
project
.
getTasks
().
register
(
"resolveMainClassName"
,
ResolveMainClassName
.
class
,
(
resolveMainClassName
)
->
{
resolveMainClassName
.
setClasspath
(
javaPluginConvention
(
project
).
getSourceSets
().
findByName
(
SourceSet
.
MAIN_SOURCE_SET_NAME
)
.
getRuntimeClasspath
().
filter
(
new
JarTypeFileSpec
()));
resolveMainClassName
.
getConfiguredMainClassName
().
convention
(
project
.
provider
(()
->
{
JavaApplication
javaApplication
=
convention
.
findByType
(
JavaApplication
.
class
);
String
javaApplicationMainClass
=
null
;
if
(
javaApplication
!=
null
)
{
try
{
javaApplicationMainClass
=
javaApplication
.
getMainClass
().
getOrNull
();
}
catch
(
NoSuchMethodError
ex
)
{
javaApplicationMainClass
=
javaApplication
.
getMainClassName
();
}
}
if
(
javaApplicationMainClass
!=
null
)
{
return
javaApplicationMainClass
;
}
SpringBootExtension
springBootExtension
=
project
.
getExtensions
()
.
findByType
(
SpringBootExtension
.
class
);
if
(
springBootExtension
!=
null
)
{
return
springBootExtension
.
getMainClass
().
getOrNull
();
}
return
null
;
}));
resolveMainClassName
.
getOutputFile
()
.
set
(
project
.
getLayout
().
getBuildDirectory
().
file
(
"spring-boot-main-class-name"
));
});
}
private
TaskProvider
<
BootJar
>
configureBootJarTask
(
Project
project
)
{
SourceSet
mainSourceSet
=
javaPluginConvention
(
project
).
getSourceSets
()
.
getByName
(
SourceSet
.
MAIN_SOURCE_SET_NAME
);
Configuration
developmentOnly
=
project
.
getConfigurations
()
.
getByName
(
SpringBootPlugin
.
DEVELOPMENT_ONLY_CONFIGURATION_NAME
);
Configuration
productionRuntimeClasspath
=
project
.
getConfigurations
()
.
getByName
(
SpringBootPlugin
.
PRODUCTION_RUNTIME_CLASSPATH_NAME
);
FileCollection
classpath
=
mainSourceSet
.
getRuntimeClasspath
()
.
minus
((
developmentOnly
.
minus
(
productionRuntimeClasspath
))).
filter
(
new
JarTypeFileSpec
());
TaskProvider
<
ResolveMainClassName
>
resolveMainClassName
=
ResolveMainClassName
.
registerForTask
(
SpringBootPlugin
.
BOOT_JAR_TASK_NAME
,
project
,
classpath
);
return
project
.
getTasks
().
register
(
SpringBootPlugin
.
BOOT_JAR_TASK_NAME
,
BootJar
.
class
,
(
bootJar
)
->
{
bootJar
.
setDescription
(
"Assembles an executable jar archive containing the main classes and their dependencies."
);
bootJar
.
setGroup
(
BasePlugin
.
BUILD_GROUP
);
SourceSet
mainSourceSet
=
javaPluginConvention
(
project
).
getSourceSets
()
.
getByName
(
SourceSet
.
MAIN_SOURCE_SET_NAME
);
bootJar
.
classpath
((
Callable
<
FileCollection
>)
()
->
{
Configuration
developmentOnly
=
project
.
getConfigurations
()
.
getByName
(
SpringBootPlugin
.
DEVELOPMENT_ONLY_CONFIGURATION_NAME
);
Configuration
productionRuntimeClasspath
=
project
.
getConfigurations
()
.
getByName
(
SpringBootPlugin
.
PRODUCTION_RUNTIME_CLASSPATH_NAME
);
return
mainSourceSet
.
getRuntimeClasspath
().
minus
((
developmentOnly
.
minus
(
productionRuntimeClasspath
)))
.
filter
(
new
JarTypeFileSpec
());
});
bootJar
.
getMainClass
().
convention
(
project
.
provider
(()
->
{
String
manifestStartClass
=
(
String
)
bootJar
.
getManifest
().
getAttributes
().
get
(
"Start-Class"
);
return
(
manifestStartClass
!=
null
)
?
manifestStartClass
:
new
MainClassConvention
(
project
,
bootJar:
:
getClasspath
).
call
();
}));
bootJar
.
classpath
(
classpath
);
Provider
<
String
>
manifestStartClass
=
project
.
provider
(()
->
(
String
)
bootJar
.
getManifest
().
getAttributes
().
get
(
"Start-Class"
));
bootJar
.
getMainClass
().
convention
(
resolveMainClassName
.
flatMap
((
resolver
)
->
manifestStartClass
.
isPresent
()
?
manifestStartClass
:
resolveMainClassName
.
get
().
readMainClassName
()));
});
}
...
...
@@ -172,41 +129,28 @@ final class JavaPluginAction implements PluginApplicationAction {
this
.
singlePublishedArtifact
.
addCandidate
(
artifact
);
}
private
void
configureBootRunTask
(
Project
project
,
TaskProvider
<
ResolveMainClassName
>
resolveMainClassName
)
{
private
void
configureBootRunTask
(
Project
project
)
{
FileCollection
classpath
=
javaPluginConvention
(
project
).
getSourceSets
()
.
findByName
(
SourceSet
.
MAIN_SOURCE_SET_NAME
).
getRuntimeClasspath
().
filter
(
new
JarTypeFileSpec
());
TaskProvider
<
ResolveMainClassName
>
resolveProvider
=
ResolveMainClassName
.
registerForTask
(
"bootRun"
,
project
,
classpath
);
project
.
getTasks
().
register
(
"bootRun"
,
BootRun
.
class
,
(
run
)
->
{
run
.
setDescription
(
"Runs this project as a Spring Boot application."
);
run
.
setGroup
(
ApplicationPlugin
.
APPLICATION_GROUP
);
run
.
classpath
(
javaPluginConvention
(
project
).
getSourceSets
().
findByName
(
SourceSet
.
MAIN_SOURCE_SET_NAME
)
.
getRuntimeClasspath
().
filter
(
new
JarTypeFileSpec
()));
run
.
classpath
(
classpath
);
run
.
getConventionMapping
().
map
(
"jvmArgs"
,
()
->
{
if
(
project
.
hasProperty
(
"applicationDefaultJvmArgs"
))
{
return
project
.
property
(
"applicationDefaultJvmArgs"
);
}
return
Collections
.
emptyList
();
});
run
.
dependsOn
(
resolveMainClassName
);
run
.
getInputs
().
file
(
resolveMainClassName
.
map
((
task
)
->
task
.
getOutputFile
()));
try
{
run
.
getMainClass
().
set
(
resolveMainClassName
.
flatMap
((
task
)
->
readMainClassName
(
task
.
getOutputFile
())
));
run
.
getMainClass
().
convention
(
resolveProvider
.
flatMap
(
ResolveMainClassName:
:
readMainClassName
));
}
catch
(
NoSuchMethodError
ex
)
{
run
.
getInputs
().
file
(
resolveProvider
.
map
((
task
)
->
task
.
getOutputFile
()));
run
.
conventionMapping
(
"main"
,
()
->
resolveMainClassName
.
flatMap
((
task
)
->
readMainClassName
(
task
.
getOutputFile
())).
get
());
}
});
}
private
Provider
<
String
>
readMainClassName
(
RegularFileProperty
outputFile
)
{
return
outputFile
.
map
((
file
)
->
{
Path
output
=
file
.
getAsFile
().
toPath
();
if
(!
Files
.
exists
(
output
))
{
return
null
;
}
try
{
return
new
String
(
Files
.
readAllBytes
(
output
),
StandardCharsets
.
UTF_8
);
}
catch
(
IOException
ex
)
{
throw
new
RuntimeException
(
"Failed to read main class name from '"
+
output
+
"'"
);
()
->
resolveProvider
.
flatMap
(
ResolveMainClassName:
:
readMainClassName
).
get
());
}
});
}
...
...
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/MainClassConvention.java
deleted
100644 → 0
View file @
c078a480
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed 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
*
* https://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
.
springframework
.
boot
.
gradle
.
plugin
;
import
java.io.File
;
import
java.io.IOException
;
import
java.lang.reflect.Method
;
import
java.util.Objects
;
import
java.util.concurrent.Callable
;
import
java.util.function.Supplier
;
import
org.gradle.api.InvalidUserDataException
;
import
org.gradle.api.Project
;
import
org.gradle.api.file.FileCollection
;
import
org.gradle.api.plugins.JavaApplication
;
import
org.gradle.api.provider.Property
;
import
org.springframework.boot.gradle.dsl.SpringBootExtension
;
import
org.springframework.boot.loader.tools.MainClassFinder
;
/**
* A {@link Callable} that provides a convention for the project's main class name.
*
* @author Andy Wilkinson
*/
final
class
MainClassConvention
implements
Callable
<
String
>
{
private
static
final
String
SPRING_BOOT_APPLICATION_CLASS_NAME
=
"org.springframework.boot.autoconfigure.SpringBootApplication"
;
private
final
Project
project
;
private
final
Supplier
<
FileCollection
>
classpathSupplier
;
MainClassConvention
(
Project
project
,
Supplier
<
FileCollection
>
classpathSupplier
)
{
this
.
project
=
project
;
this
.
classpathSupplier
=
classpathSupplier
;
}
@Override
public
String
call
()
throws
Exception
{
SpringBootExtension
springBootExtension
=
this
.
project
.
getExtensions
().
findByType
(
SpringBootExtension
.
class
);
if
(
springBootExtension
!=
null
)
{
String
mainClass
=
springBootExtension
.
getMainClass
().
getOrNull
();
if
(
mainClass
!=
null
)
{
return
mainClass
;
}
}
String
javaApplicationMainClass
=
getJavaApplicationMainClass
();
return
(
javaApplicationMainClass
!=
null
)
?
javaApplicationMainClass
:
resolveMainClass
();
}
@SuppressWarnings
({
"unchecked"
,
"deprecation"
})
private
String
getJavaApplicationMainClass
()
{
JavaApplication
javaApplication
=
this
.
project
.
getConvention
().
findByType
(
JavaApplication
.
class
);
if
(
javaApplication
==
null
)
{
return
null
;
}
Method
getMainClass
=
findMethod
(
JavaApplication
.
class
,
"getMainClass"
);
if
(
getMainClass
!=
null
)
{
try
{
Property
<
String
>
mainClass
=
(
Property
<
String
>)
getMainClass
.
invoke
(
javaApplication
);
return
mainClass
.
getOrElse
(
null
);
}
catch
(
Exception
ex
)
{
// Continue
}
}
return
javaApplication
.
getMainClassName
();
}
private
static
Method
findMethod
(
Class
<?>
type
,
String
name
)
{
for
(
Method
candidate
:
type
.
getMethods
())
{
if
(
candidate
.
getName
().
equals
(
name
))
{
return
candidate
;
}
}
return
null
;
}
private
String
resolveMainClass
()
{
return
this
.
classpathSupplier
.
get
().
filter
(
File:
:
isDirectory
).
getFiles
().
stream
().
map
(
this
::
findMainClass
)
.
filter
(
Objects:
:
nonNull
).
findFirst
().
orElseThrow
(()
->
new
InvalidUserDataException
(
"Main class name has not been configured and it could not be resolved"
));
}
private
String
findMainClass
(
File
file
)
{
try
{
return
MainClassFinder
.
findSingleMainClass
(
file
,
SPRING_BOOT_APPLICATION_CLASS_NAME
);
}
catch
(
IOException
ex
)
{
return
null
;
}
}
}
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ResolveMainClassName.java
View file @
b1c4af40
...
...
@@ -20,21 +20,29 @@ import java.io.File;
import
java.io.IOException
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.StandardOpenOption
;
import
java.util.Objects
;
import
org.gradle.api.DefaultTask
;
import
org.gradle.api.InvalidUserDataException
;
import
org.gradle.api.Project
;
import
org.gradle.api.Task
;
import
org.gradle.api.file.FileCollection
;
import
org.gradle.api.file.RegularFileProperty
;
import
org.gradle.api.plugins.BasePlugin
;
import
org.gradle.api.plugins.Convention
;
import
org.gradle.api.plugins.JavaApplication
;
import
org.gradle.api.provider.Property
;
import
org.gradle.api.provider.Provider
;
import
org.gradle.api.tasks.Classpath
;
import
org.gradle.api.tasks.Input
;
import
org.gradle.api.tasks.Optional
;
import
org.gradle.api.tasks.OutputFile
;
import
org.gradle.api.tasks.TaskAction
;
import
org.gradle.api.tasks.TaskProvider
;
import
org.springframework.boot.gradle.dsl.SpringBootExtension
;
import
org.springframework.boot.loader.tools.MainClassFinder
;
/**
...
...
@@ -102,11 +110,11 @@ public class ResolveMainClassName extends DefaultTask {
@TaskAction
void
resolveAndStoreMainClassName
()
throws
IOException
{
String
mainClassName
=
resolveMainClassName
();
File
outputFile
=
this
.
outputFile
.
getAsFile
().
get
();
outputFile
.
getParentFile
().
mkdirs
();
Files
.
write
(
this
.
outputFile
.
get
().
getAsFile
().
toPath
(),
mainClassName
.
getBytes
(
StandardCharsets
.
UTF_8
),
StandardOpenOption
.
WRITE
,
StandardOpenOption
.
CREATE
,
StandardOpenOption
.
TRUNCATE_EXISTING
);
String
mainClassName
=
resolveMainClassName
();
Files
.
write
(
outputFile
.
toPath
(),
mainClassName
.
getBytes
(
StandardCharsets
.
UTF_8
),
StandardOpenOption
.
WRITE
,
StandardOpenOption
.
CREATE
,
StandardOpenOption
.
TRUNCATE_EXISTING
);
}
private
String
resolveMainClassName
()
{
...
...
@@ -115,8 +123,7 @@ public class ResolveMainClassName extends DefaultTask {
return
configuredMainClass
;
}
return
getClasspath
().
filter
(
File:
:
isDirectory
).
getFiles
().
stream
().
map
(
this
::
findMainClass
)
.
filter
(
Objects:
:
nonNull
).
findFirst
().
orElseThrow
(()
->
new
InvalidUserDataException
(
"Main class name has not been configured and it could not be resolved"
));
.
filter
(
Objects:
:
nonNull
).
findFirst
().
orElse
(
""
);
}
private
String
findMainClass
(
File
file
)
{
...
...
@@ -128,4 +135,58 @@ public class ResolveMainClassName extends DefaultTask {
}
}
Provider
<
String
>
readMainClassName
()
{
return
this
.
outputFile
.
map
((
file
)
->
{
if
(
file
.
getAsFile
().
length
()
==
0
)
{
throw
new
InvalidUserDataException
(
"Main class name has not been configured and it could not be resolved"
);
}
Path
output
=
file
.
getAsFile
().
toPath
();
try
{
return
new
String
(
Files
.
readAllBytes
(
output
),
StandardCharsets
.
UTF_8
);
}
catch
(
IOException
ex
)
{
throw
new
RuntimeException
(
"Failed to read main class name from '"
+
output
+
"'"
);
}
});
}
static
TaskProvider
<
ResolveMainClassName
>
registerForTask
(
String
taskName
,
Project
project
,
FileCollection
classpath
)
{
TaskProvider
<
ResolveMainClassName
>
resolveMainClassNameProvider
=
project
.
getTasks
()
.
register
(
taskName
+
"MainClassName"
,
ResolveMainClassName
.
class
,
(
resolveMainClassName
)
->
{
Convention
convention
=
project
.
getConvention
();
resolveMainClassName
.
setDescription
(
"Resolves the name of the application's main class for the "
+
taskName
+
" task."
);
resolveMainClassName
.
setGroup
(
BasePlugin
.
BUILD_GROUP
);
resolveMainClassName
.
setClasspath
(
classpath
);
resolveMainClassName
.
getConfiguredMainClassName
().
convention
(
project
.
provider
(()
->
{
String
javaApplicationMainClass
=
getJavaApplicationMainClass
(
convention
);
if
(
javaApplicationMainClass
!=
null
)
{
return
javaApplicationMainClass
;
}
SpringBootExtension
springBootExtension
=
project
.
getExtensions
()
.
findByType
(
SpringBootExtension
.
class
);
return
springBootExtension
.
getMainClass
().
getOrNull
();
}));
resolveMainClassName
.
getOutputFile
()
.
set
(
project
.
getLayout
().
getBuildDirectory
().
file
(
taskName
+
"MainClassName"
));
});
return
resolveMainClassNameProvider
;
}
@SuppressWarnings
(
"deprecation"
)
private
static
String
getJavaApplicationMainClass
(
Convention
convention
)
{
JavaApplication
javaApplication
=
convention
.
findByType
(
JavaApplication
.
class
);
if
(
javaApplication
==
null
)
{
return
null
;
}
try
{
return
javaApplication
.
getMainClass
().
getOrNull
();
}
catch
(
NoSuchMethodError
ex
)
{
return
javaApplication
.
getMainClassName
();
}
}
}
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/WarPluginAction.java
View file @
b1c4af40
...
...
@@ -25,6 +25,9 @@ import org.gradle.api.file.FileCollection;
import
org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact
;
import
org.gradle.api.plugins.BasePlugin
;
import
org.gradle.api.plugins.WarPlugin
;
import
org.gradle.api.provider.Provider
;
import
org.gradle.api.tasks.SourceSet
;
import
org.gradle.api.tasks.SourceSetContainer
;
import
org.gradle.api.tasks.TaskProvider
;
import
org.springframework.boot.gradle.tasks.bundling.BootWar
;
...
...
@@ -60,23 +63,31 @@ class WarPluginAction implements PluginApplicationAction {
}
private
TaskProvider
<
BootWar
>
configureBootWarTask
(
Project
project
)
{
return
project
.
getTasks
().
register
(
SpringBootPlugin
.
BOOT_WAR_TASK_NAME
,
BootWar
.
class
,
(
bootWar
)
->
{
bootWar
.
setGroup
(
BasePlugin
.
BUILD_GROUP
);
bootWar
.
setDescription
(
"Assembles an executable war archive containing webapp"
+
" content, and the main classes and their dependencies."
);
bootWar
.
providedClasspath
(
providedRuntimeConfiguration
(
project
));
Configuration
developmentOnly
=
project
.
getConfigurations
()
.
getByName
(
SpringBootPlugin
.
DEVELOPMENT_ONLY_CONFIGURATION_NAME
);
Configuration
productionRuntimeClasspath
=
project
.
getConfigurations
()
.
getByName
(
SpringBootPlugin
.
PRODUCTION_RUNTIME_CLASSPATH_NAME
);
bootWar
.
setClasspath
(
bootWar
.
getClasspath
().
minus
((
developmentOnly
.
minus
(
productionRuntimeClasspath
)))
.
filter
(
new
JarTypeFileSpec
()));
bootWar
.
getMainClass
().
convention
(
project
.
provider
(()
->
{
String
manifestStartClass
=
(
String
)
bootWar
.
getManifest
().
getAttributes
().
get
(
"Start-Class"
);
return
(
manifestStartClass
!=
null
)
?
manifestStartClass
:
new
MainClassConvention
(
project
,
bootWar:
:
getClasspath
).
call
();
}));
});
Configuration
developmentOnly
=
project
.
getConfigurations
()
.
getByName
(
SpringBootPlugin
.
DEVELOPMENT_ONLY_CONFIGURATION_NAME
);
Configuration
productionRuntimeClasspath
=
project
.
getConfigurations
()
.
getByName
(
SpringBootPlugin
.
PRODUCTION_RUNTIME_CLASSPATH_NAME
);
FileCollection
classpath
=
project
.
getConvention
().
getByType
(
SourceSetContainer
.
class
)
.
getByName
(
SourceSet
.
MAIN_SOURCE_SET_NAME
).
getRuntimeClasspath
()
.
minus
(
providedRuntimeConfiguration
(
project
)).
minus
((
developmentOnly
.
minus
(
productionRuntimeClasspath
)))
.
filter
(
new
JarTypeFileSpec
());
TaskProvider
<
ResolveMainClassName
>
resolveMainClassName
=
ResolveMainClassName
.
registerForTask
(
SpringBootPlugin
.
BOOT_WAR_TASK_NAME
,
project
,
classpath
);
TaskProvider
<
BootWar
>
bootWarProvider
=
project
.
getTasks
().
register
(
SpringBootPlugin
.
BOOT_WAR_TASK_NAME
,
BootWar
.
class
,
(
bootWar
)
->
{
bootWar
.
setGroup
(
BasePlugin
.
BUILD_GROUP
);
bootWar
.
setDescription
(
"Assembles an executable war archive containing webapp"
+
" content, and the main classes and their dependencies."
);
bootWar
.
providedClasspath
(
providedRuntimeConfiguration
(
project
));
bootWar
.
setClasspath
(
classpath
);
Provider
<
String
>
manifestStartClass
=
project
.
provider
(()
->
(
String
)
bootWar
.
getManifest
().
getAttributes
().
get
(
"Start-Class"
));
bootWar
.
getMainClass
()
.
convention
(
resolveMainClassName
.
flatMap
((
resolver
)
->
manifestStartClass
.
isPresent
()
?
manifestStartClass
:
resolveMainClassName
.
get
().
readMainClassName
()));
});
bootWarProvider
.
map
((
bootWar
)
->
bootWar
.
getClasspath
());
return
bootWarProvider
;
}
private
FileCollection
providedRuntimeConfiguration
(
Project
project
)
{
...
...
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/junit/GradleCompatibilityExtension.java
View file @
b1c4af40
...
...
@@ -66,8 +66,7 @@ final class GradleCompatibilityExtension implements TestTemplateInvocationContex
boolean
configurationCache
=
AnnotationUtils
.
findAnnotation
(
context
.
getRequiredTestClass
(),
GradleCompatibility
.
class
).
get
()
.
configurationCache
();
if
(
configurationCache
&&
GradleVersion
.
version
(
version
).
compareTo
(
GradleVersion
.
version
(
"6.7-rc-1"
))
>=
0
)
{
if
(
configurationCache
&&
GradleVersion
.
version
(
version
).
compareTo
(
GradleVersion
.
version
(
"6.7"
))
>=
0
)
{
invocationContexts
.
add
(
new
GradleVersionTestTemplateInvocationContext
(
version
,
true
));
}
return
invocationContexts
.
stream
();
...
...
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/MainClassConventionTests.java
deleted
100644 → 0
View file @
c078a480
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed 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
*
* https://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
.
springframework
.
boot
.
gradle
.
plugin
;
import
java.io.File
;
import
java.io.IOException
;
import
org.gradle.api.Project
;
import
org.gradle.api.plugins.ApplicationPlugin
;
import
org.gradle.api.plugins.JavaApplication
;
import
org.gradle.testfixtures.ProjectBuilder
;
import
org.junit.jupiter.api.BeforeEach
;
import
org.junit.jupiter.api.Test
;
import
org.junit.jupiter.api.io.TempDir
;
import
org.springframework.boot.gradle.dsl.SpringBootExtension
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Integration tests for {@link MainClassConvention}.
*
* @author Andy Wilkinson
*/
class
MainClassConventionTests
{
@TempDir
File
temp
;
private
Project
project
;
private
MainClassConvention
convention
;
@BeforeEach
void
createConvention
()
throws
IOException
{
this
.
project
=
ProjectBuilder
.
builder
().
withProjectDir
(
this
.
temp
).
build
();
this
.
convention
=
new
MainClassConvention
(
this
.
project
,
()
->
null
);
}
@Test
void
javaApplicationExtensionMainClassNameIsUsed
()
throws
Exception
{
this
.
project
.
getPlugins
().
apply
(
ApplicationPlugin
.
class
);
JavaApplication
extension
=
this
.
project
.
getExtensions
().
findByType
(
JavaApplication
.
class
);
extension
.
getMainClass
().
set
(
"com.example.MainClass"
);
assertThat
(
this
.
convention
.
call
()).
isEqualTo
(
"com.example.MainClass"
);
}
@Test
void
springBootExtensionMainClassNameIsUsed
()
throws
Exception
{
SpringBootExtension
extension
=
this
.
project
.
getExtensions
().
create
(
"springBoot"
,
SpringBootExtension
.
class
,
this
.
project
);
extension
.
getMainClass
().
set
(
"com.example.MainClass"
);
assertThat
(
this
.
convention
.
call
()).
isEqualTo
(
"com.example.MainClass"
);
}
@Test
void
springBootExtensionMainClassNameIsUsedInPreferenceToJavaApplicationExtensionMainClassName
()
throws
Exception
{
this
.
project
.
getPlugins
().
apply
(
ApplicationPlugin
.
class
);
JavaApplication
javaApplication
=
this
.
project
.
getExtensions
().
findByType
(
JavaApplication
.
class
);
javaApplication
.
getMainClass
().
set
(
"com.example.JavaApplicationMainClass"
);
SpringBootExtension
extension
=
this
.
project
.
getExtensions
().
create
(
"springBoot"
,
SpringBootExtension
.
class
,
this
.
project
);
extension
.
getMainClass
().
set
(
"com.example.SpringBootExtensionMainClass"
);
assertThat
(
this
.
convention
.
call
()).
isEqualTo
(
"com.example.SpringBootExtensionMainClass"
);
}
}
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java
View file @
b1c4af40
...
...
@@ -34,6 +34,7 @@ import org.junit.jupiter.api.TestTemplate;
import
org.springframework.boot.gradle.testkit.GradleBuild
;
import
org.springframework.boot.loader.tools.FileUtils
;
import
org.springframework.util.FileSystemUtils
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
...
...
@@ -188,6 +189,27 @@ abstract class AbstractBootArchiveIntegrationTests {
}
}
@TestTemplate
void
startClassIsSetByResolvingTheMainClass
()
throws
IOException
{
copyMainClassApplication
();
assertThat
(
this
.
gradleBuild
.
build
(
this
.
taskName
).
task
(
":"
+
this
.
taskName
).
getOutcome
())
.
isEqualTo
(
TaskOutcome
.
SUCCESS
);
try
(
JarFile
jarFile
=
new
JarFile
(
new
File
(
this
.
gradleBuild
.
getProjectDir
(),
"build/libs"
).
listFiles
()[
0
]))
{
Attributes
mainAttributes
=
jarFile
.
getManifest
().
getMainAttributes
();
assertThat
(
mainAttributes
.
getValue
(
"Start-Class"
)).
isEqualTo
(
"com.example.main.CustomMainClass"
);
}
}
private
void
copyMainClassApplication
()
throws
IOException
{
copyApplication
(
"main"
);
}
private
void
copyApplication
(
String
name
)
throws
IOException
{
File
output
=
new
File
(
this
.
gradleBuild
.
getProjectDir
(),
"src/main/java/com/example/"
+
name
);
output
.
mkdirs
();
FileSystemUtils
.
copyRecursively
(
new
File
(
"src/test/java/com/example/"
+
name
),
output
);
}
private
void
createStandardJar
(
File
location
)
throws
IOException
{
createJar
(
location
,
(
attributes
)
->
{
});
...
...
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-startClassIsSetByResolvingTheMainClass.gradle
0 → 100644
View file @
b1c4af40
plugins
{
id
'java'
id
'application'
id
'org.springframework.boot'
version
'{version}'
}
spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-startClassIsSetByResolvingTheMainClass.gradle
0 → 100644
View file @
b1c4af40
plugins
{
id
'war'
id
'application'
id
'org.springframework.boot'
version
'{version}'
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment