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

com.liferay.source.formatter.check.util.JSPSourceUtil Maven / Gradle / Ivy

There is a newer version: 1.0.1407
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.util;

import com.liferay.petra.string.CharPool;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.source.formatter.util.FileUtil;

import java.io.File;
import java.io.IOException;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Hugo Huijser
 */
public class JSPSourceUtil {

	public static List addIncludedAndReferencedFileNames(
		List fileNames, Set checkedFileNames,
		Map contentsMap, String referencedFileNameRegex) {

		Set includedAndReferencedFileNames = new HashSet<>();

		for (String fileName : fileNames) {
			if (!checkedFileNames.add(fileName)) {
				continue;
			}

			fileName = StringUtil.replace(
				fileName, CharPool.BACK_SLASH, CharPool.SLASH);

			includedAndReferencedFileNames.addAll(
				getJSPIncludeFileNames(fileName, fileNames, contentsMap, true));
			includedAndReferencedFileNames.addAll(
				getJSPReferenceFileNames(
					fileName, fileNames, contentsMap, referencedFileNameRegex));
		}

		if (includedAndReferencedFileNames.isEmpty()) {
			return fileNames;
		}

		for (String fileName : includedAndReferencedFileNames) {
			fileName = StringUtil.replace(
				fileName, CharPool.SLASH, CharPool.BACK_SLASH);

			if (!fileNames.contains(fileName)) {
				fileNames.add(fileName);
			}
		}

		return addIncludedAndReferencedFileNames(
			fileNames, checkedFileNames, contentsMap, referencedFileNameRegex);
	}

	public static String buildFullPathIncludeFileName(
		String fileName, String includeFileName,
		Map contentsMap) {

		String path = fileName;

		while (true) {
			int y = path.lastIndexOf(CharPool.SLASH);

			if (y == -1) {
				return StringPool.BLANK;
			}

			String fullPathIncludeFileName =
				path.substring(0, y) + includeFileName;

			if (contentsMap.containsKey(fullPathIncludeFileName) &&
				!fullPathIncludeFileName.equals(fileName)) {

				return fullPathIncludeFileName;
			}

			path = path.substring(0, y);
		}
	}

	public static String compressImportsOrTaglibs(
		String fileName, String content, String attributePrefix) {

		int x = content.indexOf(attributePrefix);

		int y = content.lastIndexOf(attributePrefix);

		y = content.indexOf("%>", y);

		if ((x == -1) || (y == -1) || (x > y)) {
			return content;
		}

		String importsOrTaglibs = content.substring(x, y);

		importsOrTaglibs = StringUtil.replace(
			importsOrTaglibs, new String[] {"%>\r\n<%@ ", "%>\n<%@ "},
			new String[] {"%><%@\r\n", "%><%@\n"});

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

	public static Map getContentsMap(List fileNames)
		throws IOException {

		Map contentsMap = new ConcurrentHashMap<>();

		if (ListUtil.isEmpty(fileNames)) {
			return contentsMap;
		}

		for (String fileName : fileNames) {
			fileName = StringUtil.replace(
				fileName, CharPool.BACK_SLASH, CharPool.SLASH);

			File file = new File(fileName);

			String content = FileUtil.read(file);

			if (content == null) {
				continue;
			}

			Matcher matcher = _includeFilePattern.matcher(content);

			while (matcher.find()) {
				content = StringUtil.replaceFirst(
					content, matcher.group(),
					"@ include file=\"" + matcher.group(1) + "\"",
					matcher.start());
			}

			contentsMap.put(fileName, content);
		}

		return contentsMap;
	}

	public static Set getJSPIncludeFileNames(
		String fileName, Collection fileNames,
		Map contentsMap, boolean forceIncludeAllFiles) {

		Set includeFileNames = new HashSet<>();

		String content = contentsMap.get(fileName);

		if (Validator.isNull(content)) {
			return includeFileNames;
		}

		for (int x = -1;;) {
			x = content.indexOf("<%@ include file=", x + 1);

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

			if (!forceIncludeAllFiles) {
				Matcher matcher = _javaCodeTagPattern.matcher(content);

				if (matcher.find() && (matcher.start() == x)) {
					continue;
				}
			}

			x = content.indexOf(CharPool.QUOTE, x);

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

			int y = content.indexOf(CharPool.QUOTE, x + 1);

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

			String includeFileName = content.substring(x + 1, y);

			if (!includeFileName.startsWith(StringPool.SLASH)) {
				includeFileName = StringPool.SLASH + includeFileName;
			}

			Matcher matcher = _jspIncludeFilePattern.matcher(includeFileName);

			if (!matcher.find()) {
				throw new RuntimeException(
					"Invalid include " + includeFileName);
			}

			String extension = matcher.group(1);

			if (extension.equals("svg")) {
				continue;
			}

			includeFileName = buildFullPathIncludeFileName(
				fileName, includeFileName, contentsMap);

			if ((includeFileName.endsWith("jsp") ||
				 includeFileName.endsWith("jspf") ||
				 includeFileName.endsWith("tag")) &&
				!fileNames.contains(includeFileName)) {

				includeFileNames.add(includeFileName);
			}
		}

		return includeFileNames;
	}

	public static Set getJSPReferenceFileNames(
		String fileName, Collection fileNames,
		Map contentsMap, String referencedFileNameRegex) {

		Set referenceFileNames = new HashSet<>();

		if (!fileName.matches(referencedFileNameRegex)) {
			return referenceFileNames;
		}

		for (Map.Entry entry : contentsMap.entrySet()) {
			String referenceFileName = entry.getKey();

			if (fileNames.contains(referenceFileName)) {
				continue;
			}

			String sharedPath = fileName.substring(
				0, StringUtil.startsWithWeight(referenceFileName, fileName));

			if (Validator.isNull(sharedPath) ||
				!sharedPath.contains(StringPool.SLASH)) {

				continue;
			}

			if (!sharedPath.endsWith(StringPool.SLASH)) {
				sharedPath = sharedPath.substring(
					0, sharedPath.lastIndexOf(CharPool.SLASH) + 1);
			}

			String content = null;

			for (int x = -1;;) {
				x = sharedPath.indexOf(CharPool.SLASH, x + 1);

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

				if (content == null) {
					content = entry.getValue();
				}

				if (content.contains(
						"<%@ include file=\"" + fileName.substring(x)) ||
					content.contains(
						"<%@ include file=\"" + fileName.substring(x + 1))) {

					referenceFileNames.add(referenceFileName);

					break;
				}
			}
		}

		return referenceFileNames;
	}

	public static boolean isJavaSource(String content, int pos) {
		return isJavaSource(content, pos, false);
	}

	public static boolean isJavaSource(
		String content, int pos, boolean checkInsideTags) {

		String s = content.substring(pos);

		Matcher matcher = _javaEndTagPattern.matcher(s);

		if (matcher.find()) {
			s = s.substring(0, matcher.start());

			matcher = _javaStartTagPattern.matcher(s);

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

		if (!checkInsideTags) {
			return false;
		}

		int x = content.indexOf(CharPool.NEW_LINE, pos);

		if (x == -1) {
			return false;
		}

		s = content.substring(pos, x);

		int y = s.indexOf("%>");

		if (y == -1) {
			return false;
		}

		s = s.substring(0, y);

		if (!s.contains("<%")) {
			return true;
		}

		return false;
	}

	public static boolean isJSSource(String content, int pos) {
		if (isJavaSource(content, pos)) {
			return false;
		}

		String s = content.substring(pos);

		Matcher matcher = _auiScriptEndTagPattern.matcher(s);

		if (matcher.find()) {
			s = s.substring(0, matcher.start());

			matcher = _auiScriptStartTagPattern.matcher(s);

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

		s = content.substring(pos);

		matcher = _scriptEndTagPattern.matcher(s);

		if (matcher.find()) {
			s = s.substring(0, matcher.start());

			matcher = _scriptStartTagPattern.matcher(s);

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

		return false;
	}

	private static final Pattern _auiScriptEndTagPattern = Pattern.compile(
		"[\n\t](\n|\\Z)");
	private static final Pattern _auiScriptStartTagPattern = Pattern.compile(
		"[\n\t]]");
	private static final Pattern _includeFilePattern = Pattern.compile(
		"\\s*@\\s*include\\s*file=['\"](.*)['\"]");
	private static final Pattern _javaCodeTagPattern = Pattern.compile(
		"<%\\s*[@=\n]");
	private static final Pattern _javaEndTagPattern = Pattern.compile(
		"[\n\t]%>(\n|\\Z)");
	private static final Pattern _javaStartTagPattern = Pattern.compile(
		"[\n\t]<%\\!?(\n|\\Z)");
	private static final Pattern _jspIncludeFilePattern = Pattern.compile(
		"/.*\\.(jsp[f]?|svg|tag)");
	private static final Pattern _scriptEndTagPattern = Pattern.compile(
		"[\n\t](\n|\\Z)");
	private static final Pattern _scriptStartTagPattern = Pattern.compile(
		"[\n\t]]");

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy