net.ymate.platform.plugin.impl.DefaultPluginParser.java Source code

Java tutorial

Introduction

Here is the source code for net.ymate.platform.plugin.impl.DefaultPluginParser.java

Source

/*
 * Copyright 2007-2107 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.ymate.platform.plugin.impl;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import net.ymate.platform.base.YMP;
import net.ymate.platform.commons.i18n.I18N;
import net.ymate.platform.commons.lang.BlurObject;
import net.ymate.platform.commons.util.FileUtils;
import net.ymate.platform.commons.util.ResourceUtils;
import net.ymate.platform.commons.util.RuntimeUtils;

import net.ymate.platform.plugin.IPluginFactory;
import net.ymate.platform.plugin.IPluginParser;
import net.ymate.platform.plugin.PluginClassLoader;
import net.ymate.platform.plugin.PluginMeta;
import net.ymate.platform.plugin.PluginParserException;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * <p>
 * DefaultPluginParser
 * </p>
 * <p>
 * ????
 * </p>
 * 
 * @author (suninformation@163.com)
 * @version 0.0.0
 *          <table style="border:1px solid gray;">
 *          <tr>
 *          <th width="100px">?</th><th width="100px"></th><th
 *          width="100px"></th><th width="100px"></th>
 *          </tr>
 *          <!--  Table ?? -->
 *          <tr>
 *          <td>0.0.0</td>
 *          <td></td>
 *          <td></td>
 *          <td>2012-12-2?4:53:52</td>
 *          </tr>
 *          </table>
 */
public class DefaultPluginParser implements IPluginParser {

    private static final Log _LOG = LogFactory.getLog(DefaultPluginParser.class);

    private static final String PLUGIN_TAG = "plugin";

    private static final String ATTR_NAME = "name";
    private static final String ATTR_ALIAS = "alias";
    private static final String ATTR_CLASS = "class";
    private static final String ATTR_ID = "id";
    private static final String ATTR_VERSION = "version";
    private static final String ATTR_AUTHOR = "author";
    private static final String ATTR_EMAIL = "email";
    private static final String ATTR_AUTOMATIC = "automatic";
    private static final String ATTR_DISABLED = "disabled";
    private static final String ATTR_EXTRA_PART = "extra-part";
    private static final String ATTR_DESCRIPTION = "description";

    private IPluginFactory __pluginFactory;

    /* (non-Javadoc)
     * @see net.ymate.platform.plugin.IPluginParser#doParser()
     */
    public Map<String, PluginMeta> doParser() throws PluginParserException {
        Map<String, PluginMeta> _returnValue = new HashMap<String, PluginMeta>();
        try {
            // ?CLASSPATH???Jar
            List<String> _excludePluginIds = new ArrayList<String>();
            Iterator<URL> _configURLs = ResourceUtils
                    .getResources(__pluginFactory.getPluginConfig().getPluginManifestFile(), this.getClass(), true);
            while (_configURLs.hasNext()) {
                URL _configURL = _configURLs.next();
                List<PluginMeta> _metas = __doManifestFileProcess(__pluginFactory.getPluginClassLoader(), null,
                        _configURL);
                // ?CLASSPATH???
                for (PluginMeta _meta : _metas) {
                    if (__pluginFactory.getPluginConfig().isIncludeClassPath()) {
                        _returnValue.put(_meta.getId(), _meta);
                    }
                    _excludePluginIds.add(_meta.getId());
                }
            }
            // ??PLUGIN_HOME?
            if (StringUtils.isNotBlank(__pluginFactory.getPluginConfig().getPluginHomePath())) {
                File _pluginDirFile = new File(__pluginFactory.getPluginConfig().getPluginHomePath());
                if (_pluginDirFile.exists() && _pluginDirFile.isDirectory()) {
                    File[] _subDirFiles = _pluginDirFile.listFiles();
                    for (File _subDirFile : _subDirFiles != null ? _subDirFiles : new File[0]) {
                        if (_subDirFile.isDirectory()) {
                            ClassLoader _currentLoader = __doCreatePluginClassLoader(_subDirFile.getPath());
                            // ???
                            File _manifestFile = new File(_subDirFile,
                                    __pluginFactory.getPluginConfig().getPluginManifestFile());
                            if (_manifestFile.exists() && _manifestFile.isFile()) {
                                List<PluginMeta> _metas = __doManifestFileProcess(_currentLoader,
                                        _subDirFile.getPath(), _manifestFile.toURI().toURL());
                                for (PluginMeta _meta : _metas) {
                                    _returnValue.put(_meta.getId(), _meta);
                                }
                            } else {
                                // ???JAR?
                                Enumeration<URL> _pluginConfigURLs = _currentLoader
                                        .getResources(__pluginFactory.getPluginConfig().getPluginManifestFile());
                                while (_pluginConfigURLs.hasMoreElements()) {
                                    List<PluginMeta> _metas = __doManifestFileProcess(_currentLoader,
                                            _subDirFile.getPath(), _pluginConfigURLs.nextElement());
                                    for (PluginMeta _meta : _metas) {
                                        if (_excludePluginIds.contains(_meta.getId())) {
                                            // CLASSPATH?Jar?????
                                            break;
                                        }
                                        _returnValue.put(_meta.getId(), _meta);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new PluginParserException(RuntimeUtils.unwrapThrow(e));
        }
        return _returnValue;
    }

    /**
     * ?HOME?
     *
     * @param path
     * @return
     * @throws MalformedURLException
     */
    private ClassLoader __doCreatePluginClassLoader(String path) throws MalformedURLException {
        _LOG.info(I18N.formatMessage(YMP.__LSTRING_FILE, null, null, "ymp.plugin.create_plugin_loader", path));
        ArrayList<URL> _libList = new ArrayList<URL>();
        // JAR
        File _pluginLibDir = new File(FileUtils.fixSeparator(path) + "lib");
        if (_pluginLibDir.exists() && _pluginLibDir.isDirectory()) {
            File[] _libFiles = _pluginLibDir.listFiles();
            for (File _libFile : _libFiles != null ? _libFiles : new File[0]) {
                if (_libFile.isFile() && _libFile.getAbsolutePath().endsWith("jar")) {
                    _libList.add(_libFile.toURI().toURL());
                    _LOG.info(I18N.formatMessage(YMP.__LSTRING_FILE, null, null, "ymp.plugin.plugin_load_jar_file",
                            path, _libFile.getPath()));
                }
            }
        }
        // 
        _pluginLibDir = new File(FileUtils.fixSeparator(path) + "classes");
        if (_pluginLibDir.exists() && _pluginLibDir.isDirectory()) {
            _libList.add(_pluginLibDir.toURI().toURL());
            _LOG.info(I18N.formatMessage(YMP.__LSTRING_FILE, null, null, "ymp.plugin.plugin_load_classpath", path,
                    _pluginLibDir.getPath()));
        }
        _LOG.info(
                I18N.formatMessage(YMP.__LSTRING_FILE, null, null, "ymp.plugin.create_plugin_loader_final", path));
        return new PluginClassLoader(_libList.toArray(new URL[0]), __pluginFactory.getPluginClassLoader());
    }

    /**
     * ???
     *
      * @param classLoader
     * @param pluginPath
     * @param configFileUrl
     * @return
     * @throws IOException
     * @throws SAXException
     * @throws ParserConfigurationException
     */
    private List<PluginMeta> __doManifestFileProcess(ClassLoader classLoader, String pluginPath, URL configFileUrl)
            throws IOException, SAXException, ParserConfigurationException {
        _LOG.info(I18N.formatMessage(YMP.__LSTRING_FILE, null, null, "ymp.plugin.parse_plugin_file",
                configFileUrl.getFile()));
        List<PluginMeta> _returnValue = new ArrayList<PluginMeta>();
        //
        List<Element> _pluginElements = new ArrayList<Element>();
        //
        InputStream _in = configFileUrl.openStream();
        Document _document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(_in);
        Element _rootElement = _document.getDocumentElement();
        // ?
        boolean _pluginGroupFlag = false;
        String _pluginAuthor = _rootElement.getAttribute(ATTR_AUTHOR);
        String _pluginEmail = _rootElement.getAttribute(ATTR_EMAIL);
        String _pluginVersion = _rootElement.getAttribute(ATTR_VERSION);
        boolean _authorNotNull = StringUtils.isNotBlank(_pluginAuthor);
        boolean _emailNotNull = StringUtils.isNotBlank(_pluginEmail);
        boolean _versionNotNull = StringUtils.isNotBlank(_pluginVersion);
        //
        if (_rootElement.getNodeName().equals(PLUGIN_TAG)) {
            _pluginElements.add(_rootElement);
        } else {
            // ????????
            _pluginGroupFlag = true;
            _pluginAuthor = _rootElement.getAttribute(ATTR_AUTHOR);
            _pluginEmail = _rootElement.getAttribute(ATTR_EMAIL);
            _pluginVersion = _rootElement.getAttribute(ATTR_VERSION);
            //
            NodeList _pluginNodes = _rootElement.getElementsByTagName(PLUGIN_TAG);
            for (int _idx = 0; _idx < _pluginNodes.getLength(); _idx++) {
                _pluginElements.add((Element) _pluginNodes.item(_idx));
            }
        }
        for (Element _pluginElement : _pluginElements) {
            PluginMeta _pluginMeta = __doPluginElementProcess(classLoader, _pluginElement, pluginPath,
                    configFileUrl);
            if (_pluginMeta != null) {
                // ??????
                if (_pluginGroupFlag) {
                    if (_authorNotNull && StringUtils.isBlank(_pluginMeta.getAuthor())) {
                        _pluginMeta.setAuthor(_pluginAuthor);
                    }
                    if (_emailNotNull && StringUtils.isBlank(_pluginMeta.getEmail())) {
                        _pluginMeta.setEmail(_pluginEmail);
                    }
                    if (_versionNotNull && StringUtils.isBlank(_pluginMeta.getVersion())) {
                        _pluginMeta.setVersion(_pluginVersion);
                    }
                }
                _returnValue.add(_pluginMeta);
            }
        }
        return _returnValue;
    }

    private PluginMeta __doPluginElementProcess(ClassLoader classLoader, Element pluginElement, String pluginPath,
            URL configFileUrl) {
        String id = pluginElement.getAttribute(ATTR_ID);
        String name = pluginElement.getAttribute(ATTR_NAME);
        String alias = pluginElement.getAttribute(ATTR_ALIAS);
        String version = pluginElement.getAttribute(ATTR_VERSION);
        String initClass = pluginElement.getAttribute(ATTR_CLASS);
        if ((StringUtils.isBlank(alias) || StringUtils.isBlank(name)) && StringUtils.isBlank(initClass)) {
            _LOG.warn(I18N.formatMessage(YMP.__LSTRING_FILE, null, null, "ymp.plugin.plugin_will_be_ignored",
                    configFileUrl.getFile()));
            return null;
        }
        if (StringUtils.isBlank(id)) {
            // ?ID???MD5??ID
            id = DigestUtils.md5Hex(initClass);
        }
        //
        boolean disabled = false;
        NodeList _disabledNodes = pluginElement.getElementsByTagName(ATTR_DISABLED);
        if (_disabledNodes.getLength() > 0) {
            Node _node = _disabledNodes.item(0);
            disabled = new BlurObject(_node.getTextContent()).toBooleanValue();
        }
        if (disabled) {
            _LOG.warn(I18N.formatMessage(YMP.__LSTRING_FILE, null, null, "ymp.plugin.plugin_will_be_disabled",
                    configFileUrl.getFile()));
            return null;
        }
        String author = pluginElement.getAttribute(ATTR_AUTHOR);
        String email = pluginElement.getAttribute(ATTR_EMAIL);
        String description = "";
        NodeList _descriptionNodes = pluginElement.getElementsByTagName(ATTR_DESCRIPTION);
        if (_descriptionNodes.getLength() > 0) {
            Node _node = _descriptionNodes.item(0);
            description = _node.getTextContent();
        }
        boolean automatic = true;
        NodeList _automacticNodes = pluginElement.getElementsByTagName(ATTR_AUTOMATIC);
        if (_automacticNodes.getLength() > 0) {
            Node _node = _automacticNodes.item(0);
            automatic = new BlurObject(_node.getTextContent()).toBooleanValue();
        }
        Object _extraObj = null;
        if (__pluginFactory.getPluginConfig().getPluginExtraParserClassImpl() != null) {
            NodeList _extraNodes = pluginElement.getElementsByTagName(ATTR_EXTRA_PART);
            if (_extraNodes.getLength() > 0) {
                _extraObj = __pluginFactory.getPluginConfig().getPluginExtraParserClassImpl()
                        .doExtarParser(_extraNodes.item(0));
            }
        }
        PluginMeta _pluginMeta = new PluginMeta(classLoader, id, name, alias, initClass, version, pluginPath,
                author, email, _extraObj, description);
        _pluginMeta.setAutomatic(automatic);
        _pluginMeta.setDisabled(disabled);
        if (configFileUrl.getProtocol().equals("jar")) {
            _pluginMeta
                    .setPluginFile(new File(StringUtils.substringBetween(configFileUrl.getFile(), "file:", "!")));
        }
        return _pluginMeta;
    }

    /* (non-Javadoc)
     * @see net.ymate.platform.plugin.IPluginParser#setPluginFactory(net.ymate.platform.plugin.IPluginFactory)
     */
    public void setPluginFactory(IPluginFactory factory) {
        __pluginFactory = factory;
    }

}