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
b527e714
Commit
b527e714
authored
Mar 09, 2017
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '1.5.x'
parents
f72c5b70
1395f38e
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
798 additions
and
46 deletions
+798
-46
AbstractApplicationLauncher.java
...rk/boot/context/embedded/AbstractApplicationLauncher.java
+16
-8
AbstractEmbeddedServletContainerIntegrationTests.java
...ded/AbstractEmbeddedServletContainerIntegrationTests.java
+20
-12
BootRunApplicationLauncher.java
...ork/boot/context/embedded/BootRunApplicationLauncher.java
+141
-0
EmbeddedServletContainerJarDevelopmentIntegrationTests.java
...beddedServletContainerJarDevelopmentIntegrationTests.java
+67
-0
EmbeddedServletContainerJarPackagingIntegrationTests.java
...EmbeddedServletContainerJarPackagingIntegrationTests.java
+5
-1
EmbeddedServletContainerWarDevelopmentIntegrationTests.java
...beddedServletContainerWarDevelopmentIntegrationTests.java
+74
-0
EmbeddedServletContainerWarPackagingIntegrationTests.java
...EmbeddedServletContainerWarPackagingIntegrationTests.java
+5
-1
ExplodedApplicationLauncher.java
...rk/boot/context/embedded/ExplodedApplicationLauncher.java
+12
-2
IdeApplicationLauncher.java
...amework/boot/context/embedded/IdeApplicationLauncher.java
+152
-0
PackagedApplicationLauncher.java
...rk/boot/context/embedded/PackagedApplicationLauncher.java
+10
-0
AbstractEmbeddedServletContainerFactory.java
...ext/embedded/AbstractEmbeddedServletContainerFactory.java
+43
-7
JettyEmbeddedServletContainerFactory.java
.../embedded/jetty/JettyEmbeddedServletContainerFactory.java
+11
-2
TomcatEmbeddedServletContainerFactory.java
...mbedded/tomcat/TomcatEmbeddedServletContainerFactory.java
+8
-5
TomcatResources.java
...amework/boot/context/embedded/tomcat/TomcatResources.java
+196
-0
UndertowEmbeddedServletContainerFactory.java
...ded/undertow/UndertowEmbeddedServletContainerFactory.java
+38
-8
No files found.
spring-boot-integration-tests/spring-boot-integration-tests-embedded-servlet-container/src/test/java/org/springframework/boot/context/embedded/AbstractApplicationLauncher.java
View file @
b527e714
...
...
@@ -34,8 +34,6 @@ import org.springframework.util.FileCopyUtils;
*/
abstract
class
AbstractApplicationLauncher
extends
ExternalResource
{
private
final
File
serverPortFile
=
new
File
(
"target/server.port"
);
private
final
ApplicationBuilder
applicationBuilder
;
private
Process
process
;
...
...
@@ -62,8 +60,15 @@ abstract class AbstractApplicationLauncher extends ExternalResource {
protected
abstract
List
<
String
>
getArguments
(
File
archive
);
protected
abstract
File
getWorkingDirectory
();
protected
abstract
String
getDescription
(
String
packaging
);
private
Process
startApplication
()
throws
Exception
{
this
.
serverPortFile
.
delete
();
File
workingDirectory
=
getWorkingDirectory
();
File
serverPortFile
=
workingDirectory
==
null
?
new
File
(
"target/server.port"
)
:
new
File
(
workingDirectory
,
"target/server.port"
);
serverPortFile
.
delete
();
File
archive
=
this
.
applicationBuilder
.
buildApplication
();
List
<
String
>
arguments
=
new
ArrayList
<>();
arguments
.
add
(
System
.
getProperty
(
"java.home"
)
+
"/bin/java"
);
...
...
@@ -72,14 +77,17 @@ abstract class AbstractApplicationLauncher extends ExternalResource {
arguments
.
toArray
(
new
String
[
arguments
.
size
()]));
processBuilder
.
redirectOutput
(
Redirect
.
INHERIT
);
processBuilder
.
redirectError
(
Redirect
.
INHERIT
);
if
(
workingDirectory
!=
null
)
{
processBuilder
.
directory
(
workingDirectory
);
}
Process
process
=
processBuilder
.
start
();
this
.
httpPort
=
awaitServerPort
(
process
);
this
.
httpPort
=
awaitServerPort
(
process
,
serverPortFile
);
return
process
;
}
private
int
awaitServerPort
(
Process
process
)
throws
Exception
{
private
int
awaitServerPort
(
Process
process
,
File
serverPortFile
)
throws
Exception
{
long
end
=
System
.
currentTimeMillis
()
+
30000
;
while
(
this
.
serverPortFile
.
length
()
==
0
)
{
while
(
serverPortFile
.
length
()
==
0
)
{
if
(
System
.
currentTimeMillis
()
>
end
)
{
throw
new
IllegalStateException
(
"server.port file was not written within 30 seconds"
);
...
...
@@ -89,8 +97,8 @@ abstract class AbstractApplicationLauncher extends ExternalResource {
}
Thread
.
sleep
(
100
);
}
return
Integer
.
parseInt
(
FileCopyUtils
.
copyToString
(
new
FileReader
(
this
.
serverPortFile
)));
return
Integer
.
parseInt
(
FileCopyUtils
.
copyToString
(
new
FileReader
(
serverPortFile
)));
}
}
spring-boot-integration-tests/spring-boot-integration-tests-embedded-servlet-container/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerIntegrationTests.java
View file @
b527e714
...
...
@@ -47,25 +47,33 @@ public abstract class AbstractEmbeddedServletContainerIntegrationTests {
protected
final
RestTemplate
rest
=
new
RestTemplate
();
public
static
Object
[]
parameters
(
String
packaging
)
{
public
static
Object
[]
parameters
(
String
packaging
,
List
<
Class
<?
extends
AbstractApplicationLauncher
>>
applicationLaunchers
)
{
List
<
Object
>
parameters
=
new
ArrayList
<>();
parameters
.
addAll
(
createParameters
(
packaging
,
"jetty"
));
parameters
.
addAll
(
createParameters
(
packaging
,
"tomcat"
));
parameters
.
addAll
(
createParameters
(
packaging
,
"undertow"
));
parameters
.
addAll
(
createParameters
(
packaging
,
"jetty"
,
applicationLaunchers
));
parameters
.
addAll
(
createParameters
(
packaging
,
"tomcat"
,
applicationLaunchers
));
parameters
.
addAll
(
createParameters
(
packaging
,
"undertow"
,
applicationLaunchers
));
return
parameters
.
toArray
(
new
Object
[
parameters
.
size
()]);
}
private
static
List
<
Object
>
createParameters
(
String
packaging
,
String
container
,
String
...
version
s
)
{
List
<
Object
>
parameters
=
new
ArrayList
<>();
List
<
Class
<?
extends
AbstractApplicationLauncher
>>
applicationLauncher
s
)
{
List
<
Object
>
parameters
=
new
ArrayList
<
Object
>();
ApplicationBuilder
applicationBuilder
=
new
ApplicationBuilder
(
temporaryFolder
,
packaging
,
container
);
parameters
.
add
(
new
Object
[]
{
StringUtils
.
capitalise
(
container
)
+
" packaged "
+
packaging
,
new
PackagedApplicationLauncher
(
applicationBuilder
)
});
parameters
.
add
(
new
Object
[]
{
StringUtils
.
capitalise
(
container
)
+
" exploded "
+
packaging
,
new
ExplodedApplicationLauncher
(
applicationBuilder
)
});
for
(
Class
<?
extends
AbstractApplicationLauncher
>
launcherClass
:
applicationLaunchers
)
{
try
{
AbstractApplicationLauncher
launcher
=
launcherClass
.
getDeclaredConstructor
(
ApplicationBuilder
.
class
)
.
newInstance
(
applicationBuilder
);
String
name
=
StringUtils
.
capitalise
(
container
)
+
": "
+
launcher
.
getDescription
(
packaging
);
parameters
.
add
(
new
Object
[]
{
name
,
launcher
});
}
catch
(
Exception
ex
)
{
throw
new
RuntimeException
(
ex
);
}
}
return
parameters
;
}
...
...
spring-boot-integration-tests/spring-boot-integration-tests-embedded-servlet-container/src/test/java/org/springframework/boot/context/embedded/BootRunApplicationLauncher.java
0 → 100644
View file @
b527e714
/*
* Copyright 2012-2017 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
.
context
.
embedded
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Enumeration
;
import
java.util.List
;
import
java.util.jar.JarEntry
;
import
java.util.jar.JarFile
;
import
org.springframework.util.FileSystemUtils
;
import
org.springframework.util.StreamUtils
;
import
org.springframework.util.StringUtils
;
/**
* {@link AbstractApplicationLauncher} that launches a Spring Boot application with a
* classpath similar to that used when run with Maven or Gradle.
*
* @author Andy Wilkinson
*/
class
BootRunApplicationLauncher
extends
AbstractApplicationLauncher
{
private
final
File
exploded
=
new
File
(
"target/run"
);
BootRunApplicationLauncher
(
ApplicationBuilder
applicationBuilder
)
{
super
(
applicationBuilder
);
}
@Override
protected
List
<
String
>
getArguments
(
File
archive
)
{
try
{
explodeArchive
(
archive
);
deleteLauncherClasses
();
File
targetClasses
=
populateTargetClasses
(
archive
);
File
dependencies
=
populateDependencies
(
archive
);
populateSrcMainWebapp
();
List
<
String
>
classpath
=
new
ArrayList
<
String
>();
classpath
.
add
(
targetClasses
.
getAbsolutePath
());
for
(
File
dependency
:
dependencies
.
listFiles
())
{
classpath
.
add
(
dependency
.
getAbsolutePath
());
}
return
Arrays
.
asList
(
"-cp"
,
StringUtils
.
collectionToDelimitedString
(
classpath
,
File
.
pathSeparator
),
"com.example.ResourceHandlingApplication"
);
}
catch
(
IOException
ex
)
{
throw
new
RuntimeException
(
ex
);
}
}
private
void
deleteLauncherClasses
()
{
FileSystemUtils
.
deleteRecursively
(
new
File
(
this
.
exploded
,
"org"
));
}
private
File
populateTargetClasses
(
File
archive
)
{
File
targetClasses
=
new
File
(
this
.
exploded
,
"target/classes"
);
targetClasses
.
mkdirs
();
new
File
(
this
.
exploded
,
getClassesPath
(
archive
)).
renameTo
(
targetClasses
);
return
targetClasses
;
}
private
File
populateDependencies
(
File
archive
)
{
File
dependencies
=
new
File
(
this
.
exploded
,
"dependencies"
);
dependencies
.
mkdirs
();
List
<
String
>
libPaths
=
getLibPaths
(
archive
);
for
(
String
libPath
:
libPaths
)
{
for
(
File
jar
:
new
File
(
this
.
exploded
,
libPath
).
listFiles
())
{
jar
.
renameTo
(
new
File
(
dependencies
,
jar
.
getName
()));
}
}
return
dependencies
;
}
private
void
populateSrcMainWebapp
()
{
File
srcMainWebapp
=
new
File
(
this
.
exploded
,
"src/main/webapp"
);
srcMainWebapp
.
mkdirs
();
new
File
(
this
.
exploded
,
"webapp-resource.txt"
)
.
renameTo
(
new
File
(
srcMainWebapp
,
"webapp-resource.txt"
));
}
private
String
getClassesPath
(
File
archive
)
{
return
archive
.
getName
().
endsWith
(
".jar"
)
?
"BOOT-INF/classes"
:
"WEB-INF/classes"
;
}
private
List
<
String
>
getLibPaths
(
File
archive
)
{
return
archive
.
getName
().
endsWith
(
".jar"
)
?
Collections
.
singletonList
(
"BOOT-INF/lib"
)
:
Arrays
.
asList
(
"WEB-INF/lib"
,
"WEB-INF/lib-provided"
);
}
private
void
explodeArchive
(
File
archive
)
throws
IOException
{
FileSystemUtils
.
deleteRecursively
(
this
.
exploded
);
JarFile
jarFile
=
new
JarFile
(
archive
);
Enumeration
<
JarEntry
>
entries
=
jarFile
.
entries
();
while
(
entries
.
hasMoreElements
())
{
JarEntry
jarEntry
=
entries
.
nextElement
();
File
extracted
=
new
File
(
this
.
exploded
,
jarEntry
.
getName
());
if
(
jarEntry
.
isDirectory
())
{
extracted
.
mkdirs
();
}
else
{
FileOutputStream
extractedOutputStream
=
new
FileOutputStream
(
extracted
);
StreamUtils
.
copy
(
jarFile
.
getInputStream
(
jarEntry
),
extractedOutputStream
);
extractedOutputStream
.
close
();
}
}
jarFile
.
close
();
}
@Override
protected
File
getWorkingDirectory
()
{
return
this
.
exploded
;
}
@Override
protected
String
getDescription
(
String
packaging
)
{
return
"build system run "
+
packaging
+
" project"
;
}
}
spring-boot-integration-tests/spring-boot-integration-tests-embedded-servlet-container/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerJarDevelopmentIntegrationTests.java
0 → 100644
View file @
b527e714
/*
* Copyright 2012-2017 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
.
context
.
embedded
;
import
java.util.Arrays
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Parameterized
;
import
org.junit.runners.Parameterized.Parameters
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Integration tests for Spring Boot's embedded servlet container support when developing
* a jar application.
*
* @author Andy Wilkinson
*/
@RunWith
(
Parameterized
.
class
)
public
class
EmbeddedServletContainerJarDevelopmentIntegrationTests
extends
AbstractEmbeddedServletContainerIntegrationTests
{
@Parameters
(
name
=
"{0}"
)
public
static
Object
[]
parameters
()
{
return
AbstractEmbeddedServletContainerIntegrationTests
.
parameters
(
"jar"
,
Arrays
.
asList
(
BootRunApplicationLauncher
.
class
,
IdeApplicationLauncher
.
class
));
}
public
EmbeddedServletContainerJarDevelopmentIntegrationTests
(
String
name
,
AbstractApplicationLauncher
launcher
)
{
super
(
name
,
launcher
);
}
@Test
public
void
metaInfResourceFromDependencyIsAvailableViaHttp
()
throws
Exception
{
ResponseEntity
<
String
>
entity
=
this
.
rest
.
getForEntity
(
"/nested-meta-inf-resource.txt"
,
String
.
class
);
assertThat
(
entity
.
getStatusCode
()).
isEqualTo
(
HttpStatus
.
OK
);
}
@Test
public
void
metaInfResourceFromDependencyIsAvailableViaServletContext
()
throws
Exception
{
ResponseEntity
<
String
>
entity
=
this
.
rest
.
getForEntity
(
"/nested-meta-inf-resource.txt"
,
String
.
class
);
assertThat
(
entity
.
getStatusCode
()).
isEqualTo
(
HttpStatus
.
OK
);
}
}
spring-boot-integration-tests/spring-boot-integration-tests-embedded-servlet-container/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerJarPackagingIntegrationTests.java
View file @
b527e714
...
...
@@ -16,6 +16,8 @@
package
org
.
springframework
.
boot
.
context
.
embedded
;
import
java.util.Arrays
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Parameterized
;
...
...
@@ -38,7 +40,9 @@ public class EmbeddedServletContainerJarPackagingIntegrationTests
@Parameters
(
name
=
"{0}"
)
public
static
Object
[]
parameters
()
{
return
AbstractEmbeddedServletContainerIntegrationTests
.
parameters
(
"jar"
);
return
AbstractEmbeddedServletContainerIntegrationTests
.
parameters
(
"jar"
,
Arrays
.
asList
(
PackagedApplicationLauncher
.
class
,
ExplodedApplicationLauncher
.
class
));
}
public
EmbeddedServletContainerJarPackagingIntegrationTests
(
String
name
,
...
...
spring-boot-integration-tests/spring-boot-integration-tests-embedded-servlet-container/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerWarDevelopmentIntegrationTests.java
0 → 100644
View file @
b527e714
/*
* Copyright 2012-2017 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
.
context
.
embedded
;
import
java.util.Arrays
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Parameterized
;
import
org.junit.runners.Parameterized.Parameters
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Integration tests for Spring Boot's embedded servlet container support when developing
* a war application.
*
* @author Andy Wilkinson
*/
@RunWith
(
Parameterized
.
class
)
public
class
EmbeddedServletContainerWarDevelopmentIntegrationTests
extends
AbstractEmbeddedServletContainerIntegrationTests
{
@Parameters
(
name
=
"{0}"
)
public
static
Object
[]
parameters
()
{
return
AbstractEmbeddedServletContainerIntegrationTests
.
parameters
(
"war"
,
Arrays
.
asList
(
BootRunApplicationLauncher
.
class
,
IdeApplicationLauncher
.
class
));
}
public
EmbeddedServletContainerWarDevelopmentIntegrationTests
(
String
name
,
AbstractApplicationLauncher
launcher
)
{
super
(
name
,
launcher
);
}
@Test
public
void
metaInfResourceFromDependencyIsAvailableViaHttp
()
throws
Exception
{
ResponseEntity
<
String
>
entity
=
this
.
rest
.
getForEntity
(
"/nested-meta-inf-resource.txt"
,
String
.
class
);
assertThat
(
entity
.
getStatusCode
()).
isEqualTo
(
HttpStatus
.
OK
);
}
@Test
public
void
metaInfResourceFromDependencyIsAvailableViaServletContext
()
throws
Exception
{
ResponseEntity
<
String
>
entity
=
this
.
rest
.
getForEntity
(
"/nested-meta-inf-resource.txt"
,
String
.
class
);
assertThat
(
entity
.
getStatusCode
()).
isEqualTo
(
HttpStatus
.
OK
);
}
@Test
public
void
webappResourcesAreAvailableViaHttp
()
throws
Exception
{
ResponseEntity
<
String
>
entity
=
this
.
rest
.
getForEntity
(
"/webapp-resource.txt"
,
String
.
class
);
assertThat
(
entity
.
getStatusCode
()).
isEqualTo
(
HttpStatus
.
OK
);
}
}
spring-boot-integration-tests/spring-boot-integration-tests-embedded-servlet-container/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerWarPackagingIntegrationTests.java
View file @
b527e714
...
...
@@ -16,6 +16,8 @@
package
org
.
springframework
.
boot
.
context
.
embedded
;
import
java.util.Arrays
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Parameterized
;
...
...
@@ -38,7 +40,9 @@ public class EmbeddedServletContainerWarPackagingIntegrationTests
@Parameters
(
name
=
"{0}"
)
public
static
Object
[]
parameters
()
{
return
AbstractEmbeddedServletContainerIntegrationTests
.
parameters
(
"war"
);
return
AbstractEmbeddedServletContainerIntegrationTests
.
parameters
(
"war"
,
Arrays
.
asList
(
PackagedApplicationLauncher
.
class
,
ExplodedApplicationLauncher
.
class
));
}
public
EmbeddedServletContainerWarPackagingIntegrationTests
(
String
name
,
...
...
spring-boot-integration-tests/spring-boot-integration-tests-embedded-servlet-container/src/test/java/org/springframework/boot/context/embedded/ExplodedApplicationLauncher.java
View file @
b527e714
...
...
@@ -29,8 +29,8 @@ import org.springframework.util.FileSystemUtils;
import
org.springframework.util.StreamUtils
;
/**
* {@link AbstractApplicationLauncher} that launches a
n exploded Spring Boot application
*
using Spring Boot's Jar or War launcher
.
* {@link AbstractApplicationLauncher} that launches a
Spring Boot application using
*
{@code JarLauncher} or {@code WarLauncher} and an exploded archive
.
*
* @author Andy Wilkinson
*/
...
...
@@ -42,6 +42,16 @@ class ExplodedApplicationLauncher extends AbstractApplicationLauncher {
super
(
applicationBuilder
);
}
@Override
protected
File
getWorkingDirectory
()
{
return
this
.
exploded
;
}
@Override
protected
String
getDescription
(
String
packaging
)
{
return
"exploded "
+
packaging
;
}
@Override
protected
List
<
String
>
getArguments
(
File
archive
)
{
String
mainClass
=
archive
.
getName
().
endsWith
(
".war"
)
...
...
spring-boot-integration-tests/spring-boot-integration-tests-embedded-servlet-container/src/test/java/org/springframework/boot/context/embedded/IdeApplicationLauncher.java
0 → 100644
View file @
b527e714
/*
* Copyright 2012-2017 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
.
context
.
embedded
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Enumeration
;
import
java.util.List
;
import
java.util.jar.JarEntry
;
import
java.util.jar.JarFile
;
import
org.springframework.util.FileSystemUtils
;
import
org.springframework.util.StreamUtils
;
import
org.springframework.util.StringUtils
;
/**
* {@link AbstractApplicationLauncher} that launches a Spring Boot application with a
* classpath similar to that used when run in an IDE.
*
* @author Andy Wilkinson
*/
class
IdeApplicationLauncher
extends
AbstractApplicationLauncher
{
private
final
File
exploded
=
new
File
(
"target/ide"
);
IdeApplicationLauncher
(
ApplicationBuilder
applicationBuilder
)
{
super
(
applicationBuilder
);
}
@Override
protected
File
getWorkingDirectory
()
{
return
this
.
exploded
;
}
@Override
protected
String
getDescription
(
String
packaging
)
{
return
"IDE run "
+
packaging
+
" project"
;
}
@Override
protected
List
<
String
>
getArguments
(
File
archive
)
{
try
{
explodeArchive
(
archive
,
this
.
exploded
);
deleteLauncherClasses
();
File
targetClasses
=
populateTargetClasses
(
archive
);
File
dependencies
=
populateDependencies
(
archive
);
File
resourcesProject
=
explodedResourcesProject
(
dependencies
);
populateSrcMainWebapp
();
List
<
String
>
classpath
=
new
ArrayList
<
String
>();
classpath
.
add
(
targetClasses
.
getAbsolutePath
());
for
(
File
dependency
:
dependencies
.
listFiles
())
{
classpath
.
add
(
dependency
.
getAbsolutePath
());
}
classpath
.
add
(
resourcesProject
.
getAbsolutePath
());
return
Arrays
.
asList
(
"-cp"
,
StringUtils
.
collectionToDelimitedString
(
classpath
,
File
.
pathSeparator
),
"com.example.ResourceHandlingApplication"
);
}
catch
(
IOException
ex
)
{
throw
new
RuntimeException
(
ex
);
}
}
private
File
populateTargetClasses
(
File
archive
)
{
File
targetClasses
=
new
File
(
this
.
exploded
,
"target/classes"
);
targetClasses
.
mkdirs
();
new
File
(
this
.
exploded
,
getClassesPath
(
archive
)).
renameTo
(
targetClasses
);
return
targetClasses
;
}
private
File
populateDependencies
(
File
archive
)
{
File
dependencies
=
new
File
(
this
.
exploded
,
"dependencies"
);
dependencies
.
mkdirs
();
List
<
String
>
libPaths
=
getLibPaths
(
archive
);
for
(
String
libPath
:
libPaths
)
{
for
(
File
jar
:
new
File
(
this
.
exploded
,
libPath
).
listFiles
())
{
jar
.
renameTo
(
new
File
(
dependencies
,
jar
.
getName
()));
}
}
return
dependencies
;
}
private
File
explodedResourcesProject
(
File
dependencies
)
throws
IOException
{
File
resourcesProject
=
new
File
(
this
.
exploded
,
"resources-project/target/classes"
);
File
resourcesJar
=
new
File
(
dependencies
,
"resources-1.0.jar"
);
explodeArchive
(
resourcesJar
,
resourcesProject
);
resourcesJar
.
delete
();
return
resourcesProject
;
}
private
void
populateSrcMainWebapp
()
{
File
srcMainWebapp
=
new
File
(
this
.
exploded
,
"src/main/webapp"
);
srcMainWebapp
.
mkdirs
();
new
File
(
this
.
exploded
,
"webapp-resource.txt"
)
.
renameTo
(
new
File
(
srcMainWebapp
,
"webapp-resource.txt"
));
}
private
void
deleteLauncherClasses
()
{
FileSystemUtils
.
deleteRecursively
(
new
File
(
this
.
exploded
,
"org"
));
}
private
String
getClassesPath
(
File
archive
)
{
return
archive
.
getName
().
endsWith
(
".jar"
)
?
"BOOT-INF/classes"
:
"WEB-INF/classes"
;
}
private
List
<
String
>
getLibPaths
(
File
archive
)
{
return
archive
.
getName
().
endsWith
(
".jar"
)
?
Collections
.
singletonList
(
"BOOT-INF/lib"
)
:
Arrays
.
asList
(
"WEB-INF/lib"
,
"WEB-INF/lib-provided"
);
}
private
void
explodeArchive
(
File
archive
,
File
destination
)
throws
IOException
{
FileSystemUtils
.
deleteRecursively
(
destination
);
JarFile
jarFile
=
new
JarFile
(
archive
);
Enumeration
<
JarEntry
>
entries
=
jarFile
.
entries
();
while
(
entries
.
hasMoreElements
())
{
JarEntry
jarEntry
=
entries
.
nextElement
();
File
extracted
=
new
File
(
destination
,
jarEntry
.
getName
());
if
(
jarEntry
.
isDirectory
())
{
extracted
.
mkdirs
();
}
else
{
FileOutputStream
extractedOutputStream
=
new
FileOutputStream
(
extracted
);
StreamUtils
.
copy
(
jarFile
.
getInputStream
(
jarEntry
),
extractedOutputStream
);
extractedOutputStream
.
close
();
}
}
jarFile
.
close
();
}
}
spring-boot-integration-tests/spring-boot-integration-tests-embedded-servlet-container/src/test/java/org/springframework/boot/context/embedded/PackagedApplicationLauncher.java
View file @
b527e714
...
...
@@ -32,6 +32,16 @@ class PackagedApplicationLauncher extends AbstractApplicationLauncher {
super
(
applicationBuilder
);
}
@Override
protected
File
getWorkingDirectory
()
{
return
null
;
}
@Override
protected
String
getDescription
(
String
packaging
)
{
return
"packaged "
+
packaging
;
}
@Override
protected
List
<
String
>
getArguments
(
File
archive
)
{
return
Arrays
.
asList
(
"-jar"
,
archive
.
getAbsolutePath
());
...
...
spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactory.java
View file @
b527e714
...
...
@@ -96,15 +96,23 @@ public abstract class AbstractEmbeddedServletContainerFactory
if
(
classLoader
instanceof
URLClassLoader
)
{
for
(
URL
url
:
((
URLClassLoader
)
classLoader
).
getURLs
())
{
try
{
URLConnection
connection
=
url
.
openConnection
();
if
(
connection
instanceof
JarURLConnection
)
{
JarURLConnection
jarConnection
=
(
JarURLConnection
)
connection
;
JarFile
jar
=
jarConnection
.
getJarFile
();
if
(
jar
.
getName
().
endsWith
(
".jar"
)
&&
jar
.
getJarEntry
(
"META-INF/resources"
)
!=
null
)
{
if
(
"file"
.
equals
(
url
.
getProtocol
()))
{
File
file
=
new
File
(
url
.
getFile
());
if
(
file
.
isDirectory
()
&&
new
File
(
file
,
"META-INF/resources"
).
isDirectory
())
{
staticResourceUrls
.
add
(
url
);
}
jar
.
close
();
else
if
(
isResourcesJar
(
file
))
{
staticResourceUrls
.
add
(
url
);
}
}
else
{
URLConnection
connection
=
url
.
openConnection
();
if
(
connection
instanceof
JarURLConnection
)
{
if
(
isResourcesJar
((
JarURLConnection
)
connection
))
{
staticResourceUrls
.
add
(
url
);
}
}
}
}
catch
(
IOException
ex
)
{
...
...
@@ -115,6 +123,34 @@ public abstract class AbstractEmbeddedServletContainerFactory
return
staticResourceUrls
;
}
private
boolean
isResourcesJar
(
JarURLConnection
connection
)
{
try
{
return
isResourcesJar
(
connection
.
getJarFile
());
}
catch
(
IOException
ex
)
{
return
false
;
}
}
private
boolean
isResourcesJar
(
File
file
)
{
try
{
return
isResourcesJar
(
new
JarFile
(
file
));
}
catch
(
IOException
ex
)
{
return
false
;
}
}
private
boolean
isResourcesJar
(
JarFile
jar
)
throws
IOException
{
try
{
return
jar
.
getName
().
endsWith
(
".jar"
)
&&
(
jar
.
getJarEntry
(
"META-INF/resources"
)
!=
null
);
}
finally
{
jar
.
close
();
}
}
File
getExplodedWarFileDocumentRoot
(
File
codeSourceFile
)
{
if
(
this
.
logger
.
isDebugEnabled
())
{
this
.
logger
.
debug
(
"Code archive: "
+
codeSourceFile
);
...
...
spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java
View file @
b527e714
...
...
@@ -392,8 +392,7 @@ public class JettyEmbeddedServletContainerFactory
root
.
isDirectory
()
?
Resource
.
newResource
(
root
.
getCanonicalFile
())
:
JarResource
.
newJarResource
(
Resource
.
newResource
(
root
)));
for
(
URL
resourceJarUrl
:
this
.
getUrlsOfJarsWithMetaInfResources
())
{
Resource
resource
=
Resource
.
newResource
(
resourceJarUrl
+
"META-INF/resources"
);
Resource
resource
=
createResource
(
resourceJarUrl
);
// Jetty 9.2 and earlier do not support nested jars. See
// https://github.com/eclipse/jetty.project/issues/518
if
(
resource
.
exists
()
&&
resource
.
isDirectory
())
{
...
...
@@ -408,6 +407,16 @@ public class JettyEmbeddedServletContainerFactory
}
}
private
Resource
createResource
(
URL
url
)
throws
IOException
{
if
(
"file"
.
equals
(
url
.
getProtocol
()))
{
File
file
=
new
File
(
url
.
getFile
());
if
(
file
.
isFile
())
{
return
Resource
.
newResource
(
"jar:"
+
url
+
"!/META-INF/resources"
);
}
}
return
Resource
.
newResource
(
url
+
"META-INF/resources"
);
}
/**
* Add Jetty's {@code DefaultServlet} to the given {@link WebAppContext}.
* @param context the jetty {@link WebAppContext}
...
...
spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java
View file @
b527e714
...
...
@@ -840,20 +840,23 @@ public class TomcatEmbeddedServletContainerFactory
// A jar file in the file system. Convert to Jar URL.
jar
=
"jar:"
+
jar
+
"!/"
;
}
addJar
(
jar
);
addResourceSet
(
jar
);
}
else
{
addResourceSet
(
url
.
toString
());
}
}
}
private
void
add
Jar
(
String
jar
)
{
private
void
add
ResourceSet
(
String
resource
)
{
try
{
if
(
isInsideNestedJar
(
jar
))
{
if
(
isInsideNestedJar
(
resource
))
{
// It's a nested jar but we now don't want the suffix because Tomcat
// is going to try and locate it as a root URL (not the resource
// inside it)
jar
=
jar
.
substring
(
0
,
jar
.
length
()
-
2
);
resource
=
resource
.
substring
(
0
,
resource
.
length
()
-
2
);
}
URL
url
=
new
URL
(
jar
);
URL
url
=
new
URL
(
resource
);
String
path
=
"/META-INF/resources"
;
this
.
context
.
getResources
().
createWebResourceSet
(
ResourceSetType
.
RESOURCE_JAR
,
"/"
,
url
,
path
);
...
...
spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatResources.java
0 → 100644
View file @
b527e714
/*
* Copyright 2012-2017 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
.
context
.
embedded
.
tomcat
;
import
java.lang.reflect.Method
;
import
java.net.MalformedURLException
;
import
java.net.URL
;
import
java.util.List
;
import
javax.naming.directory.DirContext
;
import
org.apache.catalina.Context
;
import
org.apache.catalina.WebResourceRoot.ResourceSetType
;
import
org.apache.catalina.core.StandardContext
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.ReflectionUtils
;
/**
* Abstraction to add resources that works with both Tomcat 8 and 7.
*
* @author Dave Syer
* @author Phillip Webb
* @author Andy Wilkinson
*/
abstract
class
TomcatResources
{
private
final
Context
context
;
TomcatResources
(
Context
context
)
{
this
.
context
=
context
;
}
void
addResourceJars
(
List
<
URL
>
resourceJarUrls
)
{
for
(
URL
url
:
resourceJarUrls
)
{
String
file
=
url
.
getFile
();
if
(
file
.
endsWith
(
".jar"
)
||
file
.
endsWith
(
".jar!/"
))
{
String
jar
=
url
.
toString
();
if
(!
jar
.
startsWith
(
"jar:"
))
{
// A jar file in the file system. Convert to Jar URL.
jar
=
"jar:"
+
jar
+
"!/"
;
}
addJar
(
jar
);
}
else
{
addDir
(
file
,
url
);
}
}
}
protected
final
Context
getContext
()
{
return
this
.
context
;
}
/**
* Called to add a JAR to the resources.
* @param jar the URL spec for the jar
*/
protected
abstract
void
addJar
(
String
jar
);
/**
* Called to add a dir to the resource.
* @param dir the dir
* @param url the URL
*/
protected
abstract
void
addDir
(
String
dir
,
URL
url
);
/**
* Return a {@link TomcatResources} instance for the currently running Tomcat version.
* @param context the tomcat context
* @return a {@link TomcatResources} instance.
*/
public
static
TomcatResources
get
(
Context
context
)
{
if
(
ClassUtils
.
isPresent
(
"org.apache.catalina.deploy.ErrorPage"
,
null
))
{
return
new
Tomcat7Resources
(
context
);
}
return
new
Tomcat8Resources
(
context
);
}
/**
* {@link TomcatResources} for Tomcat 7.
*/
private
static
class
Tomcat7Resources
extends
TomcatResources
{
private
final
Method
addResourceJarUrlMethod
;
Tomcat7Resources
(
Context
context
)
{
super
(
context
);
this
.
addResourceJarUrlMethod
=
ReflectionUtils
.
findMethod
(
context
.
getClass
(),
"addResourceJarUrl"
,
URL
.
class
);
}
@Override
protected
void
addJar
(
String
jar
)
{
URL
url
=
getJarUrl
(
jar
);
if
(
url
!=
null
)
{
try
{
this
.
addResourceJarUrlMethod
.
invoke
(
getContext
(),
url
);
}
catch
(
Exception
ex
)
{
throw
new
IllegalStateException
(
ex
);
}
}
}
private
URL
getJarUrl
(
String
jar
)
{
try
{
return
new
URL
(
jar
);
}
catch
(
MalformedURLException
ex
)
{
// Ignore
return
null
;
}
}
@Override
protected
void
addDir
(
String
dir
,
URL
url
)
{
if
(
getContext
()
instanceof
StandardContext
)
{
try
{
Class
<?>
fileDirContextClass
=
Class
.
forName
(
"org.apache.naming.resources.FileDirContext"
);
Method
setDocBaseMethod
=
ReflectionUtils
.
findMethod
(
fileDirContextClass
,
"setDocBase"
,
String
.
class
);
Object
fileDirContext
=
fileDirContextClass
.
newInstance
();
setDocBaseMethod
.
invoke
(
fileDirContext
,
dir
);
Method
addResourcesDirContextMethod
=
ReflectionUtils
.
findMethod
(
StandardContext
.
class
,
"addResourcesDirContext"
,
DirContext
.
class
);
addResourcesDirContextMethod
.
invoke
(
getContext
(),
fileDirContext
);
}
catch
(
Exception
ex
)
{
throw
new
IllegalStateException
(
"Tomcat 7 reflection failed"
,
ex
);
}
}
}
}
/**
* {@link TomcatResources} for Tomcat 8.
*/
static
class
Tomcat8Resources
extends
TomcatResources
{
Tomcat8Resources
(
Context
context
)
{
super
(
context
);
}
@Override
protected
void
addJar
(
String
jar
)
{
addResourceSet
(
jar
);
}
@Override
protected
void
addDir
(
String
dir
,
URL
url
)
{
addResourceSet
(
url
.
toString
());
}
private
void
addResourceSet
(
String
resource
)
{
try
{
if
(
isInsideNestedJar
(
resource
))
{
// It's a nested jar but we now don't want the suffix because Tomcat
// is going to try and locate it as a root URL (not the resource
// inside it)
resource
=
resource
.
substring
(
0
,
resource
.
length
()
-
2
);
}
URL
url
=
new
URL
(
resource
);
String
path
=
"/META-INF/resources"
;
getContext
().
getResources
().
createWebResourceSet
(
ResourceSetType
.
RESOURCE_JAR
,
"/"
,
url
,
path
);
}
catch
(
Exception
ex
)
{
// Ignore (probably not a directory)
}
}
private
boolean
isInsideNestedJar
(
String
dir
)
{
return
dir
.
indexOf
(
"!/"
)
<
dir
.
lastIndexOf
(
"!/"
);
}
}
}
spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java
View file @
b527e714
...
...
@@ -18,6 +18,7 @@ package org.springframework.boot.context.embedded.undertow;
import
java.io.File
;
import
java.io.IOException
;
import
java.net.MalformedURLException
;
import
java.net.URL
;
import
java.net.URLConnection
;
import
java.nio.charset.Charset
;
...
...
@@ -464,11 +465,35 @@ public class UndertowEmbeddedServletContainerFactory
private
ResourceManager
getDocumentRootResourceManager
()
{
File
root
=
getCanonicalDocumentRoot
();
List
<
URL
>
metaInfResourceJarUrls
=
getUrlsOfJarsWithMetaInfResources
();
List
<
URL
>
metaInfResourceUrls
=
getUrlsOfJarsWithMetaInfResources
();
List
<
URL
>
resourceJarUrls
=
new
ArrayList
<
URL
>();
List
<
ResourceManager
>
resourceManagers
=
new
ArrayList
<
ResourceManager
>();
ResourceManager
rootResourceManager
=
root
.
isDirectory
()
?
new
FileResourceManager
(
root
,
0
)
:
new
JarResourceManager
(
root
);
return
new
CompositeResourceManager
(
rootResourceManager
,
new
MetaInfResourcesResourceManager
(
metaInfResourceJarUrls
));
resourceManagers
.
add
(
rootResourceManager
);
for
(
URL
url
:
metaInfResourceUrls
)
{
if
(
"file"
.
equals
(
url
.
getProtocol
()))
{
File
file
=
new
File
(
url
.
getFile
());
if
(
file
.
isFile
())
{
try
{
resourceJarUrls
.
add
(
new
URL
(
"jar:"
+
url
+
"!/"
));
}
catch
(
MalformedURLException
ex
)
{
throw
new
RuntimeException
(
ex
);
}
}
else
{
resourceManagers
.
add
(
new
FileResourceManager
(
new
File
(
file
,
"META-INF/resources"
),
0
));
}
}
else
{
resourceJarUrls
.
add
(
url
);
}
}
resourceManagers
.
add
(
new
MetaInfResourcesResourceManager
(
resourceJarUrls
));
return
new
CompositeResourceManager
(
resourceManagers
.
toArray
(
new
ResourceManager
[
resourceManagers
.
size
()]));
}
/**
...
...
@@ -618,12 +643,17 @@ public class UndertowEmbeddedServletContainerFactory
}
@Override
public
Resource
getResource
(
String
path
)
throws
IOException
{
public
Resource
getResource
(
String
path
)
{
for
(
URL
url
:
this
.
metaInfResourceJarUrls
)
{
URL
resourceUrl
=
new
URL
(
url
+
"META-INF/resources"
+
path
);
URLConnection
connection
=
resourceUrl
.
openConnection
();
if
(
connection
.
getContentLength
()
>=
0
)
{
return
new
URLResource
(
resourceUrl
,
connection
,
path
);
try
{
URL
resourceUrl
=
new
URL
(
url
+
"META-INF/resources"
+
path
);
URLConnection
connection
=
resourceUrl
.
openConnection
();
if
(
connection
.
getContentLength
()
>=
0
)
{
return
new
URLResource
(
resourceUrl
,
connection
,
path
);
}
}
catch
(
IOException
ex
)
{
// Continue
}
}
return
null
;
...
...
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