From 91d20f34fdec6b77b0b27c874983ca57a2feb584 Mon Sep 17 00:00:00 2001
From: xingxuechao
Date: Sat, 21 Jul 2018 00:27:23 +0800
Subject: [PATCH] nacos is coming
---
.gitignore | 10 +
.travis.yml | 31 +
BUILDING | 38 +
CONTRIBUTING.md | 31 +
LICENSE | 201 ++
NOTICE | 32 +
README.md | 49 +
client/pom.xml | 107 +
.../com/alibaba/nacos/api/NacosFactory.java | 86 +
.../alibaba/nacos/api/PropertyKeyConst.java | 34 +
.../nacos/api/config/ConfigFactory.java | 60 +
.../nacos/api/config/ConfigService.java | 103 +
.../api/config/filter/IConfigContext.java | 42 +
.../api/config/filter/IConfigFilter.java | 69 +
.../api/config/filter/IConfigFilterChain.java | 39 +
.../api/config/filter/IConfigRequest.java | 41 +
.../api/config/filter/IConfigResponse.java | 41 +
.../api/config/filter/IFilterConfig.java | 39 +
.../api/config/listener/AbstractListener.java | 36 +
.../listener/AbstractSharedListener.java | 57 +
.../nacos/api/config/listener/Listener.java | 43 +
.../nacos/api/exception/NacosException.java | 110 +
.../nacos/api/naming/NamingFactory.java | 34 +
.../nacos/api/naming/NamingService.java | 176 +
.../nacos/api/naming/listener/Event.java | 23 +
.../api/naming/listener/EventListener.java | 29 +
.../api/naming/listener/NamingEvent.java | 51 +
.../naming/pojo/AbstractHealthChecker.java | 179 +
.../nacos/api/naming/pojo/Cluster.java | 124 +
.../nacos/api/naming/pojo/Instance.java | 166 +
.../nacos/api/naming/pojo/Service.java | 108 +
.../client/config/NacosConfigService.java | 267 ++
.../nacos/client/config/common/Constants.java | 127 +
.../nacos/client/config/common/GroupKey.java | 123 +
.../config/filter/impl/ConfigContext.java | 43 +
.../filter/impl/ConfigFilterChainManager.java | 87 +
.../config/filter/impl/ConfigRequest.java | 78 +
.../config/filter/impl/ConfigResponse.java | 78 +
.../nacos/client/config/impl/CacheData.java | 319 ++
.../client/config/impl/ClientWorker.java | 541 +++
.../client/config/impl/EventDispatcher.java | 133 +
.../client/config/impl/HttpSimpleClient.java | 276 ++
.../nacos/client/config/impl/Limiter.java | 79 +
.../config/impl/LocalConfigInfoProcessor.java | 197 ++
.../client/config/impl/ServerHttpAgent.java | 392 +++
.../client/config/impl/ServerListManager.java | 432 +++
.../nacos/client/config/impl/SpasAdapter.java | 111 +
.../client/config/impl/TimerService.java | 48 +
.../listener/impl/PropertiesListener.java | 61 +
.../config/utils/ConcurrentDiskUtil.java | 247 ++
.../client/config/utils/ContentUtils.java | 78 +
.../nacos/client/config/utils/IOUtils.java | 151 +
.../nacos/client/config/utils/JVMUtil.java | 49 +
.../nacos/client/config/utils/LogUtils.java | 59 +
.../nacos/client/config/utils/MD5.java | 145 +
.../nacos/client/config/utils/ParamUtils.java | 154 +
.../client/config/utils/SnapShotSwitch.java | 42 +
.../nacos/client/config/utils/TenantUtil.java | 44 +
.../alibaba/nacos/client/identify/Base64.java | 707 ++++
.../nacos/client/identify/Constants.java | 47 +
.../client/identify/CredentialListener.java | 29 +
.../client/identify/CredentialService.java | 135 +
.../client/identify/CredentialWatcher.java | 214 ++
.../nacos/client/identify/Credentials.java | 65 +
.../nacos/client/identify/STSConfig.java | 128 +
.../nacos/client/identify/SpasCredential.java | 38 +
.../client/identify/SpasCredentialLoader.java | 31 +
.../alibaba/nacos/client/logger/Level.java | 48 +
.../alibaba/nacos/client/logger/Logger.java | 238 ++
.../nacos/client/logger/LoggerFactory.java | 100 +
.../nacos/client/logger/json/JSONArray.java | 398 +++
.../nacos/client/logger/json/JSONAware.java | 30 +
.../nacos/client/logger/json/JSONObject.java | 152 +
.../client/logger/json/JSONStreamAware.java | 38 +
.../nacos/client/logger/json/JSONValue.java | 343 ++
.../logger/json/parser/ContainerFactory.java | 40 +
.../logger/json/parser/ContentHandler.java | 129 +
.../client/logger/json/parser/JSONParser.java | 574 +++
.../logger/json/parser/ParseException.java | 105 +
.../client/logger/json/parser/Yylex.java | 665 ++++
.../client/logger/json/parser/Yytoken.java | 81 +
.../client/logger/log4j/Log4jLogger.java | 146 +
.../logger/log4j/Log4jLoggerFactory.java | 53 +
.../client/logger/log4j2/Log4j2Logger.java | 144 +
.../logger/log4j2/Log4j2LoggerFactory.java | 55 +
.../nacos/client/logger/nop/NopLogger.java | 99 +
.../client/logger/nop/NopLoggerFactory.java | 36 +
.../logger/option/AbstractActiveOption.java | 73 +
.../client/logger/option/ActivateOption.java | 195 ++
.../logger/option/Log4j2ActivateOption.java | 274 ++
.../logger/option/Log4jActivateOption.java | 212 ++
.../option/Logback918ActivateOption.java | 334 ++
.../logger/option/LogbackActivateOption.java | 154 +
.../option/LogbackLoggerContextUtil.java | 47 +
.../Slf4jLog4j2AdapterActivateOption.java | 68 +
.../Slf4jLog4jAdapterActivateOption.java | 71 +
.../client/logger/slf4j/Slf4jLogger.java | 178 +
.../logger/slf4j/Slf4jLoggerFactory.java | 51 +
.../client/logger/support/AppenderInfo.java | 48 +
.../support/DepthThrowableRenderer.java | 90 +
.../nacos/client/logger/support/ErrorLog.java | 35 +
.../client/logger/support/ILoggerFactory.java | 44 +
.../client/logger/support/Log4jHelper.java | 201 ++
.../nacos/client/logger/support/LogLog.java | 143 +
.../client/logger/support/LogbackHelper.java | 226 ++
.../client/logger/support/LoggerHelper.java | 252 ++
.../client/logger/support/LoggerInfo.java | 54 +
.../client/logger/support/LoggerSupport.java | 198 ++
.../client/logger/util/FormattingTuple.java | 68 +
.../client/logger/util/MessageFormatter.java | 421 +++
.../nacos/client/logger/util/MessageUtil.java | 47 +
.../client/naming/NacosNamingService.java | 242 ++
.../naming/backups/FailoverReactor.java | 242 ++
.../nacos/client/naming/beat/BeatInfo.java | 66 +
.../nacos/client/naming/beat/BeatReactor.java | 108 +
.../naming/cache/ConcurrentDiskUtil.java | 238 ++
.../nacos/client/naming/cache/DiskCache.java | 151 +
.../nacos/client/naming/core/Balancer.java | 98 +
.../nacos/client/naming/core/Domain.java | 245 ++
.../client/naming/core/EventDispatcher.java | 136 +
.../nacos/client/naming/core/HostReactor.java | 432 +++
.../nacos/client/naming/core/ProtectMode.java | 36 +
.../nacos/client/naming/core/PushRecver.java | 119 +
.../nacos/client/naming/net/HttpClient.java | 199 ++
.../nacos/client/naming/net/NamingProxy.java | 348 ++
.../nacos/client/naming/utils/Chooser.java | 229 ++
.../client/naming/utils/CollectionUtils.java | 171 +
.../client/naming/utils/GenericPoller.java | 41 +
.../nacos/client/naming/utils/IoUtils.java | 188 +
.../nacos/client/naming/utils/JvmRandom.java | 246 ++
.../nacos/client/naming/utils/LogUtils.java | 54 +
.../nacos/client/naming/utils/NetUtils.java | 40 +
.../nacos/client/naming/utils/Pair.java | 38 +
.../nacos/client/naming/utils/Poller.java | 38 +
.../client/naming/utils/RandomUtils.java | 194 ++
.../client/naming/utils/StringUtils.java | 164 +
.../naming/utils/ThreadLocalRandom.java | 288 ++
.../client/naming/utils/UtilAndComs.java | 44 +
.../nacos/client/utils/AppNameUtils.java | 96 +
.../alibaba/nacos/client/utils/EnvUtil.java | 115 +
.../alibaba/nacos/client/utils/IPUtil.java | 55 +
.../alibaba/nacos/client/utils/JSONUtils.java | 60 +
.../alibaba/nacos/client/utils/ParamUtil.java | 162 +
.../nacos/client/utils/StringUtils.java | 69 +
.../src/main/resources/application.properties | 1 +
.../com/alibaba/nacos/client/AppTest.java | 53 +
common/license | 15 +
common/pom.xml | 38 +
.../alibaba/nacos/common/AppendLicense.java | 85 +
.../alibaba/nacos/common/util/IoUtils.java | 173 +
.../alibaba/nacos/common/util/Md5Utils.java | 58 +
.../com/alibaba/nacos/common/util/Pair.java | 51 +
.../alibaba/nacos/common/util/SystemUtil.java | 63 +
.../alibaba/nacos/common/util/UuidUtil.java | 13 +
.../com/alibaba/nacos/common/AppTest.java | 53 +
config/pom.xml | 155 +
config/src/main/java/LogbackInitTest.java | 68 +
.../alibaba/nacos/config/server/Config.java | 40 +
.../aspect/CapacityManagementAspect.java | 441 +++
.../server/aspect/RequestLogAspect.java | 104 +
.../config/server/constant/Constants.java | 216 ++
.../config/server/constant/CounterMode.java | 40 +
.../server/controller/CapacityController.java | 160 +
.../controller/CommunicationController.java | 112 +
.../server/controller/ConfigController.java | 368 ++
.../server/controller/ConfigServletInner.java | 343 ++
.../server/controller/HealthController.java | 79 +
.../server/controller/HistoryController.java | 61 +
.../server/controller/ListenerController.java | 96 +
.../server/controller/OpsController.java | 60 +
.../exception/GlobalExceptionHandler.java | 67 +
.../server/exception/NacosException.java | 94 +
.../nacos/config/server/filter/WebFilter.java | 84 +
.../config/server/manager/AbstractTask.java | 64 +
.../config/server/manager/TaskManager.java | 298 ++
.../server/manager/TaskManagerMBean.java | 34 +
.../config/server/manager/TaskProcessor.java | 35 +
.../nacos/config/server/model/ACLInfo.java | 47 +
.../nacos/config/server/model/AuthType.java | 29 +
.../nacos/config/server/model/CacheItem.java | 109 +
.../server/model/ConfigAdvanceInfo.java | 100 +
.../server/model/ConfigHistoryInfo.java | 163 +
.../nacos/config/server/model/ConfigInfo.java | 83 +
.../config/server/model/ConfigInfo4Beta.java | 58 +
.../config/server/model/ConfigInfo4Tag.java | 58 +
.../config/server/model/ConfigInfoAggr.java | 196 ++
.../config/server/model/ConfigInfoBase.java | 215 ++
.../config/server/model/ConfigInfoBaseEx.java | 84 +
.../server/model/ConfigInfoChanged.java | 119 +
.../config/server/model/ConfigInfoEx.java | 89 +
.../server/model/ConfigInfoWrapper.java | 47 +
.../nacos/config/server/model/ConfigKey.java | 70 +
.../nacos/config/server/model/GroupInfo.java | 135 +
.../server/model/GroupkeyListenserStatus.java | 54 +
.../config/server/model/HistoryContext.java | 121 +
.../nacos/config/server/model/Page.java | 88 +
.../config/server/model/RestPageResult.java | 83 +
.../nacos/config/server/model/RestResult.java | 83 +
.../config/server/model/SampleResult.java | 43 +
.../nacos/config/server/model/SubInfo.java | 63 +
.../config/server/model/SubscriberStatus.java | 79 +
.../server/model/app/ApplicationInfo.java | 112 +
.../model/app/ApplicationPublishRecord.java | 49 +
.../config/server/model/app/GroupKey.java | 69 +
.../config/server/model/app/MonitorInfo.java | 133 +
.../server/model/capacity/Capacity.java | 113 +
.../server/model/capacity/GroupCapacity.java | 33 +
.../server/model/capacity/TenantCapacity.java | 33 +
.../config/server/monitor/MemoryMonitor.java | 92 +
.../server/monitor/ResponseMonitor.java | 97 +
.../config/server/service/AggrWhitelist.java | 97 +
.../service/BasicDataSourceServiceImpl.java | 331 ++
.../server/service/ClientIpWhiteList.java | 88 +
.../server/service/ClientTrackService.java | 184 +
.../server/service/ConfigDataChangeEvent.java | 69 +
.../config/server/service/ConfigService.java | 587 ++++
.../server/service/ConfigSubService.java | 265 ++
.../server/service/DataSourceService.java | 72 +
.../nacos/config/server/service/DiskUtil.java | 260 ++
.../server/service/DynamicDataSource.java | 52 +
.../server/service/LocalDataChangeEvent.java | 53 +
.../service/LocalDataSourceServiceImpl.java | 205 ++
.../server/service/LongPullingService.java | 513 +++
.../config/server/service/PersistService.java | 3090 +++++++++++++++++
.../server/service/ServerListService.java | 477 +++
.../config/server/service/SwitchService.java | 126 +
.../server/service/TimerTaskService.java | 49 +
.../service/capacity/CapacityService.java | 499 +++
.../capacity/GroupCapacityPersistService.java | 327 ++
.../TenantCapacityPersistService.java | 277 ++
.../server/service/dump/DumpService.java | 403 +++
.../config/server/service/dump/DumpTask.java | 444 +++
.../server/service/merge/MergeDataTask.java | 68 +
.../service/merge/MergeDatumService.java | 155 +
.../service/merge/MergeTaskProcessor.java | 134 +
.../service/notify/AsyncNotifyService.java | 366 ++
.../server/service/notify/NotifyService.java | 111 +
.../service/notify/NotifySingleService.java | 161 +
.../server/service/notify/NotifyTask.java | 94 +
.../service/notify/NotifyTaskProcessor.java | 102 +
.../service/trace/ConfigTraceService.java | 109 +
.../server/utils/AccumulateStatCount.java | 41 +
.../config/server/utils/AppNameUtils.java | 97 +
.../config/server/utils/ContentUtils.java | 75 +
.../nacos/config/server/utils/GroupKey.java | 120 +
.../nacos/config/server/utils/GroupKey2.java | 109 +
.../nacos/config/server/utils/IPUtil.java | 55 +
.../nacos/config/server/utils/JSONUtils.java | 60 +
.../nacos/config/server/utils/LogUtil.java | 100 +
.../nacos/config/server/utils/MD5.java | 168 +
.../nacos/config/server/utils/MD5Util.java | 183 +
.../config/server/utils/PaginationHelper.java | 215 ++
.../nacos/config/server/utils/ParamUtils.java | 155 +
.../config/server/utils/PropertyUtil.java | 276 ++
.../nacos/config/server/utils/Protocol.java | 48 +
.../config/server/utils/RegexParser.java | 82 +
.../config/server/utils/RequestUtil.java | 38 +
.../config/server/utils/ResourceUtils.java | 214 ++
.../config/server/utils/ResponseUtil.java | 40 +
.../server/utils/RunningConfigUtils.java | 68 +
.../config/server/utils/SimpleCache.java | 58 +
.../config/server/utils/SimpleFlowData.java | 124 +
.../config/server/utils/SimpleIPFlowData.java | 113 +
.../server/utils/SimpleReadWriteLock.java | 63 +
.../server/utils/SingletonRepository.java | 61 +
.../config/server/utils/StatConstants.java | 37 +
.../config/server/utils/StringUtils.java | 69 +
.../config/server/utils/SystemConfig.java | 65 +
.../nacos/config/server/utils/ThreadUtil.java | 39 +
.../nacos/config/server/utils/TimeUtils.java | 45 +
.../config/server/utils/TimeoutUtils.java | 104 +
.../config/server/utils/TraceLogUtil.java | 38 +
.../config/server/utils/UrlAnalysisUtils.java | 75 +
.../server/utils/event/EventDispatcher.java | 148 +
.../src/main/resources/application.properties | 17 +
config/src/main/resources/banner.txt | 15 +
.../main/resources/diamond-app-collector.sql | 31 +
config/src/main/resources/diamond-db.sql | 133 +
.../main/resources/nacos-config-logback.xml | 283 ++
config/src/main/resources/schema.sql | 161 +
config/src/main/resources/version/version.txt | 1 +
.../nacos/config/mock/FilterConfigMock.java | 56 +
.../nacos/config/mock/ServletContextMock.java | 356 ++
.../controller/HealthControllerUnitTest.java | 67 +
.../server/service/AggrWhitelistTest.java | 57 +
.../service/ClientTrackServiceTest.java | 62 +
.../server/service/DiskServiceUnitTest.java | 66 +
.../config/server/utils/GroupKeyTest.java | 68 +
.../server/utils/SimpleReadWriteLockTest.java | 77 +
.../utils/event/EventDispatcherTest.java | 99 +
config/src/test/resources/application.xml-bk | 0
.../test/resources/application.xml-test4derby | 0
config/src/test/resources/jdbc.properties | 0
config/src/test/resources/log4j.properties | 20 +
config/src/test/resources/user.properties | 1 +
console/pom.xml | 71 +
.../main/java/com/alibaba/nacos/Nacos.java | 34 +
.../src/main/resources/application.properties | 47 +
console/src/main/resources/banner.txt | 15 +
.../main/resources/diamond-server-logback.xml | 261 ++
console/src/main/resources/schema.sql | 161 +
core/pom.xml | 35 +
.../main/java/com/alibaba/nacos/core/App.java | 28 +
.../java/com/alibaba/nacos/core/AppTest.java | 53 +
distribution/LICENSE-BIN | 334 ++
distribution/NOTICE-BIN | 36 +
distribution/bin/deploy.sh | 4 +
distribution/bin/deploy_naming.sh | 5 +
distribution/bin/run_naming.sh | 16 +
distribution/bin/shutdown.cmd | 12 +
distribution/bin/shutdown.sh | 13 +
distribution/bin/startup.cmd | 28 +
distribution/bin/startup.sh | 57 +
distribution/conf/application.properties | 12 +
.../conf/application.properties.example | 12 +
distribution/conf/cluster.conf.example | 5 +
distribution/conf/nacos-logback.xml | 505 +++
distribution/conf/schema.sql | 161 +
distribution/pom.xml | 185 +
distribution/release-client.xml | 71 +
distribution/release-config.xml | 71 +
distribution/release-core.xml | 70 +
distribution/release-nacos.xml | 50 +
distribution/release-naming.xml | 71 +
doc/Nacos_Logo.png | Bin 0 -> 35417 bytes
doc/arch.png | 0
example/pom.xml | 42 +
.../java/com/alibaba/nacos/example/App.java | 40 +
.../alibaba/nacos/example/ConfigExample.java | 71 +
.../alibaba/nacos/example/NamingExample.java | 58 +
.../com/alibaba/nacos/example/AppTest.java | 53 +
naming/default/failover/nacos.test.4 | 1 +
naming/pom.xml | 186 +
.../com/alibaba/nacos/naming/NamingApp.java | 35 +
.../alibaba/nacos/naming/acl/AuthChecker.java | 118 +
.../alibaba/nacos/naming/acl/AuthInfo.java | 80 +
.../nacos/naming/boot/RunningConfig.java | 66 +
.../naming/controllers/CatalogController.java | 22 +
.../naming/controllers/ClusterController.java | 22 +
.../naming/controllers/CmdbController.java | 22 +
.../naming/controllers/HealthController.java | 22 +
.../controllers/InstanceController.java | 172 +
.../controllers/OperatorController.java | 22 +
.../naming/controllers/ServiceController.java | 28 +
.../alibaba/nacos/naming/core/Cluster.java | 461 +++
.../nacos/naming/core/DistroMapper.java | 496 +++
.../com/alibaba/nacos/naming/core/Domain.java | 132 +
.../nacos/naming/core/DomainsManager.java | 718 ++++
.../alibaba/nacos/naming/core/IpAddress.java | 399 +++
.../naming/core/VirtualClusterDomain.java | 618 ++++
.../naming/exception/NacosException.java | 80 +
.../exception/ResponseExceptionHandler.java | 30 +
.../AbstractHealthCheckConfig.java | 327 ++
.../AbstractHealthCheckProcessor.java | 328 ++
.../healthcheck/ClientBeatCheckTask.java | 96 +
.../healthcheck/ClientBeatProcessor.java | 95 +
.../naming/healthcheck/HealthCheckMode.java | 21 +
.../healthcheck/HealthCheckReactor.java | 48 +
.../naming/healthcheck/HealthCheckStatus.java | 81 +
.../naming/healthcheck/HealthCheckTask.java | 159 +
.../naming/healthcheck/HealthCheckType.java | 34 +
.../healthcheck/HttpHealthCheckProcessor.java | 200 ++
.../MysqlHealthCheckProcessor.java | 210 ++
.../nacos/naming/healthcheck/RsInfo.java | 120 +
.../healthcheck/TcpSuperSenseProcessor.java | 420 +++
.../naming/misc/DomainStatusSynchronizer.java | 98 +
.../alibaba/nacos/naming/misc/HttpClient.java | 398 +++
.../alibaba/nacos/naming/misc/Loggers.java | 68 +
.../alibaba/nacos/naming/misc/Message.java | 31 +
.../nacos/naming/misc/NamingProxy.java | 264 ++
.../alibaba/nacos/naming/misc/NetUtils.java | 48 +
.../naming/misc/ServerStatusSynchronizer.java | 71 +
.../com/alibaba/nacos/naming/misc/Switch.java | 349 ++
.../nacos/naming/misc/SwitchDomain.java | 391 +++
.../nacos/naming/misc/SwitchEntry.java | 62 +
.../nacos/naming/misc/Synchronizer.java | 38 +
.../nacos/naming/misc/UtilsAndCommons.java | 204 ++
.../monitor/PerformanceLoggerThread.java | 142 +
.../alibaba/nacos/naming/push/ClientInfo.java | 145 +
.../alibaba/nacos/naming/push/DataSource.java | 30 +
.../nacos/naming/push/PushService.java | 681 ++++
.../com/alibaba/nacos/naming/raft/Datum.java | 27 +
.../nacos/naming/raft/GlobalExecutor.java | 58 +
.../alibaba/nacos/naming/raft/PeerSet.java | 221 ++
.../alibaba/nacos/naming/raft/RaftCore.java | 1015 ++++++
.../nacos/naming/raft/RaftListener.java | 56 +
.../alibaba/nacos/naming/raft/RaftPeer.java | 87 +
.../alibaba/nacos/naming/raft/RaftProxy.java | 72 +
.../alibaba/nacos/naming/raft/RaftStore.java | 193 +
.../alibaba/nacos/naming/web/ApiCommands.java | 2452 +++++++++++++
.../alibaba/nacos/naming/web/AuthFilter.java | 110 +
.../alibaba/nacos/naming/web/BaseServlet.java | 71 +
.../nacos/naming/web/DistroFilter.java | 111 +
.../nacos/naming/web/MockHttpRequest.java | 390 +++
.../nacos/naming/web/NamingConfig.java | 63 +
.../alibaba/nacos/naming/web/NeedAuth.java | 25 +
.../nacos/naming/web/RaftCommands.java | 246 ++
.../src/main/resources/application.properties | 10 +
naming/src/main/resources/banner.txt | 15 +
naming/src/main/resources/naming-logback.xml | 247 ++
.../com/alibaba/nacos/naming/BaseTest.java | 50 +
.../controllers/InstanceControllerTest.java | 154 +
.../nacos/naming/core/ClusterTest.java | 100 +
.../alibaba/nacos/naming/core/DomainTest.java | 96 +
.../nacos/naming/core/DomainsManagerTest.java | 80 +
.../nacos/naming/core/IpAddressTest.java | 53 +
.../alibaba/nacos/naming/misc/SwitchTest.java | 59 +
.../nacos/naming/raft/RaftStoreTest.java | 42 +
.../nacos/naming/web/APICommandsTest.java | 130 +
pom.xml | 685 ++++
style/codeStyle.md | 31 +
test/it_test.log | 3 +
test/pom.xml | 77 +
.../main/java/com/alibaba/nacos/test/App.java | 28 +
.../java/com/alibaba/nacos/test/AppTest.java | 53 +
.../nacos/test/config/ConfigAPI_ITCase.java | 564 +++
.../naming/DeregisterInstance_ITCase.java | 115 +
.../alibaba/nacos/test/naming/NamingBase.java | 174 +
.../com/alibaba/nacos/test/naming/Params.java | 42 +
.../nacos/test/naming/RandomUtils.java | 348 ++
.../test/naming/RegisterInstance_ITCase.java | 153 +
.../nacos/test/naming/RestAPI_ITCase.java | 683 ++++
.../test/naming/SelectInstances_ITCase.java | 153 +
.../SelectOneHealthyInstance_ITCase.java | 168 +
.../nacos/test/naming/Starter_ITCase.java | 22 +
.../test/naming/SubscribeCluster_ITCase.java | 222 ++
.../nacos/test/naming/Subscribe_ITCase.java | 193 +
.../nacos/test/naming/Unsubscribe_ITCase.java | 152 +
.../nacos/test/smoke/nacosSmoke_ITCase.java | 58 +
.../src/test/resources/application.properties | 6 +
test/src/test/resources/logback-test.xml | 33 +
test/src/test/resources/schema.sql | 161 +
432 files changed, 62877 insertions(+)
create mode 100644 .gitignore
create mode 100644 .travis.yml
create mode 100644 BUILDING
create mode 100644 CONTRIBUTING.md
create mode 100644 LICENSE
create mode 100644 NOTICE
create mode 100644 README.md
create mode 100644 client/pom.xml
create mode 100644 client/src/main/java/com/alibaba/nacos/api/NacosFactory.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/config/ConfigFactory.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/config/ConfigService.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigContext.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigFilter.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigFilterChain.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigRequest.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigResponse.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/config/filter/IFilterConfig.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/config/listener/AbstractListener.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/config/listener/AbstractSharedListener.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/config/listener/Listener.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/exception/NacosException.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/naming/NamingFactory.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/naming/NamingService.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/naming/listener/Event.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/naming/listener/EventListener.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/naming/listener/NamingEvent.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/naming/pojo/AbstractHealthChecker.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/naming/pojo/Cluster.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/naming/pojo/Instance.java
create mode 100644 client/src/main/java/com/alibaba/nacos/api/naming/pojo/Service.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/common/Constants.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/common/GroupKey.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigContext.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManager.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigRequest.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigResponse.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/impl/CacheData.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/impl/EventDispatcher.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/impl/HttpSimpleClient.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/impl/Limiter.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/impl/ServerHttpAgent.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/impl/SpasAdapter.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/impl/TimerService.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/listener/impl/PropertiesListener.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/utils/ConcurrentDiskUtil.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/utils/ContentUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/utils/IOUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/utils/JVMUtil.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/utils/LogUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/utils/MD5.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/utils/ParamUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/utils/SnapShotSwitch.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/config/utils/TenantUtil.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/identify/Base64.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/identify/Constants.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/identify/CredentialListener.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/identify/CredentialService.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/identify/CredentialWatcher.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/identify/Credentials.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/identify/STSConfig.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/identify/SpasCredential.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/identify/SpasCredentialLoader.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/Level.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/Logger.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/LoggerFactory.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/json/JSONArray.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/json/JSONAware.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/json/JSONObject.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/json/JSONStreamAware.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/json/JSONValue.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/json/parser/ContainerFactory.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/json/parser/ContentHandler.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/json/parser/JSONParser.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/json/parser/ParseException.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/json/parser/Yylex.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/json/parser/Yytoken.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/log4j/Log4jLogger.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/log4j/Log4jLoggerFactory.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/log4j2/Log4j2Logger.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/log4j2/Log4j2LoggerFactory.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/nop/NopLogger.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/nop/NopLoggerFactory.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/option/AbstractActiveOption.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/option/ActivateOption.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/option/Log4j2ActivateOption.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/option/Log4jActivateOption.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/option/Logback918ActivateOption.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/option/LogbackActivateOption.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/option/LogbackLoggerContextUtil.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/option/Slf4jLog4j2AdapterActivateOption.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/option/Slf4jLog4jAdapterActivateOption.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/slf4j/Slf4jLogger.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/slf4j/Slf4jLoggerFactory.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/support/AppenderInfo.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/support/DepthThrowableRenderer.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/support/ErrorLog.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/support/ILoggerFactory.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/support/Log4jHelper.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/support/LogLog.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/support/LogbackHelper.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/support/LoggerHelper.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/support/LoggerInfo.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/support/LoggerSupport.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/util/FormattingTuple.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/util/MessageFormatter.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/logger/util/MessageUtil.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/backups/FailoverReactor.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/beat/BeatInfo.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/beat/BeatReactor.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/cache/ConcurrentDiskUtil.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/cache/DiskCache.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/core/Balancer.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/core/Domain.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/core/EventDispatcher.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/core/HostReactor.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/core/ProtectMode.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/core/PushRecver.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/net/HttpClient.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/net/NamingProxy.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/Chooser.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/CollectionUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/GenericPoller.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/IoUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/JvmRandom.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/LogUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/NetUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/Pair.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/Poller.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/RandomUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/StringUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/ThreadLocalRandom.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/naming/utils/UtilAndComs.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/utils/AppNameUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/utils/EnvUtil.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/utils/IPUtil.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/utils/JSONUtils.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/utils/ParamUtil.java
create mode 100644 client/src/main/java/com/alibaba/nacos/client/utils/StringUtils.java
create mode 100644 client/src/main/resources/application.properties
create mode 100644 client/src/test/java/com/alibaba/nacos/client/AppTest.java
create mode 100644 common/license
create mode 100644 common/pom.xml
create mode 100644 common/src/main/java/com/alibaba/nacos/common/AppendLicense.java
create mode 100644 common/src/main/java/com/alibaba/nacos/common/util/IoUtils.java
create mode 100644 common/src/main/java/com/alibaba/nacos/common/util/Md5Utils.java
create mode 100644 common/src/main/java/com/alibaba/nacos/common/util/Pair.java
create mode 100644 common/src/main/java/com/alibaba/nacos/common/util/SystemUtil.java
create mode 100644 common/src/main/java/com/alibaba/nacos/common/util/UuidUtil.java
create mode 100644 common/src/test/java/com/alibaba/nacos/common/AppTest.java
create mode 100644 config/pom.xml
create mode 100644 config/src/main/java/LogbackInitTest.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/Config.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/aspect/CapacityManagementAspect.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/aspect/RequestLogAspect.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/constant/Constants.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/constant/CounterMode.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/controller/CapacityController.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/controller/CommunicationController.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/controller/HealthController.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/controller/HistoryController.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/controller/ListenerController.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/controller/OpsController.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/exception/GlobalExceptionHandler.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/exception/NacosException.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/filter/WebFilter.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/manager/AbstractTask.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/manager/TaskManager.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/manager/TaskManagerMBean.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/manager/TaskProcessor.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ACLInfo.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/AuthType.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/CacheItem.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigAdvanceInfo.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigHistoryInfo.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfo.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfo4Beta.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfo4Tag.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoAggr.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoBase.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoBaseEx.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoChanged.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoEx.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoWrapper.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/ConfigKey.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/GroupInfo.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/GroupkeyListenserStatus.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/HistoryContext.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/Page.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/RestPageResult.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/RestResult.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/SampleResult.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/SubInfo.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/SubscriberStatus.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/app/ApplicationInfo.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/app/ApplicationPublishRecord.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/app/GroupKey.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/app/MonitorInfo.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/capacity/Capacity.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/capacity/GroupCapacity.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/model/capacity/TenantCapacity.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/monitor/MemoryMonitor.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/monitor/ResponseMonitor.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/AggrWhitelist.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/BasicDataSourceServiceImpl.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/ClientIpWhiteList.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/service/ClientTrackService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/ConfigDataChangeEvent.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/ConfigService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/ConfigSubService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/DataSourceService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/DiskUtil.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/DynamicDataSource.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/LocalDataChangeEvent.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/LocalDataSourceServiceImpl.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/service/LongPullingService.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/service/PersistService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/ServerListService.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/service/SwitchService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/TimerTaskService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/capacity/CapacityService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/capacity/GroupCapacityPersistService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/capacity/TenantCapacityPersistService.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpService.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpTask.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeDataTask.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeDatumService.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeTaskProcessor.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/notify/AsyncNotifyService.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/service/notify/NotifyService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/notify/NotifySingleService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/notify/NotifyTask.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/service/notify/NotifyTaskProcessor.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/service/trace/ConfigTraceService.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/AccumulateStatCount.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/AppNameUtils.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/ContentUtils.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/GroupKey.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/GroupKey2.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/IPUtil.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/JSONUtils.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/utils/LogUtil.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/MD5.java
create mode 100755 config/src/main/java/com/alibaba/nacos/config/server/utils/MD5Util.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/PaginationHelper.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/ParamUtils.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/PropertyUtil.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/Protocol.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/RegexParser.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/RequestUtil.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/ResourceUtils.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/ResponseUtil.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/RunningConfigUtils.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleCache.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleFlowData.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleIPFlowData.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLock.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/SingletonRepository.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/StatConstants.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/StringUtils.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/SystemConfig.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/ThreadUtil.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/TimeUtils.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/TimeoutUtils.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/TraceLogUtil.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/UrlAnalysisUtils.java
create mode 100644 config/src/main/java/com/alibaba/nacos/config/server/utils/event/EventDispatcher.java
create mode 100644 config/src/main/resources/application.properties
create mode 100644 config/src/main/resources/banner.txt
create mode 100644 config/src/main/resources/diamond-app-collector.sql
create mode 100644 config/src/main/resources/diamond-db.sql
create mode 100755 config/src/main/resources/nacos-config-logback.xml
create mode 100644 config/src/main/resources/schema.sql
create mode 100755 config/src/main/resources/version/version.txt
create mode 100644 config/src/test/java/com/alibaba/nacos/config/mock/FilterConfigMock.java
create mode 100644 config/src/test/java/com/alibaba/nacos/config/mock/ServletContextMock.java
create mode 100644 config/src/test/java/com/alibaba/nacos/config/server/controller/HealthControllerUnitTest.java
create mode 100644 config/src/test/java/com/alibaba/nacos/config/server/service/AggrWhitelistTest.java
create mode 100644 config/src/test/java/com/alibaba/nacos/config/server/service/ClientTrackServiceTest.java
create mode 100755 config/src/test/java/com/alibaba/nacos/config/server/service/DiskServiceUnitTest.java
create mode 100644 config/src/test/java/com/alibaba/nacos/config/server/utils/GroupKeyTest.java
create mode 100644 config/src/test/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLockTest.java
create mode 100755 config/src/test/java/com/alibaba/nacos/config/server/utils/event/EventDispatcherTest.java
create mode 100644 config/src/test/resources/application.xml-bk
create mode 100644 config/src/test/resources/application.xml-test4derby
create mode 100755 config/src/test/resources/jdbc.properties
create mode 100644 config/src/test/resources/log4j.properties
create mode 100755 config/src/test/resources/user.properties
create mode 100644 console/pom.xml
create mode 100644 console/src/main/java/com/alibaba/nacos/Nacos.java
create mode 100644 console/src/main/resources/application.properties
create mode 100644 console/src/main/resources/banner.txt
create mode 100755 console/src/main/resources/diamond-server-logback.xml
create mode 100644 console/src/main/resources/schema.sql
create mode 100644 core/pom.xml
create mode 100644 core/src/main/java/com/alibaba/nacos/core/App.java
create mode 100644 core/src/test/java/com/alibaba/nacos/core/AppTest.java
create mode 100644 distribution/LICENSE-BIN
create mode 100644 distribution/NOTICE-BIN
create mode 100644 distribution/bin/deploy.sh
create mode 100644 distribution/bin/deploy_naming.sh
create mode 100644 distribution/bin/run_naming.sh
create mode 100755 distribution/bin/shutdown.cmd
create mode 100644 distribution/bin/shutdown.sh
create mode 100755 distribution/bin/startup.cmd
create mode 100644 distribution/bin/startup.sh
create mode 100644 distribution/conf/application.properties
create mode 100644 distribution/conf/application.properties.example
create mode 100644 distribution/conf/cluster.conf.example
create mode 100644 distribution/conf/nacos-logback.xml
create mode 100644 distribution/conf/schema.sql
create mode 100644 distribution/pom.xml
create mode 100644 distribution/release-client.xml
create mode 100644 distribution/release-config.xml
create mode 100644 distribution/release-core.xml
create mode 100644 distribution/release-nacos.xml
create mode 100644 distribution/release-naming.xml
create mode 100644 doc/Nacos_Logo.png
create mode 100644 doc/arch.png
create mode 100644 example/pom.xml
create mode 100644 example/src/main/java/com/alibaba/nacos/example/App.java
create mode 100644 example/src/main/java/com/alibaba/nacos/example/ConfigExample.java
create mode 100644 example/src/main/java/com/alibaba/nacos/example/NamingExample.java
create mode 100644 example/src/test/java/com/alibaba/nacos/example/AppTest.java
create mode 100644 naming/default/failover/nacos.test.4
create mode 100644 naming/pom.xml
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/NamingApp.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/acl/AuthChecker.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/acl/AuthInfo.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/boot/RunningConfig.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/controllers/CatalogController.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/controllers/ClusterController.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/controllers/CmdbController.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/controllers/HealthController.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/controllers/InstanceController.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/controllers/OperatorController.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/controllers/ServiceController.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/Cluster.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/DistroMapper.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/Domain.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/DomainsManager.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/IpAddress.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/VirtualClusterDomain.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/exception/NacosException.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/exception/ResponseExceptionHandler.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/AbstractHealthCheckConfig.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/AbstractHealthCheckProcessor.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/ClientBeatCheckTask.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/ClientBeatProcessor.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/HealthCheckMode.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/HealthCheckReactor.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/HealthCheckStatus.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/HealthCheckTask.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/HealthCheckType.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/HttpHealthCheckProcessor.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/MysqlHealthCheckProcessor.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/RsInfo.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/healthcheck/TcpSuperSenseProcessor.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/DomainStatusSynchronizer.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/HttpClient.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/Loggers.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/Message.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/NamingProxy.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/NetUtils.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/ServerStatusSynchronizer.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/Switch.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/SwitchDomain.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/SwitchEntry.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/Synchronizer.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/misc/UtilsAndCommons.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/monitor/PerformanceLoggerThread.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/push/ClientInfo.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/push/DataSource.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/push/PushService.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/raft/Datum.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/raft/GlobalExecutor.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/raft/PeerSet.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/raft/RaftCore.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/raft/RaftListener.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/raft/RaftPeer.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/raft/RaftProxy.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/raft/RaftStore.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/web/ApiCommands.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/web/AuthFilter.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/web/BaseServlet.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/web/DistroFilter.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/web/MockHttpRequest.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/web/NamingConfig.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/web/NeedAuth.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/web/RaftCommands.java
create mode 100644 naming/src/main/resources/application.properties
create mode 100644 naming/src/main/resources/banner.txt
create mode 100644 naming/src/main/resources/naming-logback.xml
create mode 100644 naming/src/test/java/com/alibaba/nacos/naming/BaseTest.java
create mode 100644 naming/src/test/java/com/alibaba/nacos/naming/controllers/InstanceControllerTest.java
create mode 100644 naming/src/test/java/com/alibaba/nacos/naming/core/ClusterTest.java
create mode 100644 naming/src/test/java/com/alibaba/nacos/naming/core/DomainTest.java
create mode 100644 naming/src/test/java/com/alibaba/nacos/naming/core/DomainsManagerTest.java
create mode 100644 naming/src/test/java/com/alibaba/nacos/naming/core/IpAddressTest.java
create mode 100644 naming/src/test/java/com/alibaba/nacos/naming/misc/SwitchTest.java
create mode 100644 naming/src/test/java/com/alibaba/nacos/naming/raft/RaftStoreTest.java
create mode 100644 naming/src/test/java/com/alibaba/nacos/naming/web/APICommandsTest.java
create mode 100644 pom.xml
create mode 100644 style/codeStyle.md
create mode 100644 test/it_test.log
create mode 100644 test/pom.xml
create mode 100644 test/src/main/java/com/alibaba/nacos/test/App.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/AppTest.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/config/ConfigAPI_ITCase.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/DeregisterInstance_ITCase.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/NamingBase.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/Params.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/RandomUtils.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/RegisterInstance_ITCase.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/RestAPI_ITCase.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/SelectInstances_ITCase.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/SelectOneHealthyInstance_ITCase.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/Starter_ITCase.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/SubscribeCluster_ITCase.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/Subscribe_ITCase.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/naming/Unsubscribe_ITCase.java
create mode 100644 test/src/test/java/com/alibaba/nacos/test/smoke/nacosSmoke_ITCase.java
create mode 100644 test/src/test/resources/application.properties
create mode 100644 test/src/test/resources/logback-test.xml
create mode 100644 test/src/test/resources/schema.sql
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000000..b8425e1f9d6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+# Except this file !.gitignore
+.classpath
+.project
+.settings
+target
+.project
+.idea
+.DS_Store
+/logs
+*.iml
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000000..e4e74b6ec19
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,31 @@
+notifications:
+ email:
+ recipients:
+ - nacos_dev@linux.alibaba.com
+ - dev-nacos@googlegroups.com
+ on_success: change
+ on_failure: always
+
+language: java
+
+matrix:
+ include:
+ # On OSX, run with default JDK only.
+ # - os: osx
+ # On Linux, run with specific JDKs only.
+ - os: linux
+ env: CUSTOM_JDK="oraclejdk8"
+
+before_install:
+ - echo 'MAVEN_OPTS="$MAVEN_OPTS -Xmx1024m -XX:MaxPermSize=512m -XX:+BytecodeVerificationLocal"' >> ~/.mavenrc
+ - cat ~/.mavenrc
+ - if [ "$TRAVIS_OS_NAME" == "osx" ]; then export JAVA_HOME=$(/usr/libexec/java_home); fi
+ - if [ "$TRAVIS_OS_NAME" == "linux" ]; then jdk_switcher use "$CUSTOM_JDK"; fi
+
+script:
+ - travis_retry mvn -B clean apache-rat:check
+ - travis_retry mvn -B package jacoco:report coveralls:report
+
+after_success:
+ - mvn clean install -Pit-test
+ - mvn sonar:sonar -Psonar-apache
diff --git a/BUILDING b/BUILDING
new file mode 100644
index 00000000000..e7e968b8b45
--- /dev/null
+++ b/BUILDING
@@ -0,0 +1,38 @@
+Build Instructions for NACOS
+
+====================================================
+
+(1) Prerequisites
+
+ JDK 1.8+ is required in order to compile and run Nacos.
+
+ nacos utilizes Maven as a distribution management and packaging tool. Version 3.0.3 or later is required.
+ Maven installation and configuration instructions can be found here:
+
+ http://maven.apache.org/run-maven/index.html
+
+
+(2) Run test cases
+
+ Execute the following command in order to compile and run test cases of each components:
+
+ $ mvn test
+
+
+(3) Import projects to Eclipse IDE
+
+ First, generate eclipse project files:
+
+ $ mvn -U eclipse:eclipse
+
+ Then, import to eclipse by specifying the root directory of the project via:
+
+ [File] > [Import] > [Existing Projects into Workspace].
+
+
+(4) Build distribution packages
+
+ Execute the following command in order to build the tar.gz packages and install JAR into local repository:
+
+ #build nacos
+ $ mvn -Prelease-nacos -DskipTests clean install -U
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000000..e75d1970000
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,31 @@
+## How To Contribute
+
+We are always very happy to have contributions, whether for trivial cleanups or big new features.
+We want to have high quality, well documented codes for each programming language.
+
+Nor is code the only way to contribute to the project. We strongly value documentation, integration with other project, and gladly accept improvements for these aspects.
+
+## Contributing code
+
+To submit a change for inclusion, please do the following:
+
+#### If the change is non-trivial please include some unit tests that cover the new functionality.
+#### If you are introducing a completely new feature or API it is a good idea to start a wiki and get consensus on the basic design first.
+#### It is our job to follow up on patches in a timely fashion. Nag us if we aren't doing our job (sometimes we drop things).
+
+## Becoming a Committer
+
+We are always interested in adding new contributors. What we look for are series of contributions, good taste and ongoing interest in the project. If you are interested in becoming a committer, please let one of the existing committers know and they can help you walk through the process.
+
+Nowadays,we have several important contribution points:
+#### Wiki & JavaDoc
+#### Nacos Console
+#### Nacos SDK(C++\.Net\Php\Python\Go\Node.js)
+
+##### Prerequisite
+If you want to contribute the above listing points, you must abide our some prerequisites:
+
+###### Readability - API must have Javadoc,some very important methods also must have javadoc
+###### Testability - 80% above unit test coverage about main process
+###### Maintainability - Comply with our [PMD spec](style/codeStyle.xml), and at least 3 month update frequency
+###### Deployability - We encourage you to deploy into [maven repository](http://search.maven.org/)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000000..7f77f44e739
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (properties) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 00000000000..dcaaa07ecf4
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,32 @@
+Nacos
+Copyright 2018-2019 The Apache Software Foundation
+
+This product includes software developed at
+The Alibaba MiddleWare Group.
+
+------
+This product has a bundle Spring Boot:
+ The Spring Boot Project
+ =================
+
+Please visit the Spring Boot web site for more information:
+
+ * https://spring.io/projects/spring-boot
+
+Copyright 2014 The Spring Boot Project
+
+The Spring Boot Project licenses this file to you under the Apache License,
+version 2.0 (the "License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at:
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations
+under the License.
+
+Also, please refer to each LICENSE..txt file, which is located in
+the 'license' directory of the distribution file, for the license terms of the
+components that this product depends on.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 00000000000..3b3b20c911c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,49 @@
+## Nacos
+
+
+[](https://gitter.im/alibaba/nacos?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://www.apache.org/licenses/LICENSE-2.0.html)
+[](https://travis-ci.org/alibaba/nacos)
+
+-------
+
+Nacos is an easy-to-use platform desgined for dynamic service discovery and configuration and service management. It helps you to build cloud native applications and microservices platform easily.
+
+Service is a first-class citizen in Nacos. Nacos supports almost all type of services,for example,[Dubbo/gRPC service](xx)、[Spring Cloud RESTFul service](xx) or [Kubernetes service](xx).
+
+Nacos provides four major funcations.
+
+* **Service Discovery and Service Health Check**
+
+ Nacos makes it simple for services to register themselves and to discover other services via a DNS or HTTP interface. Nacos also provides real-time healthchecks of services to prevent sending requests to unhealthy hosts or service instance.
+
+* **Dynamic Configuration Management**
+
+ Dynamic Configuration Service allows you to manage configurations of all services in a centralized and dynamic manner across all environments. Nacos eliminates the need to redeploy applications and services when configurations are updated,which makes configuration changes more efficient and agile.
+
+* **Dynamic DNS Service**
+
+ Nacos supports weighted routing, making it easier for you to implement mid-tier load balancing, flexible routing policies, flow control, and simple DNS resolution services in the production environment within your data center. It helps you to implement DNS-based service discovery easily and prevent applications from coupling to vendor-specific service discovery APIs.
+
+* **Service and MetaData Management**
+
+ Nacos provides an easy-to-use service dashboard to help you manage your services metadata, configuration, kubernetes DNS, service health and metrics statistics.
+
+
+## Quick Start (TODO)
+It is super easy to get started with your first project.
+
+https://nacos.io/#/docs/quick-start.md
+
+Quick start for other open-source projects:
+
+[quick start with spring cloud](xx)
+[quick start with dubbo](xx)
+[quick start with kubernetes](xx)
+[more...](xx)
+
+
+## Documentation
+
+You can view full documentation on the Nacos website:
+
+[https://nacos.io/#/blog](https://nacos.io/#/blog)
diff --git a/client/pom.xml b/client/pom.xml
new file mode 100644
index 00000000000..78ddf9da055
--- /dev/null
+++ b/client/pom.xml
@@ -0,0 +1,107 @@
+
+
+ com.alibaba.nacos
+ nacos-all
+ 0.1.0
+
+
+ 4.0.0
+
+ nacos-client
+ jar
+
+ nacos-client ${project.version}
+ http://maven.apache.org
+
+
+ UTF-8
+
+
+
+
+ org.slf4j
+ slf4j-api
+ provided
+
+
+ log4j
+ log4j
+ provided
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.8.2
+ provided
+
+
+ commons-logging
+ commons-logging
+ provided
+
+
+ org.slf4j
+ slf4j-log4j12
+ provided
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ provided
+
+
+ org.slf4j
+ jcl-over-slf4j
+ provided
+
+
+ junit
+ junit
+ test
+
+
+ ${project.groupId}
+ nacos-common
+
+
+ com.alibaba
+ fastjson
+
+
+
+ ch.qos.logback
+ logback-classic
+
+
+ ch.qos.logback
+ logback-core
+
+
+
+ com.google.guava
+ guava
+
+
+
+ commons-codec
+ commons-codec
+
+
+
+ org.codehaus.jackson
+ jackson-mapper-lgpl
+
+
+ net.jcip
+ jcip-annotations
+ true
+
+
+ com.github.spotbugs
+ spotbugs-annotations
+ true
+
+
+
+
diff --git a/client/src/main/java/com/alibaba/nacos/api/NacosFactory.java b/client/src/main/java/com/alibaba/nacos/api/NacosFactory.java
new file mode 100644
index 00000000000..747bc7a45b8
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/NacosFactory.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api;
+
+import java.util.Properties;
+
+import com.alibaba.nacos.api.config.ConfigFactory;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.naming.NamingFactory;
+import com.alibaba.nacos.api.naming.NamingService;
+
+/**
+ * Nacos Factory
+ *
+ * @author Nacos
+ *
+ */
+public class NacosFactory {
+
+ /**
+ * Create config
+ *
+ * @param properties
+ * init param
+ * @return config
+ * @throws NacosException
+ * Exception
+ */
+ public static ConfigService createConfigService(Properties properties) throws NacosException {
+ return ConfigFactory.createConfigService(properties);
+ }
+
+ /**
+ * Create config
+ *
+ * @param serverAddr
+ * server list
+ * @return config
+ * @throws NacosException
+ * Exception
+ */
+ public static ConfigService createConfigService(String serverAddr) throws NacosException {
+ return ConfigFactory.createConfigService(serverAddr);
+ }
+
+ /**
+ * Create Naming
+ *
+ * @param serverAddr
+ * server list
+ * @return Naming
+ * @throws NacosException
+ * Exception
+ */
+ public static NamingService createNamingService(String serverAddr) throws NacosException {
+ return NamingFactory.createNamingService(serverAddr);
+ }
+
+ /**
+ * Create Naming
+ *
+ * @param properties
+ * init param
+ * @return Naming
+ * @throws NacosException
+ * Exception
+ */
+ public static NamingService createNamingService(Properties properties) throws NacosException {
+ return NamingFactory.createNamingService(properties);
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java b/client/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java
new file mode 100644
index 00000000000..1fc3394301f
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api;
+
+/**
+ * properties key
+ * @author Nacos
+ *
+ */
+public class PropertyKeyConst {
+
+ public final static String ENDPOINT = "endpoint";
+ public final static String NAMESPACE = "namespace";
+ public final static String ACCESS_KEY = "accessKey";
+ public final static String SECRET_KEY = "secretKey";
+ public final static String SERVER_ADDR = "serverAddr";
+ public final static String CONTEXT_PATH = "contextPath";
+ public final static String CLUSTER_NAME = "clusterName";
+ public final static String ENCODE = "encode";
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/config/ConfigFactory.java b/client/src/main/java/com/alibaba/nacos/api/config/ConfigFactory.java
new file mode 100644
index 00000000000..9bfc7e7a4bd
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/config/ConfigFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.config;
+
+import java.util.Properties;
+
+import com.alibaba.nacos.api.PropertyKeyConst;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.client.config.NacosConfigService;
+
+/**
+ * Config Factory
+ *
+ * @author Nacos
+ *
+ */
+public class ConfigFactory {
+
+ /**
+ * Create Config
+ *
+ * @param properties
+ * init param
+ * @return Config
+ * @throws NacosException
+ * Exception
+ */
+ public static ConfigService createConfigService(Properties properties) throws NacosException {
+ return new NacosConfigService(properties);
+ }
+
+ /**
+ * Create Config
+ *
+ * @param ServerAddr
+ * serverlist
+ * @return Config
+ * @throws NacosException
+ * Exception
+ */
+ public static ConfigService createConfigService(String serverAddr) throws NacosException {
+ Properties properties = new Properties();
+ properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
+ return new NacosConfigService(properties);
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/config/ConfigService.java b/client/src/main/java/com/alibaba/nacos/api/config/ConfigService.java
new file mode 100644
index 00000000000..9a96a528bef
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/config/ConfigService.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.config;
+
+import com.alibaba.nacos.api.config.listener.Listener;
+import com.alibaba.nacos.api.exception.NacosException;
+
+/**
+ * Config Interface
+ *
+ * @author Nacos
+ *
+ */
+public interface ConfigService {
+
+ /**
+ * Get Configuration
+ *
+ * @param dataId
+ * Config ID
+ * @param group
+ * Config Group
+ * @param timeoutMs
+ * read timeout
+ * @return config value
+ * @throws NacosException
+ * NacosException
+ */
+ public String getConfig(String dataId, String group, long timeoutMs) throws NacosException;
+
+ /**
+ * Add a listener to the configuration, after the server to modify the
+ * configuration, the client will use the incoming listener callback.
+ * Recommended asynchronous processing, the application can implement the
+ * getExecutor method in the ManagerListener, provide a thread pool of
+ * execution. If provided, use the main thread callback, May block other
+ * configurations or be blocked by other configurations.
+ *
+ * @param dataId
+ * Config ID
+ * @param group
+ * Config Group
+ * @param listener
+ * listener
+ * @throws NacosException
+ * NacosException
+ */
+ public void addListener(String dataId, String group, Listener listener) throws NacosException;
+
+ /**
+ * publish config.
+ *
+ * @param dataId
+ * Config ID
+ * @param group
+ * Config Group
+ * @param content
+ * Config Content
+ * @return Whether publish
+ * @throws NacosException
+ * NacosException
+ */
+ public boolean publishConfig(String dataId, String group, String content) throws NacosException;
+
+ /**
+ * Remove Config
+ *
+ * @param dataId
+ * Config ID
+ * @param group
+ * Config Group
+ * @return whether remove
+ * @throws NacosException
+ * NacosException
+ */
+ public boolean removeConfig(String dataId, String group) throws NacosException;
+
+ /**
+ * Remove Listener
+ *
+ * @param dataId
+ * Config ID
+ * @param group
+ * Config Group
+ * @param listener
+ * listener
+ */
+ public void removeListener(String dataId, String group, Listener listener);
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigContext.java b/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigContext.java
new file mode 100644
index 00000000000..2b26df8e4ca
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigContext.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.config.filter;
+
+/**
+ * Config Context Interface
+ *
+ * @author Nacos
+ *
+ */
+public interface IConfigContext {
+ /**
+ * get context by key
+ *
+ * @param key
+ * @return context
+ */
+ public Object getParameter(String key);
+
+ /**
+ * set context
+ *
+ * @param key
+ * key
+ * @param value
+ * value
+ */
+ public void setParameter(String key, Object value);
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigFilter.java b/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigFilter.java
new file mode 100644
index 00000000000..e3007640808
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigFilter.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.config.filter;
+
+import com.alibaba.nacos.api.exception.NacosException;
+
+/**
+ * Config Filter Interface
+ *
+ * @author Nacos
+ *
+ */
+public interface IConfigFilter {
+ /**
+ * Init Fuction
+ *
+ * @param filterConfig
+ * Filter Config
+ */
+ void init(IFilterConfig filterConfig);
+
+ /**
+ * do filter
+ *
+ * @param request
+ * request
+ * @param response
+ * response
+ * @param filterChain
+ * filter Chain
+ * @throws NacosException
+ * exception
+ */
+ void doFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)
+ throws NacosException;
+
+ /**
+ * deploy
+ */
+ void deploy();
+
+ /**
+ * order
+ *
+ * @return
+ */
+ int getOrder();
+
+ /**
+ * filterName
+ *
+ * @return
+ */
+ String getFilterName();
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigFilterChain.java b/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigFilterChain.java
new file mode 100644
index 00000000000..ac084d67e49
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigFilterChain.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.config.filter;
+
+import com.alibaba.nacos.api.exception.NacosException;
+
+/**
+ * Config Filter Chain Interface
+ *
+ * @author Nacos
+ *
+ */
+public interface IConfigFilterChain {
+ /**
+ * Filter aciton
+ *
+ * @param request
+ * request
+ * @param response
+ * response
+ * @throws NacosException
+ * NacosException
+ */
+ public void doFilter(IConfigRequest request, IConfigResponse response) throws NacosException;
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigRequest.java b/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigRequest.java
new file mode 100644
index 00000000000..308fe06a6a8
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigRequest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.config.filter;
+
+/**
+ * Config Request Interface
+ *
+ * @author Nacos
+ *
+ */
+public interface IConfigRequest {
+ /**
+ * get param
+ *
+ * @param key
+ * key
+ * @return value
+ */
+ public Object getParameter(String key);
+
+ /**
+ * get config context
+ *
+ * @return
+ */
+ public IConfigContext getConfigContext();
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigResponse.java b/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigResponse.java
new file mode 100644
index 00000000000..69b5aca07e6
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/config/filter/IConfigResponse.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.config.filter;
+
+/**
+ * Config Response Interface
+ *
+ * @author Nacos
+ *
+ */
+public interface IConfigResponse {
+ /**
+ * get param
+ *
+ * @param key
+ * key
+ * @return value
+ */
+ public Object getParameter(String key);
+
+ /**
+ * get context
+ *
+ * @return configContext
+ */
+ public IConfigContext getConfigContext();
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/config/filter/IFilterConfig.java b/client/src/main/java/com/alibaba/nacos/api/config/filter/IFilterConfig.java
new file mode 100644
index 00000000000..55a931ba843
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/config/filter/IFilterConfig.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.config.filter;
+/**
+ * Filter Config Interface
+ * @author Nacos
+ *
+ */
+public interface IFilterConfig {
+
+ /**
+ * get filter name
+ *
+ * @return
+ */
+ public String getFilterName();
+
+ /**
+ * get param
+ *
+ * @param name
+ * @return param
+ */
+ public Object getInitParameter(String name);
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/config/listener/AbstractListener.java b/client/src/main/java/com/alibaba/nacos/api/config/listener/AbstractListener.java
new file mode 100644
index 00000000000..817e0c5c566
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/config/listener/AbstractListener.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.config.listener;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Listner Adapter,use default notify thread
+ *
+ * @author water.lyl
+ *
+ */
+@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
+public abstract class AbstractListener implements Listener {
+
+ /**
+ * use default Executor
+ */
+ public Executor getExecutor() {
+ return null;
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/config/listener/AbstractSharedListener.java b/client/src/main/java/com/alibaba/nacos/api/config/listener/AbstractSharedListener.java
new file mode 100644
index 00000000000..dd0f83dee6d
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/config/listener/AbstractSharedListener.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.config.listener;
+
+import java.util.concurrent.Executor;
+
+/**
+ * shared listener
+ *
+ * @author Nacos
+ *
+ */
+@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
+public abstract class AbstractSharedListener implements Listener {
+ private volatile String dataId;
+ private volatile String group;
+
+ final public void fillContext(String dataId, String group) {
+ this.dataId = dataId;
+ this.group = group;
+ }
+
+ @Override
+ final public void receiveConfigInfo(String configInfo) {
+ innerReceive(dataId, group, configInfo);
+ }
+
+ @Override
+ public Executor getExecutor() {
+ return null;
+ }
+
+ /**
+ * receive
+ *
+ * @param dataId
+ * data ID
+ * @param group
+ * group
+ * @param configInfo
+ * content
+ */
+ public abstract void innerReceive(String dataId, String group, String configInfo);
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/config/listener/Listener.java b/client/src/main/java/com/alibaba/nacos/api/config/listener/Listener.java
new file mode 100644
index 00000000000..f8dc734e801
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/config/listener/Listener.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.config.listener;
+
+import java.util.concurrent.Executor;
+
+
+/**
+ * Listener for watch config
+ *
+ * @author Nacos
+ *
+ */
+public interface Listener {
+
+ /**
+ * Executor to excute this receive
+ *
+ * @return Executor
+ */
+ public Executor getExecutor();
+
+
+ /**
+ * 接收配置信息
+ *
+ * @param configInfo 配置值
+ */
+ public void receiveConfigInfo(final String configInfo);
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/exception/NacosException.java b/client/src/main/java/com/alibaba/nacos/api/exception/NacosException.java
new file mode 100644
index 00000000000..7c5ffecd83a
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/exception/NacosException.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.exception;
+
+/**
+ * Nacos Exception
+ *
+ * @author Nacos
+ *
+ */
+public class NacosException extends Exception{
+
+ /**
+ * serialVersionUID
+ */
+ private static final long serialVersionUID = -3913902031489277776L;
+
+ private int errCode;
+
+ private String errMsg;
+
+ public NacosException() {
+ };
+
+ public NacosException(int errCode, String errMsg) {
+ this.errCode = errCode;
+ this.errMsg = errMsg;
+ }
+
+ public int getErrCode() {
+ return errCode;
+ }
+
+ public String getErrMsg() {
+ return errMsg;
+ }
+
+ public void setErrCode(int errCode) {
+ this.errCode = errCode;
+ }
+
+ public void setErrMsg(String errMsg) {
+ this.errMsg = errMsg;
+ }
+
+ @Override
+ public String toString() {
+ return "ErrCode:" + errCode + ",ErrMsg:" + errMsg;
+ }
+
+ /**
+ * client error code
+ * -400 -503 throw exception to user
+ */
+ /**
+ * invalid param(参数错误)
+ */
+ public static final int CLIENT_INVALID_PARAM = -400;
+ /**
+ * over client threshold(超过server端的限流阈值)
+ */
+ public static final int CLIENT_OVER_THRESHOLD = -503;
+
+
+ /**
+ * server error code
+ * 400 403 throw exception to user
+ * 500 502 503 change ip and retry
+ */
+
+ /**
+ * invalid param(参数错误)
+ */
+ public static final int INVALID_PARAM = 400;
+ /**
+ * no right(鉴权失败)
+ */
+ public static final int NO_RIGHT = 403;
+ /**
+ * conflict(写并发冲突)
+ */
+ public static final int CONFLICT = 409;
+ /**
+ * server error(server异常,如超时)
+ */
+ public static final int SERVER_ERROR = 500;
+ /**
+ * bad gateway(路由异常,如nginx后面的Server挂掉)
+ */
+ public static final int BAD_GATEWAY = 502;
+ /**
+ * over threshold(超过server端的限流阈值)
+ */
+ public static final int OVER_THRESHOLD = 503;
+
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/naming/NamingFactory.java b/client/src/main/java/com/alibaba/nacos/api/naming/NamingFactory.java
new file mode 100644
index 00000000000..2607f05d7b9
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/naming/NamingFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.naming;
+
+import java.util.Properties;
+
+import com.alibaba.nacos.client.naming.NacosNamingService;
+
+/**
+ * @author dungu.zpf
+ */
+public class NamingFactory {
+
+ public static NamingService createNamingService(String serverList) {
+ return new NacosNamingService(serverList);
+ }
+
+ public static NamingService createNamingService(Properties properties) {
+ return new NacosNamingService(properties);
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/naming/NamingService.java b/client/src/main/java/com/alibaba/nacos/api/naming/NamingService.java
new file mode 100644
index 00000000000..a8f9763ae99
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/naming/NamingService.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.naming;
+
+import java.util.List;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.naming.listener.EventListener;
+import com.alibaba.nacos.api.naming.pojo.Instance;
+
+/**
+ * @author dungu.zpf
+ */
+public interface NamingService {
+
+ /**
+ * Register a instance to service
+ *
+ * @param serviceName name of service
+ * @param ip instance ip
+ * @param port instance port
+ * @throws NacosException
+ */
+ void registerInstance(String serviceName, String ip, int port) throws NacosException;
+
+ /**
+ * Register a instance to service with specified cluster name
+ *
+ * @param serviceName name of service
+ * @param ip instance ip
+ * @param port instance port
+ * @param clusterName instance cluster name
+ * @throws NacosException
+ */
+ void registerInstance(String serviceName, String ip, int port, String clusterName) throws NacosException;
+
+ /**
+ * Register a instance to service with specified instance properties
+ *
+ * @param serviceName name of service
+ * @param instance instance to register
+ * @throws NacosException
+ */
+ void registerInstance(String serviceName, Instance instance) throws NacosException;
+
+ /**
+ * Deregister instance from a service
+ *
+ * @param serviceName name of service
+ * @param ip instance ip
+ * @param port instance port
+ * @throws NacosException
+ */
+ void deregisterInstance(String serviceName, String ip, int port) throws NacosException;
+
+ /**
+ * Deregister instance with specified cluster name from a service
+ *
+ * @param serviceName name of service
+ * @param ip instance ip
+ * @param port instance port
+ * @param clusterName instance cluster name
+ * @throws NacosException
+ */
+ void deregisterInstance(String serviceName, String ip, int port, String clusterName) throws NacosException;
+
+ /**
+ * Get all instances of a service
+ *
+ * @param serviceName name of service
+ * @return A list of instance
+ * @throws NacosException
+ */
+ List getAllInstances(String serviceName) throws NacosException;
+
+ /**
+ * Get all instances within specified clusters of a service
+ *
+ * @param serviceName name of service
+ * @param clusters list of cluster
+ * @return A list of qualified instance
+ * @throws NacosException
+ */
+ List getAllInstances(String serviceName, List clusters) throws NacosException;
+
+ /**
+ * Get qualified instances of service
+ *
+ * @param serviceName name of service
+ * @param healthy a flag to indicate returning healthy or unhealthy instances
+ * @return A qualified list of instance
+ * @throws NacosException
+ */
+ List selectInstances(String serviceName, boolean healthy) throws NacosException;
+
+ /**
+ * Get qualified instances within specified clusters of service
+ *
+ * @param serviceName name of service
+ * @param clusters list of cluster
+ * @param healthy a flag to indicate returning healthy or unhealthy instances
+ * @return A qualified list of instance
+ * @throws NacosException
+ */
+ List selectInstances(String serviceName, List clusters, boolean healthy) throws NacosException;
+
+ /**
+ * Select one healthy instance of service using predefined load balance strategy
+ *
+ * @param serviceName name of service
+ * @return qualified instance
+ * @throws NacosException
+ */
+ Instance selectOneHealthyInstance(String serviceName) throws NacosException;
+
+ /**
+ * Select one healthy instance of service using predefined load balance strategy
+ *
+ * @param serviceName name of service
+ * @param clusters a list of clusters should the instance belongs to
+ * @return qualified instance
+ * @throws NacosException
+ */
+ Instance selectOneHealthyInstance(String serviceName, List clusters) throws NacosException;
+
+ /**
+ * Subscribe service to receive events of instances alteration
+ *
+ * @param serviceName name of service
+ * @param listener event listener
+ * @throws NacosException
+ */
+ void subscribe(String serviceName, EventListener listener) throws NacosException;
+
+ /**
+ * Subscribe service to receive events of instances alteration
+ *
+ * @param serviceName name of service
+ * @param clusters list of cluster
+ * @param listener event listener
+ * @throws NacosException
+ */
+ void subscribe(String serviceName, List clusters, EventListener listener) throws NacosException;
+
+ /**
+ * Unsubscribe event listener of service
+ *
+ * @param serviceName name of service
+ * @param listener event listener
+ * @throws NacosException
+ */
+ void unsubscribe(String serviceName, EventListener listener) throws NacosException;
+
+ /**
+ * Unsubscribe event listener of service
+ *
+ * @param serviceName name of service
+ * @param clusters list of cluster
+ * @param listener event listener
+ * @throws NacosException
+ */
+ void unsubscribe(String serviceName, List clusters, EventListener listener) throws NacosException;
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/naming/listener/Event.java b/client/src/main/java/com/alibaba/nacos/api/naming/listener/Event.java
new file mode 100644
index 00000000000..224d1ce60a2
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/naming/listener/Event.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.naming.listener;
+
+/**
+ * event interface
+ * @author dungu.zpf
+ */
+public interface Event {
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/naming/listener/EventListener.java b/client/src/main/java/com/alibaba/nacos/api/naming/listener/EventListener.java
new file mode 100644
index 00000000000..b0f0b94201c
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/naming/listener/EventListener.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.naming.listener;
+
+/**
+ * event listener
+ * @author Nacos
+ *
+ */
+public interface EventListener {
+ /**
+ * callback event
+ * @param event
+ */
+ void onEvent(Event event);
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/naming/listener/NamingEvent.java b/client/src/main/java/com/alibaba/nacos/api/naming/listener/NamingEvent.java
new file mode 100644
index 00000000000..94b42a95463
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/naming/listener/NamingEvent.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.naming.listener;
+
+import java.util.List;
+
+import com.alibaba.nacos.api.naming.pojo.Instance;
+
+/**
+ * @author dungu.zpf
+ */
+public class NamingEvent implements Event {
+
+ private String serviceName;
+
+ private List instances;
+
+ public NamingEvent(String serviceName, List instances) {
+ this.serviceName = serviceName;
+ this.instances = instances;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public void setServiceName(String serviceName) {
+ this.serviceName = serviceName;
+ }
+
+ public List getInstances() {
+ return instances;
+ }
+
+ public void setInstances(List instances) {
+ this.instances = instances;
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/naming/pojo/AbstractHealthChecker.java b/client/src/main/java/com/alibaba/nacos/api/naming/pojo/AbstractHealthChecker.java
new file mode 100644
index 00000000000..f6a46e57ded
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/naming/pojo/AbstractHealthChecker.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.naming.pojo;
+
+import com.alibaba.nacos.client.naming.utils.StringUtils;
+
+import java.util.Objects;
+
+/**
+ * @author dungu.zpf
+ */
+public abstract class AbstractHealthChecker implements Cloneable {
+
+ protected String type = "unknown";
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public static class Http extends AbstractHealthChecker {
+ public static final String TYPE = "HTTP";
+
+ private String path = StringUtils.EMPTY;
+ private String headers = StringUtils.EMPTY;
+
+ private int expectedResponseCode = 200;
+
+ public Http() {
+ this.type = TYPE;
+ }
+
+ public int getExpectedResponseCode() {
+ return expectedResponseCode;
+ }
+
+ public void setExpectedResponseCode(int expectedResponseCode) {
+ this.expectedResponseCode = expectedResponseCode;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public String getHeaders() {
+ return headers;
+ }
+
+ public void setHeaders(String headers) {
+ this.headers = headers;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(path, headers, expectedResponseCode);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Http)) {
+ return false;
+ }
+
+ Http other = (Http) obj;
+
+ if (!StringUtils.equals(type, other.getType())) {
+ return false;
+ }
+
+ if (!StringUtils.equals(path, other.getPath())) {
+ return false;
+ }
+ if (!StringUtils.equals(headers, other.getHeaders())) {
+ return false;
+ }
+ return expectedResponseCode == other.getExpectedResponseCode();
+ }
+ }
+
+ public static class Tcp extends AbstractHealthChecker {
+ public static final String TYPE = "TCP";
+
+ public Tcp() {
+ this.type = TYPE;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(TYPE);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof Tcp;
+
+ }
+ }
+
+ public static class Mysql extends AbstractHealthChecker {
+ public static final String TYPE = "MYSQL";
+
+ private String user;
+ private String pwd;
+ private String cmd;
+
+ public Mysql() {
+ this.type = TYPE;
+ }
+
+ public String getCmd() {
+ return cmd;
+ }
+
+ public String getPwd() {
+ return pwd;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public void setUser(String user) {
+ this.user = user;
+ }
+
+ public void setCmd(String cmd) {
+ this.cmd = cmd;
+ }
+
+ public void setPwd(String pwd) {
+ this.pwd = pwd;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(user, pwd, cmd);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Mysql)) {
+ return false;
+ }
+
+ Mysql other = (Mysql) obj;
+
+ if (!StringUtils.equals(user, other.getUser())) {
+ return false;
+ }
+
+ if (!StringUtils.equals(pwd, other.getPwd())) {
+ return false;
+ }
+
+ return StringUtils.equals(cmd, other.getCmd());
+
+ }
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/naming/pojo/Cluster.java b/client/src/main/java/com/alibaba/nacos/api/naming/pojo/Cluster.java
new file mode 100644
index 00000000000..eec4a3e1b05
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/naming/pojo/Cluster.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.naming.pojo;
+
+import com.alibaba.nacos.client.naming.utils.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author dungu.zpf
+ */
+public class Cluster {
+
+ /**
+ * Name of belonging service
+ */
+ private String serviceName;
+
+ /**
+ * Name of cluster
+ */
+ private String name = StringUtils.EMPTY;
+
+ /**
+ * Health check config of this cluster
+ */
+ private AbstractHealthChecker healthChecker = new AbstractHealthChecker.Tcp();
+
+ /**
+ * Default registered port for instances in this cluster.
+ */
+ private int defaultPort = 80;
+
+ /**
+ * Default health check port of instances in this cluster.
+ */
+ private int defaultCheckPort = 80;
+
+ /**
+ * Whether or not use instance port to do health check.
+ */
+ private boolean useIPPort4Check = true;
+
+
+ private Map metadata = new HashMap<>();
+
+ public Cluster() {
+
+ }
+
+ public Cluster(String clusterName) {
+ this.name = clusterName;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public void setServiceName(String serviceName) {
+ this.serviceName = serviceName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public AbstractHealthChecker getHealthChecker() {
+ return healthChecker;
+ }
+
+ public void setHealthChecker(AbstractHealthChecker healthChecker) {
+ this.healthChecker = healthChecker;
+ }
+
+ public int getDefaultPort() {
+ return defaultPort;
+ }
+
+ public void setDefaultPort(int defaultPort) {
+ this.defaultPort = defaultPort;
+ }
+
+ public int getDefaultCheckPort() {
+ return defaultCheckPort;
+ }
+
+ public void setDefaultCheckPort(int defaultCheckPort) {
+ this.defaultCheckPort = defaultCheckPort;
+ }
+
+ public boolean isUseIPPort4Check() {
+ return useIPPort4Check;
+ }
+
+ public void setUseIPPort4Check(boolean useIPPort4Check) {
+ this.useIPPort4Check = useIPPort4Check;
+ }
+
+ public Map getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(Map metadata) {
+ this.metadata = metadata;
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/naming/pojo/Instance.java b/client/src/main/java/com/alibaba/nacos/api/naming/pojo/Instance.java
new file mode 100644
index 00000000000..55ecfaa044d
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/naming/pojo/Instance.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.naming.pojo;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.annotation.JSONField;
+import com.alibaba.nacos.client.naming.utils.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author dungu.zpf
+ */
+public class Instance {
+
+ /**
+ * Unique ID of this instance.
+ */
+ private String instanceId;
+
+ /**
+ * Instance ip
+ */
+ private String ip;
+
+ /**
+ * Instance port
+ */
+ private int port;
+
+ /**
+ * Instance weight
+ */
+ private double weight = 1.0D;
+
+ /**
+ * Instance health status
+ */
+ @JSONField(name = "valid")
+ private boolean healthy = true;
+
+ /**
+ * Cluster information of instance
+ */
+ @JSONField(serialize = false)
+ private Cluster cluster = new Cluster();
+
+ /**
+ * Service information of instance
+ */
+ @JSONField(serialize = false)
+ private Service service;
+
+ /**
+ * User extended attributes
+ */
+ private Map metadata = new HashMap<>();
+
+ public String getInstanceId() {
+ return instanceId;
+ }
+
+ public void setInstanceId(String instanceId) {
+ this.instanceId = instanceId;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public double getWeight() {
+ return weight;
+ }
+
+ public void setWeight(double weight) {
+ this.weight = weight;
+ }
+
+ public boolean isHealthy() {
+ return healthy;
+ }
+
+ public void setHealthy(boolean healthy) {
+ this.healthy = healthy;
+ }
+
+ public Cluster getCluster() {
+ return cluster;
+ }
+
+ public void setCluster(Cluster cluster) {
+ this.cluster = cluster;
+ }
+
+ public Service getService() {
+ return service;
+ }
+
+ public void setService(Service service) {
+ this.service = service;
+ }
+
+ public Map getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(Map metadata) {
+ this.metadata = metadata;
+ }
+
+ public void addMetadata(String key, String value) {
+ this.metadata.put(key, value);
+ }
+
+ @Override
+ public String toString() {
+ return JSON.toJSONString(this);
+ }
+
+ public String toInetAddr() {
+ return ip + ":" + port;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Instance)) {
+ return false;
+ }
+
+ Instance host = (Instance) obj;
+
+ return StringUtils.equals(toString(), host.toString());
+ }
+
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/api/naming/pojo/Service.java b/client/src/main/java/com/alibaba/nacos/api/naming/pojo/Service.java
new file mode 100644
index 00000000000..e5274f1cb2d
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/api/naming/pojo/Service.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.api.naming.pojo;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author dungu.zpf
+ */
+public class Service {
+
+ /**
+ * Service name
+ */
+ private String name;
+
+ /**
+ * Protect threshold
+ */
+ private float protectThreshold = 0.0F;
+
+ /**
+ * Application name of this service
+ */
+ private String app;
+
+ /**
+ * Service group which is meant to classify services into different sets.
+ */
+ private String group;
+
+ /**
+ * Health check mode.
+ */
+ private String healthCheckMode;
+
+ public Service(String name) {
+ this.name = name;
+ }
+
+ private Map metadata = new HashMap<>();
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getHealthCheckMode() {
+ return healthCheckMode;
+ }
+
+ public void setHealthCheckMode(String healthCheckMode) {
+ this.healthCheckMode = healthCheckMode;
+ }
+
+ public float getProtectThreshold() {
+ return protectThreshold;
+ }
+
+ public void setProtectThreshold(float protectThreshold) {
+ this.protectThreshold = protectThreshold;
+ }
+
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ public String getGroup() {
+ return group;
+ }
+
+ public void setGroup(String group) {
+ this.group = group;
+ }
+
+ public Map getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(Map metadata) {
+ this.metadata = metadata;
+ }
+
+ public void addMetadata(String key, String value) {
+ this.metadata.put(key, value);
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java b/client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java
new file mode 100644
index 00000000000..3b4953e1039
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.config;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import com.alibaba.nacos.api.PropertyKeyConst;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.Listener;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.client.config.common.Constants;
+import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
+import com.alibaba.nacos.client.config.filter.impl.ConfigRequest;
+import com.alibaba.nacos.client.config.filter.impl.ConfigResponse;
+import com.alibaba.nacos.client.config.impl.ClientWorker;
+import com.alibaba.nacos.client.config.impl.LocalConfigInfoProcessor;
+import com.alibaba.nacos.client.config.impl.ServerHttpAgent;
+import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
+import com.alibaba.nacos.client.config.utils.ContentUtils;
+import com.alibaba.nacos.client.config.utils.LogUtils;
+import com.alibaba.nacos.client.config.utils.ParamUtils;
+import com.alibaba.nacos.client.config.utils.TenantUtil;
+import com.alibaba.nacos.client.logger.Logger;
+import com.alibaba.nacos.client.logger.support.LoggerHelper;
+import com.alibaba.nacos.client.utils.StringUtils;
+
+/**
+ * Config Impl
+ * @author Nacos
+ *
+ */
+@SuppressWarnings("PMD.ServiceOrDaoClassShouldEndWithImplRule")
+public class NacosConfigService implements ConfigService {
+
+ final static public Logger log = LogUtils.logger(NacosConfigService.class);
+ public final long POST_TIMEOUT = 3000L;
+ /**
+ * http agent
+ */
+ private ServerHttpAgent agent;
+ /**
+ * longpulling
+ */
+ private ClientWorker worker;
+ private String namespace;
+ private String encode;
+ private ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager();
+
+ public NacosConfigService(Properties properties) throws NacosException {
+ String encodeTmp = properties.getProperty(PropertyKeyConst.ENCODE);
+ if (StringUtils.isBlank(encodeTmp)) {
+ encode = Constants.ENCODE;
+ } else {
+ encode = encodeTmp.trim();
+ }
+ String namespaceTmp = properties.getProperty(PropertyKeyConst.NAMESPACE);
+ if (StringUtils.isBlank(namespaceTmp)) {
+ namespace = TenantUtil.getUserTenant();
+ properties.put(PropertyKeyConst.NAMESPACE, namespace);
+ } else {
+ namespace = namespaceTmp;
+ properties.put(PropertyKeyConst.NAMESPACE, namespace);
+ }
+ agent = new ServerHttpAgent(properties);
+ agent.start();
+ worker = new ClientWorker(agent, configFilterChainManager);
+ }
+
+ @Override
+ public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {
+ return getConfigInner(namespace, dataId, group, timeoutMs);
+ }
+
+ @Override
+ public void addListener(String dataId, String group, Listener listener) throws NacosException {
+ worker.addTenantListeners(dataId, group, Arrays.asList(listener));
+ }
+
+ @Override
+ public boolean publishConfig(String dataId, String group, String content) throws NacosException {
+ return publishConfigInner(namespace, dataId, group, null, null, null, content);
+ }
+
+ @Override
+ public boolean removeConfig(String dataId, String group) throws NacosException {
+ return removeConfigInner(namespace, dataId, group, null);
+ }
+
+ @Override
+ public void removeListener(String dataId, String group, Listener listener) {
+ worker.removeTenantListener(dataId, group, listener);
+ }
+
+ private String getConfigInner(String tenant, String dataId, String group, long timeoutMs) throws NacosException {
+ group = null2defaultGroup(group);
+ ParamUtils.checkKeyParam(dataId, group);
+ ConfigResponse cr = new ConfigResponse();
+
+ cr.setDataId(dataId);
+ cr.setTenant(tenant);
+ cr.setGroup(group);
+
+ // 优先使用本地配置
+ String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
+ if (content != null) {
+ log.warn(agent.getName(), "[get-config] get failover ok, dataId={}, group={}, tenant={}, config={}", dataId,
+ group, tenant, ContentUtils.truncateContent(content));
+ cr.setContent(content);
+ configFilterChainManager.doFilter(null, cr);
+ content = cr.getContent();
+ return content;
+ }
+
+ try {
+ content = worker.getServerConfig(dataId, group, tenant, timeoutMs);
+ cr.setContent(content);
+ configFilterChainManager.doFilter(null, cr);
+ content = cr.getContent();
+ return content;
+ } catch (NacosException ioe) {
+ if (NacosException.NO_RIGHT == ioe.getErrCode()) {
+ throw ioe;
+ }
+ log.warn("NACOS-0003",
+ LoggerHelper.getErrorCodeStr("NACOS", "NACOS-0003", "环境问题", "get from server error"));
+ log.warn(agent.getName(), "[get-config] get from server error, dataId={}, group={}, tenant={}, msg={}",
+ dataId, group, tenant, ioe.toString());
+ }
+
+ log.warn(agent.getName(), "[get-config] get snapshot ok, dataId={}, group={}, tenant={}, config={}", dataId,
+ group, tenant, ContentUtils.truncateContent(content));
+ content = LocalConfigInfoProcessor.getSnapshot(agent.getName(), dataId, group, tenant);
+ cr.setContent(content);
+ configFilterChainManager.doFilter(null, cr);
+ content = cr.getContent();
+ return content;
+ }
+
+ private String null2defaultGroup(String group) {
+ return (null == group) ? Constants.DEFAULT_GROUP : group.trim();
+ }
+
+ private boolean removeConfigInner(String tenant, String dataId, String group, String tag) throws NacosException {
+ group = null2defaultGroup(group);
+ ParamUtils.checkKeyParam(dataId, group);
+ String url = Constants.CONFIG_CONTROLLER_PATH;
+ List params = new ArrayList();
+ params.add("dataId");
+ params.add(dataId);
+ params.add("group");
+ params.add(group);
+ if (StringUtils.isNotEmpty(tenant)) {
+ params.add("tenant");
+ params.add(tenant);
+ }
+ if (StringUtils.isNotEmpty(tag)) {
+ params.add("tag");
+ params.add(tag);
+ }
+ HttpResult result = null;
+ try {
+ result = agent.httpDelete(url, null, params, encode, POST_TIMEOUT);
+ } catch (IOException ioe) {
+ log.warn("[remove] error, " + dataId + ", " + group + ", " + tenant + ", msg: " + ioe.toString());
+ return false;
+ }
+
+ if (HttpURLConnection.HTTP_OK == result.code) {
+ log.info(agent.getName(), "[remove] ok, dataId={}, group={}, tenant={}", dataId, group, tenant);
+ return true;
+ } else if (HttpURLConnection.HTTP_FORBIDDEN == result.code) {
+ log.warn(agent.getName(), "[remove] error, dataId={}, group={}, tenant={}, code={}, msg={}", dataId, group,
+ tenant, result.code, result.content);
+ throw new NacosException(result.code, result.content);
+ } else {
+ log.warn(agent.getName(), "[remove] error, dataId={}, group={}, tenant={}, code={}, msg={}", dataId, group,
+ tenant, result.code, result.content);
+ return false;
+ }
+ }
+
+ private boolean publishConfigInner(String tenant, String dataId, String group, String tag, String appName,
+ String betaIps, String content) throws NacosException {
+ group = null2defaultGroup(group);
+ ParamUtils.checkParam(dataId, group, content);
+
+ ConfigRequest cr = new ConfigRequest();
+ cr.setDataId(dataId);
+ cr.setTenant(tenant);
+ cr.setGroup(group);
+ cr.setContent(content);
+ configFilterChainManager.doFilter(cr, null);
+ content = cr.getContent();
+
+ String url = Constants.CONFIG_CONTROLLER_PATH;
+ List params = new ArrayList();
+ params.add("dataId");
+ params.add(dataId);
+ params.add("group");
+ params.add(group);
+ params.add("content");
+ params.add(content);
+ if (StringUtils.isNotEmpty(tenant)) {
+ params.add("tenant");
+ params.add(tenant);
+ }
+ if (StringUtils.isNotEmpty(appName)) {
+ params.add("appName");
+ params.add(appName);
+ }
+ if (StringUtils.isNotEmpty(tag)) {
+ params.add("tag");
+ params.add(tag);
+ }
+
+ List headers = new ArrayList();
+ if (StringUtils.isNotEmpty(betaIps)) {
+ headers.add("betaIps");
+ headers.add(betaIps);
+ }
+
+ HttpResult result = null;
+ try {
+ result = agent.httpPost(url, headers, params, encode, POST_TIMEOUT);
+ } catch (IOException ioe) {
+ log.warn("NACOS-0006",
+ LoggerHelper.getErrorCodeStr("NACOS", "NACOS-0006", "环境问题", "[publish-single] exception"));
+ log.warn(agent.getName(), "[publish-single] exception, dataId={}, group={}, msg={}", dataId, group,
+ ioe.toString());
+ return false;
+ }
+
+ if (HttpURLConnection.HTTP_OK == result.code) {
+ log.info(agent.getName(), "[publish-single] ok, dataId={}, group={}, tenant={}, config={}", dataId, group,
+ tenant, ContentUtils.truncateContent(content));
+ return true;
+ } else if (HttpURLConnection.HTTP_FORBIDDEN == result.code) {
+ log.warn(agent.getName(), "[publish-single] error, dataId={}, group={}, tenant={}, code={}, msg={}", dataId,
+ group, tenant, result.code, result.content);
+ throw new NacosException(result.code, result.content);
+ } else {
+ log.warn(agent.getName(), "[publish-single] error, dataId={}, group={}, tenant={}, code={}, msg={}", dataId,
+ group, tenant, result.code, result.content);
+ return false;
+ }
+
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/common/Constants.java b/client/src/main/java/com/alibaba/nacos/client/config/common/Constants.java
new file mode 100644
index 00000000000..6fe35f92315
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/config/common/Constants.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.config.common;
+
+/**
+ * Constant
+ *
+ * @author Nacos
+ *
+ */
+public class Constants {
+
+ public static final String CLIENT_VERSION_HEADER = "Client-Version";
+
+ public static final String CLIENT_VERSION = "3.0.0";
+
+ public static int DATA_IN_BODY_VERSION = 204;
+
+ public static final String DEFAULT_GROUP = "DEFAULT_GROUP";
+
+ public static final String APPNAME = "AppName";
+
+ public static final String UNKNOWN_APP = "UnknownApp";
+
+ public static final String DEFAULT_DOMAINNAME = "commonconfig.config-host.taobao.com";
+
+ public static final String DAILY_DOMAINNAME = "commonconfig.taobao.net";
+
+ public static final int DEFAULT_PORT = 8080;
+
+ public static final String NULL = "";
+
+ public static final String DATAID = "dataId";
+
+ public static final String GROUP = "group";
+
+ public static final String LAST_MODIFIED = "Last-Modified";
+
+ public static final String ACCEPT_ENCODING = "Accept-Encoding";
+
+ public static final String CONTENT_ENCODING = "Content-Encoding";
+
+ public static final String PROBE_MODIFY_REQUEST = "Listening-Configs";
+
+ public static final String PROBE_MODIFY_RESPONSE = "Probe-Modify-Response";
+
+ public static final String PROBE_MODIFY_RESPONSE_NEW = "Probe-Modify-Response-New";
+
+ public static final String USE_ZIP = "true";
+
+ public static final String CONTENT_MD5 = "Content-MD5";
+
+ public static final String CONFIG_VERSION = "Config-Version";
+
+ public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
+
+ public static final String SPACING_INTERVAL = "client-spacing-interval";
+
+ public static final String BASE_PATH = "/v1/cs";
+
+ public static final String CONFIG_CONTROLLER_PATH = BASE_PATH + "/configs";
+
+ /**
+ * second
+ */
+ public static final int ASYNC_UPDATE_ADDRESS_INTERVAL = 300;
+
+ /**
+ * second
+ */
+ public static final int POLLING_INTERVAL_TIME = 15;
+
+ /**
+ * millisecond
+ */
+ public static final int ONCE_TIMEOUT = 2000;
+
+ /**
+ * millisecond
+ */
+ public static final int CONN_TIMEOUT = 2000;
+
+ /**
+ * millisecond
+ */
+ public static final int SO_TIMEOUT = 60000;
+
+ /**
+ * millisecond
+ */
+ public static final int RECV_WAIT_TIMEOUT = ONCE_TIMEOUT * 5;
+
+ public static final String ENCODE = "UTF-8";
+
+ public static final String MAP_FILE = "map-file.js";
+
+ public static final int FLOW_CONTROL_THRESHOLD = 20;
+
+ public static final int FLOW_CONTROL_SLOT = 10;
+
+ public static final int FLOW_CONTROL_INTERVAL = 1000;
+
+ public static final String LINE_SEPARATOR = Character.toString((char) 1);
+
+ public static final String WORD_SEPARATOR = Character.toString((char) 2);
+
+ public static final String LONGPULLING_LINE_SEPARATOR = "\r\n";
+
+ public static final String CLIENT_APPNAME_HEADER = "Client-AppName";
+ public static final String CLIENT_REQUEST_TS_HEADER = "Client-RequestTS";
+ public static final String CLIENT_REQUEST_TOKEN_HEADER = "Client-RequestToken";
+
+ public static final int ATOMIC_MAX_SIZE = 1000;
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/common/GroupKey.java b/client/src/main/java/com/alibaba/nacos/client/config/common/GroupKey.java
new file mode 100644
index 00000000000..fce61eddc38
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/config/common/GroupKey.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.config.common;
+
+import com.alibaba.nacos.client.utils.StringUtils;
+
+/**
+ * Synthesize the form of dataId+groupId. Escapes reserved characters in dataId
+ * and groupId.
+ *
+ * @author Nacos
+ */
+public class GroupKey {
+
+ static public String getKey(String dataId, String group) {
+ StringBuilder sb = new StringBuilder();
+ urlEncode(dataId, sb);
+ sb.append('+');
+ urlEncode(group, sb);
+ return sb.toString();
+ }
+
+ static public String getKeyTenant(String dataId, String group, String tenant) {
+ StringBuilder sb = new StringBuilder();
+ urlEncode(dataId, sb);
+ sb.append('+');
+ urlEncode(group, sb);
+ if (StringUtils.isNotEmpty(tenant)) {
+ sb.append('+');
+ urlEncode(tenant, sb);
+ }
+ return sb.toString();
+ }
+
+ static public String getKey(String dataId, String group, String datumStr) {
+ StringBuilder sb = new StringBuilder();
+ urlEncode(dataId, sb);
+ sb.append('+');
+ urlEncode(group, sb);
+ sb.append('+');
+ urlEncode(datumStr, sb);
+ return sb.toString();
+ }
+
+ static public String[] parseKey(String groupKey) {
+ StringBuilder sb = new StringBuilder();
+ String dataId = null;
+ String group = null;
+ String tenant = null;
+
+ for (int i = 0; i < groupKey.length(); ++i) {
+ char c = groupKey.charAt(i);
+ if ('+' == c) {
+ if (null == dataId) {
+ dataId = sb.toString();
+ sb.setLength(0);
+ } else if (null == group) {
+ group = sb.toString();
+ sb.setLength(0);
+ } else {
+ throw new IllegalArgumentException("invalid groupkey:" + groupKey);
+ }
+ } else if ('%' == c) {
+ char next = groupKey.charAt(++i);
+ char nextnext = groupKey.charAt(++i);
+ if ('2' == next && 'B' == nextnext) {
+ sb.append('+');
+ } else if ('2' == next && '5' == nextnext) {
+ sb.append('%');
+ } else {
+ throw new IllegalArgumentException("invalid groupkey:" + groupKey);
+ }
+ } else {
+ sb.append(c);
+ }
+ }
+
+ if (StringUtils.isBlank(group)) {
+ group = sb.toString();
+ if (group.length() == 0) {
+ throw new IllegalArgumentException("invalid groupkey:" + groupKey);
+ }
+ } else {
+ tenant = sb.toString();
+ if (group.length() == 0) {
+ throw new IllegalArgumentException("invalid groupkey:" + groupKey);
+ }
+ }
+
+ return new String[] { dataId, group, tenant };
+ }
+
+ /**
+ * + -> %2B
+ * % -> %25
+ */
+ static void urlEncode(String str, StringBuilder sb) {
+ for (int idx = 0; idx < str.length(); ++idx) {
+ char c = str.charAt(idx);
+ if ('+' == c) {
+ sb.append("%2B");
+ } else if ('%' == c) {
+ sb.append("%25");
+ } else {
+ sb.append(c);
+ }
+ }
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigContext.java b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigContext.java
new file mode 100644
index 00000000000..23c65f6ec3e
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigContext.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.config.filter.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.alibaba.nacos.api.config.filter.IConfigContext;
+
+/**
+ * Config Context
+ *
+ * @author Nacos
+ *
+ */
+public class ConfigContext implements IConfigContext {
+
+ private Map param = new HashMap();
+
+ @Override
+ public Object getParameter(String key) {
+ return param.get(key);
+ }
+
+ @Override
+ public void setParameter(String key, Object value) {
+ param.put(key, value);
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManager.java b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManager.java
new file mode 100644
index 00000000000..1566113ed80
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManager.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.config.filter.impl;
+
+import java.util.List;
+
+import com.alibaba.nacos.api.config.filter.IConfigFilter;
+import com.alibaba.nacos.api.config.filter.IConfigFilterChain;
+import com.alibaba.nacos.api.config.filter.IConfigRequest;
+import com.alibaba.nacos.api.config.filter.IConfigResponse;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.google.common.collect.Lists;
+
+/**
+ * Config Filter Chain Management
+ *
+ * @author Nacos
+ *
+ */
+public class ConfigFilterChainManager implements IConfigFilterChain {
+
+ private List filters = Lists.newArrayList();
+
+ public synchronized ConfigFilterChainManager addFilter(IConfigFilter filter) {
+ // 根据order大小顺序插入
+ int i = 0;
+ while (i < this.filters.size()) {
+ IConfigFilter currentValue = this.filters.get(i);
+ if (currentValue.getFilterName().equals(filter.getFilterName())) {
+ break;
+ }
+ if (filter.getOrder() >= currentValue.getOrder() && i < this.filters.size()) {
+ i++;
+ } else {
+ this.filters.add(i, filter);
+ break;
+ }
+ }
+
+ if (i == this.filters.size()) {
+ this.filters.add(i, filter);
+ }
+ return this;
+ }
+
+
+ @Override
+ public void doFilter(IConfigRequest request, IConfigResponse response) throws NacosException {
+ new VirtualFilterChain(this.filters).doFilter(request, response);
+ }
+
+ private static class VirtualFilterChain implements IConfigFilterChain {
+
+ private final List extends IConfigFilter> additionalFilters;
+
+ private int currentPosition = 0;
+
+ public VirtualFilterChain(List extends IConfigFilter> additionalFilters) {
+ this.additionalFilters = additionalFilters;
+ }
+
+ @Override
+ public void doFilter(final IConfigRequest request, final IConfigResponse response) throws NacosException {
+ if (this.currentPosition == this.additionalFilters.size()) {
+ return;
+ } else {
+ this.currentPosition++;
+ IConfigFilter nextFilter = this.additionalFilters.get(this.currentPosition - 1);
+ nextFilter.doFilter(request, response, this);
+ }
+ }
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigRequest.java b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigRequest.java
new file mode 100644
index 00000000000..100b10d39c2
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigRequest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.config.filter.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.alibaba.nacos.api.config.filter.IConfigContext;
+import com.alibaba.nacos.api.config.filter.IConfigRequest;
+
+/**
+ * Config Request
+ *
+ * @author Nacos
+ *
+ */
+public class ConfigRequest implements IConfigRequest {
+
+ private Map param = new HashMap();
+
+ private IConfigContext configContext = new ConfigContext();
+
+ public String getTenant() {
+ return (String) param.get("tenant");
+ }
+
+ public void setTenant(String tenant) {
+ param.put("tenant", tenant);
+ }
+
+ public String getDataId() {
+ return (String) param.get("dataId");
+ }
+
+ public void setDataId(String dataId) {
+ param.put("dataId", dataId);
+ }
+
+ public String getGroup() {
+ return (String) param.get("group");
+ }
+
+ public void setGroup(String group) {
+ param.put("group", group);
+ }
+
+ public String getContent() {
+ return (String) param.get("content");
+ }
+
+ public void setContent(String content) {
+ param.put("content", content);
+ }
+
+ @Override
+ public Object getParameter(String key) {
+ return param.get(key);
+ }
+
+ @Override
+ public IConfigContext getConfigContext() {
+ return configContext;
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigResponse.java b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigResponse.java
new file mode 100644
index 00000000000..c864331cc6b
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigResponse.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.config.filter.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.alibaba.nacos.api.config.filter.IConfigContext;
+import com.alibaba.nacos.api.config.filter.IConfigResponse;
+
+/**
+ * Config Response
+ *
+ * @author Nacos
+ *
+ */
+public class ConfigResponse implements IConfigResponse {
+
+ private Map param = new HashMap();
+
+ private IConfigContext configContext = new ConfigContext();
+
+ public String getTenant() {
+ return (String) param.get("tenant");
+ }
+
+ public void setTenant(String tenant) {
+ param.put("tenant", tenant);
+ }
+
+ public String getDataId() {
+ return (String) param.get("dataId");
+ }
+
+ public void setDataId(String dataId) {
+ param.put("dataId", dataId);
+ }
+
+ public String getGroup() {
+ return (String) param.get("group");
+ }
+
+ public void setGroup(String group) {
+ param.put("group", group);
+ }
+
+ public String getContent() {
+ return (String) param.get("content");
+ }
+
+ public void setContent(String content) {
+ param.put("content", content);
+ }
+
+ @Override
+ public Object getParameter(String key) {
+ return param.get(key);
+ }
+
+ @Override
+ public IConfigContext getConfigContext() {
+ return configContext;
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/CacheData.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/CacheData.java
new file mode 100644
index 00000000000..008c810205c
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/CacheData.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.config.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import com.alibaba.nacos.api.config.listener.AbstractSharedListener;
+import com.alibaba.nacos.api.config.listener.Listener;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.client.config.common.Constants;
+import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
+import com.alibaba.nacos.client.config.filter.impl.ConfigResponse;
+import com.alibaba.nacos.client.config.utils.LogUtils;
+import com.alibaba.nacos.client.config.utils.MD5;
+import com.alibaba.nacos.client.config.utils.TenantUtil;
+import com.alibaba.nacos.client.logger.Logger;
+
+/**
+ * Listner Management
+ *
+ * @author Nacos
+ *
+ */
+public class CacheData {
+
+ final static public Logger log = LogUtils.logger(CacheData.class);
+
+ public boolean isInitializing() {
+ return isInitializing;
+ }
+
+ public void setInitializing(boolean isInitializing) {
+ this.isInitializing = isInitializing;
+ }
+
+ public String getMd5() {
+ return md5;
+ }
+
+ public String getTenant() {
+ return tenant;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String newContent) {
+ this.content = newContent;
+ this.md5 = getMd5String(content);
+ }
+
+ /**
+ * Add listener
+ *
+ * @param listener
+ * listener
+ */
+ public void addListener(Listener listener) {
+ if (null == listener) {
+ throw new IllegalArgumentException("listener is null");
+ }
+ ManagerListenerWrap wrap = new ManagerListenerWrap(listener);
+ if (listeners.addIfAbsent(wrap)) {
+ log.info(name, "[add-listener] ok, tenant={}, dataId={}, group={}, cnt={}", tenant, dataId, group,
+ listeners.size());
+ }
+ }
+
+ public void removeListener(Listener listener) {
+ if (null == listener) {
+ throw new IllegalArgumentException("listener is null");
+ }
+ ManagerListenerWrap wrap = new ManagerListenerWrap(listener);
+ if (listeners.remove(wrap)) {
+ log.info(name, "[remove-listener] ok, dataId={}, group={}, cnt={}", dataId, group, listeners.size());
+ }
+ }
+
+ /**
+ * 返回监听器列表上的迭代器,只读。保证不返回NULL。
+ */
+ public List getListeners() {
+ List result = new ArrayList();
+ for (ManagerListenerWrap wrap : listeners) {
+ result.add(wrap.listener);
+ }
+ return result;
+ }
+
+
+ public long getLocalConfigInfoVersion() {
+ return localConfigLastModified;
+ }
+ public void setLocalConfigInfoVersion(long localConfigLastModified) {
+ this.localConfigLastModified = localConfigLastModified;
+ }
+
+
+ public boolean isUseLocalConfigInfo() {
+ return isUseLocalConfig;
+ }
+ public void setUseLocalConfigInfo(boolean useLocalConfigInfo) {
+ this.isUseLocalConfig = useLocalConfigInfo;
+ if (!useLocalConfigInfo) {
+ localConfigLastModified = -1;
+ }
+ }
+
+ public int getTaskId() {
+ return taskId;
+ }
+
+ public void setTaskId(int taskId) {
+ this.taskId = taskId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((dataId == null) ? 0 : dataId.hashCode());
+ result = prime * result + ((group == null) ? 0 : group.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (null == obj || obj.getClass() != getClass()) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ CacheData other = (CacheData) obj;
+ return dataId.equals(other.dataId) && group.equals(other.group);
+ }
+
+ @Override
+ public String toString() {
+ return "CacheData [" + dataId + ", " + group + "]";
+ }
+
+ void checkListenerMd5() {
+ for (ManagerListenerWrap wrap : listeners) {
+ if (!md5.equals(wrap.lastCallMd5)) {
+ safeNotifyListener(dataId, group, content, md5, wrap);
+ }
+ }
+ }
+
+ private void safeNotifyListener(final String dataId, final String group, final String content,
+ final String md5, final ManagerListenerWrap listenerWrap) {
+ final Listener listener = listenerWrap.listener;
+
+ Runnable job = new Runnable() {
+ public void run() {
+ ClassLoader myClassLoader = Thread.currentThread().getContextClassLoader();
+ ClassLoader appClassLoader= listener.getClass().getClassLoader();
+ try {
+ if(listener instanceof AbstractSharedListener){
+ AbstractSharedListener adapter = (AbstractSharedListener) listener;
+ adapter.fillContext(dataId, group);
+ log.info(name, "[notify-context] dataId={}, group={}, md5={}", dataId, group, md5);
+ }
+ // 执行回调之前先将线程classloader设置为具体webapp的classloader,以免回调方法中调用spi接口是出现异常或错用(多应用部署才会有该问题)。
+ Thread.currentThread().setContextClassLoader(appClassLoader);
+
+ ConfigResponse cr = new ConfigResponse();
+ cr.setDataId(dataId);
+ cr.setGroup(group);
+ cr.setContent(content);
+ configFilterChainManager.doFilter(null, cr);
+ String contentTmp = cr.getContent();
+ listener.receiveConfigInfo(contentTmp);
+ listenerWrap.lastCallMd5 = md5;
+ log.info(
+ name,
+ "[notify-ok] dataId={}, group={}, md5={}, listener={} ",
+ dataId, group, md5, listener);
+ } catch (NacosException de) {
+ log.error(name, "NACOS-XXXX",
+ "[notify-error] dataId={}, group={}, md5={}, listener={} errCode={} errMsg={}", dataId,
+ group, md5, listener, de.getErrCode(), de.getErrMsg());
+ } catch (Throwable t) {
+ log.error(name, "NACOS-XXXX",
+ "[notify-error] dataId={}, group={}, md5={}, listener={} tx={}", dataId, group, md5,
+ listener, t.getCause());
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader(myClassLoader);
+ }
+ }
+ };
+
+ final long startNotify = System.currentTimeMillis();
+ try {
+ if (null != listener.getExecutor()) {
+ listener.getExecutor().execute(job);
+ } else {
+ job.run();
+ }
+ } catch (Throwable t) {
+ log.error(
+ name,
+ "NACOS-XXXX",
+ "[notify-error] dataId={}, group={}, md5={}, listener={} throwable={}",
+ dataId, group, md5, listener, t.getCause());
+ }
+ final long finishNotify = System.currentTimeMillis();
+ log.info(name, "[notify-listener] time cost={}ms in ClientWorker, dataId={}, group={}, md5={}, listener={} ",(finishNotify - startNotify), dataId ,group, md5, listener);
+ }
+
+ static public String getMd5String(String config) {
+ return (null == config) ? Constants.NULL : MD5.getInstance().getMD5String(config);
+ }
+
+ private String loadCacheContentFromDiskLocal(String name, String dataId, String group, String tenant) {
+ String content = LocalConfigInfoProcessor.getFailover(name, dataId, group, tenant);
+ content = (null != content) ? content
+ : LocalConfigInfoProcessor.getSnapshot(name, dataId, group, tenant);
+ return content;
+ }
+
+ public CacheData(ConfigFilterChainManager configFilterChainManager, String name, String dataId, String group) {
+ if (null == dataId || null == group) {
+ throw new IllegalArgumentException("dataId=" + dataId + ", group=" + group);
+ }
+ this.name = name;
+ this.configFilterChainManager = configFilterChainManager;
+ this.dataId = dataId;
+ this.group = group;
+ this.tenant = TenantUtil.getUserTenant();
+ listeners = new CopyOnWriteArrayList();
+ this.isInitializing = true;
+ this.content = loadCacheContentFromDiskLocal(name, dataId, group, tenant);
+ this.md5 = getMd5String(content);
+ }
+
+ public CacheData(ConfigFilterChainManager configFilterChainManager, String name, String dataId, String group, String tenant) {
+ if (null == dataId || null == group) {
+ throw new IllegalArgumentException("dataId=" + dataId + ", group=" + group);
+ }
+ this.name = name;
+ this.configFilterChainManager = configFilterChainManager;
+ this.dataId = dataId;
+ this.group = group;
+ this.tenant = tenant;
+ listeners = new CopyOnWriteArrayList();
+ this.isInitializing = true;
+ this.content = loadCacheContentFromDiskLocal(name, dataId, group, tenant);
+ this.md5 = getMd5String(content);
+ }
+
+ // ==================
+
+ private final String name;
+ private final ConfigFilterChainManager configFilterChainManager;
+ public final String dataId;
+ public final String group;
+ public final String tenant;
+ private final CopyOnWriteArrayList listeners;
+
+ private volatile String md5;
+ /**
+ * whether use local config
+ */
+ private volatile boolean isUseLocalConfig = false;
+ /**
+ * last motify time
+ */
+ private volatile long localConfigLastModified;
+ private volatile String content;
+ private int taskId;
+ private volatile boolean isInitializing = true;
+}
+
+class ManagerListenerWrap {
+ final Listener listener;
+ String lastCallMd5 = CacheData.getMd5String(null);
+
+ ManagerListenerWrap(Listener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (null == obj || obj.getClass() != getClass()) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ ManagerListenerWrap other = (ManagerListenerWrap) obj;
+ return listener.equals(other.listener);
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java
new file mode 100644
index 00000000000..5f60a81fc51
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java
@@ -0,0 +1,541 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.config.impl;
+
+import static com.alibaba.nacos.client.config.common.Constants.LINE_SEPARATOR;
+import static com.alibaba.nacos.client.config.common.Constants.WORD_SEPARATOR;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import com.alibaba.nacos.api.config.listener.Listener;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.client.config.common.Constants;
+import com.alibaba.nacos.client.config.common.GroupKey;
+import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
+import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
+import com.alibaba.nacos.client.config.utils.ContentUtils;
+import com.alibaba.nacos.client.config.utils.LogUtils;
+import com.alibaba.nacos.client.config.utils.MD5;
+import com.alibaba.nacos.client.config.utils.TenantUtil;
+import com.alibaba.nacos.client.logger.Logger;
+import com.alibaba.nacos.client.logger.support.LoggerHelper;
+import com.alibaba.nacos.client.utils.ParamUtil;
+import com.alibaba.nacos.client.utils.StringUtils;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+/**
+ * Longpulling
+ *
+ * @author Nacos
+ *
+ */
+public class ClientWorker {
+
+ final static public Logger log = LogUtils.logger(ClientWorker.class);
+
+ public void addListeners(String dataId, String group, List extends Listener> listeners) {
+ group = null2defaultGroup(group);
+ CacheData cache = addCacheDataIfAbsent(dataId, group);
+ for (Listener listener : listeners) {
+ cache.addListener(listener);
+ }
+ }
+
+ public void removeListener(String dataId, String group, Listener listener) {
+ group = null2defaultGroup(group);
+ CacheData cache = getCache(dataId, group);
+ if (null != cache) {
+ cache.removeListener(listener);
+ if (cache.getListeners().isEmpty()) {
+ removeCache(dataId, group);
+ }
+ }
+ }
+
+ public void addTenantListeners(String dataId, String group, List extends Listener> listeners) {
+ group = null2defaultGroup(group);
+ String tenant = agent.getTenant();
+ CacheData cache = addCacheDataIfAbsent(dataId, group, tenant);
+ for (Listener listener : listeners) {
+ cache.addListener(listener);
+ }
+ }
+
+ public void removeTenantListener(String dataId, String group, Listener listener) {
+ group = null2defaultGroup(group);
+ String tenant = agent.getTenant();
+ CacheData cache = getCache(dataId, group, tenant);
+ if (null != cache) {
+ cache.removeListener(listener);
+ if (cache.getListeners().isEmpty()) {
+ removeCache(dataId, group, tenant);
+ }
+ }
+ }
+
+ @SuppressFBWarnings("JLM_JSR166_UTILCONCURRENT_MONITORENTER")
+ void removeCache(String dataId, String group) {
+ String groupKey = GroupKey.getKey(dataId, group);
+ synchronized (cacheMap) {
+ Map copy = new HashMap(cacheMap.get());
+ copy.remove(groupKey);
+ cacheMap.set(copy);
+ }
+ log.info(agent.getName(), "[unsubscribe] {}", groupKey);
+ }
+
+ @SuppressFBWarnings("JLM_JSR166_UTILCONCURRENT_MONITORENTER")
+ void removeCache(String dataId, String group, String tenant) {
+ String groupKey = GroupKey.getKeyTenant(dataId, group, tenant);
+ synchronized (cacheMap) {
+ Map copy = new HashMap(cacheMap.get());
+ copy.remove(groupKey);
+ cacheMap.set(copy);
+ }
+ log.info(agent.getName(), "[unsubscribe] {}", groupKey);
+ }
+
+ @SuppressFBWarnings("JLM_JSR166_UTILCONCURRENT_MONITORENTER")
+ public CacheData addCacheDataIfAbsent(String dataId, String group) {
+ CacheData cache = getCache(dataId, group);
+ if (null != cache) {
+ return cache;
+ }
+
+ String key = GroupKey.getKey(dataId, group);
+ cache = new CacheData(configFilterChainManager, agent.getName(), dataId, group);
+
+ synchronized (cacheMap) {
+ CacheData cacheFromMap = getCache(dataId, group);
+ // multiple listeners on the same dataid+group and race condition,so double check again
+ //other listener thread beat me to set to cacheMap
+ if(null != cacheFromMap) {
+ cache = cacheFromMap;
+ //reset so that server not hang this check
+ cache.setInitializing(true);
+ } else {
+ int taskId = cacheMap.get().size() / (int) ParamUtil.getPerTaskConfigSize();
+ cache.setTaskId(taskId);
+ }
+
+ Map copy = new HashMap(cacheMap.get());
+ copy.put(key, cache);
+ cacheMap.set(copy);
+ }
+
+ log.info(agent.getName(), "[subscribe] {}", key);
+
+ return cache;
+ }
+ @SuppressFBWarnings("JLM_JSR166_UTILCONCURRENT_MONITORENTER")
+ public CacheData addCacheDataIfAbsent(String dataId, String group, String tenant) {
+ CacheData cache = getCache(dataId, group, tenant);
+ if (null != cache) {
+ return cache;
+ }
+ String key = GroupKey.getKeyTenant(dataId, group, tenant);
+ cache = new CacheData(configFilterChainManager, agent.getName(), dataId, group, tenant);
+ synchronized (cacheMap) {
+ CacheData cacheFromMap = getCache(dataId, group, tenant);
+ // multiple listeners on the same dataid+group and race condition,so
+ // double check again
+ // other listener thread beat me to set to cacheMap
+ if (null != cacheFromMap) {
+ cache = cacheFromMap;
+ // reset so that server not hang this check
+ cache.setInitializing(true);
+ }
+
+ Map copy = new HashMap(cacheMap.get());
+ copy.put(key, cache);
+ cacheMap.set(copy);
+ }
+ log.info(agent.getName(), "[subscribe] {}", key);
+ return cache;
+ }
+
+ public CacheData getCache(String dataId, String group) {
+ return getCache(dataId, group, TenantUtil.getUserTenant());
+ }
+
+ public CacheData getCache(String dataId, String group, String tenant) {
+ if (null == dataId || null == group) {
+ throw new IllegalArgumentException();
+ }
+ return cacheMap.get().get(GroupKey.getKeyTenant(dataId, group, tenant));
+ }
+
+
+ public String getServerConfig(String dataId, String group, String tenant, long readTimeout)
+ throws NacosException {
+ if (StringUtils.isBlank(group)) {
+ group = Constants.DEFAULT_GROUP;
+ }
+
+ HttpResult result = null;
+ try {
+ List params = null;
+ if (StringUtils.isBlank(tenant)) {
+ params = Arrays.asList("dataId", dataId, "group", group);
+ } else {
+ params = Arrays.asList("dataId", dataId, "group", group, "tenant", tenant);
+ }
+ result = agent.httpGet(Constants.CONFIG_CONTROLLER_PATH, null, params, agent.getEncode(), readTimeout);
+ } catch (IOException e) {
+ log.error(agent.getName(), "NACOS-XXXX",
+ "[sub-server] get server config exception, dataId={}, group={}, tenant={}, msg={}", dataId, group,
+ tenant, e.toString());
+ throw new NacosException(NacosException.SERVER_ERROR, e.getMessage());
+ }
+
+ switch (result.code) {
+ case HttpURLConnection.HTTP_OK:
+ LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, result.content);
+ return result.content;
+ case HttpURLConnection.HTTP_NOT_FOUND:
+ LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, null);
+ return null;
+ case HttpURLConnection.HTTP_CONFLICT: {
+ log.error(agent.getName(), "NACOS-XXXX",
+ "[sub-server-error] get server config being modified concurrently, dataId={}, group={}, tenant={}",
+ dataId, group, tenant);
+ throw new NacosException(NacosException.CONFLICT,
+ "data being modified, dataId=" + dataId + ",group=" + group + ",tenant=" + tenant);
+ }
+ case HttpURLConnection.HTTP_FORBIDDEN: {
+ log.error(agent.getName(), "NACOS-XXXX", "[sub-server-error] no right, dataId={}, group={}, tenant={}",
+ dataId, group, tenant);
+ throw new NacosException(result.code, result.content);
+ }
+ default: {
+ log.error(agent.getName(), "NACOS-XXXX", "[sub-server-error] dataId={}, group={}, tenant={}, code={}",
+ dataId, group, tenant, result.code);
+ throw new NacosException(result.code,
+ "http error, code=" + result.code + ",dataId=" + dataId + ",group=" + group + ",tenant=" + tenant);
+ }
+ }
+ }
+
+ private void checkLocalConfig(CacheData cacheData) {
+ final String dataId = cacheData.dataId;
+ final String group = cacheData.group;
+ final String tenant = cacheData.tenant;
+ File path = LocalConfigInfoProcessor.getFailoverFile(agent.getName(), dataId, group, tenant);
+
+ // 没有 -> 有
+ if (!cacheData.isUseLocalConfigInfo() && path.exists()) {
+ String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
+ String md5 = MD5.getInstance().getMD5String(content);
+ cacheData.setUseLocalConfigInfo(true);
+ cacheData.setLocalConfigInfoVersion(path.lastModified());
+ cacheData.setContent(content);
+
+ log.warn(agent.getName(),
+ "[failover-change] failover file created. dataId={}, group={}, tenant={}, md5={}, content={}",
+ dataId, group, tenant, md5, ContentUtils.truncateContent(content));
+ return;
+ }
+
+ // 有 -> 没有。不通知业务监听器,从server拿到配置后通知。
+ if (cacheData.isUseLocalConfigInfo() && !path.exists()) {
+ cacheData.setUseLocalConfigInfo(false);
+ log.warn(agent.getName(), "[failover-change] failover file deleted. dataId={}, group={}, tenant={}", dataId,
+ group, tenant);
+ return;
+ }
+
+ // 有变更
+ if (cacheData.isUseLocalConfigInfo() && path.exists()
+ && cacheData.getLocalConfigInfoVersion() != path.lastModified()) {
+ String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
+ String md5 = MD5.getInstance().getMD5String(content);
+ cacheData.setUseLocalConfigInfo(true);
+ cacheData.setLocalConfigInfoVersion(path.lastModified());
+ cacheData.setContent(content);
+ log.warn(agent.getName(),
+ "[failover-change] failover file changed. dataId={}, group={}, tenant={}, md5={}, content={}",
+ dataId, group, tenant, md5, ContentUtils.truncateContent(content));
+ return;
+ }
+ }
+
+ private String null2defaultGroup(String group) {
+ return (null == group) ? Constants.DEFAULT_GROUP : group.trim();
+ }
+
+ public void checkConfigInfo() {
+ // 分任务
+ int listenerSize = cacheMap.get().size();
+ // 向上取整为批数
+ int longingTaskCount = (int) Math.ceil(listenerSize / ParamUtil.getPerTaskConfigSize());
+ if (longingTaskCount > currentLongingTaskCount) {
+ for (int i = (int) currentLongingTaskCount; i < longingTaskCount; i++) {
+ // 要判断任务是否在执行 这块需要好好想想。 任务列表现在是无序的。变化过程可能有问题
+ executorService.execute(new LongPullingRunnable(i));
+ }
+ currentLongingTaskCount = longingTaskCount;
+ }
+ }
+
+ /**
+ * 从Server获取值变化了的DataID列表。返回的对象里只有dataId和group是有效的。 保证不返回NULL。
+ */
+ List checkUpdateDataIds(List cacheDatas, List inInitializingCacheList) {
+ StringBuilder sb = new StringBuilder();
+ for (CacheData cacheData : cacheDatas) {
+ if (!cacheData.isUseLocalConfigInfo()) {
+ sb.append(cacheData.dataId).append(WORD_SEPARATOR);
+ sb.append(cacheData.group).append(WORD_SEPARATOR);
+ if (StringUtils.isBlank(cacheData.tenant)) {
+ sb.append(cacheData.getMd5()).append(LINE_SEPARATOR);
+ } else {
+ sb.append(cacheData.getMd5()).append(WORD_SEPARATOR);
+ sb.append(cacheData.getTenant()).append(LINE_SEPARATOR);
+ }
+ if (cacheData.isInitializing()) {
+ // cacheData 首次出现在cacheMap中&首次check更新
+ inInitializingCacheList
+ .add(GroupKey.getKeyTenant(cacheData.dataId, cacheData.group, cacheData.tenant));
+ }
+ }
+ }
+ boolean isInitializingCacheList = !inInitializingCacheList.isEmpty();
+ return checkUpdateConfigStr(sb.toString(), isInitializingCacheList);
+ }
+
+ /**
+ * 从Server获取值变化了的DataID列表。返回的对象里只有dataId和group是有效的。 保证不返回NULL。
+ */
+ List checkUpdateConfigStr(String probeUpdateString, boolean isInitializingCacheList) {
+
+ List params = Arrays.asList(Constants.PROBE_MODIFY_REQUEST, probeUpdateString);
+ long timeout = TimeUnit.SECONDS.toMillis(30L);
+
+ List headers = new ArrayList(2);
+ headers.add("Long-Pulling-Timeout");
+ headers.add("" + timeout);
+
+ // told server do not hang me up if new initializing cacheData added in
+ if (isInitializingCacheList) {
+ headers.add("Long-Pulling-Timeout-No-Hangup");
+ headers.add("true");
+ }
+
+ if (StringUtils.isBlank(probeUpdateString)) {
+ return Collections.emptyList();
+ }
+
+ try {
+ HttpResult result = agent.httpPost(Constants.CONFIG_CONTROLLER_PATH + "/listener", headers, params,
+ agent.getEncode(), timeout);
+
+ if (HttpURLConnection.HTTP_OK == result.code) {
+ setHealthServer(true);
+ return parseUpdateDataIdResponse(result.content);
+ } else {
+ setHealthServer(false);
+ if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR) {
+ log.error("NACOS-0007", LoggerHelper.getErrorCodeStr("Nacos", "Nacos-0007", "环境问题",
+ "[check-update] get changed dataId error"));
+ }
+ log.error(agent.getName(), "NACOS-XXXX", "[check-update] get changed dataId error, code={}",
+ result.code);
+ }
+ } catch (IOException e) {
+ setHealthServer(false);
+ log.error(agent.getName(), "NACOS-XXXX", "[check-update] get changed dataId exception, msg={}",
+ e.toString());
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * 从HTTP响应拿到变化的groupKey。保证不返回NULL。
+ */
+ private List parseUpdateDataIdResponse(String response) {
+ if (StringUtils.isBlank(response)) {
+ return Collections.emptyList();
+ }
+
+ try {
+ response = URLDecoder.decode(response, "UTF-8");
+ } catch (Exception e) {
+ log.error(agent.getName(), "NACOS-XXXX", "[polling-resp] decode modifiedDataIdsString error", e);
+ }
+
+ List updateList = new LinkedList();
+
+ for (String dataIdAndGroup : response.split(LINE_SEPARATOR)) {
+ if (!StringUtils.isBlank(dataIdAndGroup)) {
+ String[] keyArr = dataIdAndGroup.split(WORD_SEPARATOR);
+ String dataId = keyArr[0];
+ String group = keyArr[1];
+ if (keyArr.length == 2) {
+ updateList.add(GroupKey.getKey(dataId, group));
+ log.info(agent.getName(), "[polling-resp] config changed. dataId={}, group={}", dataId, group);
+ } else if (keyArr.length == 3) {
+ String tenant = keyArr[2];
+ updateList.add(GroupKey.getKeyTenant(dataId, group, tenant));
+ log.info(agent.getName(), "[polling-resp] config changed. dataId={}, group={}, tenant={}", dataId,
+ group, tenant);
+ } else {
+ log.error(agent.getName(), "NACOS-XXXX", "[polling-resp] invalid dataIdAndGroup error",
+ dataIdAndGroup);
+ }
+ }
+ }
+ return updateList;
+ }
+
+ @SuppressWarnings("PMD.ThreadPoolCreationRule")
+ public ClientWorker(final ServerHttpAgent agent, final ConfigFilterChainManager configFilterChainManager) {
+ this.agent = agent;
+ this.configFilterChainManager = configFilterChainManager;
+ executor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(r);
+ t.setName("com.alibaba.nacos.client.Worker." + agent.getName());
+ t.setDaemon(true);
+ return t;
+ }
+ });
+
+ executorService = Executors.newCachedThreadPool(new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(r);
+ t.setName("com.alibaba.nacos.client.Worker.longPulling" + agent.getName());
+ t.setDaemon(true);
+ return t;
+ }
+ });
+
+ executor.scheduleWithFixedDelay(new Runnable() {
+ public void run() {
+ try {
+ checkConfigInfo();
+ } catch (Throwable e) {
+ log.error(agent.getName(), "NACOS-XXXX", "[sub-check] rotate check error", e);
+ }
+ }
+ }, 1L, 10L, TimeUnit.MILLISECONDS);
+ }
+
+ class LongPullingRunnable implements Runnable {
+ private int taskId;
+
+ public LongPullingRunnable(int taskId) {
+ this.taskId = taskId;
+ }
+
+ public void run() {
+ try {
+ List cacheDatas = new ArrayList();
+ // check failover config
+ for (CacheData cacheData : cacheMap.get().values()) {
+ if (cacheData.getTaskId() == taskId) {
+ cacheDatas.add(cacheData);
+ try {
+ checkLocalConfig(cacheData);
+ if (cacheData.isUseLocalConfigInfo()) {
+ cacheData.checkListenerMd5();
+ }
+ } catch (Exception e) {
+ log.error("NACOS-CLIENT", "get local config info error", e);
+ }
+ }
+ }
+
+ List inInitializingCacheList = new ArrayList();
+ // check server config
+ List changedGroupKeys = checkUpdateDataIds(cacheDatas, inInitializingCacheList);
+
+ for (String groupKey : changedGroupKeys) {
+ String[] key = GroupKey.parseKey(groupKey);
+ String dataId = key[0];
+ String group = key[1];
+ String tenant = null;
+ if (key.length == 3) {
+ tenant = key[2];
+ }
+ try {
+ String content = getServerConfig(dataId, group, tenant, 3000L);
+ CacheData cache = cacheMap.get().get(GroupKey.getKeyTenant(dataId, group, tenant));
+ cache.setContent(content);
+ log.info(agent.getName(), "[data-received] dataId={}, group={}, tenant={}, md5={}, content={}",
+ dataId, group, tenant, cache.getMd5(), ContentUtils.truncateContent(content));
+ } catch (NacosException ioe) {
+ log.error(agent.getName(), "NACOS-XXXX",
+ "[get-update] get changed config exception. dataId={}, group={}, tenant={}, msg={}",
+ dataId, group, tenant, ioe.toString());
+ }
+ }
+ for (CacheData cacheData : cacheDatas) {
+ if (!cacheData.isInitializing() || inInitializingCacheList
+ .contains(GroupKey.getKeyTenant(cacheData.dataId, cacheData.group, cacheData.tenant))) {
+ cacheData.checkListenerMd5();
+ cacheData.setInitializing(false);
+ }
+ }
+ inInitializingCacheList.clear();
+ } catch (Throwable e) {
+ log.error("500", "longPulling error", e);
+ } finally {
+ executorService.execute(this);
+ }
+ }
+ }
+
+ // =================
+
+ public boolean isHealthServer() {
+ return isHealthServer;
+ }
+
+ private void setHealthServer(boolean isHealthServer) {
+ this.isHealthServer = isHealthServer;
+ }
+
+ final ScheduledExecutorService executor;
+ final ExecutorService executorService;
+ /**
+ * groupKey -> cacheData
+ */
+ AtomicReference
+*
+* Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode
+* character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
+*
+*
+* This class is not thread-safe. Each thread should use its own instance.
+*
+*
+* @see RFC 2045
+* @author Apache Software Foundation
+* @since 1.0
+* @version $Revision: 1080712 $
+*/
+public class Base64 {
+
+ /**
+ * BASE32 characters are 6 bits in length.
+ * They are formed by taking a block of 3 octets to form a 24-bit string,
+ * which is converted into 4 BASE64 characters.
+ */
+ private static final int BITS_PER_ENCODED_BYTE = 6;
+ private static final int BYTES_PER_UNENCODED_BLOCK = 3;
+ private static final int BYTES_PER_ENCODED_BLOCK = 4;
+
+ /**
+ * Chunk separator per RFC 2045 section 2.1.
+ *
+ *
+ * N.B. The next major release may break compatibility and make this field private.
+ *
+ *
+ * @see RFC 2045 section 2.1
+ */
+ static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
+
+ /**
+ * This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet"
+ * equivalents as specified in Table 1 of RFC 2045.
+ *
+ * Thanks to "commons" project in ws.apache.org for this code.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ */
+ private static final byte[] STANDARD_ENCODE_TABLE = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+ };
+
+ /**
+ * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and /
+ * changed to - and _ to make the encoded Base64 results more URL-SAFE.
+ * This table is only used when the Base64's mode is set to URL-SAFE.
+ */
+ private static final byte[] URL_SAFE_ENCODE_TABLE = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
+ };
+
+ /**
+ * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified in
+ * Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64
+ * alphabet but fall within the bounds of the array are translated to -1.
+ *
+ * Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both
+ * URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit).
+ *
+ * Thanks to "commons" project in ws.apache.org for this code.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ */
+ private static final byte[] DECODE_TABLE = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+ };
+
+ /**
+ * Base64 uses 6-bit fields.
+ */
+ /** Mask used to extract 6 bits, used when encoding */
+ private static final int MASK_6BITS = 0x3f;
+
+ // The static final fields above are used for the original static byte[] methods on Base64.
+ // The private member fields below are used with the new streaming approach, which requires
+ // some state be preserved between calls of encode() and decode().
+
+ /**
+ * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
+ * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
+ * between the two modes.
+ */
+ private final byte[] encodeTable;
+
+ /**
+ * Only one decode table currently; keep for consistency with Base32 code
+ */
+ private final byte[] decodeTable = DECODE_TABLE;
+
+ /**
+ * Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
+ */
+ private final byte[] lineSeparator;
+
+ /**
+ * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+ * decodeSize = 3 + lineSeparator.length;
+ */
+ private final int decodeSize;
+
+ /**
+ * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+ * encodeSize = 4 + lineSeparator.length;
+ */
+ private final int encodeSize;
+
+ /**
+ * Place holder for the bytes we're dealing with for our based logic.
+ * Bitwise operations store and extract the encoding or decoding from this variable.
+ */
+ private int bitWorkArea;
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+ *
+ * When encoding the line length is 0 (no chunking), and the encoding table is STANDARD_ENCODE_TABLE.
+ *
+ *
+ *
+ * When decoding all variants are supported.
+ *
+ */
+ public Base64() {
+ this(0, CHUNK_SEPARATOR, false);
+ }
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+ *
+ * When encoding the line length and line separator are given in the constructor, and the encoding table is
+ * STANDARD_ENCODE_TABLE.
+ *
+ *
+ * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
+ *
+ *
+ * When decoding all variants are supported.
+ *
+ *
+ * @param lineLength
+ * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
+ * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
+ * @param lineSeparator
+ * Each line of encoded data will end with this sequence of bytes.
+ * @param urlSafe
+ * Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode
+ * operations. Decoding seamlessly handles both modes.
+ * @throws IllegalArgumentException
+ * The provided lineSeparator included some base64 characters. That's not going to work!
+ * @since 1.4
+ */
+ public Base64(int lineLength, byte[] lineSeparator, boolean urlSafe) {
+ chunkSeparatorLength = lineSeparator == null ? 0 : lineSeparator.length;
+ unencodedBlockSize = BYTES_PER_UNENCODED_BLOCK;
+ encodedBlockSize = BYTES_PER_ENCODED_BLOCK;
+ this.lineLength = (lineLength > 0 && chunkSeparatorLength > 0) ? (lineLength / encodedBlockSize) * encodedBlockSize : 0;
+ // TODO could be simplified if there is no requirement to reject invalid line sep when length <=0
+ // @see test case Base64Test.testConstructors()
+ if (lineSeparator != null) {
+ if (containsAlphabetOrPad(lineSeparator)) {
+ String sep = null;
+ try {
+ sep = new String(lineSeparator, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ }
+ throw new IllegalArgumentException("lineSeparator must not contain base64 characters: [" + sep + "]");
+ }
+ if (lineLength > 0){
+ this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length;
+ this.lineSeparator = new byte[lineSeparator.length];
+ System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
+ } else {
+ this.encodeSize = BYTES_PER_ENCODED_BLOCK;
+ this.lineSeparator = null;
+ }
+ } else {
+ this.encodeSize = BYTES_PER_ENCODED_BLOCK;
+ this.lineSeparator = null;
+ }
+ this.decodeSize = this.encodeSize - 1;
+ this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;
+ }
+
+ /**
+ *
+ * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with
+ * the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, so flush last
+ * remaining bytes (if not multiple of 3).
+ *
+ *
+ * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ *
+ *
+ * @param in
+ * byte[] array of binary data to base64 encode.
+ * @param inPos
+ * Position to start reading data from.
+ * @param inAvail
+ * Amount of bytes available from input for encoding.
+ */
+ void encode(byte[] in, int inPos, int inAvail) {
+ if (eof) {
+ return;
+ }
+ if (inAvail < 0) {
+ eof = true;
+ if (0 == modulus && lineLength == 0) {
+ return;
+ }
+ ensureBufferSize(encodeSize);
+ int savedPos = pos;
+ switch (modulus) {
+ case 1 :
+ buffer[pos++] = encodeTable[(bitWorkArea >> 2) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea << 4) & MASK_6BITS];
+
+ if (encodeTable == STANDARD_ENCODE_TABLE) {
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ }
+ break;
+
+ case 2 :
+ buffer[pos++] = encodeTable[(bitWorkArea >> 10) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea >> 4) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea << 2) & MASK_6BITS];
+
+ if (encodeTable == STANDARD_ENCODE_TABLE) {
+ buffer[pos++] = PAD;
+ }
+ break;
+ default:
+ break;
+ }
+ currentLinePos += pos - savedPos;
+ /**
+ * if currentPos == 0 we are at the start of a line, so don't add CRLF
+ */
+ if (lineLength > 0 && currentLinePos > 0) {
+ System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
+ pos += lineSeparator.length;
+ }
+ } else {
+ for (int i = 0; i < inAvail; i++) {
+ ensureBufferSize(encodeSize);
+ modulus = (modulus+1) % BYTES_PER_UNENCODED_BLOCK;
+ int b = in[inPos++];
+ if (b < 0) {
+ b += 256;
+ }
+ bitWorkArea = (bitWorkArea << 8) + b;
+ if (0 == modulus) {
+ buffer[pos++] = encodeTable[(bitWorkArea >> 18) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea >> 12) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea >> 6) & MASK_6BITS];
+ buffer[pos++] = encodeTable[bitWorkArea & MASK_6BITS];
+ currentLinePos += BYTES_PER_ENCODED_BLOCK;
+ if (lineLength > 0 && lineLength <= currentLinePos) {
+ System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
+ pos += lineSeparator.length;
+ currentLinePos = 0;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ *
+ * Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once
+ * with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1"
+ * call is not necessary when decoding, but it doesn't hurt, either.
+ *
+ *
+ * Ignores all non-base64 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are
+ * silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in,
+ * garbage-out philosophy: it will not check the provided data for validity.
+ *
+ *
+ * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ *
+ *
+ * @param in
+ * byte[] array of ascii data to base64 decode.
+ * @param inPos
+ * Position to start reading data from.
+ * @param inAvail
+ * Amount of bytes available from input for encoding.
+ */
+ void decode(byte[] in, int inPos, int inAvail) {
+ if (eof) {
+ return;
+ }
+ if (inAvail < 0) {
+ eof = true;
+ }
+ for (int i = 0; i < inAvail; i++) {
+ ensureBufferSize(decodeSize);
+ byte b = in[inPos++];
+ if (b == PAD) {
+ // We're done.
+ eof = true;
+ break;
+ } else {
+ if (b >= 0 && b < DECODE_TABLE.length) {
+ int result = DECODE_TABLE[b];
+ if (result >= 0) {
+ modulus = (modulus+1) % BYTES_PER_ENCODED_BLOCK;
+ bitWorkArea = (bitWorkArea << BITS_PER_ENCODED_BYTE) + result;
+ if (modulus == 0) {
+ buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+ buffer[pos++] = (byte) (bitWorkArea & MASK_8BITS);
+ }
+ }
+ }
+ }
+ }
+
+ // Two forms of EOF as far as base64 decoder is concerned: actual
+ // EOF (-1) and first time '=' character is encountered in stream.
+ // This approach makes the '=' padding characters completely optional.
+ if (eof && modulus != 0) {
+ ensureBufferSize(decodeSize);
+
+ // We have some spare bits remaining
+ // Output all whole multiples of 8 bits and ignore the rest
+ switch (modulus) {
+ // case 1: // 6 bits - ignore entirely
+ // break;
+ case 2 :
+ bitWorkArea = bitWorkArea >> 4;
+ buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
+ break;
+ case 3 :
+ bitWorkArea = bitWorkArea >> 2;
+ buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm but does not chunk the output.
+ *
+ * @param binaryData
+ * binary data to encode
+ * @return byte[] containing Base64 characters in their UTF-8 representation.
+ */
+ public static byte[] encodeBase64(byte[] binaryData) {
+ return encodeBase64(binaryData, false, false, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
+ *
+ * @param binaryData
+ * Array containing binary data to encode.
+ * @param isChunked
+ * if true this encoder will chunk the base64 output into 76 character blocks
+ * @param urlSafe
+ * if true this encoder will emit - and _ instead of the usual + and / characters.
+ * @param maxResultSize
+ * The maximum result size to accept.
+ * @return Base64-encoded data.
+ * @throws IllegalArgumentException
+ * Thrown when the input array needs an output array bigger than maxResultSize
+ * @since 1.4
+ */
+ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe, int maxResultSize) {
+ if (binaryData == null || binaryData.length == 0) {
+ return binaryData;
+ }
+
+ // Create this so can use the super-class method
+ // Also ensures that the same roundings are performed by the ctor and the code
+ Base64 b64 = isChunked ? new Base64(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe);
+ long len = b64.getEncodedLength(binaryData);
+ if (len > maxResultSize) {
+ throw new IllegalArgumentException("Input array too big, the output array would be bigger (" +
+ len +
+ ") than the specified maximum size of " +
+ maxResultSize);
+ }
+
+ return b64.encode(binaryData);
+ }
+
+
+
+ /**
+ * Decodes Base64 data into octets
+ *
+ * @param base64Data
+ * Byte array containing Base64 data
+ * @return Array containing decoded data.
+ */
+ public static byte[] decodeBase64(byte[] base64Data) {
+ return new Base64().decode(base64Data);
+ }
+
+
+ /**
+ * Returns whether or not the octet is in the Base32 alphabet.
+ *
+ * @param octet
+ * The value to test
+ * @return true if the value is defined in the the Base32 alphabet false otherwise.
+ */
+ protected boolean isInAlphabet(byte octet) {
+ return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
+ }
+
+ /**
+ * Below from base class
+ */
+
+ /**
+ * MIME chunk size per RFC 2045 section 6.8.
+ *
+ *
+ * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
+ * equal signs.
+ *
+ *
+ * @see RFC 2045 section 6.8
+ */
+ private static final int MIME_CHUNK_SIZE = 76;
+
+ private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2;
+
+ /**
+ * Defines the default buffer size - currently {@value}
+ * - must be large enough for at least one encoded block+separator
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+ /** Mask used to extract 8 bits, used in decoding bytes */
+ private static final int MASK_8BITS = 0xff;
+
+ /**
+ * Byte used to pad output.
+ */
+ private static final byte PAD_DEFAULT = '=';
+
+ private static final byte PAD = PAD_DEFAULT;
+
+ /** Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32 */
+ private final int unencodedBlockSize;
+
+ /** Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32 */
+ private final int encodedBlockSize;
+
+ /**
+ * Chunksize for encoding. Not used when decoding.
+ * A value of zero or less implies no chunking of the encoded data.
+ * Rounded down to nearest multiple of encodedBlockSize.
+ */
+ private final int lineLength;
+
+ /**
+ * Size of chunk separator. Not used unless {@link #lineLength} > 0.
+ */
+ private final int chunkSeparatorLength;
+
+ /**
+ * Buffer for streaming.
+ */
+ private byte[] buffer;
+
+ /**
+ * Position where next character should be written in the buffer.
+ */
+ private int pos;
+
+ /**
+ * Position where next character should be read from the buffer.
+ */
+ private int readPos;
+
+ /**
+ * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this object becomes useless,
+ * and must be thrown away.
+ */
+ private boolean eof;
+
+ /**
+ * Variable tracks how many characters have been written to the current line. Only used when encoding. We use it to
+ * make sure each encoded line never goes beyond lineLength (if lineLength > 0).
+ */
+ private int currentLinePos;
+
+ /**
+ * Writes to the buffer only occur after every 3/5 reads when encoding, and every 4/8 reads when decoding.
+ * This variable helps track that.
+ */
+ private int modulus;
+
+ /**
+ * Ensure that the buffer has room for size bytes
+ *
+ * @param size minimum spare space required
+ */
+ private void ensureBufferSize(int size){
+ if ((buffer == null) || (buffer.length < pos + size)){
+ if (buffer == null) {
+ buffer = new byte[DEFAULT_BUFFER_SIZE];
+ pos = 0;
+ readPos = 0;
+ } else {
+ byte[] b = new byte[buffer.length * DEFAULT_BUFFER_RESIZE_FACTOR];
+ System.arraycopy(buffer, 0, b, 0, buffer.length);
+ buffer = b;
+ }
+ }
+ }
+
+ /**
+ * Extracts buffered data into the provided byte[] array, starting at position bPos,
+ * up to a maximum of bAvail bytes. Returns how many bytes were actually extracted.
+ *
+ * @param b
+ * byte[] array to extract the buffered data into.
+ * @param bPos
+ * position in byte[] array to start extraction at.
+ * @param bAvail
+ * amount of bytes we're allowed to extract. We may extract fewer (if fewer are available).
+ * @return The number of bytes successfully extracted into the provided byte[] array.
+ */
+ private int readResults(byte[] b, int bPos, int bAvail) {
+ if (buffer != null) {
+ int len = Math.min(pos - readPos, bAvail);
+ System.arraycopy(buffer, readPos, b, bPos, len);
+ readPos += len;
+ if (readPos >= pos) {
+ buffer = null;
+ }
+ return len;
+ }
+ return eof ? -1 : 0;
+ }
+
+ /**
+ * Resets this object to its initial newly constructed state.
+ */
+ private void reset() {
+ buffer = null;
+ pos = 0;
+ readPos = 0;
+ currentLinePos = 0;
+ modulus = 0;
+ eof = false;
+ }
+
+ /**
+ * Decodes a byte[] containing characters in the Base-N alphabet.
+ *
+ * @param pArray
+ * A byte array containing Base-N character data
+ * @return a byte array containing binary data
+ */
+ private byte[] decode(byte[] pArray) {
+ reset();
+ if (pArray == null || pArray.length == 0) {
+ return pArray;
+ }
+ decode(pArray, 0, pArray.length);
+ decode(pArray, 0, -1);
+ byte[] result = new byte[pos];
+ readResults(result, 0, result.length);
+ return result;
+ }
+
+ /**
+ * Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet.
+ *
+ * @param pArray
+ * a byte array containing binary data
+ * @return A byte array containing only the basen alphabetic character data
+ */
+ private byte[] encode(byte[] pArray) {
+ reset();
+ if (pArray == null || pArray.length == 0) {
+ return pArray;
+ }
+ encode(pArray, 0, pArray.length);
+ encode(pArray, 0, -1);
+ byte[] buf = new byte[pos - readPos];
+ readResults(buf, 0, buf.length);
+ return buf;
+ }
+
+ /**
+ * Tests a given byte array to see if it contains any characters within the alphabet or PAD.
+ *
+ * Intended for use in checking line-ending arrays
+ *
+ * @param arrayOctet
+ * byte array to test
+ * @return true if any byte is a valid character in the alphabet or PAD; false otherwise
+ */
+ private boolean containsAlphabetOrPad(byte[] arrayOctet) {
+ if (arrayOctet == null) {
+ return false;
+ }
+ for (int i = 0; i < arrayOctet.length; i++) {
+ if (PAD == arrayOctet[i] || isInAlphabet(arrayOctet[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Calculates the amount of space needed to encode the supplied array.
+ *
+ * @param pArray byte[] array which will later be encoded
+ *
+ * @return amount of space needed to encoded the supplied array.
+ * Returns a long since a max-len array will require > Integer.MAX_VALUE
+ */
+ private long getEncodedLength(byte[] pArray) {
+ // Calculate non-chunked size - rounded up to allow for padding
+ // cast to long is needed to avoid possibility of overflow
+ long len = ((pArray.length + unencodedBlockSize-1) / unencodedBlockSize) * (long) encodedBlockSize;
+ if (lineLength > 0) {
+ /**
+ * Round up to nearest multiple
+ */
+ len += ((len + lineLength-1) / lineLength) * chunkSeparatorLength;
+ }
+ return len;
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/identify/Constants.java b/client/src/main/java/com/alibaba/nacos/client/identify/Constants.java
new file mode 100644
index 00000000000..2f566f7549f
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/identify/Constants.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.identify;
+
+/**
+ * Identify Constants
+ *
+ * @author Nacos
+ *
+ */
+public class Constants {
+ public static final String ACCESS_KEY = "accessKey";
+
+ public static final String SECRET_KEY = "secretKey";
+
+ public static final String PROPERTIES_FILENAME = "spas.properties";
+
+ public static final String CREDENTIAL_PATH = "/home/admin/.spas_key/";
+
+ public static final String CREDENTIAL_DEFAULT = "default";
+
+ public static final String DOCKER_CREDENTIAL_PATH = "/etc/instanceInfo";
+
+ public static final String DOCKER_ACCESS_KEY = "env_spas_accessKey";
+
+ public static final String DOCKER_SECRET_KEY = "env_spas_secretKey";
+
+ public static final String ENV_ACCESS_KEY = "spas_accessKey";
+
+ public static final String ENV_SECRET_KEY = "spas_secretKey";
+
+ public static final String NO_APP_NAME = "";
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/identify/CredentialListener.java b/client/src/main/java/com/alibaba/nacos/client/identify/CredentialListener.java
new file mode 100644
index 00000000000..943facba928
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/identify/CredentialListener.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.identify;
+
+/**
+ * Credential Listener
+ *
+ * @author Nacos
+ *
+ */
+public interface CredentialListener {
+ /**
+ * update Credential
+ */
+ public void onUpdateCredential();
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/identify/CredentialService.java b/client/src/main/java/com/alibaba/nacos/client/identify/CredentialService.java
new file mode 100644
index 00000000000..cf8f792ca72
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/identify/CredentialService.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.identify;
+
+import com.alibaba.nacos.client.config.utils.LogUtils;
+import com.alibaba.nacos.client.logger.Logger;
+import com.alibaba.nacos.client.utils.StringUtils;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Credential Service
+ *
+ * @author Nacos
+ *
+ */
+public final class CredentialService implements SpasCredentialLoader {
+ static final public Logger log = LogUtils.logger(CredentialService.class);
+ private static ConcurrentHashMap instances = new ConcurrentHashMap();
+
+ private String appName;
+ private Credentials credentials = new Credentials();
+ private CredentialWatcher watcher;
+ private CredentialListener listener;
+
+ private CredentialService(String appName) {
+ if (appName == null) {
+ String value = System.getProperty("project.name");
+ if (StringUtils.isNotEmpty(value)) {
+ appName = value;
+ }
+ }
+ this.appName = appName;
+ watcher = new CredentialWatcher(appName, this);
+ }
+
+
+ public static CredentialService getInstance() {
+ return getInstance(null);
+ }
+
+ public static CredentialService getInstance(String appName) {
+ String key = appName != null ? appName : Constants.NO_APP_NAME;
+ CredentialService instance = instances.get(key);
+ if (instance == null) {
+ instance = new CredentialService(appName);
+ CredentialService previous = instances.putIfAbsent(key, instance);
+ if (previous != null) {
+ instance = previous;
+ }
+ }
+ return instance;
+ }
+
+ public static CredentialService freeInstance() {
+ return freeInstance(null);
+ }
+
+ public static CredentialService freeInstance(String appName) {
+ String key = appName != null ? appName : Constants.NO_APP_NAME;
+ CredentialService instance = instances.remove(key);
+ if (instance != null) {
+ instance.free();
+ }
+ return instance;
+ }
+
+ public void free() {
+ if (watcher != null) {
+ watcher.stop();
+ }
+ log.info(appName, this.getClass().getSimpleName() + " is freed");
+ }
+
+ public Credentials getCredential() {
+ Credentials localCredential = credentials;
+ if (localCredential.valid()) {
+ return localCredential;
+ }
+ return credentials;
+ }
+
+ public void setCredential(Credentials credential) {
+ boolean changed = !(credentials == credential || (credentials != null && credentials.identical(credential)));
+ credentials = credential;
+ if (changed && listener != null) {
+ listener.onUpdateCredential();
+ }
+ }
+
+ public void setStaticCredential(Credentials credential) {
+ if (watcher != null) {
+ watcher.stop();
+ }
+ setCredential(credential);
+ }
+
+ public void registerCredentialListener(CredentialListener listener) {
+ this.listener = listener;
+ }
+
+ @Deprecated
+ public void setAccessKey(String accessKey) {
+ credentials.setAccessKey(accessKey);
+ }
+
+ @Deprecated
+ public void setSecretKey(String secretKey) {
+ credentials.setSecretKey(secretKey);
+ }
+
+ @Deprecated
+ public String getAccessKey() {
+ return credentials.getAccessKey();
+ }
+
+ @Deprecated
+ public String getSecretKey() {
+ return credentials.getSecretKey();
+ }
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/identify/CredentialWatcher.java b/client/src/main/java/com/alibaba/nacos/client/identify/CredentialWatcher.java
new file mode 100644
index 00000000000..553849ba948
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/identify/CredentialWatcher.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.identify;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Properties;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import com.alibaba.nacos.client.config.utils.LogUtils;
+import com.alibaba.nacos.client.logger.Logger;
+import com.alibaba.nacos.client.utils.StringUtils;
+
+/**
+ * Credential Watcher
+ *
+ * @author Nacos
+ *
+ */
+public class CredentialWatcher {
+ static final public Logger SpasLogger = LogUtils.logger(CredentialWatcher.class);
+ private static final long REFRESH_INTERVAL = 10 * 1000;
+
+ private CredentialService serviceInstance;
+ private String appName;
+ private String propertyPath;
+ private TimerTask watcher;
+ private boolean stopped;
+
+ @SuppressWarnings("PMD.AvoidUseTimerRule")
+ public CredentialWatcher(String appName, CredentialService serviceInstance) {
+ this.appName = appName;
+ this.serviceInstance = serviceInstance;
+ loadCredential(true);
+ watcher = new TimerTask() {
+ private Timer timer = new Timer(true);
+ private long modified = 0;
+
+ {
+ timer.schedule(this, REFRESH_INTERVAL, REFRESH_INTERVAL);
+ }
+
+ @Override
+ public void run() {
+ synchronized (this) {
+ if (stopped) {
+ return;
+ }
+ boolean reload = false;
+ if (propertyPath == null) {
+ reload = true;
+ } else {
+ File file = new File(propertyPath);
+ long lastModified = file.lastModified();
+ if (modified != lastModified) {
+ reload = true;
+ modified = lastModified;
+ }
+ }
+ if (reload) {
+ loadCredential(false);
+ }
+ }
+ }
+ };
+ }
+
+ public void stop() {
+ if (stopped) {
+ return;
+ }
+ if (watcher != null) {
+ synchronized (watcher) {
+ watcher.cancel();
+ stopped = true;
+ }
+ }
+ SpasLogger.info(appName, this.getClass().getSimpleName() + " is stopped");
+ }
+
+ private void loadCredential(boolean init) {
+ boolean logWarn = init;
+ if (propertyPath == null) {
+ URL url = ClassLoader.getSystemResource(Constants.PROPERTIES_FILENAME);
+ if (url != null) {
+ propertyPath = url.getPath();
+ }
+ if (propertyPath == null || propertyPath.isEmpty()) {
+
+ String value = System.getProperty("spas.identity");
+ if (StringUtils.isNotEmpty(value)) {
+ propertyPath = value;
+ }
+ if (propertyPath == null || propertyPath.isEmpty()) {
+ propertyPath = Constants.CREDENTIAL_PATH + (appName == null ? Constants.CREDENTIAL_DEFAULT : appName);
+ }
+ else {
+ if (logWarn) {
+ SpasLogger.info(appName, "Defined credential file: -D" + "spas.identity" + "=" + propertyPath);
+ }
+ }
+ }
+ else {
+ if (logWarn) {
+ SpasLogger.info(appName, "Load credential file from classpath: " + Constants.PROPERTIES_FILENAME);
+ }
+ }
+ }
+
+ InputStream propertiesIS = null;
+ do {
+ try {
+ propertiesIS = new FileInputStream(propertyPath);
+ } catch (FileNotFoundException e) {
+ if (appName != null && !appName.equals(Constants.CREDENTIAL_DEFAULT) && propertyPath.equals(Constants.CREDENTIAL_PATH + appName)) {
+ propertyPath = Constants.CREDENTIAL_PATH + Constants.CREDENTIAL_DEFAULT;
+ continue;
+ }
+ if (!Constants.DOCKER_CREDENTIAL_PATH.equals(propertyPath)) {
+ propertyPath = Constants.DOCKER_CREDENTIAL_PATH;
+ continue;
+ }
+ }
+ break;
+ } while (true);
+
+ String accessKey = null;
+ String secretKey = null;
+ if (propertiesIS == null) {
+ propertyPath = null;
+ accessKey = System.getenv(Constants.ENV_ACCESS_KEY);
+ secretKey = System.getenv(Constants.ENV_SECRET_KEY);
+ if (accessKey == null && secretKey == null) {
+ if (logWarn) {
+ SpasLogger.info(appName, "No credential found");
+ }
+ return;
+ }
+ }
+ else {
+ Properties properties = new Properties();
+ try {
+ properties.load(propertiesIS);
+ } catch (IOException e) {
+ SpasLogger.error("26", "Unable to load credential file, appName:" + appName
+ + "Unable to load credential file " + propertyPath, e);
+ propertyPath = null;
+ return;
+ } finally {
+ try {
+ propertiesIS.close();
+ } catch (IOException e) {
+ SpasLogger.error("27", "Unable to close credential file, appName:" + appName
+ + "Unable to close credential file " + propertyPath, e);
+ }
+ }
+
+ if (logWarn) {
+ SpasLogger.info(appName, "Load credential file " + propertyPath);
+ }
+
+ if (!Constants.DOCKER_CREDENTIAL_PATH.equals(propertyPath)) {
+ if (properties.containsKey(Constants.ACCESS_KEY)) {
+ accessKey = properties.getProperty(Constants.ACCESS_KEY);
+ }
+ if (properties.containsKey(Constants.SECRET_KEY)) {
+ secretKey = properties.getProperty(Constants.SECRET_KEY);
+ }
+ } else {
+ if (properties.containsKey(Constants.DOCKER_ACCESS_KEY)) {
+ accessKey = properties.getProperty(Constants.DOCKER_ACCESS_KEY);
+ }
+ if (properties.containsKey(Constants.DOCKER_SECRET_KEY)) {
+ secretKey = properties.getProperty(Constants.DOCKER_SECRET_KEY);
+ }
+ }
+ }
+
+ if (accessKey != null) {
+ accessKey = accessKey.trim();
+ }
+ if (secretKey != null) {
+ secretKey = secretKey.trim();
+ }
+
+ Credentials credential = new Credentials(accessKey, secretKey);
+ if (!credential.valid()) {
+ SpasLogger.warn("1", "Credential file missing required property" + appName + "Credential file missing "
+ + Constants.ACCESS_KEY + " or " + Constants.SECRET_KEY);
+ propertyPath = null;
+ // return;
+ }
+
+ serviceInstance.setCredential(credential);
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/identify/Credentials.java b/client/src/main/java/com/alibaba/nacos/client/identify/Credentials.java
new file mode 100644
index 00000000000..f54100bf6b8
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/identify/Credentials.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.identify;
+
+/**
+ * Credentials
+ *
+ * @author Nacos
+ *
+ */
+public class Credentials implements SpasCredential {
+
+ private volatile String accessKey;
+
+ private volatile String secretKey;
+
+ public Credentials(String accessKey, String secretKey) {
+ this.accessKey = accessKey;
+ this.secretKey = secretKey;
+ }
+
+ public Credentials() {
+ this(null, null);
+ }
+
+ public String getAccessKey() {
+ return accessKey;
+ }
+
+ public void setAccessKey(String accessKey) {
+ this.accessKey = accessKey;
+ }
+
+ public String getSecretKey() {
+ return secretKey;
+ }
+
+ public void setSecretKey(String secretKey) {
+ this.secretKey = secretKey;
+ }
+
+ public boolean valid() {
+ return accessKey != null && !accessKey.isEmpty() && secretKey != null && !secretKey.isEmpty();
+ }
+
+ public boolean identical(Credentials other) {
+ return this == other ||
+ (other != null &&
+ (accessKey == null && other.accessKey == null || accessKey != null && accessKey.equals(other.accessKey)) &&
+ (secretKey == null && other.secretKey == null || secretKey != null && secretKey.equals(other.secretKey)));
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/identify/STSConfig.java b/client/src/main/java/com/alibaba/nacos/client/identify/STSConfig.java
new file mode 100644
index 00000000000..e555c535351
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/identify/STSConfig.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.identify;
+
+import com.alibaba.nacos.client.utils.StringUtils;
+
+/**
+ * Sts config
+ *
+ * @author Nacos
+ */
+@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
+public class STSConfig {
+ private static final String RAM_SECURITY_CREDENTIALS_URL
+ = "";
+ private String ramRoleName;
+ /**
+ * STS 临时凭证有效期剩余多少时开始刷新(允许本地时间比 STS 服务时间最多慢多久)
+ */
+ private int timeToRefreshInMillisecond = 3 * 60 * 1000;
+ /**
+ * 获取 STS 临时凭证的元数据接口(包含角色名称)
+ */
+ private String securityCredentialsUrl;
+ /**
+ * 设定 STS 临时凭证,不再通过元数据接口获取
+ */
+ private String securityCredentials;
+ /**
+ * 是否缓存
+ */
+ private boolean cacheSecurityCredentials = true;
+
+ private static class Singleton {
+ private static final STSConfig INSTANCE = new STSConfig();
+ }
+
+ private STSConfig() {
+ String ramRoleName = System.getProperty("ram.role.name");
+ if (!StringUtils.isBlank(ramRoleName)) {
+ setRamRoleName(ramRoleName);
+ }
+
+ String timeToRefreshInMillisecond = System.getProperty("time.to.refresh.in.millisecond");
+ if (!StringUtils.isBlank(timeToRefreshInMillisecond)) {
+ setTimeToRefreshInMillisecond(Integer.parseInt(timeToRefreshInMillisecond));
+ }
+
+ String securityCredentials = System.getProperty("security.credentials");
+ if (!StringUtils.isBlank(securityCredentials)) {
+ setSecurityCredentials(securityCredentials);
+ }
+
+ String securityCredentialsUrl = System.getProperty("security.credentials.url");
+ if (!StringUtils.isBlank(securityCredentialsUrl)) {
+ setSecurityCredentialsUrl(securityCredentialsUrl);
+ }
+
+ String cacheSecurityCredentials = System.getProperty("cache.security.credentials");
+ if (!StringUtils.isBlank(cacheSecurityCredentials)) {
+ setCacheSecurityCredentials(Boolean.valueOf(cacheSecurityCredentials));
+ }
+ }
+
+ public static STSConfig getInstance() {
+ return Singleton.INSTANCE;
+ }
+
+ public String getRamRoleName() {
+ return ramRoleName;
+ }
+
+ public void setRamRoleName(String ramRoleName) {
+ this.ramRoleName = ramRoleName;
+ }
+
+ public int getTimeToRefreshInMillisecond() {
+ return timeToRefreshInMillisecond;
+ }
+
+ public void setTimeToRefreshInMillisecond(int timeToRefreshInMillisecond) {
+ this.timeToRefreshInMillisecond = timeToRefreshInMillisecond;
+ }
+
+ public String getSecurityCredentialsUrl() {
+ if (securityCredentialsUrl == null && ramRoleName != null) {
+ return RAM_SECURITY_CREDENTIALS_URL + ramRoleName;
+ }
+ return securityCredentialsUrl;
+ }
+
+ public void setSecurityCredentialsUrl(String securityCredentialsUrl) {
+ this.securityCredentialsUrl = securityCredentialsUrl;
+ }
+
+ public String getSecurityCredentials() {
+ return securityCredentials;
+ }
+
+ public void setSecurityCredentials(String securityCredentials) {
+ this.securityCredentials = securityCredentials;
+ }
+
+ public boolean isSTSOn() {
+ return StringUtils.isNotEmpty(getSecurityCredentials()) || StringUtils.isNotEmpty(getSecurityCredentialsUrl());
+ }
+
+ public boolean isCacheSecurityCredentials() {
+ return cacheSecurityCredentials;
+ }
+
+ public void setCacheSecurityCredentials(boolean cacheSecurityCredentials) {
+ this.cacheSecurityCredentials = cacheSecurityCredentials;
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/identify/SpasCredential.java b/client/src/main/java/com/alibaba/nacos/client/identify/SpasCredential.java
new file mode 100644
index 00000000000..8d6a2bd919f
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/identify/SpasCredential.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.identify;
+
+/**
+ * Spas Credential Interface
+ *
+ * @author Nacos
+ *
+ */
+public interface SpasCredential {
+ /**
+ * get AccessKey
+ *
+ * @return AccessKey
+ */
+ public String getAccessKey();
+
+ /**
+ * get SecretKey
+ *
+ * @return SecretKey
+ */
+ public String getSecretKey();
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/identify/SpasCredentialLoader.java b/client/src/main/java/com/alibaba/nacos/client/identify/SpasCredentialLoader.java
new file mode 100644
index 00000000000..12012ee2a21
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/identify/SpasCredentialLoader.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.identify;
+
+/**
+ * Spas Credential Loader
+ *
+ * @author Nacos
+ *
+ */
+public interface SpasCredentialLoader {
+ /**
+ * get Credential
+ *
+ * @return Credential
+ */
+ SpasCredential getCredential();
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/logger/Level.java b/client/src/main/java/com/alibaba/nacos/client/logger/Level.java
new file mode 100644
index 00000000000..38522f80113
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/logger/Level.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.logger;
+
+/**
+ * 阿里中间件日志级别
+ *
+ * @author zhuyong 2014年3月20日 上午9:57:27
+ */
+public enum Level {
+ /**
+ * log level
+ */
+ DEBUG("DEBUG"), INFO("INFO"), WARN("WARN"), ERROR("ERROR"), OFF("OFF");
+
+ private String name;
+
+ Level(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public static Level codeOf(String level) {
+ for (Level l : Level.values()) {
+ if (l.name.equals(level)) {
+ return l;
+ }
+ }
+
+ return OFF;
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/logger/Logger.java b/client/src/main/java/com/alibaba/nacos/client/logger/Logger.java
new file mode 100644
index 00000000000..f38c3e811f1
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/logger/Logger.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.nacos.client.logger;
+
+import com.alibaba.nacos.client.logger.option.ActivateOption;
+
+/**
+ *