Search in sources :

Example 1 with MessageAgent

use of org.redkale.mq.MessageAgent in project redkale by redkale.

the class NodeHttpServer method loadRestServlet.

@SuppressWarnings("unchecked")
protected void loadRestServlet(final ClassFilter<? extends WebSocket> webSocketFilter, final AnyValue restConf, final List<Object> restedObjects, final StringBuilder sb, final List<AbstractMap.SimpleEntry<String, String[]>> rests, final List<AbstractMap.SimpleEntry<String, String[]>> webss) throws Exception {
    if (!rest)
        return;
    // 不存在REST服务
    if (restConf == null)
        return;
    String prefix0 = restConf.getValue("path", "");
    if (!prefix0.isEmpty() && prefix0.charAt(prefix0.length() - 1) == '/')
        prefix0 = prefix0.substring(0, prefix0.length() - 1);
    if (!prefix0.isEmpty() && prefix0.charAt(0) != '/')
        prefix0 = '/' + prefix0;
    final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
    String mqname = restConf.getValue("mq");
    MessageAgent agent0 = null;
    if (mqname != null) {
        agent0 = application.getMessageAgent(mqname);
        if (agent0 == null)
            throw new RuntimeException("not found " + MessageAgent.class.getSimpleName() + " config for (name=" + mqname + ")");
    }
    final MessageAgent messageAgent = agent0;
    // 开启MQ时,prefix字段失效
    if (messageAgent != null)
        prefix0 = "";
    final String prefix = prefix0;
    final boolean autoload = restConf.getBoolValue("autoload", true);
    {
        // 加载RestService
        String userTypeStr = restConf.getValue("usertype");
        final Class userType = userTypeStr == null ? null : this.serverClassLoader.loadClass(userTypeStr);
        final Class baseServletType = this.serverClassLoader.loadClass(restConf.getValue("base", HttpServlet.class.getName()));
        final Set<String> includeValues = new HashSet<>();
        final Set<String> excludeValues = new HashSet<>();
        for (AnyValue item : restConf.getAnyValues("service")) {
            if (item.getBoolValue("ignore", false)) {
                excludeValues.add(item.getValue("value", ""));
            } else {
                includeValues.add(item.getValue("value", ""));
            }
        }
        final ClassFilter restFilter = ClassFilter.create(serverClassLoader, null, application.isCompileMode() ? "" : restConf.getValue("includes", ""), application.isCompileMode() ? "" : restConf.getValue("excludes", ""), includeValues, excludeValues);
        final CountDownLatch scdl = new CountDownLatch(super.interceptorServices.size());
        Stream<Service> stream = super.interceptorServices.stream();
        // 不能并行,否则在maven plugin运行环境下ClassLoader不对
        if (!application.isCompileMode())
            stream = stream.parallel();
        stream.forEach((service) -> {
            try {
                final Class stype = Sncp.getServiceType(service);
                final String name = Sncp.getResourceName(service);
                RestService rs = (RestService) stype.getAnnotation(RestService.class);
                if (rs == null || rs.ignore())
                    return;
                final String stypename = stype.getName();
                if (!autoload && !includeValues.contains(stypename))
                    return;
                if (!restFilter.accept(stypename))
                    return;
                synchronized (restedObjects) {
                    if (restedObjects.contains(service)) {
                        logger.log(Level.WARNING, stype.getName() + " repeat create rest servlet, so ignore");
                        return;
                    }
                    // 避免重复创建Rest对象
                    restedObjects.add(service);
                }
                HttpServlet servlet = httpServer.addRestServlet(serverClassLoader, service, userType, baseServletType, prefix);
                // 没有HttpMapping方法的HttpServlet调用Rest.createRestServlet就会返回null
                if (servlet == null)
                    return;
                String prefix2 = prefix;
                WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
                if (ws != null && !ws.repair())
                    prefix2 = "";
                resourceFactory.inject(servlet, NodeHttpServer.this);
                dynServletMap.put(service, servlet);
                if (messageAgent != null)
                    messageAgent.putService(this, service, servlet);
                // if (finest) logger.finest(localThreadName + " Create RestServlet(resource.name='" + name + "') = " + servlet);
                if (rests != null) {
                    String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
                    for (int i = 0; i < mappings.length; i++) {
                        mappings[i] = prefix2 + mappings[i];
                    }
                    synchronized (rests) {
                        rests.add(new AbstractMap.SimpleEntry<>(Sncp.getServiceType(service).getName() + "#" + name, mappings));
                    }
                }
            } finally {
                scdl.countDown();
            }
        });
        scdl.await();
    }
    if (webSocketFilter != null) {
        // 加载RestWebSocket
        final Set<String> includeValues = new HashSet<>();
        final Set<String> excludeValues = new HashSet<>();
        for (AnyValue item : restConf.getAnyValues("websocket")) {
            if (item.getBoolValue("ignore", false)) {
                excludeValues.add(item.getValue("value", ""));
            } else {
                includeValues.add(item.getValue("value", ""));
            }
        }
        final ClassFilter restFilter = ClassFilter.create(serverClassLoader, null, application.isCompileMode() ? "" : restConf.getValue("includes", ""), application.isCompileMode() ? "" : restConf.getValue("excludes", ""), includeValues, excludeValues);
        final boolean finest = logger.isLoggable(Level.FINEST);
        List<FilterEntry<? extends WebSocket>> list = new ArrayList(webSocketFilter.getFilterEntrys());
        for (FilterEntry<? extends WebSocket> en : list) {
            Class<WebSocket> clazz = (Class<WebSocket>) en.getType();
            if (Modifier.isAbstract(clazz.getModifiers())) {
                logger.log(Level.FINE, clazz.getName() + " cannot abstract on rest websocket, so ignore");
                continue;
            }
            if (Modifier.isFinal(clazz.getModifiers())) {
                logger.log(Level.FINE, clazz.getName() + " cannot final on rest websocket, so ignore");
                continue;
            }
            final Class<? extends WebSocket> stype = en.getType();
            if (stype.getAnnotation(Rest.RestDyn.class) != null)
                continue;
            RestWebSocket rs = stype.getAnnotation(RestWebSocket.class);
            if (rs == null || rs.ignore())
                continue;
            final String stypename = stype.getName();
            if (!autoload && !includeValues.contains(stypename))
                continue;
            if (!restFilter.accept(stypename))
                continue;
            if (restedObjects.contains(stype)) {
                logger.log(Level.WARNING, stype.getName() + " repeat create rest websocket, so ignore");
                continue;
            }
            // 避免重复创建Rest对象
            restedObjects.add(stype);
            WebSocketServlet servlet = httpServer.addRestWebSocketServlet(serverClassLoader, stype, messageAgent, prefix, en.getProperty());
            // 没有RestOnMessage方法的HttpServlet调用Rest.createRestWebSocketServlet就会返回null
            if (servlet == null)
                continue;
            String prefix2 = prefix;
            WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
            if (ws != null && !ws.repair())
                prefix2 = "";
            resourceFactory.inject(servlet, NodeHttpServer.this);
            if (finest)
                logger.finest(localThreadName + " " + stype.getName() + " create a RestWebSocketServlet");
            if (webss != null) {
                String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
                for (int i = 0; i < mappings.length; i++) {
                    mappings[i] = prefix2 + mappings[i];
                }
                synchronized (webss) {
                    webss.add(new AbstractMap.SimpleEntry<>(stype.getName() + "#" + rs.name(), mappings));
                }
            }
        }
    }
    if (messageAgent != null)
        this.messageAgents.put(messageAgent.getName(), messageAgent);
}
Also used : java.lang.reflect(java.lang.reflect) java.util(java.util) org.redkale.watch(org.redkale.watch) org.redkale.net(org.redkale.net) Level(java.util.logging.Level) javax.annotation(javax.annotation) CountDownLatch(java.util.concurrent.CountDownLatch) org.redkale.util(org.redkale.util) java.net(java.net) Stream(java.util.stream.Stream) RESNAME_SNCP_ADDR(org.redkale.boot.Application.RESNAME_SNCP_ADDR) org.redkale.net.http(org.redkale.net.http) DefaultAnyValue(org.redkale.util.AnyValue.DefaultAnyValue) Annotation(java.lang.annotation.Annotation) ClusterAgent(org.redkale.cluster.ClusterAgent) Sncp(org.redkale.net.sncp.Sncp) MessageAgent(org.redkale.mq.MessageAgent) org.redkale.service(org.redkale.service) FilterEntry(org.redkale.boot.ClassFilter.FilterEntry) FilterEntry(org.redkale.boot.ClassFilter.FilterEntry) Stream(java.util.stream.Stream) MessageAgent(org.redkale.mq.MessageAgent) CountDownLatch(java.util.concurrent.CountDownLatch) DefaultAnyValue(org.redkale.util.AnyValue.DefaultAnyValue)

Example 2 with MessageAgent

use of org.redkale.mq.MessageAgent in project redkale by redkale.

the class NodeServer method initResource.

private void initResource() {
    final NodeServer self = this;
    // ---------------------------------------------------------------------------------------------
    final ResourceFactory appResFactory = application.getResourceFactory();
    final TransportFactory appSncpTranFactory = application.getSncpTransportFactory();
    final AnyValue resources = application.config.getAnyValue("resources");
    final String confURI = appResFactory.find(RESNAME_APP_CONF, String.class);
    final Map<String, SimpleEntry<Class, AnyValue>> cacheResource = new HashMap<>();
    final Map<String, SimpleEntry<Class, AnyValue>> dataResources = new HashMap<>();
    if (resources != null) {
        for (AnyValue sourceConf : resources.getAnyValues("source")) {
            try {
                String classval = sourceConf.getValue("value");
                Class type = null;
                if (classval == null || classval.isEmpty()) {
                    RedkaleClassLoader.putServiceLoader(CacheSourceProvider.class);
                    List<CacheSourceProvider> providers = new ArrayList<>();
                    Iterator<CacheSourceProvider> it = ServiceLoader.load(CacheSourceProvider.class, serverClassLoader).iterator();
                    while (it.hasNext()) {
                        CacheSourceProvider s = it.next();
                        if (s != null)
                            RedkaleClassLoader.putReflectionPublicConstructors(s.getClass(), s.getClass().getName());
                        if (s != null && s.acceptsConf(sourceConf)) {
                            providers.add(s);
                        }
                    }
                    Collections.sort(providers, (a, b) -> {
                        Priority p1 = a == null ? null : a.getClass().getAnnotation(Priority.class);
                        Priority p2 = b == null ? null : b.getClass().getAnnotation(Priority.class);
                        return (p2 == null ? 0 : p2.value()) - (p1 == null ? 0 : p1.value());
                    });
                    for (CacheSourceProvider provider : providers) {
                        type = provider.sourceClass();
                        if (type != null)
                            break;
                    }
                } else {
                    type = serverClassLoader.loadClass(classval);
                }
                if (type == DataSource.class) {
                    type = DataMemorySource.class;
                    for (AnyValue itemConf : sourceConf.getAnyValues("property")) {
                        if (itemConf.getValue("name", "").contains(DataSources.JDBC_URL)) {
                            type = DataJdbcSource.class;
                            break;
                        }
                    }
                }
                if (!Service.class.isAssignableFrom(type)) {
                    logger.log(Level.SEVERE, "load application source resource, but not Service error: " + sourceConf);
                } else if (CacheSource.class.isAssignableFrom(type)) {
                    cacheResource.put(sourceConf.getValue("name", ""), new SimpleEntry(type, sourceConf));
                } else if (DataSource.class.isAssignableFrom(type)) {
                    dataResources.put(sourceConf.getValue("name", ""), new SimpleEntry(type, sourceConf));
                } else {
                    logger.log(Level.SEVERE, "load application source resource, but not CacheSource error: " + sourceConf);
                }
            } catch (Exception e) {
                logger.log(Level.SEVERE, "load application source resource error: " + sourceConf, e);
            }
        }
    }
    // ------------------------------------- 注册 Resource --------------------------------------------------------
    resourceFactory.register((ResourceFactory rf, final Object src, String resourceName, Field field, final Object attachment) -> {
        try {
            Resource res = field.getAnnotation(Resource.class);
            if (res == null || !res.name().startsWith("properties."))
                return;
            // 远程模式不得注入 DataSource
            if ((src instanceof Service) && Sncp.isRemote((Service) src))
                return;
            Class type = field.getType();
            if (type != AnyValue.class && type != AnyValue[].class)
                return;
            Object resource = null;
            final AnyValue properties = resources == null ? null : resources.getAnyValue("properties");
            if (properties != null && type == AnyValue.class) {
                resource = properties.getAnyValue(res.name().substring("properties.".length()));
                appResFactory.register(resourceName, AnyValue.class, resource);
            } else if (properties != null && type == AnyValue[].class) {
                resource = properties.getAnyValues(res.name().substring("properties.".length()));
                appResFactory.register(resourceName, AnyValue[].class, resource);
            }
            field.set(src, resource);
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Resource inject error", e);
        }
    }, AnyValue.class, AnyValue[].class);
    // ------------------------------------- 注册 Local AutoLoad(false) Service --------------------------------------------------------
    resourceFactory.register((ResourceFactory rf, final Object src, String resourceName, Field field, final Object attachment) -> {
        Class<Service> resServiceType = Service.class;
        try {
            if (field.getAnnotation(Resource.class) == null)
                return;
            // 远程模式不得注入 AutoLoad Service
            if ((src instanceof Service) && Sncp.isRemote((Service) src))
                return;
            if (!Service.class.isAssignableFrom(field.getType()))
                return;
            resServiceType = (Class) field.getType();
            if (resServiceType.getAnnotation(Local.class) == null)
                return;
            AutoLoad al = resServiceType.getAnnotation(AutoLoad.class);
            if (al == null || al.value())
                return;
            // ResourceFactory resfactory = (isSNCP() ? appResFactory : resourceFactory);
            SncpClient client = src instanceof Service ? Sncp.getSncpClient((Service) src) : null;
            final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
            final Set<String> groups = new HashSet<>();
            Service service = Modifier.isFinal(resServiceType.getModifiers()) ? (Service) resServiceType.getConstructor().newInstance() : Sncp.createLocalService(serverClassLoader, resourceName, resServiceType, null, appResFactory, appSncpTranFactory, sncpAddr, groups, null);
            appResFactory.register(resourceName, resServiceType, service);
            field.set(src, service);
            // 给其可能包含@Resource的字段赋值;
            rf.inject(service, self);
            if (!application.isCompileMode())
                service.init(null);
            logger.info("[" + Thread.currentThread().getName() + "] Load Service(@Local @AutoLoad service = " + resServiceType.getSimpleName() + ", resourceName = '" + resourceName + "')");
        } catch (Exception e) {
            logger.log(Level.SEVERE, "[" + Thread.currentThread().getName() + "] Load @Local @AutoLoad(false) Service inject " + resServiceType + " to " + src + " error", e);
        }
    }, Service.class);
    // ------------------------------------- 注册 DataSource --------------------------------------------------------
    resourceFactory.register((ResourceFactory rf, final Object src, String resourceName, Field field, final Object attachment) -> {
        try {
            if (field.getAnnotation(Resource.class) == null)
                return;
            // 远程模式不得注入 DataSource
            if ((src instanceof Service) && Sncp.isRemote((Service) src))
                return;
            SimpleEntry<Class, AnyValue> resEntry = dataResources.get(resourceName);
            AnyValue sourceConf = resEntry == null ? null : resEntry.getValue();
            DataSource source = null;
            if (sourceConf != null) {
                final Class sourceType = resEntry.getKey();
                if (sourceType == DataJdbcSource.class) {
                    source = DataSources.createDataSource(resourceName, sourceConf);
                } else {
                    boolean can = false;
                    RedkaleClassLoader.putReflectionPublicConstructors(sourceType, sourceType.getName());
                    for (Constructor cr : sourceType.getConstructors()) {
                        if (cr.getParameterCount() == 0) {
                            can = true;
                            break;
                        }
                    }
                    if (DataSource.class.isAssignableFrom(sourceType) && can) {
                        // 必须有空构造函数
                        if (Modifier.isFinal(sourceType.getModifiers()) || sourceType.getAnnotation(Local.class) != null) {
                            source = (DataSource) sourceType.getConstructor().newInstance();
                            RedkaleClassLoader.putReflectionPublicConstructors(sourceType, sourceType.getName());
                        } else {
                            final Service srcService = (Service) src;
                            SncpClient client = Sncp.getSncpClient(srcService);
                            final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
                            final Set<String> groups = new HashSet<>();
                            source = (DataSource) Sncp.createLocalService(serverClassLoader, resourceName, sourceType, client == null ? null : client.getMessageAgent(), appResFactory, appSncpTranFactory, sncpAddr, groups, Sncp.getConf(srcService));
                        }
                    }
                }
            }
            if (source == null) {
                // 从persistence.xml配置中创建
                source = DataSources.createDataSource(confURI, resourceName);
            }
            RedkaleClassLoader.putReflectionPublicConstructors(source.getClass(), source.getClass().getName());
            application.dataSources.add(source);
            ResourceType rt = source.getClass().getAnnotation(ResourceType.class);
            if (rt != null && rt.value() != DataSource.class) {
                appResFactory.register(resourceName, rt.value(), source);
            } else if (source instanceof SearchSource) {
                appResFactory.register(resourceName, SearchSource.class, source);
            }
            appResFactory.register(resourceName, DataSource.class, source);
            field.set(src, source);
            // 给AsyncGroup和其他@Resource的字段赋值;
            rf.inject(source, self);
            // NodeServer.this.watchFactory.inject(src);
            if (!application.isCompileMode() && source instanceof Service)
                ((Service) source).init(sourceConf);
            logger.info("[" + Thread.currentThread().getName() + "] Load DataSource (type = " + source.getClass().getSimpleName() + ", resourceName = '" + resourceName + "')");
        } catch (Exception e) {
            logger.log(Level.SEVERE, "[" + Thread.currentThread().getName() + "] DataSource inject to " + src + " error", e);
        }
    }, DataSource.class);
    // ------------------------------------- 注册 CacheSource --------------------------------------------------------
    resourceFactory.register(new ResourceFactory.ResourceLoader() {

        @Override
        public void load(ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) {
            try {
                if (field.getAnnotation(Resource.class) == null)
                    return;
                if (!(src instanceof Service))
                    throw new RuntimeException("CacheSource must be inject in Service, cannot " + src);
                // 远程模式不需要注入 CacheSource
                if ((src instanceof Service) && Sncp.isRemote((Service) src))
                    return;
                final Service srcService = (Service) src;
                SncpClient client = Sncp.getSncpClient(srcService);
                final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
                SimpleEntry<Class, AnyValue> resEntry = cacheResource.get(resourceName);
                AnyValue sourceConf = resEntry == null ? null : resEntry.getValue();
                if (sourceConf == null) {
                    SimpleEntry<Class, AnyValue> resEntry2 = dataResources.get(resourceName);
                    sourceConf = resEntry2 == null ? null : resEntry2.getValue();
                }
                Class sourceType0 = CacheMemorySource.class;
                if (sourceConf != null) {
                    String classval = sourceConf.getValue("value");
                    if (classval == null || classval.isEmpty()) {
                        RedkaleClassLoader.putServiceLoader(CacheSourceProvider.class);
                        List<CacheSourceProvider> providers = new ArrayList<>();
                        Iterator<CacheSourceProvider> it = ServiceLoader.load(CacheSourceProvider.class, serverClassLoader).iterator();
                        while (it.hasNext()) {
                            CacheSourceProvider s = it.next();
                            if (s != null)
                                RedkaleClassLoader.putReflectionPublicConstructors(s.getClass(), s.getClass().getName());
                            if (s != null && s.acceptsConf(sourceConf)) {
                                providers.add(s);
                            }
                        }
                        Collections.sort(providers, (a, b) -> {
                            Priority p1 = a == null ? null : a.getClass().getAnnotation(Priority.class);
                            Priority p2 = b == null ? null : b.getClass().getAnnotation(Priority.class);
                            return (p2 == null ? 0 : p2.value()) - (p1 == null ? 0 : p1.value());
                        });
                        for (CacheSourceProvider provider : providers) {
                            sourceType0 = provider.sourceClass();
                            if (sourceType0 != null)
                                break;
                        }
                    } else {
                        sourceType0 = serverClassLoader.loadClass(classval);
                    }
                }
                final Class sourceType = sourceType0;
                Object source = null;
                if (CacheSource.class.isAssignableFrom(sourceType)) {
                    // CacheSource
                    RedkaleClassLoader.putReflectionPublicConstructors(sourceType, sourceType.getName());
                    source = sourceType == CacheMemorySource.class ? new CacheMemorySource(resourceName) : (Modifier.isFinal(sourceType.getModifiers()) || sourceType.getAnnotation(Local.class) != null) ? sourceType.getConstructor().newInstance() : (CacheSource) Sncp.createLocalService(serverClassLoader, resourceName, sourceType, client == null ? null : client.getMessageAgent(), appResFactory, appSncpTranFactory, sncpAddr, null, Sncp.getConf(srcService));
                    Type genericType = field.getGenericType();
                    application.cacheSources.add((CacheSource) source);
                    appResFactory.register(resourceName, CacheSource.class, source);
                    if (genericType != CacheSource.class) {
                        appResFactory.register(resourceName, genericType, source);
                    }
                }
                field.set(src, source);
                // 
                rf.inject(source, self);
                if (!application.isCompileMode() && source instanceof Service)
                    ((Service) source).init(sourceConf);
                if ((src instanceof org.redkale.net.http.WebSocketNodeService) && sncpAddr != null) {
                    // 只有WebSocketNodeService的服务才需要给SNCP服务注入CacheMemorySource
                    NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr);
                    if (source != null && source.getClass().getAnnotation(Local.class) == null) {
                        // 本地模式的Service不生成SncpServlet
                        sncpServer.getSncpServer().addSncpServlet((Service) source);
                    }
                // logger.info("[" + Thread.currentThread().getName() + "] Load Service " + source);
                }
                logger.info("[" + Thread.currentThread().getName() + "] Load CacheSource (type = " + source.getClass().getSimpleName() + ", resourceName = '" + resourceName + "')");
            } catch (Exception e) {
                logger.log(Level.SEVERE, "DataSource inject error", e);
            }
        }

        @Override
        public boolean autoNone() {
            return false;
        }
    }, CacheSource.class);
    // ------------------------------------- 注册 WebSocketNode --------------------------------------------------------
    resourceFactory.register(new ResourceFactory.ResourceLoader() {

        @Override
        public void load(ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) {
            try {
                if (field.getAnnotation(Resource.class) == null)
                    return;
                // 远程模式不需要注入 WebSocketNode
                if ((src instanceof Service) && Sncp.isRemote((Service) src))
                    return;
                Service nodeService = (Service) rf.find(resourceName, WebSocketNode.class);
                if (nodeService == null) {
                    final HashSet<String> groups = new HashSet<>();
                    if (groups.isEmpty() && isSNCP() && NodeServer.this.sncpGroup != null)
                        groups.add(NodeServer.this.sncpGroup);
                    nodeService = Sncp.createLocalService(serverClassLoader, resourceName, org.redkale.net.http.WebSocketNodeService.class, Sncp.getMessageAgent((Service) src), application.getResourceFactory(), application.getSncpTransportFactory(), NodeServer.this.sncpAddress, groups, (AnyValue) null);
                    (isSNCP() ? appResFactory : resourceFactory).register(resourceName, WebSocketNode.class, nodeService);
                    ((org.redkale.net.http.WebSocketNodeService) nodeService).setName(resourceName);
                }
                resourceFactory.inject(nodeService, self);
                MessageAgent messageAgent = Sncp.getMessageAgent((Service) src);
                if (messageAgent != null && Sncp.getMessageAgent(nodeService) == null)
                    Sncp.setMessageAgent(nodeService, messageAgent);
                field.set(src, nodeService);
                if (Sncp.isRemote(nodeService)) {
                    remoteServices.add(nodeService);
                } else {
                    // 动态加载的Service也存在按需加载的注入资源
                    rf.inject(nodeService);
                    localServices.add(nodeService);
                    interceptorServices.add(nodeService);
                    if (consumer != null)
                        consumer.accept(null, nodeService);
                }
            } catch (Exception e) {
                logger.log(Level.SEVERE, "WebSocketNode inject error", e);
            }
        }

        @Override
        public boolean autoNone() {
            return false;
        }
    }, WebSocketNode.class);
}
Also used : java.lang.reflect(java.lang.reflect) java.util.logging(java.util.logging) Application(org.redkale.boot.Application) Filter(org.redkale.net.Filter) RedkaleClassLoader(org.redkale.util.RedkaleClassLoader) java.util(java.util) java.util.concurrent(java.util.concurrent) org.redkale.net(org.redkale.net) java.nio.file(java.nio.file) javax.annotation(javax.annotation) org.redkale.util(org.redkale.util) java.net(java.net) org.redkale.net.http(org.redkale.net.http) java.io(java.io) org.redkale.net.sncp(org.redkale.net.sncp) Annotation(java.lang.annotation.Annotation) ClusterAgent(org.redkale.cluster.ClusterAgent) MessageAgent(org.redkale.mq.MessageAgent) java.util.function(java.util.function) org.redkale.service(org.redkale.service) SimpleEntry(java.util.AbstractMap.SimpleEntry) FilterEntry(org.redkale.boot.ClassFilter.FilterEntry) org.redkale.source(org.redkale.source) SimpleEntry(java.util.AbstractMap.SimpleEntry) MessageAgent(org.redkale.mq.MessageAgent) org.redkale.net.http(org.redkale.net.http)

Example 3 with MessageAgent

use of org.redkale.mq.MessageAgent in project redkale by redkale.

the class Sncp method createRemoteService.

/**
 * <blockquote><pre>
 * &#64;Resource(name = "")
 * &#64;SncpDyn(remote = true)
 * &#64;ResourceType(TestService.class)
 * public final class _DynRemoteTestService extends TestService{
 *
 *      private AnyValue _redkale_conf;
 *
 *      private SncpClient _redkale_client;
 *
 *      &#64;Override
 *      public void createSomeThing(TestBean bean){
 *          _redkale_client.remote(0, bean);
 *      }
 *
 *      &#64;Override
 *      public String findSomeThing(){
 *          return _redkale_client.remote(1);
 *      }
 *
 *      &#64;Override
 *      public String updateSomeThing(String id){
 *          return  _redkale_client.remote(2, id);
 *      }
 * }
 * </pre></blockquote>
 *
 * 创建远程模式的Service实例
 *
 * @param <T>                    Service泛型
 * @param classLoader            ClassLoader
 * @param name                   资源名
 * @param serviceTypeOrImplClass Service类
 * @param messageAgent           MQ管理器
 * @param transportFactory       TransportFactory
 * @param clientAddress          本地IP地址
 * @param groups0                所有的组节点,包含自身
 * @param conf                   启动配置项
 *
 * @return Service的远程模式实例
 */
@SuppressWarnings("unchecked")
public static <T extends Service> T createRemoteService(final ClassLoader classLoader, final String name, final Class<T> serviceTypeOrImplClass, final MessageAgent messageAgent, final TransportFactory transportFactory, final InetSocketAddress clientAddress, final Set<String> groups0, final AnyValue conf) {
    if (serviceTypeOrImplClass == null)
        return null;
    if (!Service.class.isAssignableFrom(serviceTypeOrImplClass))
        return null;
    final Set<String> groups = groups0 == null ? new HashSet<>() : groups0;
    ResourceFactory.checkResourceName(name);
    final int mod = serviceTypeOrImplClass.getModifiers();
    boolean realed = !(java.lang.reflect.Modifier.isAbstract(mod) || serviceTypeOrImplClass.isInterface());
    if (!java.lang.reflect.Modifier.isPublic(mod))
        return null;
    final String supDynName = serviceTypeOrImplClass.getName().replace('.', '/');
    final String clientName = SncpClient.class.getName().replace('.', '/');
    final String resDesc = Type.getDescriptor(Resource.class);
    final String clientDesc = Type.getDescriptor(SncpClient.class);
    final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
    final String anyValueDesc = Type.getDescriptor(AnyValue.class);
    final ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
    // final String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + REMOTEPREFIX + serviceTypeOrImplClass.getSimpleName();
    final String newDynName = "org/redkaledyn/service/remote/_DynRemoteService__" + serviceTypeOrImplClass.getName().replace('.', '_').replace('$', '_');
    try {
        Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
        Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz;
        T service = (T) newClazz.getDeclaredConstructor().newInstance();
        SncpClient client = new SncpClient(name, serviceTypeOrImplClass, service, messageAgent, transportFactory, true, realed ? createLocalServiceClass(loader, name, serviceTypeOrImplClass) : serviceTypeOrImplClass, clientAddress);
        client.setRemoteGroups(groups);
        if (transportFactory != null)
            client.setRemoteGroupTransport(transportFactory.loadTransport(clientAddress, groups));
        {
            Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
            c.setAccessible(true);
            c.set(service, client);
        }
        if (messageAgent != null) {
            Field c = newClazz.getDeclaredField(FIELDPREFIX + "_messageagent");
            c.setAccessible(true);
            c.set(service, messageAgent);
            if (service instanceof WebSocketNode) {
                c = WebSocketNode.class.getDeclaredField("messageAgent");
                c.setAccessible(true);
                c.set(service, messageAgent);
            }
        }
        {
            Field c = newClazz.getDeclaredField(FIELDPREFIX + "_conf");
            c.setAccessible(true);
            c.set(service, conf);
        }
        if (transportFactory != null)
            transportFactory.addSncpService(service);
        return service;
    } catch (Throwable ex) {
    }
    // ------------------------------------------------------------------------------
    ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
    FieldVisitor fv;
    MethodDebugVisitor mv;
    AnnotationVisitor av0;
    cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, serviceTypeOrImplClass.isInterface() ? "java/lang/Object" : supDynName, serviceTypeOrImplClass.isInterface() ? new String[] { supDynName } : null);
    {
        av0 = cw.visitAnnotation(resDesc, true);
        av0.visit("name", name);
        av0.visitEnd();
    }
    {
        av0 = cw.visitAnnotation(Type.getDescriptor(ResourceType.class), true);
        ResourceType rty = serviceTypeOrImplClass.getAnnotation(ResourceType.class);
        av0.visit("value", Type.getType(Type.getDescriptor(rty == null ? serviceTypeOrImplClass : rty.value())));
        av0.visitEnd();
    }
    {
        av0 = cw.visitAnnotation(sncpDynDesc, true);
        av0.visit("remote", Boolean.TRUE);
        av0.visitEnd();
    }
    {
        // 给新类加上 原有的Annotation
        for (Annotation ann : serviceTypeOrImplClass.getAnnotations()) {
            if (ann instanceof Resource || ann instanceof SncpDyn || ann instanceof ResourceType)
                continue;
            MethodDebugVisitor.visitAnnotation(cw.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
        }
    }
    {
        fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_conf", anyValueDesc, null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_client", clientDesc, null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_messageagent", Type.getDescriptor(MessageAgent.class), null, null);
        fv.visitEnd();
    }
    {
        // 构造函数
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
        // mv.setDebug(true);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, serviceTypeOrImplClass.isInterface() ? "java/lang/Object" : supDynName, "<init>", "()V", false);
        mv.visitInsn(RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    {
        // init
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "init", "(" + anyValueDesc + ")V", null, null));
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 2);
        mv.visitEnd();
    }
    {
        // stop
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "stop", "(" + anyValueDesc + ")V", null, null));
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 2);
        mv.visitEnd();
    }
    {
        // destroy
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "destroy", "(" + anyValueDesc + ")V", null, null));
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 2);
        mv.visitEnd();
    }
    {
        // toString()
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
        Label l1 = new Label();
        mv.visitJumpInsn(IFNONNULL, l1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;", false);
        Label l2 = new Label();
        mv.visitJumpInsn(GOTO, l2);
        mv.visitLabel(l1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
        mv.visitMethodInsn(INVOKEVIRTUAL, clientName, "toSimpleString", "()Ljava/lang/String;", false);
        mv.visitLabel(l2);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    int i = -1;
    for (final SncpAction entry : SncpClient.getSncpActions(realed ? createLocalServiceClass(loader, name, serviceTypeOrImplClass) : serviceTypeOrImplClass)) {
        final int index = ++i;
        final java.lang.reflect.Method method = entry.method;
        {
            mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, method.getName(), Type.getMethodDescriptor(method), null, null));
            // mv.setDebug(true);
            {
                // 给参数加上 Annotation
                final Annotation[][] anns = method.getParameterAnnotations();
                for (int k = 0; k < anns.length; k++) {
                    for (Annotation ann : anns[k]) {
                        MethodDebugVisitor.visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
                    }
                }
            }
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
            MethodDebugVisitor.pushInt(mv, index);
            {
                // 传参数
                int paramlen = entry.paramTypes.length;
                MethodDebugVisitor.pushInt(mv, paramlen);
                mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
                java.lang.reflect.Type[] paramtypes = entry.paramTypes;
                int insn = 0;
                for (int j = 0; j < paramtypes.length; j++) {
                    final java.lang.reflect.Type pt = paramtypes[j];
                    mv.visitInsn(DUP);
                    insn++;
                    MethodDebugVisitor.pushInt(mv, j);
                    if (pt instanceof Class && ((Class) pt).isPrimitive()) {
                        if (pt == long.class) {
                            mv.visitVarInsn(LLOAD, insn++);
                        } else if (pt == float.class) {
                            mv.visitVarInsn(FLOAD, insn++);
                        } else if (pt == double.class) {
                            mv.visitVarInsn(DLOAD, insn++);
                        } else {
                            mv.visitVarInsn(ILOAD, insn);
                        }
                        Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance((Class) pt, 1), 0).getClass();
                        mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor((Class) pt) + ")" + Type.getDescriptor(bigclaz), false);
                    } else {
                        mv.visitVarInsn(ALOAD, insn);
                    }
                    mv.visitInsn(AASTORE);
                }
            }
            mv.visitMethodInsn(INVOKEVIRTUAL, clientName, "remote", "(I[Ljava/lang/Object;)Ljava/lang/Object;", false);
            // mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
            if (method.getGenericReturnType() == void.class) {
                mv.visitInsn(POP);
                mv.visitInsn(RETURN);
            } else {
                Class returnclz = method.getReturnType();
                Class bigPrimitiveClass = returnclz.isPrimitive() ? java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(returnclz, 1), 0).getClass() : returnclz;
                mv.visitTypeInsn(CHECKCAST, (returnclz.isPrimitive() ? bigPrimitiveClass : returnclz).getName().replace('.', '/'));
                if (returnclz.isPrimitive()) {
                    String bigPrimitiveName = bigPrimitiveClass.getName().replace('.', '/');
                    try {
                        java.lang.reflect.Method pm = bigPrimitiveClass.getMethod(returnclz.getSimpleName() + "Value");
                        mv.visitMethodInsn(INVOKEVIRTUAL, bigPrimitiveName, pm.getName(), Type.getMethodDescriptor(pm), false);
                    } catch (Exception ex) {
                        // 不可能会发生
                        throw new RuntimeException(ex);
                    }
                    if (returnclz == long.class) {
                        mv.visitInsn(LRETURN);
                    } else if (returnclz == float.class) {
                        mv.visitInsn(FRETURN);
                    } else if (returnclz == double.class) {
                        mv.visitInsn(DRETURN);
                    } else {
                        mv.visitInsn(IRETURN);
                    }
                } else {
                    mv.visitInsn(ARETURN);
                }
            }
            mv.visitMaxs(20, 20);
            mv.visitEnd();
        }
    }
    cw.visitEnd();
    byte[] bytes = cw.toByteArray();
    Class<?> newClazz = new ClassLoader(loader) {

        public final Class<?> loadClass(String name, byte[] b) {
            return defineClass(name, b, 0, b.length);
        }
    }.loadClass(newDynName.replace('/', '.'), bytes);
    RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
    RedkaleClassLoader.putReflectionPublicConstructors(newClazz, newDynName.replace('/', '.'));
    RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
    try {
        T service = (T) newClazz.getDeclaredConstructor().newInstance();
        SncpClient client = new SncpClient(name, serviceTypeOrImplClass, service, messageAgent, transportFactory, true, realed ? createLocalServiceClass(loader, name, serviceTypeOrImplClass) : serviceTypeOrImplClass, clientAddress);
        client.setRemoteGroups(groups);
        if (transportFactory != null)
            client.setRemoteGroupTransport(transportFactory.loadTransport(clientAddress, groups));
        {
            Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
            c.setAccessible(true);
            c.set(service, client);
            RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), c);
        }
        if (messageAgent != null) {
            Field c = newClazz.getDeclaredField(FIELDPREFIX + "_messageagent");
            c.setAccessible(true);
            c.set(service, messageAgent);
            RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), c);
            if (service instanceof WebSocketNode) {
                c = WebSocketNode.class.getDeclaredField("messageAgent");
                c.setAccessible(true);
                c.set(service, messageAgent);
                RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), c);
            }
        }
        {
            Field c = newClazz.getDeclaredField(FIELDPREFIX + "_conf");
            c.setAccessible(true);
            c.set(service, conf);
            RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), c);
        }
        if (transportFactory != null)
            transportFactory.addSncpService(service);
        return service;
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}
Also used : MethodDebugVisitor(org.redkale.asm.MethodDebugVisitor) java.lang.reflect(java.lang.reflect) SncpAction(org.redkale.net.sncp.SncpClient.SncpAction) Resource(javax.annotation.Resource) MessageAgent(org.redkale.mq.MessageAgent) Annotation(java.lang.annotation.Annotation) Type(org.redkale.asm.Type) WebSocketNode(org.redkale.net.http.WebSocketNode)

Example 4 with MessageAgent

use of org.redkale.mq.MessageAgent in project redkale by redkale.

the class NodeHttpServer method initWebSocketService.

private void initWebSocketService() {
    final NodeServer self = this;
    final ResourceFactory regFactory = application.getResourceFactory();
    resourceFactory.register((ResourceFactory rf, final Object src, final String resourceName, Field field, Object attachment) -> {
        // 主要用于单点的服务
        try {
            if (field.getAnnotation(Resource.class) == null)
                return;
            if (!(src instanceof WebSocketServlet))
                return;
            ResourceFactory.ResourceLoader loader = null;
            ResourceFactory sncpResFactory = null;
            for (NodeServer ns : application.servers) {
                if (!ns.isSNCP())
                    continue;
                sncpResFactory = ns.resourceFactory;
                loader = sncpResFactory.findLoader(WebSocketNode.class, field);
                if (loader != null)
                    break;
            }
            if (loader != null)
                loader.load(sncpResFactory, src, resourceName, field, attachment);
            synchronized (regFactory) {
                Service nodeService = (Service) rf.find(resourceName, WebSocketNode.class);
                if (sncpResFactory != null && resourceFactory.find(RESNAME_SNCP_ADDR, String.class) == null) {
                    resourceFactory.register(RESNAME_SNCP_ADDR, InetSocketAddress.class, sncpResFactory.find(RESNAME_SNCP_ADDR, InetSocketAddress.class));
                    resourceFactory.register(RESNAME_SNCP_ADDR, SocketAddress.class, sncpResFactory.find(RESNAME_SNCP_ADDR, SocketAddress.class));
                    resourceFactory.register(RESNAME_SNCP_ADDR, String.class, sncpResFactory.find(RESNAME_SNCP_ADDR, String.class));
                }
                if (nodeService == null) {
                    MessageAgent messageAgent = null;
                    try {
                        Field c = WebSocketServlet.class.getDeclaredField("messageAgent");
                        c.setAccessible(true);
                        messageAgent = (MessageAgent) c.get(src);
                    } catch (Exception ex) {
                        logger.log(Level.WARNING, "WebSocketServlet getMessageAgent error", ex);
                    }
                    nodeService = Sncp.createLocalService(serverClassLoader, resourceName, org.redkale.net.http.WebSocketNodeService.class, messageAgent, application.getResourceFactory(), application.getSncpTransportFactory(), (InetSocketAddress) null, (Set<String>) null, (AnyValue) null);
                    regFactory.register(resourceName, WebSocketNode.class, nodeService);
                }
                resourceFactory.inject(nodeService, self);
                field.set(src, nodeService);
                logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + nodeService);
            }
        } catch (Exception e) {
            logger.log(Level.SEVERE, "WebSocketNode inject error", e);
        }
    }, WebSocketNode.class);
}
Also used : MessageAgent(org.redkale.mq.MessageAgent) DefaultAnyValue(org.redkale.util.AnyValue.DefaultAnyValue) org.redkale.net(org.redkale.net) java.net(java.net)

Aggregations

MessageAgent (org.redkale.mq.MessageAgent)4 Annotation (java.lang.annotation.Annotation)3 java.lang.reflect (java.lang.reflect)3 java.net (java.net)3 org.redkale.net (org.redkale.net)3 java.util (java.util)2 javax.annotation (javax.annotation)2 FilterEntry (org.redkale.boot.ClassFilter.FilterEntry)2 ClusterAgent (org.redkale.cluster.ClusterAgent)2 org.redkale.net.http (org.redkale.net.http)2 org.redkale.service (org.redkale.service)2 org.redkale.util (org.redkale.util)2 DefaultAnyValue (org.redkale.util.AnyValue.DefaultAnyValue)2 java.io (java.io)1 java.nio.file (java.nio.file)1 SimpleEntry (java.util.AbstractMap.SimpleEntry)1 java.util.concurrent (java.util.concurrent)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 java.util.function (java.util.function)1 java.util.logging (java.util.logging)1