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
8da82d2d
Commit
8da82d2d
authored
Mar 24, 2021
by
Phillip Webb
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '2.4.x'
Closes gh-25790
parents
02a6de44
35aeae5a
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
114 additions
and
22 deletions
+114
-22
BootstrapRegistryInitializer.java
...rg/springframework/boot/BootstrapRegistryInitializer.java
+37
-0
Bootstrapper.java
.../src/main/java/org/springframework/boot/Bootstrapper.java
+2
-0
SpringApplication.java
...main/java/org/springframework/boot/SpringApplication.java
+28
-4
SpringApplicationBuilder.java
...pringframework/boot/builder/SpringApplicationBuilder.java
+20
-4
SpringApplicationTests.java
...java/org/springframework/boot/SpringApplicationTests.java
+8
-6
SpringApplicationBuilderTests.java
...framework/boot/builder/SpringApplicationBuilderTests.java
+10
-0
SampleBootstrapRegistryApplication.java
...strapregistry/app/SampleBootstrapRegistryApplication.java
+2
-2
SubversionBootstrap.java
...t/bootstrapregistry/external/svn/SubversionBootstrap.java
+7
-6
No files found.
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/BootstrapRegistryInitializer.java
0 → 100644
View file @
8da82d2d
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
;
/**
* Callback interface that can be used to initialize a {@link BootstrapRegistry} before it
* is used.
*
* @author Phillip Webb
* @since 2.4.5
* @see SpringApplication#addBootstrapRegistryInitializer(BootstrapRegistryInitializer)
* @see BootstrapRegistry
*/
@FunctionalInterface
public
interface
BootstrapRegistryInitializer
{
/**
* Initialize the given {@link BootstrapRegistry} with any required registrations.
* @param registry the registry to initialize
*/
void
initialize
(
BootstrapRegistry
registry
);
}
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/Bootstrapper.java
View file @
8da82d2d
...
@@ -24,7 +24,9 @@ package org.springframework.boot;
...
@@ -24,7 +24,9 @@ package org.springframework.boot;
* @since 2.4.0
* @since 2.4.0
* @see SpringApplication#addBootstrapper(Bootstrapper)
* @see SpringApplication#addBootstrapper(Bootstrapper)
* @see BootstrapRegistry
* @see BootstrapRegistry
* @deprecated since 2.4.5 in favor of {@link BootstrapRegistryInitializer}
*/
*/
@Deprecated
public
interface
Bootstrapper
{
public
interface
Bootstrapper
{
/**
/**
...
...
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java
View file @
8da82d2d
...
@@ -236,7 +236,7 @@ public class SpringApplication {
...
@@ -236,7 +236,7 @@ public class SpringApplication {
private
Map
<
String
,
Object
>
defaultProperties
;
private
Map
<
String
,
Object
>
defaultProperties
;
private
List
<
Bootstrap
per
>
bootstrapp
ers
;
private
List
<
Bootstrap
RegistryInitializer
>
bootstrapRegistryInitializ
ers
;
private
Set
<
String
>
additionalProfiles
=
Collections
.
emptySet
();
private
Set
<
String
>
additionalProfiles
=
Collections
.
emptySet
();
...
@@ -282,12 +282,22 @@ public class SpringApplication {
...
@@ -282,12 +282,22 @@ public class SpringApplication {
Assert
.
notNull
(
primarySources
,
"PrimarySources must not be null"
);
Assert
.
notNull
(
primarySources
,
"PrimarySources must not be null"
);
this
.
primarySources
=
new
LinkedHashSet
<>(
Arrays
.
asList
(
primarySources
));
this
.
primarySources
=
new
LinkedHashSet
<>(
Arrays
.
asList
(
primarySources
));
this
.
webApplicationType
=
WebApplicationType
.
deduceFromClasspath
();
this
.
webApplicationType
=
WebApplicationType
.
deduceFromClasspath
();
this
.
bootstrap
pers
=
new
ArrayList
<>(
getSpringFactoriesInstances
(
Bootstrapper
.
class
)
);
this
.
bootstrap
RegistryInitializers
=
getBootstrapRegistryInitializersFromSpringFactories
(
);
setInitializers
((
Collection
)
getSpringFactoriesInstances
(
ApplicationContextInitializer
.
class
));
setInitializers
((
Collection
)
getSpringFactoriesInstances
(
ApplicationContextInitializer
.
class
));
setListeners
((
Collection
)
getSpringFactoriesInstances
(
ApplicationListener
.
class
));
setListeners
((
Collection
)
getSpringFactoriesInstances
(
ApplicationListener
.
class
));
this
.
mainApplicationClass
=
deduceMainApplicationClass
();
this
.
mainApplicationClass
=
deduceMainApplicationClass
();
}
}
@SuppressWarnings
(
"deprecation"
)
private
List
<
BootstrapRegistryInitializer
>
getBootstrapRegistryInitializersFromSpringFactories
()
{
ArrayList
<
BootstrapRegistryInitializer
>
initializers
=
new
ArrayList
<>();
getSpringFactoriesInstances
(
Bootstrapper
.
class
).
stream
()
.
map
((
bootstrapper
)
->
((
BootstrapRegistryInitializer
)
bootstrapper:
:
initialize
))
.
forEach
(
initializers:
:
add
);
initializers
.
addAll
(
getSpringFactoriesInstances
(
BootstrapRegistryInitializer
.
class
));
return
initializers
;
}
private
Class
<?>
deduceMainApplicationClass
()
{
private
Class
<?>
deduceMainApplicationClass
()
{
try
{
try
{
StackTraceElement
[]
stackTrace
=
new
RuntimeException
().
getStackTrace
();
StackTraceElement
[]
stackTrace
=
new
RuntimeException
().
getStackTrace
();
...
@@ -351,7 +361,7 @@ public class SpringApplication {
...
@@ -351,7 +361,7 @@ public class SpringApplication {
private
DefaultBootstrapContext
createBootstrapContext
()
{
private
DefaultBootstrapContext
createBootstrapContext
()
{
DefaultBootstrapContext
bootstrapContext
=
new
DefaultBootstrapContext
();
DefaultBootstrapContext
bootstrapContext
=
new
DefaultBootstrapContext
();
this
.
bootstrap
p
ers
.
forEach
((
initializer
)
->
initializer
.
initialize
(
bootstrapContext
));
this
.
bootstrap
RegistryInitializ
ers
.
forEach
((
initializer
)
->
initializer
.
initialize
(
bootstrapContext
));
return
bootstrapContext
;
return
bootstrapContext
;
}
}
...
@@ -1046,10 +1056,24 @@ public class SpringApplication {
...
@@ -1046,10 +1056,24 @@ public class SpringApplication {
* {@link BootstrapRegistry}.
* {@link BootstrapRegistry}.
* @param bootstrapper the bootstraper
* @param bootstrapper the bootstraper
* @since 2.4.0
* @since 2.4.0
* @deprecated since 2.4.5 in favor of
* {@link #addBootstrapRegistryInitializer(BootstrapRegistryInitializer)}
*/
*/
@Deprecated
public
void
addBootstrapper
(
Bootstrapper
bootstrapper
)
{
public
void
addBootstrapper
(
Bootstrapper
bootstrapper
)
{
Assert
.
notNull
(
bootstrapper
,
"Bootstrapper must not be null"
);
Assert
.
notNull
(
bootstrapper
,
"Bootstrapper must not be null"
);
this
.
bootstrappers
.
add
(
bootstrapper
);
this
.
bootstrapRegistryInitializers
.
add
(
bootstrapper:
:
initialize
);
}
/**
* Adds {@link BootstrapRegistryInitializer} instances that can be used to initialize
* the {@link BootstrapRegistry}.
* @param bootstrapRegistryInitializer the bootstrap registry initializer to add
* @since 2.4.5
*/
public
void
addBootstrapRegistryInitializer
(
BootstrapRegistryInitializer
bootstrapRegistryInitializer
)
{
Assert
.
notNull
(
bootstrapRegistryInitializer
,
"BootstrapRegistryInitializer must not be null"
);
this
.
bootstrapRegistryInitializers
.
addAll
(
Arrays
.
asList
(
bootstrapRegistryInitializer
));
}
}
/**
/**
...
...
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java
View file @
8da82d2d
...
@@ -31,7 +31,7 @@ import org.springframework.beans.factory.support.BeanNameGenerator;
...
@@ -31,7 +31,7 @@ import org.springframework.beans.factory.support.BeanNameGenerator;
import
org.springframework.boot.ApplicationContextFactory
;
import
org.springframework.boot.ApplicationContextFactory
;
import
org.springframework.boot.Banner
;
import
org.springframework.boot.Banner
;
import
org.springframework.boot.BootstrapRegistry
;
import
org.springframework.boot.BootstrapRegistry
;
import
org.springframework.boot.Bootstrap
p
er
;
import
org.springframework.boot.Bootstrap
RegistryInitializ
er
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.WebApplicationType
;
import
org.springframework.boot.WebApplicationType
;
import
org.springframework.boot.convert.ApplicationConversionService
;
import
org.springframework.boot.convert.ApplicationConversionService
;
...
@@ -400,17 +400,33 @@ public class SpringApplicationBuilder {
...
@@ -400,17 +400,33 @@ public class SpringApplicationBuilder {
}
}
/**
/**
* Adds a {@link
Bootstrapper} that can be used to initialize th
e
* Adds a {@link
org.springframework.boot.Bootstrapper} that can be used to initializ
e
* {@link BootstrapRegistry}.
*
the
{@link BootstrapRegistry}.
* @param bootstrapper the bootstraper
* @param bootstrapper the bootstraper
* @return the current builder
* @return the current builder
* @since 2.4.0
* @since 2.4.0
* @deprecated since 2.4.5 in favor of
* {@link #addBootstrapRegistryInitializer(BootstrapRegistryInitializer)}
*/
*/
public
SpringApplicationBuilder
addBootstrapper
(
Bootstrapper
bootstrapper
)
{
@Deprecated
public
SpringApplicationBuilder
addBootstrapper
(
org
.
springframework
.
boot
.
Bootstrapper
bootstrapper
)
{
this
.
application
.
addBootstrapper
(
bootstrapper
);
this
.
application
.
addBootstrapper
(
bootstrapper
);
return
this
;
return
this
;
}
}
/**
* Adds {@link BootstrapRegistryInitializer} instances that can be used to initialize
* the {@link BootstrapRegistry}.
* @param bootstrapRegistryInitializer the bootstrap registry initializer to add
* @return the current builder
* @since 2.4.5
*/
public
SpringApplicationBuilder
addBootstrapRegistryInitializer
(
BootstrapRegistryInitializer
bootstrapRegistryInitializer
)
{
this
.
application
.
addBootstrapRegistryInitializer
(
bootstrapRegistryInitializer
);
return
this
;
}
/**
/**
* Flag to control whether the application should be initialized lazily.
* Flag to control whether the application should be initialized lazily.
* @param lazyInitialization the flag to set. Defaults to false.
* @param lazyInitialization the flag to set. Defaults to false.
...
...
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java
View file @
8da82d2d
...
@@ -1219,10 +1219,10 @@ class SpringApplicationTests {
...
@@ -1219,10 +1219,10 @@ class SpringApplicationTests {
}
}
@Test
@Test
void
addBootstrap
p
er
()
{
void
addBootstrap
RegistryInitializ
er
()
{
SpringApplication
application
=
new
SpringApplication
(
ExampleConfig
.
class
);
SpringApplication
application
=
new
SpringApplication
(
ExampleConfig
.
class
);
application
.
setWebApplicationType
(
WebApplicationType
.
NONE
);
application
.
setWebApplicationType
(
WebApplicationType
.
NONE
);
application
.
addBootstrap
p
er
(
application
.
addBootstrap
RegistryInitializ
er
(
(
bootstrapContext
)
->
bootstrapContext
.
register
(
String
.
class
,
InstanceSupplier
.
of
(
"boot"
)));
(
bootstrapContext
)
->
bootstrapContext
.
register
(
String
.
class
,
InstanceSupplier
.
of
(
"boot"
)));
TestApplicationListener
listener
=
new
TestApplicationListener
();
TestApplicationListener
listener
=
new
TestApplicationListener
();
application
.
addListeners
(
listener
);
application
.
addListeners
(
listener
);
...
@@ -1235,10 +1235,10 @@ class SpringApplicationTests {
...
@@ -1235,10 +1235,10 @@ class SpringApplicationTests {
}
}
@Test
@Test
void
addBootstrap
p
erCanRegisterBeans
()
{
void
addBootstrap
RegistryInitializ
erCanRegisterBeans
()
{
SpringApplication
application
=
new
SpringApplication
(
ExampleConfig
.
class
);
SpringApplication
application
=
new
SpringApplication
(
ExampleConfig
.
class
);
application
.
setWebApplicationType
(
WebApplicationType
.
NONE
);
application
.
setWebApplicationType
(
WebApplicationType
.
NONE
);
application
.
addBootstrap
p
er
((
bootstrapContext
)
->
{
application
.
addBootstrap
RegistryInitializ
er
((
bootstrapContext
)
->
{
bootstrapContext
.
register
(
String
.
class
,
InstanceSupplier
.
of
(
"boot"
));
bootstrapContext
.
register
(
String
.
class
,
InstanceSupplier
.
of
(
"boot"
));
bootstrapContext
.
addCloseListener
((
event
)
->
event
.
getApplicationContext
().
getBeanFactory
()
bootstrapContext
.
addCloseListener
((
event
)
->
event
.
getApplicationContext
().
getBeanFactory
()
.
registerSingleton
(
"test"
,
event
.
getBootstrapContext
().
get
(
String
.
class
)));
.
registerSingleton
(
"test"
,
event
.
getBootstrapContext
().
get
(
String
.
class
)));
...
@@ -1248,6 +1248,7 @@ class SpringApplicationTests {
...
@@ -1248,6 +1248,7 @@ class SpringApplicationTests {
}
}
@Test
@Test
@Deprecated
void
whenABootstrapperImplementsOnlyTheOldMethodThenItIsCalled
()
{
void
whenABootstrapperImplementsOnlyTheOldMethodThenItIsCalled
()
{
SpringApplication
application
=
new
SpringApplication
(
ExampleConfig
.
class
);
SpringApplication
application
=
new
SpringApplication
(
ExampleConfig
.
class
);
application
.
setWebApplicationType
(
WebApplicationType
.
NONE
);
application
.
setWebApplicationType
(
WebApplicationType
.
NONE
);
...
@@ -1259,6 +1260,7 @@ class SpringApplicationTests {
...
@@ -1259,6 +1260,7 @@ class SpringApplicationTests {
}
}
@Test
@Test
@Deprecated
void
whenABootstrapperImplementsTheOldMethodAndTheNewMethodThenOnlyTheNewMethodIsCalled
()
{
void
whenABootstrapperImplementsTheOldMethodAndTheNewMethodThenOnlyTheNewMethodIsCalled
()
{
SpringApplication
application
=
new
SpringApplication
(
ExampleConfig
.
class
);
SpringApplication
application
=
new
SpringApplication
(
ExampleConfig
.
class
);
application
.
setWebApplicationType
(
WebApplicationType
.
NONE
);
application
.
setWebApplicationType
(
WebApplicationType
.
NONE
);
...
@@ -1758,18 +1760,19 @@ class SpringApplicationTests {
...
@@ -1758,18 +1760,19 @@ class SpringApplicationTests {
}
}
@Deprecated
static
class
OnlyOldMethodTestBootstrapper
implements
Bootstrapper
{
static
class
OnlyOldMethodTestBootstrapper
implements
Bootstrapper
{
private
boolean
intitialized
;
private
boolean
intitialized
;
@Override
@Override
@SuppressWarnings
(
"deprecation"
)
public
void
intitialize
(
BootstrapRegistry
registry
)
{
public
void
intitialize
(
BootstrapRegistry
registry
)
{
this
.
intitialized
=
true
;
this
.
intitialized
=
true
;
}
}
}
}
@Deprecated
static
class
BothMethodsTestBootstrapper
implements
Bootstrapper
{
static
class
BothMethodsTestBootstrapper
implements
Bootstrapper
{
private
boolean
intitialized
;
private
boolean
intitialized
;
...
@@ -1777,7 +1780,6 @@ class SpringApplicationTests {
...
@@ -1777,7 +1780,6 @@ class SpringApplicationTests {
private
boolean
initialized
;
private
boolean
initialized
;
@Override
@Override
@SuppressWarnings
(
"deprecation"
)
public
void
intitialize
(
BootstrapRegistry
registry
)
{
public
void
intitialize
(
BootstrapRegistry
registry
)
{
this
.
intitialized
=
true
;
this
.
intitialized
=
true
;
}
}
...
...
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/builder/SpringApplicationBuilderTests.java
View file @
8da82d2d
...
@@ -283,6 +283,7 @@ class SpringApplicationBuilderTests {
...
@@ -283,6 +283,7 @@ class SpringApplicationBuilderTests {
}
}
@Test
@Test
@Deprecated
void
addBootstrapper
()
{
void
addBootstrapper
()
{
SpringApplicationBuilder
application
=
new
SpringApplicationBuilder
(
ExampleConfig
.
class
)
SpringApplicationBuilder
application
=
new
SpringApplicationBuilder
(
ExampleConfig
.
class
)
.
web
(
WebApplicationType
.
NONE
).
addBootstrapper
((
context
)
->
context
.
addCloseListener
(
.
web
(
WebApplicationType
.
NONE
).
addBootstrapper
((
context
)
->
context
.
addCloseListener
(
...
@@ -291,6 +292,15 @@ class SpringApplicationBuilderTests {
...
@@ -291,6 +292,15 @@ class SpringApplicationBuilderTests {
assertThat
(
this
.
context
.
getBean
(
"test"
)).
isEqualTo
(
"spring"
);
assertThat
(
this
.
context
.
getBean
(
"test"
)).
isEqualTo
(
"spring"
);
}
}
@Test
void
addBootstrapRegistryInitializer
()
{
SpringApplicationBuilder
application
=
new
SpringApplicationBuilder
(
ExampleConfig
.
class
)
.
web
(
WebApplicationType
.
NONE
).
addBootstrapRegistryInitializer
((
context
)
->
context
.
addCloseListener
(
(
event
)
->
event
.
getApplicationContext
().
getBeanFactory
().
registerSingleton
(
"test"
,
"spring"
)));
this
.
context
=
application
.
run
();
assertThat
(
this
.
context
.
getBean
(
"test"
)).
isEqualTo
(
"spring"
);
}
@Test
@Test
void
setEnvironmentPrefix
()
{
void
setEnvironmentPrefix
()
{
SpringApplicationBuilder
builder
=
new
SpringApplicationBuilder
(
ExampleConfig
.
class
).
environmentPrefix
(
"test"
);
SpringApplicationBuilder
builder
=
new
SpringApplicationBuilder
(
ExampleConfig
.
class
).
environmentPrefix
(
"test"
);
...
...
spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-bootstrap-registry/src/main/java/smoketest/bootstrapregistry/app/SampleBootstrapRegistryApplication.java
View file @
8da82d2d
/*
/*
* Copyright 2012-202
0
the original author or authors.
* Copyright 2012-202
1
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -29,7 +29,7 @@ public class SampleBootstrapRegistryApplication {
...
@@ -29,7 +29,7 @@ public class SampleBootstrapRegistryApplication {
// SubversionClient that still has access to data provided in the
// SubversionClient that still has access to data provided in the
// application.properties file
// application.properties file
SpringApplication
application
=
new
SpringApplication
(
SampleBootstrapRegistryApplication
.
class
);
SpringApplication
application
=
new
SpringApplication
(
SampleBootstrapRegistryApplication
.
class
);
application
.
addBootstrap
p
er
(
SubversionBootstrap
.
withCustomClient
(
MySubversionClient:
:
new
));
application
.
addBootstrap
RegistryInitializ
er
(
SubversionBootstrap
.
withCustomClient
(
MySubversionClient:
:
new
));
application
.
run
(
args
);
application
.
run
(
args
);
}
}
...
...
spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-bootstrap-registry/src/main/java/smoketest/bootstrapregistry/external/svn/SubversionBootstrap.java
View file @
8da82d2d
/*
/*
* Copyright 2012-202
0
the original author or authors.
* Copyright 2012-202
1
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -19,10 +19,10 @@ package smoketest.bootstrapregistry.external.svn;
...
@@ -19,10 +19,10 @@ package smoketest.bootstrapregistry.external.svn;
import
java.util.function.Function
;
import
java.util.function.Function
;
import
org.springframework.boot.BootstrapContext
;
import
org.springframework.boot.BootstrapContext
;
import
org.springframework.boot.Bootstrap
p
er
;
import
org.springframework.boot.Bootstrap
RegistryInitializ
er
;
/**
/**
* Allows the user to register a {@link Bootstrap
p
er} with a custom
* Allows the user to register a {@link Bootstrap
RegistryInitializ
er} with a custom
* {@link SubversionClient}.
* {@link SubversionClient}.
*
*
* @author Phillip Webb
* @author Phillip Webb
...
@@ -33,11 +33,12 @@ public final class SubversionBootstrap {
...
@@ -33,11 +33,12 @@ public final class SubversionBootstrap {
}
}
/**
/**
* Return a {@link Bootstrap
p
er} for the given client factory.
* Return a {@link Bootstrap
RegistryInitializ
er} for the given client factory.
* @param clientFactory the client factory
* @param clientFactory the client factory
* @return a {@link Bootstrap
p
er} instance
* @return a {@link Bootstrap
RegistryInitializ
er} instance
*/
*/
public
static
Bootstrapper
withCustomClient
(
Function
<
SubversionServerCertificate
,
SubversionClient
>
clientFactory
)
{
public
static
BootstrapRegistryInitializer
withCustomClient
(
Function
<
SubversionServerCertificate
,
SubversionClient
>
clientFactory
)
{
return
(
registry
)
->
registry
.
register
(
SubversionClient
.
class
,
return
(
registry
)
->
registry
.
register
(
SubversionClient
.
class
,
(
bootstrapContext
)
->
createSubversionClient
(
bootstrapContext
,
clientFactory
));
(
bootstrapContext
)
->
createSubversionClient
(
bootstrapContext
,
clientFactory
));
}
}
...
...
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