This commit is contained in:
@@ -415,7 +415,7 @@ public final class Application {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}, Application.class, WatchFactory.class, NodeSncpServer.class, NodeHttpServer.class, NodeWatchServer.class);
|
}, Application.class, NodeSncpServer.class, NodeHttpServer.class, NodeWatchServer.class);
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
initResources();
|
initResources();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,14 @@ public abstract class PrepareServlet<K extends Serializable, C extends Context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void removeServlet(S servlet) {
|
||||||
|
synchronized (lock1) {
|
||||||
|
Set<S> newservlets = new HashSet<>(servlets);
|
||||||
|
newservlets.remove(servlet);
|
||||||
|
this.servlets = newservlets;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void putMapping(K key, S servlet) {
|
protected void putMapping(K key, S servlet) {
|
||||||
synchronized (lock2) {
|
synchronized (lock2) {
|
||||||
Map<K, S> newmappings = new HashMap<>(mappings);
|
Map<K, S> newmappings = new HashMap<>(mappings);
|
||||||
@@ -63,6 +71,28 @@ public abstract class PrepareServlet<K extends Serializable, C extends Context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void removeMapping(K key) {
|
||||||
|
synchronized (lock2) {
|
||||||
|
Map<K, S> newmappings = new HashMap<>(mappings);
|
||||||
|
newmappings.remove(key);
|
||||||
|
this.mappings = newmappings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void removeMapping(S servlet) {
|
||||||
|
synchronized (lock2) {
|
||||||
|
List<K> keys = new ArrayList<>();
|
||||||
|
Map<K, S> newmappings = new HashMap<>(mappings);
|
||||||
|
for (Map.Entry<K, S> en : newmappings.entrySet()) {
|
||||||
|
if (en.getValue().equals(servlet)) {
|
||||||
|
keys.add(en.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (K key : keys) newmappings.remove(key);
|
||||||
|
this.mappings = newmappings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected S mappingServlet(K key) {
|
protected S mappingServlet(K key) {
|
||||||
return mappings.get(key);
|
return mappings.get(key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ package org.redkale.net.http;
|
|||||||
import org.redkale.util.AnyValue.DefaultAnyValue;
|
import org.redkale.util.AnyValue.DefaultAnyValue;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.AbstractMap.SimpleEntry;
|
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
import java.util.regex.*;
|
import java.util.regex.*;
|
||||||
@@ -28,12 +27,12 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
|
|||||||
|
|
||||||
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
|
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
|
||||||
|
|
||||||
protected SimpleEntry<Predicate<String>, HttpServlet>[] regArray = null; //regArray 包含 regWsArray
|
protected MappingEntry[] regArray = null; //regArray 包含 regWsArray
|
||||||
|
|
||||||
|
protected MappingEntry[] regWsArray = null;
|
||||||
|
|
||||||
protected Map<String, WebSocketServlet> wsmappings = new HashMap<>(); //super.mappings 包含 wsmappings
|
protected Map<String, WebSocketServlet> wsmappings = new HashMap<>(); //super.mappings 包含 wsmappings
|
||||||
|
|
||||||
protected SimpleEntry<Predicate<String>, WebSocketServlet>[] regWsArray = null;
|
|
||||||
|
|
||||||
protected HttpServlet resourceHttpServlet = new HttpResourceServlet();
|
protected HttpServlet resourceHttpServlet = new HttpResourceServlet();
|
||||||
|
|
||||||
protected final Map<String, Class> allMapStrings = new HashMap<>();
|
protected final Map<String, Class> allMapStrings = new HashMap<>();
|
||||||
@@ -44,6 +43,30 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
|
|||||||
|
|
||||||
private BiPredicate<String, String>[] forbidURIPredicates; //禁用的URL的Predicate, 必须与 forbidURIMaps 保持一致
|
private BiPredicate<String, String>[] forbidURIPredicates; //禁用的URL的Predicate, 必须与 forbidURIMaps 保持一致
|
||||||
|
|
||||||
|
public HttpServlet removeHttpServlet(HttpServlet servlet) {
|
||||||
|
HttpServlet rs = null;
|
||||||
|
synchronized (allMapStrings) {
|
||||||
|
//待开发
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends HttpServlet> HttpServlet removeHttpServlet(Class<T> servletType) {
|
||||||
|
HttpServlet rs = null;
|
||||||
|
synchronized (allMapStrings) {
|
||||||
|
//待开发
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpServlet removeHttpServlet(String mapping) {
|
||||||
|
HttpServlet rs = null;
|
||||||
|
synchronized (allMapStrings) {
|
||||||
|
//待开发
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean addForbidURIReg(final String urlreg) {
|
public boolean addForbidURIReg(final String urlreg) {
|
||||||
if (urlreg == null || urlreg.isEmpty()) return false;
|
if (urlreg == null || urlreg.isEmpty()) return false;
|
||||||
synchronized (excludeLock) {
|
synchronized (excludeLock) {
|
||||||
@@ -140,9 +163,9 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
|
|||||||
if (request.isWebSocket()) {
|
if (request.isWebSocket()) {
|
||||||
servlet = wsmappings.get(uri);
|
servlet = wsmappings.get(uri);
|
||||||
if (servlet == null && this.regWsArray != null) {
|
if (servlet == null && this.regWsArray != null) {
|
||||||
for (SimpleEntry<Predicate<String>, WebSocketServlet> en : regWsArray) {
|
for (MappingEntry en : regWsArray) {
|
||||||
if (en.getKey().test(uri)) {
|
if (en.predicate.test(uri)) {
|
||||||
servlet = en.getValue();
|
servlet = en.servlet;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,9 +177,9 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
|
|||||||
} else {
|
} else {
|
||||||
servlet = mappingServlet(uri);
|
servlet = mappingServlet(uri);
|
||||||
if (servlet == null && this.regArray != null) {
|
if (servlet == null && this.regArray != null) {
|
||||||
for (SimpleEntry<Predicate<String>, HttpServlet> en : regArray) {
|
for (MappingEntry en : regArray) {
|
||||||
if (en.getKey().test(uri)) {
|
if (en.predicate.test(uri)) {
|
||||||
servlet = en.getValue();
|
servlet = en.servlet;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,19 +239,19 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
|
|||||||
mapping = mapping + "$";
|
mapping = mapping + "$";
|
||||||
}
|
}
|
||||||
if (regArray == null) {
|
if (regArray == null) {
|
||||||
regArray = new SimpleEntry[1];
|
regArray = new MappingEntry[1];
|
||||||
regArray[0] = new SimpleEntry<>(Pattern.compile(mapping).asPredicate(), servlet);
|
regArray[0] = new MappingEntry(mapping, Pattern.compile(mapping).asPredicate(), servlet);
|
||||||
} else {
|
} else {
|
||||||
regArray = Arrays.copyOf(regArray, regArray.length + 1);
|
regArray = Arrays.copyOf(regArray, regArray.length + 1);
|
||||||
regArray[regArray.length - 1] = new SimpleEntry<>(Pattern.compile(mapping).asPredicate(), servlet);
|
regArray[regArray.length - 1] = new MappingEntry(mapping, Pattern.compile(mapping).asPredicate(), servlet);
|
||||||
}
|
}
|
||||||
if (servlet instanceof WebSocketServlet) {
|
if (servlet instanceof WebSocketServlet) {
|
||||||
if (regWsArray == null) {
|
if (regWsArray == null) {
|
||||||
regWsArray = new SimpleEntry[1];
|
regWsArray = new MappingEntry[1];
|
||||||
regWsArray[0] = new SimpleEntry<>(Pattern.compile(mapping).asPredicate(), (WebSocketServlet) servlet);
|
regWsArray[0] = new MappingEntry(mapping, Pattern.compile(mapping).asPredicate(), (WebSocketServlet) servlet);
|
||||||
} else {
|
} else {
|
||||||
regWsArray = Arrays.copyOf(regWsArray, regWsArray.length + 1);
|
regWsArray = Arrays.copyOf(regWsArray, regWsArray.length + 1);
|
||||||
regWsArray[regWsArray.length - 1] = new SimpleEntry<>(Pattern.compile(mapping).asPredicate(), (WebSocketServlet) servlet);
|
regWsArray[regWsArray.length - 1] = new MappingEntry(mapping, Pattern.compile(mapping).asPredicate(), (WebSocketServlet) servlet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (mapping != null && !mapping.isEmpty()) {
|
} else if (mapping != null && !mapping.isEmpty()) {
|
||||||
@@ -285,4 +308,19 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
|
|||||||
this.regWsArray = null;
|
this.regWsArray = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static class MappingEntry {
|
||||||
|
|
||||||
|
public final String mapping;
|
||||||
|
|
||||||
|
public final Predicate<String> predicate;
|
||||||
|
|
||||||
|
public final HttpServlet servlet;
|
||||||
|
|
||||||
|
public MappingEntry(String mapping, Predicate<String> predicate, HttpServlet servlet) {
|
||||||
|
this.mapping = mapping;
|
||||||
|
this.predicate = predicate;
|
||||||
|
this.servlet = servlet;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,40 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
|
|||||||
return (HttpFilter) this.prepare.removeFilter(filterName);
|
return (HttpFilter) this.prepare.removeFilter(filterName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除HttpServlet
|
||||||
|
*
|
||||||
|
* @param servlet HttpServlet
|
||||||
|
*
|
||||||
|
* @return HttpServlet
|
||||||
|
*/
|
||||||
|
public HttpServlet removeHttpServlet(HttpServlet servlet) {
|
||||||
|
return ((HttpPrepareServlet) this.prepare).removeHttpServlet(servlet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除HttpServlet
|
||||||
|
*
|
||||||
|
* @param <T> 泛型
|
||||||
|
* @param servletType Class
|
||||||
|
*
|
||||||
|
* @return HttpServlet
|
||||||
|
*/
|
||||||
|
public <T extends HttpServlet> HttpServlet removeHttpServlet(Class<T> servletType) {
|
||||||
|
return ((HttpPrepareServlet) this.prepare).removeHttpServlet(servletType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除HttpServlet
|
||||||
|
*
|
||||||
|
* @param mapping String
|
||||||
|
*
|
||||||
|
* @return HttpServlet
|
||||||
|
*/
|
||||||
|
public HttpServlet removeHttpServlet(String mapping) {
|
||||||
|
return ((HttpPrepareServlet) this.prepare).removeHttpServlet(mapping);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 屏蔽请求URL的正则表达式
|
* 屏蔽请求URL的正则表达式
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -42,10 +42,6 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
|
|
||||||
private final boolean finest = logger.isLoggable(Level.FINEST);
|
private final boolean finest = logger.isLoggable(Level.FINEST);
|
||||||
|
|
||||||
private final Class<? extends Service> type;
|
|
||||||
|
|
||||||
private final String serviceName;
|
|
||||||
|
|
||||||
private final DLong serviceid;
|
private final DLong serviceid;
|
||||||
|
|
||||||
private final HashMap<DLong, SncpServletAction> actions = new HashMap<>();
|
private final HashMap<DLong, SncpServletAction> actions = new HashMap<>();
|
||||||
@@ -53,8 +49,7 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
private Supplier<ByteBuffer> bufferSupplier;
|
private Supplier<ByteBuffer> bufferSupplier;
|
||||||
|
|
||||||
public SncpDynServlet(final BsonConvert convert, final String serviceName, final Class<? extends Service> type, final Service service) {
|
public SncpDynServlet(final BsonConvert convert, final String serviceName, final Class<? extends Service> type, final Service service) {
|
||||||
this.serviceName = serviceName;
|
super(serviceName, type, service);
|
||||||
this.type = type;
|
|
||||||
this.serviceid = Sncp.hash(type.getName() + ':' + serviceName);
|
this.serviceid = Sncp.hash(type.getName() + ':' + serviceName);
|
||||||
Set<DLong> actionids = new HashSet<>();
|
Set<DLong> actionids = new HashSet<>();
|
||||||
for (java.lang.reflect.Method method : service.getClass().getMethods()) {
|
for (java.lang.reflect.Method method : service.getClass().getMethods()) {
|
||||||
|
|||||||
@@ -25,15 +25,30 @@ public class SncpPrepareServlet extends PrepareServlet<DLong, SncpContext, SncpR
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addServlet(SncpServlet servlet, Object attachment, AnyValue conf, DLong... mappings) {
|
public void addServlet(SncpServlet servlet, Object attachment, AnyValue conf, DLong... mappings) {
|
||||||
addServlet((SncpServlet) servlet, conf);
|
addSncpServlet((SncpServlet) servlet, conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addServlet(SncpServlet servlet, AnyValue conf) {
|
public void addSncpServlet(SncpServlet servlet, AnyValue conf) {
|
||||||
setServletConf(servlet, conf);
|
setServletConf(servlet, conf);
|
||||||
putMapping(servlet.getServiceid(), servlet);
|
putMapping(servlet.getServiceid(), servlet);
|
||||||
putServlet(servlet);
|
putServlet(servlet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T> SncpServlet removeSncpServlet(String name, Class<T> type) {
|
||||||
|
SncpServlet rs = null;
|
||||||
|
for (SncpServlet servlet : getServlets()) {
|
||||||
|
if (servlet.serviceName.equals(name) && servlet.type.equals(type)) {
|
||||||
|
rs = servlet;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rs != null) {
|
||||||
|
removeMapping(rs);
|
||||||
|
removeServlet(rs);
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
public List<SncpServlet> getSncpServlets() {
|
public List<SncpServlet> getSncpServlets() {
|
||||||
return new ArrayList<>(getServlets());
|
return new ArrayList<>(getServlets());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,35 @@ public class SncpServer extends Server<DLong, SncpContext, SncpRequest, SncpResp
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除SncpServlet
|
||||||
|
*
|
||||||
|
* @param <T> 泛型
|
||||||
|
* @param resname String
|
||||||
|
* @param type Class
|
||||||
|
*
|
||||||
|
* @return SncpServlet
|
||||||
|
*/
|
||||||
|
public <T extends Service> SncpServlet removeSncpServlet(String resname, Class<T> type) {
|
||||||
|
return ((SncpPrepareServlet) this.prepare).removeSncpServlet(resname, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除SncpServlet
|
||||||
|
*
|
||||||
|
* @param sncpService Service
|
||||||
|
*
|
||||||
|
* @return SncpServlet
|
||||||
|
*/
|
||||||
|
public SncpServlet removeSncpServlet(Service sncpService) {
|
||||||
|
SncpServlet servlet = null;
|
||||||
|
String resname = Sncp.getResourceName(sncpService);
|
||||||
|
for (Class type : Sncp.getResourceTypes(sncpService)) {
|
||||||
|
servlet = ((SncpPrepareServlet) this.prepare).removeSncpServlet(resname, type);
|
||||||
|
}
|
||||||
|
return servlet;
|
||||||
|
}
|
||||||
|
|
||||||
public void addSncpServlet(Service sncpService) {
|
public void addSncpServlet(Service sncpService) {
|
||||||
for (Class type : Sncp.getResourceTypes(sncpService)) {
|
for (Class type : Sncp.getResourceTypes(sncpService)) {
|
||||||
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), Sncp.getResourceName(sncpService), type, sncpService);
|
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), Sncp.getResourceName(sncpService), type, sncpService);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package org.redkale.net.sncp;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
|
import org.redkale.service.Service;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,6 +20,26 @@ import org.redkale.util.*;
|
|||||||
*/
|
*/
|
||||||
public abstract class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse> implements Comparable<SncpServlet> {
|
public abstract class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse> implements Comparable<SncpServlet> {
|
||||||
|
|
||||||
|
protected final Class<? extends Service> type;
|
||||||
|
|
||||||
|
protected final String serviceName;
|
||||||
|
|
||||||
|
protected final Service service;
|
||||||
|
|
||||||
|
protected SncpServlet(String serviceName, Class<? extends Service> type, Service service) {
|
||||||
|
this.type = type;
|
||||||
|
this.service = service;
|
||||||
|
this.serviceName = serviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Service getService() {
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServiceName() {
|
||||||
|
return serviceName;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract DLong getServiceid();
|
public abstract DLong getServiceid();
|
||||||
|
|
||||||
protected ExecutorService getExecutor() {
|
protected ExecutorService getExecutor() {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.charset.*;
|
import java.nio.charset.*;
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
import javax.net.ssl.*;
|
import javax.net.ssl.*;
|
||||||
|
|
||||||
@@ -276,6 +277,30 @@ public final class Utility {
|
|||||||
return news;
|
return news;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将符合条件的元素从数组中删除
|
||||||
|
*
|
||||||
|
* @param <T> 泛型
|
||||||
|
* @param array 原数组
|
||||||
|
* @param filter Predicate
|
||||||
|
*
|
||||||
|
* @return 新数组
|
||||||
|
*/
|
||||||
|
public static <T> T[] remove(final T[] array, final Predicate filter) {
|
||||||
|
if (array == null || array.length == 0 || filter == null) return array;
|
||||||
|
final T[] news = (T[]) Array.newInstance(array.getClass().getComponentType(), array.length);
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < news.length; i++) {
|
||||||
|
if (!filter.test(array[i])) {
|
||||||
|
news[index++] = array[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index == news.length) return news;
|
||||||
|
final T[] rs = (T[]) Array.newInstance(array.getClass().getComponentType(), index);
|
||||||
|
System.arraycopy(news, 0, rs, 0, index);
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断字符串是否包含指定的字符,包含返回true
|
* 判断字符串是否包含指定的字符,包含返回true
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.watch;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
|
||||||
import java.util.function.LongSupplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 详情见: https://redkale.org
|
|
||||||
*
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class WatchFactory {
|
|
||||||
|
|
||||||
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 String name;
|
|
||||||
|
|
||||||
private final WatchFactory parent;
|
|
||||||
|
|
||||||
private WatchFactory(String name, WatchFactory parent) {
|
|
||||||
this.name = name;
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(WatchNode bean) {
|
|
||||||
if (bean == null) return;
|
|
||||||
checkName(bean.getName());
|
|
||||||
beans.add(new WeakReference<>(bean));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static WatchFactory root() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WatchFactory createChild(final String name) {
|
|
||||||
WatchFactory child = new WatchFactory(name, 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) {
|
|
||||||
return createWatchNumber(name, "", false, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WatchNumber createWatchNumber(String name, boolean interval) {
|
|
||||||
return createWatchNumber(name, "", interval, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WatchNumber createWatchNumber(String name, String description) {
|
|
||||||
return createWatchNumber(name, description, false, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WatchNumber createWatchNumber(String name, String description, long v) {
|
|
||||||
return createWatchNumber(name, description, false, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WatchNumber createWatchNumber(String name, String description, boolean interval) {
|
|
||||||
return createWatchNumber(name, description, interval, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WatchNumber createWatchNumber(String name, String description, boolean interval, long v) {
|
|
||||||
return new WatchNumber(name, description, interval, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(String name, LongSupplier supplier) {
|
|
||||||
register(name, "", supplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(String name, String description, LongSupplier 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 //");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <T> boolean inject(final Object src) {
|
|
||||||
return inject(src, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <T> boolean inject(final Object src, final T attachment) {
|
|
||||||
return inject(src, attachment, new ArrayList<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> boolean inject(final Object src, final T attachment, final List<Object> list) {
|
|
||||||
if (src == null) return false;
|
|
||||||
try {
|
|
||||||
list.add(src);
|
|
||||||
Class clazz = src.getClass();
|
|
||||||
do {
|
|
||||||
for (Field field : clazz.getDeclaredFields()) {
|
|
||||||
if (Modifier.isFinal(field.getModifiers())) continue;
|
|
||||||
field.setAccessible(true);
|
|
||||||
final Class type = field.getType();
|
|
||||||
Watchable wo = field.getAnnotation(Watchable.class);
|
|
||||||
if (wo == null && !WatchNode.class.isAssignableFrom(type)) continue;
|
|
||||||
}
|
|
||||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
|
||||||
return true;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.watch;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* <p> 详情见: https://redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
interface WatchNode {
|
|
||||||
|
|
||||||
public String getName();
|
|
||||||
|
|
||||||
public String getDescription();
|
|
||||||
|
|
||||||
public long getValue();
|
|
||||||
|
|
||||||
public boolean isInterval();
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.watch;
|
|
||||||
|
|
||||||
import java.beans.*;
|
|
||||||
import java.util.concurrent.atomic.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* <p> 详情见: https://redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
final class WatchNumber extends AtomicLong implements WatchNode {
|
|
||||||
|
|
||||||
private final boolean interval;
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
private final String description;
|
|
||||||
|
|
||||||
@ConstructorProperties({"name", "description", "interval", "value"})
|
|
||||||
protected WatchNumber(String name, String description, boolean interval, long value) {
|
|
||||||
this.name = name;
|
|
||||||
this.description = description;
|
|
||||||
this.interval = interval;
|
|
||||||
this.set(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue() {
|
|
||||||
return super.longValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInterval() {
|
|
||||||
return interval;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.watch;
|
|
||||||
|
|
||||||
import java.util.function.LongSupplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* <p> 详情见: https://redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class WatchSupplier implements WatchNode {
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
private final String description;
|
|
||||||
|
|
||||||
private final LongSupplier supplier;
|
|
||||||
|
|
||||||
WatchSupplier(String name, String description, LongSupplier supplier) {
|
|
||||||
this.name = name;
|
|
||||||
this.description = description;
|
|
||||||
this.supplier = supplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return this.description;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue() {
|
|
||||||
return supplier == null ? Long.MIN_VALUE : supplier.getAsLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInterval() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.watch;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.*;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 该注解只能放在field类型为Collection, Map, 或者java.util.concurrent.atomic.AtomicXXX的Number类);
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 详情见: https://redkale.org
|
|
||||||
*
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Inherited
|
|
||||||
@Documented
|
|
||||||
@Target({FIELD, METHOD})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@interface Watchable {
|
|
||||||
|
|
||||||
String name();
|
|
||||||
|
|
||||||
String description() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 该值指明是不是只收集阶段数据, 而且被注解的字段只能被赋予java.util.concurrent.atomic.AtomicXXX的Number类型字段。
|
|
||||||
* 例如收集每分钟的注册用户数, 就需要将interval设置true。
|
|
||||||
*
|
|
||||||
* @return 是否收集
|
|
||||||
*/
|
|
||||||
boolean interval() default false;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user