Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
apollo
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
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
Administrator
apollo
Commits
82790e5f
Commit
82790e5f
authored
Jan 21, 2020
by
songdragon
Committed by
Jason Song
Jan 21, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add OrderedProperties to keep the property order in apollo-client
parent
42edb9da
Changes
26
Show whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
652 additions
and
54 deletions
+652
-54
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfig.java
.../com/ctrip/framework/apollo/internals/AbstractConfig.java
+6
-2
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigFile.java
.../ctrip/framework/apollo/internals/AbstractConfigFile.java
+5
-1
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigRepository.java
.../framework/apollo/internals/AbstractConfigRepository.java
+3
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultConfig.java
...a/com/ctrip/framework/apollo/internals/DefaultConfig.java
+5
-5
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultInjector.java
...com/ctrip/framework/apollo/internals/DefaultInjector.java
+3
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/LocalFileConfigRepository.java
...framework/apollo/internals/LocalFileConfigRepository.java
+3
-4
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/RemoteConfigRepository.java
...ip/framework/apollo/internals/RemoteConfigRepository.java
+1
-1
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/SimpleConfig.java
...va/com/ctrip/framework/apollo/internals/SimpleConfig.java
+1
-1
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/YamlConfigFile.java
.../com/ctrip/framework/apollo/internals/YamlConfigFile.java
+1
-1
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java
...ollo/spring/boot/ApolloApplicationContextInitializer.java
+2
-1
apollo-client/src/main/java/com/ctrip/framework/apollo/util/ConfigUtil.java
...main/java/com/ctrip/framework/apollo/util/ConfigUtil.java
+32
-3
apollo-client/src/main/java/com/ctrip/framework/apollo/util/OrderedProperties.java
...va/com/ctrip/framework/apollo/util/OrderedProperties.java
+114
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/util/factory/DefaultPropertiesFactory.java
...amework/apollo/util/factory/DefaultPropertiesFactory.java
+34
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/util/factory/PropertiesFactory.java
...trip/framework/apollo/util/factory/PropertiesFactory.java
+28
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/util/yaml/YamlParser.java
...java/com/ctrip/framework/apollo/util/yaml/YamlParser.java
+6
-2
apollo-client/src/test/java/com/ctrip/framework/apollo/BaseIntegrationTest.java
.../java/com/ctrip/framework/apollo/BaseIntegrationTest.java
+16
-6
apollo-client/src/test/java/com/ctrip/framework/apollo/integration/ConfigIntegrationTest.java
...p/framework/apollo/integration/ConfigIntegrationTest.java
+104
-11
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/DefaultConfigTest.java
...m/ctrip/framework/apollo/internals/DefaultConfigTest.java
+3
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/LocalFileConfigRepositoryTest.java
...ework/apollo/internals/LocalFileConfigRepositoryTest.java
+53
-8
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/PropertiesConfigFileTest.java
.../framework/apollo/internals/PropertiesConfigFileTest.java
+8
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/RemoteConfigRepositoryTest.java
...ramework/apollo/internals/RemoteConfigRepositoryTest.java
+34
-6
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/SimpleConfigTest.java
...om/ctrip/framework/apollo/internals/SimpleConfigTest.java
+14
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/XmlConfigFileTest.java
...m/ctrip/framework/apollo/internals/XmlConfigFileTest.java
+14
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/YamlConfigFileTest.java
.../ctrip/framework/apollo/internals/YamlConfigFileTest.java
+40
-1
apollo-client/src/test/java/com/ctrip/framework/apollo/util/ConfigUtilTest.java
.../java/com/ctrip/framework/apollo/util/ConfigUtilTest.java
+17
-1
apollo-client/src/test/java/com/ctrip/framework/apollo/util/OrderedPropertiesTest.java
...om/ctrip/framework/apollo/util/OrderedPropertiesTest.java
+105
-0
No files found.
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfig.java
View file @
82790e5f
...
...
@@ -11,6 +11,7 @@ import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import
com.ctrip.framework.apollo.tracer.Tracer
;
import
com.ctrip.framework.apollo.tracer.spi.Transaction
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
com.ctrip.framework.apollo.util.function.Functions
;
import
com.ctrip.framework.apollo.util.parser.Parsers
;
import
com.google.common.base.Function
;
...
...
@@ -58,6 +59,8 @@ public abstract class AbstractConfig implements Config {
private
final
List
<
Cache
>
allCaches
;
private
final
AtomicLong
m_configVersion
;
//indicate config version
protected
PropertiesFactory
propertiesFactory
;
static
{
m_executorService
=
Executors
.
newCachedThreadPool
(
ApolloThreadFactory
.
create
(
"Config"
,
true
));
...
...
@@ -68,6 +71,7 @@ public abstract class AbstractConfig implements Config {
m_configVersion
=
new
AtomicLong
();
m_arrayCache
=
Maps
.
newConcurrentMap
();
allCaches
=
Lists
.
newArrayList
();
propertiesFactory
=
ApolloInjector
.
getInstance
(
PropertiesFactory
.
class
);
}
@Override
...
...
@@ -493,11 +497,11 @@ public abstract class AbstractConfig implements Config {
List
<
ConfigChange
>
calcPropertyChanges
(
String
namespace
,
Properties
previous
,
Properties
current
)
{
if
(
previous
==
null
)
{
previous
=
new
Properties
();
previous
=
propertiesFactory
.
getPropertiesInstance
();
}
if
(
current
==
null
)
{
current
=
new
Properties
();
current
=
propertiesFactory
.
getPropertiesInstance
();
}
Set
<
String
>
previousKeys
=
previous
.
stringPropertyNames
();
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigFile.java
View file @
82790e5f
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
com.ctrip.framework.apollo.build.ApolloInjector
;
import
com.ctrip.framework.apollo.enums.ConfigSourceType
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
java.util.List
;
import
java.util.Properties
;
import
java.util.concurrent.ExecutorService
;
...
...
@@ -30,6 +32,7 @@ public abstract class AbstractConfigFile implements ConfigFile, RepositoryChange
protected
final
String
m_namespace
;
protected
final
AtomicReference
<
Properties
>
m_configProperties
;
private
final
List
<
ConfigFileChangeListener
>
m_listeners
=
Lists
.
newCopyOnWriteArrayList
();
protected
final
PropertiesFactory
propertiesFactory
;
private
volatile
ConfigSourceType
m_sourceType
=
ConfigSourceType
.
NONE
;
...
...
@@ -42,6 +45,7 @@ public abstract class AbstractConfigFile implements ConfigFile, RepositoryChange
m_configRepository
=
configRepository
;
m_namespace
=
namespace
;
m_configProperties
=
new
AtomicReference
<>();
propertiesFactory
=
ApolloInjector
.
getInstance
(
PropertiesFactory
.
class
);
initialize
();
}
...
...
@@ -72,7 +76,7 @@ public abstract class AbstractConfigFile implements ConfigFile, RepositoryChange
if
(
newProperties
.
equals
(
m_configProperties
.
get
()))
{
return
;
}
Properties
newConfigProperties
=
new
Properties
();
Properties
newConfigProperties
=
propertiesFactory
.
getPropertiesInstance
();
newConfigProperties
.
putAll
(
newProperties
);
String
oldValue
=
getContent
();
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigRepository.java
View file @
82790e5f
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
com.ctrip.framework.apollo.build.ApolloInjector
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
java.util.List
;
import
java.util.Properties
;
...
...
@@ -16,6 +18,7 @@ import com.google.common.collect.Lists;
public
abstract
class
AbstractConfigRepository
implements
ConfigRepository
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
AbstractConfigRepository
.
class
);
private
List
<
RepositoryChangeListener
>
m_listeners
=
Lists
.
newCopyOnWriteArrayList
();
protected
PropertiesFactory
propertiesFactory
=
ApolloInjector
.
getInstance
(
PropertiesFactory
.
class
);
protected
boolean
trySync
()
{
try
{
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultConfig.java
View file @
82790e5f
...
...
@@ -4,12 +4,12 @@ import com.ctrip.framework.apollo.enums.ConfigSourceType;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.Collections
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.Properties
;
import
java.util.Set
;
import
java.util.HashMap
;
import
java.util.concurrent.atomic.AtomicReference
;
import
org.slf4j.Logger
;
...
...
@@ -88,7 +88,7 @@ public class DefaultConfig extends AbstractConfig implements RepositoryChangeLis
// step 4: check properties file from classpath
if
(
value
==
null
&&
m_resourceProperties
!=
null
)
{
value
=
(
String
)
m_resourceProperties
.
get
(
key
);
value
=
(
String
)
m_resourceProperties
.
get
Property
(
key
);
}
if
(
value
==
null
&&
m_configProperties
.
get
()
==
null
&&
m_warnLogRateLimiter
.
tryAcquire
())
{
...
...
@@ -115,7 +115,7 @@ public class DefaultConfig extends AbstractConfig implements RepositoryChangeLis
private
Set
<
String
>
stringPropertyNames
(
Properties
properties
)
{
//jdk9以下版本Properties#enumerateStringProperties方法存在性能问题,keys() + get(k) 重复迭代, jdk9之后改为entrySet遍历.
Map
<
String
,
String
>
h
=
new
HashMap
<>();
Map
<
String
,
String
>
h
=
new
Linked
HashMap
<>();
for
(
Map
.
Entry
<
Object
,
Object
>
e
:
properties
.
entrySet
())
{
Object
k
=
e
.
getKey
();
Object
v
=
e
.
getValue
();
...
...
@@ -133,7 +133,7 @@ public class DefaultConfig extends AbstractConfig implements RepositoryChangeLis
}
ConfigSourceType
sourceType
=
m_configRepository
.
getSourceType
();
Properties
newConfigProperties
=
new
Properties
();
Properties
newConfigProperties
=
propertiesFactory
.
getPropertiesInstance
();
newConfigProperties
.
putAll
(
newProperties
);
Map
<
String
,
ConfigChange
>
actualChanges
=
updateAndCalcConfigChanges
(
newConfigProperties
,
sourceType
);
...
...
@@ -213,7 +213,7 @@ public class DefaultConfig extends AbstractConfig implements RepositoryChangeLis
Properties
properties
=
null
;
if
(
in
!=
null
)
{
properties
=
new
Properties
();
properties
=
propertiesFactory
.
getPropertiesInstance
();
try
{
properties
.
load
(
in
);
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultInjector.java
View file @
82790e5f
...
...
@@ -9,6 +9,8 @@ import com.ctrip.framework.apollo.spi.DefaultConfigFactoryManager;
import
com.ctrip.framework.apollo.spi.DefaultConfigRegistry
;
import
com.ctrip.framework.apollo.tracer.Tracer
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
com.ctrip.framework.apollo.util.http.HttpUtil
;
import
com.ctrip.framework.apollo.util.yaml.YamlParser
;
...
...
@@ -62,6 +64,7 @@ public class DefaultInjector implements Injector {
bind
(
ConfigServiceLocator
.
class
).
in
(
Singleton
.
class
);
bind
(
RemoteConfigLongPollService
.
class
).
in
(
Singleton
.
class
);
bind
(
YamlParser
.
class
).
in
(
Singleton
.
class
);
bind
(
PropertiesFactory
.
class
).
to
(
DefaultPropertiesFactory
.
class
).
in
(
Singleton
.
class
);
}
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/LocalFileConfigRepository.java
View file @
82790e5f
...
...
@@ -88,7 +88,7 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
if
(
m_fileProperties
==
null
)
{
sync
();
}
Properties
result
=
new
Properties
();
Properties
result
=
propertiesFactory
.
getPropertiesInstance
();
result
.
putAll
(
m_fileProperties
);
return
result
;
}
...
...
@@ -117,7 +117,7 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
if
(
newProperties
.
equals
(
m_fileProperties
))
{
return
;
}
Properties
newFileProperties
=
new
Properties
();
Properties
newFileProperties
=
propertiesFactory
.
getPropertiesInstance
();
newFileProperties
.
putAll
(
newProperties
);
updateFileProperties
(
newFileProperties
,
m_upstream
.
getSourceType
());
this
.
fireRepositoryChange
(
namespace
,
newProperties
);
...
...
@@ -191,8 +191,7 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
try
{
in
=
new
FileInputStream
(
file
);
properties
=
new
Properties
();
properties
=
propertiesFactory
.
getPropertiesInstance
();
properties
.
load
(
in
);
logger
.
debug
(
"Loading local config file {} successfully!"
,
file
.
getAbsolutePath
());
}
catch
(
IOException
ex
)
{
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/RemoteConfigRepository.java
View file @
82790e5f
...
...
@@ -158,7 +158,7 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
}
private
Properties
transformApolloConfigToProperties
(
ApolloConfig
apolloConfig
)
{
Properties
result
=
new
Properties
();
Properties
result
=
propertiesFactory
.
getPropertiesInstance
();
result
.
putAll
(
apolloConfig
.
getConfigurations
());
return
result
;
}
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/SimpleConfig.java
View file @
82790e5f
...
...
@@ -81,7 +81,7 @@ public class SimpleConfig extends AbstractConfig implements RepositoryChangeList
if
(
newProperties
.
equals
(
m_configProperties
))
{
return
;
}
Properties
newConfigProperties
=
new
Properties
();
Properties
newConfigProperties
=
propertiesFactory
.
getPropertiesInstance
();
newConfigProperties
.
putAll
(
newProperties
);
List
<
ConfigChange
>
changes
=
calcPropertyChanges
(
namespace
,
m_configProperties
,
newConfigProperties
);
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/YamlConfigFile.java
View file @
82790e5f
...
...
@@ -61,7 +61,7 @@ public class YamlConfigFile extends PlainTextConfigFile implements PropertiesCom
private
Properties
toProperties
()
{
if
(!
this
.
hasContent
())
{
return
new
Properties
();
return
propertiesFactory
.
getPropertiesInstance
();
}
try
{
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java
View file @
82790e5f
...
...
@@ -6,6 +6,7 @@ import com.ctrip.framework.apollo.core.ConfigConsts;
import
com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory
;
import
com.ctrip.framework.apollo.spring.config.PropertySourcesConstants
;
import
com.ctrip.framework.apollo.spring.util.SpringInjector
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
com.google.common.base.Splitter
;
import
com.google.common.base.Strings
;
import
java.util.List
;
...
...
@@ -61,7 +62,7 @@ public class ApolloApplicationContextInitializer implements
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ApolloApplicationContextInitializer
.
class
);
private
static
final
Splitter
NAMESPACE_SPLITTER
=
Splitter
.
on
(
","
).
omitEmptyStrings
().
trimResults
();
private
static
final
String
[]
APOLLO_SYSTEM_PROPERTIES
=
{
"app.id"
,
ConfigConsts
.
APOLLO_CLUSTER_KEY
,
"apollo.cacheDir"
,
"apollo.accesskey.secret"
,
ConfigConsts
.
APOLLO_META_KEY
};
"apollo.cacheDir"
,
"apollo.accesskey.secret"
,
ConfigConsts
.
APOLLO_META_KEY
,
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
};
private
final
ConfigPropertySourceFactory
configPropertySourceFactory
=
SpringInjector
.
getInstance
(
ConfigPropertySourceFactory
.
class
);
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/util/ConfigUtil.java
View file @
82790e5f
package
com
.
ctrip
.
framework
.
apollo
.
util
;
import
static
com
.
ctrip
.
framework
.
apollo
.
util
.
factory
.
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
;
import
com.google.common.util.concurrent.RateLimiter
;
import
java.io.File
;
import
java.util.concurrent.TimeUnit
;
...
...
@@ -18,6 +20,7 @@ import com.google.common.base.Strings;
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ConfigUtil
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ConfigUtil
.
class
);
private
int
refreshInterval
=
5
;
private
TimeUnit
refreshIntervalTimeUnit
=
TimeUnit
.
MINUTES
;
...
...
@@ -36,6 +39,7 @@ public class ConfigUtil {
private
long
longPollingInitialDelayInMills
=
2000
;
//2 seconds
private
boolean
autoUpdateInjectedSpringProperties
=
true
;
private
final
RateLimiter
warnLogRateLimiter
;
private
boolean
propertiesOrdered
=
false
;
public
ConfigUtil
()
{
warnLogRateLimiter
=
RateLimiter
.
create
(
0.017
);
// 1 warning log output per minute
...
...
@@ -47,6 +51,7 @@ public class ConfigUtil {
initMaxConfigCacheSize
();
initLongPollingInitialDelayInMills
();
initAutoUpdateInjectedSpringProperties
();
initPropertiesOrdered
();
}
/**
...
...
@@ -281,12 +286,14 @@ public class ConfigUtil {
}
private
void
initLongPollingInitialDelayInMills
()
{
String
customizedLongPollingInitialDelay
=
System
.
getProperty
(
"apollo.longPollingInitialDelayInMills"
);
String
customizedLongPollingInitialDelay
=
System
.
getProperty
(
"apollo.longPollingInitialDelayInMills"
);
if
(!
Strings
.
isNullOrEmpty
(
customizedLongPollingInitialDelay
))
{
try
{
longPollingInitialDelayInMills
=
Long
.
parseLong
(
customizedLongPollingInitialDelay
);
}
catch
(
Throwable
ex
)
{
logger
.
error
(
"Config for apollo.longPollingInitialDelayInMills is invalid: {}"
,
customizedLongPollingInitialDelay
);
logger
.
error
(
"Config for apollo.longPollingInitialDelayInMills is invalid: {}"
,
customizedLongPollingInitialDelay
);
}
}
}
...
...
@@ -300,7 +307,8 @@ public class ConfigUtil {
String
enableAutoUpdate
=
System
.
getProperty
(
"apollo.autoUpdateInjectedSpringProperties"
);
if
(
Strings
.
isNullOrEmpty
(
enableAutoUpdate
))
{
// 2. Get from app.properties
enableAutoUpdate
=
Foundation
.
app
().
getProperty
(
"apollo.autoUpdateInjectedSpringProperties"
,
null
);
enableAutoUpdate
=
Foundation
.
app
()
.
getProperty
(
"apollo.autoUpdateInjectedSpringProperties"
,
null
);
}
if
(!
Strings
.
isNullOrEmpty
(
enableAutoUpdate
))
{
autoUpdateInjectedSpringProperties
=
Boolean
.
parseBoolean
(
enableAutoUpdate
.
trim
());
...
...
@@ -310,4 +318,25 @@ public class ConfigUtil {
public
boolean
isAutoUpdateInjectedSpringPropertiesEnabled
()
{
return
autoUpdateInjectedSpringProperties
;
}
private
void
initPropertiesOrdered
()
{
String
enablePropertiesOrdered
=
System
.
getProperty
(
APOLLO_PROPERTY_ORDER_ENABLE
);
if
(
Strings
.
isNullOrEmpty
(
enablePropertiesOrdered
))
{
enablePropertiesOrdered
=
Foundation
.
app
().
getProperty
(
APOLLO_PROPERTY_ORDER_ENABLE
,
"false"
);
}
if
(!
Strings
.
isNullOrEmpty
(
enablePropertiesOrdered
))
{
try
{
propertiesOrdered
=
Boolean
.
parseBoolean
(
enablePropertiesOrdered
);
}
catch
(
Throwable
ex
)
{
logger
.
warn
(
"Config for {} is invalid: {}, set default value: false"
,
APOLLO_PROPERTY_ORDER_ENABLE
,
enablePropertiesOrdered
);
}
}
}
public
boolean
isPropertiesOrderEnabled
()
{
return
propertiesOrdered
;
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/util/OrderedProperties.java
0 → 100755
View file @
82790e5f
package
com
.
ctrip
.
framework
.
apollo
.
util
;
import
java.util.Collections
;
import
java.util.Enumeration
;
import
java.util.Iterator
;
import
java.util.LinkedHashMap
;
import
java.util.LinkedHashSet
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.Properties
;
import
java.util.Set
;
/**
* An OrderedProperties instance will keep appearance order in config file.
*
* <strong>
* Warnings: 1. It should be noticed that stream APIs or JDk1.8 APIs( listed in
* https://github.com/ctripcorp/apollo/pull/2861) are not implemented here. 2. {@link Properties}
* implementation are different between JDK1.8 and later JDKs. At least, {@link Properties} have an
* individual implementation in JDK10. Hence, there should be an individual putAll method here.
* </strong>
*
* @author songdragon@zts.io
*/
public
class
OrderedProperties
extends
Properties
{
private
static
final
long
serialVersionUID
=
-
1741073539526213291L
;
private
final
Set
<
String
>
propertyNames
;
public
OrderedProperties
()
{
propertyNames
=
Collections
.
synchronizedSet
(
new
LinkedHashSet
<
String
>());
}
@Override
public
synchronized
Object
put
(
Object
key
,
Object
value
)
{
addPropertyName
(
key
);
return
super
.
put
(
key
,
value
);
}
private
void
addPropertyName
(
Object
key
)
{
if
(
key
instanceof
String
)
{
propertyNames
.
add
((
String
)
key
);
}
}
@Override
public
Set
<
String
>
stringPropertyNames
()
{
return
propertyNames
;
}
@Override
public
Enumeration
<?>
propertyNames
()
{
return
Collections
.
enumeration
(
propertyNames
);
}
@Override
public
synchronized
Enumeration
<
Object
>
keys
()
{
return
new
Enumeration
<
Object
>()
{
private
final
Iterator
<
String
>
i
=
propertyNames
.
iterator
();
@Override
public
boolean
hasMoreElements
()
{
return
i
.
hasNext
();
}
@Override
public
Object
nextElement
()
{
return
i
.
next
();
}
};
}
@Override
public
Set
<
Object
>
keySet
()
{
return
new
LinkedHashSet
<
Object
>(
propertyNames
);
}
@Override
public
Set
<
Entry
<
Object
,
Object
>>
entrySet
()
{
Set
<
Entry
<
Object
,
Object
>>
original
=
super
.
entrySet
();
LinkedHashMap
<
Object
,
Entry
<
Object
,
Object
>>
entryMap
=
new
LinkedHashMap
<>();
for
(
String
propertyName
:
propertyNames
)
{
entryMap
.
put
(
propertyName
,
null
);
}
for
(
Entry
<
Object
,
Object
>
entry
:
original
)
{
entryMap
.
put
(
entry
.
getKey
(),
entry
);
}
return
new
LinkedHashSet
<>(
entryMap
.
values
());
}
@Override
public
synchronized
void
putAll
(
Map
<?,
?>
t
)
{
super
.
putAll
(
t
);
for
(
Object
name
:
t
.
keySet
())
{
addPropertyName
(
name
);
}
}
@Override
public
synchronized
void
clear
()
{
super
.
clear
();
this
.
propertyNames
.
clear
();
}
@Override
public
synchronized
Object
remove
(
Object
key
)
{
this
.
propertyNames
.
remove
(
key
);
return
super
.
remove
(
key
);
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/util/factory/DefaultPropertiesFactory.java
0 → 100644
View file @
82790e5f
package
com
.
ctrip
.
framework
.
apollo
.
util
.
factory
;
import
com.ctrip.framework.apollo.build.ApolloInjector
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.ctrip.framework.apollo.util.OrderedProperties
;
import
com.google.common.base.Strings
;
import
java.util.Properties
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
/**
* Default PropertiesFactory implementation.
*
* @author songdragon@zts.io
*/
public
class
DefaultPropertiesFactory
implements
PropertiesFactory
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
DefaultPropertiesFactory
.
class
);
private
ConfigUtil
m_configUtil
;
public
DefaultPropertiesFactory
()
{
m_configUtil
=
ApolloInjector
.
getInstance
(
ConfigUtil
.
class
);
}
@Override
public
Properties
getPropertiesInstance
()
{
if
(
m_configUtil
.
isPropertiesOrderEnabled
())
{
return
new
OrderedProperties
();
}
else
{
return
new
Properties
();
}
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/util/factory/PropertiesFactory.java
0 → 100644
View file @
82790e5f
package
com
.
ctrip
.
framework
.
apollo
.
util
.
factory
;
import
java.util.Properties
;
/**
* Factory interface to construct Properties instances.
*
* @author songdragon@zts.io
*/
public
interface
PropertiesFactory
{
/**
* Configuration to keep properties order as same as line order in .yml/.yaml/.properties file.
*/
public
static
final
String
APOLLO_PROPERTY_ORDER_ENABLE
=
"apollo.property.order.enable"
;
/**
* <pre>
* Default implementation:
* 1. if {@link APOLLO_PROPERTY_ORDER_ENABLE} is true return a new
* instance of {@link com.ctrip.framework.apollo.util.OrderedProperties}.
* 2. else return a new instance of {@link Properties}
* </pre>
*
* @return
*/
public
Properties
getPropertiesInstance
();
}
apollo-client/src/main/java/com/ctrip/framework/apollo/util/yaml/YamlParser.java
View file @
82790e5f
package
com
.
ctrip
.
framework
.
apollo
.
util
.
yaml
;
import
com.ctrip.framework.apollo.build.ApolloInjector
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
java.util.AbstractMap
;
import
java.util.Collection
;
import
java.util.Collections
;
...
...
@@ -25,12 +27,14 @@ import com.ctrip.framework.apollo.core.utils.StringUtils;
public
class
YamlParser
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
YamlParser
.
class
);
private
PropertiesFactory
propertiesFactory
=
ApolloInjector
.
getInstance
(
PropertiesFactory
.
class
);
/**
* Transform yaml content to properties
*/
public
Properties
yamlToProperties
(
String
yamlContent
)
{
Yaml
yaml
=
createYaml
();
final
Properties
result
=
new
Properties
();
final
Properties
result
=
propertiesFactory
.
getPropertiesInstance
();
process
(
new
MatchCallback
()
{
@Override
public
void
process
(
Properties
properties
,
Map
<
String
,
Object
>
map
)
{
...
...
@@ -91,7 +95,7 @@ public class YamlParser {
}
private
boolean
process
(
Map
<
String
,
Object
>
map
,
MatchCallback
callback
)
{
Properties
properties
=
new
Properties
();
Properties
properties
=
propertiesFactory
.
getPropertiesInstance
();
properties
.
putAll
(
getFlattenedMap
(
map
));
if
(
logger
.
isDebugEnabled
())
{
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/BaseIntegrationTest.java
View file @
82790e5f
...
...
@@ -32,7 +32,8 @@ import com.google.gson.Gson;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
abstract
class
BaseIntegrationTest
{
public
abstract
class
BaseIntegrationTest
{
private
static
final
int
PORT
=
findFreePort
();
private
static
final
String
metaServiceUrl
=
"http://localhost:"
+
PORT
;
private
static
final
String
someAppName
=
"someAppName"
;
...
...
@@ -74,6 +75,7 @@ public abstract class BaseIntegrationTest{
/**
* init and start a jetty server, remember to call server.stop when the task is finished
*
* @param handlers
* @throws Exception
*/
...
...
@@ -139,6 +141,7 @@ public abstract class BaseIntegrationTest{
}
public
static
class
MockConfigUtil
extends
ConfigUtil
{
@Override
public
String
getAppId
()
{
return
someAppId
;
...
...
@@ -198,13 +201,19 @@ public abstract class BaseIntegrationTest{
public
long
getLongPollingInitialDelayInMills
()
{
return
0
;
}
@Override
public
boolean
isPropertiesOrderEnabled
()
{
return
true
;
}
}
/**
* Returns a free port number on localhost.
*
* Heavily inspired from org.eclipse.jdt.launching.SocketUtil (to avoid a dependency to JDT just because of this).
* Slightly improved with close() missing in JDT. And throws exception instead of returning -1.
* <p>
* Heavily inspired from org.eclipse.jdt.launching.SocketUtil (to avoid a dependency to JDT just
* because of this). Slightly improved with close() missing in JDT. And throws exception instead
* of returning -1.
*
* @return a free port number on localhost
* @throws IllegalStateException if unable to find a free port
...
...
@@ -230,7 +239,8 @@ public abstract class BaseIntegrationTest{
}
}
}
throw
new
IllegalStateException
(
"Could not find a free TCP/IP port to start embedded Jetty HTTP Server on"
);
throw
new
IllegalStateException
(
"Could not find a free TCP/IP port to start embedded Jetty HTTP Server on"
);
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/integration/ConfigIntegrationTest.java
View file @
82790e5f
...
...
@@ -9,9 +9,7 @@ import java.io.File;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.nio.file.Files
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Properties
;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicInteger
;
...
...
@@ -19,6 +17,7 @@ import javax.servlet.ServletException;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
org.eclipse.jetty.server.Request
;
import
org.eclipse.jetty.server.handler.AbstractHandler
;
import
org.eclipse.jetty.server.handler.ContextHandler
;
...
...
@@ -48,11 +47,13 @@ import com.google.common.util.concurrent.SettableFuture;
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ConfigIntegrationTest
extends
BaseIntegrationTest
{
private
String
someReleaseKey
;
private
File
configDir
;
private
String
defaultNamespace
;
private
String
someOtherNamespace
;
private
RemoteConfigLongPollService
remoteConfigLongPollService
;
private
PropertiesFactory
propertiesFactory
;
@Before
public
void
setUp
()
throws
Exception
{
...
...
@@ -67,6 +68,9 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
}
configDir
.
mkdirs
();
remoteConfigLongPollService
=
ApolloInjector
.
getInstance
(
RemoteConfigLongPollService
.
class
);
System
.
setProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
,
"true"
);
propertiesFactory
=
ApolloInjector
.
getInstance
(
PropertiesFactory
.
class
);
}
@Override
...
...
@@ -74,6 +78,7 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
public
void
tearDown
()
throws
Exception
{
ReflectionTestUtils
.
invokeMethod
(
remoteConfigLongPollService
,
"stopLongPollingRefresh"
);
recursiveDelete
(
configDir
);
System
.
clearProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
);
super
.
tearDown
();
}
...
...
@@ -110,6 +115,28 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
assertEquals
(
someDefaultValue
,
config
.
getProperty
(
someNonExistedKey
,
someDefaultValue
));
}
@Test
public
void
testOrderGetConfigWithNoLocalFileButWithRemoteConfig
()
throws
Exception
{
String
someKey1
=
"someKey1"
;
String
someValue1
=
"someValue1"
;
String
someKey2
=
"someKey2"
;
String
someValue2
=
"someValue2"
;
Map
<
String
,
String
>
configurations
=
new
LinkedHashMap
<>();
configurations
.
put
(
someKey1
,
someValue1
);
configurations
.
put
(
someKey2
,
someValue2
);
ApolloConfig
apolloConfig
=
assembleApolloConfig
(
ImmutableMap
.
copyOf
(
configurations
));
ContextHandler
handler
=
mockConfigServerHandler
(
HttpServletResponse
.
SC_OK
,
apolloConfig
);
startServerWithHandlers
(
handler
);
Config
config
=
ConfigService
.
getAppConfig
();
Set
<
String
>
propertyNames
=
config
.
getPropertyNames
();
Iterator
<
String
>
it
=
propertyNames
.
iterator
();
assertEquals
(
someKey1
,
it
.
next
());
assertEquals
(
someKey2
,
it
.
next
());
}
@Test
public
void
testGetConfigWithLocalFileAndWithRemoteConfig
()
throws
Exception
{
String
someKey
=
"someKey"
;
...
...
@@ -128,6 +155,45 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
assertEquals
(
anotherValue
,
config
.
getProperty
(
someKey
,
null
));
}
@Test
public
void
testOrderGetConfigWithLocalFileAndWithRemoteConfig
()
throws
Exception
{
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
String
anotherValue
=
"anotherValue"
;
String
someKey1
=
"someKey1"
;
String
someValue1
=
"someValue1"
;
String
anotherValue1
=
"anotherValue1"
;
String
someKey2
=
"someKey2"
;
String
someValue2
=
"someValue2"
;
Properties
properties
=
propertiesFactory
.
getPropertiesInstance
();
properties
.
put
(
someKey
,
someValue
);
properties
.
put
(
someKey1
,
someValue1
);
properties
.
put
(
someKey2
,
someValue2
);
createLocalCachePropertyFile
(
properties
);
Map
<
String
,
String
>
configurations
=
new
LinkedHashMap
<>();
configurations
.
put
(
someKey
,
anotherValue
);
configurations
.
put
(
someKey1
,
anotherValue1
);
configurations
.
put
(
someKey2
,
someValue2
);
ApolloConfig
apolloConfig
=
assembleApolloConfig
(
ImmutableMap
.
copyOf
(
configurations
));
ContextHandler
handler
=
mockConfigServerHandler
(
HttpServletResponse
.
SC_OK
,
apolloConfig
);
startServerWithHandlers
(
handler
);
Config
config
=
ConfigService
.
getAppConfig
();
assertEquals
(
anotherValue
,
config
.
getProperty
(
someKey
,
null
));
Set
<
String
>
propertyNames
=
config
.
getPropertyNames
();
Iterator
<
String
>
it
=
propertyNames
.
iterator
();
assertEquals
(
someKey
,
it
.
next
());
assertEquals
(
someKey1
,
it
.
next
());
assertEquals
(
someKey2
,
it
.
next
());
assertEquals
(
anotherValue1
,
config
.
getProperty
(
someKey1
,
""
));
}
@Test
public
void
testGetConfigWithNoLocalFileAndRemoteConfigError
()
throws
Exception
{
ContextHandler
handler
=
...
...
@@ -158,6 +224,31 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
assertEquals
(
someValue
,
config
.
getProperty
(
someKey
,
null
));
}
@Test
public
void
testOrderGetConfigWithLocalFileAndRemoteConfigError
()
throws
Exception
{
String
someKey1
=
"someKey1"
;
String
someValue1
=
"someValue1"
;
String
someKey2
=
"someKey2"
;
String
someValue2
=
"someValue2"
;
Properties
properties
=
propertiesFactory
.
getPropertiesInstance
();
properties
.
put
(
someKey1
,
someValue1
);
properties
.
put
(
someKey2
,
someValue2
);
createLocalCachePropertyFile
(
properties
);
ContextHandler
handler
=
mockConfigServerHandler
(
HttpServletResponse
.
SC_INTERNAL_SERVER_ERROR
,
null
);
startServerWithHandlers
(
handler
);
Config
config
=
ConfigService
.
getAppConfig
();
assertEquals
(
someValue1
,
config
.
getProperty
(
someKey1
,
null
));
assertEquals
(
someValue2
,
config
.
getProperty
(
someKey2
,
null
));
Set
<
String
>
propertyNames
=
config
.
getPropertyNames
();
Iterator
<
String
>
it
=
propertyNames
.
iterator
();
assertEquals
(
someKey1
,
it
.
next
());
assertEquals
(
someKey2
,
it
.
next
());
}
@Test
public
void
testGetConfigWithNoLocalFileAndRemoteMetaServiceRetry
()
throws
Exception
{
String
someKey
=
"someKey"
;
...
...
@@ -279,7 +370,8 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
}
@Test
public
void
testLongPollRefreshWithMultipleNamespacesAndOnlyOneNamespaceNotified
()
throws
Exception
{
public
void
testLongPollRefreshWithMultipleNamespacesAndOnlyOneNamespaceNotified
()
throws
Exception
{
final
String
someKey
=
"someKey"
;
final
String
someValue
=
"someValue"
;
final
String
anotherValue
=
"anotherValue"
;
...
...
@@ -323,7 +415,8 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
}
@Test
public
void
testLongPollRefreshWithMultipleNamespacesAndMultipleNamespaceNotified
()
throws
Exception
{
public
void
testLongPollRefreshWithMultipleNamespacesAndMultipleNamespaceNotified
()
throws
Exception
{
final
String
someKey
=
"someKey"
;
final
String
someValue
=
"someValue"
;
final
String
anotherValue
=
"anotherValue"
;
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/DefaultConfigTest.java
View file @
82790e5f
...
...
@@ -10,6 +10,8 @@ import static org.mockito.Mockito.verify;
import
static
org
.
mockito
.
Mockito
.
when
;
import
com.ctrip.framework.apollo.enums.ConfigSourceType
;
import
com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
com.google.common.collect.Maps
;
import
com.google.common.collect.Sets
;
import
java.io.File
;
...
...
@@ -57,6 +59,7 @@ public class DefaultConfigTest {
public
void
setUp
()
throws
Exception
{
MockInjector
.
reset
();
MockInjector
.
setInstance
(
ConfigUtil
.
class
,
new
MockConfigUtil
());
MockInjector
.
setInstance
(
PropertiesFactory
.
class
,
new
DefaultPropertiesFactory
());
someResourceDir
=
new
File
(
ClassLoaderUtil
.
getClassPath
()
+
"/META-INF/config"
);
someResourceDir
.
mkdirs
();
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/LocalFileConfigRepositoryTest.java
View file @
82790e5f
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
static
org
.
hamcrest
.
Matchers
.
both
;
import
static
org
.
hamcrest
.
Matchers
.
containsInAnyOrder
;
import
static
org
.
hamcrest
.
Matchers
.
everyItem
;
import
static
org
.
hamcrest
.
Matchers
.
isIn
;
import
static
org
.
hamcrest
.
core
.
IsEqual
.
equalTo
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
...
...
@@ -10,11 +14,15 @@ import static org.mockito.Mockito.verify;
import
static
org
.
mockito
.
Mockito
.
when
;
import
com.ctrip.framework.apollo.enums.ConfigSourceType
;
import
com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.util.Map.Entry
;
import
java.util.Properties
;
import
org.hamcrest.Matcher
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
...
...
@@ -31,6 +39,7 @@ import com.google.common.io.Files;
* Created by Jason on 4/9/16.
*/
public
class
LocalFileConfigRepositoryTest
{
private
File
someBaseDir
;
private
String
someNamespace
;
private
ConfigRepository
upstreamRepo
;
...
...
@@ -40,6 +49,7 @@ public class LocalFileConfigRepositoryTest {
private
String
defaultKey
;
private
String
defaultValue
;
private
ConfigSourceType
someSourceType
;
private
MockConfigUtil
configUtil
;
@Before
public
void
setUp
()
throws
Exception
{
...
...
@@ -57,7 +67,10 @@ public class LocalFileConfigRepositoryTest {
when
(
upstreamRepo
.
getSourceType
()).
thenReturn
(
someSourceType
);
MockInjector
.
reset
();
MockInjector
.
setInstance
(
ConfigUtil
.
class
,
new
MockConfigUtil
());
configUtil
=
new
MockConfigUtil
();
MockInjector
.
setInstance
(
ConfigUtil
.
class
,
configUtil
);
MockInjector
.
setInstance
(
PropertiesFactory
.
class
,
new
DefaultPropertiesFactory
());
}
@After
...
...
@@ -110,7 +123,8 @@ public class LocalFileConfigRepositoryTest {
Files
.
write
(
defaultKey
+
"="
+
someValue
,
file
,
Charsets
.
UTF_8
);
LocalFileConfigRepository
localRepo
=
new
LocalFileConfigRepository
(
someNamespace
,
upstreamRepo
);
LocalFileConfigRepository
localRepo
=
new
LocalFileConfigRepository
(
someNamespace
,
upstreamRepo
);
localRepo
.
setLocalCacheDir
(
someBaseDir
,
true
);
Properties
properties
=
localRepo
.
getConfig
();
...
...
@@ -127,9 +141,20 @@ public class LocalFileConfigRepositoryTest {
Properties
result
=
localFileConfigRepository
.
getConfig
();
if
(!
isJDK11
()
||
(
isJDK11
()
&&
configUtil
.
isPropertiesOrderEnabled
()))
{
assertThat
(
"LocalFileConfigRepository's properties should be the same as fallback repo's when there is no local cache"
,
result
.
entrySet
(),
equalTo
(
someProperties
.
entrySet
()));
}
else
{
//In JDK11 Properties return EntrySet without customize equals implementation, so equalTo will check
//whether they are same object. This is why two statements are used to check items in entryset.
assertThat
(
"LocalFileConfigRepository's properties should be the same as fallback repo's when there is no local cache"
,
result
.
entrySet
(),
everyItem
(
isIn
(
someProperties
.
entrySet
())));
assertThat
(
"LocalFileConfigRepository's properties should be the same as fallback repo's when there is no local cache"
,
someProperties
.
entrySet
(),
everyItem
(
isIn
(
result
.
entrySet
())));
}
assertEquals
(
someSourceType
,
localFileConfigRepository
.
getSourceType
());
}
...
...
@@ -148,9 +173,20 @@ public class LocalFileConfigRepositoryTest {
Properties
anotherProperties
=
anotherLocalRepoWithNoFallback
.
getConfig
();
if
(!
isJDK11
()
||
(
isJDK11
()
&&
configUtil
.
isPropertiesOrderEnabled
()))
{
assertThat
(
"LocalFileConfigRepository should persist local cache files and return that afterwards"
,
someProperties
.
entrySet
(),
equalTo
(
anotherProperties
.
entrySet
()));
}
else
{
//In JDK11 Properties return EntrySet without customize equals implementation, so equalTo will check
//whether they are same object. This is why two statements are used to check items in entryset.
assertThat
(
"LocalFileConfigRepository's properties should be the same as fallback repo's when there is no local cache"
,
someProperties
.
entrySet
(),
everyItem
(
isIn
(
anotherProperties
.
entrySet
())));
assertThat
(
"LocalFileConfigRepository's properties should be the same as fallback repo's when there is no local cache"
,
anotherProperties
.
entrySet
(),
everyItem
(
isIn
(
someProperties
.
entrySet
())));
}
assertEquals
(
someSourceType
,
localRepo
.
getSourceType
());
}
...
...
@@ -185,6 +221,7 @@ public class LocalFileConfigRepositoryTest {
}
public
static
class
MockConfigUtil
extends
ConfigUtil
{
@Override
public
String
getAppId
()
{
return
someAppId
;
...
...
@@ -194,6 +231,10 @@ public class LocalFileConfigRepositoryTest {
public
String
getCluster
()
{
return
someCluster
;
}
public
String
getJavaVersion
()
{
return
System
.
getProperty
(
"java.version"
);
}
}
private
File
createLocalCachePropertyFile
(
Properties
properties
)
throws
IOException
{
...
...
@@ -209,4 +250,8 @@ public class LocalFileConfigRepositoryTest {
}
return
file
;
}
private
boolean
isJDK11
()
{
return
configUtil
.
getJavaVersion
().
startsWith
(
"11."
);
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/PropertiesConfigFileTest.java
View file @
82790e5f
...
...
@@ -7,8 +7,12 @@ import static org.junit.Assert.assertTrue;
import
static
org
.
mockito
.
Mockito
.
when
;
import
com.ctrip.framework.apollo.ConfigFileChangeListener
;
import
com.ctrip.framework.apollo.build.MockInjector
;
import
com.ctrip.framework.apollo.enums.PropertyChangeType
;
import
com.ctrip.framework.apollo.model.ConfigFileChangeEvent
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
com.google.common.util.concurrent.SettableFuture
;
import
java.util.Properties
;
...
...
@@ -26,6 +30,7 @@ import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
*/
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
PropertiesConfigFileTest
{
private
String
someNamespace
;
@Mock
private
ConfigRepository
configRepository
;
...
...
@@ -33,6 +38,9 @@ public class PropertiesConfigFileTest {
@Before
public
void
setUp
()
throws
Exception
{
someNamespace
=
"someName"
;
MockInjector
.
reset
();
MockInjector
.
setInstance
(
ConfigUtil
.
class
,
new
ConfigUtil
());
MockInjector
.
setInstance
(
PropertiesFactory
.
class
,
new
DefaultPropertiesFactory
());
}
@Test
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/RemoteConfigRepositoryTest.java
View file @
82790e5f
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
static
org
.
junit
.
Assert
.
assertArrayEquals
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
...
...
@@ -22,6 +23,8 @@ import com.ctrip.framework.apollo.core.signature.Signature;
import
com.ctrip.framework.apollo.enums.ConfigSourceType
;
import
com.ctrip.framework.apollo.exceptions.ApolloConfigException
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
com.ctrip.framework.apollo.util.http.HttpRequest
;
import
com.ctrip.framework.apollo.util.http.HttpResponse
;
import
com.ctrip.framework.apollo.util.http.HttpUtil
;
...
...
@@ -37,6 +40,7 @@ import java.util.Map;
import
java.util.Properties
;
import
java.util.concurrent.TimeUnit
;
import
javax.servlet.http.HttpServletResponse
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -45,12 +49,14 @@ import org.mockito.Mock;
import
org.mockito.invocation.InvocationOnMock
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.mockito.stubbing.Answer
;
import
org.springframework.test.util.ReflectionTestUtils
;
/**
* Created by Jason on 4/9/16.
*/
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
RemoteConfigRepositoryTest
{
@Mock
private
ConfigServiceLocator
configServiceLocator
;
private
String
someNamespace
;
...
...
@@ -92,16 +98,26 @@ public class RemoteConfigRepositoryTest {
MockInjector
.
setInstance
(
RemoteConfigLongPollService
.
class
,
remoteConfigLongPollService
);
System
.
setProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
,
"true"
);
PropertiesFactory
propertiesFactory
=
new
DefaultPropertiesFactory
();
MockInjector
.
setInstance
(
PropertiesFactory
.
class
,
propertiesFactory
);
someAppId
=
"someAppId"
;
someCluster
=
"someCluster"
;
}
@After
public
void
tearDown
()
throws
Exception
{
System
.
clearProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
);
}
@Test
public
void
testLoadConfig
()
throws
Exception
{
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
Map
<
String
,
String
>
configurations
=
Maps
.
newHashMap
();
Map
<
String
,
String
>
configurations
=
Maps
.
new
Linked
HashMap
();
configurations
.
put
(
someKey
,
someValue
);
configurations
.
put
(
"someKey2"
,
"someValue2"
);
ApolloConfig
someApolloConfig
=
assembleApolloConfig
(
configurations
);
when
(
someResponse
.
getStatusCode
()).
thenReturn
(
200
);
...
...
@@ -111,9 +127,16 @@ public class RemoteConfigRepositoryTest {
Properties
config
=
remoteConfigRepository
.
getConfig
();
assertEquals
(
configurations
,
config
);
// assertEquals(configurations, config);
assertTrue
(
configurations
.
equals
(
config
));
assertEquals
(
ConfigSourceType
.
REMOTE
,
remoteConfigRepository
.
getSourceType
());
remoteConfigLongPollService
.
stopLongPollingRefresh
();
if
(
configUtil
.
isPropertiesOrderEnabled
())
{
String
[]
actualArrays
=
config
.
keySet
().
toArray
(
new
String
[]{});
String
[]
expectedArrays
=
{
"someKey"
,
"someKey2"
};
assertArrayEquals
(
expectedArrays
,
actualArrays
);
}
}
@Test
...
...
@@ -236,7 +259,8 @@ public class RemoteConfigRepositoryTest {
verify
(
someListener
,
times
(
1
)).
onRepositoryChange
(
eq
(
someNamespace
),
captor
.
capture
());
assertEquals
(
newConfigurations
,
captor
.
getValue
());
final
ArgumentCaptor
<
HttpRequest
>
httpRequestArgumentCaptor
=
ArgumentCaptor
.
forClass
(
HttpRequest
.
class
);
final
ArgumentCaptor
<
HttpRequest
>
httpRequestArgumentCaptor
=
ArgumentCaptor
.
forClass
(
HttpRequest
.
class
);
verify
(
httpUtil
,
atLeast
(
2
)).
doGet
(
httpRequestArgumentCaptor
.
capture
(),
eq
(
ApolloConfig
.
class
));
HttpRequest
request
=
httpRequestArgumentCaptor
.
getValue
();
...
...
@@ -265,7 +289,8 @@ public class RemoteConfigRepositoryTest {
when
(
someApolloConfig
.
getReleaseKey
()).
thenReturn
(
someReleaseKey
);
String
queryConfigUrl
=
remoteConfigRepository
.
assembleQueryConfigUrl
(
someUri
,
someAppId
,
someCluster
,
someNamespace
,
null
,
notificationMessages
,
.
assembleQueryConfigUrl
(
someUri
,
someAppId
,
someCluster
,
someNamespace
,
null
,
notificationMessages
,
someApolloConfig
);
remoteConfigLongPollService
.
stopLongPollingRefresh
();
...
...
@@ -275,7 +300,8 @@ public class RemoteConfigRepositoryTest {
assertTrue
(
queryConfigUrl
.
contains
(
"releaseKey=20160705193346-583078ef5716c055%2B20160705193308-31c471ddf9087c3f"
));
assertTrue
(
queryConfigUrl
.
contains
(
"messages="
+
UrlEscapers
.
urlFormParameterEscaper
().
escape
(
gson
.
toJson
(
notificationMessages
))));
.
contains
(
"messages="
+
UrlEscapers
.
urlFormParameterEscaper
()
.
escape
(
gson
.
toJson
(
notificationMessages
))));
}
private
ApolloConfig
assembleApolloConfig
(
Map
<
String
,
String
>
configurations
)
{
...
...
@@ -291,6 +317,7 @@ public class RemoteConfigRepositoryTest {
}
public
static
class
MockConfigUtil
extends
ConfigUtil
{
@Override
public
String
getAppId
()
{
return
someAppId
;
...
...
@@ -338,9 +365,10 @@ public class RemoteConfigRepositoryTest {
}
public
static
class
MockHttpUtil
extends
HttpUtil
{
@Override
public
<
T
>
HttpResponse
<
T
>
doGet
(
HttpRequest
httpRequest
,
Class
<
T
>
responseType
)
{
if
(
someResponse
.
getStatusCode
()
==
200
||
someResponse
.
getStatusCode
()
==
304
)
{
if
(
someResponse
.
getStatusCode
()
==
200
||
someResponse
.
getStatusCode
()
==
304
)
{
return
(
HttpResponse
<
T
>)
someResponse
;
}
throw
new
ApolloConfigException
(
String
.
format
(
"Http request failed due to status code: %d"
,
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/SimpleConfigTest.java
View file @
82790e5f
...
...
@@ -4,10 +4,14 @@ import static org.junit.Assert.assertEquals;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
com.ctrip.framework.apollo.build.MockInjector
;
import
com.ctrip.framework.apollo.enums.ConfigSourceType
;
import
com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
java.util.Properties
;
import
java.util.concurrent.TimeUnit
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -27,6 +31,7 @@ import com.google.common.util.concurrent.SettableFuture;
*/
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
SimpleConfigTest
{
private
String
someNamespace
;
@Mock
private
ConfigRepository
configRepository
;
...
...
@@ -35,6 +40,15 @@ public class SimpleConfigTest {
@Before
public
void
setUp
()
throws
Exception
{
someNamespace
=
"someName"
;
System
.
setProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
,
"true"
);
PropertiesFactory
propertiesFactory
=
new
DefaultPropertiesFactory
();
MockInjector
.
setInstance
(
PropertiesFactory
.
class
,
propertiesFactory
);
}
@After
public
void
tearDown
()
throws
Exception
{
System
.
clearProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
);
}
@Test
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/XmlConfigFileTest.java
View file @
82790e5f
...
...
@@ -7,12 +7,16 @@ import static org.junit.Assert.assertTrue;
import
static
org
.
mockito
.
Mockito
.
when
;
import
com.ctrip.framework.apollo.ConfigFileChangeListener
;
import
com.ctrip.framework.apollo.build.MockInjector
;
import
com.ctrip.framework.apollo.enums.PropertyChangeType
;
import
com.ctrip.framework.apollo.model.ConfigFileChangeEvent
;
import
com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
com.google.common.util.concurrent.SettableFuture
;
import
java.util.Properties
;
import
java.util.concurrent.TimeUnit
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -27,6 +31,7 @@ import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
*/
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
XmlConfigFileTest
{
private
String
someNamespace
;
@Mock
private
ConfigRepository
configRepository
;
...
...
@@ -34,6 +39,15 @@ public class XmlConfigFileTest {
@Before
public
void
setUp
()
throws
Exception
{
someNamespace
=
"someName"
;
System
.
setProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
,
"true"
);
PropertiesFactory
propertiesFactory
=
new
DefaultPropertiesFactory
();
MockInjector
.
setInstance
(
PropertiesFactory
.
class
,
propertiesFactory
);
}
@After
public
void
tearDown
()
throws
Exception
{
System
.
clearProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
);
}
@Test
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/YamlConfigFileTest.java
View file @
82790e5f
...
...
@@ -7,8 +7,12 @@ import com.ctrip.framework.apollo.build.MockInjector;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.enums.ConfigSourceType
;
import
com.ctrip.framework.apollo.exceptions.ApolloConfigException
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
com.ctrip.framework.apollo.util.yaml.YamlParser
;
import
java.util.Properties
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -17,6 +21,7 @@ import org.mockito.runners.MockitoJUnitRunner;
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
YamlConfigFileTest
{
private
String
someNamespace
;
@Mock
private
ConfigRepository
configRepository
;
...
...
@@ -29,8 +34,17 @@ public class YamlConfigFileTest {
public
void
setUp
()
throws
Exception
{
someNamespace
=
"someName"
;
System
.
setProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
,
"true"
);
MockInjector
.
reset
();
MockInjector
.
setInstance
(
YamlParser
.
class
,
yamlParser
);
MockInjector
.
setInstance
(
ConfigUtil
.
class
,
new
ConfigUtil
());
MockInjector
.
setInstance
(
PropertiesFactory
.
class
,
new
DefaultPropertiesFactory
());
}
@After
public
void
tearDown
()
throws
Exception
{
System
.
clearProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
);
}
@Test
...
...
@@ -54,6 +68,30 @@ public class YamlConfigFileTest {
assertSame
(
yamlProperties
,
configFile
.
asProperties
());
}
@Test
public
void
testWhenHasContentWithOrder
()
throws
Exception
{
Properties
someProperties
=
new
Properties
();
String
key
=
ConfigConsts
.
CONFIG_FILE_CONTENT_KEY
;
String
someContent
=
"someKey: 'someValue'\nsomeKey2: 'someValue2'"
;
someProperties
.
setProperty
(
key
,
someContent
);
someSourceType
=
ConfigSourceType
.
LOCAL
;
Properties
yamlProperties
=
new
YamlParser
().
yamlToProperties
(
someContent
);
when
(
configRepository
.
getConfig
()).
thenReturn
(
someProperties
);
when
(
configRepository
.
getSourceType
()).
thenReturn
(
someSourceType
);
when
(
yamlParser
.
yamlToProperties
(
someContent
)).
thenReturn
(
yamlProperties
);
YamlConfigFile
configFile
=
new
YamlConfigFile
(
someNamespace
,
configRepository
);
assertSame
(
someContent
,
configFile
.
getContent
());
assertSame
(
yamlProperties
,
configFile
.
asProperties
());
String
[]
actualArrays
=
configFile
.
asProperties
().
keySet
().
toArray
(
new
String
[]{});
String
[]
expectedArrays
=
{
"someKey"
,
"someKey2"
};
assertArrayEquals
(
expectedArrays
,
actualArrays
);
}
@Test
public
void
testWhenHasNoContent
()
throws
Exception
{
when
(
configRepository
.
getConfig
()).
thenReturn
(
null
);
...
...
@@ -78,7 +116,8 @@ public class YamlConfigFileTest {
when
(
configRepository
.
getConfig
()).
thenReturn
(
someProperties
);
when
(
configRepository
.
getSourceType
()).
thenReturn
(
someSourceType
);
when
(
yamlParser
.
yamlToProperties
(
someInvalidContent
)).
thenThrow
(
new
RuntimeException
(
"some exception"
));
when
(
yamlParser
.
yamlToProperties
(
someInvalidContent
))
.
thenThrow
(
new
RuntimeException
(
"some exception"
));
YamlConfigFile
configFile
=
new
YamlConfigFile
(
someNamespace
,
configRepository
);
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/util/ConfigUtilTest.java
View file @
82790e5f
...
...
@@ -2,6 +2,7 @@ package com.ctrip.framework.apollo.util;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.util.factory.PropertiesFactory
;
import
java.io.File
;
import
org.junit.After
;
import
org.junit.Test
;
...
...
@@ -15,6 +16,7 @@ import static org.mockito.Mockito.when;
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ConfigUtilTest
{
@After
public
void
tearDown
()
throws
Exception
{
System
.
clearProperty
(
ConfigConsts
.
APOLLO_CLUSTER_KEY
);
...
...
@@ -27,6 +29,7 @@ public class ConfigUtilTest {
System
.
clearProperty
(
"apollo.longPollingInitialDelayInMills"
);
System
.
clearProperty
(
"apollo.autoUpdateInjectedSpringProperties"
);
System
.
clearProperty
(
"apollo.cacheDir"
);
System
.
clearProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
);
}
@Test
...
...
@@ -162,7 +165,8 @@ public class ConfigUtilTest {
@Test
public
void
testCustomizeLongPollingInitialDelayInMills
()
throws
Exception
{
long
someLongPollingDelayInMills
=
1
;
System
.
setProperty
(
"apollo.longPollingInitialDelayInMills"
,
String
.
valueOf
(
someLongPollingDelayInMills
));
System
.
setProperty
(
"apollo.longPollingInitialDelayInMills"
,
String
.
valueOf
(
someLongPollingDelayInMills
));
ConfigUtil
configUtil
=
new
ConfigUtil
();
...
...
@@ -221,4 +225,16 @@ public class ConfigUtilTest {
assertEquals
(
"/opt/data/"
+
someAppId
,
configUtil
.
getDefaultLocalCacheDir
());
}
@Test
public
void
testCustomizePropertiesOrdered
()
{
boolean
propertiesOrdered
=
true
;
System
.
setProperty
(
PropertiesFactory
.
APOLLO_PROPERTY_ORDER_ENABLE
,
String
.
valueOf
(
propertiesOrdered
));
ConfigUtil
configUtil
=
new
ConfigUtil
();
assertEquals
(
propertiesOrdered
,
configUtil
.
isPropertiesOrderEnabled
());
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/util/OrderedPropertiesTest.java
0 → 100644
View file @
82790e5f
package
com
.
ctrip
.
framework
.
apollo
.
util
;
import
static
org
.
junit
.
Assert
.*;
import
java.util.Collection
;
import
java.util.Enumeration
;
import
java.util.Properties
;
import
org.junit.Before
;
import
org.junit.Ignore
;
import
org.junit.Test
;
public
class
OrderedPropertiesTest
{
private
OrderedProperties
orderedProperties
;
private
Properties
legacyProperties
;
@Before
public
void
setUp
()
{
orderedProperties
=
new
OrderedProperties
();
orderedProperties
.
setProperty
(
"key1"
,
"value1"
);
orderedProperties
.
setProperty
(
"key2"
,
"value2"
);
}
@Test
public
void
testOrderedPropertiesInvokedAsLegacyProperties
()
{
legacyProperties
=
orderedProperties
;
assertEquals
(
orderedProperties
.
size
(),
legacyProperties
.
size
());
legacyProperties
.
put
(
"key3"
,
"value3"
);
assertEquals
(
orderedProperties
.
size
(),
legacyProperties
.
size
());
assertEquals
(
orderedProperties
.
getProperty
(
"key3"
),
legacyProperties
.
getProperty
(
"key3"
));
assertEquals
(
orderedProperties
.
get
(
"key3"
),
legacyProperties
.
get
(
"key3"
));
assertEquals
(
orderedProperties
.
containsKey
(
"key2"
),
legacyProperties
.
containsKey
(
"key2"
));
assertEquals
(
orderedProperties
.
containsValue
(
"key2"
),
legacyProperties
.
containsValue
(
"key2"
));
assertEquals
(
orderedProperties
.
containsValue
(
"value2"
),
legacyProperties
.
containsValue
(
"value2"
));
assertEquals
(
orderedProperties
.
entrySet
(),
legacyProperties
.
entrySet
());
assertEquals
(
orderedProperties
.
keySet
(),
legacyProperties
.
keySet
());
}
@Test
public
void
testClear
()
{
orderedProperties
.
clear
();
assertEquals
(
0
,
orderedProperties
.
size
());
assertTrue
(
orderedProperties
.
isEmpty
());
}
@Test
public
void
testClone
()
{
OrderedProperties
clone
=
(
OrderedProperties
)
orderedProperties
.
clone
();
assertNotSame
(
clone
,
orderedProperties
);
assertEquals
(
orderedProperties
,
clone
);
}
@Test
public
void
testRemove
()
{
Object
value1
=
orderedProperties
.
remove
(
"key1"
);
assertEquals
(
"value1"
,
value1
);
value1
=
orderedProperties
.
remove
(
"key1"
);
assertNull
(
value1
);
assertNull
(
orderedProperties
.
get
(
"key1"
));
assertFalse
(
orderedProperties
.
keySet
().
contains
(
"key1"
));
}
@Test
public
void
testValues
()
{
Collection
<
Object
>
values
=
orderedProperties
.
values
();
assertEquals
(
2
,
values
.
size
());
assertTrue
(
values
.
contains
(
"value1"
));
assertTrue
(
values
.
contains
(
"value2"
));
}
@Test
(
expected
=
NullPointerException
.
class
)
public
void
testPutNull
()
{
orderedProperties
.
put
(
"key3"
,
null
);
}
@Test
public
void
testPropertyNames
()
{
Enumeration
<
String
>
propertyNames
=
(
Enumeration
<
String
>)
orderedProperties
.
propertyNames
();
assertTrue
(
propertyNames
.
nextElement
().
equals
(
"key1"
));
assertTrue
(
propertyNames
.
nextElement
().
equals
(
"key2"
));
}
@Test
public
void
testKeys
()
{
Enumeration
<
Object
>
keys
=
orderedProperties
.
keys
();
assertTrue
(
keys
.
hasMoreElements
());
assertEquals
(
"key1"
,
keys
.
nextElement
());
assertTrue
(
keys
.
hasMoreElements
());
assertEquals
(
"key2"
,
keys
.
nextElement
());
}
}
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