This commit is contained in:
@@ -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全局对象
|
||||||
|
|
||||||
|
|||||||
@@ -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.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,15 +142,15 @@ public final class Application {
|
|||||||
|
|
||||||
//Server启动的计数器,用于确保所有Server都启动完后再进行下一步处理
|
//Server启动的计数器,用于确保所有Server都启动完后再进行下一步处理
|
||||||
private final CountDownLatch serversLatch;
|
private final CountDownLatch serversLatch;
|
||||||
|
|
||||||
private Application(final AnyValue config) {
|
private Application(final AnyValue config) {
|
||||||
this(false, config);
|
this(false, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Application(final boolean singletonrun, final AnyValue config) {
|
private Application(final boolean singletonrun, final AnyValue config) {
|
||||||
this.singletonrun = singletonrun;
|
this.singletonrun = singletonrun;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
||||||
final File root = new File(System.getProperty(RESNAME_APP_HOME));
|
final File root = new File(System.getProperty(RESNAME_APP_HOME));
|
||||||
this.resourceFactory.register(RESNAME_APP_TIME, long.class, this.startTime);
|
this.resourceFactory.register(RESNAME_APP_TIME, long.class, this.startTime);
|
||||||
this.resourceFactory.register(RESNAME_APP_HOME, Path.class, root.toPath());
|
this.resourceFactory.register(RESNAME_APP_HOME, Path.class, root.toPath());
|
||||||
@@ -193,7 +193,7 @@ public final class Application {
|
|||||||
properties.entrySet().stream().forEach(x -> {
|
properties.entrySet().stream().forEach(x -> {
|
||||||
x.setValue(x.getValue().toString().replace("${APP_HOME}", rootpath));
|
x.setValue(x.getValue().toString().replace("${APP_HOME}", rootpath));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (properties.getProperty("java.util.logging.FileHandler.formatter") == null) {
|
if (properties.getProperty("java.util.logging.FileHandler.formatter") == null) {
|
||||||
properties.setProperty("java.util.logging.FileHandler.formatter", LogFileHandler.LoggingFormater.class.getName());
|
properties.setProperty("java.util.logging.FileHandler.formatter", LogFileHandler.LoggingFormater.class.getName());
|
||||||
}
|
}
|
||||||
@@ -275,27 +275,31 @@ public final class Application {
|
|||||||
this.transportExecutor = transportExec;
|
this.transportExecutor = transportExec;
|
||||||
this.transportChannelGroup = transportGroup;
|
this.transportChannelGroup = transportGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceFactory getResourceFactory() {
|
public ResourceFactory getResourceFactory() {
|
||||||
return resourceFactory;
|
return resourceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WatchFactory getWatchFactory() {
|
public WatchFactory getWatchFactory() {
|
||||||
return watchFactory;
|
return watchFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<NodeServer> getNodeServers() {
|
||||||
|
return new ArrayList<>(servers);
|
||||||
|
}
|
||||||
|
|
||||||
public File getHome() {
|
public File getHome() {
|
||||||
return home;
|
return home;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getStartTime() {
|
public long getStartTime() {
|
||||||
return startTime;
|
return startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initLogging() {
|
private void initLogging() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init() throws Exception {
|
public void init() throws Exception {
|
||||||
System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "" + Runtime.getRuntime().availableProcessors() * 4);
|
System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "" + Runtime.getRuntime().availableProcessors() * 4);
|
||||||
System.setProperty("convert.bson.tiny", "true");
|
System.setProperty("convert.bson.tiny", "true");
|
||||||
@@ -304,7 +308,7 @@ public final class Application {
|
|||||||
System.setProperty("convert.json.pool.size", "128");
|
System.setProperty("convert.json.pool.size", "128");
|
||||||
System.setProperty("convert.bson.writer.buffer.defsize", "4096");
|
System.setProperty("convert.bson.writer.buffer.defsize", "4096");
|
||||||
System.setProperty("convert.json.writer.buffer.defsize", "4096");
|
System.setProperty("convert.json.writer.buffer.defsize", "4096");
|
||||||
|
|
||||||
File persist = new File(this.home, "conf/persistence.xml");
|
File persist = new File(this.home, "conf/persistence.xml");
|
||||||
final String homepath = this.home.getCanonicalPath();
|
final String homepath = this.home.getCanonicalPath();
|
||||||
if (persist.isFile()) System.setProperty(DataSources.DATASOURCE_CONFPATH, persist.getCanonicalPath());
|
if (persist.isFile()) System.setProperty(DataSources.DATASOURCE_CONFPATH, persist.getCanonicalPath());
|
||||||
@@ -357,7 +361,7 @@ public final class Application {
|
|||||||
this.resourceFactory.register(JsonFactory.root().getConvert());
|
this.resourceFactory.register(JsonFactory.root().getConvert());
|
||||||
initResources();
|
initResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initResources() throws Exception {
|
private void initResources() throws Exception {
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
final AnyValue resources = config.getAnyValue("resources");
|
final AnyValue resources = config.getAnyValue("resources");
|
||||||
@@ -386,14 +390,14 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startSelfServer() throws Exception {
|
private void startSelfServer() throws Exception {
|
||||||
final Application application = this;
|
final Application application = this;
|
||||||
new Thread() {
|
new Thread() {
|
||||||
{
|
{
|
||||||
setName("Application-Control-Thread");
|
setName("Application-Control-Thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
@@ -451,7 +455,7 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendCommand(String command) throws Exception {
|
private void sendCommand(String command) throws Exception {
|
||||||
final DatagramChannel channel = DatagramChannel.open();
|
final DatagramChannel channel = DatagramChannel.open();
|
||||||
channel.configureBlocking(true);
|
channel.configureBlocking(true);
|
||||||
@@ -484,15 +488,18 @@ public final class Application {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() throws Exception {
|
public void start() throws Exception {
|
||||||
final AnyValue[] entrys = config.getAnyValues("server");
|
final AnyValue[] entrys = config.getAnyValues("server");
|
||||||
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,11 +509,12 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void runServers(CountDownLatch timecd, final List<AnyValue> serconfs) throws Exception {
|
private void runServers(CountDownLatch timecd, final List<AnyValue> serconfs) throws Exception {
|
||||||
this.servicecdl = new CountDownLatch(serconfs.size());
|
this.servicecdl = new CountDownLatch(serconfs.size());
|
||||||
@@ -520,7 +528,7 @@ public final class Application {
|
|||||||
setName(serconf.getValue("protocol", "Server").toUpperCase() + "-" + host + ":" + serconf.getIntValue("port") + "-Thread");
|
setName(serconf.getValue("protocol", "Server").toUpperCase() + "-" + host + ":" + serconf.getIntValue("port") + "-Thread");
|
||||||
this.setDaemon(true);
|
this.setDaemon(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
@@ -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) {
|
||||||
@@ -577,11 +594,11 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
sercdl.await();
|
sercdl.await();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Service> T singleton(Class<T> serviceClass) throws Exception {
|
public static <T extends Service> T singleton(Class<T> serviceClass) throws Exception {
|
||||||
return singleton("", serviceClass);
|
return singleton("", serviceClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Service> T singleton(String name, Class<T> serviceClass) throws Exception {
|
public static <T extends Service> T singleton(String name, Class<T> serviceClass) throws Exception {
|
||||||
if (serviceClass == null) throw new IllegalArgumentException("serviceClass is null");
|
if (serviceClass == null) throw new IllegalArgumentException("serviceClass is null");
|
||||||
final Application application = Application.create(true);
|
final Application application = Application.create(true);
|
||||||
@@ -595,14 +612,14 @@ public final class Application {
|
|||||||
if (serviceClass.isInterface()) throw new IllegalArgumentException("interface class not allowed");
|
if (serviceClass.isInterface()) throw new IllegalArgumentException("interface class not allowed");
|
||||||
throw new IllegalArgumentException(serviceClass.getName() + " maybe have zero not-final public method");
|
throw new IllegalArgumentException(serviceClass.getName() + " maybe have zero not-final public method");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Application create(final boolean singleton) throws IOException {
|
public static Application create(final boolean singleton) throws IOException {
|
||||||
final String home = new File(System.getProperty(RESNAME_APP_HOME, "")).getCanonicalPath();
|
final String home = new File(System.getProperty(RESNAME_APP_HOME, "")).getCanonicalPath();
|
||||||
System.setProperty(RESNAME_APP_HOME, home);
|
System.setProperty(RESNAME_APP_HOME, home);
|
||||||
File appfile = new File(home, "conf/application.xml");
|
File appfile = new File(home, "conf/application.xml");
|
||||||
return new Application(singleton, load(new FileInputStream(appfile)));
|
return new Application(singleton, load(new FileInputStream(appfile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
Utility.midnight(); //先初始化一下Utility
|
Utility.midnight(); //先初始化一下Utility
|
||||||
//运行主程序
|
//运行主程序
|
||||||
@@ -624,7 +641,7 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> findSncpGroups(Transport sameGroupTransport, Collection<Transport> diffGroupTransports) {
|
Set<String> findSncpGroups(Transport sameGroupTransport, Collection<Transport> diffGroupTransports) {
|
||||||
Set<String> gs = new HashSet<>();
|
Set<String> gs = new HashSet<>();
|
||||||
if (sameGroupTransport != null) gs.add(sameGroupTransport.getName());
|
if (sameGroupTransport != null) gs.add(sameGroupTransport.getName());
|
||||||
@@ -635,7 +652,7 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
return gs;
|
return gs;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeSncpServer findNodeSncpServer(final InetSocketAddress sncpAddr) {
|
NodeSncpServer findNodeSncpServer(final InetSocketAddress sncpAddr) {
|
||||||
for (NodeServer node : servers) {
|
for (NodeServer node : servers) {
|
||||||
if (node.isSNCP() && sncpAddr.equals(node.getSncpAddress())) {
|
if (node.isSNCP() && sncpAddr.equals(node.getSncpAddress())) {
|
||||||
@@ -644,12 +661,12 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupInfo findGroupInfo(String group) {
|
GroupInfo findGroupInfo(String group) {
|
||||||
if (group == null) return null;
|
if (group == null) return null;
|
||||||
return globalGroups.get(group);
|
return globalGroups.get(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shutdown() throws Exception {
|
private void shutdown() throws Exception {
|
||||||
servers.stream().forEach((server) -> {
|
servers.stream().forEach((server) -> {
|
||||||
try {
|
try {
|
||||||
@@ -660,7 +677,7 @@ public final class Application {
|
|||||||
serversLatch.countDown();
|
serversLatch.countDown();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (DataSource source : dataSources) {
|
for (DataSource source : dataSources) {
|
||||||
try {
|
try {
|
||||||
source.getClass().getMethod("close").invoke(source);
|
source.getClass().getMethod("close").invoke(source);
|
||||||
@@ -683,7 +700,7 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AnyValue load(final InputStream in0) {
|
private static AnyValue load(final InputStream in0) {
|
||||||
final DefaultAnyValue any = new DefaultAnyValue();
|
final DefaultAnyValue any = new DefaultAnyValue();
|
||||||
try (final InputStream in = in0) {
|
try (final InputStream in = in0) {
|
||||||
@@ -697,7 +714,7 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
return any;
|
return any;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void load(final DefaultAnyValue any, final Node root) {
|
private static void load(final DefaultAnyValue any, final Node root) {
|
||||||
final String home = System.getProperty(RESNAME_APP_HOME);
|
final String home = System.getProperty(RESNAME_APP_HOME);
|
||||||
NamedNodeMap nodes = root.getAttributes();
|
NamedNodeMap nodes = root.getAttributes();
|
||||||
@@ -715,6 +732,6 @@ public final class Application {
|
|||||||
load(sub, node);
|
load(sub, node);
|
||||||
any.addValue(node.getNodeName(), sub);
|
any.addValue(node.getNodeName(), sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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>节点
|
||||||
|
|||||||
35
src/org/redkale/boot/NodeWatchServer.java
Normal file
35
src/org/redkale/boot/NodeWatchServer.java
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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<>());
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/org/redkale/watch/WatchService.java
Normal file
16
src/org/redkale/watch/WatchService.java
Normal 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 {
|
||||||
|
|
||||||
|
}
|
||||||
17
src/org/redkale/watch/WatchServlet.java
Normal file
17
src/org/redkale/watch/WatchServlet.java
Normal 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 {
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user