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
9f464e9c
Commit
9f464e9c
authored
Jun 24, 2014
by
Phillip Webb
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'gh-1070'
parents
c713c809
f30b962f
Changes
29
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
650 additions
and
114 deletions
+650
-114
JarCommand.java
.../org/springframework/boot/cli/command/jar/JarCommand.java
+4
-1
build-tool-plugins.adoc
spring-boot-docs/src/main/asciidoc/build-tool-plugins.adoc
+6
-1
howto.adoc
spring-boot-docs/src/main/asciidoc/howto.adoc
+44
-0
SpringBootPluginExtension.groovy
...ingframework/boot/gradle/SpringBootPluginExtension.groovy
+7
-0
ProjectLibraries.java
...ringframework/boot/gradle/repackage/ProjectLibraries.java
+58
-22
RepackagePluginFeatures.java
...mework/boot/gradle/repackage/RepackagePluginFeatures.java
+17
-1
RepackageTask.java
.../springframework/boot/gradle/repackage/RepackageTask.java
+2
-22
FileUtils.java
...java/org/springframework/boot/loader/tools/FileUtils.java
+40
-1
JarWriter.java
...java/org/springframework/boot/loader/tools/JarWriter.java
+8
-3
Library.java
...n/java/org/springframework/boot/loader/tools/Library.java
+79
-0
LibraryCallback.java
...rg/springframework/boot/loader/tools/LibraryCallback.java
+2
-3
Repackager.java
...ava/org/springframework/boot/loader/tools/Repackager.java
+4
-3
FileUtilsTests.java
...org/springframework/boot/loader/tools/FileUtilsTests.java
+24
-0
RepackagerTests.java
...rg/springframework/boot/loader/tools/RepackagerTests.java
+18
-6
JarFileArchive.java
...g/springframework/boot/loader/archive/JarFileArchive.java
+62
-0
Handler.java
...ain/java/org/springframework/boot/loader/jar/Handler.java
+6
-25
JarEntryData.java
...ava/org/springframework/boot/loader/jar/JarEntryData.java
+7
-1
JarURLConnection.java
...org/springframework/boot/loader/jar/JarURLConnection.java
+31
-18
LaunchedURLClassLoaderTests.java
...ingframework/boot/loader/LaunchedURLClassLoaderTests.java
+24
-0
TestJarCreator.java
.../java/org/springframework/boot/loader/TestJarCreator.java
+7
-0
JarFileArchiveTests.java
...ingframework/boot/loader/archive/JarFileArchiveTests.java
+16
-1
JarFileTests.java
...ava/org/springframework/boot/loader/jar/JarFileTests.java
+12
-0
pom.xml
...s/spring-boot-maven-plugin/src/it/jar-with-unpack/pom.xml
+65
-0
SampleApplication.java
...with-unpack/src/main/java/org/test/SampleApplication.java
+8
-0
verify.groovy
...ng-boot-maven-plugin/src/it/jar-with-unpack/verify.groovy
+28
-0
ArtifactsLibraries.java
...va/org/springframework/boot/maven/ArtifactsLibraries.java
+21
-2
RepackageMojo.java
...in/java/org/springframework/boot/maven/RepackageMojo.java
+10
-1
ArtifactsLibrariesTests.java
...g/springframework/boot/maven/ArtifactsLibrariesTests.java
+31
-3
Verify.java
.../src/test/java/org/springframework/boot/maven/Verify.java
+9
-0
No files found.
spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/JarCommand.java
View file @
9f464e9c
...
@@ -56,6 +56,8 @@ import org.springframework.boot.cli.jar.PackagedSpringApplicationLauncher;
...
@@ -56,6 +56,8 @@ import org.springframework.boot.cli.jar.PackagedSpringApplicationLauncher;
import
org.springframework.boot.loader.tools.JarWriter
;
import
org.springframework.boot.loader.tools.JarWriter
;
import
org.springframework.boot.loader.tools.Layout
;
import
org.springframework.boot.loader.tools.Layout
;
import
org.springframework.boot.loader.tools.Layouts
;
import
org.springframework.boot.loader.tools.Layouts
;
import
org.springframework.boot.loader.tools.Library
;
import
org.springframework.boot.loader.tools.LibraryScope
;
import
org.springframework.core.io.Resource
;
import
org.springframework.core.io.Resource
;
import
org.springframework.core.io.support.PathMatchingResourcePatternResolver
;
import
org.springframework.core.io.support.PathMatchingResourcePatternResolver
;
import
org.springframework.util.Assert
;
import
org.springframework.util.Assert
;
...
@@ -248,7 +250,8 @@ public class JarCommand extends OptionParsingCommand {
...
@@ -248,7 +250,8 @@ public class JarCommand extends OptionParsingCommand {
private
void
addDependency
(
JarWriter
writer
,
File
dependency
)
private
void
addDependency
(
JarWriter
writer
,
File
dependency
)
throws
FileNotFoundException
,
IOException
{
throws
FileNotFoundException
,
IOException
{
if
(
dependency
.
isFile
())
{
if
(
dependency
.
isFile
())
{
writer
.
writeNestedLibrary
(
"lib/"
,
dependency
);
writer
.
writeNestedLibrary
(
"lib/"
,
new
Library
(
dependency
,
LibraryScope
.
COMPILE
));
}
}
}
}
...
...
spring-boot-docs/src/main/asciidoc/build-tool-plugins.adoc
View file @
9f464e9c
...
@@ -511,6 +511,11 @@ The following configuration options are available:
...
@@ -511,6 +511,11 @@ The following configuration options are available:
|`layout`
|`layout`
|The type of archive, corresponding to how the dependencies are laid out inside
|The type of archive, corresponding to how the dependencies are laid out inside
(defaults to a guess based on the archive type).
(defaults to a guess based on the archive type).
|`requiresUnpack`
|A list of dependencies (in the form ``groupId:artifactId'' that must be unpacked from
fat jars in order to run. Items are still packaged into the fat jar, but they will be
automatically unpacked when it runs.
|===
|===
...
@@ -619,7 +624,7 @@ Here is a typical example repackage:
...
@@ -619,7 +624,7 @@ Here is a typical example repackage:
@Override
@Override
public void doWithLibraries(LibraryCallback callback) throws IOException {
public void doWithLibraries(LibraryCallback callback) throws IOException {
// Build system specific implementation, callback for each dependency
// Build system specific implementation, callback for each dependency
// callback.library(ne
stedFile, LibraryScope.COMPILE
);
// callback.library(ne
w Library(nestedFile, LibraryScope.COMPILE)
);
}
}
});
});
----
----
...
...
spring-boot-docs/src/main/asciidoc/howto.adoc
View file @
9f464e9c
...
@@ -1618,6 +1618,50 @@ For Gradle users the steps are similar. Example:
...
@@ -1618,6 +1618,50 @@ For Gradle users the steps are similar. Example:
[[howto-extract-specific-libraries-when-an-executable-jar-runs]]
=== Extract specific libraries when an executable jar runs
Most nested libraries in an executable jar do not need to be unpacked in order to run,
however, certain libraries can have problems. For example, JRuby includes its own nested
jar support which assumes that the `jruby-complete.jar` is always directly available as a
file in its own right.
To deal with any problematic libraries, you can flag that specific nested jars should be
automatically unpacked to the ``temp folder'' when the executable jar first runs.
For example, to indicate that JRuby should be flagged for unpack using the Maven Plugin
you would add the following configuration:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<requiresUnpack>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
</dependency>
</requiresUnpack>
</configuration>
</plugin>
</plugins>
</build>
----
And to do that same with Gradle:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
springBoot {
requiresUnpack = ['org.jruby:jruby-complete']
}
----
[[howto-create-a-nonexecutable-jar]]
[[howto-create-a-nonexecutable-jar]]
=== Create a non-executable JAR with exclusions
=== Create a non-executable JAR with exclusions
Often if you have an executable and a non-executable jar as build products, the executable
Often if you have an executable and a non-executable jar as build products, the executable
...
...
spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/SpringBootPluginExtension.groovy
View file @
9f464e9c
...
@@ -107,6 +107,12 @@ public class SpringBootPluginExtension {
...
@@ -107,6 +107,12 @@ public class SpringBootPluginExtension {
(
layout
==
null
?
null
:
layout
.
layout
)
(
layout
==
null
?
null
:
layout
.
layout
)
}
}
/**
* Libraries that must be unpacked from fat jars in order to run. Use Strings in the
* form {@literal groupId:artifactId}.
*/
Set
<
String
>
requiresUnpack
;
/**
/**
* Location of an agent jar to attach to the VM when running the application with runJar task.
* Location of an agent jar to attach to the VM when running the application with runJar task.
*/
*/
...
@@ -121,4 +127,5 @@ public class SpringBootPluginExtension {
...
@@ -121,4 +127,5 @@ public class SpringBootPluginExtension {
* If exclude rules should be applied to dependencies based on the spring-dependencies-bom
* If exclude rules should be applied to dependencies based on the spring-dependencies-bom
*/
*/
boolean
applyExcludeRules
=
true
;
boolean
applyExcludeRules
=
true
;
}
}
spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/repackage/ProjectLibraries.java
View file @
9f464e9c
...
@@ -18,11 +18,17 @@ package org.springframework.boot.gradle.repackage;
...
@@ -18,11 +18,17 @@ package org.springframework.boot.gradle.repackage;
import
java.io.File
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.HashSet
;
import
java.util.LinkedHashSet
;
import
java.util.Set
;
import
org.gradle.api.Project
;
import
org.gradle.api.Project
;
import
org.gradle.api.artifacts.Configuration
;
import
org.gradle.api.artifacts.Configuration
;
import
org.gradle.api.file.FileCollection
;
import
org.gradle.api.artifacts.ModuleVersionIdentifier
;
import
org.gradle.api.artifacts.ResolvedArtifact
;
import
org.springframework.boot.gradle.SpringBootPluginExtension
;
import
org.springframework.boot.loader.tools.Libraries
;
import
org.springframework.boot.loader.tools.Libraries
;
import
org.springframework.boot.loader.tools.Library
;
import
org.springframework.boot.loader.tools.LibraryCallback
;
import
org.springframework.boot.loader.tools.LibraryCallback
;
import
org.springframework.boot.loader.tools.LibraryScope
;
import
org.springframework.boot.loader.tools.LibraryScope
;
...
@@ -36,22 +42,24 @@ class ProjectLibraries implements Libraries {
...
@@ -36,22 +42,24 @@ class ProjectLibraries implements Libraries {
private
final
Project
project
;
private
final
Project
project
;
private
final
SpringBootPluginExtension
extension
;
private
String
providedConfigurationName
=
"providedRuntime"
;
private
String
providedConfigurationName
=
"providedRuntime"
;
private
String
customConfigurationName
=
null
;
private
String
customConfigurationName
=
null
;
/**
/**
* Create a new {@link ProjectLibraries} instance of the specified {@link Project}.
* Create a new {@link ProjectLibraries} instance of the specified {@link Project}.
*
* @param project the gradle project
* @param project the gradle project
* @param extension the extension
*/
*/
public
ProjectLibraries
(
Project
project
)
{
public
ProjectLibraries
(
Project
project
,
SpringBootPluginExtension
extension
)
{
this
.
project
=
project
;
this
.
project
=
project
;
this
.
extension
=
extension
;
}
}
/**
/**
* Set the name of the provided configuration. Defaults to 'providedRuntime'.
* Set the name of the provided configuration. Defaults to 'providedRuntime'.
*
* @param providedConfigurationName the providedConfigurationName to set
* @param providedConfigurationName the providedConfigurationName to set
*/
*/
public
void
setProvidedConfigurationName
(
String
providedConfigurationName
)
{
public
void
setProvidedConfigurationName
(
String
providedConfigurationName
)
{
...
@@ -64,27 +72,20 @@ class ProjectLibraries implements Libraries {
...
@@ -64,27 +72,20 @@ class ProjectLibraries implements Libraries {
@Override
@Override
public
void
doWithLibraries
(
LibraryCallback
callback
)
throws
IOException
{
public
void
doWithLibraries
(
LibraryCallback
callback
)
throws
IOException
{
Set
<
ResolvedArtifact
>
custom
=
getArtifacts
(
this
.
customConfigurationName
);
FileCollection
custom
=
this
.
customConfigurationName
!=
null
?
this
.
project
.
getConfigurations
().
findByName
(
this
.
customConfigurationName
)
:
null
;
if
(
custom
!=
null
)
{
if
(
custom
!=
null
)
{
libraries
(
LibraryScope
.
CUSTOM
,
custom
,
callback
);
libraries
(
LibraryScope
.
CUSTOM
,
custom
,
callback
);
}
}
else
{
else
{
FileCollection
compile
=
this
.
project
.
getConfigurations
()
Set
<
ResolvedArtifact
>
compile
=
getArtifacts
(
"compile"
);
.
getByName
(
"compile"
);
FileCollection
runtime
=
this
.
project
.
getConfigurations
()
.
getByName
(
"runtime"
);
runtime
=
runtime
.
minus
(
compile
);
FileCollection
provided
=
this
.
project
.
getConfigurations
()
Set
<
ResolvedArtifact
>
runtime
=
getArtifacts
(
"runtime"
);
.
findByName
(
this
.
providedConfigurationNam
e
);
runtime
=
minus
(
runtime
,
compil
e
);
Set
<
ResolvedArtifact
>
provided
=
getArtifacts
(
this
.
providedConfigurationName
);
if
(
provided
!=
null
)
{
if
(
provided
!=
null
)
{
compile
=
compile
.
minus
(
provided
);
compile
=
minus
(
compile
,
provided
);
runtime
=
runtime
.
minus
(
provided
);
runtime
=
minus
(
runtime
,
provided
);
}
}
libraries
(
LibraryScope
.
COMPILE
,
compile
,
callback
);
libraries
(
LibraryScope
.
COMPILE
,
compile
,
callback
);
...
@@ -93,12 +94,47 @@ class ProjectLibraries implements Libraries {
...
@@ -93,12 +94,47 @@ class ProjectLibraries implements Libraries {
}
}
}
}
private
void
libraries
(
LibraryScope
scope
,
FileCollection
files
,
private
Set
<
ResolvedArtifact
>
getArtifacts
(
String
configurationName
)
{
Configuration
configuration
=
(
configurationName
==
null
?
null
:
this
.
project
.
getConfigurations
().
findByName
(
configurationName
));
return
(
configuration
==
null
?
null
:
configuration
.
getResolvedConfiguration
()
.
getResolvedArtifacts
());
}
private
Set
<
ResolvedArtifact
>
minus
(
Set
<
ResolvedArtifact
>
source
,
Set
<
ResolvedArtifact
>
toRemove
)
{
if
(
source
==
null
||
toRemove
==
null
)
{
return
source
;
}
Set
<
File
>
filesToRemove
=
new
HashSet
<
File
>();
for
(
ResolvedArtifact
artifact
:
toRemove
)
{
filesToRemove
.
add
(
artifact
.
getFile
());
}
Set
<
ResolvedArtifact
>
result
=
new
LinkedHashSet
<
ResolvedArtifact
>();
for
(
ResolvedArtifact
artifact
:
source
)
{
if
(!
toRemove
.
contains
(
artifact
.
getFile
()))
{
result
.
add
(
artifact
);
}
}
return
result
;
}
private
void
libraries
(
LibraryScope
scope
,
Set
<
ResolvedArtifact
>
artifacts
,
LibraryCallback
callback
)
throws
IOException
{
LibraryCallback
callback
)
throws
IOException
{
if
(
file
s
!=
null
)
{
if
(
artifact
s
!=
null
)
{
for
(
File
file:
file
s
)
{
for
(
ResolvedArtifact
artifact
:
artifact
s
)
{
callback
.
library
(
file
,
scope
);
callback
.
library
(
new
Library
(
artifact
.
getFile
(),
scope
,
isUnpackRequired
(
artifact
))
);
}
}
}
}
}
}
private
boolean
isUnpackRequired
(
ResolvedArtifact
artifact
)
{
if
(
this
.
extension
.
getRequiresUnpack
()
!=
null
)
{
ModuleVersionIdentifier
id
=
artifact
.
getModuleVersion
().
getId
();
return
this
.
extension
.
getRequiresUnpack
().
contains
(
id
.
getGroup
()
+
":"
+
id
.
getName
());
}
return
false
;
}
}
}
spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/repackage/RepackagePluginFeatures.java
View file @
9f464e9c
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
package
org
.
springframework
.
boot
.
gradle
.
repackage
;
package
org
.
springframework
.
boot
.
gradle
.
repackage
;
import
java.io.File
;
import
java.io.File
;
import
java.io.IOException
;
import
org.gradle.api.Action
;
import
org.gradle.api.Action
;
import
org.gradle.api.Project
;
import
org.gradle.api.Project
;
...
@@ -27,6 +28,8 @@ import org.gradle.api.plugins.BasePlugin;
...
@@ -27,6 +28,8 @@ import org.gradle.api.plugins.BasePlugin;
import
org.gradle.api.tasks.bundling.Jar
;
import
org.gradle.api.tasks.bundling.Jar
;
import
org.springframework.boot.gradle.PluginFeatures
;
import
org.springframework.boot.gradle.PluginFeatures
;
import
org.springframework.boot.gradle.SpringBootPluginExtension
;
import
org.springframework.boot.gradle.SpringBootPluginExtension
;
import
org.springframework.boot.loader.tools.Library
;
import
org.springframework.boot.loader.tools.LibraryCallback
;
import
org.springframework.util.StringUtils
;
import
org.springframework.util.StringUtils
;
/**
/**
...
@@ -124,11 +127,24 @@ public class RepackagePluginFeatures implements PluginFeatures {
...
@@ -124,11 +127,24 @@ public class RepackagePluginFeatures implements PluginFeatures {
+
classifier
+
"."
+
StringUtils
.
getFilenameExtension
(
outputName
);
+
classifier
+
"."
+
StringUtils
.
getFilenameExtension
(
outputName
);
File
outputFile
=
new
File
(
inputFile
.
getParentFile
(),
outputName
);
File
outputFile
=
new
File
(
inputFile
.
getParentFile
(),
outputName
);
this
.
task
.
getInputs
().
file
(
jarTask
);
this
.
task
.
getInputs
().
file
(
jarTask
);
this
.
task
.
getInputs
().
file
(
this
.
task
.
getDependencies
()
);
addLibraryDependencies
(
this
.
task
);
this
.
task
.
getOutputs
().
file
(
outputFile
);
this
.
task
.
getOutputs
().
file
(
outputFile
);
this
.
task
.
setOutputFile
(
outputFile
);
this
.
task
.
setOutputFile
(
outputFile
);
}
}
private
void
addLibraryDependencies
(
final
RepackageTask
task
)
{
try
{
task
.
getLibraries
().
doWithLibraries
(
new
LibraryCallback
()
{
public
void
library
(
Library
library
)
throws
IOException
{
task
.
getInputs
().
file
(
library
.
getFile
());
}
});
}
catch
(
IOException
ex
)
{
throw
new
IllegalStateException
(
ex
);
}
}
}
}
}
}
spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/repackage/RepackageTask.java
View file @
9f464e9c
...
@@ -18,8 +18,6 @@ package org.springframework.boot.gradle.repackage;
...
@@ -18,8 +18,6 @@ package org.springframework.boot.gradle.repackage;
import
java.io.File
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
import
org.gradle.api.Action
;
import
org.gradle.api.Action
;
...
@@ -29,8 +27,6 @@ import org.gradle.api.tasks.TaskAction;
...
@@ -29,8 +27,6 @@ import org.gradle.api.tasks.TaskAction;
import
org.gradle.api.tasks.TaskContainer
;
import
org.gradle.api.tasks.TaskContainer
;
import
org.gradle.api.tasks.bundling.Jar
;
import
org.gradle.api.tasks.bundling.Jar
;
import
org.springframework.boot.gradle.SpringBootPluginExtension
;
import
org.springframework.boot.gradle.SpringBootPluginExtension
;
import
org.springframework.boot.loader.tools.LibraryCallback
;
import
org.springframework.boot.loader.tools.LibraryScope
;
import
org.springframework.boot.loader.tools.Repackager
;
import
org.springframework.boot.loader.tools.Repackager
;
import
org.springframework.util.FileCopyUtils
;
import
org.springframework.util.FileCopyUtils
;
...
@@ -101,27 +97,11 @@ public class RepackageTask extends DefaultTask {
...
@@ -101,27 +97,11 @@ public class RepackageTask extends DefaultTask {
project
.
getTasks
().
withType
(
Jar
.
class
,
new
RepackageAction
(
extension
,
libraries
));
project
.
getTasks
().
withType
(
Jar
.
class
,
new
RepackageAction
(
extension
,
libraries
));
}
}
public
File
[]
getDependencies
()
{
public
ProjectLibraries
getLibraries
()
{
ProjectLibraries
libraries
=
getLibraries
();
final
List
<
File
>
files
=
new
ArrayList
<
File
>();
try
{
libraries
.
doWithLibraries
(
new
LibraryCallback
()
{
@Override
public
void
library
(
File
file
,
LibraryScope
scope
)
throws
IOException
{
files
.
add
(
file
);
}
});
}
catch
(
IOException
ex
)
{
throw
new
IllegalStateException
(
"Cannot retrieve dependencies"
,
ex
);
}
return
files
.
toArray
(
new
File
[
files
.
size
()]);
}
private
ProjectLibraries
getLibraries
()
{
Project
project
=
getProject
();
Project
project
=
getProject
();
SpringBootPluginExtension
extension
=
project
.
getExtensions
().
getByType
(
SpringBootPluginExtension
extension
=
project
.
getExtensions
().
getByType
(
SpringBootPluginExtension
.
class
);
SpringBootPluginExtension
.
class
);
ProjectLibraries
libraries
=
new
ProjectLibraries
(
project
);
ProjectLibraries
libraries
=
new
ProjectLibraries
(
project
,
extension
);
if
(
extension
.
getProvidedConfiguration
()
!=
null
)
{
if
(
extension
.
getProvidedConfiguration
()
!=
null
)
{
libraries
.
setProvidedConfigurationName
(
extension
.
getProvidedConfiguration
());
libraries
.
setProvidedConfigurationName
(
extension
.
getProvidedConfiguration
());
}
}
...
...
spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/FileUtils.java
View file @
9f464e9c
...
@@ -17,13 +17,19 @@
...
@@ -17,13 +17,19 @@
package
org
.
springframework
.
boot
.
loader
.
tools
;
package
org
.
springframework
.
boot
.
loader
.
tools
;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.security.DigestInputStream
;
import
java.security.MessageDigest
;
import
java.security.NoSuchAlgorithmException
;
/**
/**
* Utilities for manipulating files and directories in Spring Boot tooling.
* Utilities for manipulating files and directories in Spring Boot tooling.
*
*
* @author Dave Syer
* @author Dave Syer
* @author Phillip Webb
*/
*/
public
class
FileUtils
{
public
abstract
class
FileUtils
{
/**
/**
* Utility to remove duplicate files from an "output" directory if they already exist
* Utility to remove duplicate files from an "output" directory if they already exist
...
@@ -50,4 +56,37 @@ public class FileUtils {
...
@@ -50,4 +56,37 @@ public class FileUtils {
}
}
}
}
/**
* Generate a SHA.1 Hash for a given file.
* @param file the file to hash
* @return the hash value as a String
* @throws IOException
*/
public
static
String
sha1Hash
(
File
file
)
throws
IOException
{
try
{
DigestInputStream
inputStream
=
new
DigestInputStream
(
new
FileInputStream
(
file
),
MessageDigest
.
getInstance
(
"SHA-1"
));
try
{
byte
[]
buffer
=
new
byte
[
4098
];
while
(
inputStream
.
read
(
buffer
)
!=
-
1
)
{
// Read the entire stream
}
return
bytesToHex
(
inputStream
.
getMessageDigest
().
digest
());
}
finally
{
inputStream
.
close
();
}
}
catch
(
NoSuchAlgorithmException
ex
)
{
throw
new
IllegalStateException
(
ex
);
}
}
private
static
String
bytesToHex
(
byte
[]
bytes
)
{
StringBuilder
hex
=
new
StringBuilder
();
for
(
byte
b
:
bytes
)
{
hex
.
append
(
String
.
format
(
"%02x"
,
b
));
}
return
hex
.
toString
();
}
}
}
spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java
View file @
9f464e9c
...
@@ -50,7 +50,7 @@ public class JarWriter {
...
@@ -50,7 +50,7 @@ public class JarWriter {
private
static
final
String
NESTED_LOADER_JAR
=
"META-INF/loader/spring-boot-loader.jar"
;
private
static
final
String
NESTED_LOADER_JAR
=
"META-INF/loader/spring-boot-loader.jar"
;
private
static
final
int
BUFFER_SIZE
=
4096
;
private
static
final
int
BUFFER_SIZE
=
32
*
1024
;
private
final
JarOutputStream
jarOutput
;
private
final
JarOutputStream
jarOutput
;
...
@@ -122,11 +122,16 @@ public class JarWriter {
...
@@ -122,11 +122,16 @@ public class JarWriter {
/**
/**
* Write a nested library.
* Write a nested library.
* @param destination the destination of the library
* @param destination the destination of the library
* @param
file the library file
* @param
library the library
* @throws IOException if the write fails
* @throws IOException if the write fails
*/
*/
public
void
writeNestedLibrary
(
String
destination
,
File
file
)
throws
IOException
{
public
void
writeNestedLibrary
(
String
destination
,
Library
library
)
throws
IOException
{
File
file
=
library
.
getFile
();
JarEntry
entry
=
new
JarEntry
(
destination
+
file
.
getName
());
JarEntry
entry
=
new
JarEntry
(
destination
+
file
.
getName
());
if
(
library
.
isUnpackRequired
())
{
entry
.
setComment
(
"UNPACK:"
+
FileUtils
.
sha1Hash
(
file
));
}
new
CrcAndSize
(
file
).
setupStoredEntry
(
entry
);
new
CrcAndSize
(
file
).
setupStoredEntry
(
entry
);
writeEntry
(
entry
,
new
InputStreamEntryWriter
(
new
FileInputStream
(
file
),
true
));
writeEntry
(
entry
,
new
InputStreamEntryWriter
(
new
FileInputStream
(
file
),
true
));
}
}
...
...
spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Library.java
0 → 100644
View file @
9f464e9c
/*
* Copyright 2012-2014 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
*
* 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
.
springframework
.
boot
.
loader
.
tools
;
import
java.io.File
;
/**
* Encapsulates information about a single library that may be packed into the archive.
*
* @author Phillip Webb
* @since 1.1.2
* @see Libraries
*/
public
class
Library
{
private
final
File
file
;
private
final
LibraryScope
scope
;
private
final
boolean
unpackRequired
;
/**
* Create a new {@link Library}.
* @param file the source file
* @param scope the scope of the library
*/
public
Library
(
File
file
,
LibraryScope
scope
)
{
this
(
file
,
scope
,
false
);
}
/**
* Create a new {@link Library}.
* @param file the source file
* @param scope the scope of the library
* @param unpackRequired if the library needs to be unpacked before it can be used
*/
public
Library
(
File
file
,
LibraryScope
scope
,
boolean
unpackRequired
)
{
this
.
file
=
file
;
this
.
scope
=
scope
;
this
.
unpackRequired
=
unpackRequired
;
}
/**
* @return the library file
*/
public
File
getFile
()
{
return
this
.
file
;
}
/**
* @return the scope of the library
*/
public
LibraryScope
getScope
()
{
return
this
.
scope
;
}
/**
* @return if the file cannot be used directly as a nested jar and needs to be
* unpacked.
*/
public
boolean
isUnpackRequired
()
{
return
this
.
unpackRequired
;
}
}
spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/LibraryCallback.java
View file @
9f464e9c
...
@@ -28,10 +28,9 @@ public interface LibraryCallback {
...
@@ -28,10 +28,9 @@ public interface LibraryCallback {
/**
/**
* Callback to for a single library backed by a {@link File}.
* Callback to for a single library backed by a {@link File}.
* @param file the library file
* @param library the library
* @param scope the scope of the library
* @throws IOException
* @throws IOException
*/
*/
void
library
(
File
file
,
LibraryScope
scope
)
throws
IOException
;
void
library
(
Library
library
)
throws
IOException
;
}
}
spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java
View file @
9f464e9c
...
@@ -141,12 +141,13 @@ public class Repackager {
...
@@ -141,12 +141,13 @@ public class Repackager {
libraries
.
doWithLibraries
(
new
LibraryCallback
()
{
libraries
.
doWithLibraries
(
new
LibraryCallback
()
{
@Override
@Override
public
void
library
(
File
file
,
LibraryScope
scope
)
throws
IOException
{
public
void
library
(
Library
library
)
throws
IOException
{
File
file
=
library
.
getFile
();
if
(
isZip
(
file
))
{
if
(
isZip
(
file
))
{
String
destination
=
Repackager
.
this
.
layout
String
destination
=
Repackager
.
this
.
layout
.
getLibraryDestination
(
file
.
getName
(),
scope
);
.
getLibraryDestination
(
file
.
getName
(),
library
.
getScope
()
);
if
(
destination
!=
null
)
{
if
(
destination
!=
null
)
{
writer
.
writeNestedLibrary
(
destination
,
file
);
writer
.
writeNestedLibrary
(
destination
,
library
);
}
}
}
}
}
}
...
...
spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/FileUtilsTests.java
View file @
9f464e9c
...
@@ -17,22 +17,32 @@
...
@@ -17,22 +17,32 @@
package
org
.
springframework
.
boot
.
loader
.
tools
;
package
org
.
springframework
.
boot
.
loader
.
tools
;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
org.junit.Before
;
import
org.junit.Before
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.junit.rules.TemporaryFolder
;
import
org.springframework.util.FileSystemUtils
;
import
org.springframework.util.FileSystemUtils
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
/**
/**
* Tests fir {@link FileUtils}.
* Tests fir {@link FileUtils}.
*
*
* @author Dave Syer
* @author Dave Syer
* @author Phillip Webb
*/
*/
public
class
FileUtilsTests
{
public
class
FileUtilsTests
{
@Rule
public
TemporaryFolder
temporaryFolder
=
new
TemporaryFolder
();
private
File
outputDirectory
;
private
File
outputDirectory
;
private
File
originDirectory
;
private
File
originDirectory
;
...
@@ -91,4 +101,18 @@ public class FileUtilsTests {
...
@@ -91,4 +101,18 @@ public class FileUtilsTests {
assertTrue
(
file
.
exists
());
assertTrue
(
file
.
exists
());
}
}
@Test
public
void
hash
()
throws
Exception
{
File
file
=
this
.
temporaryFolder
.
newFile
();
OutputStream
outputStream
=
new
FileOutputStream
(
file
);
try
{
outputStream
.
write
(
new
byte
[]
{
1
,
2
,
3
});
}
finally
{
outputStream
.
close
();
}
assertThat
(
FileUtils
.
sha1Hash
(
file
),
equalTo
(
"7037807198c22a7d2b0807371d763779a84fdfcf"
));
}
}
}
spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java
View file @
9f464e9c
...
@@ -19,6 +19,7 @@ package org.springframework.boot.loader.tools;
...
@@ -19,6 +19,7 @@ package org.springframework.boot.loader.tools;
import
java.io.File
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.jar.Attributes
;
import
java.util.jar.Attributes
;
import
java.util.jar.JarEntry
;
import
java.util.jar.JarFile
;
import
java.util.jar.JarFile
;
import
java.util.jar.Manifest
;
import
java.util.jar.Manifest
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipEntry
;
...
@@ -33,6 +34,7 @@ import org.springframework.boot.loader.tools.sample.ClassWithoutMainMethod;
...
@@ -33,6 +34,7 @@ import org.springframework.boot.loader.tools.sample.ClassWithoutMainMethod;
import
org.springframework.util.FileCopyUtils
;
import
org.springframework.util.FileCopyUtils
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
hamcrest
.
Matchers
.
startsWith
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Matchers
.
anyString
;
import
static
org
.
mockito
.
Matchers
.
anyString
;
...
@@ -258,6 +260,7 @@ public class RepackagerTests {
...
@@ -258,6 +260,7 @@ public class RepackagerTests {
TestJarFile
libJar
=
new
TestJarFile
(
this
.
temporaryFolder
);
TestJarFile
libJar
=
new
TestJarFile
(
this
.
temporaryFolder
);
libJar
.
addClass
(
"a/b/C.class"
,
ClassWithoutMainMethod
.
class
);
libJar
.
addClass
(
"a/b/C.class"
,
ClassWithoutMainMethod
.
class
);
final
File
libJarFile
=
libJar
.
getFile
();
final
File
libJarFile
=
libJar
.
getFile
();
final
File
libJarFileToUnpack
=
libJar
.
getFile
();
final
File
libNonJarFile
=
this
.
temporaryFolder
.
newFile
();
final
File
libNonJarFile
=
this
.
temporaryFolder
.
newFile
();
FileCopyUtils
.
copy
(
new
byte
[]
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
},
libNonJarFile
);
FileCopyUtils
.
copy
(
new
byte
[]
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
},
libNonJarFile
);
this
.
testJarFile
.
addClass
(
"a/b/C.class"
,
ClassWithMainMethod
.
class
);
this
.
testJarFile
.
addClass
(
"a/b/C.class"
,
ClassWithMainMethod
.
class
);
...
@@ -266,12 +269,18 @@ public class RepackagerTests {
...
@@ -266,12 +269,18 @@ public class RepackagerTests {
repackager
.
repackage
(
new
Libraries
()
{
repackager
.
repackage
(
new
Libraries
()
{
@Override
@Override
public
void
doWithLibraries
(
LibraryCallback
callback
)
throws
IOException
{
public
void
doWithLibraries
(
LibraryCallback
callback
)
throws
IOException
{
callback
.
library
(
libJarFile
,
LibraryScope
.
COMPILE
);
callback
.
library
(
new
Library
(
libJarFile
,
LibraryScope
.
COMPILE
));
callback
.
library
(
libNonJarFile
,
LibraryScope
.
COMPILE
);
callback
.
library
(
new
Library
(
libJarFileToUnpack
,
LibraryScope
.
COMPILE
,
true
));
callback
.
library
(
new
Library
(
libNonJarFile
,
LibraryScope
.
COMPILE
));
}
}
});
});
assertThat
(
hasEntry
(
file
,
"lib/"
+
libJarFile
.
getName
()),
equalTo
(
true
));
assertThat
(
hasEntry
(
file
,
"lib/"
+
libJarFile
.
getName
()),
equalTo
(
true
));
assertThat
(
hasEntry
(
file
,
"lib/"
+
libJarFileToUnpack
.
getName
()),
equalTo
(
true
));
assertThat
(
hasEntry
(
file
,
"lib/"
+
libNonJarFile
.
getName
()),
equalTo
(
false
));
assertThat
(
hasEntry
(
file
,
"lib/"
+
libNonJarFile
.
getName
()),
equalTo
(
false
));
JarEntry
entry
=
getEntry
(
file
,
"lib/"
+
libJarFileToUnpack
.
getName
());
assertThat
(
entry
.
getComment
(),
startsWith
(
"UNPACK:"
));
assertThat
(
entry
.
getComment
().
length
(),
equalTo
(
47
));
}
}
@Test
@Test
...
@@ -290,7 +299,7 @@ public class RepackagerTests {
...
@@ -290,7 +299,7 @@ public class RepackagerTests {
repackager
.
repackage
(
new
Libraries
()
{
repackager
.
repackage
(
new
Libraries
()
{
@Override
@Override
public
void
doWithLibraries
(
LibraryCallback
callback
)
throws
IOException
{
public
void
doWithLibraries
(
LibraryCallback
callback
)
throws
IOException
{
callback
.
library
(
libJarFile
,
scope
);
callback
.
library
(
new
Library
(
libJarFile
,
scope
)
);
}
}
});
});
assertThat
(
hasEntry
(
file
,
"test/"
+
libJarFile
.
getName
()),
equalTo
(
true
));
assertThat
(
hasEntry
(
file
,
"test/"
+
libJarFile
.
getName
()),
equalTo
(
true
));
...
@@ -331,7 +340,7 @@ public class RepackagerTests {
...
@@ -331,7 +340,7 @@ public class RepackagerTests {
repackager
.
repackage
(
new
Libraries
()
{
repackager
.
repackage
(
new
Libraries
()
{
@Override
@Override
public
void
doWithLibraries
(
LibraryCallback
callback
)
throws
IOException
{
public
void
doWithLibraries
(
LibraryCallback
callback
)
throws
IOException
{
callback
.
library
(
ne
stedFile
,
LibraryScope
.
COMPILE
);
callback
.
library
(
ne
w
Library
(
nestedFile
,
LibraryScope
.
COMPILE
)
);
}
}
});
});
...
@@ -345,7 +354,6 @@ public class RepackagerTests {
...
@@ -345,7 +354,6 @@ public class RepackagerTests {
finally
{
finally
{
jarFile
.
close
();
jarFile
.
close
();
}
}
}
}
private
boolean
hasLauncherClasses
(
File
file
)
throws
IOException
{
private
boolean
hasLauncherClasses
(
File
file
)
throws
IOException
{
...
@@ -354,9 +362,13 @@ public class RepackagerTests {
...
@@ -354,9 +362,13 @@ public class RepackagerTests {
}
}
private
boolean
hasEntry
(
File
file
,
String
name
)
throws
IOException
{
private
boolean
hasEntry
(
File
file
,
String
name
)
throws
IOException
{
return
getEntry
(
file
,
name
)
!=
null
;
}
private
JarEntry
getEntry
(
File
file
,
String
name
)
throws
IOException
{
JarFile
jarFile
=
new
JarFile
(
file
);
JarFile
jarFile
=
new
JarFile
(
file
);
try
{
try
{
return
jarFile
.
get
Entry
(
name
)
!=
null
;
return
jarFile
.
get
JarEntry
(
name
)
;
}
}
finally
{
finally
{
jarFile
.
close
();
jarFile
.
close
();
...
...
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java
View file @
9f464e9c
...
@@ -17,7 +17,10 @@
...
@@ -17,7 +17,10 @@
package
org
.
springframework
.
boot
.
loader
.
archive
;
package
org
.
springframework
.
boot
.
loader
.
archive
;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.net.MalformedURLException
;
import
java.net.MalformedURLException
;
import
java.net.URL
;
import
java.net.URL
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
...
@@ -27,6 +30,7 @@ import java.util.List;
...
@@ -27,6 +30,7 @@ import java.util.List;
import
java.util.jar.JarEntry
;
import
java.util.jar.JarEntry
;
import
java.util.jar.Manifest
;
import
java.util.jar.Manifest
;
import
org.springframework.boot.loader.data.RandomAccessData.ResourceAccess
;
import
org.springframework.boot.loader.jar.JarEntryData
;
import
org.springframework.boot.loader.jar.JarEntryData
;
import
org.springframework.boot.loader.jar.JarEntryFilter
;
import
org.springframework.boot.loader.jar.JarEntryFilter
;
import
org.springframework.boot.loader.jar.JarFile
;
import
org.springframework.boot.loader.jar.JarFile
;
...
@@ -39,12 +43,23 @@ import org.springframework.boot.loader.util.AsciiBytes;
...
@@ -39,12 +43,23 @@ import org.springframework.boot.loader.util.AsciiBytes;
*/
*/
public
class
JarFileArchive
extends
Archive
{
public
class
JarFileArchive
extends
Archive
{
private
static
final
AsciiBytes
UNPACK_MARKER
=
new
AsciiBytes
(
"UNPACK:"
);
private
static
final
int
BUFFER_SIZE
=
32
*
1024
;
private
final
JarFile
jarFile
;
private
final
JarFile
jarFile
;
private
final
List
<
Entry
>
entries
;
private
final
List
<
Entry
>
entries
;
private
URL
url
;
public
JarFileArchive
(
File
file
)
throws
IOException
{
public
JarFileArchive
(
File
file
)
throws
IOException
{
this
(
file
,
null
);
}
public
JarFileArchive
(
File
file
,
URL
url
)
throws
IOException
{
this
(
new
JarFile
(
file
));
this
(
new
JarFile
(
file
));
this
.
url
=
url
;
}
}
public
JarFileArchive
(
JarFile
jarFile
)
{
public
JarFileArchive
(
JarFile
jarFile
)
{
...
@@ -58,6 +73,9 @@ public class JarFileArchive extends Archive {
...
@@ -58,6 +73,9 @@ public class JarFileArchive extends Archive {
@Override
@Override
public
URL
getUrl
()
throws
MalformedURLException
{
public
URL
getUrl
()
throws
MalformedURLException
{
if
(
this
.
url
!=
null
)
{
return
this
.
url
;
}
return
this
.
jarFile
.
getUrl
();
return
this
.
jarFile
.
getUrl
();
}
}
...
@@ -84,10 +102,54 @@ public class JarFileArchive extends Archive {
...
@@ -84,10 +102,54 @@ public class JarFileArchive extends Archive {
protected
Archive
getNestedArchive
(
Entry
entry
)
throws
IOException
{
protected
Archive
getNestedArchive
(
Entry
entry
)
throws
IOException
{
JarEntryData
data
=
((
JarFileEntry
)
entry
).
getJarEntryData
();
JarEntryData
data
=
((
JarFileEntry
)
entry
).
getJarEntryData
();
if
(
data
.
getComment
().
startsWith
(
UNPACK_MARKER
))
{
return
getUnpackedNestedArchive
(
data
);
}
JarFile
jarFile
=
this
.
jarFile
.
getNestedJarFile
(
data
);
JarFile
jarFile
=
this
.
jarFile
.
getNestedJarFile
(
data
);
return
new
JarFileArchive
(
jarFile
);
return
new
JarFileArchive
(
jarFile
);
}
}
private
Archive
getUnpackedNestedArchive
(
JarEntryData
data
)
throws
IOException
{
AsciiBytes
hash
=
data
.
getComment
().
substring
(
UNPACK_MARKER
.
length
());
String
name
=
data
.
getName
().
toString
();
if
(
name
.
lastIndexOf
(
"/"
)
!=
-
1
)
{
name
=
name
.
substring
(
name
.
lastIndexOf
(
"/"
)
+
1
);
}
File
file
=
new
File
(
getTempUnpackFolder
(),
hash
.
toString
()
+
"-"
+
name
);
if
(!
file
.
exists
()
||
file
.
length
()
!=
data
.
getSize
())
{
unpack
(
data
,
file
);
}
return
new
JarFileArchive
(
file
,
file
.
toURI
().
toURL
());
}
private
File
getTempUnpackFolder
()
{
File
tempFolder
=
new
File
(
System
.
getProperty
(
"java.io.tmpdir"
));
File
unpackFolder
=
new
File
(
tempFolder
,
"spring-boot-libs"
);
unpackFolder
.
mkdirs
();
return
unpackFolder
;
}
private
void
unpack
(
JarEntryData
data
,
File
file
)
throws
IOException
{
InputStream
inputStream
=
data
.
getData
().
getInputStream
(
ResourceAccess
.
ONCE
);
try
{
OutputStream
outputStream
=
new
FileOutputStream
(
file
);
try
{
byte
[]
buffer
=
new
byte
[
BUFFER_SIZE
];
int
bytesRead
=
-
1
;
while
((
bytesRead
=
inputStream
.
read
(
buffer
))
!=
-
1
)
{
outputStream
.
write
(
buffer
,
0
,
bytesRead
);
}
outputStream
.
flush
();
}
finally
{
outputStream
.
close
();
}
}
finally
{
inputStream
.
close
();
}
}
@Override
@Override
public
Archive
getFilteredArchive
(
final
EntryRenameFilter
filter
)
throws
IOException
{
public
Archive
getFilteredArchive
(
final
EntryRenameFilter
filter
)
throws
IOException
{
JarFile
filteredJar
=
this
.
jarFile
.
getFilteredJarFile
(
new
JarEntryFilter
()
{
JarFile
filteredJar
=
this
.
jarFile
.
getFilteredJarFile
(
new
JarEntryFilter
()
{
...
...
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/Handler.java
View file @
9f464e9c
...
@@ -83,7 +83,7 @@ public class Handler extends URLStreamHandler {
...
@@ -83,7 +83,7 @@ public class Handler extends URLStreamHandler {
return
new
JarURLConnection
(
url
,
this
.
jarFile
);
return
new
JarURLConnection
(
url
,
this
.
jarFile
);
}
}
try
{
try
{
return
new
JarURLConnection
(
url
,
getJarFileFromUrl
(
url
));
return
new
JarURLConnection
(
url
,
get
Root
JarFileFromUrl
(
url
));
}
}
catch
(
Exception
ex
)
{
catch
(
Exception
ex
)
{
return
openFallbackConnection
(
url
,
ex
);
return
openFallbackConnection
(
url
,
ex
);
...
@@ -96,10 +96,11 @@ public class Handler extends URLStreamHandler {
...
@@ -96,10 +96,11 @@ public class Handler extends URLStreamHandler {
return
openConnection
(
getFallbackHandler
(),
url
);
return
openConnection
(
getFallbackHandler
(),
url
);
}
}
catch
(
Exception
ex
)
{
catch
(
Exception
ex
)
{
this
.
logger
.
log
(
Level
.
WARNING
,
"Unable to open fallback handler"
,
ex
);
if
(
reason
instanceof
IOException
)
{
if
(
reason
instanceof
IOException
)
{
this
.
logger
.
log
(
Level
.
FINEST
,
"Unable to open fallback handler"
,
ex
);
throw
(
IOException
)
reason
;
throw
(
IOException
)
reason
;
}
}
this
.
logger
.
log
(
Level
.
WARNING
,
"Unable to open fallback handler"
,
ex
);
if
(
reason
instanceof
RuntimeException
)
{
if
(
reason
instanceof
RuntimeException
)
{
throw
(
RuntimeException
)
reason
;
throw
(
RuntimeException
)
reason
;
}
}
...
@@ -111,7 +112,6 @@ public class Handler extends URLStreamHandler {
...
@@ -111,7 +112,6 @@ public class Handler extends URLStreamHandler {
if
(
this
.
fallbackHandler
!=
null
)
{
if
(
this
.
fallbackHandler
!=
null
)
{
return
this
.
fallbackHandler
;
return
this
.
fallbackHandler
;
}
}
for
(
String
handlerClassName
:
FALLBACK_HANDLERS
)
{
for
(
String
handlerClassName
:
FALLBACK_HANDLERS
)
{
try
{
try
{
Class
<?>
handlerClass
=
Class
.
forName
(
handlerClassName
);
Class
<?>
handlerClass
=
Class
.
forName
(
handlerClassName
);
...
@@ -135,24 +135,14 @@ public class Handler extends URLStreamHandler {
...
@@ -135,24 +135,14 @@ public class Handler extends URLStreamHandler {
return
(
URLConnection
)
OPEN_CONNECTION_METHOD
.
invoke
(
handler
,
url
);
return
(
URLConnection
)
OPEN_CONNECTION_METHOD
.
invoke
(
handler
,
url
);
}
}
public
JarFile
getJarFileFromUrl
(
URL
url
)
throws
IOException
{
public
JarFile
getRootJarFileFromUrl
(
URL
url
)
throws
IOException
{
String
spec
=
url
.
getFile
();
String
spec
=
url
.
getFile
();
int
separatorIndex
=
spec
.
indexOf
(
SEPARATOR
);
int
separatorIndex
=
spec
.
indexOf
(
SEPARATOR
);
if
(
separatorIndex
==
-
1
)
{
if
(
separatorIndex
==
-
1
)
{
throw
new
MalformedURLException
(
"Jar URL does not contain !/ separator"
);
throw
new
MalformedURLException
(
"Jar URL does not contain !/ separator"
);
}
}
String
name
=
spec
.
substring
(
0
,
separatorIndex
);
JarFile
jar
=
null
;
return
getRootJarFile
(
name
);
while
(
separatorIndex
!=
-
1
)
{
String
name
=
spec
.
substring
(
0
,
separatorIndex
);
jar
=
(
jar
==
null
?
getRootJarFile
(
name
)
:
getNestedJarFile
(
jar
,
name
));
spec
=
spec
.
substring
(
separatorIndex
+
SEPARATOR
.
length
());
separatorIndex
=
spec
.
indexOf
(
SEPARATOR
);
}
return
jar
;
}
}
private
JarFile
getRootJarFile
(
String
name
)
throws
IOException
{
private
JarFile
getRootJarFile
(
String
name
)
throws
IOException
{
...
@@ -175,15 +165,6 @@ public class Handler extends URLStreamHandler {
...
@@ -175,15 +165,6 @@ public class Handler extends URLStreamHandler {
}
}
}
}
private
JarFile
getNestedJarFile
(
JarFile
jarFile
,
String
name
)
throws
IOException
{
JarEntry
jarEntry
=
jarFile
.
getJarEntry
(
name
);
if
(
jarEntry
==
null
)
{
throw
new
IOException
(
"Unable to find nested jar '"
+
name
+
"' from '"
+
jarFile
+
"'"
);
}
return
jarFile
.
getNestedJarFile
(
jarEntry
);
}
/**
/**
* Add the given {@link JarFile} to the root file cache.
* Add the given {@link JarFile} to the root file cache.
* @param sourceFile the source file to add
* @param sourceFile the source file to add
...
...
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarEntryData.java
View file @
9f464e9c
...
@@ -93,7 +93,13 @@ public final class JarEntryData {
...
@@ -93,7 +93,13 @@ public final class JarEntryData {
return
inputStream
;
return
inputStream
;
}
}
RandomAccessData
getData
()
throws
IOException
{
/**
* @return the underlying {@link RandomAccessData} for this entry. Generally this
* method should not be called directly and instead data should be accessed via
* {@link JarFile#getInputStream(ZipEntry)}.
* @throws IOException
*/
public
RandomAccessData
getData
()
throws
IOException
{
if
(
this
.
data
==
null
)
{
if
(
this
.
data
==
null
)
{
// aspectjrt-1.7.4.jar has a different ext bytes length in the
// aspectjrt-1.7.4.jar has a different ext bytes length in the
// local directory to the central directory. We need to re-read
// local directory to the central directory. We need to re-read
...
...
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java
View file @
9f464e9c
...
@@ -61,8 +61,6 @@ class JarURLConnection extends java.net.JarURLConnection {
...
@@ -61,8 +61,6 @@ class JarURLConnection extends java.net.JarURLConnection {
private
static
ThreadLocal
<
Boolean
>
useFastExceptions
=
new
ThreadLocal
<
Boolean
>();
private
static
ThreadLocal
<
Boolean
>
useFastExceptions
=
new
ThreadLocal
<
Boolean
>();
private
final
String
jarFileUrlSpec
;
private
final
JarFile
jarFile
;
private
final
JarFile
jarFile
;
private
JarEntryData
jarEntryData
;
private
JarEntryData
jarEntryData
;
...
@@ -71,19 +69,26 @@ class JarURLConnection extends java.net.JarURLConnection {
...
@@ -71,19 +69,26 @@ class JarURLConnection extends java.net.JarURLConnection {
private
JarEntryName
jarEntryName
;
private
JarEntryName
jarEntryName
;
protected
JarURLConnection
(
URL
url
,
JarFile
jarFile
)
throws
MalformedURL
Exception
{
protected
JarURLConnection
(
URL
url
,
JarFile
jarFile
)
throws
IO
Exception
{
// What we pass to super is ultimately ignored
// What we pass to super is ultimately ignored
super
(
EMPTY_JAR_URL
);
super
(
EMPTY_JAR_URL
);
this
.
url
=
url
;
this
.
url
=
url
;
String
spec
=
url
.
getFile
().
substring
(
jarFile
.
getUrl
().
getFile
().
length
());
int
separator
;
while
((
separator
=
spec
.
indexOf
(
SEPARATOR
))
>
0
)
{
jarFile
=
getNestedJarFile
(
jarFile
,
spec
.
substring
(
0
,
separator
));
spec
=
spec
.
substring
(
separator
+
SEPARATOR
.
length
());
}
this
.
jarFile
=
jarFile
;
this
.
jarFile
=
jarFile
;
String
spec
=
url
.
getFile
();
this
.
jarEntryName
=
getJarEntryName
(
spec
);
int
separator
=
spec
.
lastIndexOf
(
SEPARATOR
);
}
if
(
separator
==
-
1
)
{
throw
new
MalformedURLException
(
"no "
+
SEPARATOR
+
" found in url spec:"
private
JarFile
getNestedJarFile
(
JarFile
jarFile
,
String
name
)
throws
IOException
{
+
spec
);
JarEntry
jarEntry
=
jarFile
.
getJarEntry
(
name
);
if
(
jarEntry
==
null
)
{
throwFileNotFound
(
jarEntry
,
jarFile
);
}
}
this
.
jarFileUrlSpec
=
spec
.
substring
(
0
,
separator
);
return
jarFile
.
getNestedJarFile
(
jarEntry
);
this
.
jarEntryName
=
getJarEntryName
(
spec
.
substring
(
separator
+
2
));
}
}
private
JarEntryName
getJarEntryName
(
String
spec
)
{
private
JarEntryName
getJarEntryName
(
String
spec
)
{
...
@@ -99,16 +104,20 @@ class JarURLConnection extends java.net.JarURLConnection {
...
@@ -99,16 +104,20 @@ class JarURLConnection extends java.net.JarURLConnection {
this
.
jarEntryData
=
this
.
jarFile
.
getJarEntryData
(
this
.
jarEntryName
this
.
jarEntryData
=
this
.
jarFile
.
getJarEntryData
(
this
.
jarEntryName
.
asAsciiBytes
());
.
asAsciiBytes
());
if
(
this
.
jarEntryData
==
null
)
{
if
(
this
.
jarEntryData
==
null
)
{
if
(
Boolean
.
TRUE
.
equals
(
useFastExceptions
.
get
()))
{
throwFileNotFound
(
this
.
jarEntryName
,
this
.
jarFile
);
throw
FILE_NOT_FOUND_EXCEPTION
;
}
throw
new
FileNotFoundException
(
"JAR entry "
+
this
.
jarEntryName
+
" not found in "
+
this
.
jarFile
.
getName
());
}
}
}
}
this
.
connected
=
true
;
this
.
connected
=
true
;
}
}
private
void
throwFileNotFound
(
Object
entry
,
JarFile
jarFile
)
throws
FileNotFoundException
{
if
(
Boolean
.
TRUE
.
equals
(
useFastExceptions
.
get
()))
{
throw
FILE_NOT_FOUND_EXCEPTION
;
}
throw
new
FileNotFoundException
(
"JAR entry "
+
entry
+
" not found in "
+
jarFile
.
getName
());
}
@Override
@Override
public
Manifest
getManifest
()
throws
IOException
{
public
Manifest
getManifest
()
throws
IOException
{
try
{
try
{
...
@@ -135,10 +144,14 @@ class JarURLConnection extends java.net.JarURLConnection {
...
@@ -135,10 +144,14 @@ class JarURLConnection extends java.net.JarURLConnection {
private
URL
buildJarFileUrl
()
{
private
URL
buildJarFileUrl
()
{
try
{
try
{
if
(
this
.
jarFileUrlSpec
.
indexOf
(
SEPARATOR
)
==
-
1
)
{
String
spec
=
this
.
jarFile
.
getUrl
().
getFile
();
return
new
URL
(
this
.
jarFileUrlSpec
);
if
(
spec
.
endsWith
(
SEPARATOR
))
{
spec
=
spec
.
substring
(
0
,
spec
.
length
()
-
SEPARATOR
.
length
());
}
if
(
spec
.
indexOf
(
SEPARATOR
)
==
-
1
)
{
return
new
URL
(
spec
);
}
}
return
new
URL
(
"jar:"
+
this
.
jarFileUrlS
pec
);
return
new
URL
(
"jar:"
+
s
pec
);
}
}
catch
(
MalformedURLException
ex
)
{
catch
(
MalformedURLException
ex
)
{
throw
new
IllegalStateException
(
ex
);
throw
new
IllegalStateException
(
ex
);
...
...
spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/LaunchedURLClassLoaderTests.java
View file @
9f464e9c
...
@@ -16,21 +16,32 @@
...
@@ -16,21 +16,32 @@
package
org
.
springframework
.
boot
.
loader
;
package
org
.
springframework
.
boot
.
loader
;
import
java.io.File
;
import
java.net.URL
;
import
java.net.URL
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.junit.rules.TemporaryFolder
;
import
org.springframework.boot.loader.jar.JarFile
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
/**
/**
* Tests for {@link LaunchedURLClassLoader}.
* Tests for {@link LaunchedURLClassLoader}.
*
*
* @author Dave Syer
* @author Dave Syer
* @author Phillip Webb
*/
*/
@SuppressWarnings
(
"resource"
)
public
class
LaunchedURLClassLoaderTests
{
public
class
LaunchedURLClassLoaderTests
{
@Rule
public
TemporaryFolder
temporaryFolder
=
new
TemporaryFolder
();
@Test
@Test
public
void
resolveResourceFromWindowsFilesystem
()
throws
Exception
{
public
void
resolveResourceFromWindowsFilesystem
()
throws
Exception
{
// This path is invalid - it should return null even on Windows.
// This path is invalid - it should return null even on Windows.
...
@@ -76,4 +87,17 @@ public class LaunchedURLClassLoaderTests {
...
@@ -76,4 +87,17 @@ public class LaunchedURLClassLoaderTests {
assertTrue
(
loader
.
getResources
(
""
).
hasMoreElements
());
assertTrue
(
loader
.
getResources
(
""
).
hasMoreElements
());
}
}
@Test
public
void
resolveFromNested
()
throws
Exception
{
File
file
=
this
.
temporaryFolder
.
newFile
();
TestJarCreator
.
createTestJar
(
file
);
JarFile
jarFile
=
new
JarFile
(
file
);
URL
url
=
jarFile
.
getUrl
();
LaunchedURLClassLoader
loader
=
new
LaunchedURLClassLoader
(
new
URL
[]
{
url
},
null
);
URL
resource
=
loader
.
getResource
(
"nested.jar!/3.dat"
);
assertThat
(
resource
.
toString
(),
equalTo
(
url
+
"nested.jar!/3.dat"
));
assertThat
(
resource
.
openConnection
().
getInputStream
().
read
(),
equalTo
(
3
));
}
}
}
spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/TestJarCreator.java
View file @
9f464e9c
...
@@ -35,6 +35,10 @@ import java.util.zip.ZipEntry;
...
@@ -35,6 +35,10 @@ import java.util.zip.ZipEntry;
public
abstract
class
TestJarCreator
{
public
abstract
class
TestJarCreator
{
public
static
void
createTestJar
(
File
file
)
throws
Exception
{
public
static
void
createTestJar
(
File
file
)
throws
Exception
{
createTestJar
(
file
,
false
);
}
public
static
void
createTestJar
(
File
file
,
boolean
unpackNested
)
throws
Exception
{
FileOutputStream
fileOutputStream
=
new
FileOutputStream
(
file
);
FileOutputStream
fileOutputStream
=
new
FileOutputStream
(
file
);
JarOutputStream
jarOutputStream
=
new
JarOutputStream
(
fileOutputStream
);
JarOutputStream
jarOutputStream
=
new
JarOutputStream
(
fileOutputStream
);
try
{
try
{
...
@@ -50,6 +54,9 @@ public abstract class TestJarCreator {
...
@@ -50,6 +54,9 @@ public abstract class TestJarCreator {
byte
[]
nestedJarData
=
getNestedJarData
();
byte
[]
nestedJarData
=
getNestedJarData
();
nestedEntry
.
setSize
(
nestedJarData
.
length
);
nestedEntry
.
setSize
(
nestedJarData
.
length
);
nestedEntry
.
setCompressedSize
(
nestedJarData
.
length
);
nestedEntry
.
setCompressedSize
(
nestedJarData
.
length
);
if
(
unpackNested
)
{
nestedEntry
.
setComment
(
"UNPACK:0000000000000000000000000000000000000000"
);
}
CRC32
crc32
=
new
CRC32
();
CRC32
crc32
=
new
CRC32
();
crc32
.
update
(
nestedJarData
);
crc32
.
update
(
nestedJarData
);
nestedEntry
.
setCrc
(
crc32
.
getValue
());
nestedEntry
.
setCrc
(
crc32
.
getValue
());
...
...
spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/JarFileArchiveTests.java
View file @
9f464e9c
...
@@ -29,7 +29,9 @@ import org.springframework.boot.loader.TestJarCreator;
...
@@ -29,7 +29,9 @@ import org.springframework.boot.loader.TestJarCreator;
import
org.springframework.boot.loader.archive.Archive.Entry
;
import
org.springframework.boot.loader.archive.Archive.Entry
;
import
org.springframework.boot.loader.util.AsciiBytes
;
import
org.springframework.boot.loader.util.AsciiBytes
;
import
static
org
.
hamcrest
.
Matchers
.
endsWith
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
hamcrest
.
Matchers
.
startsWith
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertThat
;
/**
/**
...
@@ -48,8 +50,12 @@ public class JarFileArchiveTests {
...
@@ -48,8 +50,12 @@ public class JarFileArchiveTests {
@Before
@Before
public
void
setup
()
throws
Exception
{
public
void
setup
()
throws
Exception
{
setup
(
false
);
}
private
void
setup
(
boolean
unpackNested
)
throws
Exception
{
this
.
rootJarFile
=
this
.
temporaryFolder
.
newFile
();
this
.
rootJarFile
=
this
.
temporaryFolder
.
newFile
();
TestJarCreator
.
createTestJar
(
this
.
rootJarFile
);
TestJarCreator
.
createTestJar
(
this
.
rootJarFile
,
unpackNested
);
this
.
archive
=
new
JarFileArchive
(
this
.
rootJarFile
);
this
.
archive
=
new
JarFileArchive
(
this
.
rootJarFile
);
}
}
...
@@ -80,6 +86,15 @@ public class JarFileArchiveTests {
...
@@ -80,6 +86,15 @@ public class JarFileArchiveTests {
equalTo
(
"jar:file:"
+
this
.
rootJarFile
.
getPath
()
+
"!/nested.jar!/"
));
equalTo
(
"jar:file:"
+
this
.
rootJarFile
.
getPath
()
+
"!/nested.jar!/"
));
}
}
@Test
public
void
getNestedUnpackedArchive
()
throws
Exception
{
setup
(
true
);
Entry
entry
=
getEntriesMap
(
this
.
archive
).
get
(
"nested.jar"
);
Archive
nested
=
this
.
archive
.
getNestedArchive
(
entry
);
assertThat
(
nested
.
getUrl
().
toString
(),
startsWith
(
"file:"
));
assertThat
(
nested
.
getUrl
().
toString
(),
endsWith
(
".jar"
));
}
@Test
@Test
public
void
getFilteredArchive
()
throws
Exception
{
public
void
getFilteredArchive
()
throws
Exception
{
Archive
filteredArchive
=
this
.
archive
Archive
filteredArchive
=
this
.
archive
...
...
spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarFileTests.java
View file @
9f464e9c
...
@@ -408,4 +408,16 @@ public class JarFileTests {
...
@@ -408,4 +408,16 @@ public class JarFileTests {
getEntries
();
getEntries
();
getNestedJarFile
();
getNestedJarFile
();
}
}
@Test
public
void
cannotLoadMissingJar
()
throws
Exception
{
// relates to gh-1070
JarFile
nestedJarFile
=
this
.
jarFile
.
getNestedJarFile
(
this
.
jarFile
.
getEntry
(
"nested.jar"
));
URL
nestedUrl
=
nestedJarFile
.
getUrl
();
URL
url
=
new
URL
(
nestedUrl
,
nestedJarFile
.
getUrl
()
+
"missing.jar!/3.dat"
);
this
.
thrown
.
expect
(
FileNotFoundException
.
class
);
url
.
openConnection
().
getInputStream
();
}
}
}
spring-boot-tools/spring-boot-maven-plugin/src/it/jar-with-unpack/pom.xml
0 → 100644
View file @
9f464e9c
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
org.springframework.boot.maven.it
</groupId>
<artifactId>
jar-with-unpack
</artifactId>
<version>
0.0.1.BUILD-SNAPSHOT
</version>
<properties>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>
@project.groupId@
</groupId>
<artifactId>
@project.artifactId@
</artifactId>
<version>
@project.version@
</version>
<executions>
<execution>
<goals>
<goal>
repackage
</goal>
</goals>
<configuration>
<requiresUnpack>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-core
</artifactId>
</dependency>
</requiresUnpack>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-jar-plugin
</artifactId>
<version>
2.4
</version>
<configuration>
<archive>
<manifestEntries>
<Not-Used>
Foo
</Not-Used>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-context
</artifactId>
<version>
4.0.5.RELEASE
</version>
</dependency>
<dependency>
<groupId>
javax.servlet
</groupId>
<artifactId>
javax.servlet-api
</artifactId>
<version>
3.0.1
</version>
<scope>
provided
</scope>
</dependency>
<dependency>
<groupId>
log4j
</groupId>
<artifactId>
log4j
</artifactId>
<version>
1.2.17
</version>
</dependency>
</dependencies>
</project>
spring-boot-tools/spring-boot-maven-plugin/src/it/jar-with-unpack/src/main/java/org/test/SampleApplication.java
0 → 100644
View file @
9f464e9c
package
org
.
test
;
public
class
SampleApplication
{
public
static
void
main
(
String
[]
args
)
{
}
}
spring-boot-tools/spring-boot-maven-plugin/src/it/jar-with-unpack/verify.groovy
0 → 100644
View file @
9f464e9c
/*
* Copyright 2012-2014 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
*
* 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.
*/
import
java.io.*
;
import
org.springframework.boot.maven.*
;
File
f
=
new
File
(
basedir
,
"target/jar-with-unpack-0.0.1.BUILD-SNAPSHOT.jar"
);
new
Verify
.
JarArchiveVerification
(
f
,
Verify
.
SAMPLE_APP
)
{
@Override
protected
void
verifyZipEntries
(
Verify
.
ArchiveVerifier
verifier
)
throws
Exception
{
super
.
verifyZipEntries
(
verifier
)
verifier
.
hasUnpackEntry
(
"lib/spring-core-4.0.5.RELEASE.jar"
)
verifier
.
hasNonUnpackEntry
(
"lib/spring-context-4.0.5.RELEASE.jar"
)
}
}.
verify
();
spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java
View file @
9f464e9c
...
@@ -17,13 +17,16 @@
...
@@ -17,13 +17,16 @@
package
org
.
springframework
.
boot
.
maven
;
package
org
.
springframework
.
boot
.
maven
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.Set
;
import
org.apache.maven.artifact.Artifact
;
import
org.apache.maven.artifact.Artifact
;
import
org.apache.maven.model.Dependency
;
import
org.springframework.boot.loader.tools.Libraries
;
import
org.springframework.boot.loader.tools.Libraries
;
import
org.springframework.boot.loader.tools.Library
;
import
org.springframework.boot.loader.tools.LibraryCallback
;
import
org.springframework.boot.loader.tools.LibraryCallback
;
import
org.springframework.boot.loader.tools.LibraryScope
;
import
org.springframework.boot.loader.tools.LibraryScope
;
...
@@ -46,8 +49,11 @@ public class ArtifactsLibraries implements Libraries {
...
@@ -46,8 +49,11 @@ public class ArtifactsLibraries implements Libraries {
private
final
Set
<
Artifact
>
artifacts
;
private
final
Set
<
Artifact
>
artifacts
;
public
ArtifactsLibraries
(
Set
<
Artifact
>
artifacts
)
{
private
final
Collection
<
Dependency
>
unpacks
;
public
ArtifactsLibraries
(
Set
<
Artifact
>
artifacts
,
Collection
<
Dependency
>
unpacks
)
{
this
.
artifacts
=
artifacts
;
this
.
artifacts
=
artifacts
;
this
.
unpacks
=
unpacks
;
}
}
@Override
@Override
...
@@ -55,8 +61,21 @@ public class ArtifactsLibraries implements Libraries {
...
@@ -55,8 +61,21 @@ public class ArtifactsLibraries implements Libraries {
for
(
Artifact
artifact
:
this
.
artifacts
)
{
for
(
Artifact
artifact
:
this
.
artifacts
)
{
LibraryScope
scope
=
SCOPES
.
get
(
artifact
.
getScope
());
LibraryScope
scope
=
SCOPES
.
get
(
artifact
.
getScope
());
if
(
scope
!=
null
&&
artifact
.
getFile
()
!=
null
)
{
if
(
scope
!=
null
&&
artifact
.
getFile
()
!=
null
)
{
callback
.
library
(
artifact
.
getFile
(),
scope
);
callback
.
library
(
new
Library
(
artifact
.
getFile
(),
scope
,
isUnpackRequired
(
artifact
)));
}
}
}
private
boolean
isUnpackRequired
(
Artifact
artifact
)
{
if
(
this
.
unpacks
!=
null
)
{
for
(
Dependency
unpack
:
this
.
unpacks
)
{
if
(
artifact
.
getGroupId
().
equals
(
unpack
.
getGroupId
())
&&
artifact
.
getArtifactId
().
equals
(
unpack
.
getArtifactId
()))
{
return
true
;
}
}
}
}
}
return
false
;
}
}
}
}
spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java
View file @
9f464e9c
...
@@ -18,11 +18,13 @@ package org.springframework.boot.maven;
...
@@ -18,11 +18,13 @@ package org.springframework.boot.maven;
import
java.io.File
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Set
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
import
java.util.jar.JarFile
;
import
java.util.jar.JarFile
;
import
org.apache.maven.artifact.Artifact
;
import
org.apache.maven.artifact.Artifact
;
import
org.apache.maven.model.Dependency
;
import
org.apache.maven.plugin.MojoExecutionException
;
import
org.apache.maven.plugin.MojoExecutionException
;
import
org.apache.maven.plugin.MojoFailureException
;
import
org.apache.maven.plugin.MojoFailureException
;
import
org.apache.maven.plugins.annotations.Component
;
import
org.apache.maven.plugins.annotations.Component
;
...
@@ -108,6 +110,13 @@ public class RepackageMojo extends AbstractDependencyFilterMojo {
...
@@ -108,6 +110,13 @@ public class RepackageMojo extends AbstractDependencyFilterMojo {
@Parameter
@Parameter
private
LayoutType
layout
;
private
LayoutType
layout
;
/**
* A list of the libraries that must be unpacked from fat jars in order to run.
* @since 1.1
*/
@Parameter
private
List
<
Dependency
>
requiresUnpack
;
@Override
@Override
public
void
execute
()
throws
MojoExecutionException
,
MojoFailureException
{
public
void
execute
()
throws
MojoExecutionException
,
MojoFailureException
{
if
(
this
.
project
.
getPackaging
().
equals
(
"pom"
))
{
if
(
this
.
project
.
getPackaging
().
equals
(
"pom"
))
{
...
@@ -144,7 +153,7 @@ public class RepackageMojo extends AbstractDependencyFilterMojo {
...
@@ -144,7 +153,7 @@ public class RepackageMojo extends AbstractDependencyFilterMojo {
Set
<
Artifact
>
artifacts
=
filterDependencies
(
this
.
project
.
getArtifacts
(),
Set
<
Artifact
>
artifacts
=
filterDependencies
(
this
.
project
.
getArtifacts
(),
getFilters
());
getFilters
());
Libraries
libraries
=
new
ArtifactsLibraries
(
artifacts
);
Libraries
libraries
=
new
ArtifactsLibraries
(
artifacts
,
this
.
requiresUnpack
);
try
{
try
{
repackager
.
repackage
(
target
,
libraries
);
repackager
.
repackage
(
target
,
libraries
);
}
}
...
...
spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ArtifactsLibrariesTest.java
→
spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ArtifactsLibrariesTest
s
.java
View file @
9f464e9c
...
@@ -21,13 +21,19 @@ import java.util.Collections;
...
@@ -21,13 +21,19 @@ import java.util.Collections;
import
java.util.Set
;
import
java.util.Set
;
import
org.apache.maven.artifact.Artifact
;
import
org.apache.maven.artifact.Artifact
;
import
org.apache.maven.model.Dependency
;
import
org.junit.Before
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.mockito.ArgumentCaptor
;
import
org.mockito.Captor
;
import
org.mockito.Mock
;
import
org.mockito.Mock
;
import
org.mockito.MockitoAnnotations
;
import
org.mockito.MockitoAnnotations
;
import
org.springframework.boot.loader.tools.Library
;
import
org.springframework.boot.loader.tools.LibraryCallback
;
import
org.springframework.boot.loader.tools.LibraryCallback
;
import
org.springframework.boot.loader.tools.LibraryScope
;
import
org.springframework.boot.loader.tools.LibraryScope
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
verify
;
...
@@ -36,7 +42,7 @@ import static org.mockito.Mockito.verify;
...
@@ -36,7 +42,7 @@ import static org.mockito.Mockito.verify;
*
*
* @author Phillip Webb
* @author Phillip Webb
*/
*/
public
class
ArtifactsLibrariesTest
{
public
class
ArtifactsLibrariesTest
s
{
@Mock
@Mock
private
Artifact
artifact
;
private
Artifact
artifact
;
...
@@ -50,11 +56,14 @@ public class ArtifactsLibrariesTest {
...
@@ -50,11 +56,14 @@ public class ArtifactsLibrariesTest {
@Mock
@Mock
private
LibraryCallback
callback
;
private
LibraryCallback
callback
;
@Captor
private
ArgumentCaptor
<
Library
>
libraryCaptor
;
@Before
@Before
public
void
setup
()
{
public
void
setup
()
{
MockitoAnnotations
.
initMocks
(
this
);
MockitoAnnotations
.
initMocks
(
this
);
this
.
artifacts
=
Collections
.
singleton
(
this
.
artifact
);
this
.
artifacts
=
Collections
.
singleton
(
this
.
artifact
);
this
.
libs
=
new
ArtifactsLibraries
(
this
.
artifacts
);
this
.
libs
=
new
ArtifactsLibraries
(
this
.
artifacts
,
null
);
given
(
this
.
artifact
.
getFile
()).
willReturn
(
this
.
file
);
given
(
this
.
artifact
.
getFile
()).
willReturn
(
this
.
file
);
}
}
...
@@ -63,6 +72,25 @@ public class ArtifactsLibrariesTest {
...
@@ -63,6 +72,25 @@ public class ArtifactsLibrariesTest {
given
(
this
.
artifact
.
getType
()).
willReturn
(
"jar"
);
given
(
this
.
artifact
.
getType
()).
willReturn
(
"jar"
);
given
(
this
.
artifact
.
getScope
()).
willReturn
(
"compile"
);
given
(
this
.
artifact
.
getScope
()).
willReturn
(
"compile"
);
this
.
libs
.
doWithLibraries
(
this
.
callback
);
this
.
libs
.
doWithLibraries
(
this
.
callback
);
verify
(
this
.
callback
).
library
(
this
.
file
,
LibraryScope
.
COMPILE
);
verify
(
this
.
callback
).
library
(
this
.
libraryCaptor
.
capture
());
Library
library
=
this
.
libraryCaptor
.
getValue
();
assertThat
(
library
.
getFile
(),
equalTo
(
this
.
file
));
assertThat
(
library
.
getScope
(),
equalTo
(
LibraryScope
.
COMPILE
));
assertThat
(
library
.
isUnpackRequired
(),
equalTo
(
false
));
}
@Test
public
void
callbackWithUnpack
()
throws
Exception
{
given
(
this
.
artifact
.
getGroupId
()).
willReturn
(
"gid"
);
given
(
this
.
artifact
.
getArtifactId
()).
willReturn
(
"aid"
);
given
(
this
.
artifact
.
getType
()).
willReturn
(
"jar"
);
given
(
this
.
artifact
.
getScope
()).
willReturn
(
"compile"
);
Dependency
unpack
=
new
Dependency
();
unpack
.
setGroupId
(
"gid"
);
unpack
.
setArtifactId
(
"aid"
);
this
.
libs
=
new
ArtifactsLibraries
(
this
.
artifacts
,
Collections
.
singleton
(
unpack
));
this
.
libs
.
doWithLibraries
(
this
.
callback
);
verify
(
this
.
callback
).
library
(
this
.
libraryCaptor
.
capture
());
assertThat
(
this
.
libraryCaptor
.
getValue
().
isUnpackRequired
(),
equalTo
(
true
));
}
}
}
}
spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/Verify.java
View file @
9f464e9c
...
@@ -87,6 +87,15 @@ public class Verify {
...
@@ -87,6 +87,15 @@ public class Verify {
}
}
}
}
public
boolean
hasNonUnpackEntry
(
String
entry
)
{
return
!
hasUnpackEntry
(
entry
);
}
public
boolean
hasUnpackEntry
(
String
entry
)
{
String
comment
=
this
.
content
.
get
(
entry
).
getComment
();
return
comment
!=
null
&&
comment
.
startsWith
(
"UNPACK:"
);
}
public
boolean
hasEntry
(
String
entry
)
{
public
boolean
hasEntry
(
String
entry
)
{
return
this
.
content
.
containsKey
(
entry
);
return
this
.
content
.
containsKey
(
entry
);
}
}
...
...
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