现象:
今天,同事有个问题问我,就是他建了一个Maven项目的portlet,名字叫inter-portlet-communication-test ,然后maven打包后,在$liferay_home下多了一个文件叫inter-portlet-communication-test-0.0.1-SNAPSHOT.war,
但是当运行时,这个构件到tomcat的webapp下的目录名称总是inter-portlet,并不显示后面的communication-test,并且无论是改为inter-portlet1-communication-test还是叫inter-portlet2-communication-test2都一样。
分析:
为了解决这个问题,我们可以断点跟踪分析:
首先,因为我们通过Maven的liferay:deploy命令将我们的portlet构件部署到了$liferay_home/deploy目录,所以这将触发PortletAutoDeployListener的deploy方法的执行:
- 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行,我们继续跟进:
它会去调用PortletAutoDeployer类的autoDeploy(File file,String context)方法:
- 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方法:
- public void deployFile(File srcFile, String specifiedContext)
- throws Exception {
- PluginPackage pluginPackage = readPluginPackage(srcFile);
- ..
这个会在方法的首行调用BaseDeployer的readPluginPackage方法,并且把我们的放在$liferay_home/deployer的war包封装一个File对象传递:
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目录下建子目录。
结束。