/** * 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.upgrade.table.builder; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.ReleaseInfo; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.tools.ArgumentsUtil; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.PathMatcher; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author Brian Wing Shun Chan */ public class UpgradeTableBuilder { public static void main(String[] args) throws Exception { Map<String, String> arguments = ArgumentsUtil.parseArguments(args); String baseDirName = GetterUtil.getString( arguments.get("upgrade.base.dir"), UpgradeTableBuilderArgs.BASE_DIR_NAME); boolean osgiModule = GetterUtil.getBoolean( arguments.get("upgrade.osgi.module"), UpgradeTableBuilderArgs.OSGI_MODULE); String releaseInfoFileName = arguments.get("upgrade.release.info.file"); String upgradeTableDirName = arguments.get("upgrade.table.dir"); try { new UpgradeTableBuilder( baseDirName, osgiModule, releaseInfoFileName, upgradeTableDirName); } catch (Exception e) { ArgumentsUtil.processMainException(arguments, e); } } public UpgradeTableBuilder( String baseDirName, boolean osgiModule, String releaseInfoFileName, String upgradeTableDirName) throws Exception { _baseDirName = baseDirName; _osgiModule = osgiModule; if (_osgiModule) { _releaseInfoVersion = null; } else { _releaseInfoVersion = _getReleaseInfoVersion(releaseInfoFileName); } _upgradeTableDirName = upgradeTableDirName; FileSystem fileSystem = FileSystems.getDefault(); final PathMatcher pathMatcher = fileSystem.getPathMatcher( "glob:**/upgrade/v**/util/*Table.java"); Files.walkFileTree( Paths.get(_baseDirName), new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile( Path path, BasicFileAttributes basicFileAttributes) throws IOException { if (pathMatcher.matches(path)) { _buildUpgradeTable(path); } return FileVisitResult.CONTINUE; } }); } private void _buildUpgradeTable(Path path) throws IOException { String pathString = path.toString(); pathString = pathString.replace('\\', '/'); String upgradeFileVersion = pathString.replaceFirst( ".*/upgrade/v(.+)/util.*", "$1"); upgradeFileVersion = upgradeFileVersion.replace('_', '.'); if (upgradeFileVersion.contains("to")) { upgradeFileVersion = upgradeFileVersion.replaceFirst( ".+\\.to\\.(.+)", "$1"); } String fileName = String.valueOf(path.getFileName()); String tableName = fileName.substring(0, fileName.length() - 10); String upgradeFileName = tableName + "ModelImpl.java"; Path upgradeFilePath = Paths.get( _upgradeTableDirName, upgradeFileVersion, upgradeFileName); if (Files.notExists(upgradeFilePath)) { if (!upgradeFileVersion.equals(_getSchemaVersion())) { return; } upgradeFilePath = _getUpgradeFilePath(upgradeFileName); if (upgradeFilePath == null) { return; } } String content = _read(path); String packagePath = _getPackagePath(content); String className = fileName.substring(0, fileName.length() - 5); String upgradeFileContent = _read(upgradeFilePath); String author = _getAuthor(content); Path indexesFilePath = _getIndexesFilePath(upgradeFileVersion); String[] addIndexes = _getAddIndexes(indexesFilePath, tableName); content = _getContent( packagePath, className, upgradeFileContent, author, addIndexes); Files.write(path, content.getBytes(StandardCharsets.UTF_8)); } private List<Path> _findFiles( String baseDirName, String pattern, final int limit) throws IOException { final List<Path> paths = new ArrayList<>(); FileSystem fileSystem = FileSystems.getDefault(); final PathMatcher pathMatcher = fileSystem.getPathMatcher( "glob:" + pattern); Files.walkFileTree( Paths.get(baseDirName), new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile( Path filePath, BasicFileAttributes basicFileAttributes) { if (pathMatcher.matches(filePath)) { paths.add(filePath); if (paths.size() == limit) { return FileVisitResult.TERMINATE; } } return FileVisitResult.CONTINUE; } }); return paths; } private String[] _getAddIndexes(Path indexesFilePath, String tableName) throws IOException { List<String> addIndexes = new ArrayList<>(); try (BufferedReader bufferedReader = Files.newBufferedReader( indexesFilePath, StandardCharsets.UTF_8)) { String line = null; while ((line = bufferedReader.readLine()) != null) { if (line.contains(" on " + tableName + " (") || line.contains(" on " + tableName + "_ (")) { String sql = line.trim(); if (sql.endsWith(";")) { sql = sql.substring(0, sql.length() - 1); } addIndexes.add(sql); } } } return addIndexes.toArray(new String[addIndexes.size()]); } private String _getAuthor(String content) { int x = content.indexOf("* @author "); if (x != -1) { int y = content.indexOf("*", x + 1); if (y != -1) { return content.substring(x + 10, y).trim(); } } return _AUTHOR; } private String _getContent( String packagePath, String className, String content, String author, String[] addIndexes) throws IOException { int x = content.indexOf("public static final String TABLE_NAME ="); if (x == -1) { x = content.indexOf("public static String TABLE_NAME ="); } int y = content.indexOf("public static final String TABLE_SQL_DROP ="); if (y == -1) { y = content.indexOf("public static String TABLE_SQL_DROP ="); } y = content.indexOf(";", y); content = content.substring(x, y + 1); content = content.replace("\t", ""); content = content.replace("{ \"", "{\""); content = content.replace("new Integer(Types.", "Types."); content = content.replace(") }", "}"); content = content.replace(" }", "}"); while (content.contains("\n\n")) { content = content.replace("\n\n", "\n"); } StringBuilder sb = new StringBuilder(); sb.append(_getCopyright()); sb.append("\n\npackage "); sb.append(packagePath); sb.append(";\n\n"); sb.append("import java.sql.Types;\n\n"); if (content.contains("TABLE_COLUMNS_MAP")) { sb.append("import java.util.HashMap;\n"); sb.append("import java.util.Map;\n\n"); } sb.append("/**\n"); sb.append(" * @author\t "); sb.append(author); sb.append("\n"); sb.append(" * @generated\n"); sb.append(" */\n"); sb.append("public class "); sb.append(className); sb.append(" {\n\n"); String[] lines = content.split("\\n"); for (String line : lines) { if (line.startsWith("public static") || line.startsWith("};")) { sb.append("\t"); } else if (line.startsWith("{\"")) { sb.append("\t\t"); } sb.append(line); sb.append("\n"); if (line.endsWith(";")) { sb.append("\n"); } } sb.append("\tpublic static final String[] TABLE_SQL_ADD_INDEXES = {\n"); for (int i = 0; i < addIndexes.length; i++) { String addIndex = addIndexes[i]; sb.append("\t\t\""); sb.append(addIndex); sb.append("\""); if ((i + 1) < addIndexes.length) { sb.append(","); } sb.append("\n"); } sb.append("\t};\n\n"); sb.append("}"); return sb.toString(); } private String _getCopyright() throws IOException { Path path = Paths.get(_baseDirName); path = path.toAbsolutePath(); while (path != null) { Path copyrightFilePath = path.resolve("copyright.txt"); if (Files.exists(copyrightFilePath)) { return _read(copyrightFilePath); } path = path.getParent(); } return null; } private Path _getIndexesFilePath(String upgradeFileVersion) throws IOException { Path indexesFilePath = null; if (_osgiModule) { List<Path> paths = _findFiles( _baseDirName, "**/sql/indexes.sql", 1); if (!paths.isEmpty()) { indexesFilePath = paths.get(0); } } else { indexesFilePath = Paths.get( _upgradeTableDirName, upgradeFileVersion, "indexes.sql"); if (Files.notExists(indexesFilePath)) { indexesFilePath = Paths.get(_baseDirName, "../sql/indexes.sql"); } } return indexesFilePath; } private String _getPackagePath(String content) { Matcher matcher = _packagePathPattern.matcher(content); if (matcher.find()) { return matcher.group(1); } return null; } private String _getReleaseInfoVersion(String fileName) throws IOException { if (Validator.isNull(fileName)) { return ReleaseInfo.getVersion(); } String releaseInfo = _read(Paths.get(fileName)); Matcher matcher = _releaseInfoVersionPattern.matcher(releaseInfo); if (!matcher.find()) { throw new IOException( "Unable to get release info version from " + fileName); } return matcher.group(1); } private String _getSchemaVersion() throws IOException { if (!_osgiModule) { return _releaseInfoVersion; } Properties properties = new Properties(); Path path = Paths.get(_baseDirName, "bnd.bnd"); try (InputStream inputStream = Files.newInputStream(path)) { properties.load(inputStream); } return properties.getProperty("Liferay-Require-SchemaVersion"); } private Path _getUpgradeFilePath(String fileName) throws IOException { List<Path> paths = _findFiles(_baseDirName, "**/" + fileName, 1); if (paths.isEmpty()) { return null; } return paths.get(0); } private String _read(Path path) throws IOException { String s = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); return s.replace("\r\n", "\n"); } private static final String _AUTHOR = "Brian Wing Shun Chan"; private static final Pattern _packagePathPattern = Pattern.compile( "package (.+?);"); private static final Pattern _releaseInfoVersionPattern = Pattern.compile( "private static final String _VERSION = \"(.+)\";"); private final String _baseDirName; private final boolean _osgiModule; private final String _releaseInfoVersion; private final String _upgradeTableDirName; }