This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
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.*;
|
||||
@@ -21,6 +22,7 @@ import java.nio.channels.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.logging.*;
|
||||
import javax.xml.parsers.*;
|
||||
import org.w3c.dom.*;
|
||||
@@ -391,6 +393,8 @@ public final class Application {
|
||||
private void runServers(CountDownLatch timecd, final List<AnyValue> serconfs) throws Exception {
|
||||
this.servicecdl = new CountDownLatch(serconfs.size());
|
||||
CountDownLatch sercdl = new CountDownLatch(serconfs.size());
|
||||
final AtomicBoolean inited = new AtomicBoolean(false);
|
||||
final Map<String, Class<? extends NodeServer>> nodeClasses = new HashMap<>();
|
||||
for (final AnyValue serconf : serconfs) {
|
||||
Thread thread = new Thread() {
|
||||
{
|
||||
@@ -410,6 +414,28 @@ public final class Application {
|
||||
server = new NodeSncpServer(Application.this, serconf);
|
||||
} else if ("HTTP".equalsIgnoreCase(protocol)) {
|
||||
server = new NodeHttpServer(Application.this, serconf);
|
||||
} else {
|
||||
if (!inited.get()) {
|
||||
synchronized (nodeClasses) {
|
||||
if (!inited.get()) {
|
||||
inited.set(true);
|
||||
ClassFilter profilter = new ClassFilter(NodeProtocol.class, NodeServer.class);
|
||||
ClassFilter.Loader.load(home, profilter);
|
||||
final Set<FilterEntry<NodeServer>> entrys = profilter.getFilterEntrys();
|
||||
for (FilterEntry<NodeServer> entry : entrys) {
|
||||
final Class<? extends NodeServer> type = entry.getType();
|
||||
NodeProtocol pros = type.getAnnotation(NodeProtocol.class);
|
||||
for (String p : pros.value()) {
|
||||
final Class<? extends NodeServer> old = nodeClasses.get(p);
|
||||
if (old != null && old != type) throw new RuntimeException("Protocol(" + p + ") had NodeServer-Class(" + old.getName() + ") but repeat NodeServer-Class(" + type.getName() + ")");
|
||||
nodeClasses.put(p, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Class<? extends NodeServer> nodeClass = nodeClasses.get(protocol);
|
||||
if (nodeClass != null) server = NodeServer.create(nodeClass, Application.this, serconf);
|
||||
}
|
||||
if (server == null) {
|
||||
logger.log(Level.SEVERE, "Not found Server Class for protocol({0})", serconf.getValue("protocol"));
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.lang.annotation.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.jar.*;
|
||||
import java.util.logging.*;
|
||||
import java.util.regex.*;
|
||||
@@ -322,6 +323,12 @@ public final class ClassFilter<T> {
|
||||
|
||||
protected static final Logger logger = Logger.getLogger(Loader.class.getName());
|
||||
|
||||
protected static final ConcurrentMap<URL, Set<String>> cache = new ConcurrentHashMap<>();
|
||||
|
||||
public static void close() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载当前线程的classpath扫描所有class进行过滤
|
||||
* <p>
|
||||
@@ -346,33 +353,69 @@ public final class ClassFilter<T> {
|
||||
List<File> files = new ArrayList<>();
|
||||
boolean debug = logger.isLoggable(Level.FINEST);
|
||||
StringBuilder debugstr = new StringBuilder();
|
||||
for (URL url : urljares) {
|
||||
try (JarFile jar = new JarFile(URLDecoder.decode(url.getFile(), "UTF-8"))) {
|
||||
Enumeration<JarEntry> it = jar.entries();
|
||||
while (it.hasMoreElements()) {
|
||||
String entryname = it.nextElement().getName().replace('/', '.');
|
||||
if (entryname.endsWith(".class") && entryname.indexOf('$') < 0) {
|
||||
String classname = entryname.substring(0, entryname.length() - 6);
|
||||
if (classname.startsWith("javax.") || classname.startsWith("org.") || classname.startsWith("com.mysql.")) continue;
|
||||
if (debug) debugstr.append(classname).append("\r\n");
|
||||
for (final ClassFilter filter : filters) {
|
||||
if (filter != null) filter.filter(null, classname);
|
||||
for (final URL url : urljares) {
|
||||
Set<String> classes = cache.get(url);
|
||||
if (classes == null) {
|
||||
synchronized (cache) {
|
||||
if (cache.get(url) == null) {
|
||||
classes = new CopyOnWriteArraySet<>();
|
||||
cache.put(url, classes);
|
||||
} else {
|
||||
classes = cache.get(url);
|
||||
}
|
||||
}
|
||||
try (JarFile jar = new JarFile(URLDecoder.decode(url.getFile(), "UTF-8"))) {
|
||||
Enumeration<JarEntry> it = jar.entries();
|
||||
while (it.hasMoreElements()) {
|
||||
String entryname = it.nextElement().getName().replace('/', '.');
|
||||
if (entryname.endsWith(".class") && entryname.indexOf('$') < 0) {
|
||||
String classname = entryname.substring(0, entryname.length() - 6);
|
||||
if (classname.startsWith("javax.") || classname.startsWith("org.") || classname.startsWith("com.mysql.")) continue;
|
||||
classes.add(classname);
|
||||
if (debug) debugstr.append(classname).append("\r\n");
|
||||
for (final ClassFilter filter : filters) {
|
||||
if (filter != null) filter.filter(null, classname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (String classname : classes) {
|
||||
for (final ClassFilter filter : filters) {
|
||||
if (filter != null) filter.filter(null, classname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (URL url : urlfiles) {
|
||||
files.clear();
|
||||
File root = new File(url.getFile());
|
||||
String rootpath = root.getPath();
|
||||
loadClassFiles(exclude, root, files);
|
||||
for (File f : files) {
|
||||
String classname = f.getPath().substring(rootpath.length() + 1, f.getPath().length() - 6).replace(File.separatorChar, '.');
|
||||
if (classname.startsWith("javax.") || classname.startsWith("org.") || classname.startsWith("com.mysql.")) continue;
|
||||
if (debug) debugstr.append(classname).append("\r\n");
|
||||
for (final ClassFilter filter : filters) {
|
||||
if (filter != null) filter.filter(null, classname);
|
||||
for (final URL url : urlfiles) {
|
||||
Set<String> classes = cache.get(url);
|
||||
if (classes == null) {
|
||||
synchronized (cache) {
|
||||
if (cache.get(url) == null) {
|
||||
classes = new CopyOnWriteArraySet<>();
|
||||
cache.put(url, classes);
|
||||
} else {
|
||||
classes = cache.get(url);
|
||||
}
|
||||
}
|
||||
files.clear();
|
||||
File root = new File(url.getFile());
|
||||
String rootpath = root.getPath();
|
||||
loadClassFiles(exclude, root, files);
|
||||
for (File f : files) {
|
||||
String classname = f.getPath().substring(rootpath.length() + 1, f.getPath().length() - 6).replace(File.separatorChar, '.');
|
||||
if (classname.startsWith("javax.") || classname.startsWith("org.") || classname.startsWith("com.mysql.")) continue;
|
||||
classes.add(classname);
|
||||
if (debug) debugstr.append(classname).append("\r\n");
|
||||
for (final ClassFilter filter : filters) {
|
||||
if (filter != null) filter.filter(null, classname);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (String classname : classes) {
|
||||
for (final ClassFilter filter : filters) {
|
||||
if (filter != null) filter.filter(null, classname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import javax.annotation.*;
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@NodeProtocol({"HTTP", "HTTPS"})
|
||||
public final class NodeHttpServer extends NodeServer {
|
||||
|
||||
private final HttpServer httpServer;
|
||||
|
||||
19
src/com/wentch/redkale/boot/NodeProtocol.java
Normal file
19
src/com/wentch/redkale/boot/NodeProtocol.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface NodeProtocol {
|
||||
String[] value();
|
||||
}
|
||||
@@ -73,6 +73,14 @@ public abstract class NodeServer {
|
||||
this.fine = logger.isLoggable(Level.FINE);
|
||||
}
|
||||
|
||||
public static <T extends NodeServer> NodeServer create(Class<T> clazz, Application application, AnyValue serconf) {
|
||||
try {
|
||||
return clazz.getConstructor(Application.class, AnyValue.class).newInstance(application, serconf);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void init(AnyValue config) throws Exception {
|
||||
this.nodeConf = config == null ? AnyValue.create() : config;
|
||||
if (isSNCP()) { // SNCP协议
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.logging.*;
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@NodeProtocol({"SNCP"})
|
||||
public final class NodeSncpServer extends NodeServer {
|
||||
|
||||
private final SncpServer sncpServer;
|
||||
|
||||
@@ -15,7 +15,6 @@ import java.nio.*;
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@AutoLoad(false)
|
||||
public class BindingIcepServlet extends IcepServlet {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,14 +19,17 @@ public class IcepPrepareServlet extends PrepareServlet<IcepRequest, IcepResponse
|
||||
private final HashMap<Short, IcepServlet> servletmaps = new HashMap<>();
|
||||
|
||||
public IcepPrepareServlet() {
|
||||
BindingIcepServlet servlet = new BindingIcepServlet();
|
||||
this.servletmaps.put(servlet.getRequestid(), new BindingIcepServlet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Context context, AnyValue config) {
|
||||
}
|
||||
|
||||
public void addIcepServlet(IcepServlet servlet, AnyValue conf) {
|
||||
servlet.conf = conf;
|
||||
this.servletmaps.put(servlet.getRequestid(), servlet);
|
||||
}
|
||||
|
||||
// 28.[00,03,00,08, 21,12,a4,42,45,6f,4e,77,4e,47,71,55,32,37,77,39, 00,19,00,04,11,00,00,00]
|
||||
@Override
|
||||
public void execute(IcepRequest request, IcepResponse response) throws IOException {
|
||||
|
||||
@@ -22,18 +22,20 @@ public final class IcepServer extends Server {
|
||||
public IcepServer() {
|
||||
this(System.currentTimeMillis(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
"content":"{\"cmd\":\"icecandidate\",\"candidate\":{\"candidate\":\"candidate:3791502225 1 tcp 1518214911 10.28.2.207 0 typ host tcptype active generation 0\",\"sdpMid\":\"video\",\"sdpMLineIndex\":1}}"
|
||||
@param args
|
||||
@throws Exception
|
||||
*/
|
||||
"content":"{\"cmd\":\"icecandidate\",\"candidate\":{\"candidate\":\"candidate:3791502225 1 tcp 1518214911 10.28.2.207 0 typ host tcptype active generation 0\",\"sdpMid\":\"video\",\"sdpMLineIndex\":1}}"
|
||||
@param args
|
||||
@throws Exception
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
DefaultAnyValue conf = new DefaultAnyValue();
|
||||
conf.addValue("host", "10.28.2.207");
|
||||
conf.addValue("port", "3478");
|
||||
final CountDownLatch cdl = new CountDownLatch(1);
|
||||
final IcepServer server = new IcepServer();
|
||||
server.init(conf);
|
||||
server.init(conf);
|
||||
server.addIcepServlet(new BindingIcepServlet(), null);
|
||||
server.start();
|
||||
cdl.await();
|
||||
}
|
||||
@@ -47,6 +49,10 @@ public final class IcepServer extends Server {
|
||||
super.init(config);
|
||||
}
|
||||
|
||||
public void addIcepServlet(IcepServlet servlet, AnyValue conf) {
|
||||
((IcepPrepareServlet) this.prepare).addIcepServlet(servlet, conf);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Context createContext() {
|
||||
|
||||
72
src/com/wentch/redkale/net/icep/NodeIcepServer.java
Normal file
72
src/com/wentch/redkale/net/icep/NodeIcepServer.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.net.icep;
|
||||
|
||||
import com.wentch.redkale.boot.*;
|
||||
import com.wentch.redkale.boot.ClassFilter.FilterEntry;
|
||||
import com.wentch.redkale.net.*;
|
||||
import com.wentch.redkale.util.*;
|
||||
import com.wentch.redkale.util.AnyValue.DefaultAnyValue;
|
||||
import java.lang.reflect.*;
|
||||
import java.net.*;
|
||||
import java.util.logging.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@NodeProtocol({"ICEP"})
|
||||
public class NodeIcepServer extends NodeServer {
|
||||
|
||||
private final IcepServer icepServer;
|
||||
|
||||
public NodeIcepServer(Application application, AnyValue serconf) {
|
||||
super(application, application.getResourceFactory().createChild(), createServer(application, serconf));
|
||||
this.icepServer = (IcepServer) server;
|
||||
}
|
||||
|
||||
private static Server createServer(Application application, AnyValue serconf) {
|
||||
return new IcepServer(application.getStartTime(), application.getWatchFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getSocketAddress() {
|
||||
return icepServer == null ? null : icepServer.getSocketAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||
return createClassFilter(null, null, IcepServlet.class, null, "servlets", "servlet");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter) throws Exception {
|
||||
if (icepServer != null) loadIcepServlet(this.nodeConf.getAnyValue("servlets"), servletFilter);
|
||||
}
|
||||
|
||||
protected void loadIcepServlet(final AnyValue conf, ClassFilter<? extends Servlet> filter) throws Exception {
|
||||
final StringBuilder sb = logger.isLoggable(Level.FINE) ? new StringBuilder() : null;
|
||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
for (FilterEntry<? extends Servlet> en : filter.getFilterEntrys()) {
|
||||
Class<IcepServlet> clazz = (Class<IcepServlet>) en.getType();
|
||||
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
||||
final IcepServlet servlet = clazz.newInstance();
|
||||
factory.inject(servlet);
|
||||
DefaultAnyValue servletConf = (DefaultAnyValue) en.getProperty();
|
||||
this.icepServer.addIcepServlet(servlet, servletConf);
|
||||
if (sb != null) sb.append(threadName).append(" Loaded ").append(clazz.getName()).append(" --> ").append(format(servlet.getRequestid())).append(LINE_SEPARATOR);
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString());
|
||||
}
|
||||
|
||||
private static String format(short value) {
|
||||
String str = Integer.toHexString(value);
|
||||
if (str.length() == 1) return "0x000" + str;
|
||||
if (str.length() == 2) return "0x00" + str;
|
||||
if (str.length() == 3) return "0x0" + str;
|
||||
return "0x" + str;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user