Search in sources :

Example 1 with Application

use of org.redkale.boot.Application 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)

Aggregations

java.io (java.io)1 Annotation (java.lang.annotation.Annotation)1 java.lang.reflect (java.lang.reflect)1 java.net (java.net)1 java.nio.file (java.nio.file)1 java.util (java.util)1 SimpleEntry (java.util.AbstractMap.SimpleEntry)1 java.util.concurrent (java.util.concurrent)1 java.util.function (java.util.function)1 java.util.logging (java.util.logging)1 javax.annotation (javax.annotation)1 Application (org.redkale.boot.Application)1 FilterEntry (org.redkale.boot.ClassFilter.FilterEntry)1 ClusterAgent (org.redkale.cluster.ClusterAgent)1 MessageAgent (org.redkale.mq.MessageAgent)1 org.redkale.net (org.redkale.net)1 Filter (org.redkale.net.Filter)1 org.redkale.net.http (org.redkale.net.http)1 org.redkale.net.sncp (org.redkale.net.sncp)1 org.redkale.service (org.redkale.service)1