This commit is contained in:
Redkale
2017-05-14 11:34:15 +08:00
parent 6d74355fc0
commit 853e823a8d
14 changed files with 290 additions and 61 deletions

View File

@@ -11,7 +11,6 @@ import java.util.*;
import javax.persistence.*; import javax.persistence.*;
import org.redkale.convert.json.JsonConvert; import org.redkale.convert.json.JsonConvert;
import org.redkale.net.http.*; import org.redkale.net.http.*;
import org.redkale.service.*;
import org.redkale.source.*; import org.redkale.source.*;
import org.redkale.util.*; import org.redkale.util.*;
@@ -24,9 +23,7 @@ import org.redkale.util.*;
* *
* @author zhangjx * @author zhangjx
*/ */
@AutoLoad(false) public final class ApiDocsService {
@Local
public final class ApiDocsService extends AbstractService {
private final Application app; //Application全局对象 private final Application app; //Application全局对象

View File

@@ -26,7 +26,7 @@ import org.redkale.service.Service;
import org.redkale.source.*; import org.redkale.source.*;
import org.redkale.util.AnyValue.DefaultAnyValue; import org.redkale.util.AnyValue.DefaultAnyValue;
import org.redkale.util.*; import org.redkale.util.*;
import org.redkale.watch.WatchFactory; import org.redkale.watch.*;
import org.w3c.dom.*; import org.w3c.dom.*;
/** /**
@@ -284,6 +284,10 @@ public final class Application {
return watchFactory; return watchFactory;
} }
public List<NodeServer> getNodeServers() {
return new ArrayList<>(servers);
}
public File getHome() { public File getHome() {
return home; return home;
} }
@@ -490,9 +494,12 @@ public final class Application {
CountDownLatch timecd = new CountDownLatch(entrys.length); CountDownLatch timecd = new CountDownLatch(entrys.length);
final List<AnyValue> sncps = new ArrayList<>(); final List<AnyValue> sncps = new ArrayList<>();
final List<AnyValue> others = new ArrayList<>(); final List<AnyValue> others = new ArrayList<>();
final List<AnyValue> watchs = new ArrayList<>();
for (final AnyValue entry : entrys) { for (final AnyValue entry : entrys) {
if (entry.getValue("protocol", "").toUpperCase().startsWith("SNCP")) { if (entry.getValue("protocol", "").toUpperCase().startsWith("SNCP")) {
sncps.add(entry); sncps.add(entry);
} else if (entry.getValue("protocol", "").toUpperCase().startsWith("WATCH")) {
watchs.add(entry);
} else { } else {
others.add(entry); others.add(entry);
} }
@@ -502,6 +509,7 @@ public final class Application {
runServers(timecd, sncps); //必须确保sncp都启动后再启动其他协议 runServers(timecd, sncps); //必须确保sncp都启动后再启动其他协议
runServers(timecd, others); runServers(timecd, others);
runServers(timecd, watchs); //必须在所有server都启动后再启动
timecd.await(); timecd.await();
logger.info(this.getClass().getSimpleName() + " started in " + (System.currentTimeMillis() - startTime) + " ms"); logger.info(this.getClass().getSimpleName() + " started in " + (System.currentTimeMillis() - startTime) + " ms");
if (!singletonrun) this.serversLatch.await(); if (!singletonrun) this.serversLatch.await();
@@ -530,13 +538,22 @@ public final class Application {
NodeServer server = null; NodeServer server = null;
if ("SNCP".equals(protocol)) { if ("SNCP".equals(protocol)) {
server = NodeSncpServer.createNodeServer(Application.this, serconf); server = NodeSncpServer.createNodeServer(Application.this, serconf);
} else if ("WATCH".equalsIgnoreCase(protocol)) {
DefaultAnyValue serconf2 = (DefaultAnyValue) serconf;
DefaultAnyValue rest = (DefaultAnyValue) serconf2.getAnyValue("rest");
if (rest == null) {
rest = new DefaultAnyValue();
serconf2.addValue("rest", rest);
}
rest.setValue("base", WatchServlet.class.getName());
server = new NodeWatchServer(Application.this, serconf);
} else if ("HTTP".equalsIgnoreCase(protocol)) { } else if ("HTTP".equalsIgnoreCase(protocol)) {
server = new NodeHttpServer(Application.this, serconf); server = new NodeHttpServer(Application.this, serconf);
} else { } else {
if (!inited.get()) { if (!inited.get()) {
synchronized (nodeClasses) { synchronized (nodeClasses) {
if (!inited.getAndSet(true)) { //加载自定义的协议SOCKS if (!inited.getAndSet(true)) { //加载自定义的协议SOCKS
ClassFilter profilter = new ClassFilter(NodeProtocol.class, NodeServer.class); ClassFilter profilter = new ClassFilter(NodeProtocol.class, NodeServer.class, (Class[]) null);
ClassFilter.Loader.load(home, serconf.getValue("excludelibs", "").split(";"), profilter); ClassFilter.Loader.load(home, serconf.getValue("excludelibs", "").split(";"), profilter);
final Set<FilterEntry<NodeServer>> entrys = profilter.getFilterEntrys(); final Set<FilterEntry<NodeServer>> entrys = profilter.getFilterEntrys();
for (FilterEntry<NodeServer> entry : entrys) { for (FilterEntry<NodeServer> entry : entrys) {

View File

@@ -40,6 +40,8 @@ public final class ClassFilter<T> {
private Class superClass; //符合的父类型。不为空时扫描结果的class必须是superClass的子类 private Class superClass; //符合的父类型。不为空时扫描结果的class必须是superClass的子类
private Class[] excludeSuperClasses; //不符合的父类型。
private Class<? extends Annotation> annotationClass;//符合的注解。不为空时扫描结果的class必须包含该注解 private Class<? extends Annotation> annotationClass;//符合的注解。不为空时扫描结果的class必须包含该注解
private Pattern[] includePatterns; //符合的classname正则表达式 private Pattern[] includePatterns; //符合的classname正则表达式
@@ -56,18 +58,19 @@ public final class ClassFilter<T> {
private AnyValue conf; //基本配置信息, 当符合条件时将conf的属性赋值到FilterEntry中去。 private AnyValue conf; //基本配置信息, 当符合条件时将conf的属性赋值到FilterEntry中去。
public ClassFilter(Class<? extends Annotation> annotationClass, Class superClass) { public ClassFilter(Class<? extends Annotation> annotationClass, Class superClass, Class[] excludeSuperClasses) {
this(annotationClass, superClass, null); this(annotationClass, superClass, excludeSuperClasses, null);
} }
public ClassFilter(Class<? extends Annotation> annotationClass, Class superClass, AnyValue conf) { public ClassFilter(Class<? extends Annotation> annotationClass, Class superClass, Class[] excludeSuperClasses, AnyValue conf) {
this.annotationClass = annotationClass; this.annotationClass = annotationClass;
this.superClass = superClass; this.superClass = superClass;
this.excludeSuperClasses = excludeSuperClasses;
this.conf = conf; this.conf = conf;
} }
public static ClassFilter create(String includeregs, String excluderegs, Set<String> includeValues, Set<String> excludeValues) { public static ClassFilter create(Class[] excludeSuperClasses, String includeregs, String excluderegs, Set<String> includeValues, Set<String> excludeValues) {
ClassFilter filter = new ClassFilter(null, null); ClassFilter filter = new ClassFilter(null, null, excludeSuperClasses);
filter.setIncludePatterns(includeregs == null ? null : includeregs.split(";")); filter.setIncludePatterns(includeregs == null ? null : includeregs.split(";"));
filter.setExcludePatterns(excluderegs == null ? null : excluderegs.split(";")); filter.setExcludePatterns(excluderegs == null ? null : excluderegs.split(";"));
filter.setPrivilegeIncludes(includeValues); filter.setPrivilegeIncludes(includeValues);
@@ -247,7 +250,13 @@ public final class ClassFilter<T> {
public boolean accept(AnyValue property, Class clazz, boolean autoscan) { public boolean accept(AnyValue property, Class clazz, boolean autoscan) {
if (this.refused || !Modifier.isPublic(clazz.getModifiers())) return false; if (this.refused || !Modifier.isPublic(clazz.getModifiers())) return false;
if (annotationClass != null && clazz.getAnnotation(annotationClass) == null) return false; if (annotationClass != null && clazz.getAnnotation(annotationClass) == null) return false;
return superClass == null || (clazz != superClass && superClass.isAssignableFrom(clazz)); boolean rs = superClass == null || (clazz != superClass && superClass.isAssignableFrom(clazz));
if (rs && this.excludeSuperClasses != null && this.excludeSuperClasses.length > 0) {
for (Class c : this.excludeSuperClasses) {
if (c != null && (clazz == c || clazz.isAssignableFrom(c))) return false;
}
}
return rs;
} }
public static Pattern[] toPattern(String[] regs) { public static Pattern[] toPattern(String[] regs) {
@@ -269,6 +278,18 @@ public final class ClassFilter<T> {
this.superClass = superClass; this.superClass = superClass;
} }
public Class getSuperClass() {
return superClass;
}
public Class[] getExcludeSuperClasses() {
return excludeSuperClasses;
}
public void setExcludeSuperClasses(Class[] excludeSuperClasses) {
this.excludeSuperClasses = excludeSuperClasses;
}
public void setAnnotationClass(Class<? extends Annotation> annotationClass) { public void setAnnotationClass(Class<? extends Annotation> annotationClass) {
this.annotationClass = annotationClass; this.annotationClass = annotationClass;
} }
@@ -293,10 +314,6 @@ public final class ClassFilter<T> {
return annotationClass; return annotationClass;
} }
public Class getSuperClass() {
return superClass;
}
public boolean isRefused() { public boolean isRefused() {
return refused; return refused;
} }

View File

@@ -5,8 +5,10 @@
*/ */
package org.redkale.boot; package org.redkale.boot;
import java.lang.annotation.Annotation;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.file.WatchService;
import java.util.*; import java.util.*;
import java.util.logging.Level; import java.util.logging.Level;
import javax.annotation.Resource; import javax.annotation.Resource;
@@ -17,6 +19,7 @@ import org.redkale.net.sncp.Sncp;
import org.redkale.service.*; import org.redkale.service.*;
import org.redkale.util.AnyValue.DefaultAnyValue; import org.redkale.util.AnyValue.DefaultAnyValue;
import org.redkale.util.*; import org.redkale.util.*;
import org.redkale.watch.WatchServlet;
/** /**
* HTTP Server节点的配置Server * HTTP Server节点的配置Server
@@ -50,7 +53,12 @@ public class NodeHttpServer extends NodeServer {
@Override @Override
protected ClassFilter<Servlet> createServletClassFilter() { protected ClassFilter<Servlet> createServletClassFilter() {
return createClassFilter(null, WebServlet.class, HttpServlet.class, null, "servlets", "servlet"); return createClassFilter(null, WebServlet.class, HttpServlet.class, new Class[]{WatchServlet.class}, null, "servlets", "servlet");
}
@Override
protected ClassFilter<Service> createServiceClassFilter() {
return createClassFilter(this.sncpGroup, null, Service.class, new Class[]{WatchService.class}, Annotation.class, "services", "service");
} }
@Override @Override
@@ -101,6 +109,7 @@ public class NodeHttpServer extends NodeServer {
final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>(); final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>();
for (FilterEntry<? extends Servlet> en : list) { for (FilterEntry<? extends Servlet> en : list) {
Class<HttpServlet> clazz = (Class<HttpServlet>) en.getType(); Class<HttpServlet> clazz = (Class<HttpServlet>) en.getType();
if (WatchServlet.class.isAssignableFrom(clazz)) continue; //给Watch服务使用
if (Modifier.isAbstract(clazz.getModifiers())) continue; if (Modifier.isAbstract(clazz.getModifiers())) continue;
WebServlet ws = clazz.getAnnotation(WebServlet.class); WebServlet ws = clazz.getAnnotation(WebServlet.class);
if (ws == null || ws.value().length == 0) continue; if (ws == null || ws.value().length == 0) continue;
@@ -159,7 +168,7 @@ public class NodeHttpServer extends NodeServer {
} }
} }
final ClassFilter restFilter = ClassFilter.create(restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues); final ClassFilter restFilter = ClassFilter.create(null, restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
super.interceptorServices.forEach((service) -> { super.interceptorServices.forEach((service) -> {
final Class stype = Sncp.getServiceType(service); final Class stype = Sncp.getServiceType(service);
@@ -172,6 +181,7 @@ public class NodeHttpServer extends NodeServer {
if (!restFilter.accept(stypename)) return; if (!restFilter.accept(stypename)) return;
HttpServlet servlet = httpServer.addRestServlet(name, stype, service, baseServletClass, prefix, (AnyValue) null); HttpServlet servlet = httpServer.addRestServlet(name, stype, service, baseServletClass, prefix, (AnyValue) null);
if (servlet == null) return; //没有HttpMapping方法的HttpServlet调用Rest.createRestServlet就会返回null
resourceFactory.inject(servlet, NodeHttpServer.this); resourceFactory.inject(servlet, NodeHttpServer.this);
if (finest) logger.finest(threadName + " Create RestServlet(resource.name='" + name + "') = " + servlet); if (finest) logger.finest(threadName + " Create RestServlet(resource.name='" + name + "') = " + servlet);
if (ss != null) { if (ss != null) {

View File

@@ -63,7 +63,7 @@ public abstract class NodeServer {
protected final Server server; protected final Server server;
//当前Server的SNCP协议的组 //当前Server的SNCP协议的组
private String sncpGroup = null; protected String sncpGroup = null;
//SNCP服务的地址 非SNCP为null //SNCP服务的地址 非SNCP为null
private InetSocketAddress sncpAddress; private InetSocketAddress sncpAddress;
@@ -492,12 +492,12 @@ public abstract class NodeServer {
protected abstract ClassFilter<Servlet> createServletClassFilter(); protected abstract ClassFilter<Servlet> createServletClassFilter();
protected ClassFilter<Service> createServiceClassFilter() { protected ClassFilter<Service> createServiceClassFilter() {
return createClassFilter(this.sncpGroup, null, Service.class, Annotation.class, "services", "service"); return createClassFilter(this.sncpGroup, null, Service.class, null, Annotation.class, "services", "service");
} }
protected ClassFilter createClassFilter(final String localGroup, Class<? extends Annotation> ref, protected ClassFilter createClassFilter(final String localGroup, Class<? extends Annotation> ref,
Class inter, Class<? extends Annotation> ref2, String properties, String property) { Class inter, Class[] excludeSuperClasses, Class<? extends Annotation> ref2, String properties, String property) {
ClassFilter cf = new ClassFilter(ref, inter, null); ClassFilter cf = new ClassFilter(ref, inter, excludeSuperClasses, null);
if (properties == null && properties == null) return cf; if (properties == null && properties == null) return cf;
if (this.serverConf == null) return cf; if (this.serverConf == null) return cf;
AnyValue[] proplist = this.serverConf.getAnyValues(properties); AnyValue[] proplist = this.serverConf.getAnyValues(properties);
@@ -515,7 +515,7 @@ public abstract class NodeServer {
prop = new AnyValue.DefaultAnyValue(); prop = new AnyValue.DefaultAnyValue();
prop.addValue("groups", sc); prop.addValue("groups", sc);
} }
ClassFilter filter = new ClassFilter(ref, inter, prop); ClassFilter filter = new ClassFilter(ref, inter, excludeSuperClasses, prop);
for (AnyValue av : list.getAnyValues(property)) { // <service> 或 <servlet> 节点 for (AnyValue av : list.getAnyValues(property)) { // <service> 或 <servlet> 节点
final AnyValue[] items = av.getAnyValues("property"); final AnyValue[] items = av.getAnyValues("property");
if (av instanceof DefaultAnyValue && items.length > 0) { //存在 <property>节点 if (av instanceof DefaultAnyValue && items.length > 0) { //存在 <property>节点

View File

@@ -0,0 +1,35 @@
/*
* 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 org.redkale.boot;
import java.lang.annotation.Annotation;
import org.redkale.net.*;
import org.redkale.net.http.*;
import org.redkale.service.Service;
import org.redkale.util.AnyValue;
import org.redkale.watch.*;
/**
*
* @author zhangjx
*/
@NodeProtocol({"WATCH"})
public class NodeWatchServer extends NodeHttpServer {
public NodeWatchServer(Application application, AnyValue serconf) {
super(application, serconf);
}
@Override
protected ClassFilter<Service> createServiceClassFilter() {
return createClassFilter(this.sncpGroup, null, WatchService.class, null, Annotation.class, "services", "service");
}
@Override
protected ClassFilter<Servlet> createServletClassFilter() {
return createClassFilter(null, WebServlet.class, WatchServlet.class, null, null, "servlets", "servlet");
}
}

View File

@@ -39,6 +39,50 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
protected final Map<String, Class> allMapStrings = new HashMap<>(); protected final Map<String, Class> allMapStrings = new HashMap<>();
private final Object excludeLock = new Object();
private Map<String, Predicate<String>> excludeUrlMaps; //禁用的URL的正则表达式, 必须与 excludeUrlPredicates 保持一致
private Predicate<String>[] excludeUrlPredicates; //禁用的URL的Predicate, 必须与 excludeUrlMaps 保持一致
public void addExcludeUrlReg(final String urlreg) {
if (urlreg == null || urlreg.isEmpty()) return;
synchronized (excludeLock) {
if (excludeUrlMaps != null && excludeUrlMaps.containsKey(urlreg)) return;
if (excludeUrlMaps == null) excludeUrlMaps = new HashMap<>();
Predicate<String> predicate = Pattern.compile(urlreg).asPredicate();
excludeUrlMaps.put(urlreg, predicate);
excludeUrlPredicates = Utility.append(excludeUrlPredicates, predicate);
}
}
public void removeExcludeUrlReg(final String urlreg) {
if (urlreg == null || urlreg.isEmpty()) return;
synchronized (excludeLock) {
if (excludeUrlMaps == null || excludeUrlPredicates == null || !excludeUrlMaps.containsKey(urlreg)) return;
Predicate<String> predicate = excludeUrlMaps.get(urlreg);
excludeUrlMaps.remove(urlreg);
int index = -1;
for (int i = 0; i < excludeUrlPredicates.length; i++) {
if (excludeUrlPredicates[i] == predicate) {
index = i;
break;
}
}
if (index > -1) {
if (excludeUrlPredicates.length == 1) {
excludeUrlPredicates = null;
} else {
int newlen = excludeUrlPredicates.length - 1;
Predicate[] news = new Predicate[newlen];
System.arraycopy(excludeUrlPredicates, 0, news, 0, index);
System.arraycopy(excludeUrlPredicates, index + 1, news, index, newlen - index);
excludeUrlPredicates = news;
}
}
}
}
@Override @Override
public void init(HttpContext context, AnyValue config) { public void init(HttpContext context, AnyValue config) {
Collection<HttpServlet> servlets = getServlets(); Collection<HttpServlet> servlets = getServlets();
@@ -83,6 +127,19 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
public void execute(HttpRequest request, HttpResponse response) throws IOException { public void execute(HttpRequest request, HttpResponse response) throws IOException {
try { try {
final String uri = request.getRequestURI(); final String uri = request.getRequestURI();
boolean forbid = false;
if (excludeUrlPredicates != null && excludeUrlPredicates.length > 0) {
for (Predicate<String> predicate : excludeUrlPredicates) {
if (predicate != null && predicate.test(uri)) {
forbid = true;
break;
}
}
}
if (forbid) {
response.finish(403, response.getHttpCode(403));
return;
}
Servlet<HttpContext, HttpRequest, HttpResponse> servlet = null; Servlet<HttpContext, HttpRequest, HttpResponse> servlet = null;
if (request.isWebSocket()) { if (request.isWebSocket()) {
servlet = wsmappings.get(uri); servlet = wsmappings.get(uri);

View File

@@ -23,7 +23,7 @@ import org.redkale.watch.WatchFactory;
* *
* @author zhangjx * @author zhangjx
*/ */
public final class HttpServer extends Server<String, HttpContext, HttpRequest, HttpResponse, HttpServlet> { public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpResponse, HttpServlet> {
public HttpServer() { public HttpServer() {
this(System.currentTimeMillis(), null); this(System.currentTimeMillis(), null);
@@ -139,6 +139,7 @@ public final class HttpServer extends Server<String, HttpContext, HttpRequest, H
} }
final boolean first = servlet == null; final boolean first = servlet == null;
if (servlet == null) servlet = Rest.createRestServlet(baseServletClass, serviceType); if (servlet == null) servlet = Rest.createRestServlet(baseServletClass, serviceType);
if (servlet == null) return null; //没有HttpMapping方法的HttpServlet调用Rest.createRestServlet就会返回null
try { //若提供动态变更Service服务功能则改Rest服务无法做出相应更新 try { //若提供动态变更Service服务功能则改Rest服务无法做出相应更新
Field field = servlet.getClass().getDeclaredField(Rest.REST_SERVICE_FIELD_NAME); Field field = servlet.getClass().getDeclaredField(Rest.REST_SERVICE_FIELD_NAME);
field.setAccessible(true); field.setAccessible(true);
@@ -258,4 +259,21 @@ public final class HttpServer extends Server<String, HttpContext, HttpRequest, H
return httpcontext; return httpcontext;
} }
/**
* 增加可以屏蔽的URL正则表达式
*
* @param urlreg URL正则表达式
*/
public void addExcludeUrlReg(final String urlreg) {
((HttpPrepareServlet) this.prepare).addExcludeUrlReg(urlreg);
}
/**
* 删除可以屏蔽的URL正则表达式
*
* @param urlreg URL正则表达式
*/
public void removeExcludeUrlReg(final String urlreg) {
((HttpPrepareServlet) this.prepare).removeExcludeUrlReg(urlreg);
}
} }

View File

@@ -135,7 +135,7 @@ public final class Rest {
final Class userType = hut == null ? Object.class : hut.value(); final Class userType = hut == null ? Object.class : hut.value();
final String supDynName = baseServletClass.getName().replace('.', '/'); final String supDynName = baseServletClass.getName().replace('.', '/');
final RestService controller = serviceType.getAnnotation(RestService.class); final RestService controller = serviceType.getAnnotation(RestService.class);
if (controller != null && controller.ignore()) return null; //标记为ignore=true不创建Servlet if (controller != null && controller.ignore()) throw new RuntimeException(baseServletClass + " is ignore Rest Service Class"); //标记为ignore=true不创建Servlet
ClassLoader loader = Sncp.class.getClassLoader(); ClassLoader loader = Sncp.class.getClassLoader();
String newDynName = serviceTypeInternalName.substring(0, serviceTypeInternalName.lastIndexOf('/') + 1) + "_Dyn" + serviceType.getSimpleName().replaceAll("Service.*$", "") + "RestServlet"; String newDynName = serviceTypeInternalName.substring(0, serviceTypeInternalName.lastIndexOf('/') + 1) + "_Dyn" + serviceType.getSimpleName().replaceAll("Service.*$", "") + "RestServlet";

View File

@@ -23,7 +23,7 @@ import org.redkale.watch.*;
* @author zhangjx * @author zhangjx
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class SncpServer extends Server<DLong, SncpContext, SncpRequest, SncpResponse, SncpServlet> { public class SncpServer extends Server<DLong, SncpContext, SncpRequest, SncpResponse, SncpServlet> {
public SncpServer() { public SncpServer() {
this(System.currentTimeMillis(), null); this(System.currentTimeMillis(), null);

View File

@@ -41,6 +41,8 @@ public final class ResourceFactory {
private static final ResourceFactory instance = new ResourceFactory(null); private static final ResourceFactory instance = new ResourceFactory(null);
private final List<WeakReference<ResourceFactory>> chidren = new CopyOnWriteArrayList<>();
private final ConcurrentHashMap<Type, ResourceLoader> loadermap = new ConcurrentHashMap(); private final ConcurrentHashMap<Type, ResourceLoader> loadermap = new ConcurrentHashMap();
private final ConcurrentHashMap<Type, ConcurrentHashMap<String, ResourceEntry>> store = new ConcurrentHashMap(); private final ConcurrentHashMap<Type, ConcurrentHashMap<String, ResourceEntry>> store = new ConcurrentHashMap();
@@ -54,7 +56,18 @@ public final class ResourceFactory {
} }
public ResourceFactory createChild() { public ResourceFactory createChild() {
return new ResourceFactory(this); ResourceFactory child = new ResourceFactory(this);
this.chidren.add(new WeakReference<>(child));
return child;
}
public List<ResourceFactory> getChildren() {
List<ResourceFactory> result = new ArrayList<>();
for (WeakReference<ResourceFactory> ref : chidren) {
ResourceFactory rf = ref.get();
if (rf != null) result.add(rf);
}
return result;
} }
public void release() { public void release() {

View File

@@ -13,13 +13,17 @@ import java.util.function.LongSupplier;
/** /**
* *
* <p> 详情见: https://redkale.org * <p>
* 详情见: https://redkale.org
*
* @author zhangjx * @author zhangjx
*/ */
public final class WatchFactory { public final class WatchFactory {
private static final WatchFactory instance = new WatchFactory(null); private static final WatchFactory instance = new WatchFactory(null);
private final List<WeakReference<WatchFactory>> chidren = new CopyOnWriteArrayList<>();
private final List<WeakReference<WatchNode>> beans = new CopyOnWriteArrayList<>(); private final List<WeakReference<WatchNode>> beans = new CopyOnWriteArrayList<>();
private final WatchFactory parent; private final WatchFactory parent;
@@ -29,7 +33,9 @@ public final class WatchFactory {
} }
public void register(WatchNode bean) { public void register(WatchNode bean) {
if (bean != null) beans.add(new WeakReference<>(bean)); if (bean == null) return;
checkName(bean.getName());
beans.add(new WeakReference<>(bean));
} }
public static WatchFactory root() { public static WatchFactory root() {
@@ -37,7 +43,27 @@ public final class WatchFactory {
} }
public WatchFactory createChild() { public WatchFactory createChild() {
return new WatchFactory(this); WatchFactory child = new WatchFactory(this);
this.chidren.add(new WeakReference<>(child));
return child;
}
public List<WatchFactory> getChildren() {
List<WatchFactory> result = new ArrayList<>();
for (WeakReference<WatchFactory> ref : chidren) {
WatchFactory rf = ref.get();
if (rf != null) result.add(rf);
}
return result;
}
public List<WatchNode> getWatchNodes() {
List<WatchNode> result = new ArrayList<>();
for (WeakReference<WatchNode> ref : beans) {
WatchNode rf = ref.get();
if (rf != null) result.add(rf);
}
return result;
} }
public WatchNumber createWatchNumber(String name) { public WatchNumber createWatchNumber(String name) {
@@ -74,6 +100,12 @@ public final class WatchFactory {
register(new WatchSupplier(name, description, supplier)); register(new WatchSupplier(name, description, supplier));
} }
public void checkName(String name) {
if (name == null || (!name.isEmpty() && !name.matches("^[a-zA-Z0-9_;/\\-\\.\\[\\]\\(\\)]+$")) || name.contains("//")) {
throw new IllegalArgumentException("Watch.name(" + name + ") contains illegal character, must be (a-z,A-Z,0-9,/,_,.,(,),-,[,]) and cannot contains //");
}
}
public boolean inject(final Object src) { public boolean inject(final Object src) {
return inject(src, new ArrayList<>()); return inject(src, new ArrayList<>());
} }

View File

@@ -0,0 +1,16 @@
/*
* 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 org.redkale.watch;
import org.redkale.service.*;
/**
*
* @author zhangjx
*/
public interface WatchService extends Service {
}

View File

@@ -0,0 +1,17 @@
/*
* 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 org.redkale.watch;
import org.redkale.net.http.HttpServlet;
/**
*
* <p> 详情见: https://redkale.org
* @author zhangjx
*/
public class WatchServlet extends HttpServlet {
}