現象:web
今天,同事有個問題問我,就是他建了一個Maven項目的portlet,名字叫inter-portlet-communication-test ,而後maven打包後,在$liferay_home下多了一個文件叫inter-portlet-communication-test-0.0.1-SNAPSHOT.war,tomcat
可是當運行時,這個構件到tomcat的webapp下的目錄名稱老是inter-portlet,並不顯示後面的communication-test,而且不管是改成inter-portlet1-communication-test仍是叫inter-portlet2-communication-test2都同樣。服務器
分析:app
爲了解決這個問題,咱們能夠斷點跟蹤分析:webapp
首先,由於咱們經過Maven的liferay:deploy命令將咱們的portlet構件部署到了$liferay_home/deploy目錄,因此這將觸發PortletAutoDeployListener的deploy方法的執行:maven
- public void deploy(File file, String context) throws AutoDeployException {
- if (_log.isDebugEnabled()) {
- _log.debug("Invoking deploy for " + file.getPath());
- }
- AutoDeployer deployer = null;
- if (isMatchingFile(
- file, "WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD)) {
- deployer = _autoDeployer;
- }
- ...
- if (_log.isInfoEnabled()) {
- _log.info("Copying portlets for " + file.getPath());
- }
- if (_log.isDebugEnabled()) {
- _log.debug("Using deployer " + deployer.getClass().getName());
- }
- deployer.autoDeploy(file, context);
- if (_log.isInfoEnabled()) {
- _log.info(
- "Portlets for " + file.getPath() + " copied successfully. " +
- "Deployment will start in a few seconds.");
- }
- }
由於咱們的構件中有portlet.xml,因此知足08-09行的條件,而後會打印日誌,接着執行第23行,咱們繼續跟進:ide
它會去調用PortletAutoDeployer類的autoDeploy(File file,String context)方法:this
- public void autoDeploy(File file, String context)
- throws AutoDeployException {
- List<String> wars = new ArrayList<String>();
- wars.add(file.getName());
- this.wars = wars;
- try {
- deployFile(file, context);
- }
- catch (Exception e) {
- throw new AutoDeployException(e);
- }
- }
而後在第11行調用父類BaseDeployer的deployFile方法:url
- public void deployFile(File srcFile, String specifiedContext)
- throws Exception {
- PluginPackage pluginPackage = readPluginPackage(srcFile);
- ..
這個會在方法的首行調用BaseDeployer的readPluginPackage方法,而且把咱們的放在$liferay_home/deployer的war包封裝一個File對象傳遞:spa
readPluginPackage方法以下:
- public PluginPackage readPluginPackage(File file) {
- if (!file.exists()) {
- return null;
- }
- InputStream is = null;
- ZipFile zipFile = null;
- try {
- boolean parseProps = false;
- if (file.isDirectory()) {
- ...
- }
- else {
- zipFile = new ZipFile(file);
- File pluginPackageXmlFile = new File(
- file.getParent() + "/merge/" + file.getName() +
- "/WEB-INF/liferay-plugin-package.xml");
- if (pluginPackageXmlFile.exists()) {
- is = new FileInputStream(pluginPackageXmlFile);
- }
- else {
- ZipEntry zipEntry = zipFile.getEntry(
- "WEB-INF/liferay-plugin-package.xml");
- if (zipEntry != null) {
- is = zipFile.getInputStream(zipEntry);
- }
- }
- File pluginPackagePropertiesFile = new File(
- file.getParent() + "/merge/" + file.getName() +
- "/WEB-INF/liferay-plugin-package.properties");
- if ((is == null) && pluginPackagePropertiesFile.exists()) {
- is = new FileInputStream(pluginPackagePropertiesFile);
- parseProps = true;
- }
- else {
- ZipEntry zipEntry = zipFile.getEntry(
- "WEB-INF/liferay-plugin-package.properties");
- if ((is == null) && (zipEntry != null)) {
- is = zipFile.getInputStream(zipEntry);
- parseProps = true;
- }
- }
- }
- if (is == null) {
- if (_log.isInfoEnabled()) {
- _log.info(
- file.getPath() + " does not have a " +
- "WEB-INF/liferay-plugin-package.xml or " +
- "WEB-INF/liferay-plugin-package.properties");
- }
- return null;
- }
- if (parseProps) {
- String displayName = getDisplayName(file);
- String propertiesString = StringUtil.read(is);
- Properties properties = PropertiesUtil.load(propertiesString);
- return PluginPackageUtil.readPluginPackageProperties(
- displayName, properties);
- }
- else {
- String xml = StringUtil.read(is);
- xml = XMLFormatter.fixProlog(xml);
- return PluginPackageUtil.readPluginPackageXml(xml);
- }
- }
- catch (Exception e) {
- _log.error(file.getPath() + ": " + e.toString());
- }
- finally {
- ...
- }
- return null;
- }
由於咱們在$liferay_home/deploy目錄下的是一個war包而不是一個目錄,因此執行第15行開始的else分支,並且咱們提供的liferay-plugin-package是.properties文件而不是xml文件,因此執行第43行開始的else分支,它用來解析liferay-plugin-package.properties文件。
最終,它在第73行中調用PluginPackageUtil的readPluginPackageProperties方法,進而會調用私有的_readPluginPackageProperties方法,咱們繼續跟進:
- private PluginPackage _readPluginPackageProperties(
- String displayName, Properties properties) {
- int pos = displayName.indexOf("-portlet");
- String pluginType = Plugin.TYPE_PORTLET;
- if (pos == -1) {
- pos = displayName.indexOf("-ext");
- pluginType = Plugin.TYPE_EXT;
- }
- if (pos == -1) {
- pos = displayName.indexOf("-hook");
- pluginType = Plugin.TYPE_HOOK;
- }
- if (pos == -1) {
- pos = displayName.indexOf("-layouttpl");
- pluginType = Plugin.TYPE_LAYOUT_TEMPLATE;
- }
- if (pos == -1) {
- pos = displayName.indexOf("-theme");
- pluginType = Plugin.TYPE_THEME;
- }
- if (pos == -1) {
- pos = displayName.indexOf("-web");
- pluginType = Plugin.TYPE_WEB;
- }
- if (pos == -1) {
- return null;
- }
- String displayPrefix = displayName.substring(0, pos);
- String moduleGroupId = GetterUtil.getString(
- properties.getProperty("module-group-id"));
- String moduleArtifactId = displayPrefix + "-" + pluginType;
- String moduleVersion = null;
- int moduleVersionPos = pos + pluginType.length() + 2;
- if (displayName.length() > moduleVersionPos) {
- moduleVersion = displayName.substring(moduleVersionPos);
- }
- else {
- moduleVersion = ReleaseInfo.getVersion();
- }
- String moduleId =
- moduleGroupId + "/" + moduleArtifactId + "/" + moduleVersion +
- "/war";
- String pluginName = GetterUtil.getString(
- properties.getProperty("name"));
- String deploymentContext = GetterUtil.getString(
- properties.getProperty("recommended-deployment-context"),
- moduleArtifactId);
- String author = GetterUtil.getString(properties.getProperty("author"));
- List<String> types = new ArrayList<String>();
- types.add(pluginType);
- List<License> licenses = new ArrayList<License>();
- String[] licensesArray = StringUtil.split(
- properties.getProperty("licenses"));
- for (int i = 0; i < licensesArray.length; i++) {
- License license = new License();
- license.setName(licensesArray[i].trim());
- license.setOsiApproved(true);
- licenses.add(license);
- }
- List<String> liferayVersions = new ArrayList<String>();
- String[] liferayVersionsArray = StringUtil.split(
- properties.getProperty("liferay-versions"));
- for (String liferayVersion : liferayVersionsArray) {
- liferayVersions.add(liferayVersion.trim());
- }
- if (liferayVersions.size() == 0) {
- liferayVersions.add(ReleaseInfo.getVersion() + "+");
- }
- List<String> tags = new ArrayList<String>();
- String[] tagsArray = StringUtil.split(properties.getProperty("tags"));
- for (String tag : tagsArray) {
- tags.add(tag.trim());
- }
- String shortDescription = GetterUtil.getString(
- properties.getProperty("short-description"));
- String longDescription = GetterUtil.getString(
- properties.getProperty("long-description"));
- String changeLog = GetterUtil.getString(
- properties.getProperty("change-log"));
- String pageURL = GetterUtil.getString(
- properties.getProperty("page-url"));
- String downloadURL = GetterUtil.getString(
- properties.getProperty("download-url"));
- PluginPackage pluginPackage = new PluginPackageImpl(moduleId);
- pluginPackage.setName(pluginName);
- pluginPackage.setRecommendedDeploymentContext(deploymentContext);
- //pluginPackage.setModifiedDate(null);
- pluginPackage.setAuthor(author);
- pluginPackage.setTypes(types);
- pluginPackage.setLicenses(licenses);
- pluginPackage.setLiferayVersions(liferayVersions);
- pluginPackage.setTags(tags);
- pluginPackage.setShortDescription(shortDescription);
- pluginPackage.setLongDescription(longDescription);
- pluginPackage.setChangeLog(changeLog);
- //pluginPackage.setScreenshots(null);
- pluginPackage.setPageURL(pageURL);
- pluginPackage.setDownloadURL(downloadURL);
- //pluginPackage.setDeploymentSettings(null);
- return pluginPackage;
- }
從這裏咱們就一目瞭然了,它會先獲取displayName中"-portlet"的下標,而後得到第42行獲取這個下標前面的部分做爲displayPrefix,而後46行用這個displayPrefix加上短橫"-"加上pluginType(在第06行被解析,爲字符串"portlet"),這3個字符串鏈接做爲最終的moduleArtifactId. 按照咱們的例子,咱們的displayName是inter-portlet-communication-test,因此displayPrefix就是"inter",因此最後和'-'還有'portlet'拼接來來的字符串就是'inter-portlet',這也能夠解釋爲何不顯示後面的communication-test,和爲何吧portlet改成portlet1,其結果不變的緣由。
最後,當咱們在這裏得到了moduleArtifactId以後,在第66行設給字符串deploymentContext, 而後在第125行設置給字符串變量recommendedDeploymentContext,而後這就是咱們指望的, 因此最終web服務器會用這個字符串的值在webapps目錄下建子目錄。
結束。