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
eff0fc02
Commit
eff0fc02
authored
Nov 17, 2016
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '1.4.x' into 1.5.x
parents
7b742fd7
918e122d
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
917 additions
and
2 deletions
+917
-2
ClassLoaderFilesResourcePatternResolver.java
...ools/restart/ClassLoaderFilesResourcePatternResolver.java
+165
-0
Restarter.java
.../org/springframework/boot/devtools/restart/Restarter.java
+5
-0
ClassLoaderFileURLStreamHandler.java
.../restart/classloader/ClassLoaderFileURLStreamHandler.java
+2
-2
pom.xml
spring-boot-integration-tests/pom.xml
+1
-0
pom.xml
...boot-integration-tests/spring-boot-devtools-tests/pom.xml
+90
-0
ControllerOne.java
...vtools-tests/src/test/java/com/example/ControllerOne.java
+30
-0
DevToolsTestApplication.java
...ts/src/test/java/com/example/DevToolsTestApplication.java
+32
-0
ApplicationLauncher.java
...ingframework/boot/devtools/tests/ApplicationLauncher.java
+28
-0
DevToolsIntegrationTests.java
...amework/boot/devtools/tests/DevToolsIntegrationTests.java
+191
-0
ExplodedRemoteApplicationLauncher.java
...oot/devtools/tests/ExplodedRemoteApplicationLauncher.java
+54
-0
JarFileRemoteApplicationLauncher.java
...boot/devtools/tests/JarFileRemoteApplicationLauncher.java
+86
-0
JavaLauncher.java
...org/springframework/boot/devtools/tests/JavaLauncher.java
+53
-0
LaunchedApplication.java
...ingframework/boot/devtools/tests/LaunchedApplication.java
+47
-0
LocalApplicationLauncher.java
...amework/boot/devtools/tests/LocalApplicationLauncher.java
+60
-0
RemoteApplicationLauncher.java
...mework/boot/devtools/tests/RemoteApplicationLauncher.java
+67
-0
pom.xml
spring-boot-parent/pom.xml
+5
-0
checkstyle-suppressions.xml
...ng-boot-parent/src/checkstyle/checkstyle-suppressions.xml
+1
-0
No files found.
spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/ClassLoaderFilesResourcePatternResolver.java
0 → 100644
View file @
eff0fc02
/*
* Copyright 2012-2016 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
.
devtools
.
restart
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.net.MalformedURLException
;
import
java.net.URL
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map.Entry
;
import
java.util.Set
;
import
org.springframework.boot.devtools.restart.classloader.ClassLoaderFile
;
import
org.springframework.boot.devtools.restart.classloader.ClassLoaderFile.Kind
;
import
org.springframework.boot.devtools.restart.classloader.ClassLoaderFileURLStreamHandler
;
import
org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles
;
import
org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles.SourceFolder
;
import
org.springframework.core.io.AbstractResource
;
import
org.springframework.core.io.Resource
;
import
org.springframework.core.io.UrlResource
;
import
org.springframework.core.io.support.PathMatchingResourcePatternResolver
;
import
org.springframework.core.io.support.ResourcePatternResolver
;
import
org.springframework.util.AntPathMatcher
;
/**
* A {@code ResourcePatternResolver} that considers {@link ClassLoaderFiles} when
* resolving resources.
*
* @author Andy Wilkinson
*/
final
class
ClassLoaderFilesResourcePatternResolver
implements
ResourcePatternResolver
{
private
static
final
Set
<
String
>
LOCATION_PATTERN_PREFIXES
=
Collections
.
unmodifiableSet
(
new
HashSet
<
String
>(
Arrays
.
asList
(
CLASSPATH_ALL_URL_PREFIX
,
CLASSPATH_URL_PREFIX
)));
private
final
ResourcePatternResolver
delegate
=
new
PathMatchingResourcePatternResolver
();
private
final
AntPathMatcher
antPathMatcher
=
new
AntPathMatcher
();
private
final
ClassLoaderFiles
classLoaderFiles
;
ClassLoaderFilesResourcePatternResolver
(
ClassLoaderFiles
classLoaderFiles
)
{
this
.
classLoaderFiles
=
classLoaderFiles
;
}
@Override
public
Resource
getResource
(
String
location
)
{
Resource
candidate
=
this
.
delegate
.
getResource
(
location
);
if
(
isExcludedResource
(
candidate
))
{
return
new
DeletedClassLoaderFileResource
(
location
);
}
return
candidate
;
}
@Override
public
ClassLoader
getClassLoader
()
{
return
this
.
delegate
.
getClassLoader
();
}
@Override
public
Resource
[]
getResources
(
String
locationPattern
)
throws
IOException
{
List
<
Resource
>
resources
=
new
ArrayList
<
Resource
>();
Resource
[]
candidates
=
this
.
delegate
.
getResources
(
locationPattern
);
for
(
Resource
candidate
:
candidates
)
{
if
(!
isExcludedResource
(
candidate
))
{
resources
.
add
(
candidate
);
}
}
resources
.
addAll
(
getAdditionalResources
(
locationPattern
));
return
resources
.
toArray
(
new
Resource
[
resources
.
size
()]);
}
private
String
trimLocationPattern
(
String
locationPattern
)
{
for
(
String
prefix
:
LOCATION_PATTERN_PREFIXES
)
{
if
(
locationPattern
.
startsWith
(
prefix
))
{
return
locationPattern
.
substring
(
prefix
.
length
());
}
}
return
locationPattern
;
}
private
List
<
Resource
>
getAdditionalResources
(
String
locationPattern
)
throws
MalformedURLException
{
List
<
Resource
>
additionalResources
=
new
ArrayList
<
Resource
>();
String
trimmedLocationPattern
=
trimLocationPattern
(
locationPattern
);
for
(
SourceFolder
sourceFolder
:
this
.
classLoaderFiles
.
getSourceFolders
())
{
for
(
Entry
<
String
,
ClassLoaderFile
>
entry
:
sourceFolder
.
getFilesEntrySet
())
{
if
(
entry
.
getValue
().
getKind
()
==
Kind
.
ADDED
&&
this
.
antPathMatcher
.
match
(
trimmedLocationPattern
,
entry
.
getKey
()))
{
additionalResources
.
add
(
new
UrlResource
(
new
URL
(
"reloaded"
,
null
,
-
1
,
"/"
+
entry
.
getKey
(),
new
ClassLoaderFileURLStreamHandler
(
entry
.
getValue
()))));
}
}
}
return
additionalResources
;
}
private
boolean
isExcludedResource
(
Resource
resource
)
{
for
(
SourceFolder
sourceFolder
:
this
.
classLoaderFiles
.
getSourceFolders
())
{
for
(
Entry
<
String
,
ClassLoaderFile
>
entry
:
sourceFolder
.
getFilesEntrySet
())
{
try
{
if
(
entry
.
getValue
().
getKind
()
==
Kind
.
DELETED
&&
resource
.
exists
()
&&
resource
.
getURI
().
toString
().
endsWith
(
entry
.
getKey
()))
{
return
true
;
}
}
catch
(
IOException
ex
)
{
throw
new
IllegalStateException
(
"Failed to retrieve URI from '"
+
resource
+
"'"
,
ex
);
}
}
}
return
false
;
}
/**
* A {@link Resource} that represents a {@link ClassLoaderFile} that has been
* {@link Kind#DELETED deleted}.
*
* @author Andy Wilkinson
*/
private
final
class
DeletedClassLoaderFileResource
extends
AbstractResource
{
private
final
String
name
;
private
DeletedClassLoaderFileResource
(
String
name
)
{
this
.
name
=
name
;
}
@Override
public
boolean
exists
()
{
return
false
;
}
@Override
public
String
getDescription
()
{
return
"Deleted: "
+
this
.
name
;
}
@Override
public
InputStream
getInputStream
()
throws
IOException
{
throw
new
IOException
(
this
.
name
+
" has been deleted"
);
}
}
}
\ No newline at end of file
spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/Restarter.java
View file @
eff0fc02
...
...
@@ -49,6 +49,7 @@ import org.springframework.boot.devtools.restart.classloader.RestartClassLoader;
import
org.springframework.boot.logging.DeferredLog
;
import
org.springframework.cglib.core.ClassNameReader
;
import
org.springframework.context.ConfigurableApplicationContext
;
import
org.springframework.context.support.GenericApplicationContext
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.util.Assert
;
...
...
@@ -419,6 +420,10 @@ public class Restarter {
if
(
applicationContext
!=
null
&&
applicationContext
.
getParent
()
!=
null
)
{
return
;
}
if
(
applicationContext
instanceof
GenericApplicationContext
)
{
((
GenericApplicationContext
)
applicationContext
).
setResourceLoader
(
new
ClassLoaderFilesResourcePatternResolver
(
this
.
classLoaderFiles
));
}
this
.
rootContexts
.
add
(
applicationContext
);
}
...
...
spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/classloader/ClassLoaderFileURLStreamHandler.java
View file @
eff0fc02
...
...
@@ -28,11 +28,11 @@ import java.net.URLStreamHandler;
*
* @author Phillip Webb
*/
class
ClassLoaderFileURLStreamHandler
extends
URLStreamHandler
{
public
class
ClassLoaderFileURLStreamHandler
extends
URLStreamHandler
{
private
ClassLoaderFile
file
;
ClassLoaderFileURLStreamHandler
(
ClassLoaderFile
file
)
{
public
ClassLoaderFileURLStreamHandler
(
ClassLoaderFile
file
)
{
this
.
file
=
file
;
}
...
...
spring-boot-integration-tests/pom.xml
View file @
eff0fc02
...
...
@@ -21,6 +21,7 @@
<java.version>
1.8
</java.version>
</properties>
<modules>
<module>
spring-boot-devtools-tests
</module>
<module>
spring-boot-gradle-tests
</module>
<module>
spring-boot-launch-script-tests
</module>
<module>
spring-boot-security-tests
</module>
...
...
spring-boot-integration-tests/spring-boot-devtools-tests/pom.xml
0 → 100644
View file @
eff0fc02
<?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>
<parent>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-integration-tests
</artifactId>
<version>
1.5.0.BUILD-SNAPSHOT
</version>
</parent>
<artifactId>
spring-boot-devtools-tests
</artifactId>
<name>
Spring Boot DevTools Tests
</name>
<description>
${project.name}
</description>
<url>
http://projects.spring.io/spring-boot/
</url>
<organization>
<name>
Pivotal Software, Inc.
</name>
<url>
http://www.spring.io
</url>
</organization>
<properties>
<main.basedir>
${basedir}/../..
</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-devtools
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
net.bytebuddy
</groupId>
<artifactId>
byte-buddy
</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-dependency-plugin
</artifactId>
<executions>
<execution>
<id>
copy-dependencies
</id>
<phase>
process-test-resources
</phase>
<goals>
<goal>
copy-dependencies
</goal>
</goals>
<configuration>
<includeScope>
runtime
</includeScope>
<outputDirectory>
${project.build.directory}/dependencies
</outputDirectory>
<overWriteSnapshots>
true
</overWriteSnapshots>
<overWriteIfNewer>
true
</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>
org.eclipse.m2e
</groupId>
<artifactId>
lifecycle-mapping
</artifactId>
<version>
1.0.0
</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-dependency-plugin
</artifactId>
<versionRange>
[2.10,)
</versionRange>
<goals>
<goal>
copy-dependencies
</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/com/example/ControllerOne.java
0 → 100644
View file @
eff0fc02
/*
* Copyright 2012-2016 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
com
.
example
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
@RestController
public
class
ControllerOne
{
@RequestMapping
(
"/one"
)
public
String
one
()
{
return
"one"
;
}
}
spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/com/example/DevToolsTestApplication.java
0 → 100644
View file @
eff0fc02
/*
* Copyright 2012-2016 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
com
.
example
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.builder.SpringApplicationBuilder
;
import
org.springframework.boot.system.EmbeddedServerPortFileWriter
;
@SpringBootApplication
public
class
DevToolsTestApplication
{
public
static
void
main
(
String
[]
args
)
{
new
SpringApplicationBuilder
(
DevToolsTestApplication
.
class
)
.
listeners
(
new
EmbeddedServerPortFileWriter
(
"target/server.port"
))
.
run
(
args
);
}
}
spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/ApplicationLauncher.java
0 → 100644
View file @
eff0fc02
/*
* Copyright 2012-2016 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
.
devtools
.
tests
;
/**
* Launches an application with DevTools.
*
* @author Andy Wilkinson
*/
public
interface
ApplicationLauncher
{
LaunchedApplication
launchApplication
(
JavaLauncher
javaLauncher
)
throws
Exception
;
}
spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/DevToolsIntegrationTests.java
0 → 100644
View file @
eff0fc02
/*
* Copyright 2012-2016 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
.
devtools
.
tests
;
import
java.io.File
;
import
java.io.FileReader
;
import
java.util.ArrayList
;
import
java.util.List
;
import
net.bytebuddy.ByteBuddy
;
import
net.bytebuddy.description.annotation.AnnotationDescription
;
import
net.bytebuddy.description.modifier.Visibility
;
import
net.bytebuddy.dynamic.DynamicType.Builder
;
import
net.bytebuddy.implementation.FixedValue
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Parameterized
;
import
org.junit.runners.Parameterized.Parameters
;
import
org.springframework.boot.test.web.client.TestRestTemplate
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.util.FileCopyUtils
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Integration tests for DevTools.
*
* @author Andy Wilkinson
*/
@RunWith
(
Parameterized
.
class
)
public
class
DevToolsIntegrationTests
{
private
LaunchedApplication
launchedApplication
;
private
final
File
serverPortFile
=
new
File
(
"target/server.port"
);
private
final
ApplicationLauncher
applicationLauncher
;
@Rule
public
JavaLauncher
javaLauncher
=
new
JavaLauncher
();
@Parameters
(
name
=
"{0}"
)
public
static
Object
[]
parameters
()
{
return
new
Object
[]
{
new
Object
[]
{
new
LocalApplicationLauncher
()
},
new
Object
[]
{
new
ExplodedRemoteApplicationLauncher
()
},
new
Object
[]
{
new
JarFileRemoteApplicationLauncher
()
}
};
}
public
DevToolsIntegrationTests
(
ApplicationLauncher
applicationLauncher
)
{
this
.
applicationLauncher
=
applicationLauncher
;
}
@Before
public
void
launchApplication
()
throws
Exception
{
this
.
serverPortFile
.
delete
();
this
.
launchedApplication
=
this
.
applicationLauncher
.
launchApplication
(
this
.
javaLauncher
);
}
@After
public
void
stopApplication
()
{
this
.
launchedApplication
.
stop
();
}
@Test
public
void
addARequestMappingToAnExistingController
()
throws
Exception
{
TestRestTemplate
template
=
new
TestRestTemplate
();
String
urlBase
=
"http://localhost:"
+
awaitServerPort
()
+
"/"
;
assertThat
(
template
.
getForObject
(
urlBase
+
"/one"
,
String
.
class
))
.
isEqualTo
(
"one"
);
assertThat
(
template
.
getForEntity
(
urlBase
+
"/two"
,
String
.
class
).
getStatusCode
())
.
isEqualTo
(
HttpStatus
.
NOT_FOUND
);
controller
(
"com.example.ControllerOne"
).
withRequestMapping
(
"one"
)
.
withRequestMapping
(
"two"
).
build
();
assertThat
(
template
.
getForObject
(
urlBase
+
"/one"
,
String
.
class
))
.
isEqualTo
(
"one"
);
assertThat
(
template
.
getForObject
(
"http://localhost:"
+
awaitServerPort
()
+
"/two"
,
String
.
class
)).
isEqualTo
(
"two"
);
}
@Test
public
void
removeARequestMappingFromAnExistingController
()
throws
Exception
{
TestRestTemplate
template
=
new
TestRestTemplate
();
assertThat
(
template
.
getForObject
(
"http://localhost:"
+
awaitServerPort
()
+
"/one"
,
String
.
class
)).
isEqualTo
(
"one"
);
controller
(
"com.example.ControllerOne"
).
build
();
assertThat
(
template
.
getForEntity
(
"http://localhost:"
+
awaitServerPort
()
+
"/one"
,
String
.
class
).
getStatusCode
()).
isEqualTo
(
HttpStatus
.
NOT_FOUND
);
}
@Test
public
void
createAController
()
throws
Exception
{
TestRestTemplate
template
=
new
TestRestTemplate
();
String
urlBase
=
"http://localhost:"
+
awaitServerPort
()
+
"/"
;
assertThat
(
template
.
getForObject
(
urlBase
+
"/one"
,
String
.
class
))
.
isEqualTo
(
"one"
);
assertThat
(
template
.
getForEntity
(
urlBase
+
"/two"
,
String
.
class
).
getStatusCode
())
.
isEqualTo
(
HttpStatus
.
NOT_FOUND
);
controller
(
"com.example.ControllerTwo"
).
withRequestMapping
(
"two"
).
build
();
assertThat
(
template
.
getForObject
(
urlBase
+
"/one"
,
String
.
class
))
.
isEqualTo
(
"one"
);
assertThat
(
template
.
getForObject
(
"http://localhost:"
+
awaitServerPort
()
+
"/two"
,
String
.
class
)).
isEqualTo
(
"two"
);
}
@Test
public
void
deleteAController
()
throws
Exception
{
TestRestTemplate
template
=
new
TestRestTemplate
();
assertThat
(
template
.
getForObject
(
"http://localhost:"
+
awaitServerPort
()
+
"/one"
,
String
.
class
)).
isEqualTo
(
"one"
);
assertThat
(
new
File
(
this
.
launchedApplication
.
getClassesDirectory
(),
"com/example/ControllerOne.class"
).
delete
()).
isTrue
();
assertThat
(
template
.
getForEntity
(
"http://localhost:"
+
awaitServerPort
()
+
"/one"
,
String
.
class
).
getStatusCode
()).
isEqualTo
(
HttpStatus
.
NOT_FOUND
);
}
private
int
awaitServerPort
()
throws
Exception
{
long
end
=
System
.
currentTimeMillis
()
+
20000
;
while
(!
this
.
serverPortFile
.
exists
())
{
if
(
System
.
currentTimeMillis
()
>
end
)
{
throw
new
IllegalStateException
(
"server.port file was not written within 20 seconds"
);
}
Thread
.
sleep
(
100
);
}
int
port
=
Integer
.
valueOf
(
FileCopyUtils
.
copyToString
(
new
FileReader
(
this
.
serverPortFile
)));
this
.
serverPortFile
.
delete
();
return
port
;
}
private
ControllerBuilder
controller
(
String
name
)
{
return
new
ControllerBuilder
(
name
,
this
.
launchedApplication
.
getClassesDirectory
());
}
private
static
final
class
ControllerBuilder
{
private
final
List
<
String
>
mappings
=
new
ArrayList
<
String
>();
private
final
String
name
;
private
final
File
classesDirectory
;
private
ControllerBuilder
(
String
name
,
File
classesDirectory
)
{
this
.
name
=
name
;
this
.
classesDirectory
=
classesDirectory
;
}
public
ControllerBuilder
withRequestMapping
(
String
mapping
)
{
this
.
mappings
.
add
(
mapping
);
return
this
;
}
public
void
build
()
throws
Exception
{
Builder
<
Object
>
builder
=
new
ByteBuddy
().
subclass
(
Object
.
class
)
.
name
(
this
.
name
).
annotateType
(
AnnotationDescription
.
Builder
.
ofType
(
RestController
.
class
).
build
());
for
(
String
mapping
:
this
.
mappings
)
{
builder
=
builder
.
defineMethod
(
mapping
,
String
.
class
,
Visibility
.
PUBLIC
)
.
intercept
(
FixedValue
.
value
(
mapping
)).
annotateMethod
(
AnnotationDescription
.
Builder
.
ofType
(
RequestMapping
.
class
)
.
defineArray
(
"value"
,
mapping
).
build
());
}
builder
.
make
().
saveIn
(
this
.
classesDirectory
);
}
}
}
spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/ExplodedRemoteApplicationLauncher.java
0 → 100644
View file @
eff0fc02
/*
* Copyright 2012-2016 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
.
devtools
.
tests
;
import
java.io.File
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.springframework.util.FileSystemUtils
;
import
org.springframework.util.StringUtils
;
/**
* {@link ApplicationLauncher} that launches a remote application with its classes
* available directly on the file system.
*
* @author Andy Wilkinson
*/
public
class
ExplodedRemoteApplicationLauncher
extends
RemoteApplicationLauncher
{
@Override
protected
String
createApplicationClassPath
()
throws
Exception
{
File
appDirectory
=
new
File
(
"target/app"
);
FileSystemUtils
.
deleteRecursively
(
appDirectory
);
appDirectory
.
mkdirs
();
FileSystemUtils
.
copyRecursively
(
new
File
(
"target/test-classes/com"
),
new
File
(
"target/app/com"
));
List
<
String
>
entries
=
new
ArrayList
<
String
>();
entries
.
add
(
"target/app"
);
for
(
File
jar
:
new
File
(
"target/dependencies"
).
listFiles
())
{
entries
.
add
(
jar
.
getAbsolutePath
());
}
return
StringUtils
.
collectionToDelimitedString
(
entries
,
File
.
pathSeparator
);
}
@Override
public
String
toString
()
{
return
"exploded remote"
;
}
}
spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/JarFileRemoteApplicationLauncher.java
0 → 100644
View file @
eff0fc02
/*
* Copyright 2012-2016 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
.
devtools
.
tests
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.jar.Attributes
;
import
java.util.jar.JarOutputStream
;
import
java.util.jar.Manifest
;
import
java.util.zip.ZipEntry
;
import
org.springframework.util.FileSystemUtils
;
import
org.springframework.util.StreamUtils
;
import
org.springframework.util.StringUtils
;
/**
* {@link ApplicationLauncher} that launches a remote application with its classes in a
* jar file.
*
* @author Andy Wilkinson
*/
public
class
JarFileRemoteApplicationLauncher
extends
RemoteApplicationLauncher
{
@Override
protected
String
createApplicationClassPath
()
throws
Exception
{
File
appDirectory
=
new
File
(
"target/app"
);
FileSystemUtils
.
deleteRecursively
(
appDirectory
);
appDirectory
.
mkdirs
();
Manifest
manifest
=
new
Manifest
();
manifest
.
getMainAttributes
().
put
(
Attributes
.
Name
.
MANIFEST_VERSION
,
"1.0"
);
JarOutputStream
output
=
new
JarOutputStream
(
new
FileOutputStream
(
new
File
(
appDirectory
,
"app.jar"
)),
manifest
);
FileSystemUtils
.
copyRecursively
(
new
File
(
"target/test-classes/com"
),
new
File
(
"target/app/com"
));
addToJar
(
output
,
new
File
(
"target/app/"
),
new
File
(
"target/app/"
));
output
.
close
();
List
<
String
>
entries
=
new
ArrayList
<
String
>();
entries
.
add
(
"target/app/app.jar"
);
for
(
File
jar
:
new
File
(
"target/dependencies"
).
listFiles
())
{
entries
.
add
(
jar
.
getAbsolutePath
());
}
String
classpath
=
StringUtils
.
collectionToDelimitedString
(
entries
,
File
.
pathSeparator
);
return
classpath
;
}
private
void
addToJar
(
JarOutputStream
output
,
File
root
,
File
current
)
throws
IOException
{
for
(
File
file
:
current
.
listFiles
())
{
if
(
file
.
isDirectory
())
{
addToJar
(
output
,
root
,
file
);
}
output
.
putNextEntry
(
new
ZipEntry
(
file
.
getAbsolutePath
().
substring
(
root
.
getAbsolutePath
().
length
()
+
1
)
+
(
file
.
isDirectory
()
?
"/"
:
""
)));
if
(
file
.
isFile
())
{
StreamUtils
.
copy
(
new
FileInputStream
(
file
),
output
);
}
output
.
closeEntry
();
}
}
@Override
public
String
toString
()
{
return
"jar file remote"
;
}
}
spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/JavaLauncher.java
0 → 100644
View file @
eff0fc02
/*
* Copyright 2012-2016 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
.
devtools
.
tests
;
import
java.io.File
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
org.junit.rules.TestRule
;
import
org.junit.runner.Description
;
import
org.junit.runners.model.Statement
;
/**
* @author awilkinson
*/
public
class
JavaLauncher
implements
TestRule
{
private
File
outputDirectory
;
@Override
public
Statement
apply
(
Statement
base
,
Description
description
)
{
this
.
outputDirectory
=
new
File
(
"target/output/"
+
"/"
+
description
.
getMethodName
().
replaceAll
(
"[^A-Za-z]+"
,
""
));
this
.
outputDirectory
.
mkdirs
();
return
base
;
}
Process
launch
(
String
name
,
String
classpath
,
String
...
args
)
throws
IOException
{
List
<
String
>
command
=
new
ArrayList
<
String
>(
Arrays
.
asList
(
System
.
getProperty
(
"java.home"
)
+
"/bin/java"
,
"-cp"
,
classpath
));
command
.
addAll
(
Arrays
.
asList
(
args
));
return
new
ProcessBuilder
(
command
.
toArray
(
new
String
[
command
.
size
()]))
.
redirectError
(
new
File
(
this
.
outputDirectory
,
name
+
".err"
))
.
redirectOutput
(
new
File
(
this
.
outputDirectory
,
name
+
".out"
)).
start
();
}
}
spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/LaunchedApplication.java
0 → 100644
View file @
eff0fc02
/*
* Copyright 2012-2016 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
.
devtools
.
tests
;
import
java.io.File
;
/**
* An application launched by {@link ApplicationLauncher}.
*
* @author Andy Wilkinson
*/
class
LaunchedApplication
{
private
final
File
classesDirectory
;
private
final
Process
[]
processes
;
LaunchedApplication
(
File
classesDirectory
,
Process
...
processes
)
{
this
.
classesDirectory
=
classesDirectory
;
this
.
processes
=
processes
;
}
void
stop
()
{
for
(
Process
process
:
this
.
processes
)
{
process
.
destroy
();
}
}
File
getClassesDirectory
()
{
return
this
.
classesDirectory
;
}
}
spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/LocalApplicationLauncher.java
0 → 100644
View file @
eff0fc02
/*
* Copyright 2012-2016 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
.
devtools
.
tests
;
import
java.io.File
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.springframework.util.FileSystemUtils
;
import
org.springframework.util.StringUtils
;
/**
* {@link ApplicationLauncher} that launches a local application with DevTools enabled.
*
* @author Andy Wilkinson
*/
public
class
LocalApplicationLauncher
implements
ApplicationLauncher
{
@Override
public
LaunchedApplication
launchApplication
(
JavaLauncher
javaLauncher
)
throws
Exception
{
Process
process
=
javaLauncher
.
launch
(
"local"
,
createApplicationClassPath
(),
"com.example.DevToolsTestApplication"
,
"--server.port=0"
);
return
new
LaunchedApplication
(
new
File
(
"target/app"
),
process
);
}
protected
String
createApplicationClassPath
()
throws
Exception
{
File
appDirectory
=
new
File
(
"target/app"
);
FileSystemUtils
.
deleteRecursively
(
appDirectory
);
appDirectory
.
mkdirs
();
FileSystemUtils
.
copyRecursively
(
new
File
(
"target/test-classes/com"
),
new
File
(
"target/app/com"
));
List
<
String
>
entries
=
new
ArrayList
<
String
>();
entries
.
add
(
"target/app"
);
for
(
File
jar
:
new
File
(
"target/dependencies"
).
listFiles
())
{
entries
.
add
(
jar
.
getAbsolutePath
());
}
return
StringUtils
.
collectionToDelimitedString
(
entries
,
File
.
pathSeparator
);
}
@Override
public
String
toString
()
{
return
"local"
;
}
}
spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/RemoteApplicationLauncher.java
0 → 100644
View file @
eff0fc02
/*
* Copyright 2012-2016 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
.
devtools
.
tests
;
import
java.io.File
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.springframework.boot.devtools.RemoteSpringApplication
;
import
org.springframework.util.FileSystemUtils
;
import
org.springframework.util.SocketUtils
;
import
org.springframework.util.StringUtils
;
/**
* Base class for {@link ApplicationLauncher} implementations that use
* {@link RemoteSpringApplication}.
*
* @author Andy Wilkinson
*/
abstract
class
RemoteApplicationLauncher
implements
ApplicationLauncher
{
@Override
public
LaunchedApplication
launchApplication
(
JavaLauncher
javaLauncher
)
throws
Exception
{
int
port
=
SocketUtils
.
findAvailableTcpPort
();
Process
application
=
javaLauncher
.
launch
(
"app"
,
createApplicationClassPath
(),
"com.example.DevToolsTestApplication"
,
"--server.port="
+
port
,
"--spring.devtools.remote.secret=secret"
);
Process
remoteSpringApplication
=
javaLauncher
.
launch
(
"remote-spring-application"
,
createRemoteSpringApplicationClassPath
(),
RemoteSpringApplication
.
class
.
getName
(),
"--spring.devtools.remote.secret=secret"
,
"http://localhost:"
+
port
);
return
new
LaunchedApplication
(
new
File
(
"target/remote"
),
application
,
remoteSpringApplication
);
}
protected
abstract
String
createApplicationClassPath
()
throws
Exception
;
private
String
createRemoteSpringApplicationClassPath
()
throws
Exception
{
File
remoteDirectory
=
new
File
(
"target/remote"
);
FileSystemUtils
.
deleteRecursively
(
remoteDirectory
);
remoteDirectory
.
mkdirs
();
FileSystemUtils
.
copyRecursively
(
new
File
(
"target/test-classes/com"
),
new
File
(
"target/remote/com"
));
List
<
String
>
entries
=
new
ArrayList
<
String
>();
entries
.
add
(
"target/remote"
);
for
(
File
jar
:
new
File
(
"target/dependencies"
).
listFiles
())
{
entries
.
add
(
jar
.
getAbsolutePath
());
}
return
StringUtils
.
collectionToDelimitedString
(
entries
,
File
.
pathSeparator
);
}
}
spring-boot-parent/pom.xml
View file @
eff0fc02
...
...
@@ -77,6 +77,11 @@
<artifactId>
jline
</artifactId>
<version>
2.11
</version>
</dependency>
<dependency>
<groupId>
net.bytebuddy
</groupId>
<artifactId>
byte-buddy
</artifactId>
<version>
1.5.4
</version>
</dependency>
<dependency>
<groupId>
net.sf.jopt-simple
</groupId>
<artifactId>
jopt-simple
</artifactId>
...
...
spring-boot-parent/src/checkstyle/checkstyle-suppressions.xml
View file @
eff0fc02
...
...
@@ -6,6 +6,7 @@
<suppress
files=
"SpringApplicationTests\.java"
checks=
"FinalClass"
/>
<suppress
files=
".+Configuration\.java"
checks=
"HideUtilityClassConstructor"
/>
<suppress
files=
"LaunchScriptTestApplication\.java"
checks=
"HideUtilityClassConstructor"
/>
<suppress
files=
"DevToolsTestApplication\.java"
checks=
"HideUtilityClassConstructor"
/>
<suppress
files=
"SignalUtils\.java"
checks=
"IllegalImport"
/>
<suppress
files=
"[\\/]src[\\/]test[\\/]java[\\/]cli[\\/]command[\\/]"
checks=
"ImportControl"
/>
<suppress
files=
"[\\/]src[\\/]main[\\/]java[\\/]sample[\\/]"
checks=
"ImportControl"
/>
...
...
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