diff --git a/apm-collector/apm-collector-core/pom.xml b/apm-collector/apm-collector-core/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c68a10e864bddf716d2d3fd9a43bcb41d818ac04
--- /dev/null
+++ b/apm-collector/apm-collector-core/pom.xml
@@ -0,0 +1,27 @@
+
+
+
+ apm-collector
+ org.skywalking
+ 3.2-2017
+
+ 4.0.0
+
+ apm-collector-core
+ jar
+
+
+
+ org.yaml
+ snakeyaml
+ 1.18
+
+
+ ch.qos.logback
+ logback-classic
+ 1.2.3
+
+
+
\ No newline at end of file
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/CollectorException.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/CollectorException.java
new file mode 100644
index 0000000000000000000000000000000000000000..f541218f9f441490b38ae7eba40a59936a8801cd
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/CollectorException.java
@@ -0,0 +1,15 @@
+package org.skywalking.apm.collector.core;
+
+/**
+ * @author pengys5
+ */
+public class CollectorException extends Exception {
+
+ public CollectorException(String message) {
+ super(message);
+ }
+
+ public CollectorException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/client/Client.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/client/Client.java
new file mode 100644
index 0000000000000000000000000000000000000000..661792e7135bde9692718a47c24025ba2c62aa14
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/client/Client.java
@@ -0,0 +1,21 @@
+package org.skywalking.apm.collector.core.client;
+
+/**
+ * @author pengys5
+ */
+public interface Client {
+
+ void initialize() throws ClientException;
+
+ void insert(String path) throws ClientException;
+
+ void update();
+
+ String select(String path) throws ClientException;
+
+ void delete();
+
+ boolean exist(String path) throws ClientException;
+
+ void listen(String path) throws ClientException;
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/client/ClientException.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/client/ClientException.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b7be888e5181bc1e31c9f0da1cbfacd742caa0f
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/client/ClientException.java
@@ -0,0 +1,16 @@
+package org.skywalking.apm.collector.core.client;
+
+import org.skywalking.apm.collector.core.CollectorException;
+
+/**
+ * @author pengys5
+ */
+public abstract class ClientException extends CollectorException {
+ public ClientException(String message) {
+ super(message);
+ }
+
+ public ClientException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/client/DataListener.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/client/DataListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..1022d39aa89f3a00466b133116daa2ba6ce96d2c
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/client/DataListener.java
@@ -0,0 +1,12 @@
+package org.skywalking.apm.collector.core.client;
+
+import java.util.List;
+
+/**
+ * @author pengys5
+ */
+public interface DataListener {
+ List items();
+
+ void listen() throws ClientException;
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterDataInitializer.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterDataInitializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..3be6aeaee1e8508fecf3dda3ce84b2300602b848
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterDataInitializer.java
@@ -0,0 +1,24 @@
+package org.skywalking.apm.collector.core.cluster;
+
+import org.skywalking.apm.collector.core.client.Client;
+import org.skywalking.apm.collector.core.client.ClientException;
+import org.skywalking.apm.collector.core.framework.DataInitializer;
+
+/**
+ * @author pengys5
+ */
+public abstract class ClusterDataInitializer implements DataInitializer {
+
+ public static final String BASE_CATALOG = "collector.cluster";
+ public static final String FOR_UI_CATALOG = BASE_CATALOG + ".ui";
+ public static final String FOR_AGENT_CATALOG = BASE_CATALOG + ".agent";
+
+ @Override public final void initialize(Client client) throws ClientException {
+ if (!existItem(client, FOR_UI_CATALOG)) {
+ addItem(client, FOR_UI_CATALOG);
+ }
+ if (!existItem(client, FOR_AGENT_CATALOG)) {
+ addItem(client, FOR_AGENT_CATALOG);
+ }
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterDefinitionFile.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterDefinitionFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa1bb7b5428d3771a9e6f255b941e9aae5f30f08
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterDefinitionFile.java
@@ -0,0 +1,13 @@
+package org.skywalking.apm.collector.core.cluster;
+
+import org.skywalking.apm.collector.core.framework.DefinitionFile;
+
+/**
+ * @author pengys5
+ */
+public class ClusterDefinitionFile extends DefinitionFile {
+
+ @Override protected String fileName() {
+ return "cluster-configuration.define";
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterModuleDefine.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterModuleDefine.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ac18f2f2923c010255f1c7968ab6370aea32577
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterModuleDefine.java
@@ -0,0 +1,29 @@
+package org.skywalking.apm.collector.core.cluster;
+
+import java.util.Map;
+import org.skywalking.apm.collector.core.client.Client;
+import org.skywalking.apm.collector.core.client.ClientException;
+import org.skywalking.apm.collector.core.config.ConfigParseException;
+import org.skywalking.apm.collector.core.module.ModuleDefine;
+import org.skywalking.apm.collector.core.server.Server;
+
+/**
+ * @author pengys5
+ */
+public abstract class ClusterModuleDefine extends ModuleDefine {
+
+ @Override public final void initialize(Map config) throws ClusterModuleException {
+ try {
+ configParser().parse(config);
+ Client client = client();
+ client.initialize();
+ dataInitializer().initialize(client);
+ } catch (ConfigParseException | ClientException e) {
+ throw new ClusterModuleException(e.getMessage(), e);
+ }
+ }
+
+ @Override public final Server server() {
+ throw new UnsupportedOperationException("");
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterModuleException.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterModuleException.java
new file mode 100644
index 0000000000000000000000000000000000000000..3171f58b2910c13871622a662ede3f2f2a8fa080
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/ClusterModuleException.java
@@ -0,0 +1,17 @@
+package org.skywalking.apm.collector.core.cluster;
+
+import org.skywalking.apm.collector.core.module.ModuleException;
+
+/**
+ * @author pengys5
+ */
+public class ClusterModuleException extends ModuleException {
+
+ public ClusterModuleException(String message) {
+ super(message);
+ }
+
+ public ClusterModuleException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/Discovery.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/Discovery.java
new file mode 100644
index 0000000000000000000000000000000000000000..0957d512545a813fadb76a7162484f4a730d5d38
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/Discovery.java
@@ -0,0 +1,9 @@
+package org.skywalking.apm.collector.core.cluster;
+
+/**
+ * @author pengys5
+ */
+public interface Discovery {
+
+ void discover();
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/Registration.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/Registration.java
new file mode 100644
index 0000000000000000000000000000000000000000..c37bb83bb20639a85905f969f36b137cda06af53
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/cluster/Registration.java
@@ -0,0 +1,9 @@
+package org.skywalking.apm.collector.core.cluster;
+
+/**
+ * @author pengys5
+ */
+public interface Registration {
+
+ void register();
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigException.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigException.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d6f3f32c9efff8f37a6af8df62a702c8cefe30b
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigException.java
@@ -0,0 +1,17 @@
+package org.skywalking.apm.collector.core.config;
+
+import org.skywalking.apm.collector.core.CollectorException;
+
+/**
+ * @author pengys5
+ */
+public abstract class ConfigException extends CollectorException {
+
+ public ConfigException(String message) {
+ super(message);
+ }
+
+ public ConfigException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigLoader.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..06e1cff84b3678d8b70132921c4431107e93a65e
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigLoader.java
@@ -0,0 +1,9 @@
+package org.skywalking.apm.collector.core.config;
+
+import org.skywalking.apm.collector.core.framework.Loader;
+
+/**
+ * @author pengys5
+ */
+public interface ConfigLoader extends Loader {
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigLoaderException.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigLoaderException.java
new file mode 100644
index 0000000000000000000000000000000000000000..98abef0e47e2a688b1c3ca92d50dcf9c5d767ba0
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigLoaderException.java
@@ -0,0 +1,15 @@
+package org.skywalking.apm.collector.core.config;
+
+/**
+ * @author pengys5
+ */
+public abstract class ConfigLoaderException extends ConfigException {
+
+ public ConfigLoaderException(String message) {
+ super(message);
+ }
+
+ public ConfigLoaderException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigParseException.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigParseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..474abdce9089c78b808d1fef4637f684065bcd6b
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/config/ConfigParseException.java
@@ -0,0 +1,15 @@
+package org.skywalking.apm.collector.core.config;
+
+/**
+ * @author pengys5
+ */
+public class ConfigParseException extends ConfigException {
+
+ public ConfigParseException(String message) {
+ super(message);
+ }
+
+ public ConfigParseException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/DataInitializer.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/DataInitializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c9fc0c053fb1ef4e4e8c38f4e52f0d1dd57bb16
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/DataInitializer.java
@@ -0,0 +1,15 @@
+package org.skywalking.apm.collector.core.framework;
+
+import org.skywalking.apm.collector.core.client.Client;
+import org.skywalking.apm.collector.core.client.ClientException;
+
+/**
+ * @author pengys5
+ */
+public interface DataInitializer {
+ void initialize(Client client) throws ClientException;
+
+ void addItem(Client client, String itemKey) throws ClientException;
+
+ boolean existItem(Client client, String itemKey) throws ClientException;
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Decision.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Decision.java
new file mode 100644
index 0000000000000000000000000000000000000000..15c61fb7a3c6abff7940fb48a14e34c835d6ec9a
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Decision.java
@@ -0,0 +1,7 @@
+package org.skywalking.apm.collector.core.framework;
+
+/**
+ * @author pengys5
+ */
+public interface Decision {
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Define.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Define.java
new file mode 100644
index 0000000000000000000000000000000000000000..591a383435a699b60051c7923fa90783505b6dd8
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Define.java
@@ -0,0 +1,15 @@
+package org.skywalking.apm.collector.core.framework;
+
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public interface Define {
+
+ void initialize(Map config) throws DefineException;
+
+ String getName();
+
+ void setName(String name);
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/DefineException.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/DefineException.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff3401b805fc50481fb49294b318778c1bc2945e
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/DefineException.java
@@ -0,0 +1,17 @@
+package org.skywalking.apm.collector.core.framework;
+
+import org.skywalking.apm.collector.core.CollectorException;
+
+/**
+ * @author pengys5
+ */
+public abstract class DefineException extends CollectorException {
+
+ public DefineException(String message) {
+ super(message);
+ }
+
+ public DefineException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/DefinitionFile.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/DefinitionFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..dae247d7856dbe4a70c0afc48f45824ae834d83d
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/DefinitionFile.java
@@ -0,0 +1,15 @@
+package org.skywalking.apm.collector.core.framework;
+
+/**
+ * @author pengys5
+ */
+public abstract class DefinitionFile {
+
+ private final String CATALOG = "META-INF/defines/";
+
+ protected abstract String fileName();
+
+ public final String get() {
+ return CATALOG + fileName();
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Loader.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Loader.java
new file mode 100644
index 0000000000000000000000000000000000000000..70957c8a415bc11a985e14b7f7167b332ff7cf6a
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Loader.java
@@ -0,0 +1,11 @@
+package org.skywalking.apm.collector.core.framework;
+
+import org.skywalking.apm.collector.core.config.ConfigException;
+
+/**
+ * @author pengys5
+ */
+public interface Loader {
+
+ void load() throws ConfigException;
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/PriorityDecision.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/PriorityDecision.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f19d746c9da955ad3bfc34725706eb08f2453b3
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/PriorityDecision.java
@@ -0,0 +1,31 @@
+package org.skywalking.apm.collector.core.framework;
+
+import java.util.List;
+
+/**
+ * @author pengys5
+ */
+public class PriorityDecision implements Decision {
+
+ public Object decide(List source) {
+ return source.get(0);
+ }
+
+ public static class Priority {
+ private final int value;
+ private final Object object;
+
+ public Priority(int value, Object object) {
+ this.value = value;
+ this.object = object;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public Object getObject() {
+ return object;
+ }
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Provider.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Provider.java
new file mode 100644
index 0000000000000000000000000000000000000000..222c1e9fb5e8c670f23afc2f5fddd9873b571e9c
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Provider.java
@@ -0,0 +1,8 @@
+package org.skywalking.apm.collector.core.framework;
+
+/**
+ * @author pengys5
+ */
+public interface Provider {
+ D create();
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Starter.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Starter.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d7a4f8febefe55ceb92e56dec22732426ef2f52
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Starter.java
@@ -0,0 +1,8 @@
+package org.skywalking.apm.collector.core.framework;
+
+/**
+ * @author pengys5
+ */
+public interface Starter {
+ void start();
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Writer.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Writer.java
new file mode 100644
index 0000000000000000000000000000000000000000..68c40c065d84d3ef17e68626f18ae5ea3c538e24
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/framework/Writer.java
@@ -0,0 +1,7 @@
+package org.skywalking.apm.collector.core.framework;
+
+/**
+ * @author pengys5
+ */
+public interface Writer {
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/Module.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/Module.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d3f57145649e60a262a12c7bfaf08a3c029081e
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/Module.java
@@ -0,0 +1,10 @@
+package org.skywalking.apm.collector.core.module;
+
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public interface Module {
+ void install(Map configuration);
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigLoader.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3d882e53b3c8da799f202e41bb5241be0d11bbf
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigLoader.java
@@ -0,0 +1,38 @@
+package org.skywalking.apm.collector.core.module;
+
+import java.io.FileNotFoundException;
+import java.util.Map;
+import org.skywalking.apm.collector.core.config.ConfigLoader;
+import org.skywalking.apm.collector.core.util.ResourceUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * @author pengys5
+ */
+public class ModuleConfigLoader implements ConfigLoader {
+
+ private final Logger logger = LoggerFactory.getLogger(ModuleConfigLoader.class);
+
+ @Override public void load() throws ModuleConfigLoaderException {
+ Yaml yaml = new Yaml();
+ ModuleInstaller installer = new ModuleInstaller();
+
+ Map configurations = null;
+ try {
+ configurations = (Map)yaml.load(ResourceUtils.read("application.yml"));
+ } catch (FileNotFoundException e) {
+ throw new ModuleConfigLoaderException(e.getMessage(), e);
+ }
+ configurations.forEach((moduleName, moduleConfig) -> {
+ logger.info("module name \"{}\" from application.yml", moduleName);
+ try {
+ installer.install(moduleName, moduleConfig);
+ } catch (ModuleException e) {
+ logger.error("module \"{}\" install failure", moduleName);
+ logger.error(e.getMessage(), e);
+ }
+ });
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigLoaderException.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigLoaderException.java
new file mode 100644
index 0000000000000000000000000000000000000000..9143d01977a74afae3586b79b67fd36cbd6b01d5
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigLoaderException.java
@@ -0,0 +1,16 @@
+package org.skywalking.apm.collector.core.module;
+
+import org.skywalking.apm.collector.core.config.ConfigLoaderException;
+
+/**
+ * @author pengys5
+ */
+public class ModuleConfigLoaderException extends ConfigLoaderException {
+ public ModuleConfigLoaderException(String message) {
+ super(message);
+ }
+
+ public ModuleConfigLoaderException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigParser.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f2fbd94180c1e923abd98bedb90a0a2347f1d5c
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigParser.java
@@ -0,0 +1,11 @@
+package org.skywalking.apm.collector.core.module;
+
+import java.util.Map;
+import org.skywalking.apm.collector.core.config.ConfigParseException;
+
+/**
+ * @author pengys5
+ */
+public interface ModuleConfigParser {
+ void parse(Map config) throws ConfigParseException;
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleDefine.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleDefine.java
new file mode 100644
index 0000000000000000000000000000000000000000..e6a661350839b6a45ce4ce92b0b6a5518b009a95
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleDefine.java
@@ -0,0 +1,34 @@
+package org.skywalking.apm.collector.core.module;
+
+import org.skywalking.apm.collector.core.client.Client;
+import org.skywalking.apm.collector.core.framework.DataInitializer;
+import org.skywalking.apm.collector.core.framework.Define;
+import org.skywalking.apm.collector.core.server.Server;
+
+/**
+ * @author pengys5
+ */
+public abstract class ModuleDefine implements Define {
+
+ private String moduleName;
+
+ @Override public final String getName() {
+ return moduleName;
+ }
+
+ @Override public final void setName(String name) {
+ this.moduleName = name;
+ }
+
+ protected abstract ModuleGroup group();
+
+ protected abstract boolean defaultModule();
+
+ protected abstract ModuleConfigParser configParser();
+
+ protected abstract Client client();
+
+ protected abstract Server server();
+
+ protected abstract DataInitializer dataInitializer();
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleDefinitionFile.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleDefinitionFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..dbe447e7aa47ed69d60aab3c893beb870f21b547
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleDefinitionFile.java
@@ -0,0 +1,12 @@
+package org.skywalking.apm.collector.core.module;
+
+import org.skywalking.apm.collector.core.framework.DefinitionFile;
+
+/**
+ * @author pengys5
+ */
+public class ModuleDefinitionFile extends DefinitionFile {
+ @Override protected String fileName() {
+ return "module.define";
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleException.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleException.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a58ce36632a49301a977ad35299bcba4f7eeec1
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleException.java
@@ -0,0 +1,17 @@
+package org.skywalking.apm.collector.core.module;
+
+import org.skywalking.apm.collector.core.framework.DefineException;
+
+/**
+ * @author pengys5
+ */
+public abstract class ModuleException extends DefineException {
+
+ public ModuleException(String message) {
+ super(message);
+ }
+
+ public ModuleException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleGroup.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleGroup.java
new file mode 100644
index 0000000000000000000000000000000000000000..3732640eab58317a6fca98fa1787008f680a60b7
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleGroup.java
@@ -0,0 +1,8 @@
+package org.skywalking.apm.collector.core.module;
+
+/**
+ * @author pengys5
+ */
+public enum ModuleGroup {
+ Cluster, Worker, Queue
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleInstaller.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleInstaller.java
new file mode 100644
index 0000000000000000000000000000000000000000..61b1dc866271a912b92ca5b8401e3c5228010532
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleInstaller.java
@@ -0,0 +1,46 @@
+package org.skywalking.apm.collector.core.module;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.skywalking.apm.collector.core.framework.DefineException;
+import org.skywalking.apm.collector.core.util.DefinitionLoader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author pengys5
+ */
+public class ModuleInstaller {
+
+ private final Logger logger = LoggerFactory.getLogger(ModuleInstaller.class);
+
+ private final Map moduleDefineMap;
+
+ protected ModuleInstaller() {
+ moduleDefineMap = new LinkedHashMap<>();
+ ModuleDefinitionFile definitionFile = new ModuleDefinitionFile();
+ logger.info("definition file name: {}", definitionFile.fileName());
+ DefinitionLoader definitionLoader = DefinitionLoader.load(ModuleDefine.class, definitionFile);
+ for (ModuleDefine moduleDefine : definitionLoader) {
+ logger.info("loaded module class: {}", moduleDefine.getClass().getName());
+ moduleDefineMap.put(moduleDefine.getName(), moduleDefine);
+ }
+ }
+
+ public void install(String moduleName, Map moduleConfig) throws ModuleException {
+ Map module = (LinkedHashMap)moduleConfig;
+ module.entrySet().forEach(subModuleConfig -> {
+ String subMoudleName = moduleName + "." + subModuleConfig.getKey();
+ logger.info("install sub module {}", subMoudleName);
+ try {
+ if (moduleDefineMap.containsKey(subMoudleName)) {
+ moduleDefineMap.get(subMoudleName).initialize(subModuleConfig.getValue());
+ } else {
+ logger.error("could not found the module definition, module name: {}", subMoudleName);
+ }
+ } catch (DefineException e) {
+ logger.error(e.getMessage(), e);
+ }
+ });
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/server/Server.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/server/Server.java
new file mode 100644
index 0000000000000000000000000000000000000000..eede89b810e73aac3f504c2dd5d12bc5c2149e14
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/server/Server.java
@@ -0,0 +1,9 @@
+package org.skywalking.apm.collector.core.server;
+
+/**
+ * @author pengys5
+ */
+public interface Server {
+
+ void initialize() throws ServerException;
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/server/ServerException.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/server/ServerException.java
new file mode 100644
index 0000000000000000000000000000000000000000..30d37f9aaa22334f9d2b202268dcb483d1ff60d3
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/server/ServerException.java
@@ -0,0 +1,17 @@
+package org.skywalking.apm.collector.core.server;
+
+import org.skywalking.apm.collector.core.CollectorException;
+
+/**
+ * @author pengys5
+ */
+public abstract class ServerException extends CollectorException {
+
+ public ServerException(String message) {
+ super(message);
+ }
+
+ public ServerException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/server/ServerModuleDefine.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/server/ServerModuleDefine.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f580ff3453be435fe8be6f83275c647ef142661
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/server/ServerModuleDefine.java
@@ -0,0 +1,9 @@
+package org.skywalking.apm.collector.core.server;
+
+import org.skywalking.apm.collector.core.module.ModuleDefine;
+
+/**
+ * @author pengys5
+ */
+public abstract class ServerModuleDefine extends ModuleDefine {
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/DefinitionLoader.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/DefinitionLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..bd5164620cc665d2446532f0c4b775c5fb4e40de
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/DefinitionLoader.java
@@ -0,0 +1,81 @@
+package org.skywalking.apm.collector.core.util;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import org.skywalking.apm.collector.core.framework.Define;
+import org.skywalking.apm.collector.core.framework.DefinitionFile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author pengys5
+ */
+public class DefinitionLoader implements Iterable {
+
+ private final Logger logger = LoggerFactory.getLogger(DefinitionLoader.class);
+
+ private final Class definition;
+ private final DefinitionFile definitionFile;
+
+ protected DefinitionLoader(Class svc, DefinitionFile definitionFile) {
+ this.definition = Objects.requireNonNull(svc, "definition interface cannot be null");
+ this.definitionFile = definitionFile;
+ }
+
+ public static DefinitionLoader load(Class definition, DefinitionFile definitionFile) {
+ return new DefinitionLoader(definition, definitionFile);
+ }
+
+ @Override public final Iterator iterator() {
+ logger.info("load definition file: {}", definitionFile.get());
+ Properties properties = new Properties();
+ Map definitionList = new LinkedHashMap<>();
+ try {
+ Enumeration urlEnumeration = this.getClass().getClassLoader().getResources(definitionFile.get());
+ while (urlEnumeration.hasMoreElements()) {
+ URL definitionFileURL = urlEnumeration.nextElement();
+ logger.info("definition file url: {}", definitionFileURL.getPath());
+ properties.load(new FileReader(definitionFileURL.getPath()));
+
+ Enumeration defineItem = properties.propertyNames();
+ while (defineItem.hasMoreElements()) {
+ String key = (String)defineItem.nextElement();
+ String fullNameClass = properties.getProperty(key);
+ definitionList.put(key, fullNameClass);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ Iterator> moduleDefineIterator = definitionList.entrySet().iterator();
+
+ return new Iterator() {
+ @Override public boolean hasNext() {
+ return moduleDefineIterator.hasNext();
+ }
+
+ @Override public D next() {
+ Map.Entry moduleDefineEntry = moduleDefineIterator.next();
+ String definitionName = moduleDefineEntry.getKey();
+ String definitionClass = moduleDefineEntry.getValue();
+ logger.info("key: {}, definitionClass: {}", definitionName, definitionClass);
+ try {
+ Class c = Class.forName(definitionClass);
+ Define define = (Define)c.newInstance();
+ define.setName(definitionName);
+ return (D)define;
+ } catch (Exception e) {
+ }
+ return null;
+ }
+ };
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/ObjectUtils.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/ObjectUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..f65b38d323f64e1e924990cd7b7c6b2509094d25
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/ObjectUtils.java
@@ -0,0 +1,12 @@
+package org.skywalking.apm.collector.core.util;
+
+import com.sun.istack.internal.Nullable;
+
+/**
+ * @author pengys5
+ */
+public class ObjectUtils {
+ public static boolean isEmpty(@Nullable Object obj) {
+ return obj == null;
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/ResourceUtils.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/ResourceUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..31daeec6fd9d9c15185f95be7e87a97ad04b1f1a
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/ResourceUtils.java
@@ -0,0 +1,16 @@
+package org.skywalking.apm.collector.core.util;
+
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+
+/**
+ * @author pengys5
+ */
+public class ResourceUtils {
+
+ private static final String PATH = ResourceUtils.class.getResource("/").getPath();
+
+ public static FileReader read(String fileName) throws FileNotFoundException {
+ return new FileReader(PATH + fileName);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/StringUtils.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/StringUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..c1b0ab3de3ee59c8567deb8ef72215731c13bb77
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/StringUtils.java
@@ -0,0 +1,15 @@
+package org.skywalking.apm.collector.core.util;
+
+import com.sun.istack.internal.Nullable;
+
+/**
+ * @author pengys5
+ */
+public class StringUtils {
+
+ public static final String EMPTY_STRING = "";
+
+ public static boolean isEmpty(@Nullable Object str) {
+ return (str == null || EMPTY_STRING.equals(str));
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/worker/WorkerModuleDefine.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/worker/WorkerModuleDefine.java
new file mode 100644
index 0000000000000000000000000000000000000000..f337a1de5f112f97e97eb9461e5831a09d4d4e94
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/worker/WorkerModuleDefine.java
@@ -0,0 +1,34 @@
+package org.skywalking.apm.collector.core.worker;
+
+import java.util.Map;
+import org.skywalking.apm.collector.core.client.Client;
+import org.skywalking.apm.collector.core.config.ConfigParseException;
+import org.skywalking.apm.collector.core.framework.DataInitializer;
+import org.skywalking.apm.collector.core.module.ModuleDefine;
+import org.skywalking.apm.collector.core.module.ModuleException;
+import org.skywalking.apm.collector.core.server.Server;
+import org.skywalking.apm.collector.core.server.ServerException;
+
+/**
+ * @author pengys5
+ */
+public abstract class WorkerModuleDefine extends ModuleDefine {
+
+ @Override public final void initialize(Map config) throws ModuleException {
+ try {
+ configParser().parse(config);
+ Server server = server();
+ server.initialize();
+ } catch (ConfigParseException | ServerException e) {
+ throw new WorkerModuleException(e.getMessage(), e);
+ }
+ }
+
+ @Override public final Client client() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public final DataInitializer dataInitializer() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/worker/WorkerModuleException.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/worker/WorkerModuleException.java
new file mode 100644
index 0000000000000000000000000000000000000000..339968f61b3cf7f15f8fbf3440b5f2991ebd90da
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/worker/WorkerModuleException.java
@@ -0,0 +1,17 @@
+package org.skywalking.apm.collector.core.worker;
+
+import org.skywalking.apm.collector.core.module.ModuleException;
+
+/**
+ * @author pengys5
+ */
+public class WorkerModuleException extends ModuleException {
+
+ public WorkerModuleException(String message) {
+ super(message);
+ }
+
+ public WorkerModuleException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/main/resources/logback.xml b/apm-collector/apm-collector-core/src/main/resources/logback.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b0df07af44a54e469a9924f4b34e67ef4f59211b
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/main/resources/logback.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/config/ModuleConfigLoaderTestCase.java b/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/config/ModuleConfigLoaderTestCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..85f802f23a669b4bcf5331819b8ba9ca3fe86845
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/config/ModuleConfigLoaderTestCase.java
@@ -0,0 +1,18 @@
+package org.skywalking.apm.collector.core.config;
+
+import java.io.FileNotFoundException;
+import org.junit.Test;
+import org.skywalking.apm.collector.core.module.ModuleConfigLoader;
+import org.skywalking.apm.collector.core.module.ModuleConfigLoaderException;
+
+/**
+ * @author pengys5
+ */
+public class ModuleConfigLoaderTestCase {
+
+ @Test
+ public void testLoad() throws ModuleConfigLoaderException {
+ ModuleConfigLoader loader = new ModuleConfigLoader();
+ loader.load();
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/module/ClusterModuleForTest.java b/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/module/ClusterModuleForTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b6ece374610b66e319fe68347eb335193cd92d3c
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/module/ClusterModuleForTest.java
@@ -0,0 +1,17 @@
+package org.skywalking.apm.collector.core.module;
+
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author pengys5
+ */
+public class ClusterModuleForTest implements Module {
+
+ private final Logger logger = LoggerFactory.getLogger(ModuleInstaller.class);
+
+ @Override public void install(Map configuration) {
+ logger.debug(configuration.toString());
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/module/ModuleInstallerTestCase.java b/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/module/ModuleInstallerTestCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..9032bb1451f2dae3a5154e0030ac723c80ce3b72
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/module/ModuleInstallerTestCase.java
@@ -0,0 +1,19 @@
+package org.skywalking.apm.collector.core.module;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class ModuleInstallerTestCase {
+
+ @Before
+ public void init() {
+ }
+
+ @Test
+ public void testInstall() {
+ ModuleInstaller installer = new ModuleInstaller();
+ }
+}
diff --git a/apm-collector/apm-collector-core/src/test/resources/META-INF/defines/module.define b/apm-collector/apm-collector-core/src/test/resources/META-INF/defines/module.define
new file mode 100644
index 0000000000000000000000000000000000000000..5d6f8c358c044a9a9d3c0fbe700175ea664f7f39
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/test/resources/META-INF/defines/module.define
@@ -0,0 +1 @@
+cluster=org.skywalking.apm.collector.core.module.ClusterModuleForTest
\ No newline at end of file
diff --git a/apm-collector/apm-collector-core/src/test/resources/application.yml b/apm-collector/apm-collector-core/src/test/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ec549438f98e8ef1327bacc81e5dbf36e58c7068
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/test/resources/application.yml
@@ -0,0 +1,8 @@
+cluster:
+ zookeeper:
+ host: localhost-zk
+ port: 1000
+ redis:
+ host: localhost-rd
+ port: 2000
+
diff --git a/apm-collector/apm-collector-core/src/test/resources/logback-test.xml b/apm-collector/apm-collector-core/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9b51230a90dfb29eca5bdbdc0261aa04c027ccbb
--- /dev/null
+++ b/apm-collector/apm-collector-core/src/test/resources/logback-test.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
\ No newline at end of file