天天看點

Liferay 啟動過程分析5-初始化插件包

 在MainServlet中,初始化ServletContextPool之後,就開始初始化plugin package:

.. 

    PluginPackage pluginPackage = null; 

        try { 

            pluginPackage = initPluginPackage(); 

        } 

它會調用同類的initPluginPackage()方法:

protected PluginPackage initPluginPackage() throws Exception { 

        ServletContext servletContext = getServletContext(); 

        return PluginPackageUtil.readPluginPackageServletContext( 

            servletContext); 

    } 

這段代碼會進而調用PluginPackageUtil類的readPluginPackageServletContext方法,這裡做了一個封裝:

public static PluginPackage readPluginPackageServletContext( 

            ServletContext servletContext) 

        throws DocumentException, IOException { 

        return _instance._readPluginPackageServletContext(servletContext); 

最終會調用PluginPackageUtil的私有方法_readPluginPackageServletContext方法:

private PluginPackage _readPluginPackageServletContext( 

        String servletContextName = servletContext.getServletContextName(); 

        String xml = HttpUtil.URLtoString( 

            servletContext.getResource("/WEB-INF/liferay-plugin-package.xml")); 

        if (_log.isInfoEnabled()) { 

            if (servletContextName == null) { 

                _log.info("Reading plugin package for the root context"); 

            } 

            else { 

                _log.info("Reading plugin package for " + servletContextName); 

        PluginPackage pluginPackage = null; 

        if (xml == null) { 

            String propertiesString = HttpUtil.URLtoString( 

                servletContext.getResource( 

                    "/WEB-INF/liferay-plugin-package.properties")); 

            if (propertiesString != null) { 

                if (_log.isDebugEnabled()) { 

                    _log.debug( 

                        "Reading plugin package from " + 

                            "liferay-plugin-package.properties"); 

                } 

                Properties properties = PropertiesUtil.load(propertiesString); 

                String displayName = servletContextName; 

                if (displayName.startsWith(StringPool.SLASH)) { 

                    displayName = displayName.substring(1); 

                pluginPackage = _readPluginPackageProperties( 

                    displayName, properties); 

            if (pluginPackage == null) { 

                    _log.debug("Reading plugin package from MANIFEST.MF"); 

                pluginPackage =_readPluginPackageServletManifest( 

                    servletContext); 

        else { 

            if (_log.isDebugEnabled()) { 

                _log.debug( 

                    "Reading plugin package from liferay-plugin-package.xml"); 

            pluginPackage = _readPluginPackageXml(xml); 

        pluginPackage.setContext(servletContextName); 

        return pluginPackage; 

讀取XML格式的配置檔案還是.properties格式的配置檔案:

我們先看到在第08行,會去讀取ROOT應用下的liferay-plugin-package.xml檔案+MANIFEST.MF檔案,如果沒有這個xml擴充名的檔案,則會去讀取liferay-plugin-package.properties檔案,(PS,難怪我用了一個月的Liferay,有些portlet用xml檔案有些用properties檔案配置的,都可以)。

讀取MANIFEST.MF檔案:(ROOT應用下沒有,是以不用讀)

因為我們ROOT應用下有liferay-plugin-package.xml,是以跳轉到45行,它會去讀取ROOT應用下的MANIFEST.MF:

private PluginPackage _readPluginPackageServletManifest( 

        throws IOException { 

            Attributes attributes = null; 

        InputStream inputStream = servletContext.getResourceAsStream( 

            "/META-INF/MANIFEST.MF"); 

        if (inputStream != null) { 

            Manifest manifest = new Manifest(inputStream); 

            attributes = manifest.getMainAttributes(); 

            attributes = new Attributes(); 

        String artifactGroupId = attributes.getValue( 

            "Implementation-Vendor-Id"); 

        if (Validator.isNull(artifactGroupId)) { 

            artifactGroupId = attributes.getValue("Implementation-Vendor"); 

            artifactGroupId = GetterUtil.getString( 

                attributes.getValue("Bundle-Vendor"), servletContextName); 

        String artifactId = attributes.getValue("Implementation-Title"); 

        if (Validator.isNull(artifactId)) { 

            artifactId = GetterUtil.getString( 

                attributes.getValue("Bundle-Name"), servletContextName); 

        String version = attributes.getValue("Implementation-Version"); 

        if (Validator.isNull(version)) { 

            version = GetterUtil.getString( 

                attributes.getValue("Bundle-Version"), Version.UNKNOWN); 

        if (version.equals(Version.UNKNOWN) && _log.isWarnEnabled()) { 

            _log.warn( 

                "Plugin package on context " + servletContextName + 

                    " cannot be tracked because this WAR does not contain a " + 

                        "liferay-plugin-package.xml file"); 

        PluginPackage pluginPackage = new PluginPackageImpl( 

            artifactGroupId + StringPool.SLASH + artifactId + StringPool.SLASH + 

                version + StringPool.SLASH + "war"); 

        pluginPackage.setName(artifactId); 

        String shortDescription = attributes.getValue("Bundle-Description"); 

        if (Validator.isNotNull(shortDescription)) { 

            pluginPackage.setShortDescription(shortDescription); 

        String pageURL = attributes.getValue("Bundle-DocURL"); 

        if (Validator.isNotNull(pageURL)) { 

            pluginPackage.setPageURL(pageURL); 

從這裡代碼,我們可以看出,它吧這個檔案的一些資訊都讀取出來,但是對于ROOT引用沒有這個MANIFEST.MF檔案,是以忽略。

讀取liferay-plugin-package.xml檔案:

然後,它會去解析liferay-plugin-package.xml檔案,即開始進入_readPluginPackageServletContext方法的第60行。解析代碼為:

private PluginPackage _readPluginPackageXml(String xml) 

        throws DocumentException { 

        Document document = SAXReaderUtil.read(xml); 

        Element rootElement = document.getRootElement(); 

        return _readPluginPackageXml(rootElement); 

它會委托另一個重載方法,隻不過入參是Element而不是String了:

private PluginPackage _readPluginPackageXml(Element pluginPackageElement) { 

        String name = pluginPackageElement.elementText("name"); 

        if (_log.isDebugEnabled()) { 

            _log.debug("Reading pluginPackage definition " + name); 

            GetterUtil.getString( 

                pluginPackageElement.elementText("module-id"))); 

        List<String> liferayVersions = _readList( 

            pluginPackageElement.element("liferay-versions"), 

            "liferay-version"); 

        List<String> types = _readList( 

            pluginPackageElement.element("types"), "type"); 

        pluginPackage.setName(_readText(name)); 

        pluginPackage.setRecommendedDeploymentContext( 

            _readText( 

                pluginPackageElement.elementText( 

                    "recommended-deployment-context"))); 

        pluginPackage.setModifiedDate( 

            _readDate(pluginPackageElement.elementText("modified-date"))); 

        pluginPackage.setAuthor( 

            _readText(pluginPackageElement.elementText("author"))); 

        pluginPackage.setTypes(types); 

        pluginPackage.setLicenses( 

            _readLicenseList( 

                pluginPackageElement.element("licenses"), "license")); 

        pluginPackage.setLiferayVersions(liferayVersions); 

        pluginPackage.setTags( 

            _readList(pluginPackageElement.element("tags"), "tag")); 

        pluginPackage.setShortDescription( 

            _readText(pluginPackageElement.elementText("short-description"))); 

        pluginPackage.setLongDescription( 

            _readHtml(pluginPackageElement.elementText("long-description"))); 

        pluginPackage.setChangeLog( 

            _readHtml(pluginPackageElement.elementText("change-log"))); 

        pluginPackage.setScreenshots( 

            _readScreenshots(pluginPackageElement.element("screenshots"))); 

        pluginPackage.setPageURL( 

            _readText(pluginPackageElement.elementText("page-url"))); 

        pluginPackage.setDownloadURL( 

            _readText(pluginPackageElement.elementText("download-url"))); 

        pluginPackage.setDeploymentSettings( 

            _readProperties( 

                pluginPackageElement.element("deployment-settings"), 

                "setting")); 

從這裡看出來,它就是建立一個PluginPackage對象,然後用這個XML檔案中的資訊往其中填充資訊而已:

我們ROOT應用的liferay-plugin-package.xml如下所示:

<?xml version="1.0"?> 

<!DOCTYPE plugin-package PUBLIC "-//Liferay//DTD Plugin Package 6.1.0//EN" "http://www.liferay.com/dtd/liferay-plugin-package_6_1_0.dtd"> 

<plugin-package> 

    <name>Liferay Core Plugins</name> 

    <module-id>liferay/core-plugins/6.1.0/war</module-id> 

    <types> 

        <type>layout-template</type> 

        <type>portlet</type> 

        <type>theme</type> 

    </types> 

    <short-description> 

        Portlets, themes, and layout templates included with Liferay Portal. 

    </short-description> 

    <change-log> 

        Adapted to the latest version of Liferay. 

    </change-log> 

    <page-url>http://www.liferay.com/web/guest/downloads</page-url> 

    <author>Liferay, Inc.</author> 

    <licenses> 

        <license osi-approved="true">LGPL</license> 

    </licenses> 

    <liferay-versions> 

        <liferay-version>6.1.0</liferay-version> 

    </liferay-versions> 

</plugin-package> 

綁定這個Liferay Core Plugin到ROOT context:

當解析完ROOT應用下的PluginPackage之後,它會綁定到ROOT Context,通過執行_readPluginPackageServletContext方法的第60行:

pluginPackage.setContext(servletContextName); 

于是,現在Core Plugin就作為第一個PluginPackage被架構所使用了。

本文轉自 charles_wang888 51CTO部落格,原文連結:http://blog.51cto.com/supercharles888/906049,如需轉載請自行聯系原作者