Package cc.concurrent.config.client

Source Code of cc.concurrent.config.client.Config

package cc.concurrent.config.client;

import cc.concurrent.config.client.loader.Loader;
import cc.concurrent.config.client.loader.LocalLoader;
import cc.concurrent.config.client.loader.RemoteLoader;
import cc.concurrent.config.core.model.CheckParam;
import cc.concurrent.config.core.model.FilePublished;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static com.google.common.base.Preconditions.checkNotNull;

/**
* User: yanghe.liang
* Date: 13-11-2
* Time: 下午6:24
*/
public class Config {

    private final static Logger logger = LoggerFactory.getLogger(Config.class);

    private final RemoteLoader remoteLoader;
    private final LocalLoader localLoader;
    private final boolean isRemoteFirst;
    private final long remoteCheckInterval;

    private final ConcurrentHashMap<Class<?>, BeanDesc<?>> cache = new ConcurrentHashMap<Class<?>, BeanDesc<?>>();
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    public Config(String appName, String remoteUrl, int remoteCheckInterval, String localDir) {
        this(appName, remoteUrl, remoteCheckInterval, localDir, false);
    }

    public Config(String appName, String remoteUrl, int remoteCheckInterval, String localDir, boolean isRemoteFirst) {
        this.remoteLoader = new RemoteLoader(appName, remoteUrl, localDir);
        this.remoteCheckInterval = remoteCheckInterval;
        this.localLoader = new LocalLoader(appName, localDir);
        this.isRemoteFirst = isRemoteFirst;
    }

    public void start(Class<?> ... clazzs) {
        try {
            remoteLoader.init();
            localLoader.init();
            for (Class<?> clazz : clazzs) {
                getBean(clazz, true);
            }
            startMonitor();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new IllegalStateException(e);
        }
    }

    public <T> T getBean(Class<T> clazz) {
        return getBean(clazz, isRemoteFirst);
    }

    @SuppressWarnings("unchecked")
    public <T> T getBean(Class<T> clazz, boolean isRemoteFirst) {
        checkNotNull(clazz);
        BeanDesc<?> beanDesc = cache.get(clazz);
        if (beanDesc == null) {
            synchronized (clazz.getName().intern()) {
                beanDesc = cache.get(clazz);
                if (beanDesc == null) {
                    beanDesc = loadBeanDesc(clazz, isRemoteFirst);
                    if (beanDesc != null) {
                        cache.put(clazz, beanDesc);
                    }
                }
            }
        }
        checkNotNull(beanDesc);
        return (T) beanDesc.getBean();
    }

    private <T> BeanDesc<T> loadBeanDesc(Class<T> clazz, boolean isRemoteFirst) {
        Root root = clazz.getAnnotation(Root.class);
        checkNotNull(root, "class %s must have annotation %s", clazz.getName(), Root.class.getName());
        String fileName = root.name();

        List<Loader> loaders = isRemoteFirst ?
                Lists.newArrayList(remoteLoader, localLoader) :
                Lists.newArrayList(localLoader, remoteLoader);

        for (Loader loader : loaders) {
            try {
                return loader.load(fileName, clazz);
            } catch (IllegalStateException e) {
                logger.error(e.getMessage());
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
        return null;
    }

    private void startMonitor() {
        scheduler.scheduleWithFixedDelay(new Runnable() {

            @Override
            public void run() {
                try {
                    List<CheckParam> checkParams = Lists.newArrayList();
                    Set<Map.Entry<Class<?>, BeanDesc<?>>> entries = cache.entrySet();
                    Map<String, Class<?>> classMap = Maps.newHashMap(); // fileName对应的Class
                    for (Map.Entry<Class<?>, BeanDesc<?>> entry : entries) {
                        BeanDesc<?> beanDesc = entry.getValue();
                        checkParams.add(new CheckParam(beanDesc.getFileName(), beanDesc.getMd5()));
                        classMap.put(beanDesc.getFileName(), beanDesc.getBean().getClass());
                    }
                    if (logger.isDebugEnabled()) {
                        logger.debug("checkParams=" + checkParams);
                    }
                    List<FilePublished> changes = remoteLoader.checkAndDownload(checkParams);
                    if (logger.isDebugEnabled()) {
                        logger.debug("changes=" + changes);
                    }
                    for (FilePublished change : changes) {
                        String fileName = change.getFileName();
                        String xml = change.getXml();
                        String md5 = change.getMd5();
                        Class<?> clazz = classMap.get(fileName);
                        Serializer serializer = new Persister();
                        Object bean = serializer.read(clazz, change.getXml(), false);
                        BeanDesc<?> beanDesc = new BeanDesc<Object>(fileName, md5, bean);
                        cache.replace(clazz, beanDesc); // 更新cache
                        remoteLoader.cacheXml(fileName, xml); // 缓存到本地
                    }
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }, remoteCheckInterval, remoteCheckInterval, TimeUnit.SECONDS);
    }

}















TOP

Related Classes of cc.concurrent.config.client.Config

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.