All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alipay.rdf.file.loader.ExtensionLoader Maven / Gradle / Ivy

There is a newer version: 2.2.11
Show newest version
package com.alipay.rdf.file.loader;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import com.alipay.rdf.file.exception.RdfErrorEnum;
import com.alipay.rdf.file.exception.RdfFileException;
import com.alipay.rdf.file.util.RdfFileLogUtil;
import com.alipay.rdf.file.util.RdfFileUtil;

/**
 * Copyright (C) 2013-2018 Ant Financial Services Group
 * 
 * @author hongwei.quhw
 * @version $Id: ExtensionLoader.java, v 0.1 2017年4月1日 上午10:26:46 hongwei.quhw Exp $
 */
@SuppressWarnings("unchecked")
public class ExtensionLoader {
    private static final String                                          RDF_SERVICE_DIR   = "META-INF/rdf-file/services/";

    private static final ConcurrentHashMap, ExtensionLoader> EXTENSION_LOADERS = new ConcurrentHashMap, ExtensionLoader>();

    private final Object                                                 instanceLock      = new Object();
    private final Object                                                 clazzLock         = new Object();

    private final Class                                               type;

    private ConcurrentHashMap                                 cachedInstances   = null;

    private ConcurrentHashMap>                          cachedClasses     = null;

    private ConcurrentHashMap, List>                    cachedClass2Names = null;

    private ExtensionLoader(Class type) {
        this.type = type;
    }

    public static  ExtensionLoader getExtensionLoader(Class type) {
        RdfFileUtil.assertNotNull(type, "rdf-file#getExtensionLoader(type=null)",
            RdfErrorEnum.ILLEGAL_ARGUMENT);

        ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
        if (loader == null) {
            loader = new ExtensionLoader(type);
            EXTENSION_LOADERS.putIfAbsent(type, loader);
        }

        return loader;
    }

    public T getExtension(String name) {
        return getExtensions().get(RdfFileUtil.assertTrimNotBlank(name, "Extension name == null"));
    }

    public T getNewExtension(String name) {
        Class clazz = getExtensionClasses().get(RdfFileUtil.assertTrimNotBlank(name,
            "rdf-file#Extension name == null", RdfErrorEnum.ILLEGAL_ARGUMENT));

        if (clazz == null) {
            System.out.println(cachedClasses);
        }

        RdfFileUtil.assertNotNull(clazz,
            "rdf-file#Extension type=" + type.getName() + ", name =" + name + ", class == null",
            RdfErrorEnum.EXTENSION_ERROR);

        try {
            return (T) clazz.newInstance();
        } catch (InstantiationException e) {
            throw new RdfFileException(e, RdfErrorEnum.EXTENSION_ERROR);
        } catch (IllegalAccessException e) {
            throw new RdfFileException(e, RdfErrorEnum.EXTENSION_ERROR);
        }
    }

    public Map getExtensions() {
        if (null == cachedInstances) {
            synchronized (instanceLock) {
                if (null == cachedInstances) {
                    ConcurrentHashMap tempCachedInstances = new ConcurrentHashMap();
                    loadFile(tempCachedInstances);
                    cachedInstances = tempCachedInstances;
                }
            }
        }

        return cachedInstances;
    }

    public List getExtensionAlias(Class clazz) {
        getExtensionClasses();

        return cachedClass2Names.get(clazz);
    }

    public Class getExtensionClass(String name) {
        return (Class) getExtensionClasses().get(name);
    }

    public ConcurrentHashMap> getExtensionClasses() {
        if (null == cachedClasses) {
            synchronized (clazzLock) {
                if (null == cachedClasses) {
                    ConcurrentHashMap> tempCachedClasses = new ConcurrentHashMap>();
                    cachedClass2Names = new ConcurrentHashMap, List>();
                    loadExtensionFile(tempCachedClasses);
                    cachedClasses = tempCachedClasses;
                }
            }
        }

        return cachedClasses;
    }

    private void loadFile(ConcurrentHashMap cachedInstances) {
        ConcurrentHashMap> extensionClasses = getExtensionClasses();

        for (Entry> entry : extensionClasses.entrySet()) {
            try {
                cachedInstances.put(entry.getKey(), (T) entry.getValue().newInstance());
            } catch (InstantiationException e) {
                throw new RdfFileException(e, RdfErrorEnum.EXTENSION_ERROR);
            } catch (IllegalAccessException e) {
                throw new RdfFileException(e, RdfErrorEnum.EXTENSION_ERROR);
            }
        }
    }

    private void loadExtensionFile(ConcurrentHashMap> cachedClasses) {
        String fileName = RDF_SERVICE_DIR + type.getName();

        try {
            Enumeration urls = RdfFileUtil.getDefaultClassLoader().getResources(fileName);

            if (null == urls) {
                return;
            }

            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                BufferedReader reader = new BufferedReader(
                    new InputStreamReader(url.openStream(), "utf-8"));
                try {
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                        line = line.trim();
                        int idx = line.indexOf('=');
                        if (idx < 1) {
                            throw new RdfFileException("rdf-file#type=" + type.getName()
                                                       + ",extension服务配置格式错误 url=" + url.toString(),
                                RdfErrorEnum.EXTENSION_ERROR);
                        }

                        String key = RdfFileUtil.assertTrimNotBlank(line.substring(0, idx));
                        line = RdfFileUtil.assertTrimNotBlank(line.substring(idx + 1));

                        if (line.length() > 0) {
                            Class clazz = Class.forName(line, true,
                                RdfFileUtil.getDefaultClassLoader());
                            if (!type.isAssignableFrom(clazz)) {
                                throw new RdfFileException(
                                    "rdf-file#type=" + type.getName() + ", class: [" + line
                                                           + "] is not subtype of "
                                                           + type.getName(),
                                    RdfErrorEnum.EXTENSION_ERROR);
                            }
                            String[] aliases = key.split(",");

                            List aliasList = cachedClass2Names.get(clazz);
                            if (null == aliasList) {
                                aliasList = new ArrayList();
                                cachedClass2Names.put(clazz, aliasList);
                            }

                            for (String alias : aliases) {
                                alias = RdfFileUtil.assertTrimNotBlank(alias);
                                Class old = cachedClasses.get(alias);

                                if (null != old) {
                                    if (RdfFileLogUtil.common.isWarn()) {
                                        RdfFileLogUtil.common
                                            .warn("rdf-file#type=" + type.getName() + ",class=["
                                                  + clazz.getName() + "],key=[" + alias
                                                  + "] 重复定义了 url=" + url.getPath());
                                    }
                                } else {
                                    cachedClasses.putIfAbsent(alias, clazz);
                                    aliasList.add(alias);
                                }
                            }
                        }
                    }
                } finally {
                    if (null != reader) {
                        reader.close();
                    }
                }
            }
        } catch (RdfFileException e) {
            throw e;
        } catch (Throwable e) {
            throw new RdfFileException(
                "rdf-file#type=" + type.getName() + ",ExtensionLoader " + fileName + " 扩展失败", e,
                RdfErrorEnum.EXTENSION_ERROR);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy