diff --git a/src/com/wentch/redkale/boot/Application.java b/src/com/wentch/redkale/boot/Application.java
deleted file mode 100644
index 443f6bec1..000000000
--- a/src/com/wentch/redkale/boot/Application.java
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package com.wentch.redkale.boot;
-
-import com.wentch.redkale.boot.ClassFilter.FilterEntry;
-import com.wentch.redkale.convert.bson.*;
-import com.wentch.redkale.convert.json.*;
-import com.wentch.redkale.net.*;
-import com.wentch.redkale.net.sncp.*;
-import com.wentch.redkale.service.*;
-import com.wentch.redkale.source.*;
-import com.wentch.redkale.util.*;
-import com.wentch.redkale.util.AnyValue.DefaultAnyValue;
-import com.wentch.redkale.watch.*;
-import java.io.*;
-import java.net.*;
-import java.nio.*;
-import java.nio.channels.*;
-import java.nio.file.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-import java.util.function.*;
-import java.util.logging.*;
-import javax.xml.parsers.*;
-import org.w3c.dom.*;
-
-/**
- * 编译时需要加入: -XDignore.symbol.file=true
- *
- * 进程启动类,程序启动后读取application.xml,进行classpath扫描动态加载Service与Servlet
- * 优先加载所有SNCP协议的服务, 再加载其他协议服务,
- * 最后进行Service、Servlet与其他资源之间的依赖注入。
- *
- *
- * @author zhangjx
- */
-public final class Application {
-
- //当前进程启动的时间, 类型: long
- public static final String RESNAME_APP_TIME = "APP_TIME";
-
- //当前进程的根目录, 类型:String
- public static final String RESNAME_APP_HOME = "APP_HOME";
-
- //application.xml 文件中resources节点的内容, 类型: AnyValue
- public static final String RESNAME_APP_GRES = "APP_GRES";
-
- //当前进程节点的name, 类型:String
- public static final String RESNAME_APP_NODE = "APP_NODE";
-
- //当前进程节点的IP地址, 类型:InetAddress、String
- public static final String RESNAME_APP_ADDR = "APP_ADDR";
-
- //当前SNCP Server的IP地址+端口集合 类型: Map、HashMap
- public static final String RESNAME_APP_NODES = "APP_NODES";
-
- //当前Service的IP地址+端口 类型: SocketAddress、InetSocketAddress、String
- public static final String RESNAME_SERVER_ADDR = "SERVER_ADDR"; // SERVER_ADDR
-
- //当前SNCP Server所属的组 类型: String
- public static final String RESNAME_SERVER_GROUP = "SERVER_GROUP";
-
- //当前Service所属的组 类型: Set、String[]
- public static final String RESNAME_SNCP_GROUPS = Sncp.RESNAME_SNCP_GROUPS; // SNCP_GROUPS
-
- protected final Map globalNodes = new HashMap<>();
-
- private final Map> globalGroups = new HashMap<>();
-
- protected final List transports = new ArrayList<>();
-
- protected final InetAddress localAddress;
-
- protected final List sources = new CopyOnWriteArrayList<>();
-
- protected final List servers = new CopyOnWriteArrayList<>();
-
- protected CountDownLatch servicecdl; //会出现两次赋值
-
- //--------------------------------------------------------------------------------------------
- private final ResourceFactory factory = ResourceFactory.root();
-
- private final WatchFactory watch = WatchFactory.root();
-
- private File home;
-
- private final Logger logger;
-
- private final AnyValue config;
-
- private final long startTime = System.currentTimeMillis();
-
- private final CountDownLatch serversLatch;
-
- private Application(final AnyValue config) {
- this.config = config;
-
- final File root = new File(System.getProperty(RESNAME_APP_HOME));
- this.factory.register(RESNAME_APP_TIME, long.class, this.startTime);
- this.factory.register(RESNAME_APP_HOME, Path.class, root.toPath());
- this.factory.register(RESNAME_APP_HOME, File.class, root);
- try {
- this.factory.register(RESNAME_APP_HOME, root.getCanonicalPath());
- this.home = root.getCanonicalFile();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- String localaddr = config.getValue("address", "").trim();
- this.localAddress = localaddr.isEmpty() ? Utility.localInetAddress() : new InetSocketAddress(localaddr, 0).getAddress();
- Application.this.factory.register(RESNAME_APP_ADDR, Application.this.localAddress.getHostAddress());
- Application.this.factory.register(RESNAME_APP_ADDR, InetAddress.class, Application.this.localAddress);
- {
- String node = config.getValue("node", "").trim();
- if (node.isEmpty()) {
- StringBuilder sb = new StringBuilder();
- byte[] bs = this.localAddress.getAddress();
- int v1 = bs[bs.length - 2] & 0xff;
- int v2 = bs[bs.length - 1] & 0xff;
- if (v1 <= 0xf) sb.append('0');
- sb.append(Integer.toHexString(v1));
- if (v2 <= 0xf) sb.append('0');
- sb.append(Integer.toHexString(v2));
- node = sb.toString();
- }
- Application.this.factory.register(RESNAME_APP_NODE, node);
- System.setProperty(RESNAME_APP_NODE, node);
- }
- //以下是初始化日志配置
- final File logconf = new File(root, "conf/logging.properties");
- if (logconf.isFile() && logconf.canRead()) {
- try {
- final String rootpath = root.getCanonicalPath().replace('\\', '/');
- FileInputStream fin = new FileInputStream(logconf);
- Properties properties = new Properties();
- properties.load(fin);
- fin.close();
- properties.entrySet().stream().forEach(x -> {
- x.setValue(x.getValue().toString().replace("${APP_HOME}", rootpath));
- });
-
- if (properties.getProperty("java.util.logging.FileHandler.formatter") == null) {
- properties.setProperty("java.util.logging.FileHandler.formatter", LogFileHandler.LoggingFormater.class.getName());
- }
- if (properties.getProperty("java.util.logging.ConsoleHandler.formatter") == null) {
- properties.setProperty("java.util.logging.ConsoleHandler.formatter", LogFileHandler.LoggingFormater.class.getName());
- }
- String fileHandlerPattern = properties.getProperty("java.util.logging.FileHandler.pattern");
- if (fileHandlerPattern != null && fileHandlerPattern.contains("%d")) {
- final String fileHandlerClass = LogFileHandler.class.getName();
- Properties prop = new Properties();
- final String handlers = properties.getProperty("handlers");
- if (handlers != null && handlers.contains("java.util.logging.FileHandler")) {
- prop.setProperty("handlers", handlers.replace("java.util.logging.FileHandler", fileHandlerClass));
- }
- if (!prop.isEmpty()) {
- String prefix = fileHandlerClass + ".";
- properties.entrySet().stream().forEach(x -> {
- if (x.getKey().toString().startsWith("java.util.logging.FileHandler.")) {
- prop.put(x.getKey().toString().replace("java.util.logging.FileHandler.", prefix), x.getValue());
- }
- });
- prop.entrySet().stream().forEach(x -> {
- properties.put(x.getKey(), x.getValue());
- });
- }
- properties.put(SncpClient.class.getSimpleName() + ".handlers", LogFileHandler.SncpLogFileHandler.class.getName());
- }
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- final PrintStream ps = new PrintStream(out);
- properties.forEach((x, y) -> ps.println(x + "=" + y));
- LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray()));
- } catch (Exception e) {
- Logger.getLogger(this.getClass().getSimpleName()).log(Level.WARNING, "init logger configuration error", e);
- }
- }
- this.logger = Logger.getLogger(this.getClass().getSimpleName());
- this.serversLatch = new CountDownLatch(config.getAnyValues("server").length + 1);
- }
-
- public ResourceFactory getResourceFactory() {
- return factory;
- }
-
- public WatchFactory getWatchFactory() {
- return watch;
- }
-
- public File getHome() {
- return home;
- }
-
- public long getStartTime() {
- return startTime;
- }
-
- private void initLogging() {
-
- }
-
- public void init() throws Exception {
- System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "" + Runtime.getRuntime().availableProcessors() * 4);
- System.setProperty("convert.bson.pool.size", "128");
- System.setProperty("convert.json.pool.size", "128");
- System.setProperty("convert.bson.writer.buffer.defsize", "4096");
- System.setProperty("convert.json.writer.buffer.defsize", "4096");
-
- File persist = new File(this.home, "conf/persistence.xml");
- final String homepath = this.home.getCanonicalPath();
- if (persist.isFile()) System.setProperty(DataDefaultSource.DATASOURCE_CONFPATH, persist.getCanonicalPath());
- logger.log(Level.INFO, RESNAME_APP_HOME + "=" + homepath + "\r\n" + RESNAME_APP_ADDR + "=" + this.localAddress.getHostAddress());
- String lib = config.getValue("lib", "").trim().replace("${APP_HOME}", homepath);
- lib = lib.isEmpty() ? (homepath + "/conf") : (lib + ";" + homepath + "/conf");
- Server.loadLib(logger, lib);
- initLogging();
- if (this.localAddress != null) {
- byte[] bs = this.localAddress.getAddress();
- int v = (0xff & bs[bs.length - 2]) % 10 * 100 + (0xff & bs[bs.length - 1]);
- this.factory.register("property.datasource.nodeid", "" + v);
- }
- //------------------------------------------------------------------------
- final AnyValue resources = config.getAnyValue("resources");
- if (resources != null) {
- factory.register(RESNAME_APP_GRES, AnyValue.class, resources);
- final AnyValue properties = resources.getAnyValue("properties");
- if (properties != null) {
- String dfloads = properties.getValue("load");
- if (dfloads != null) {
- for (String dfload : dfloads.split(";")) {
- if (dfload.trim().isEmpty()) continue;
- dfload = dfload.trim().replace("${APP_HOME}", home.getCanonicalPath()).replace('\\', '/');
- final File df = (dfload.indexOf('/') < 0) ? new File(home, "conf/" + dfload) : new File(dfload);
- if (df.isFile()) {
- Properties ps = new Properties();
- InputStream in = new FileInputStream(df);
- ps.load(in);
- in.close();
- ps.forEach((x, y) -> factory.register("property." + x, y));
- }
- }
- }
- for (AnyValue prop : properties.getAnyValues("property")) {
- String name = prop.getValue("name");
- String value = prop.getValue("value");
- if (name == null || value == null) continue;
- if (name.startsWith("system.property.")) {
- System.setProperty(name.substring("system.property.".length()), value);
- } else {
- factory.register("property." + name, value);
- }
- }
- }
- }
- this.factory.register(BsonFactory.root());
- this.factory.register(JsonFactory.root());
- this.factory.register(BsonFactory.root().getConvert());
- this.factory.register(JsonFactory.root().getConvert());
- initResources();
- }
-
- private void initResources() throws Exception {
- //-------------------------------------------------------------------------
- final AnyValue resources = config.getAnyValue("resources");
- if (resources != null) {
- //------------------------------------------------------------------------
-
- for (AnyValue conf : resources.getAnyValues("group")) {
- final String group = conf.getValue("name", "");
- String protocol = conf.getValue("protocol", Transport.DEFAULT_PROTOCOL).toUpperCase();
- if (!"TCP".equalsIgnoreCase(protocol) && !"UDP".equalsIgnoreCase(protocol)) {
- throw new RuntimeException("Not supported Transport Protocol " + conf.getValue("protocol"));
- }
- Set addrs = globalGroups.get(group);
- if (addrs == null) {
- addrs = new LinkedHashSet<>();
- globalGroups.put(group, addrs);
- }
- for (AnyValue node : conf.getAnyValues("node")) {
- final InetSocketAddress addr = new InetSocketAddress(node.getValue("addr"), node.getIntValue("port"));
- addrs.add(addr);
- String oldgroup = globalNodes.get(addr);
- if (oldgroup != null) throw new RuntimeException(addr + " had one more group " + (globalNodes.get(addr)));
- globalNodes.put(addr, group);
- }
- }
- }
- //------------------------------------------------------------------------
- }
-
- private void startSelfServer() throws Exception {
- final Application application = this;
- new Thread() {
- {
- setName("Application-Control-Thread");
- }
-
- @Override
- public void run() {
- try {
- final DatagramChannel channel = DatagramChannel.open();
- channel.configureBlocking(true);
- channel.socket().setSoTimeout(3000);
- channel.bind(new InetSocketAddress(config.getValue("host", "127.0.0.1"), config.getIntValue("port")));
- boolean loop = true;
- ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
- while (loop) {
- buffer.clear();
- SocketAddress address = channel.receive(buffer);
- buffer.flip();
- byte[] bytes = new byte[buffer.remaining()];
- buffer.get(bytes);
- if ("SHUTDOWN".equalsIgnoreCase(new String(bytes))) {
- try {
- long s = System.currentTimeMillis();
- logger.info(application.getClass().getSimpleName() + " shutdowning");
- application.shutdown();
- buffer.clear();
- buffer.put("SHUTDOWN OK".getBytes());
- buffer.flip();
- channel.send(buffer, address);
- long e = System.currentTimeMillis() - s;
- logger.info(application.getClass().getSimpleName() + " shutdown in " + e + " ms");
- application.serversLatch.countDown();
- System.exit(0);
- } catch (Exception ex) {
- logger.log(Level.INFO, "SHUTDOWN FAIL", ex);
- buffer.clear();
- buffer.put("SHUTDOWN FAIL".getBytes());
- buffer.flip();
- channel.send(buffer, address);
- }
- }
- }
- } catch (Exception e) {
- logger.log(Level.INFO, "Control fail", e);
- System.exit(1);
- }
- }
- }.start();
- }
-
- private void sendShutDown() throws Exception {
- final DatagramChannel channel = DatagramChannel.open();
- channel.configureBlocking(true);
- channel.connect(new InetSocketAddress(config.getValue("host", "127.0.0.1"), config.getIntValue("port")));
- ByteBuffer buffer = ByteBuffer.allocate(128);
- buffer.put("SHUTDOWN".getBytes());
- buffer.flip();
- channel.write(buffer);
- buffer.clear();
- channel.configureBlocking(false);
- channel.read(buffer);
- buffer.flip();
- byte[] bytes = new byte[buffer.remaining()];
- buffer.get(bytes);
- channel.close();
- logger.info(new String(bytes));
- Thread.sleep(500);
- }
-
- public void start() throws Exception {
- final AnyValue[] entrys = config.getAnyValues("server");
- CountDownLatch timecd = new CountDownLatch(entrys.length);
- final List sncps = new ArrayList<>();
- final List others = new ArrayList<>();
- for (final AnyValue entry : entrys) {
- if (entry.getValue("protocol", "").toUpperCase().startsWith("SNCP")) {
- sncps.add(entry);
- } else {
- others.add(entry);
- }
- }
- if (!sncps.isEmpty() && globalNodes.isEmpty()) throw new RuntimeException("found SNCP Server node but not found node info.");
-
- factory.register(RESNAME_APP_NODES, new TypeToken