This commit is contained in:
地平线
2015-09-16 10:53:45 +08:00
parent 28d65644fe
commit 1cc63fc12f
10 changed files with 208 additions and 30 deletions

View File

@@ -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"));

View File

@@ -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);
}
}
}
}

View File

@@ -27,6 +27,7 @@ import javax.annotation.*;
*
* @author zhangjx
*/
@NodeProtocol({"HTTP", "HTTPS"})
public final class NodeHttpServer extends NodeServer {
private final HttpServer httpServer;

View 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();
}

View File

@@ -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协议

View File

@@ -15,6 +15,7 @@ import java.util.logging.*;
*
* @author zhangjx
*/
@NodeProtocol({"SNCP"})
public final class NodeSncpServer extends NodeServer {
private final SncpServer sncpServer;

View File

@@ -15,7 +15,6 @@ import java.nio.*;
*
* @author zhangjx
*/
@AutoLoad(false)
public class BindingIcepServlet extends IcepServlet {
@Override

View File

@@ -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 {

View File

@@ -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() {

View 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;
}
}