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
15bc25dc
Commit
15bc25dc
authored
Sep 24, 2013
by
Phillip Webb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Further re-organization of launcher code
parent
0e0eb7d3
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
377 additions
and
230 deletions
+377
-230
pom.xml
spring-boot-tools/spring-boot-loader/pom.xml
+2
-1
ExecutableArchiveLauncher.java
...pringframework/boot/loader/ExecutableArchiveLauncher.java
+106
-0
JarLauncher.java
...ain/java/org/springframework/boot/loader/JarLauncher.java
+11
-10
LaunchedURLClassLoader.java
...g/springframework/boot/loader/LaunchedURLClassLoader.java
+1
-1
Launcher.java
...c/main/java/org/springframework/boot/loader/Launcher.java
+45
-57
MainMethodRunner.java
...ava/org/springframework/boot/loader/MainMethodRunner.java
+2
-2
PropertiesLauncher.java
...a/org/springframework/boot/loader/PropertiesLauncher.java
+59
-75
WarLauncher.java
...ain/java/org/springframework/boot/loader/WarLauncher.java
+14
-15
Archive.java
...java/org/springframework/boot/loader/archive/Archive.java
+53
-19
ExplodedArchive.java
.../springframework/boot/loader/archive/ExplodedArchive.java
+23
-11
JarFileArchive.java
...g/springframework/boot/loader/archive/JarFileArchive.java
+20
-9
package-info.java
...org/springframework/boot/loader/archive/package-info.java
+6
-8
package-info.java
...va/org/springframework/boot/loader/data/package-info.java
+1
-1
PropertiesLauncherTests.java
.../springframework/boot/loader/PropertiesLauncherTests.java
+22
-13
ExplodedArchiveTests.java
...ngframework/boot/loader/archive/ExplodedArchiveTests.java
+6
-3
JarFileArchiveTests.java
...ingframework/boot/loader/archive/JarFileArchiveTests.java
+6
-5
No files found.
spring-boot-tools/spring-boot-loader/pom.xml
View file @
15bc25dc
...
...
@@ -13,14 +13,15 @@
<main.basedir>
${basedir}/../..
</main.basedir>
</properties>
<dependencies>
<!-- TODO: maybe put these in the parent? -->
<dependency>
<groupId>
org.slf4j
</groupId>
<artifactId>
jcl-over-slf4j
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
ch.qos.logback
</groupId>
<artifactId>
logback-classic
</artifactId>
<scope>
test
</scope>
</dependency>
</dependencies>
<build>
...
...
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/
Abstract
Launcher.java
→
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/
ExecutableArchive
Launcher.java
View file @
15bc25dc
/*
* Copyright 2013 the original author or authors.
* Copyright 201
2-201
3 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.
...
...
@@ -22,44 +22,34 @@ import java.security.CodeSource;
import
java.security.ProtectionDomain
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.logging.Logger
;
import
java.util.jar.JarEntry
;
import
org.springframework.boot.loader.archive.Archive
;
import
org.springframework.boot.loader.archive.Archive.Entry
;
import
org.springframework.boot.loader.archive.Archive.EntryFilter
;
import
org.springframework.boot.loader.archive.ExplodedArchive
;
import
org.springframework.boot.loader.archive.JarFileArchive
;
/**
* Base class for launchers that can start an application with a fully configured
* classpath.
* Base class for executable archive {@link Launcher}s.
*
* @author Phillip Webb
* @author Dave Syer
*/
public
abstract
class
AbstractLauncher
implements
ArchiveFilter
{
private
Logger
logger
=
Logger
.
getLogger
(
AbstractLauncher
.
class
.
getName
());
public
abstract
class
ExecutableArchiveLauncher
extends
Launcher
{
private
LaunchHelper
helper
=
new
LaunchHelper
()
;
private
final
Archive
archive
;
/**
* Launch the application. This method is the initial entry point that should be
* called by a subclass {@code public static void main(String[] args)} method.
* @param args the incoming arguments
*/
public
void
launch
(
String
[]
args
)
{
public
ExecutableArchiveLauncher
()
{
try
{
launch
(
args
,
getClass
().
getProtectionDomain
()
);
this
.
archive
=
createArchive
(
);
}
catch
(
Exception
ex
)
{
ex
.
printStackTrace
();
System
.
exit
(
1
);
throw
new
IllegalStateException
(
ex
);
}
}
/**
* Launch the application given the protection domain.
* @param args the incoming arguments
* @param protectionDomain the protection domain
* @throws Exception
*/
protected
void
launch
(
String
[]
args
,
ProtectionDomain
protectionDomain
)
throws
Exception
{
private
Archive
createArchive
()
throws
Exception
{
ProtectionDomain
protectionDomain
=
getClass
().
getProtectionDomain
();
CodeSource
codeSource
=
protectionDomain
.
getCodeSource
();
URI
location
=
(
codeSource
==
null
?
null
:
codeSource
.
getLocation
().
toURI
());
String
path
=
(
location
==
null
?
null
:
location
.
getPath
());
...
...
@@ -71,34 +61,46 @@ public abstract class AbstractLauncher implements ArchiveFilter {
throw
new
IllegalStateException
(
"Unable to determine code source archive from "
+
root
);
}
Archive
archive
=
(
root
.
isDirectory
()
?
new
ExplodedArchive
(
root
)
:
new
JarFileArchive
(
root
));
launch
(
args
,
archive
);
return
(
root
.
isDirectory
()
?
new
ExplodedArchive
(
root
)
:
new
JarFileArchive
(
root
));
}
protected
final
Archive
getArchive
()
{
return
this
.
archive
;
}
@Override
protected
String
getMainClass
()
throws
Exception
{
return
this
.
archive
.
getMainClass
();
}
@Override
protected
List
<
Archive
>
getClassPathArchives
()
throws
Exception
{
List
<
Archive
>
archives
=
new
ArrayList
<
Archive
>(
this
.
archive
.
getNestedArchives
(
new
EntryFilter
()
{
@Override
public
boolean
matches
(
Entry
entry
)
{
return
isNestedArchive
(
entry
);
}
}));
postProcessClassPathArchives
(
archives
);
return
archives
;
}
/**
*
Launch the application given the archive file
*
@param args the incoming arguments
* @param
archive the underlying (zip/war/jar) archive
* @
throws Exception
*
Determine if the specified {@link JarEntry} is a nested item that should be added
*
to the classpath. The method is called once for each entry.
* @param
entry the jar entry
* @
return {@code true} if the entry is a nested item (jar or folder)
*/
protected
void
launch
(
String
[]
args
,
Archive
archive
)
throws
Exception
{
List
<
Archive
>
lib
=
new
ArrayList
<
Archive
>();
lib
.
addAll
(
this
.
helper
.
findNestedArchives
(
archive
,
this
));
this
.
logger
.
fine
(
"Added "
+
lib
.
size
()
+
" entries"
);
postProcessLib
(
archive
,
lib
);
String
mainClass
=
this
.
helper
.
getMainClass
(
archive
);
this
.
helper
.
launch
(
args
,
mainClass
,
lib
);
}
protected
abstract
boolean
isNestedArchive
(
Archive
.
Entry
entry
);
/**
* Called to post-process lib entries before they are used. Implementations can add
* and remove entries.
* @param archive the archive
* @param lib the existing lib
* Called to post-process archive entries before they are used. Implementations can
* add and remove entries.
* @param archives the archives
* @throws Exception
*/
protected
void
postProcess
Lib
(
Archive
archive
,
List
<
Archive
>
lib
)
throws
Exception
{
protected
void
postProcess
ClassPathArchives
(
List
<
Archive
>
archives
)
throws
Exception
{
}
}
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/JarLauncher.java
View file @
15bc25dc
...
...
@@ -18,26 +18,27 @@ package org.springframework.boot.loader;
import
java.util.List
;
import
org.springframework.boot.loader.archive.Archive
;
/**
* {@link
AbstractLauncher} for JAR based archives. This launcher assumes that dependency
*
jars are
included inside a {@code /lib} directory.
* {@link
Launcher} for JAR based archives. This launcher assumes that dependency jars are
* included inside a {@code /lib} directory.
*
* @author Phillip Webb
*/
public
class
JarLauncher
extends
AbstractLauncher
{
public
static
void
main
(
String
[]
args
)
{
new
JarLauncher
().
launch
(
args
);
}
public
class
JarLauncher
extends
ExecutableArchiveLauncher
{
@Override
p
ublic
boolean
is
Archive
(
Archive
.
Entry
entry
)
{
p
rotected
boolean
isNested
Archive
(
Archive
.
Entry
entry
)
{
return
!
entry
.
isDirectory
()
&&
entry
.
getName
().
startsWith
(
"lib/"
);
}
@Override
protected
void
postProcess
Lib
(
Archive
archive
,
List
<
Archive
>
lib
)
throws
Exception
{
lib
.
add
(
0
,
archive
);
protected
void
postProcess
ClassPathArchives
(
List
<
Archive
>
archives
)
throws
Exception
{
archives
.
add
(
0
,
getArchive
()
);
}
public
static
void
main
(
String
[]
args
)
{
new
JarLauncher
().
launch
(
args
);
}
}
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java
View file @
15bc25dc
...
...
@@ -25,7 +25,7 @@ import java.security.PrivilegedExceptionAction;
import
org.springframework.boot.loader.jar.RandomAccessJarFile
;
/**
* {@link ClassLoader} used by the {@link
Abstract
Launcher}.
* {@link ClassLoader} used by the {@link Launcher}.
*
* @author Phillip Webb
*/
...
...
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/Launch
Help
er.java
→
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/Launcher.java
View file @
15bc25dc
/*
* Copyright 201
2-201
3 the original author or authors.
* Copyright 2013 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.
...
...
@@ -22,79 +22,64 @@ import java.util.ArrayList;
import
java.util.List
;
import
java.util.logging.Logger
;
import
org.springframework.boot.loader.archive.Archive
;
/**
* Common convenience methods shared by launcher implementations.
* Base class for launchers that can start an application with a fully configured
* classpath backed by one or more {@link Archive}s.
*
* @author Phillip Webb
* @author Dave Syer
*/
public
class
LaunchHelp
er
{
public
abstract
class
Launch
er
{
pr
ivate
Logger
logger
=
Logger
.
getLogger
(
LaunchHelp
er
.
class
.
getName
());
pr
otected
Logger
logger
=
Logger
.
getLogger
(
Launch
er
.
class
.
getName
());
/**
* The main runner class. This must be loaded by the created ClassLoader so cannot be
* directly referenced.
*/
private
static
final
String
RUNNER_CLASS
=
AbstractLauncher
.
class
.
getPackag
e
()
.
getName
()
+
".MainMethodRunner"
;
private
static
final
String
RUNNER_CLASS
=
Launcher
.
class
.
getPackage
().
getNam
e
()
+
".MainMethodRunner"
;
/**
* Launch the application. This method is the initial entry point that should be
* called by a subclass {@code public static void main(String[] args)} method.
* @param args the incoming arguments
* @param mainClass the main class
* @param lib a collection of archives (zip/jar/war or directory)
* @throws Exception
*/
public
void
launch
(
String
[]
args
,
String
mainClass
,
List
<
Archive
>
lib
)
throws
Exception
{
ClassLoader
classLoader
=
createClassLoader
(
lib
);
launch
(
args
,
mainClass
,
classLoader
);
}
/**
* @param archive the archive to search
* @return an accumulation of nested archives
* @throws Exception
*/
p
ublic
List
<
Archive
>
findNestedArchives
(
Archive
archive
,
ArchiveFilter
filter
)
throws
Exception
{
List
<
Archive
>
lib
=
new
ArrayList
<
Archive
>(
);
for
(
Archive
.
Entry
entry
:
archive
.
getEntries
())
{
if
(
filter
.
isArchive
(
entry
))
{
this
.
logger
.
fine
(
"Adding: "
+
entry
.
getName
());
lib
.
add
(
archive
.
getNestedArchive
(
entry
)
);
}
p
rotected
void
launch
(
String
[]
args
)
{
try
{
ClassLoader
classLoader
=
createClassLoader
(
getClassPathArchives
()
);
launch
(
args
,
getMainClass
(),
classLoader
);
}
catch
(
Exception
ex
)
{
ex
.
printStackTrace
(
);
System
.
exit
(
1
);
}
return
lib
;
}
/**
* Obtain the main class that should be used to launch the application. By default
* this method uses a {@code Start-Class} manifest entry.
* @param archive the archive
* @return the main class
* Create a classloader for the specified archives.
* @param archives the archives
* @return the classloader
* @throws Exception
*/
public
String
getMainClass
(
Archive
archive
)
throws
Exception
{
String
mainClass
=
archive
.
getManifest
().
getMainAttributes
()
.
getValue
(
"Start-Class"
);
if
(
mainClass
==
null
)
{
throw
new
IllegalStateException
(
"No 'Start-Class' manifest entry specified"
);
protected
ClassLoader
createClassLoader
(
List
<
Archive
>
archives
)
throws
Exception
{
List
<
URL
>
urls
=
new
ArrayList
<
URL
>(
archives
.
size
());
for
(
Archive
archive
:
archives
)
{
urls
.
add
(
archive
.
getUrl
());
}
return
mainClass
;
return
createClassLoader
(
urls
.
toArray
(
new
URL
[
urls
.
size
()]))
;
}
/**
* Create a classloader for the specified
lib.
* @param
lib the lib
* Create a classloader for the specified
URLs
* @param
urls the URLs
* @return the classloader
* @throws Exception
*/
protected
ClassLoader
createClassLoader
(
List
<
Archive
>
lib
)
throws
Exception
{
URL
[]
urls
=
new
URL
[
lib
.
size
()];
for
(
int
i
=
0
;
i
<
urls
.
length
;
i
++)
{
urls
[
i
]
=
lib
.
get
(
i
).
getUrl
();
}
return
createClassLoader
(
urls
);
protected
ClassLoader
createClassLoader
(
URL
[]
urls
)
throws
Exception
{
return
new
LaunchedURLClassLoader
(
urls
,
getClass
().
getClassLoader
());
}
/**
...
...
@@ -113,16 +98,6 @@ public class LaunchHelper {
runnerThread
.
start
();
}
/**
* Create a classloader for the specified URLs
* @param urls the URLs
* @return the classloader
* @throws Exception
*/
protected
ClassLoader
createClassLoader
(
URL
[]
urls
)
throws
Exception
{
return
new
LaunchedURLClassLoader
(
urls
,
getClass
().
getClassLoader
());
}
/**
* Create the {@code MainMethodRunner} used to launch the application.
* @param mainClass the main class
...
...
@@ -139,4 +114,17 @@ public class LaunchHelper {
return
(
Runnable
)
constructor
.
newInstance
(
mainClass
,
args
);
}
/**
* Returns the main class that should be launched.
* @return the name of the main class
* @throws Exception
*/
protected
abstract
String
getMainClass
()
throws
Exception
;
/**
* Returns the archives that will be used to construct the class path.
* @return the class path archives
* @throws Exception
*/
protected
abstract
List
<
Archive
>
getClassPathArchives
()
throws
Exception
;
}
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/MainMethodRunner.java
View file @
15bc25dc
...
...
@@ -19,8 +19,8 @@ package org.springframework.boot.loader;
import
java.lang.reflect.Method
;
/**
* Utility class that used by {@link
Abstract
Launcher}s to call a main method. This class allows
* methods to be executed within a thread configured with a specific context classloader.
* Utility class that used by {@link Launcher}s to call a main method. This class allows
* methods to be executed within a thread configured with a specific context class
loader.
*
* @author Phillip Webb
*/
...
...
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java
View file @
15bc25dc
...
...
@@ -30,11 +30,15 @@ import java.util.List;
import
java.util.Properties
;
import
java.util.logging.Logger
;
import
org.springframework.boot.loader.archive.Archive
;
import
org.springframework.boot.loader.archive.Archive.Entry
;
import
org.springframework.boot.loader.archive.Archive.EntryFilter
;
import
org.springframework.boot.loader.archive.ExplodedArchive
;
import
org.springframework.boot.loader.util.SystemPropertyUtils
;
/**
* {@link
AbstractLauncher} for archives with user-configured classpath and main class vi
a
*
a
properties file. This model is often more flexible and more amenable to creating
* {@link
Launcher} for archives with user-configured classpath and main class via
a
* properties file. This model is often more flexible and more amenable to creating
* well-behaved OS-level services than a model based on executable jars.
*
* <p>
...
...
@@ -60,9 +64,9 @@ import org.springframework.boot.loader.util.SystemPropertyUtils;
*
* @author Dave Syer
*/
public
class
PropertiesLauncher
implements
ArchiveFilt
er
{
public
class
PropertiesLauncher
extends
Launch
er
{
private
Logger
logger
=
Logger
.
getLogger
(
Abstract
Launcher
.
class
.
getName
());
private
Logger
logger
=
Logger
.
getLogger
(
Launcher
.
class
.
getName
());
/**
* Properties key for main class
...
...
@@ -105,92 +109,28 @@ public class PropertiesLauncher implements ArchiveFilter {
private
static
final
List
<
String
>
DEFAULT_PATHS
=
Arrays
.
asList
(
"lib/"
);
private
final
File
home
;
private
List
<
String
>
paths
=
new
ArrayList
<
String
>(
DEFAULT_PATHS
);
private
Properties
properties
=
new
Properties
();
private
LaunchHelper
helper
=
new
LaunchHelper
();
public
static
void
main
(
String
[]
args
)
{
new
PropertiesLauncher
().
launch
(
args
);
}
/**
* Launch the application. This method is the initial entry point that should be
* called by a subclass {@code public static void main(String[] args)} method.
* @param args the incoming arguments
*/
public
void
launch
(
String
[]
args
)
{
public
PropertiesLauncher
()
{
try
{
File
home
=
getHomeDirectory
();
initialize
(
home
);
this
.
helper
.
launch
(
args
,
getMainClass
(
home
),
getLibrary
(
home
,
this
.
paths
)
);
this
.
home
=
getHomeDirectory
();
initialize
Properties
(
this
.
home
);
initializePaths
(
);
}
catch
(
Exception
ex
)
{
ex
.
printStackTrace
();
System
.
exit
(
1
);
throw
new
IllegalStateException
(
ex
);
}
}
@Override
public
boolean
isArchive
(
Archive
.
Entry
entry
)
{
return
entry
.
isDirectory
()
||
isArchive
(
entry
.
getName
());
}
protected
File
getHomeDirectory
()
{
return
new
File
(
SystemPropertyUtils
.
resolvePlaceholders
(
System
.
getProperty
(
HOME
,
"${user.dir}"
)));
}
protected
String
getMainClass
(
File
home
)
throws
Exception
{
if
(
System
.
getProperty
(
MAIN
)
!=
null
)
{
return
SystemPropertyUtils
.
resolvePlaceholders
(
System
.
getProperty
(
MAIN
));
}
if
(
this
.
properties
.
containsKey
(
MAIN
))
{
return
SystemPropertyUtils
.
resolvePlaceholders
(
this
.
properties
.
getProperty
(
MAIN
));
}
return
this
.
helper
.
getMainClass
(
new
ExplodedArchive
(
home
));
}
protected
void
initialize
(
File
home
)
throws
Exception
{
initializeProperties
(
home
);
initializePaths
();
}
private
boolean
isArchive
(
String
name
)
{
return
name
.
endsWith
(
".jar"
)
||
name
.
endsWith
(
".zip"
);
}
/**
* Search the configured paths and look for nested archives.
*
* @param home the home directory for this launch
* @param paths the directory roots for classpath entries
* @return a library of archives that can be used as a classpath
* @throws Exception
*/
private
List
<
Archive
>
getLibrary
(
File
home
,
List
<
String
>
paths
)
throws
Exception
{
List
<
Archive
>
lib
=
new
ArrayList
<
Archive
>();
for
(
String
path
:
paths
)
{
String
root
=
cleanupPath
(
stripFileUrlPrefix
(
path
));
File
file
=
new
File
(
root
);
if
(!
root
.
startsWith
(
"/"
))
{
file
=
new
File
(
home
,
root
);
}
if
(
file
.
isDirectory
())
{
this
.
logger
.
info
(
"Adding classpath entries from "
+
path
);
Archive
archive
=
new
ExplodedArchive
(
file
);
lib
.
addAll
(
this
.
helper
.
findNestedArchives
(
archive
,
this
));
lib
.
add
(
0
,
archive
);
}
else
{
this
.
logger
.
info
(
"No directory found at "
+
path
);
}
}
return
lib
;
}
private
void
initializeProperties
(
File
home
)
throws
Exception
,
IOException
{
String
config
=
SystemPropertyUtils
.
resolvePlaceholders
(
System
.
getProperty
(
CONFIG_NAME
,
"application"
))
+
".properties"
;
...
...
@@ -346,6 +286,46 @@ public class PropertiesLauncher implements ArchiveFilter {
return
paths
;
}
@Override
protected
String
getMainClass
()
throws
Exception
{
if
(
System
.
getProperty
(
MAIN
)
!=
null
)
{
return
SystemPropertyUtils
.
resolvePlaceholders
(
System
.
getProperty
(
MAIN
));
}
if
(
this
.
properties
.
containsKey
(
MAIN
))
{
return
SystemPropertyUtils
.
resolvePlaceholders
(
this
.
properties
.
getProperty
(
MAIN
));
}
return
new
ExplodedArchive
(
this
.
home
).
getMainClass
();
}
@Override
protected
List
<
Archive
>
getClassPathArchives
()
throws
Exception
{
List
<
Archive
>
lib
=
new
ArrayList
<
Archive
>();
for
(
String
path
:
this
.
paths
)
{
String
root
=
cleanupPath
(
stripFileUrlPrefix
(
path
));
File
file
=
new
File
(
root
);
if
(!
root
.
startsWith
(
"/"
))
{
file
=
new
File
(
this
.
home
,
root
);
}
if
(
file
.
isDirectory
())
{
this
.
logger
.
info
(
"Adding classpath entries from "
+
path
);
Archive
archive
=
new
ExplodedArchive
(
file
);
lib
.
addAll
(
archive
.
getNestedArchives
(
new
EntryFilter
()
{
@Override
public
boolean
matches
(
Entry
entry
)
{
return
entry
.
isDirectory
()
||
entry
.
getName
().
endsWith
(
".jar"
)
||
entry
.
getName
().
endsWith
(
".zip"
);
}
}));
lib
.
add
(
0
,
archive
);
}
else
{
this
.
logger
.
info
(
"No directory found at "
+
path
);
}
}
return
lib
;
}
private
String
cleanupPath
(
String
path
)
{
path
=
path
.
trim
();
// Always a directory
...
...
@@ -359,4 +339,8 @@ public class PropertiesLauncher implements ArchiveFilter {
return
path
;
}
public
static
void
main
(
String
[]
args
)
{
new
PropertiesLauncher
().
launch
(
args
);
}
}
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/WarLauncher.java
View file @
15bc25dc
...
...
@@ -19,21 +19,19 @@ package org.springframework.boot.loader;
import
java.io.IOException
;
import
java.util.List
;
import
org.springframework.boot.loader.archive.Archive
;
/**
* {@link
AbstractLauncher} for WAR based archives. This launcher for standard WAR
*
archives. Supports dependencies in {@code WEB-INF/lib} as well as
*
{@code WEB-INF/lib-provided},
classes are loaded from {@code WEB-INF/classes}.
* {@link
Launcher} for WAR based archives. This launcher for standard WAR archives.
*
Supports dependencies in {@code WEB-INF/lib} as well as {@code WEB-INF/lib-provided},
* classes are loaded from {@code WEB-INF/classes}.
*
* @author Phillip Webb
*/
public
class
WarLauncher
extends
AbstractLauncher
{
public
static
void
main
(
String
[]
args
)
{
new
WarLauncher
().
launch
(
args
);
}
public
class
WarLauncher
extends
ExecutableArchiveLauncher
{
@Override
public
boolean
isArchive
(
Archive
.
Entry
entry
)
{
public
boolean
is
Nested
Archive
(
Archive
.
Entry
entry
)
{
if
(
entry
.
isDirectory
())
{
return
entry
.
getName
().
equals
(
"WEB-INF/classes/"
);
}
...
...
@@ -44,20 +42,18 @@ public class WarLauncher extends AbstractLauncher {
}
@Override
protected
void
postProcess
Lib
(
Archive
archive
,
List
<
Archive
>
lib
)
throws
Exception
{
lib
.
add
(
0
,
filterArchive
(
archive
));
protected
void
postProcess
ClassPathArchives
(
List
<
Archive
>
archives
)
throws
Exception
{
archives
.
add
(
0
,
getFilteredArchive
(
));
}
/**
* Filter the specified WAR file to exclude elements that should not appear on the
* classpath.
* @param archive the source archive
* @return the filtered archive
* @throws IOException on error
*/
protected
Archive
filterArchive
(
Archive
archive
)
throws
IOException
{
return
archive
.
getFilteredArchive
(
new
Archive
.
EntryFilter
()
{
protected
Archive
getFilteredArchive
()
throws
IOException
{
return
getArchive
().
getFilteredArchive
(
new
Archive
.
EntryRenameFilter
()
{
@Override
public
String
apply
(
String
entryName
,
Archive
.
Entry
entry
)
{
if
(
entryName
.
startsWith
(
"META-INF/"
)
||
entryName
.
startsWith
(
"WEB-INF/"
))
{
...
...
@@ -68,4 +64,7 @@ public class WarLauncher extends AbstractLauncher {
});
}
public
static
void
main
(
String
[]
args
)
{
new
WarLauncher
().
launch
(
args
);
}
}
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/Archive.java
→
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/
archive/
Archive.java
View file @
15bc25dc
...
...
@@ -14,48 +14,67 @@
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
loader
;
package
org
.
springframework
.
boot
.
loader
.
archive
;
import
java.io.IOException
;
import
java.net.MalformedURLException
;
import
java.net.URL
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.jar.Manifest
;
import
org.springframework.boot.loader.Launcher
;
/**
* An archive that can be launched by the {@link
Abstract
Launcher}.
* An archive that can be launched by the {@link Launcher}.
*
* @author Phillip Webb
* @see JarFileArchive
*/
public
interface
Archive
{
public
abstract
class
Archive
{
/**
* Returns a URL that can be used to load the archive.
* @return the archive URL
* @throws MalformedURLException
*/
public
abstract
URL
getUrl
()
throws
MalformedURLException
;
/**
* Obtain the main class that should be used to launch the application. By default
* this method uses a {@code Start-Class} manifest entry.
* @return the main class
* @throws Exception
*/
public
String
getMainClass
()
throws
Exception
{
String
mainClass
=
getManifest
().
getMainAttributes
().
getValue
(
"Start-Class"
);
if
(
mainClass
==
null
)
{
throw
new
IllegalStateException
(
"No 'Start-Class' manifest entry specified"
);
}
return
mainClass
;
}
/**
* Returns the manifest of the archive.
* @return the manifest
* @throws IOException
*/
Manifest
getManifest
()
throws
IOException
;
public
abstract
Manifest
getManifest
()
throws
IOException
;
/**
* Returns a
rchive entries
.
* Returns a
ll entries from the archive
.
* @return the archive entries
*/
Iterable
<
Entry
>
getEntries
();
public
abstract
Collection
<
Entry
>
getEntries
();
/**
* Returns a URL that can be used to load the archive.
* @return the archive URL
* @throws MalformedURLException
*/
URL
getUrl
()
throws
MalformedURLException
;
/**
* Returns a nest archive from on the the contained entries.
* @param entry the entry (may be a directory or file)
* @return the nested archive
* Returns nested {@link Archive}s for entries that match the specified filter.
* @param filter the filter used to limit entries
* @return nested archives
* @throws IOException
*/
Archive
getNestedArchive
(
Entry
entry
)
throws
IOException
;
public
abstract
List
<
Archive
>
getNestedArchives
(
EntryFilter
filter
)
throws
IOException
;
/**
* Returns a filtered version of the archive.
...
...
@@ -63,7 +82,8 @@ public interface Archive {
* @return a filter archive
* @throws IOException
*/
Archive
getFilteredArchive
(
EntryFilter
filter
)
throws
IOException
;
public
abstract
Archive
getFilteredArchive
(
EntryRenameFilter
filter
)
throws
IOException
;
/**
* Represents a single entry in the archive.
...
...
@@ -85,10 +105,24 @@ public interface Archive {
}
/**
*
A filter for archive entries
.
*
Strategy interface to filter {@link Entry Entries}
.
*/
public
static
interface
EntryFilter
{
/**
* Apply the jar entry filter.
* @param entry the entry to filter
* @return {@code true} if the filter matches
*/
boolean
matches
(
Entry
entry
);
}
/**
* Strategy interface to filter or rename {@link Entry Entries}.
*/
public
static
interface
EntryRenameFilter
{
/**
* Apply the jar entry filter.
* @param entryName the current entry name. This may be different that the
...
...
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/ExplodedArchive.java
→
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/
archive/
ExplodedArchive.java
View file @
15bc25dc
...
...
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
loader
;
package
org
.
springframework
.
boot
.
loader
.
archive
;
import
java.io.File
;
import
java.io.FileInputStream
;
...
...
@@ -24,10 +24,13 @@ import java.net.MalformedURLException;
import
java.net.URL
;
import
java.net.URLConnection
;
import
java.net.URLStreamHandler
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.jar.Manifest
;
...
...
@@ -37,7 +40,7 @@ import java.util.jar.Manifest;
*
* @author Phillip Webb
*/
public
class
ExplodedArchive
implement
s
Archive
{
public
class
ExplodedArchive
extend
s
Archive
{
private
static
final
Set
<
String
>
SKIPPED_NAMES
=
new
HashSet
<
String
>(
Arrays
.
asList
(
"."
,
".."
));
...
...
@@ -82,6 +85,12 @@ public class ExplodedArchive implements Archive {
}
}
@Override
public
URL
getUrl
()
throws
MalformedURLException
{
FilteredURLStreamHandler
handler
=
new
FilteredURLStreamHandler
();
return
new
URL
(
"file"
,
""
,
-
1
,
this
.
root
.
getAbsolutePath
()
+
"/"
,
handler
);
}
@Override
public
Manifest
getManifest
()
throws
IOException
{
if
(
this
.
manifest
==
null
&&
this
.
entries
.
containsKey
(
MANIFEST_ENTRY_NAME
))
{
...
...
@@ -98,25 +107,28 @@ public class ExplodedArchive implements Archive {
}
@Override
public
Iterable
<
Entry
>
getEntries
()
{
return
this
.
entries
.
values
();
public
List
<
Archive
>
getNestedArchives
(
EntryFilter
filter
)
throws
IOException
{
List
<
Archive
>
nestedArchives
=
new
ArrayList
<
Archive
>();
for
(
Entry
entry
:
getEntries
())
{
if
(
filter
.
matches
(
entry
))
{
nestedArchives
.
add
(
getNestedArchive
(
entry
));
}
}
return
Collections
.
unmodifiableList
(
nestedArchives
);
}
@Override
public
URL
getUrl
()
throws
MalformedURLException
{
FilteredURLStreamHandler
handler
=
new
FilteredURLStreamHandler
();
return
new
URL
(
"file"
,
""
,
-
1
,
this
.
root
.
getAbsolutePath
()
+
"/"
,
handler
);
// return this.root.toURI().toURL();
public
Collection
<
Entry
>
getEntries
()
{
return
Collections
.
unmodifiableCollection
(
this
.
entries
.
values
());
}
@Override
public
Archive
getNestedArchive
(
Entry
entry
)
throws
IOException
{
protected
Archive
getNestedArchive
(
Entry
entry
)
throws
IOException
{
File
file
=
((
FileEntry
)
entry
).
getFile
();
return
(
file
.
isDirectory
()
?
new
ExplodedArchive
(
file
)
:
new
JarFileArchive
(
file
));
}
@Override
public
Archive
getFilteredArchive
(
EntryFilter
filter
)
throws
IOException
{
public
Archive
getFilteredArchive
(
Entry
Rename
Filter
filter
)
throws
IOException
{
Map
<
String
,
Entry
>
filteredEntries
=
new
LinkedHashMap
<
String
,
Archive
.
Entry
>();
for
(
Map
.
Entry
<
String
,
Entry
>
entry
:
this
.
entries
.
entrySet
())
{
String
filteredName
=
filter
.
apply
(
entry
.
getKey
(),
entry
.
getValue
());
...
...
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/JarFileArchive.java
→
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/
archive/
JarFileArchive.java
View file @
15bc25dc
...
...
@@ -14,13 +14,14 @@
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
loader
;
package
org
.
springframework
.
boot
.
loader
.
archive
;
import
java.io.File
;
import
java.io.IOException
;
import
java.net.MalformedURLException
;
import
java.net.URL
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Enumeration
;
import
java.util.List
;
...
...
@@ -35,7 +36,7 @@ import org.springframework.boot.loader.jar.RandomAccessJarFile;
*
* @author Phillip Webb
*/
public
class
JarFileArchive
implement
s
Archive
{
public
class
JarFileArchive
extend
s
Archive
{
private
final
RandomAccessJarFile
jarFile
;
...
...
@@ -55,30 +56,40 @@ public class JarFileArchive implements Archive {
this
.
entries
=
Collections
.
unmodifiableList
(
jarFileEntries
);
}
@Override
public
URL
getUrl
()
throws
MalformedURLException
{
return
this
.
jarFile
.
getUrl
();
}
@Override
public
Manifest
getManifest
()
throws
IOException
{
return
this
.
jarFile
.
getManifest
();
}
@Override
public
Iterable
<
Entry
>
getEntries
()
{
return
this
.
entries
;
public
List
<
Archive
>
getNestedArchives
(
EntryFilter
filter
)
throws
IOException
{
List
<
Archive
>
nestedArchives
=
new
ArrayList
<
Archive
>();
for
(
Entry
entry
:
getEntries
())
{
if
(
filter
.
matches
(
entry
))
{
nestedArchives
.
add
(
getNestedArchive
(
entry
));
}
}
return
Collections
.
unmodifiableList
(
nestedArchives
);
}
@Override
public
URL
getUrl
()
throws
MalformedURLException
{
return
this
.
jarFile
.
getUrl
(
);
public
Collection
<
Entry
>
getEntries
()
{
return
Collections
.
unmodifiableCollection
(
this
.
entries
);
}
@Override
public
Archive
getNestedArchive
(
Entry
entry
)
throws
IOException
{
protected
Archive
getNestedArchive
(
Entry
entry
)
throws
IOException
{
JarEntry
jarEntry
=
((
JarFileEntry
)
entry
).
getJarEntry
();
RandomAccessJarFile
jarFile
=
this
.
jarFile
.
getNestedJarFile
(
jarEntry
);
return
new
JarFileArchive
(
jarFile
);
}
@Override
public
Archive
getFilteredArchive
(
final
EntryFilter
filter
)
throws
IOException
{
public
Archive
getFilteredArchive
(
final
Entry
Rename
Filter
filter
)
throws
IOException
{
RandomAccessJarFile
filteredJar
=
this
.
jarFile
.
getFilteredJarFile
(
new
JarEntryFilter
()
{
@Override
...
...
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/
ArchiveFilter
.java
→
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/
archive/package-info
.java
View file @
15bc25dc
/*
* Copyright 201
2-201
3 the original author or authors.
* Copyright 2013 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.
...
...
@@ -14,13 +14,11 @@
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
loader
;
/**
* @author Dave Syer
* Abstraction over logical Archives be they backed by a JAR file or unpacked into a
* folder.
*
* @see org.springframework.boot.loader.archive.Archive
*/
public
interface
ArchiveFilter
{
public
boolean
isArchive
(
Archive
.
Entry
entry
);
package
org
.
springframework
.
boot
.
loader
.
archive
;
}
spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/data/package-info.java
View file @
15bc25dc
...
...
@@ -17,7 +17,7 @@
/**
* Classes and interfaces to allows random access to a block of data.
*
*
@see org.springframework.boot.loader.data.RandomAccessData
* @see org.springframework.boot.loader.data.RandomAccessData
*/
package
org
.
springframework
.
boot
.
loader
.
data
;
spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java
View file @
15bc25dc
...
...
@@ -17,63 +17,72 @@
package
org
.
springframework
.
boot
.
loader
;
import
java.io.File
;
import
java.io.IOException
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
/**
* Tests for {@link PropertiesLauncher}.
*
* @author Dave Syer
*/
public
class
PropertiesLauncherTests
{
private
PropertiesLauncher
launcher
=
new
PropertiesLauncher
();
@Before
public
void
setup
()
throws
IOException
{
System
.
setProperty
(
"loader.home"
,
new
File
(
"src/test/resources"
).
getAbsolutePath
());
}
@After
public
void
close
()
{
System
.
clearProperty
(
"loader.system"
);
System
.
clearProperty
(
"loader.home"
);
System
.
clearProperty
(
"loader.path"
);
System
.
clearProperty
(
"loader.main"
);
System
.
clearProperty
(
"loader.config.name"
);
System
.
clearProperty
(
"loader.config.location"
);
System
.
clearProperty
(
"loader.system"
);
}
@Test
public
void
testDefaultHome
()
{
assertEquals
(
new
File
(
System
.
getProperty
(
"user.dir"
)),
this
.
launcher
.
getHomeDirectory
());
PropertiesLauncher
launcher
=
new
PropertiesLauncher
();
assertEquals
(
new
File
(
System
.
getProperty
(
"loader.home"
)),
launcher
.
getHomeDirectory
());
}
@Test
public
void
testUserSpecifiedMain
()
throws
Exception
{
this
.
launcher
.
initialize
(
new
File
(
"."
)
);
assertEquals
(
"demo.Application"
,
this
.
launcher
.
getMainClass
(
null
));
PropertiesLauncher
launcher
=
new
PropertiesLauncher
(
);
assertEquals
(
"demo.Application"
,
launcher
.
getMainClass
(
));
assertEquals
(
null
,
System
.
getProperty
(
"loader.main"
));
}
@Test
public
void
testUserSpecifiedConfigName
()
throws
Exception
{
System
.
setProperty
(
"loader.config.name"
,
"foo"
);
this
.
launcher
.
initialize
(
new
File
(
"."
));
assertEquals
(
"my.Application"
,
this
.
launcher
.
getMainClass
(
null
));
assertEquals
(
"[etc/]"
,
ReflectionTestUtils
.
getField
(
this
.
launcher
,
"paths"
)
.
toString
());
PropertiesLauncher
launcher
=
new
PropertiesLauncher
();
assertEquals
(
"my.Application"
,
launcher
.
getMainClass
());
assertEquals
(
"[etc/]"
,
ReflectionTestUtils
.
getField
(
launcher
,
"paths"
).
toString
());
}
@Test
public
void
testSystemPropertySpecifiedMain
()
throws
Exception
{
System
.
setProperty
(
"loader.main"
,
"foo.Bar"
);
this
.
launcher
.
initialize
(
new
File
(
"."
)
);
assertEquals
(
"foo.Bar"
,
this
.
launcher
.
getMainClass
(
null
));
PropertiesLauncher
launcher
=
new
PropertiesLauncher
(
);
assertEquals
(
"foo.Bar"
,
launcher
.
getMainClass
(
));
}
@Test
public
void
testSystemPropertiesSet
()
throws
Exception
{
System
.
setProperty
(
"loader.system"
,
"true"
);
this
.
launcher
.
initialize
(
new
File
(
"."
)
);
new
PropertiesLauncher
(
);
assertEquals
(
"demo.Application"
,
System
.
getProperty
(
"loader.main"
));
}
...
...
spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/ExplodedArchiveTests.java
→
spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/
archive/
ExplodedArchiveTests.java
View file @
15bc25dc
...
...
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
loader
;
package
org
.
springframework
.
boot
.
loader
.
archive
;
import
java.io.File
;
import
java.io.FileOutputStream
;
...
...
@@ -33,7 +33,10 @@ import org.junit.Before;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.rules.TemporaryFolder
;
import
org.springframework.boot.loader.Archive.Entry
;
import
org.springframework.boot.loader.TestJarCreator
;
import
org.springframework.boot.loader.archive.Archive
;
import
org.springframework.boot.loader.archive.Archive.Entry
;
import
org.springframework.boot.loader.archive.ExplodedArchive
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
hamcrest
.
Matchers
.
nullValue
;
...
...
@@ -126,7 +129,7 @@ public class ExplodedArchiveTests {
@Test
public
void
getFilteredArchive
()
throws
Exception
{
Archive
filteredArchive
=
this
.
archive
.
getFilteredArchive
(
new
Archive
.
EntryFilter
()
{
.
getFilteredArchive
(
new
Archive
.
Entry
Rename
Filter
()
{
@Override
public
String
apply
(
String
entryName
,
Entry
entry
)
{
if
(
entryName
.
equals
(
"1.dat"
))
{
...
...
spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/JarFileArchiveTests.java
→
spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/
archive/
JarFileArchiveTests.java
View file @
15bc25dc
...
...
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
loader
;
package
org
.
springframework
.
boot
.
loader
.
archive
;
import
java.io.File
;
import
java.net.URL
;
...
...
@@ -25,9 +25,10 @@ import org.junit.Before;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.rules.TemporaryFolder
;
import
org.springframework.boot.loader.Archive
;
import
org.springframework.boot.loader.JarFileArchive
;
import
org.springframework.boot.loader.Archive.Entry
;
import
org.springframework.boot.loader.TestJarCreator
;
import
org.springframework.boot.loader.archive.Archive
;
import
org.springframework.boot.loader.archive.JarFileArchive
;
import
org.springframework.boot.loader.archive.Archive.Entry
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
junit
.
Assert
.
assertThat
;
...
...
@@ -83,7 +84,7 @@ public class JarFileArchiveTests {
@Test
public
void
getFilteredArchive
()
throws
Exception
{
Archive
filteredArchive
=
this
.
archive
.
getFilteredArchive
(
new
Archive
.
EntryFilter
()
{
.
getFilteredArchive
(
new
Archive
.
Entry
Rename
Filter
()
{
@Override
public
String
apply
(
String
entryName
,
Entry
entry
)
{
if
(
entryName
.
equals
(
"1.dat"
))
{
...
...
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