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

com.liferay.portal.tools.deploy.BaseAutoDeployer Maven / Gradle / Ivy

/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.tools.deploy;

import com.liferay.petra.function.UnsafeConsumer;
import com.liferay.petra.string.CharPool;
import com.liferay.petra.string.StringBundler;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.deploy.DeployUtil;
import com.liferay.portal.kernel.deploy.auto.AutoDeployException;
import com.liferay.portal.kernel.deploy.auto.AutoDeployer;
import com.liferay.portal.kernel.deploy.auto.context.AutoDeploymentContext;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.plugin.License;
import com.liferay.portal.kernel.plugin.PluginPackage;
import com.liferay.portal.kernel.servlet.PluginContextListener;
import com.liferay.portal.kernel.servlet.PortalClassLoaderServlet;
import com.liferay.portal.kernel.servlet.PortalDelegateServlet;
import com.liferay.portal.kernel.servlet.PortletServlet;
import com.liferay.portal.kernel.servlet.SecurePluginContextListener;
import com.liferay.portal.kernel.servlet.SecureServlet;
import com.liferay.portal.kernel.servlet.SerializableSessionAttributeListener;
import com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter;
import com.liferay.portal.kernel.util.FileUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.HashMapBuilder;
import com.liferay.portal.kernel.util.PropertiesUtil;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.SystemProperties;
import com.liferay.portal.kernel.util.TextFormatter;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.xml.Document;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portal.kernel.xml.UnsecureSAXReaderUtil;
import com.liferay.portal.plugin.PluginPackageUtil;
import com.liferay.portal.tools.WebXMLBuilder;
import com.liferay.portal.util.PropsValues;

import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * @author Brian Wing Shun Chan
 * @author Sandeep Soni
 */
public class BaseAutoDeployer implements AutoDeployer {

	public static final String DEPLOY_TO_PREFIX = "DEPLOY_TO__";

	public BaseAutoDeployer(String pluginType) {
		_pluginType = pluginType;
	}

	@Override
	public int autoDeploy(AutoDeploymentContext autoDeploymentContext)
		throws AutoDeployException {

		try {
			File srcFile = autoDeploymentContext.getFile();
			PluginPackage pluginPackage =
				autoDeploymentContext.getPluginPackage();

			if (pluginPackage == null) {
				pluginPackage = _readPluginPackage(srcFile);

				autoDeploymentContext.setPluginPackage(pluginPackage);
			}

			if (_log.isInfoEnabled()) {
				_log.info("Deploying " + srcFile.getName());
			}

			String specifiedContext = autoDeploymentContext.getContext();

			String displayName = specifiedContext;

			String preliminaryContext = specifiedContext;

			// The order of priority of the context is: 1.) the specified
			// context, 2.) if the file name starts with DEPLOY_TO_PREFIX, use
			// the file name after the prefix, or 3.) the recommended deployment
			// context as specified in liferay-plugin-package.properties, or 4.)
			// the file name.

			String srcFileName = srcFile.getName();

			if (Validator.isNull(specifiedContext) &&
				srcFileName.startsWith(DEPLOY_TO_PREFIX)) {

				displayName = srcFileName.substring(
					DEPLOY_TO_PREFIX.length(), srcFileName.length() - 4);

				preliminaryContext = displayName;
			}

			if (preliminaryContext == null) {
				preliminaryContext = _getDisplayName(srcFile);
			}

			if (pluginPackage != null) {
				if (!PluginPackageUtil.isCurrentVersionSupported(
						pluginPackage.getLiferayVersions())) {

					throw new AutoDeployException(
						srcFile.getName() +
							" does not support this version of Liferay");
				}

				if (displayName == null) {
					displayName =
						pluginPackage.getRecommendedDeploymentContext();
				}

				if (Validator.isNull(displayName)) {
					displayName = _getDisplayName(srcFile);
				}

				pluginPackage.setContext(displayName);

				PluginPackageUtil.updateInstallingPluginPackage(
					preliminaryContext, pluginPackage);
			}

			String deployDir = null;

			if (Validator.isNotNull(displayName)) {
				deployDir = displayName + ".war";
			}
			else {
				deployDir = srcFile.getName();
				displayName = _getDisplayName(srcFile);
			}

			String destDir = autoDeploymentContext.getDestDir();

			File deployDirFile = new File(destDir + "/" + deployDir);

			try {
				PluginPackage previousPluginPackage = _readPluginPackage(
					deployDirFile);

				if ((pluginPackage != null) &&
					(previousPluginPackage != null)) {

					String name = pluginPackage.getName();
					String previousVersion = previousPluginPackage.getVersion();
					String version = pluginPackage.getVersion();

					if (_log.isInfoEnabled()) {
						_log.info(
							StringBundler.concat(
								"Updating ", name, " from version ",
								previousVersion, " to version ", version));
					}

					if (pluginPackage.isPreviousVersionThan(
							previousPluginPackage)) {

						if (_log.isInfoEnabled()) {
							_log.info(
								StringBundler.concat(
									"Not updating ", name, " because version ",
									previousVersion, " is newer than version ",
									version));
						}

						return AutoDeployer.CODE_SKIP_NEWER_VERSION;
					}
				}

				File mergeDirFile = new File(
					srcFile.getParent() + "/merge/" + srcFile.getName());

				if (srcFile.isDirectory()) {
					_deployDirectory(
						srcFile, mergeDirFile, deployDirFile, displayName,
						pluginPackage);
				}
				else {
					boolean deployed = _deployFile(
						srcFile, mergeDirFile, deployDirFile, displayName,
						pluginPackage);

					if (!deployed) {
						String context = preliminaryContext;

						if (pluginPackage != null) {
							context = pluginPackage.getContext();
						}

						PluginPackageUtil.endPluginPackageInstallation(context);
					}
				}

				return AutoDeployer.CODE_DEFAULT;
			}
			catch (Exception exception) {
				if (pluginPackage != null) {
					PluginPackageUtil.endPluginPackageInstallation(
						pluginPackage.getContext());
				}

				throw exception;
			}
		}
		catch (Exception exception) {
			throw new AutoDeployException(exception);
		}
	}

	@Override
	public void close() throws IOException {
		UnsafeConsumer.accept(
			tempDirPaths, DeployUtil::deletePath, IOException.class);
	}

	@Override
	public void copyDependencyXml(String fileName, String targetDir)
		throws Exception {

		copyDependencyXml(fileName, targetDir, null);
	}

	@Override
	public void copyDependencyXml(
			String fileName, String targetDir, Map filterMap)
		throws Exception {

		copyDependencyXml(fileName, targetDir, filterMap, false);
	}

	@Override
	public void copyDependencyXml(
			String fileName, String targetDir, Map filterMap,
			boolean overwrite)
		throws Exception {

		DeployUtil.copyDependencyXml(
			fileName, targetDir, fileName, filterMap, overwrite);
	}

	@Override
	public void copyXmls(
			File srcFile, String displayName, PluginPackage pluginPackage)
		throws Exception {

		copyDependencyXml("web.xml", srcFile + "/WEB-INF");
	}

	public void deployDirectory(
			File srcFile, String displayName, PluginPackage pluginPackage)
		throws Exception {

		_deployDirectory(srcFile, null, null, displayName, pluginPackage);
	}

	public String getExtraContent(
			double webXmlVersion, File srcFile, String displayName)
		throws Exception {

		if (displayName.startsWith(StringPool.FORWARD_SLASH)) {
			displayName = displayName.substring(1);
		}

		StringBundler sb = new StringBundler(69);

		sb.append("");
		sb.append(displayName);
		sb.append("");

		if (webXmlVersion < 2.4) {
			sb.append("");
			sb.append("liferay-invoker-enabled");
			sb.append("false");
			sb.append("");
		}

		if (PropsValues.SESSION_VERIFY_SERIALIZABLE_ATTRIBUTE) {
			sb.append("");
			sb.append("");
			sb.append(SerializableSessionAttributeListener.class.getName());
			sb.append("");
			sb.append("");
		}

		boolean hasTaglib = false;

		if (Validator.isNotNull(auiTaglibDTD) ||
			Validator.isNotNull(portletTaglibDTD) ||
			Validator.isNotNull(portletExtTaglibDTD) ||
			Validator.isNotNull(securityTaglibDTD) ||
			Validator.isNotNull(themeTaglibDTD) ||
			Validator.isNotNull(uiTaglibDTD) ||
			Validator.isNotNull(utilTaglibDTD)) {

			hasTaglib = true;
		}

		if (hasTaglib && (webXmlVersion > 2.3)) {
			sb.append("");
		}

		if (Validator.isNotNull(auiTaglibDTD)) {
			sb.append("");
			sb.append("http://liferay.com/tld/aui");
			sb.append("");
			sb.append("/WEB-INF/tld/liferay-aui.tld");
			sb.append("");
			sb.append("");
		}

		if (Validator.isNotNull(portletTaglibDTD)) {
			sb.append("");
			sb.append("http://java.sun.com/portlet_2_0");
			sb.append("");
			sb.append("");
			sb.append("/WEB-INF/tld/liferay-portlet_2_0.tld");
			sb.append("");
			sb.append("");
			sb.append("");
			sb.append("");
			sb.append("http://xmlns.jcp.org/portlet_3_0");
			sb.append("");
			sb.append("");
			sb.append("/WEB-INF/tld/liferay-portlet.tld");
			sb.append("");
			sb.append("");
		}

		if (Validator.isNotNull(portletExtTaglibDTD)) {
			sb.append("");
			sb.append("");
			sb.append("http://liferay.com/tld/portlet");
			sb.append("");
			sb.append("");
			sb.append("/WEB-INF/tld/liferay-portlet-ext.tld");
			sb.append("");
			sb.append("");
		}

		if (Validator.isNotNull(securityTaglibDTD)) {
			sb.append("");
			sb.append("");
			sb.append("http://liferay.com/tld/security");
			sb.append("");
			sb.append("");
			sb.append("/WEB-INF/tld/liferay-security.tld");
			sb.append("");
			sb.append("");
		}

		if (Validator.isNotNull(themeTaglibDTD)) {
			sb.append("");
			sb.append("http://liferay.com/tld/theme");
			sb.append("");
			sb.append("/WEB-INF/tld/liferay-theme.tld");
			sb.append("");
			sb.append("");
		}

		if (Validator.isNotNull(uiTaglibDTD)) {
			sb.append("");
			sb.append("http://liferay.com/tld/ui");
			sb.append("");
			sb.append("/WEB-INF/tld/liferay-ui.tld");
			sb.append("");
			sb.append("");
		}

		if (Validator.isNotNull(utilTaglibDTD)) {
			sb.append("");
			sb.append("http://liferay.com/tld/util");
			sb.append("");
			sb.append("/WEB-INF/tld/liferay-util.tld");
			sb.append("");
			sb.append("");
		}

		if (hasTaglib && (webXmlVersion > 2.3)) {
			sb.append("");
		}

		return sb.toString();
	}

	public String getIgnoreFiltersContent(File srcFile) throws Exception {
		boolean ignoreFiltersEnabled = true;

		Properties properties = _getPluginPackageProperties(srcFile);

		if (properties != null) {
			ignoreFiltersEnabled = GetterUtil.getBoolean(
				properties.getProperty("ignore-filters-enabled"), true);
		}

		if (ignoreFiltersEnabled) {
			return FileUtil.read(
				DeployUtil.getResourcePath(
					tempDirPaths, "ignore-filters-web.xml"));
		}

		return StringPool.BLANK;
	}

	public String getPluginType() {
		return _pluginType;
	}

	@Override
	public Map processPluginPackageProperties(
			File srcFile, String displayName, PluginPackage pluginPackage)
		throws Exception {

		if (pluginPackage == null) {
			return null;
		}

		Properties properties = _getPluginPackageProperties(srcFile);

		if ((properties == null) || properties.isEmpty()) {
			return null;
		}

		Map filterMap = _getPluginPackageXmlFilterMap(
			pluginPackage);

		if (filterMap == null) {
			return null;
		}

		copyDependencyXml(
			"liferay-plugin-package.xml", srcFile + "/WEB-INF", filterMap,
			true);

		return filterMap;
	}

	public void updateDeployDirectory(File srcFile) throws Exception {
	}

	protected String auiTaglibDTD;
	protected String portletExtTaglibDTD;
	protected String portletTaglibDTD;
	protected String securityTaglibDTD;
	protected final Set tempDirPaths = new HashSet<>();
	protected String themeTaglibDTD;
	protected String uiTaglibDTD;
	protected String utilTaglibDTD;

	private void _copyJars(File srcFile) throws Exception {
		for (String jar : _jars) {
			String jarFullName = DeployUtil.getResourcePath(tempDirPaths, jar);

			String jarName = jarFullName.substring(
				jarFullName.lastIndexOf("/") + 1);

			if (!FileUtil.exists(jarFullName)) {
				DeployUtil.getResourcePath(tempDirPaths, jarName);
			}

			FileUtil.copyFile(jarFullName, srcFile + "/WEB-INF/lib/" + jarName);
		}
	}

	private void _copyPortalDependencies(File srcFile) throws Exception {
		Properties properties = _getPluginPackageProperties(srcFile);

		if (properties == null) {
			return;
		}

		// jars

		String[] portalJars = StringUtil.split(
			properties.getProperty(
				"portal-dependency-jars",
				properties.getProperty("portal.dependency.jars")));

		for (String portalJar : portalJars) {
			portalJar = portalJar.trim();

			if (_log.isDebugEnabled()) {
				_log.debug("Copy portal JAR " + portalJar);
			}

			try {
				String portalJarPath =
					PropsValues.LIFERAY_SHIELDED_CONTAINER_LIB_PORTAL_DIR +
						portalJar;

				FileUtil.copyFile(
					portalJarPath, srcFile + "/WEB-INF/lib/" + portalJar);
			}
			catch (Exception exception) {
				_log.error("Unable to copy portal JAR " + portalJar, exception);
			}
		}

		// tlds

		String[] portalTlds = StringUtil.split(
			properties.getProperty(
				"portal-dependency-tlds",
				properties.getProperty("portal.dependency.tlds")));

		for (String portalTld : portalTlds) {
			portalTld = portalTld.trim();

			if (_log.isDebugEnabled()) {
				_log.debug("Copy portal TLD " + portalTld);
			}

			try {
				String portalTldPath = DeployUtil.getResourcePath(
					tempDirPaths, portalTld);

				FileUtil.copyFile(
					portalTldPath, srcFile + "/WEB-INF/tld/" + portalTld);
			}
			catch (Exception exception) {
				_log.error("Unable to copy portal TLD " + portalTld, exception);
			}
		}
	}

	private void _copyProperties(File srcFile, PluginPackage pluginPackage)
		throws Exception {

		File servicePropertiesFile = new File(
			srcFile.getAbsolutePath() + "/WEB-INF/classes/service.properties");

		if (!servicePropertiesFile.exists()) {
			return;
		}

		File portletPropertiesFile = new File(
			srcFile.getAbsolutePath() + "/WEB-INF/classes/portlet.properties");

		if (portletPropertiesFile.exists()) {
			return;
		}

		String pluginPackageName = null;

		if (pluginPackage != null) {
			pluginPackageName = pluginPackage.getName();
		}
		else {
			pluginPackageName = srcFile.getName();
		}

		FileUtil.write(
			portletPropertiesFile, "plugin.package.name=" + pluginPackageName);
	}

	private void _copyTlds(File srcFile) throws Exception {
		if (Validator.isNotNull(auiTaglibDTD)) {
			FileUtil.copyFile(
				auiTaglibDTD, srcFile + "/WEB-INF/tld/liferay-aui.tld");
		}

		if (Validator.isNotNull(portletTaglibDTD)) {
			FileUtil.copyFile(
				portletTaglibDTD, srcFile + "/WEB-INF/tld/liferay-portlet.tld");
			FileUtil.copyFile(
				DeployUtil.getResourcePath(
					tempDirPaths, "liferay-portlet_2_0.tld"),
				srcFile + "/WEB-INF/tld/liferay-portlet_2_0.tld");
		}

		if (Validator.isNotNull(portletExtTaglibDTD)) {
			FileUtil.copyFile(
				portletExtTaglibDTD,
				srcFile + "/WEB-INF/tld/liferay-portlet-ext.tld");
		}

		if (Validator.isNotNull(securityTaglibDTD)) {
			FileUtil.copyFile(
				securityTaglibDTD,
				srcFile + "/WEB-INF/tld/liferay-security.tld");
		}

		if (Validator.isNotNull(themeTaglibDTD)) {
			FileUtil.copyFile(
				themeTaglibDTD, srcFile + "/WEB-INF/tld/liferay-theme.tld");
		}

		if (Validator.isNotNull(uiTaglibDTD)) {
			FileUtil.copyFile(
				uiTaglibDTD, srcFile + "/WEB-INF/tld/liferay-ui.tld");
		}

		if (Validator.isNotNull(utilTaglibDTD)) {
			FileUtil.copyFile(
				utilTaglibDTD, srcFile + "/WEB-INF/tld/liferay-util.tld");
		}
	}

	private void _deployDirectory(
			File srcFile, File mergeDir, File deployDir, String displayName,
			PluginPackage pluginPackage)
		throws Exception {

		_rewriteFiles(srcFile);

		_mergeDirectory(mergeDir, srcFile);

		processPluginPackageProperties(srcFile, displayName, pluginPackage);

		_copyJars(srcFile);
		_copyProperties(srcFile, pluginPackage);
		_copyTlds(srcFile);
		copyXmls(srcFile, displayName, pluginPackage);
		_copyPortalDependencies(srcFile);

		File webXml = new File(srcFile + "/WEB-INF/web.xml");

		_updateWebXml(webXml, srcFile, displayName);

		if (deployDir == null) {
			return;
		}

		updateDeployDirectory(srcFile);

		FileUtil.copyDirectory(srcFile, deployDir);
	}

	private boolean _deployFile(
			File srcFile, File mergeDir, File deployDir, String displayName,
			PluginPackage pluginPackage)
		throws Exception {

		Path tempDirPath = Files.createTempDirectory(
			Paths.get(SystemProperties.get(SystemProperties.TMP_DIR)), null);

		File tempDir = tempDirPath.toFile();

		FileUtil.unzip(srcFile, tempDir);

		_deployDirectory(
			tempDir, mergeDir, deployDir, displayName, pluginPackage);

		FileUtil.deltree(tempDir);

		return true;
	}

	private String _getDisplayName(File srcFile) {
		String displayName = srcFile.getName();

		if (StringUtil.endsWith(displayName, ".war") ||
			StringUtil.endsWith(displayName, ".xml")) {

			displayName = displayName.substring(0, displayName.length() - 4);
		}

		return displayName;
	}

	private String _getInvokerFilterContent() {
		return StringBundler.concat(
			_getInvokerFilterContent("ASYNC"),
			_getInvokerFilterContent("ERROR"),
			_getInvokerFilterContent("FORWARD"),
			_getInvokerFilterContent("INCLUDE"),
			_getInvokerFilterContent("REQUEST"));
	}

	private String _getInvokerFilterContent(String dispatcher) {
		StringBundler sb = new StringBundler(24);

		sb.append("");
		sb.append("Invoker Filter - ");
		sb.append(dispatcher);
		sb.append("");
		sb.append("");
		sb.append(InvokerFilter.class.getName());
		sb.append("");
		sb.append("true");
		sb.append("");
		sb.append("dispatcher");
		sb.append("");
		sb.append(dispatcher);
		sb.append("");
		sb.append("");
		sb.append("");

		sb.append("");
		sb.append("Invoker Filter - ");
		sb.append(dispatcher);
		sb.append("");
		sb.append("/*");
		sb.append("");
		sb.append(dispatcher);
		sb.append("");
		sb.append("");

		return sb.toString();
	}

	private String _getPluginPackageLicensesXml(List licenses) {
		if (licenses.isEmpty()) {
			return StringPool.BLANK;
		}

		StringBundler sb = new StringBundler((5 * licenses.size()) + 2);

		for (int i = 0; i < licenses.size(); i++) {
			License license = licenses.get(i);

			if (i == 0) {
				sb.append("\r\n");
			}

			sb.append("\t\t");
			sb.append(license.getName());
			sb.append("\r\n");

			if ((i + 1) == licenses.size()) {
				sb.append("\t");
			}
		}

		return sb.toString();
	}

	private String _getPluginPackageLiferayVersionsXml(
		List liferayVersions) {

		if (liferayVersions.isEmpty()) {
			return StringPool.BLANK;
		}

		StringBundler sb = new StringBundler((liferayVersions.size() * 3) + 2);

		for (int i = 0; i < liferayVersions.size(); i++) {
			String liferayVersion = liferayVersions.get(i);

			if (i == 0) {
				sb.append("\r\n");
			}

			sb.append("\t\t");
			sb.append(liferayVersion);
			sb.append("\r\n");

			if ((i + 1) == liferayVersions.size()) {
				sb.append("\t");
			}
		}

		return sb.toString();
	}

	private Properties _getPluginPackageProperties(File srcFile)
		throws Exception {

		File propertiesFile = new File(
			srcFile + "/WEB-INF/liferay-plugin-package.properties");

		if (!propertiesFile.exists()) {
			return null;
		}

		String propertiesString = FileUtil.read(propertiesFile);

		return PropertiesUtil.load(propertiesString);
	}

	private String _getPluginPackageRequiredDeploymentContextsXml(
		List requiredDeploymentContexts) {

		if (requiredDeploymentContexts.isEmpty()) {
			return StringPool.BLANK;
		}

		StringBundler sb = new StringBundler(
			(requiredDeploymentContexts.size() * 3) + 2);

		for (int i = 0; i < requiredDeploymentContexts.size(); i++) {
			String requiredDeploymentContext = requiredDeploymentContexts.get(
				i);

			if (i == 0) {
				sb.append("\r\n");
			}

			sb.append("\t\t");
			sb.append(requiredDeploymentContext);
			sb.append("\r\n");

			if ((i + 1) == requiredDeploymentContexts.size()) {
				sb.append("\t");
			}
		}

		return sb.toString();
	}

	private String _getPluginPackageTagsXml(List tags) {
		if (tags.isEmpty()) {
			return StringPool.BLANK;
		}

		StringBundler sb = new StringBundler((tags.size() * 3) + 2);

		for (int i = 0; i < tags.size(); i++) {
			String tag = tags.get(i);

			if (i == 0) {
				sb.append("\r\n");
			}

			sb.append("\t\t");
			sb.append(tag);
			sb.append("\r\n");

			if ((i + 1) == tags.size()) {
				sb.append("\t");
			}
		}

		return sb.toString();
	}

	private Map _getPluginPackageXmlFilterMap(
		PluginPackage pluginPackage) {

		List pluginTypes = pluginPackage.getTypes();

		String pluginType = pluginTypes.get(0);

		if (!pluginType.equals(getPluginType())) {
			return null;
		}

		return HashMapBuilder.put(
			"author", _wrapCDATA(pluginPackage.getAuthor())
		).put(
			"change_log", _wrapCDATA(pluginPackage.getChangeLog())
		).put(
			"licenses",
			_getPluginPackageLicensesXml(pluginPackage.getLicenses())
		).put(
			"liferay_versions",
			_getPluginPackageLiferayVersionsXml(
				pluginPackage.getLiferayVersions())
		).put(
			"long_description", _wrapCDATA(pluginPackage.getLongDescription())
		).put(
			"module_artifact_id", pluginPackage.getArtifactId()
		).put(
			"module_group_id", pluginPackage.getGroupId()
		).put(
			"module_version", pluginPackage.getVersion()
		).put(
			"page_url", pluginPackage.getPageURL()
		).put(
			"plugin_name", _wrapCDATA(pluginPackage.getName())
		).put(
			"plugin_type", pluginType
		).put(
			"plugin_type_name",
			TextFormatter.format(pluginType, TextFormatter.J)
		).put(
			"recommended_deployment_context",
			pluginPackage.getRecommendedDeploymentContext()
		).put(
			"required_deployment_contexts",
			_getPluginPackageRequiredDeploymentContextsXml(
				pluginPackage.getRequiredDeploymentContexts())
		).put(
			"short_description", _wrapCDATA(pluginPackage.getShortDescription())
		).put(
			"tags", _getPluginPackageTagsXml(pluginPackage.getTags())
		).build();
	}

	private void _mergeDirectory(File mergeDir, File targetDir)
		throws Exception {

		if ((mergeDir == null) || !mergeDir.exists()) {
			return;
		}

		FileUtil.copyDirectory(mergeDir, targetDir);
	}

	private PluginPackage _readPluginPackage(File file) {
		if (!file.exists()) {
			return null;
		}

		InputStream inputStream = null;
		ZipFile zipFile = null;

		try {
			boolean parseProps = false;

			if (file.isDirectory()) {
				String path = file.getPath();

				File pluginPackageXmlFile = new File(
					StringBundler.concat(
						file.getParent(), "/merge/", file.getName(),
						"/WEB-INF/liferay-plugin-package.xml"));

				if (pluginPackageXmlFile.exists()) {
					inputStream = new FileInputStream(pluginPackageXmlFile);
				}
				else {
					pluginPackageXmlFile = new File(
						path + "/WEB-INF/liferay-plugin-package.xml");

					if (pluginPackageXmlFile.exists()) {
						inputStream = new FileInputStream(pluginPackageXmlFile);
					}
				}

				File pluginPackagePropertiesFile = new File(
					StringBundler.concat(
						file.getParent(), "/merge/", file.getName(),
						"/WEB-INF/liferay-plugin-package.properties"));

				if ((inputStream == null) &&
					pluginPackagePropertiesFile.exists()) {

					inputStream = new FileInputStream(
						pluginPackagePropertiesFile);

					parseProps = true;
				}
				else {
					pluginPackagePropertiesFile = new File(
						path + "/WEB-INF/liferay-plugin-package.properties");

					if ((inputStream == null) &&
						pluginPackagePropertiesFile.exists()) {

						inputStream = new FileInputStream(
							pluginPackagePropertiesFile);

						parseProps = true;
					}
				}
			}
			else {
				zipFile = new ZipFile(file);

				File pluginPackageXmlFile = new File(
					StringBundler.concat(
						file.getParent(), "/merge/", file.getName(),
						"/WEB-INF/liferay-plugin-package.xml"));

				if (pluginPackageXmlFile.exists()) {
					inputStream = new FileInputStream(pluginPackageXmlFile);
				}
				else {
					ZipEntry zipEntry = zipFile.getEntry(
						"WEB-INF/liferay-plugin-package.xml");

					if (zipEntry != null) {
						inputStream = zipFile.getInputStream(zipEntry);
					}
				}

				File pluginPackagePropertiesFile = new File(
					StringBundler.concat(
						file.getParent(), "/merge/", file.getName(),
						"/WEB-INF/liferay-plugin-package.properties"));

				if ((inputStream == null) &&
					pluginPackagePropertiesFile.exists()) {

					inputStream = new FileInputStream(
						pluginPackagePropertiesFile);

					parseProps = true;
				}
				else {
					ZipEntry zipEntry = zipFile.getEntry(
						"WEB-INF/liferay-plugin-package.properties");

					if ((inputStream == null) && (zipEntry != null)) {
						inputStream = zipFile.getInputStream(zipEntry);

						parseProps = true;
					}
				}
			}

			if (inputStream == null) {
				if (_log.isInfoEnabled()) {
					_log.info(
						StringBundler.concat(
							file.getPath(), " does not have a ",
							"WEB-INF/liferay-plugin-package.xml or ",
							"WEB-INF/liferay-plugin-package.properties"));
				}

				return null;
			}

			if (parseProps) {
				String propertiesString = StringUtil.read(inputStream);

				Properties properties = PropertiesUtil.load(propertiesString);

				return PluginPackageUtil.readPluginPackageProperties(
					_getDisplayName(file), properties);
			}

			String xml = StringUtil.read(inputStream);

			// LEP-1921

			int pos = xml.indexOf(CharPool.LESS_THAN);

			if (pos > 0) {
				xml = xml.substring(pos);
			}

			return PluginPackageUtil.readPluginPackageXml(xml);
		}
		catch (Exception exception) {
			_log.error(file.getPath() + ": " + exception.toString(), exception);
		}
		finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				}
				catch (IOException ioException) {
					if (_log.isDebugEnabled()) {
						_log.debug(ioException);
					}
				}
			}

			if (zipFile != null) {
				try {
					zipFile.close();
				}
				catch (IOException ioException) {
					if (_log.isDebugEnabled()) {
						_log.debug(ioException);
					}
				}
			}
		}

		return null;
	}

	private void _rewriteFiles(File srcDir) throws Exception {
		String[] fileNames = FileUtil.listFiles(srcDir + "/WEB-INF/");

		for (String fileName : fileNames) {
			String shortFileName = GetterUtil.getString(
				FileUtil.getShortFileName(fileName));

			// LEP-6415

			if (StringUtil.equalsIgnoreCase(shortFileName, "mule-config.xml")) {
				continue;
			}

			String ext = GetterUtil.getString(FileUtil.getExtension(fileName));

			if (!StringUtil.equalsIgnoreCase(ext, "xml")) {
				continue;
			}

			// Make sure to rewrite any XML files to include external entities
			// into same file. See LEP-3142.

			File file = new File(srcDir + "/WEB-INF/" + fileName);

			try {
				Document doc = UnsecureSAXReaderUtil.read(file);

				String content = doc.formattedString(StringPool.TAB, true);

				FileUtil.write(file, content);
			}
			catch (Exception exception) {
				if (_log.isWarnEnabled()) {
					_log.warn(
						StringBundler.concat(
							"Unable to format ", file, ": ",
							exception.getMessage()));
				}
			}
		}
	}

	private String _secureWebXml(
			String content, boolean hasCustomServletListener,
			boolean securityManagerEnabled)
		throws Exception {

		if (!hasCustomServletListener && !securityManagerEnabled) {
			return content;
		}

		Document document = UnsecureSAXReaderUtil.read(content);

		Element rootElement = document.getRootElement();

		List listenerClasses = new ArrayList<>();

		List listenerElements = rootElement.elements("listener");

		for (Element listenerElement : listenerElements) {
			String listenerClass = GetterUtil.getString(
				listenerElement.elementText("listener-class"));

			if (listenerClass.equals(PluginContextListener.class.getName()) ||
				listenerClass.equals(
					SecurePluginContextListener.class.getName())) {

				continue;
			}

			listenerClasses.add(listenerClass);

			listenerElement.detach();
		}

		Element contextParamElement = rootElement.addElement("context-param");

		Element paramNameElement = contextParamElement.addElement("param-name");

		paramNameElement.addText("portalListenerClasses");

		Element paramValueElement = contextParamElement.addElement(
			"param-value");

		paramValueElement.addText(StringUtil.merge(listenerClasses));

		if (!securityManagerEnabled) {
			return document.compactString();
		}

		List servletElements = rootElement.elements("servlet");

		for (Element servletElement : servletElements) {
			Element servletClassElement = servletElement.element(
				"servlet-class");

			String servletClass = GetterUtil.getString(
				servletClassElement.getText());

			if (servletClass.equals(PortalClassLoaderServlet.class.getName()) ||
				servletClass.equals(PortalDelegateServlet.class.getName()) ||
				servletClass.equals(PortletServlet.class.getName())) {

				continue;
			}

			servletClassElement.setText(SecureServlet.class.getName());

			Element initParamElement = servletElement.addElement("init-param");

			paramNameElement = initParamElement.addElement("param-name");

			paramNameElement.addText("servlet-class");

			paramNameElement = initParamElement.addElement("param-value");

			paramNameElement.addText(servletClass);
		}

		return document.compactString();
	}

	private String _updateLiferayWebXml(
			double webXmlVersion, File srcFile, String webXmlContent)
		throws Exception {

		boolean liferayWebXmlEnabled = true;

		Properties properties = _getPluginPackageProperties(srcFile);

		if (properties != null) {
			liferayWebXmlEnabled = GetterUtil.getBoolean(
				properties.getProperty("liferay-web-xml-enabled"), true);
		}

		webXmlContent = WebXMLBuilder.organizeWebXML(webXmlContent);

		int x = webXmlContent.indexOf("");
		int y = webXmlContent.lastIndexOf("");

		String webXmlFiltersContent = StringPool.BLANK;

		if ((x == -1) || (y == -1)) {
			x = webXmlContent.lastIndexOf("") + 15;

			y = x;
		}
		else {
			if (liferayWebXmlEnabled && (webXmlVersion > 2.3)) {
				webXmlFiltersContent = webXmlContent.substring(x, y + 17);

				y = y + 17;
			}
			else {
				x = y + 17;
				y = y + 17;
			}
		}

		if (webXmlVersion < 2.4) {
			return webXmlContent.substring(0, x) + webXmlContent.substring(y);
		}

		String liferayWebXmlContent = FileUtil.read(
			DeployUtil.getResourcePath(tempDirPaths, "web.xml"));

		int z = liferayWebXmlContent.indexOf("");

		liferayWebXmlContent =
			liferayWebXmlContent.substring(0, z) + webXmlFiltersContent +
				liferayWebXmlContent.substring(z);

		liferayWebXmlContent = WebXMLBuilder.organizeWebXML(
			liferayWebXmlContent);

		FileUtil.write(
			srcFile + "/WEB-INF/liferay-web.xml", liferayWebXmlContent);

		return webXmlContent.substring(0, x) + _getInvokerFilterContent() +
			webXmlContent.substring(y);
	}

	private void _updateWebXml(File webXml, File srcFile, String displayName)
		throws Exception {

		// Check version

		String content = FileUtil.read(webXml);

		content = WebXMLBuilder.organizeWebXML(content);

		int x = content.indexOf("");

		if (x != -1) {
			int y = content.indexOf("", x);

			y = content.indexOf(">", y) + 1;

			content = content.substring(0, x) + content.substring(y);
		}

		Document document = UnsecureSAXReaderUtil.read(content);

		Element rootElement = document.getRootElement();

		double webXmlVersion = GetterUtil.getDouble(
			rootElement.attributeValue("version"), 2.3);

		if (webXmlVersion <= 2.3) {
			throw new AutoDeployException(
				webXml.getName() +
					" must be updated to the Servlet 2.4 specification");
		}

		// Plugin context listener

		StringBundler sb = new StringBundler(5);

		sb.append("");
		sb.append("");

		boolean hasCustomServletListener = false;

		List listenerElements = rootElement.elements("listener");

		for (Element listenerElement : listenerElements) {
			String listenerClass = GetterUtil.getString(
				listenerElement.elementText("listener-class"));

			if (listenerClass.equals(PluginContextListener.class.getName()) ||
				listenerClass.equals(
					SerializableSessionAttributeListener.class.getName()) ||
				listenerClass.equals(
					SecurePluginContextListener.class.getName())) {

				continue;
			}

			hasCustomServletListener = true;

			break;
		}

		boolean securityManagerEnabled = false;

		Properties properties = _getPluginPackageProperties(srcFile);

		if (properties != null) {
			securityManagerEnabled = GetterUtil.getBoolean(
				properties.getProperty("security-manager-enabled"));
		}

		if (hasCustomServletListener || securityManagerEnabled) {
			sb.append(SecurePluginContextListener.class.getName());
		}
		else {
			sb.append(PluginContextListener.class.getName());
		}

		sb.append("");
		sb.append("");

		String pluginContextListenerContent = sb.toString();

		// Merge content

		String extraContent = getExtraContent(
			webXmlVersion, srcFile, displayName);

		int pos = content.indexOf("");

		if (pos == -1) {
			pos = content.indexOf("");
		}

		String newContent = StringBundler.concat(
			content.substring(0, pos), pluginContextListenerContent,
			extraContent, content.substring(pos));

		// Update liferay-web.xml

		newContent = _updateLiferayWebXml(webXmlVersion, srcFile, newContent);

		// Update web.xml

		newContent = _secureWebXml(
			newContent, hasCustomServletListener, securityManagerEnabled);

		newContent = WebXMLBuilder.organizeWebXML(newContent);

		FileUtil.write(webXml, newContent, true);

		if (_log.isDebugEnabled()) {
			_log.debug(
				StringBundler.concat(
					"Modifying Servlet ", webXmlVersion, " ", webXml));
		}
	}

	private String _wrapCDATA(String string) {
		return StringPool.CDATA_OPEN + string + StringPool.CDATA_CLOSE;
	}

	private static final Log _log = LogFactoryUtil.getLog(
		BaseAutoDeployer.class);

	private static final List _jars = Arrays.asList(
		"util-bridges.jar", "util-java.jar");

	private final String _pluginType;

	private static class JarFileNameFilter implements FilenameFilter {

		@Override
		public boolean accept(File file, String fileName) {
			if (fileName.startsWith(_prefix) && fileName.endsWith(".jar")) {
				return true;
			}

			return false;
		}

		private JarFileNameFilter(String prefix) {
			_prefix = prefix;
		}

		private final String _prefix;

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy