Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
ipgallery.common.java
/
microservice
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Registry
Issues
0
Merge Requests
0
Pipelines
Wiki
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
f8a6fbf5
authored
May 09, 2017
by
amir
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
end of day commits
parent
4002ac06
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
232 additions
and
15 deletions
src/main/java/microservice/MicroserviceApp.java
src/main/java/microservice/io/iface/CommonServices.java
src/main/java/microservice/io/impl/IRestClientRestImpl.java
src/main/java/microservice/io/impl/service/IPubSubServiceMqttImpl.java
src/main/java/microservice/io/impl/service/IRestServiceHttpImpl.java
src/main/java/microservice/utils/ServiceBuilderFactory.java
src/test/java/microservice/TestMicroserviceApp.java
src/main/java/microservice/MicroserviceApp.java
View file @
f8a6fbf5
...
@@ -109,6 +109,8 @@ public class MicroserviceApp
...
@@ -109,6 +109,8 @@ public class MicroserviceApp
public
boolean
isEnableDefaultServiceAuthorization
()
{
return
enableDefaultServiceAuthorization
;
}
public
boolean
isEnableDefaultServiceAuthorization
()
{
return
enableDefaultServiceAuthorization
;
}
public
IServiceDiscovery
getServiceDiscovery
()
{
return
serviceDiscovery
;
}
/*************************
/*************************
* WITH SECTION
* WITH SECTION
*************************/
*************************/
...
...
src/main/java/microservice/io/iface/CommonServices.java
View file @
f8a6fbf5
...
@@ -110,13 +110,29 @@ public class CommonServices {
...
@@ -110,13 +110,29 @@ public class CommonServices {
}
}
public
enum
EnumRestServiceMode
{
E_UNKNOWN
,
E_CLIENT
,
E_SERVER
,
E_CLIENT_SERVER
}
public
static
abstract
class
IRestService
extends
IService
{
public
static
abstract
class
IRestService
extends
IService
{
EnumRestServiceMode
serviceMode
=
EnumRestServiceMode
.
E_UNKNOWN
;
protected
ICommandClient
restClient
=
null
;
public
EnumRestServiceMode
getServiceMode
()
{
return
serviceMode
;
}
public
void
setServiceMode
(
EnumRestServiceMode
serviceMode
)
{
this
.
serviceMode
=
serviceMode
;
}
public
abstract
BaseRestResponse
create
(
CommandParams
cmdParams
);
public
abstract
BaseRestResponse
create
(
CommandParams
cmdParams
);
public
abstract
BaseRestResponse
read
(
CommandParams
cmdParams
);
public
abstract
BaseRestResponse
read
(
CommandParams
cmdParams
);
public
abstract
BaseRestResponse
update
(
CommandParams
cmdParams
);
public
abstract
BaseRestResponse
update
(
CommandParams
cmdParams
);
public
abstract
BaseRestResponse
delete
(
CommandParams
cmdParams
);
public
abstract
BaseRestResponse
delete
(
CommandParams
cmdParams
);
public
void
setRestClient
(
ICommandClient
restClient
)
{
this
.
restClient
=
restClient
;
}
}
}
enum
EnumPubSubCommands
implements
IServiceCommands
{
enum
EnumPubSubCommands
implements
IServiceCommands
{
...
@@ -142,9 +158,9 @@ public class CommonServices {
...
@@ -142,9 +158,9 @@ public class CommonServices {
}
}
}
}
public
abstract
void
subscribe
(
String
topic
,
Consumer
<
String
>
notify
Func
);
public
abstract
void
subscribe
(
String
topic
,
Consumer
<
PubSubMsgContext
>
notifyFunc
,
Consumer
<
String
>
error
Func
);
public
abstract
void
unsubscribe
(
String
topic
);
public
abstract
void
unsubscribe
(
String
topic
);
public
abstract
void
publish
(
String
topic
,
String
message
);
public
abstract
void
publish
(
PubSubMsgContext
pubSubMsgContext
);
}
}
enum
EnumMsgQCommands
{
enum
EnumMsgQCommands
{
...
@@ -153,8 +169,45 @@ public class CommonServices {
...
@@ -153,8 +169,45 @@ public class CommonServices {
}
}
public
static
abstract
class
IMsgQService
extends
IService
{
public
static
abstract
class
IMsgQService
extends
IService
{
public
class
MsgQContext
implements
IMsgContext
{
public
String
header
=
null
;
public
String
msg
=
null
;
public
MsgQContext
(
String
header
,
String
msg
)
{
this
.
header
=
header
;
this
.
msg
=
msg
;
}
@Override
public
void
setParameters
(
Map
<
String
,
String
>
parameters
)
{
}
}
public
abstract
void
receive
(
Consumer
<
String
>
receiveFunc
);
public
abstract
void
receive
(
Consumer
<
String
>
receiveFunc
);
public
abstract
void
send
(
String
msg
);
public
abstract
void
send
(
String
msg
);
}
}
public
interface
IClient
{
}
public
interface
IRestClient
extends
IClient
{
BaseRestResponse
create
(
CommandParams
cmdParams
);
BaseRestResponse
read
(
CommandParams
cmdParams
);
BaseRestResponse
update
(
CommandParams
cmdParams
);
BaseRestResponse
delete
(
CommandParams
cmdParams
);
}
public
interface
IMsgQueueClient
extends
IClient
{
boolean
send
(
IMsgQService
.
MsgQContext
msgQContext
);
}
public
interface
IPubSubClient
extends
IClient
{
void
publish
(
IPubSubService
.
PubSubMsgContext
pubSubContext
);
void
subscribe
(
String
topic
,
Consumer
<
String
>
notifyFunc
,
Consumer
<
String
>
errorFunc
);
void
unsubscribe
(
String
topic
);
}
}
}
src/main/java/microservice/io/impl/IRestClientRestImpl.java
View file @
f8a6fbf5
...
@@ -224,7 +224,8 @@ public class IRestClientRestImpl implements ICommandClient
...
@@ -224,7 +224,8 @@ public class IRestClientRestImpl implements ICommandClient
super
();
super
();
if
(
RestClientParams
.
class
.
isInstance
(
params
))
if
(
RestClientParams
.
class
.
isInstance
(
params
))
this
.
clientParams
=
(
RestClientParams
)
params
;
this
.
clientParams
=
(
RestClientParams
)
params
;
else
throw
new
Exception
(
"wrong initialization params"
+
params
.
getClass
().
getName
());
else
throw
new
Exception
(
"wrong initialization params"
+
params
.
getClass
().
getName
());
httpRestClient
=
new
SimpleRestClient
(
clientParams
.
getServiceName
(),
clientParams
.
getAddress
());
httpRestClient
=
new
SimpleRestClient
(
clientParams
.
getServiceName
(),
clientParams
.
getAddress
());
httpRestClient
.
Initialize
(
clientParams
.
getMaxConnection
());
httpRestClient
.
Initialize
(
clientParams
.
getMaxConnection
());
if
(
clientParams
.
isMetricsEnabled
())
if
(
clientParams
.
isMetricsEnabled
())
...
...
src/main/java/microservice/io/impl/service/IPubSubServiceMqttImpl.java
View file @
f8a6fbf5
...
@@ -31,8 +31,9 @@ public class IPubSubServiceMqttImpl extends CommonServices.IPubSubService {
...
@@ -31,8 +31,9 @@ public class IPubSubServiceMqttImpl extends CommonServices.IPubSubService {
this
.
clientId
=
Long
.
toString
(
System
.
currentTimeMillis
());
this
.
clientId
=
Long
.
toString
(
System
.
currentTimeMillis
());
}
}
@Override
@Override
public
void
subscribe
(
String
topic
,
Consumer
<
String
>
notify
Func
)
{
public
void
subscribe
(
String
topic
,
Consumer
<
PubSubMsgContext
>
notifyFunc
,
Consumer
<
String
>
error
Func
)
{
}
}
...
@@ -42,7 +43,7 @@ public class IPubSubServiceMqttImpl extends CommonServices.IPubSubService {
...
@@ -42,7 +43,7 @@ public class IPubSubServiceMqttImpl extends CommonServices.IPubSubService {
}
}
@Override
@Override
public
void
publish
(
String
topic
,
String
message
)
{
public
void
publish
(
PubSubMsgContext
pubSubMsgContext
)
{
}
}
...
...
src/main/java/microservice/io/impl/service/IRestServiceHttpImpl.java
View file @
f8a6fbf5
...
@@ -17,6 +17,7 @@ import io.undertow.util.Headers;
...
@@ -17,6 +17,7 @@ import io.undertow.util.Headers;
import
io.undertow.util.HttpString
;
import
io.undertow.util.HttpString
;
import
io.undertow.util.MimeMappings
;
import
io.undertow.util.MimeMappings
;
import
microservice.MicroserviceApp
;
import
microservice.MicroserviceApp
;
import
microservice.MicroserviceClient
;
import
microservice.RestContext
;
import
microservice.RestContext
;
import
microservice.common.EncryptionUtils
;
import
microservice.common.EncryptionUtils
;
import
microservice.defs.Constants
;
import
microservice.defs.Constants
;
...
@@ -26,11 +27,17 @@ import microservice.handlers.Reactor;
...
@@ -26,11 +27,17 @@ import microservice.handlers.Reactor;
import
microservice.io.iface.*
;
import
microservice.io.iface.*
;
import
microservice.io.impl.IRequestRestImpl
;
import
microservice.io.impl.IRequestRestImpl
;
import
microservice.io.impl.IResponseRestImpl
;
import
microservice.io.impl.IResponseRestImpl
;
import
microservice.io.impl.IRestClientRestImpl
;
import
microservice.params.BaseClientParams
;
import
microservice.params.CommandParams
;
import
microservice.params.CommandParams
;
import
microservice.params.RestClientParams
;
import
microservice.params.RestServerParams
;
import
microservice.params.RestServerParams
;
import
microservice.types.BaseRestResponse
;
import
microservice.types.BaseRestResponse
;
import
microservice.types.UserProfile
;
import
microservice.types.UserProfile
;
import
java.util.function.Function
;
import
java.util.function.Supplier
;
import
static
io
.
undertow
.
Handlers
.
resource
;
import
static
io
.
undertow
.
Handlers
.
resource
;
import
static
microservice
.
defs
.
Constants
.*;
import
static
microservice
.
defs
.
Constants
.*;
...
@@ -40,12 +47,13 @@ import static microservice.defs.Constants.*;
...
@@ -40,12 +47,13 @@ import static microservice.defs.Constants.*;
public
class
IRestServiceHttpImpl
extends
CommonServices
.
IRestService
implements
HttpHandler
,
IContainer
{
public
class
IRestServiceHttpImpl
extends
CommonServices
.
IRestService
implements
HttpHandler
,
IContainer
{
ILogger
logger
=
null
;
ILogger
logger
=
null
;
RestServerParams
restServerParams
;
RestServerParams
restServerParams
=
null
;
Undertow
restServer
=
null
;
Undertow
restServer
=
null
;
Thread
restThread
=
null
;
Thread
restThread
=
null
;
private
String
appName
;
private
String
appName
;
public
ObjectMapper
objMapper
=
null
;
public
ObjectMapper
objMapper
=
null
;
protected
Enums
.
EnumAuthenticationType
authType
=
Enums
.
EnumAuthenticationType
.
DEFAULT
;
protected
Enums
.
EnumAuthenticationType
authType
=
Enums
.
EnumAuthenticationType
.
DEFAULT
;
MicroserviceClient
restClient
=
null
;
/**
/**
* is the jwt token in the Authorization header or in the request query param
* is the jwt token in the Authorization header or in the request query param
...
@@ -57,28 +65,50 @@ public class IRestServiceHttpImpl extends CommonServices.IRestService implements
...
@@ -57,28 +65,50 @@ public class IRestServiceHttpImpl extends CommonServices.IRestService implements
this
.
objMapper
=
new
ObjectMapper
();
this
.
objMapper
=
new
ObjectMapper
();
}
}
public
IRestServiceHttpImpl
()
{
this
.
objMapper
=
new
ObjectMapper
();
}
public
void
setRestServerParams
(
RestServerParams
restServerParams
)
{
this
.
restServerParams
=
restServerParams
;
}
public
Enums
.
EnumAuthenticationType
getAuthType
()
{
return
authType
;
}
public
Enums
.
EnumAuthenticationType
getAuthType
()
{
return
authType
;
}
public
void
setAuthType
(
Enums
.
EnumAuthenticationType
authType
)
{
this
.
authType
=
authType
;
}
public
void
setAuthType
(
Enums
.
EnumAuthenticationType
authType
)
{
this
.
authType
=
authType
;
}
public
BaseRestResponse
handleSyncRespCommand
(
Supplier
<
BaseRestResponse
>
command
)
{
BaseRestResponse
resp
=
null
;
try
{
if
(
restClient
!=
null
)
resp
=
command
.
get
();
}
catch
(
Exception
e
)
{
resp
=
new
BaseRestResponse
(
false
,
e
.
toString
());
}
finally
{
if
(
resp
==
null
)
resp
=
new
BaseRestResponse
(
false
,
null
);
}
return
resp
;
}
@Override
@Override
public
BaseRestResponse
create
(
CommandParams
cmdParams
)
{
public
BaseRestResponse
create
(
CommandParams
cmdParams
)
{
return
null
;
return
handleSyncRespCommand
(()
->
restClient
.
create
(
cmdParams
)
)
;
}
}
@Override
@Override
public
BaseRestResponse
read
(
CommandParams
cmdParams
)
{
public
BaseRestResponse
read
(
CommandParams
cmdParams
)
{
return
null
;
return
handleSyncRespCommand
(()
->
restClient
.
read
(
cmdParams
)
)
;
}
}
@Override
@Override
public
BaseRestResponse
update
(
CommandParams
cmdParams
)
{
public
BaseRestResponse
update
(
CommandParams
cmdParams
)
{
return
null
;
return
handleSyncRespCommand
(()
->
restClient
.
update
(
cmdParams
)
)
;
}
}
@Override
@Override
public
BaseRestResponse
delete
(
CommandParams
cmdParams
)
{
public
BaseRestResponse
delete
(
CommandParams
cmdParams
)
{
return
null
;
return
handleSyncRespCommand
(()
->
restClient
.
delete
(
cmdParams
)
)
;
}
}
@Override
@Override
...
@@ -112,6 +142,19 @@ public class IRestServiceHttpImpl extends CommonServices.IRestService implements
...
@@ -112,6 +142,19 @@ public class IRestServiceHttpImpl extends CommonServices.IRestService implements
serverBuilder
.
setHandler
(
pathHandler
);
serverBuilder
.
setHandler
(
pathHandler
);
// build
// build
this
.
restServer
=
serverBuilder
.
build
();
this
.
restServer
=
serverBuilder
.
build
();
/**
* create client
*/
try
{
BaseClientParams
clientParams
=
new
RestClientParams
(
""
,
true
,
10
,
null
,
null
);
IRestClientRestImpl
cmdClient
=
new
IRestClientRestImpl
(
clientParams
)
.
withServiceDiscovery
(
MicroserviceApp
.
getsInstance
().
getServiceDiscovery
());
restClient
=
new
MicroserviceClient
(
cmdClient
,
clientParams
);
}
catch
(
Exception
exp
)
{
logger
.
error
(
exp
.
toString
());
return
false
;
}
return
true
;
return
true
;
}
}
...
@@ -210,6 +253,9 @@ public class IRestServiceHttpImpl extends CommonServices.IRestService implements
...
@@ -210,6 +253,9 @@ public class IRestServiceHttpImpl extends CommonServices.IRestService implements
@Override
@Override
public
void
run
()
{
public
void
run
()
{
if
(
getServiceMode
().
equals
(
CommonServices
.
EnumRestServiceMode
.
E_CLIENT
))
return
;
restThread
=
new
Thread
(()
->
{
restThread
=
new
Thread
(()
->
{
try
try
{
{
...
...
src/main/java/microservice/utils/ServiceBuilderFactory.java
0 → 100644
View file @
f8a6fbf5
package
microservice
.
utils
;
import
microservice.io.iface.CommonServices
;
import
microservice.io.iface.ICommandClient
;
import
microservice.io.impl.IRestClientRestImpl
;
import
microservice.io.impl.service.IRestServiceHttpImpl
;
import
microservice.params.RestClientParams
;
import
microservice.params.RestServerParams
;
/**
* Created by amir on 09/05/17.
*/
public
class
ServiceBuilderFactory
{
public
static
RestServiceHttpBuilder
createRestServiceHttpBuilder
(
CommonServices
.
EnumRestServiceMode
serviceMode
){
return
new
RestServiceHttpBuilder
(
serviceMode
);
}
public
interface
IBuilder
{
CommonServices
.
IService
build
();
}
public
static
class
RestServiceHttpBuilder
implements
IBuilder
{
IRestServiceHttpImpl
restServiceHttp
=
null
;
RestServerParams
restServerParams
=
null
;
ICommandClient
restClient
=
null
;
RestClientParams
restClientParams
=
null
;
CommonServices
.
EnumRestServiceMode
serviceMode
=
CommonServices
.
EnumRestServiceMode
.
E_UNKNOWN
;
public
RestServiceHttpBuilder
(
CommonServices
.
EnumRestServiceMode
serviceMode
)
{
this
.
serviceMode
=
serviceMode
;
}
public
RestServiceHttpBuilder
hasRestServerParams
(
RestServerParams
restServerParams
)
{
this
.
restServerParams
=
restServerParams
;
return
this
;
}
public
RestServiceHttpBuilder
hasRestClientParams
(
RestClientParams
restClientParams
)
{
this
.
restClientParams
=
restClientParams
;
return
this
;
}
/**
* in case you want a different client the the regular http
* @param restClient
* @return
*/
public
RestServiceHttpBuilder
withRestClient
(
ICommandClient
restClient
)
{
this
.
restClient
=
restClient
;
return
this
;
}
@Override
public
CommonServices
.
IService
build
()
{
if
(
validateParams
())
{
try
{
restServiceHttp
=
new
IRestServiceHttpImpl
();
restServiceHttp
.
setServiceMode
(
serviceMode
);
switch
(
serviceMode
)
{
case
E_SERVER:
restServiceHttp
.
setRestServerParams
(
restServerParams
);
break
;
case
E_CLIENT:
if
(
restClient
==
null
)
restClient
=
new
IRestClientRestImpl
(
restClientParams
);
restServiceHttp
.
setRestClient
(
restClient
);
break
;
case
E_CLIENT_SERVER:
restServiceHttp
.
setRestServerParams
(
restServerParams
);
if
(
restClient
==
null
)
restClient
=
new
IRestClientRestImpl
(
restClientParams
);
restServiceHttp
.
setRestClient
(
restClient
);
break
;
}
}
catch
(
Exception
exp
){
System
.
err
.
println
(
this
.
getClass
().
getName
().
toString
()
+
"Exception >> "
+
exp
);
restServiceHttp
=
null
;
}
}
else
{
System
.
err
.
println
(
this
.
getClass
().
getName
().
toString
()
+
" >> Failed in validating params"
);
}
return
restServiceHttp
;
}
private
boolean
validateParams
()
{
switch
(
serviceMode
){
case
E_UNKNOWN:
return
false
;
case
E_SERVER:
if
(
this
.
restServerParams
==
null
)
return
false
;
break
;
case
E_CLIENT:
if
(
this
.
restClientParams
==
null
)
return
false
;
break
;
case
E_CLIENT_SERVER:
if
(
this
.
restServerParams
==
null
||
this
.
restClientParams
==
null
)
break
;
}
return
true
;
}
}
}
src/test/java/microservice/TestMicroserviceApp.java
View file @
f8a6fbf5
...
@@ -11,6 +11,7 @@ import microservice.io.impl.service.IRestServiceHttpImpl;
...
@@ -11,6 +11,7 @@ import microservice.io.impl.service.IRestServiceHttpImpl;
import
microservice.params.*
;
import
microservice.params.*
;
import
microservice.types.BaseRestResponse
;
import
microservice.types.BaseRestResponse
;
import
microservice.utils.ServiceBuilderFactory
;
import
org.eclipse.paho.client.mqttv3.MqttException
;
import
org.eclipse.paho.client.mqttv3.MqttException
;
import
org.junit.Test
;
import
org.junit.Test
;
...
@@ -75,11 +76,15 @@ public class TestMicroserviceApp {
...
@@ -75,11 +76,15 @@ public class TestMicroserviceApp {
{
{
System
.
setProperty
(
"configFile.location"
,
"/opt/mcx/config/config.properties"
);
System
.
setProperty
(
"configFile.location"
,
"/opt/mcx/config/config.properties"
);
String
appName
=
"testApp"
;
String
appName
=
"testApp"
;
CommonServices
.
IService
restService
=
ServiceBuilderFactory
.
createRestServiceHttpBuilder
(
CommonServices
.
EnumRestServiceMode
.
E_SERVER
)
.
hasRestServerParams
(
new
RestServerParams
(
32000
,
"localhost"
,
2
))
.
build
();
microservice
.
MicroserviceApp
msApp
=
new
microservice
.
MicroserviceApp
(
appName
);
microservice
.
MicroserviceApp
msApp
=
new
microservice
.
MicroserviceApp
(
appName
);
msApp
.
withMetrics
()
msApp
.
withMetrics
()
.
withMonitoring
()
.
withMonitoring
()
//.withDefaultServiceAuthorization()
//.withDefaultServiceAuthorization()
.
addService
(
Enums
.
EnumServiceType
.
E_REST
,
new
IRestServiceHttpImpl
(
new
RestServerParams
(
32000
,
"localhost"
,
2
))
,
"undertowRestService"
)
.
addService
(
Enums
.
EnumServiceType
.
E_REST
,
restService
,
"undertowRestService"
)
.
addMethod
(
Enums
.
EnumServiceType
.
E_REST
,
CommonServices
.
EnumRestCommands
.
E_READ
,
"/resource/{rid}"
,(
msgCtx
,
orgService
)
->
{
.
addMethod
(
Enums
.
EnumServiceType
.
E_REST
,
CommonServices
.
EnumRestCommands
.
E_READ
,
"/resource/{rid}"
,(
msgCtx
,
orgService
)
->
{
BaseRestResponse
brr
=
new
BaseRestResponse
(
true
,
null
);
BaseRestResponse
brr
=
new
BaseRestResponse
(
true
,
null
);
RestContext
restContext
=
(
RestContext
)
msgCtx
;
RestContext
restContext
=
(
RestContext
)
msgCtx
;
...
@@ -92,11 +97,11 @@ public class TestMicroserviceApp {
...
@@ -92,11 +97,11 @@ public class TestMicroserviceApp {
restContext
.
container
.
writeObjectToResponse
(
restContext
.
response
,
brr
);
restContext
.
container
.
writeObjectToResponse
(
restContext
.
response
,
brr
);
})
})
.
addMethod
(
Enums
.
EnumServiceType
.
E_REST
,
CommonServices
.
EnumRestCommands
.
E_READ
,
"/resource/r2"
,(
msgCtx
,
orgService
)
->
{
.
addMethod
(
Enums
.
EnumServiceType
.
E_REST
,
CommonServices
.
EnumRestCommands
.
E_READ
,
"/resource/r2"
,(
msgCtx
,
orgService
)
->
{
CommonServices
.
IRestService
outRestService
=
(
CommonServices
.
IRestService
)
MicroserviceApp
.
getsInstance
().
getService
(
Enums
.
EnumServiceType
.
E_REST
,
"undertowRestService"
);
CommonServices
.
IRestService
inRestService
=
(
CommonServices
.
IRestService
)
MicroserviceApp
.
getsInstance
().
getService
(
Enums
.
EnumServiceType
.
E_REST
,
"undertowRestService"
);
CommonServices
.
IRestService
restService
=
(
CommonServices
.
IRestService
)
orgService
;
CommandParams
cmdParams
=
new
CommandParams
();
CommandParams
cmdParams
=
new
CommandParams
();
BaseRestResponse
brr
=
restService
.
read
(
cmdParams
);
RestContext
restContext
=
(
RestContext
)
msgCtx
;
//restService.writeResponse(brr);
BaseRestResponse
brr
=
inRestService
.
read
(
cmdParams
);
restContext
.
container
.
writeObjectToResponse
(
restContext
.
response
,
brr
);
})
})
.
_build
()
.
_build
()
.
_run
();
.
_run
();
...
...
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