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

com.liferay.source.formatter.check.LanguageKeysCheck Maven / Gradle / Ivy

There is a newer version: 1.0.1457
Show newest version
/**
 * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
 * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
 */

package com.liferay.source.formatter.check;

import com.liferay.petra.string.CharPool;
import com.liferay.petra.string.StringBundler;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.TextFormatter;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.source.formatter.BNDSettings;
import com.liferay.source.formatter.SourceFormatterExcludes;
import com.liferay.source.formatter.check.util.SourceUtil;
import com.liferay.source.formatter.util.FileUtil;
import com.liferay.source.formatter.util.SourceFormatterUtil;

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Hugo Huijser
 */
public class LanguageKeysCheck extends BaseFileCheck {

	@Override
	public boolean isLiferaySourceCheck() {
		return true;
	}

	@Override
	protected String doProcess(
			String fileName, String absolutePath, String content)
		throws IOException {

		_checkLanguageKeys(fileName, absolutePath, content, getPatterns());

		return content;
	}

	protected List getPatterns() {
		return Arrays.asList(
			languageKeyPattern, _metaAnnotationDescriptionParameterPattern,
			_metaAnnotationNameParameterPattern);
	}

	protected final Pattern languageKeyPattern = Pattern.compile(
		"LanguageUtil.(?:get|format)\\([^;%]+|Liferay.Language.get\\('([^']+)");

	private void _checkLanguageKeys(
			String fileName, String absolutePath, String content,
			List patterns)
		throws IOException {

		if (fileName.endsWith(".vm")) {
			return;
		}

		Properties portalLanguageProperties = _getPortalLanguageProperties(
			absolutePath);

		if (portalLanguageProperties.isEmpty()) {
			return;
		}

		for (Pattern pattern : patterns) {
			_checkLanguageKeys(
				fileName, absolutePath, content, portalLanguageProperties,
				pattern);
		}
	}

	private void _checkLanguageKeys(
			String fileName, String absolutePath, String content,
			Properties portalLanguageProperties, Pattern pattern)
		throws IOException {

		Matcher matcher = pattern.matcher(content);

		Properties buildGradleLanguageProperties = null;
		Properties langModuleLanguageProperties = null;
		Properties moduleLanguageProperties = null;

		while (matcher.find()) {
			String[] languageKeys = _getLanguageKeys(matcher);

			for (String languageKey : languageKeys) {
				if (Validator.isNumber(languageKey) ||
					languageKey.endsWith(StringPool.CLOSE_CURLY_BRACE) ||
					languageKey.endsWith(StringPool.DASH) ||
					languageKey.endsWith(StringPool.OPEN_BRACKET) ||
					languageKey.endsWith(StringPool.PERIOD) ||
					languageKey.endsWith(StringPool.UNDERLINE) ||
					languageKey.startsWith(StringPool.DASH) ||
					languageKey.startsWith(StringPool.DOLLAR) ||
					languageKey.startsWith(StringPool.OPEN_BRACKET) ||
					languageKey.startsWith(StringPool.OPEN_CURLY_BRACE) ||
					languageKey.startsWith(StringPool.PERIOD) ||
					languageKey.startsWith(StringPool.UNDERLINE) ||
					portalLanguageProperties.containsKey(languageKey)) {

					continue;
				}

				if (moduleLanguageProperties == null) {
					moduleLanguageProperties = _getModuleLanguageProperties(
						fileName);
				}

				if (moduleLanguageProperties.containsKey(languageKey)) {
					continue;
				}

				if (buildGradleLanguageProperties == null) {
					buildGradleLanguageProperties =
						_getBuildGradleLanguageProperties(absolutePath);
				}

				if (buildGradleLanguageProperties.containsKey(languageKey)) {
					continue;
				}

				if (langModuleLanguageProperties == null) {
					langModuleLanguageProperties =
						_getLangModuleLanguageProperties(absolutePath);
				}

				if (langModuleLanguageProperties.containsKey(languageKey)) {
					continue;
				}

				BNDSettings bndSettings = getBNDSettings(fileName);

				if (bndSettings != null) {
					Properties bndLanguageProperties =
						bndSettings.getLanguageProperties();

					if ((bndLanguageProperties == null) ||
						bndLanguageProperties.containsKey(languageKey)) {

						continue;
					}
				}

				addMessage(
					fileName, "Missing language key \"" + languageKey + "\"");
			}
		}
	}

	private Properties _getBuildGradleLanguageProperties(String absolutePath)
		throws IOException {

		Properties properties = new Properties();

		String buildGradleContent = null;
		String buildGradleFileLocation = absolutePath;

		while (true) {
			int pos = buildGradleFileLocation.lastIndexOf(StringPool.SLASH);

			if (pos == -1) {
				return properties;
			}

			buildGradleFileLocation = buildGradleFileLocation.substring(
				0, pos + 1);

			File file = new File(buildGradleFileLocation + "build.gradle");

			if (file.exists()) {
				buildGradleContent = FileUtil.read(file);

				break;
			}

			buildGradleFileLocation = StringUtil.replaceLast(
				buildGradleFileLocation, CharPool.SLASH, StringPool.BLANK);
		}

		Matcher matcher = _applyLangMergerPluginPattern.matcher(
			buildGradleContent);

		if (!matcher.find()) {
			return properties;
		}

		String moduleLocation = StringUtil.replaceLast(
			buildGradleFileLocation, CharPool.SLASH, StringPool.BLANK);

		List moduleLangDirNames = _getModuleLangDirNames(
			moduleLocation, buildGradleContent);

		for (String moduleLangDirName : moduleLangDirNames) {
			String moduleLangLanguagePropertiesFileName =
				moduleLangDirName + "/Language.properties";

			File file = new File(moduleLangLanguagePropertiesFileName);

			if (!file.exists()) {
				continue;
			}

			InputStream inputStream = new FileInputStream(file);

			properties.load(inputStream);
		}

		return properties;
	}

	private Properties _getLangModuleLanguageProperties(String absolutePath)
		throws IOException {

		Properties properties = new Properties();

		if (!isModulesFile(absolutePath)) {
			return properties;
		}

		List langModulePaths = new ArrayList<>();

		String fileLocation = absolutePath;

		int x = fileLocation.length();

		while (true) {
			x = fileLocation.lastIndexOf(CharPool.SLASH, x - 1);

			if (x == -1) {
				break;
			}

			fileLocation = fileLocation.substring(0, x);

			if (fileLocation.endsWith("/modules")) {
				break;
			}

			File directory = new File(fileLocation);

			if (!directory.exists()) {
				continue;
			}

			for (File subdirectory : directory.listFiles(File::isDirectory)) {
				String subdirectoryPath = SourceUtil.getAbsolutePath(
					subdirectory);

				if (subdirectoryPath.endsWith("-lang")) {
					langModulePaths.add(subdirectoryPath);
				}
			}

			if (isSubrepository() &&
				FileUtil.exists(fileLocation + "/gradle.properties")) {

				break;
			}
		}

		for (String langModulePath : langModulePaths) {
			List languagePropertyFileNames =
				SourceFormatterUtil.scanForFileNames(
					langModulePath, new String[0],
					new String[] {"**/resources/content/Language.properties"},
					new SourceFormatterExcludes(), true);

			if (!languagePropertyFileNames.isEmpty()) {
				properties.load(
					new FileInputStream(
						new File(languagePropertyFileNames.get(0))));
			}
		}

		if (absolutePath.contains("/modules/dxp/apps/")) {
			properties.putAll(
				_getLangModuleLanguageProperties(
					StringUtil.replace(
						absolutePath, "/modules/dxp/apps/", "/modules/apps/")));
		}

		return properties;
	}

	private String[] _getLanguageKeys(Matcher matcher) {
		int groupCount = matcher.groupCount();

		if (groupCount == 1) {
			String languageKey = matcher.group(1);

			if (Validator.isNotNull(languageKey)) {
				return new String[] {languageKey};
			}
		}
		else if (groupCount == 2) {
			String languageKey = matcher.group(2);

			languageKey = TextFormatter.format(languageKey, TextFormatter.K);

			return new String[] {languageKey};
		}

		StringBundler sb = new StringBundler();

		String match = matcher.group();

		int count = 0;

		for (int i = 0; i < match.length(); i++) {
			char c = match.charAt(i);

			if (c == CharPool.CLOSE_PARENTHESIS) {
				if (count <= 1) {
					return new String[0];
				}

				count--;
			}
			else if (c == CharPool.OPEN_PARENTHESIS) {
				count++;
			}
			else if ((c == CharPool.QUOTE) && (count <= 1)) {
				while (i < match.length()) {
					i++;

					if (match.charAt(i) == CharPool.QUOTE) {
						String languageKey = sb.toString();

						if (match.startsWith("names")) {
							return StringUtil.split(languageKey);
						}

						return new String[] {languageKey};
					}

					sb.append(match.charAt(i));
				}
			}
		}

		return new String[0];
	}

	private List _getModuleLangDirNames(
		String moduleLocation, String buildGradleContent) {

		List moduleLangDirNames = new ArrayList<>();

		Matcher matcher = _mergeLangPattern.matcher(buildGradleContent);

		if (matcher.find()) {
			String[] sourceDirs = StringUtil.split(matcher.group(1));

			for (String sourceDir : sourceDirs) {
				sourceDir = StringUtil.trim(sourceDir);

				moduleLangDirNames.add(
					moduleLocation + StringPool.SLASH +
						sourceDir.substring(1, sourceDir.length() - 1));
			}

			return moduleLangDirNames;
		}

		int x = moduleLocation.lastIndexOf(StringPool.SLASH);

		String baseModuleName = moduleLocation.substring(0, x);

		int y = baseModuleName.lastIndexOf(StringPool.SLASH);

		baseModuleName = baseModuleName.substring(y + 1);

		String moduleLangDirName =
			moduleLocation.substring(0, x + 1) + baseModuleName +
				"-lang/src/main/resources/content";

		File moduleLangDir = new File(moduleLangDirName);

		if (!moduleLangDir.exists() &&
			moduleLangDirName.contains("/modules/ee/")) {

			moduleLangDirName = StringUtil.replaceFirst(
				moduleLangDirName, "/modules/ee/", "/modules/");
		}

		moduleLangDirNames.add(moduleLangDirName);

		if (moduleLangDirName.contains("/modules/dxp/apps/")) {
			moduleLangDirNames.add(
				StringUtil.replace(
					moduleLangDirName, "/modules/dxp/apps/", "/modules/apps/"));
		}

		String projectName = getProjectName();

		if (Validator.isNotNull(projectName)) {
			String projectLangDirName = StringBundler.concat(
				moduleLocation.substring(0, x + 1), projectName,
				"-lang/src/main/resources/content");

			File projectLangDir = new File(projectLangDirName);

			if (projectLangDir.exists()) {
				moduleLangDirNames.add(projectLangDirName);
			}
		}

		return moduleLangDirNames;
	}

	private Properties _getModuleLanguageProperties(String fileName) {
		Properties properties = new Properties();

		StringBundler sb = new StringBundler(3);

		int pos = fileName.indexOf("/docroot/");

		if (pos != -1) {
			sb.append(fileName.substring(0, pos + 9));
			sb.append("WEB-INF/src/");
		}
		else {
			pos = fileName.indexOf("src/");

			if (pos == -1) {
				return properties;
			}

			sb.append(fileName.substring(0, pos + 4));

			if (fileName.contains("src/main/")) {
				sb.append("main/resources/");
			}
		}

		sb.append("content/Language.properties");

		try {
			properties = new Properties();

			InputStream inputStream = new FileInputStream(sb.toString());

			properties.load(inputStream);

			return properties;
		}
		catch (Exception exception) {
			if (_log.isDebugEnabled()) {
				_log.debug(exception);
			}
		}

		return properties;
	}

	private synchronized Properties _getPortalLanguageProperties(
			String absolutePath)
		throws IOException {

		if (_portalLanguageProperties != null) {
			return _portalLanguageProperties;
		}

		_portalLanguageProperties = new Properties();

		String portalLanguagePropertiesFileName = getAttributeValue(
			_PORTAL_LANGUAGE_PROPERTIES_FILE_NAME, absolutePath);

		if (Validator.isNull(portalLanguagePropertiesFileName)) {
			return _portalLanguageProperties;
		}

		String propertiesContent = getPortalContent(
			portalLanguagePropertiesFileName, absolutePath);

		Properties properties = new Properties();

		properties.load(new StringReader(propertiesContent));

		_portalLanguageProperties.putAll(properties);

		return _portalLanguageProperties;
	}

	private static final String _PORTAL_LANGUAGE_PROPERTIES_FILE_NAME =
		"portalLanguagePropertiesFileName";

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

	private static final Pattern _applyLangMergerPluginPattern =
		Pattern.compile(
			"^apply[ \t]+plugin[ \t]*:[ \t]+\"com.liferay.lang.merger\"$",
			Pattern.MULTILINE);
	private static final Pattern _mergeLangPattern = Pattern.compile(
		"mergeLang \\{.*sourceDirs = \\[(.*?)\\]", Pattern.DOTALL);
	private static final Pattern _metaAnnotationDescriptionParameterPattern =
		Pattern.compile(
			"@Meta\\.(?:AD|OCD)\\([^\\{]*?description\\s*=\\s*\"(.+?)\"");
	private static final Pattern _metaAnnotationNameParameterPattern =
		Pattern.compile("@Meta\\.(?:AD|OCD)\\([^\\{]*?name\\s*=\\s*\"(.+?)\"");

	private Properties _portalLanguageProperties;

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy