Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
superrain51
apollo
提交
5bb2aaf1
apollo
项目概览
superrain51
/
apollo
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
apollo
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5bb2aaf1
编写于
4月 12, 2016
作者:
Y
Yiming Liu
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #79 from nobodyiam/client-refresh-merge
Add client side auto refresh capability
上级
b1c4b7d8
df474afd
变更
26
隐藏空白更改
内联
并排
Showing
26 changed file
with
719 addition
and
118 deletion
+719
-118
apollo-biz/src/main/java/com/ctrip/apollo/biz/repository/ReleaseRepository.java
...va/com/ctrip/apollo/biz/repository/ReleaseRepository.java
+1
-2
apollo-biz/src/main/java/com/ctrip/apollo/biz/service/ConfigService.java
...main/java/com/ctrip/apollo/biz/service/ConfigService.java
+1
-1
apollo-client/src/main/java/com/ctrip/apollo/Config.java
apollo-client/src/main/java/com/ctrip/apollo/Config.java
+2
-0
apollo-client/src/main/java/com/ctrip/apollo/ConfigChangeListener.java
.../src/main/java/com/ctrip/apollo/ConfigChangeListener.java
+10
-0
apollo-client/src/main/java/com/ctrip/apollo/internals/AbstractConfig.java
.../main/java/com/ctrip/apollo/internals/AbstractConfig.java
+84
-0
apollo-client/src/main/java/com/ctrip/apollo/internals/AbstractConfigRepository.java
.../com/ctrip/apollo/internals/AbstractConfigRepository.java
+39
-0
apollo-client/src/main/java/com/ctrip/apollo/internals/ConfigRepository.java
...ain/java/com/ctrip/apollo/internals/ConfigRepository.java
+13
-1
apollo-client/src/main/java/com/ctrip/apollo/internals/DefaultConfig.java
...c/main/java/com/ctrip/apollo/internals/DefaultConfig.java
+74
-5
apollo-client/src/main/java/com/ctrip/apollo/internals/DefaultConfigManager.java
...java/com/ctrip/apollo/internals/DefaultConfigManager.java
+1
-1
apollo-client/src/main/java/com/ctrip/apollo/internals/LocalFileConfigRepository.java
...com/ctrip/apollo/internals/LocalFileConfigRepository.java
+44
-18
apollo-client/src/main/java/com/ctrip/apollo/internals/RemoteConfigRepository.java
...va/com/ctrip/apollo/internals/RemoteConfigRepository.java
+50
-15
apollo-client/src/main/java/com/ctrip/apollo/internals/RepositoryChangeListener.java
.../com/ctrip/apollo/internals/RepositoryChangeListener.java
+10
-0
apollo-client/src/main/java/com/ctrip/apollo/internals/SimpleConfig.java
...rc/main/java/com/ctrip/apollo/internals/SimpleConfig.java
+35
-7
apollo-client/src/main/java/com/ctrip/apollo/model/ConfigChange.java
...nt/src/main/java/com/ctrip/apollo/model/ConfigChange.java
+63
-0
apollo-client/src/main/java/com/ctrip/apollo/model/ConfigChangeEvent.java
...c/main/java/com/ctrip/apollo/model/ConfigChangeEvent.java
+38
-0
apollo-client/src/main/java/com/ctrip/apollo/model/ConfigRefreshResult.java
...main/java/com/ctrip/apollo/model/ConfigRefreshResult.java
+0
-41
apollo-client/src/main/java/com/ctrip/apollo/spi/DefaultConfigFactory.java
.../main/java/com/ctrip/apollo/spi/DefaultConfigFactory.java
+1
-2
apollo-client/src/main/java/com/ctrip/apollo/util/http/HttpUtil.java
...nt/src/main/java/com/ctrip/apollo/util/http/HttpUtil.java
+10
-9
apollo-client/src/test/java/com/ctrip/apollo/ConfigServiceTest.java
...ent/src/test/java/com/ctrip/apollo/ConfigServiceTest.java
+5
-0
apollo-client/src/test/java/com/ctrip/apollo/internals/DefaultConfigManagerTest.java
.../com/ctrip/apollo/internals/DefaultConfigManagerTest.java
+7
-0
apollo-client/src/test/java/com/ctrip/apollo/internals/DefaultConfigTest.java
...st/java/com/ctrip/apollo/internals/DefaultConfigTest.java
+87
-4
apollo-client/src/test/java/com/ctrip/apollo/internals/LocalFileConfigRepositoryTest.java
...ctrip/apollo/internals/LocalFileConfigRepositoryTest.java
+34
-5
apollo-client/src/test/java/com/ctrip/apollo/internals/RemoteConfigRepositoryTest.java
...om/ctrip/apollo/internals/RemoteConfigRepositoryTest.java
+27
-2
apollo-client/src/test/java/com/ctrip/apollo/internals/SimpleConfigTest.java
...est/java/com/ctrip/apollo/internals/SimpleConfigTest.java
+62
-2
apollo-client/src/test/java/com/ctrip/apollo/spi/DefaultConfigFactoryTest.java
...t/java/com/ctrip/apollo/spi/DefaultConfigFactoryTest.java
+1
-1
apollo-demo/src/main/java/ApolloConfigDemo.java
apollo-demo/src/main/java/ApolloConfigDemo.java
+20
-2
未找到文件。
apollo-biz/src/main/java/com/ctrip/apollo/biz/repository/ReleaseRepository.java
浏览文件 @
5bb2aaf1
...
...
@@ -13,8 +13,7 @@ import com.ctrip.apollo.biz.entity.Release;
*/
public
interface
ReleaseRepository
extends
PagingAndSortingRepository
<
Release
,
Long
>
{
@Query
(
"SELECT r FROM Release r WHERE r.appId = :appId AND r.clusterName = :clusterName AND r.namespaceName = :namespaceName order by r.id desc"
)
Release
findLatest
(
@Param
(
"appId"
)
String
appId
,
@Param
(
"clusterName"
)
String
clusterName
,
Release
findFirstByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc
(
@Param
(
"appId"
)
String
appId
,
@Param
(
"clusterName"
)
String
clusterName
,
@Param
(
"namespaceName"
)
String
namespaceName
);
List
<
Release
>
findByAppIdAndClusterNameAndNamespaceName
(
String
appId
,
String
clusterName
,
...
...
apollo-biz/src/main/java/com/ctrip/apollo/biz/service/ConfigService.java
浏览文件 @
5bb2aaf1
...
...
@@ -30,7 +30,7 @@ public class ConfigService {
private
Type
configurationTypeReference
=
new
TypeToken
<
Map
<
String
,
String
>>(){}.
getType
();
public
Release
findRelease
(
String
appId
,
String
clusterName
,
String
namespaceName
)
{
Release
release
=
releaseRepository
.
find
Latest
(
appId
,
clusterName
,
namespaceName
);
Release
release
=
releaseRepository
.
find
FirstByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc
(
appId
,
clusterName
,
namespaceName
);
return
release
;
}
...
...
apollo-client/src/main/java/com/ctrip/apollo/Config.java
浏览文件 @
5bb2aaf1
...
...
@@ -12,4 +12,6 @@ public interface Config {
* @return the property value
*/
public
String
getProperty
(
String
key
,
String
defaultValue
);
public
void
addChangeListener
(
ConfigChangeListener
listener
);
}
apollo-client/src/main/java/com/ctrip/apollo/ConfigChangeListener.java
0 → 100644
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo
;
import
com.ctrip.apollo.model.ConfigChangeEvent
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
interface
ConfigChangeListener
{
public
void
onChange
(
ConfigChangeEvent
changeEvent
);
}
apollo-client/src/main/java/com/ctrip/apollo/internals/AbstractConfig.java
0 → 100644
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo.internals
;
import
com.google.common.base.Objects
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Sets
;
import
com.ctrip.apollo.Config
;
import
com.ctrip.apollo.ConfigChangeListener
;
import
com.ctrip.apollo.enums.PropertyChangeType
;
import
com.ctrip.apollo.model.ConfigChange
;
import
com.ctrip.apollo.model.ConfigChangeEvent
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.util.List
;
import
java.util.Properties
;
import
java.util.Set
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
abstract
class
AbstractConfig
implements
Config
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
AbstractConfig
.
class
);
private
List
<
ConfigChangeListener
>
m_listeners
=
Lists
.
newCopyOnWriteArrayList
();
@Override
public
void
addChangeListener
(
ConfigChangeListener
listener
)
{
if
(!
m_listeners
.
contains
(
listener
))
{
m_listeners
.
add
(
listener
);
}
}
protected
void
fireConfigChange
(
ConfigChangeEvent
changeEvent
)
{
for
(
ConfigChangeListener
listener
:
m_listeners
)
{
try
{
listener
.
onChange
(
changeEvent
);
}
catch
(
Throwable
t
)
{
logger
.
error
(
"Failed to invoke config change listener {}"
,
listener
.
getClass
(),
t
);
}
}
}
List
<
ConfigChange
>
calcPropertyChanges
(
Properties
previous
,
Properties
current
)
{
if
(
previous
==
null
)
{
previous
=
new
Properties
();
}
if
(
current
==
null
)
{
current
=
new
Properties
();
}
Set
<
String
>
previousKeys
=
previous
.
stringPropertyNames
();
Set
<
String
>
currentKeys
=
current
.
stringPropertyNames
();
Set
<
String
>
commonKeys
=
Sets
.
intersection
(
previousKeys
,
currentKeys
);
Set
<
String
>
newKeys
=
Sets
.
difference
(
currentKeys
,
commonKeys
);
Set
<
String
>
removedKeys
=
Sets
.
difference
(
previousKeys
,
commonKeys
);
List
<
ConfigChange
>
changes
=
Lists
.
newArrayList
();
for
(
String
newKey
:
newKeys
)
{
changes
.
add
(
new
ConfigChange
(
newKey
,
null
,
current
.
getProperty
(
newKey
),
PropertyChangeType
.
NEW
));
}
for
(
String
removedKey
:
removedKeys
)
{
changes
.
add
(
new
ConfigChange
(
removedKey
,
previous
.
getProperty
(
removedKey
),
null
,
PropertyChangeType
.
DELETED
));
}
for
(
String
commonKey
:
commonKeys
)
{
String
previousValue
=
previous
.
getProperty
(
commonKey
);
String
currentValue
=
current
.
getProperty
(
commonKey
);
if
(
Objects
.
equal
(
previousValue
,
currentValue
))
{
continue
;
}
changes
.
add
(
new
ConfigChange
(
commonKey
,
previousValue
,
currentValue
,
PropertyChangeType
.
MODIFIED
));
}
return
changes
;
}
}
apollo-client/src/main/java/com/ctrip/apollo/internals/AbstractConfigRepository.java
0 → 100644
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo.internals
;
import
com.google.common.collect.Lists
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.util.List
;
import
java.util.Properties
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
abstract
class
AbstractConfigRepository
implements
ConfigRepository
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
AbstractConfigRepository
.
class
);
private
List
<
RepositoryChangeListener
>
m_listeners
=
Lists
.
newCopyOnWriteArrayList
();
@Override
public
void
addChangeListener
(
RepositoryChangeListener
listener
)
{
if
(!
m_listeners
.
contains
(
listener
))
{
m_listeners
.
add
(
listener
);
}
}
@Override
public
void
removeChangeListener
(
RepositoryChangeListener
listener
)
{
m_listeners
.
remove
(
listener
);
}
protected
void
fireRepositoryChange
(
String
namespace
,
Properties
newProperties
)
{
for
(
RepositoryChangeListener
listener
:
m_listeners
)
{
try
{
listener
.
onRepositoryChange
(
namespace
,
newProperties
);
}
catch
(
Throwable
t
)
{
logger
.
error
(
"Failed to invoke repository change listener {}"
,
listener
.
getClass
(),
t
);
}
}
}
}
apollo-client/src/main/java/com/ctrip/apollo/internals/ConfigRepository.java
浏览文件 @
5bb2aaf1
...
...
@@ -6,7 +6,19 @@ import java.util.Properties;
* @author Jason Song(song_s@ctrip.com)
*/
public
interface
ConfigRepository
{
public
Properties
loadConfig
();
/**
* Get the config from this repository
* @return
*/
public
Properties
getConfig
();
/**
* Set the fallback repo for this repository
* @param fallbackConfigRepository
*/
public
void
setFallback
(
ConfigRepository
fallbackConfigRepository
);
public
void
addChangeListener
(
RepositoryChangeListener
listener
);
public
void
removeChangeListener
(
RepositoryChangeListener
listener
);
}
apollo-client/src/main/java/com/ctrip/apollo/internals/DefaultConfig.java
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo.internals
;
import
com.ctrip.apollo.Config
;
import
com.google.common.collect.ImmutableMap
;
import
com.ctrip.apollo.core.utils.ClassLoaderUtil
;
import
com.ctrip.apollo.enums.PropertyChangeType
;
import
com.ctrip.apollo.model.ConfigChange
;
import
com.ctrip.apollo.model.ConfigChangeEvent
;
import
com.dianping.cat.Cat
;
import
org.slf4j.Logger
;
...
...
@@ -9,12 +13,15 @@ import org.slf4j.LoggerFactory;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.Properties
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
DefaultConfig
implements
Config
{
public
class
DefaultConfig
extends
AbstractConfig
implements
RepositoryChangeListener
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
DefaultConfig
.
class
);
private
final
String
m_namespace
;
private
Properties
m_resourceProperties
;
...
...
@@ -30,7 +37,8 @@ public class DefaultConfig implements Config {
private
void
initialize
()
{
try
{
m_configProperties
=
m_configRepository
.
loadConfig
();
m_configProperties
=
m_configRepository
.
getConfig
();
m_configRepository
.
addChangeListener
(
this
);
}
catch
(
Throwable
ex
)
{
String
message
=
String
.
format
(
"Init Apollo Local Config failed - namespace: %s"
,
m_namespace
);
...
...
@@ -68,6 +76,69 @@ public class DefaultConfig implements Config {
return
value
==
null
?
defaultValue
:
value
;
}
@Override
public
synchronized
void
onRepositoryChange
(
String
namespace
,
Properties
newProperties
)
{
if
(
newProperties
.
equals
(
m_configProperties
))
{
return
;
}
Properties
newConfigProperties
=
new
Properties
();
newConfigProperties
.
putAll
(
newProperties
);
Map
<
String
,
ConfigChange
>
actualChanges
=
updateAndCalcConfigChanges
(
newConfigProperties
);
this
.
fireConfigChange
(
new
ConfigChangeEvent
(
m_namespace
,
actualChanges
));
}
private
Map
<
String
,
ConfigChange
>
updateAndCalcConfigChanges
(
Properties
newConfigProperties
)
{
List
<
ConfigChange
>
configChanges
=
calcPropertyChanges
(
m_configProperties
,
newConfigProperties
);
// List<ConfigChange> actualChanges = Lists.newArrayListWithCapacity(configChanges.size());
ImmutableMap
.
Builder
<
String
,
ConfigChange
>
actualChanges
=
new
ImmutableMap
.
Builder
<>();
/** === Double check since DefaultConfig has multiple config sources ==== **/
//1. use getProperty to update configChanges's old value
for
(
ConfigChange
change
:
configChanges
)
{
change
.
setOldValue
(
this
.
getProperty
(
change
.
getPropertyName
(),
change
.
getOldValue
()));
}
//2. update m_configProperties
m_configProperties
=
newConfigProperties
;
//3. use getProperty to update configChange's new value and calc the final changes
for
(
ConfigChange
change
:
configChanges
)
{
change
.
setNewValue
(
this
.
getProperty
(
change
.
getPropertyName
(),
change
.
getNewValue
()));
switch
(
change
.
getChangeType
())
{
case
NEW:
if
(
Objects
.
equals
(
change
.
getOldValue
(),
change
.
getNewValue
()))
{
break
;
}
if
(!
Objects
.
isNull
(
change
.
getOldValue
()))
{
change
.
setChangeType
(
PropertyChangeType
.
MODIFIED
);
}
actualChanges
.
put
(
change
.
getPropertyName
(),
change
);
break
;
case
MODIFIED:
if
(!
Objects
.
equals
(
change
.
getOldValue
(),
change
.
getNewValue
()))
{
actualChanges
.
put
(
change
.
getPropertyName
(),
change
);
}
break
;
case
DELETED:
if
(
Objects
.
equals
(
change
.
getOldValue
(),
change
.
getNewValue
()))
{
break
;
}
if
(!
Objects
.
isNull
(
change
.
getNewValue
()))
{
change
.
setChangeType
(
PropertyChangeType
.
MODIFIED
);
}
actualChanges
.
put
(
change
.
getPropertyName
(),
change
);
break
;
}
}
return
actualChanges
.
build
();
}
private
Properties
loadFromResource
(
String
namespace
)
{
String
name
=
String
.
format
(
"META-INF/config/%s.properties"
,
namespace
);
InputStream
in
=
ClassLoaderUtil
.
getLoader
().
getResourceAsStream
(
name
);
...
...
@@ -92,6 +163,4 @@ public class DefaultConfig implements Config {
return
properties
;
}
}
apollo-client/src/main/java/com/ctrip/apollo/internals/DefaultConfigManager.java
浏览文件 @
5bb2aaf1
...
...
@@ -19,7 +19,7 @@ public class DefaultConfigManager implements ConfigManager {
@Inject
private
ConfigFactoryManager
m_factoryManager
;
private
Map
<
String
,
Config
>
m_configs
=
Maps
.
new
Hash
Map
();
private
Map
<
String
,
Config
>
m_configs
=
Maps
.
new
Concurrent
Map
();
@Override
public
Config
getConfig
(
String
namespace
)
{
...
...
apollo-client/src/main/java/com/ctrip/apollo/internals/LocalFileConfigRepository.java
浏览文件 @
5bb2aaf1
...
...
@@ -22,14 +22,15 @@ import java.util.Properties;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
LocalFileConfigRepository
implements
ConfigRepository
{
public
class
LocalFileConfigRepository
extends
AbstractConfigRepository
implements
RepositoryChangeListener
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
LocalFileConfigRepository
.
class
);
private
PlexusContainer
m_container
;
private
final
PlexusContainer
m_container
;
private
final
String
m_namespace
;
private
final
File
m_baseDir
;
private
final
ConfigUtil
m_configUtil
;
private
Properties
m_fileProperties
;
private
ConfigRepository
m_fallback
;
private
volatile
Properties
m_fileProperties
;
private
volatile
ConfigRepository
m_fallback
;
public
LocalFileConfigRepository
(
File
baseDir
,
String
namespace
)
{
m_baseDir
=
baseDir
;
...
...
@@ -43,7 +44,7 @@ public class LocalFileConfigRepository implements ConfigRepository {
}
@Override
public
Properties
load
Config
()
{
public
Properties
get
Config
()
{
if
(
m_fileProperties
==
null
)
{
initLocalConfig
();
}
...
...
@@ -54,26 +55,51 @@ public class LocalFileConfigRepository implements ConfigRepository {
@Override
public
void
setFallback
(
ConfigRepository
fallbackConfigRepository
)
{
//clear previous listener
if
(
m_fallback
!=
null
)
{
m_fallback
.
removeChangeListener
(
this
);
}
m_fallback
=
fallbackConfigRepository
;
fallbackConfigRepository
.
addChangeListener
(
this
);
}
void
initLocalConfig
()
{
if
(
m_fallback
!=
null
)
{
try
{
m_fileProperties
=
m_fallback
.
loadConfig
();
//TODO register change listener
persistLocalCacheFile
(
m_baseDir
,
m_namespace
);
return
;
}
catch
(
Throwable
ex
)
{
logger
.
error
(
"Load config from fallback loader failed"
,
ex
);
Cat
.
logError
(
ex
);
}
@Override
public
synchronized
void
onRepositoryChange
(
String
namespace
,
Properties
newProperties
)
{
if
(
newProperties
.
equals
(
m_fileProperties
))
{
return
;
}
Properties
newFileProperties
=
new
Properties
();
newFileProperties
.
putAll
(
newProperties
);
this
.
m_fileProperties
=
newFileProperties
;
persistLocalCacheFile
(
m_baseDir
,
m_namespace
);
this
.
fireRepositoryChange
(
namespace
,
newProperties
);
}
void
initLocalConfig
()
{
try
{
m_fileProperties
=
this
.
loadFromLocalCacheFile
(
m_baseDir
,
m_namespace
);
}
catch
(
IOException
ex
)
{
throw
new
RuntimeException
(
"Loading config from local cache file failed"
,
ex
);
}
catch
(
Throwable
ex
)
{
logger
.
error
(
"Load config from local config cache file failed"
,
ex
);
}
//TODO check whether properties is expired or should we return after it's synced with fallback?
if
(
m_fileProperties
!=
null
)
{
return
;
}
if
(
m_fallback
==
null
)
{
throw
new
RuntimeException
(
"Load config from local config cache failed and there is no fallback repository!"
);
}
try
{
m_fileProperties
=
m_fallback
.
getConfig
();
persistLocalCacheFile
(
m_baseDir
,
m_namespace
);
}
catch
(
Throwable
ex
)
{
String
message
=
String
.
format
(
"Load config from fallback repository %s failed"
,
m_fallback
.
getClass
());
logger
.
error
(
message
,
ex
);
throw
new
RuntimeException
(
message
,
ex
);
}
}
...
...
apollo-client/src/main/java/com/ctrip/apollo/internals/RemoteConfigRepository.java
浏览文件 @
5bb2aaf1
...
...
@@ -5,6 +5,7 @@ import com.google.common.collect.Lists;
import
com.ctrip.apollo.core.dto.ApolloConfig
;
import
com.ctrip.apollo.core.dto.ServiceDTO
;
import
com.ctrip.apollo.core.utils.ApolloThreadFactory
;
import
com.ctrip.apollo.util.ConfigUtil
;
import
com.ctrip.apollo.util.http.HttpRequest
;
import
com.ctrip.apollo.util.http.HttpResponse
;
...
...
@@ -18,19 +19,22 @@ import org.unidal.lookup.ContainerLoader;
import
java.util.List
;
import
java.util.Properties
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.ScheduledExecutorService
;
import
java.util.concurrent.atomic.AtomicReference
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
RemoteConfigRepository
implements
ConfigRepository
{
public
class
RemoteConfigRepository
extends
AbstractConfigRepository
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
RemoteConfigRepository
.
class
);
private
PlexusContainer
m_container
;
private
ConfigServiceLocator
m_serviceLocator
;
private
HttpUtil
m_httpUtil
;
private
ConfigUtil
m_configUtil
;
private
AtomicReference
<
ApolloConfig
>
m_configCache
;
private
String
m_namespace
;
private
final
ConfigServiceLocator
m_serviceLocator
;
private
final
HttpUtil
m_httpUtil
;
private
final
ConfigUtil
m_configUtil
;
private
volatile
AtomicReference
<
ApolloConfig
>
m_configCache
;
private
final
String
m_namespace
;
private
final
ScheduledExecutorService
m_executorService
;
public
RemoteConfigRepository
(
String
namespace
)
{
m_namespace
=
namespace
;
...
...
@@ -43,12 +47,15 @@ public class RemoteConfigRepository implements ConfigRepository {
}
catch
(
ComponentLookupException
e
)
{
throw
new
IllegalStateException
(
"Unable to load component!"
,
e
);
}
this
.
m_executorService
=
Executors
.
newScheduledThreadPool
(
1
,
ApolloThreadFactory
.
create
(
"RemoteConfigRepository"
,
true
));
this
.
schedulePeriodicRefresh
();
}
@Override
public
Properties
load
Config
()
{
public
Properties
get
Config
()
{
if
(
m_configCache
.
get
()
==
null
)
{
init
RemoteConfig
();
this
.
load
RemoteConfig
();
}
return
transformApolloConfigToProperties
(
m_configCache
.
get
());
}
...
...
@@ -58,8 +65,37 @@ public class RemoteConfigRepository implements ConfigRepository {
//remote config doesn't need fallback
}
private
void
initRemoteConfig
()
{
m_configCache
.
set
(
this
.
loadApolloConfig
());
private
void
schedulePeriodicRefresh
()
{
logger
.
info
(
"Schedule periodic refresh with interval: {} {}"
,
m_configUtil
.
getRefreshInterval
(),
m_configUtil
.
getRefreshTimeUnit
());
this
.
m_executorService
.
scheduleAtFixedRate
(
new
Runnable
()
{
@Override
public
void
run
()
{
try
{
loadRemoteConfig
();
}
catch
(
Throwable
ex
)
{
logger
.
error
(
"Refreshing config failed"
,
ex
);
}
}
},
m_configUtil
.
getRefreshInterval
(),
m_configUtil
.
getRefreshInterval
(),
m_configUtil
.
getRefreshTimeUnit
());
}
synchronized
void
loadRemoteConfig
()
{
ApolloConfig
previous
=
m_configCache
.
get
();
ApolloConfig
current
=
loadApolloConfig
();
//HTTP 304, nothing changed
if
(
previous
==
current
)
{
return
;
}
logger
.
info
(
"Remote Config changes!"
);
m_configCache
.
set
(
current
);
this
.
fireRepositoryChange
(
m_namespace
,
this
.
getConfig
());
}
private
Properties
transformApolloConfigToProperties
(
ApolloConfig
apolloConfig
)
{
...
...
@@ -72,16 +108,15 @@ public class RemoteConfigRepository implements ConfigRepository {
private
ApolloConfig
loadApolloConfig
()
{
String
appId
=
m_configUtil
.
getAppId
();
String
cluster
=
m_configUtil
.
getCluster
();
String
ur
i
=
getConfigServiceUrl
(
);
String
ur
l
=
assembleUrl
(
getConfigServiceUrl
(),
appId
,
cluster
,
m_namespace
,
m_configCache
.
get
()
);
logger
.
info
(
"Loading config from {}, appId={}, cluster={}, namespace={}"
,
uri
,
appId
,
cluster
,
m_namespace
);
HttpRequest
request
=
new
HttpRequest
(
assembleUrl
(
uri
,
appId
,
cluster
,
m_namespace
,
m_configCache
.
get
()));
logger
.
info
(
"Loading config from {}"
,
url
);
HttpRequest
request
=
new
HttpRequest
(
url
);
try
{
HttpResponse
<
ApolloConfig
>
response
=
m_httpUtil
.
doGet
(
request
,
ApolloConfig
.
class
);
if
(
response
.
getStatusCode
()
==
304
)
{
logger
.
info
(
"Config server responds with 304 HTTP status code."
);
return
m_configCache
.
get
();
}
...
...
apollo-client/src/main/java/com/ctrip/apollo/internals/RepositoryChangeListener.java
0 → 100644
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo.internals
;
import
java.util.Properties
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
interface
RepositoryChangeListener
{
public
void
onRepositoryChange
(
String
namespace
,
Properties
newProperties
);
}
apollo-client/src/main/java/com/ctrip/apollo/internals/SimpleConfig.java
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo.internals
;
import
com.ctrip.apollo.Config
;
import
com.google.common.base.Function
;
import
com.google.common.collect.Maps
;
import
com.ctrip.apollo.model.ConfigChange
;
import
com.ctrip.apollo.model.ConfigChangeEvent
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Properties
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
SimpleConfig
implements
Config
{
public
class
SimpleConfig
extends
AbstractConfig
implements
RepositoryChangeListener
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
SimpleConfig
.
class
);
private
String
m_namespace
;
private
ConfigRepository
m_configRepository
;
private
Properties
m_configProperties
;
private
final
String
m_namespace
;
private
final
ConfigRepository
m_configRepository
;
private
volatile
Properties
m_configProperties
;
public
SimpleConfig
(
String
namespace
,
ConfigRepository
configRepository
)
{
m_namespace
=
namespace
;
...
...
@@ -24,9 +30,10 @@ public class SimpleConfig implements Config {
private
void
initialize
()
{
try
{
m_configProperties
=
m_configRepository
.
loadConfig
();
m_configProperties
=
m_configRepository
.
getConfig
();
m_configRepository
.
addChangeListener
(
this
);
}
catch
(
Throwable
ex
)
{
String
message
=
String
.
format
(
"Init Apollo
Remot
e Config failed - namespace: %s"
,
String
message
=
String
.
format
(
"Init Apollo
Simpl
e Config failed - namespace: %s"
,
m_namespace
);
logger
.
error
(
message
,
ex
);
throw
new
RuntimeException
(
message
,
ex
);
...
...
@@ -38,4 +45,25 @@ public class SimpleConfig implements Config {
return
this
.
m_configProperties
.
getProperty
(
key
,
defaultValue
);
}
@Override
public
synchronized
void
onRepositoryChange
(
String
namespace
,
Properties
newProperties
)
{
if
(
newProperties
.
equals
(
m_configProperties
))
{
return
;
}
Properties
newConfigProperties
=
new
Properties
();
newConfigProperties
.
putAll
(
newProperties
);
List
<
ConfigChange
>
changes
=
calcPropertyChanges
(
m_configProperties
,
newConfigProperties
);
Map
<
String
,
ConfigChange
>
changeMap
=
Maps
.
uniqueIndex
(
changes
,
new
Function
<
ConfigChange
,
String
>()
{
@Override
public
String
apply
(
ConfigChange
input
)
{
return
input
.
getPropertyName
();
}
});
m_configProperties
=
newConfigProperties
;
this
.
fireConfigChange
(
new
ConfigChangeEvent
(
m_namespace
,
changeMap
));
}
}
apollo-client/src/main/java/com/ctrip/apollo/model/
Property
Change.java
→
apollo-client/src/main/java/com/ctrip/apollo/model/
Config
Change.java
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo.model
;
import
com.google.common.base.MoreObjects
;
import
com.ctrip.apollo.enums.PropertyChangeType
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
Property
Change
{
private
String
propertyName
;
private
Object
oldValue
;
private
Object
newValue
;
public
class
Config
Change
{
private
final
String
propertyName
;
private
String
oldValue
;
private
String
newValue
;
private
PropertyChangeType
changeType
;
public
PropertyChange
(
String
propertyName
,
Object
oldValue
,
Object
newValue
,
PropertyChangeType
changeType
)
{
public
ConfigChange
(
String
propertyName
,
String
oldValue
,
String
newValue
,
PropertyChangeType
changeType
)
{
this
.
propertyName
=
propertyName
;
this
.
oldValue
=
oldValue
;
this
.
newValue
=
newValue
;
...
...
@@ -24,31 +26,38 @@ public class PropertyChange {
return
propertyName
;
}
public
void
setPropertyName
(
String
propertyName
)
{
this
.
propertyName
=
propertyName
;
}
public
Object
getOldValue
()
{
public
String
getOldValue
()
{
return
oldValue
;
}
public
void
setOldValue
(
Object
oldValue
)
{
this
.
oldValue
=
old
Value
;
public
String
getNewValue
(
)
{
return
new
Value
;
}
public
Object
getNewValu
e
()
{
return
newValu
e
;
public
PropertyChangeType
getChangeTyp
e
()
{
return
changeTyp
e
;
}
public
void
set
NewValue
(
Object
new
Value
)
{
this
.
newValue
=
new
Value
;
public
void
set
OldValue
(
String
old
Value
)
{
this
.
oldValue
=
old
Value
;
}
public
PropertyChangeType
getChangeType
(
)
{
return
changeTyp
e
;
public
void
setNewValue
(
String
newValue
)
{
this
.
newValue
=
newValu
e
;
}
public
void
setChangeType
(
PropertyChangeType
changeType
)
{
this
.
changeType
=
changeType
;
}
@Override
public
String
toString
()
{
return
MoreObjects
.
toStringHelper
(
this
)
.
omitNullValues
()
.
add
(
"propertyName"
,
propertyName
)
.
add
(
"oldValue"
,
oldValue
)
.
add
(
"newValue"
,
newValue
)
.
add
(
"changeType"
,
changeType
)
.
toString
();
}
}
apollo-client/src/main/java/com/ctrip/apollo/model/ConfigChangeEvent.java
0 → 100644
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo.model
;
import
java.util.Map
;
import
java.util.Set
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ConfigChangeEvent
{
private
final
String
m_namespace
;
private
final
Map
<
String
,
ConfigChange
>
changes
;
public
ConfigChangeEvent
(
String
m_namespace
,
Map
<
String
,
ConfigChange
>
changes
)
{
this
.
m_namespace
=
m_namespace
;
this
.
changes
=
changes
;
}
public
Set
<
String
>
changedKeys
()
{
return
changes
.
keySet
();
}
public
ConfigChange
getChange
(
String
key
)
{
return
changes
.
get
(
key
);
}
/**
* Please note that the returned Map is immutable
* @return changes
*/
public
Map
<
String
,
ConfigChange
>
getChanges
()
{
return
changes
;
}
public
String
getNamespace
()
{
return
m_namespace
;
}
}
apollo-client/src/main/java/com/ctrip/apollo/model/ConfigRefreshResult.java
已删除
100644 → 0
浏览文件 @
b1c4b7d8
package
com.ctrip.apollo.model
;
import
com.google.common.collect.Lists
;
import
java.util.List
;
import
java.util.Properties
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ConfigRefreshResult
{
private
String
m_namespace
;
private
Properties
m_properties
;
private
List
<
PropertyChange
>
m_changes
;
public
ConfigRefreshResult
(
String
namespace
,
Properties
properties
)
{
this
.
m_namespace
=
namespace
;
this
.
m_properties
=
properties
;
m_changes
=
Lists
.
newArrayList
();
}
public
Properties
getProperties
()
{
return
m_properties
;
}
public
String
getNamespace
()
{
return
m_namespace
;
}
public
List
<
PropertyChange
>
getChanges
()
{
return
m_changes
;
}
public
void
setChanges
(
List
<
PropertyChange
>
changes
)
{
this
.
m_changes
=
changes
;
}
public
boolean
hasChanges
()
{
return
!
m_changes
.
isEmpty
();
}
}
apollo-client/src/main/java/com/ctrip/apollo/spi/DefaultConfigFactory.java
浏览文件 @
5bb2aaf1
...
...
@@ -33,8 +33,7 @@ public class DefaultConfigFactory implements ConfigFactory {
}
LocalFileConfigRepository
createLocalConfigRepository
(
String
namespace
)
{
LocalFileConfigRepository
localFileConfigLoader
=
LocalFileConfigRepository
localFileConfigLoader
=
new
LocalFileConfigRepository
(
m_baseDir
,
namespace
);
localFileConfigLoader
.
setFallback
(
createRemoteConfigRepository
(
namespace
));
return
localFileConfigLoader
;
...
...
apollo-client/src/main/java/com/ctrip/apollo/util/http/HttpUtil.java
浏览文件 @
5bb2aaf1
...
...
@@ -39,18 +39,19 @@ public class HttpUtil {
conn
.
setRequestMethod
(
"GET"
);
if
(
httpRequest
.
getConnectTimeout
()
<
0
)
{
conn
.
setConnectTimeout
(
m_configUtil
.
getConnectTimeout
());
}
else
{
conn
.
setConnectTimeout
(
httpRequest
.
getConnectTimeout
());
int
connectTimeout
=
httpRequest
.
getConnectTimeout
();
if
(
connectTimeout
<
0
)
{
connectTimeout
=
m_configUtil
.
getConnectTimeout
();
}
if
(
httpRequest
.
getReadTimeout
()
<
0
)
{
conn
.
setReadTimeout
(
m_configUtil
.
getReadTimeout
());
}
else
{
conn
.
setReadTimeout
(
httpRequest
.
getReadTimeout
());
int
readTimeout
=
httpRequest
.
getReadTimeout
();
if
(
readTimeout
<
0
)
{
readTimeout
=
m_configUtil
.
getReadTimeout
();
}
conn
.
setConnectTimeout
(
connectTimeout
);
conn
.
setReadTimeout
(
readTimeout
);
conn
.
connect
();
int
statusCode
=
conn
.
getResponseCode
();
...
...
@@ -66,7 +67,7 @@ public class HttpUtil {
}
throw
new
RuntimeException
(
String
.
format
(
"Get operation failed
, status code - %d"
,
statusCode
));
String
.
format
(
"Get operation failed
for %s, status code - %d"
,
httpRequest
.
getUrl
()
,
statusCode
));
}
catch
(
Throwable
ex
)
{
throw
new
RuntimeException
(
"Could not complete get operation"
,
ex
);
...
...
apollo-client/src/test/java/com/ctrip/apollo/ConfigServiceTest.java
浏览文件 @
5bb2aaf1
...
...
@@ -71,6 +71,11 @@ public class ConfigServiceTest extends ComponentTestCase {
return
m_namespace
+
":"
+
key
;
}
@Override
public
void
addChangeListener
(
ConfigChangeListener
listener
)
{
}
}
public
static
class
MockConfigFactory
implements
ConfigFactory
{
...
...
apollo-client/src/test/java/com/ctrip/apollo/internals/DefaultConfigManagerTest.java
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo.internals
;
import
com.ctrip.apollo.Config
;
import
com.ctrip.apollo.ConfigChangeListener
;
import
com.ctrip.apollo.spi.ConfigFactory
;
import
com.ctrip.apollo.spi.ConfigFactoryManager
;
...
...
@@ -60,6 +61,12 @@ public class DefaultConfigManagerTest extends ComponentTestCase {
public
String
getProperty
(
String
key
,
String
defaultValue
)
{
return
namespace
+
":"
+
key
;
}
@Override
public
void
addChangeListener
(
ConfigChangeListener
listener
)
{
}
};
}
};
...
...
apollo-client/src/test/java/com/ctrip/apollo/internals/DefaultConfigTest.java
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo.internals
;
import
com.google.common.base.Charsets
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.io.Files
;
import
com.ctrip.apollo.ConfigChangeListener
;
import
com.ctrip.apollo.core.utils.ClassLoaderUtil
;
import
com.ctrip.apollo.enums.PropertyChangeType
;
import
com.ctrip.apollo.model.ConfigChange
;
import
com.ctrip.apollo.model.ConfigChangeEvent
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.mockito.ArgumentCaptor
;
import
java.io.File
;
import
java.util.Properties
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
/**
...
...
@@ -69,7 +77,7 @@ public class DefaultConfigTest {
someProperties
=
new
Properties
();
someProperties
.
setProperty
(
someKey
,
someLocalFileValue
);
someProperties
.
setProperty
(
anotherKey
,
someLocalFileValue
);
when
(
configRepository
.
load
Config
()).
thenReturn
(
someProperties
);
when
(
configRepository
.
get
Config
()).
thenReturn
(
someProperties
);
//set up resource file
File
resourceFile
=
new
File
(
someResourceDir
,
someNamespace
+
".properties"
);
...
...
@@ -79,9 +87,8 @@ public class DefaultConfigTest {
Files
.
append
(
System
.
getProperty
(
"line.separator"
),
resourceFile
,
Charsets
.
UTF_8
);
Files
.
append
(
lastKey
+
"="
+
someResourceValue
,
resourceFile
,
Charsets
.
UTF_8
);
DefaultConfig
defaultConfig
=
new
DefaultConfig
(
someNamespace
,
configRepository
);
DefaultConfig
defaultConfig
=
new
DefaultConfig
(
someNamespace
,
configRepository
);
String
someKeyValue
=
defaultConfig
.
getProperty
(
someKey
,
null
);
String
anotherKeyValue
=
defaultConfig
.
getProperty
(
anotherKey
,
null
);
...
...
@@ -95,4 +102,80 @@ public class DefaultConfigTest {
assertEquals
(
someResourceValue
,
lastKeyValue
);
}
@Test
public
void
testOnRepositoryChange
()
throws
Exception
{
String
someKey
=
"someKey"
;
String
someSystemPropertyValue
=
"system-property-value"
;
String
anotherKey
=
"anotherKey"
;
String
someLocalFileValue
=
"local-file-value"
;
String
keyToBeDeleted
=
"keyToBeDeleted"
;
String
keyToBeDeletedValue
=
"keyToBeDeletedValue"
;
String
yetAnotherKey
=
"yetAnotherKey"
;
String
yetAnotherValue
=
"yetAnotherValue"
;
String
yetAnotherResourceValue
=
"yetAnotherResourceValue"
;
//set up system property
System
.
setProperty
(
someKey
,
someSystemPropertyValue
);
//set up config repo
someProperties
=
new
Properties
();
someProperties
.
putAll
(
ImmutableMap
.
of
(
someKey
,
someLocalFileValue
,
anotherKey
,
someLocalFileValue
,
keyToBeDeleted
,
keyToBeDeletedValue
,
yetAnotherKey
,
yetAnotherValue
));
when
(
configRepository
.
getConfig
()).
thenReturn
(
someProperties
);
//set up resource file
File
resourceFile
=
new
File
(
someResourceDir
,
someNamespace
+
".properties"
);
Files
.
append
(
yetAnotherKey
+
"="
+
yetAnotherResourceValue
,
resourceFile
,
Charsets
.
UTF_8
);
DefaultConfig
defaultConfig
=
new
DefaultConfig
(
someNamespace
,
configRepository
);
ConfigChangeListener
someListener
=
mock
(
ConfigChangeListener
.
class
);
defaultConfig
.
addChangeListener
(
someListener
);
Properties
newProperties
=
new
Properties
();
String
someKeyNewValue
=
"new-some-value"
;
String
anotherKeyNewValue
=
"another-new-value"
;
String
newKey
=
"newKey"
;
String
newValue
=
"newValue"
;
newProperties
.
putAll
(
ImmutableMap
.
of
(
someKey
,
someKeyNewValue
,
anotherKey
,
anotherKeyNewValue
,
newKey
,
newValue
));
final
ArgumentCaptor
<
ConfigChangeEvent
>
captor
=
ArgumentCaptor
.
forClass
(
ConfigChangeEvent
.
class
);
defaultConfig
.
onRepositoryChange
(
someNamespace
,
newProperties
);
verify
(
someListener
,
times
(
1
)).
onChange
(
captor
.
capture
());
ConfigChangeEvent
changeEvent
=
captor
.
getValue
();
assertEquals
(
someNamespace
,
changeEvent
.
getNamespace
());
assertEquals
(
4
,
changeEvent
.
getChanges
().
size
());
ConfigChange
anotherKeyChange
=
changeEvent
.
getChange
(
anotherKey
);
assertEquals
(
someLocalFileValue
,
anotherKeyChange
.
getOldValue
());
assertEquals
(
anotherKeyNewValue
,
anotherKeyChange
.
getNewValue
());
assertEquals
(
PropertyChangeType
.
MODIFIED
,
anotherKeyChange
.
getChangeType
());
ConfigChange
yetAnotherKeyChange
=
changeEvent
.
getChange
(
yetAnotherKey
);
assertEquals
(
yetAnotherValue
,
yetAnotherKeyChange
.
getOldValue
());
assertEquals
(
yetAnotherResourceValue
,
yetAnotherKeyChange
.
getNewValue
());
assertEquals
(
PropertyChangeType
.
MODIFIED
,
yetAnotherKeyChange
.
getChangeType
());
ConfigChange
keyToBeDeletedChange
=
changeEvent
.
getChange
(
keyToBeDeleted
);
assertEquals
(
keyToBeDeletedValue
,
keyToBeDeletedChange
.
getOldValue
());
assertEquals
(
null
,
keyToBeDeletedChange
.
getNewValue
());
assertEquals
(
PropertyChangeType
.
DELETED
,
keyToBeDeletedChange
.
getChangeType
());
ConfigChange
newKeyChange
=
changeEvent
.
getChange
(
newKey
);
assertEquals
(
null
,
newKeyChange
.
getOldValue
());
assertEquals
(
newValue
,
newKeyChange
.
getNewValue
());
assertEquals
(
PropertyChangeType
.
NEW
,
newKeyChange
.
getChangeType
());
}
}
apollo-client/src/test/java/com/ctrip/apollo/internals/LocalFileConfigRepositoryTest.java
浏览文件 @
5bb2aaf1
...
...
@@ -8,6 +8,7 @@ import com.ctrip.apollo.util.ConfigUtil;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.mockito.ArgumentCaptor
;
import
org.unidal.lookup.ComponentTestCase
;
import
java.io.File
;
...
...
@@ -16,7 +17,11 @@ import java.util.Properties;
import
static
org
.
hamcrest
.
core
.
IsEqual
.
equalTo
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
only
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
/**
...
...
@@ -40,7 +45,7 @@ public class LocalFileConfigRepositoryTest extends ComponentTestCase {
someProperties
=
new
Properties
();
someProperties
.
setProperty
(
"defaultKey"
,
"defaultValue"
);
fallbackRepo
=
mock
(
ConfigRepository
.
class
);
when
(
fallbackRepo
.
load
Config
()).
thenReturn
(
someProperties
);
when
(
fallbackRepo
.
get
Config
()).
thenReturn
(
someProperties
);
defineComponent
(
ConfigUtil
.
class
,
MockConfigUtil
.
class
);
}
...
...
@@ -83,7 +88,7 @@ public class LocalFileConfigRepositoryTest extends ComponentTestCase {
Files
.
write
(
someKey
+
"="
+
someValue
,
file
,
Charsets
.
UTF_8
);
LocalFileConfigRepository
localRepo
=
new
LocalFileConfigRepository
(
someBaseDir
,
someNamespace
);
Properties
properties
=
localRepo
.
load
Config
();
Properties
properties
=
localRepo
.
get
Config
();
assertEquals
(
someValue
,
properties
.
getProperty
(
someKey
));
...
...
@@ -97,7 +102,7 @@ public class LocalFileConfigRepositoryTest extends ComponentTestCase {
localFileConfigRepository
.
setFallback
(
fallbackRepo
);
Properties
result
=
localFileConfigRepository
.
load
Config
();
Properties
result
=
localFileConfigRepository
.
get
Config
();
assertThat
(
"LocalFileConfigRepository's properties should be the same as fallback repo's when there is no local cache"
,
...
...
@@ -111,13 +116,13 @@ public class LocalFileConfigRepositoryTest extends ComponentTestCase {
localRepo
.
setFallback
(
fallbackRepo
);
Properties
someProperties
=
localRepo
.
load
Config
();
Properties
someProperties
=
localRepo
.
get
Config
();
LocalFileConfigRepository
anotherLocalRepoWithNoFallback
=
new
LocalFileConfigRepository
(
someBaseDir
,
someNamespace
);
Properties
anotherProperties
=
anotherLocalRepoWithNoFallback
.
load
Config
();
Properties
anotherProperties
=
anotherLocalRepoWithNoFallback
.
get
Config
();
assertThat
(
"LocalFileConfigRepository should persist local cache files and return that afterwards"
,
...
...
@@ -125,6 +130,30 @@ public class LocalFileConfigRepositoryTest extends ComponentTestCase {
}
@Test
public
void
testOnRepositoryChange
()
throws
Exception
{
RepositoryChangeListener
someListener
=
mock
(
RepositoryChangeListener
.
class
);
LocalFileConfigRepository
localFileConfigRepository
=
new
LocalFileConfigRepository
(
someBaseDir
,
someNamespace
);
localFileConfigRepository
.
setFallback
(
fallbackRepo
);
localFileConfigRepository
.
addChangeListener
(
someListener
);
localFileConfigRepository
.
getConfig
();
Properties
anotherProperties
=
new
Properties
();
anotherProperties
.
put
(
"anotherKey"
,
"anotherValue"
);
localFileConfigRepository
.
onRepositoryChange
(
someNamespace
,
anotherProperties
);
final
ArgumentCaptor
<
Properties
>
captor
=
ArgumentCaptor
.
forClass
(
Properties
.
class
);
verify
(
someListener
,
times
(
1
)).
onRepositoryChange
(
eq
(
someNamespace
),
captor
.
capture
());
assertEquals
(
anotherProperties
,
captor
.
getValue
());
}
public
static
class
MockConfigUtil
extends
ConfigUtil
{
@Override
public
String
getAppId
()
{
...
...
apollo-client/src/test/java/com/ctrip/apollo/internals/RemoteConfigRepositoryTest.java
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo.internals
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
...
...
@@ -13,6 +14,7 @@ import com.ctrip.apollo.util.http.HttpUtil;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.ArgumentCaptor
;
import
org.mockito.Mock
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.unidal.lookup.ComponentTestCase
;
...
...
@@ -22,7 +24,10 @@ import java.util.Map;
import
java.util.Properties
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
/**
...
...
@@ -60,7 +65,7 @@ public class RemoteConfigRepositoryTest extends ComponentTestCase {
when
(
someResponse
.
getBody
()).
thenReturn
(
someApolloConfig
);
RemoteConfigRepository
remoteConfigRepository
=
new
RemoteConfigRepository
(
someNamespace
);
Properties
config
=
remoteConfigRepository
.
load
Config
();
Properties
config
=
remoteConfigRepository
.
get
Config
();
assertEquals
(
configurations
,
config
);
}
...
...
@@ -71,7 +76,27 @@ public class RemoteConfigRepositoryTest extends ComponentTestCase {
when
(
someResponse
.
getStatusCode
()).
thenReturn
(
500
);
RemoteConfigRepository
remoteConfigRepository
=
new
RemoteConfigRepository
(
someNamespace
);
remoteConfigRepository
.
loadConfig
();
remoteConfigRepository
.
getConfig
();
}
@Test
public
void
testRepositoryChangeListener
()
throws
Exception
{
Map
<
String
,
String
>
configurations
=
ImmutableMap
.
of
(
"someKey"
,
"someValue"
);
ApolloConfig
someApolloConfig
=
assembleApolloConfig
(
configurations
);
when
(
someResponse
.
getStatusCode
()).
thenReturn
(
200
);
when
(
someResponse
.
getBody
()).
thenReturn
(
someApolloConfig
);
RepositoryChangeListener
someListener
=
mock
(
RepositoryChangeListener
.
class
);
RemoteConfigRepository
remoteConfigRepository
=
new
RemoteConfigRepository
(
someNamespace
);
remoteConfigRepository
.
addChangeListener
(
someListener
);
final
ArgumentCaptor
<
Properties
>
captor
=
ArgumentCaptor
.
forClass
(
Properties
.
class
);
remoteConfigRepository
.
loadRemoteConfig
();
verify
(
someListener
,
times
(
1
)).
onRepositoryChange
(
eq
(
someNamespace
),
captor
.
capture
());
assertEquals
(
configurations
,
captor
.
getValue
());
}
private
ApolloConfig
assembleApolloConfig
(
Map
<
String
,
String
>
configurations
)
{
...
...
apollo-client/src/test/java/com/ctrip/apollo/internals/SimpleConfigTest.java
浏览文件 @
5bb2aaf1
package
com.ctrip.apollo.internals
;
import
com.google.common.collect.ImmutableMap
;
import
com.ctrip.apollo.ConfigChangeListener
;
import
com.ctrip.apollo.enums.PropertyChangeType
;
import
com.ctrip.apollo.model.ConfigChange
;
import
com.ctrip.apollo.model.ConfigChangeEvent
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.ArgumentCaptor
;
import
org.mockito.Mock
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
java.util.Properties
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
/**
...
...
@@ -32,7 +43,7 @@ public class SimpleConfigTest {
String
someValue
=
"someValue"
;
someProperties
.
setProperty
(
someKey
,
someValue
);
when
(
configRepository
.
load
Config
()).
thenReturn
(
someProperties
);
when
(
configRepository
.
get
Config
()).
thenReturn
(
someProperties
);
SimpleConfig
config
=
new
SimpleConfig
(
someNamespace
,
configRepository
);
...
...
@@ -41,8 +52,57 @@ public class SimpleConfigTest {
@Test
(
expected
=
RuntimeException
.
class
)
public
void
testLoadConfigFromConfigRepositoryError
()
throws
Exception
{
when
(
configRepository
.
load
Config
()).
thenThrow
(
Throwable
.
class
);
when
(
configRepository
.
get
Config
()).
thenThrow
(
Throwable
.
class
);
new
SimpleConfig
(
someNamespace
,
configRepository
);
}
@Test
public
void
testOnRepositoryChange
()
throws
Exception
{
Properties
someProperties
=
new
Properties
();
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
String
anotherKey
=
"anotherKey"
;
String
anotherValue
=
"anotherValue"
;
someProperties
.
putAll
(
ImmutableMap
.
of
(
someKey
,
someValue
,
anotherKey
,
anotherValue
));
Properties
anotherProperties
=
new
Properties
();
String
newKey
=
"newKey"
;
String
newValue
=
"newValue"
;
String
someValueNew
=
"someValueNew"
;
anotherProperties
.
putAll
(
ImmutableMap
.
of
(
someKey
,
someValueNew
,
newKey
,
newValue
));
when
(
configRepository
.
getConfig
()).
thenReturn
(
someProperties
);
ConfigChangeListener
someListener
=
mock
(
ConfigChangeListener
.
class
);
SimpleConfig
config
=
new
SimpleConfig
(
someNamespace
,
configRepository
);
config
.
addChangeListener
(
someListener
);
config
.
onRepositoryChange
(
someNamespace
,
anotherProperties
);
ArgumentCaptor
<
ConfigChangeEvent
>
captor
=
ArgumentCaptor
.
forClass
(
ConfigChangeEvent
.
class
);
verify
(
someListener
,
times
(
1
)).
onChange
(
captor
.
capture
());
ConfigChangeEvent
changeEvent
=
captor
.
getValue
();
assertEquals
(
someNamespace
,
changeEvent
.
getNamespace
());
assertEquals
(
3
,
changeEvent
.
getChanges
().
size
());
ConfigChange
someKeyChange
=
changeEvent
.
getChange
(
someKey
);
assertEquals
(
someValue
,
someKeyChange
.
getOldValue
());
assertEquals
(
someValueNew
,
someKeyChange
.
getNewValue
());
assertEquals
(
PropertyChangeType
.
MODIFIED
,
someKeyChange
.
getChangeType
());
ConfigChange
anotherKeyChange
=
changeEvent
.
getChange
(
anotherKey
);
assertEquals
(
anotherValue
,
anotherKeyChange
.
getOldValue
());
assertEquals
(
null
,
anotherKeyChange
.
getNewValue
());
assertEquals
(
PropertyChangeType
.
DELETED
,
anotherKeyChange
.
getChangeType
());
ConfigChange
newKeyChange
=
changeEvent
.
getChange
(
newKey
);
assertEquals
(
null
,
newKeyChange
.
getOldValue
());
assertEquals
(
newValue
,
newKeyChange
.
getNewValue
());
assertEquals
(
PropertyChangeType
.
NEW
,
newKeyChange
.
getChangeType
());
}
}
apollo-client/src/test/java/com/ctrip/apollo/spi/DefaultConfigFactoryTest.java
浏览文件 @
5bb2aaf1
...
...
@@ -40,7 +40,7 @@ public class DefaultConfigFactoryTest extends ComponentTestCase {
someProperties
.
setProperty
(
someKey
,
someValue
);
LocalFileConfigRepository
someLocalConfigRepo
=
mock
(
LocalFileConfigRepository
.
class
);
when
(
someLocalConfigRepo
.
load
Config
()).
thenReturn
(
someProperties
);
when
(
someLocalConfigRepo
.
get
Config
()).
thenReturn
(
someProperties
);
doReturn
(
someLocalConfigRepo
).
when
(
defaultConfigFactory
).
createLocalConfigRepository
(
someNamespace
);
...
...
apollo-demo/src/main/java/ApolloConfigDemo.java
浏览文件 @
5bb2aaf1
import
com.ctrip.apollo.Config
;
import
com.ctrip.apollo.ConfigChangeListener
;
import
com.ctrip.apollo.ConfigService
;
import
com.ctrip.apollo.model.ConfigChange
;
import
com.ctrip.apollo.model.ConfigChangeEvent
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
...
...
@@ -9,16 +15,18 @@ import java.io.InputStreamReader;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ApolloConfigDemo
{
public
class
ApolloConfigDemo
implements
ConfigChangeListener
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ApolloConfigDemo
.
class
);
private
Config
config
;
public
ApolloConfigDemo
()
{
config
=
ConfigService
.
getConfig
();
config
.
addChangeListener
(
this
);
}
private
String
getConfig
(
String
key
)
{
String
result
=
config
.
getProperty
(
key
,
"undefined"
);
System
.
out
.
println
(
String
.
format
(
"Loading key: %s with value: %s"
,
key
,
result
));
logger
.
info
(
String
.
format
(
"Loading key: %s with value: %s"
,
key
,
result
));
return
result
;
}
...
...
@@ -35,4 +43,14 @@ public class ApolloConfigDemo {
apolloConfigDemo
.
getConfig
(
input
);
}
}
@Override
public
void
onChange
(
ConfigChangeEvent
changeEvent
)
{
logger
.
info
(
"Changes for namespace {}"
,
changeEvent
.
getNamespace
());
for
(
ConfigChange
change
:
changeEvent
.
getChanges
().
values
())
{
logger
.
info
(
"Change - key: {}, oldValue: {}, newValue: {}, changeType: {}"
,
change
.
getPropertyName
(),
change
.
getOldValue
(),
change
.
getNewValue
(),
change
.
getChangeType
());
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录