/** * 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.gradle.plugins.theme.builder; import com.liferay.gradle.plugins.css.builder.BuildCSSTask; import com.liferay.gradle.plugins.css.builder.CSSBuilderPlugin; import com.liferay.gradle.util.FileUtil; import com.liferay.gradle.util.GradleUtil; import com.liferay.gradle.util.Validator; import java.io.File; import java.io.IOException; import java.util.concurrent.Callable; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.gradle.api.Action; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.DependencySet; import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileCopyDetails; import org.gradle.api.file.FileTreeElement; import org.gradle.api.plugins.BasePlugin; import org.gradle.api.plugins.WarPlugin; import org.gradle.api.plugins.WarPluginConvention; import org.gradle.api.specs.Spec; import org.gradle.api.tasks.TaskContainer; import org.gradle.api.tasks.bundling.War; /** * @author Andrea Di Giorgi */ public class ThemeBuilderPlugin implements Plugin<Project> { public static final String BUILD_THEME_TASK_NAME = "buildTheme"; public static final String PARENT_THEMES_CONFIGURATION_NAME = "parentThemes"; public static final String THEME_BUILDER_CONFIGURATION_NAME = "themeBuilder"; @Override public void apply(Project project) { GradleUtil.applyPlugin(project, CSSBuilderPlugin.class); GradleUtil.applyPlugin(project, WarPlugin.class); BuildCSSTask buildCSSTask = (BuildCSSTask)GradleUtil.getTask( project, CSSBuilderPlugin.BUILD_CSS_TASK_NAME); War war = (War)GradleUtil.getTask(project, WarPlugin.WAR_TASK_NAME); WarPluginConvention warPluginConvention = GradleUtil.getConvention( project, WarPluginConvention.class); Configuration parentThemesConfiguration = _addConfigurationParentThemes( project); Configuration themeBuilderConfiguration = _addConfigurationThemeBuilder( project); BuildThemeTask buildThemeTask = _addTaskBuildTheme( project, parentThemesConfiguration, warPluginConvention); _configureTaskBuildCSS(buildCSSTask, buildThemeTask); _configureTaskWar(war, buildCSSTask, buildThemeTask); _configureTasksBuildTheme(project, themeBuilderConfiguration); } private Configuration _addConfigurationParentThemes(final Project project) { Configuration configuration = GradleUtil.addConfiguration( project, PARENT_THEMES_CONFIGURATION_NAME); configuration.defaultDependencies( new Action<DependencySet>() { @Override public void execute(DependencySet dependencySet) { _addDependenciesParentThemes(project); } }); configuration.setDescription( "Configures the parent theme JARs required to build theme files."); configuration.setTransitive(false); configuration.setVisible(false); return configuration; } private Configuration _addConfigurationThemeBuilder(final Project project) { Configuration configuration = GradleUtil.addConfiguration( project, THEME_BUILDER_CONFIGURATION_NAME); configuration.defaultDependencies( new Action<DependencySet>() { @Override public void execute(DependencySet dependencySet) { _addDependenciesThemeBuilder(project); } }); configuration.setDescription( "Configures Liferay Portal Tools Theme Builder for this project."); configuration.setVisible(false); return configuration; } private void _addDependenciesParentThemes(Project project) { GradleUtil.addDependency( project, PARENT_THEMES_CONFIGURATION_NAME, "com.liferay", "com.liferay.frontend.theme.styled", "latest.release"); GradleUtil.addDependency( project, PARENT_THEMES_CONFIGURATION_NAME, "com.liferay", "com.liferay.frontend.theme.unstyled", "latest.release"); GradleUtil.addDependency( project, PARENT_THEMES_CONFIGURATION_NAME, "com.liferay.plugins", "classic-theme", "latest.release"); } private void _addDependenciesThemeBuilder(Project project) { GradleUtil.addDependency( project, THEME_BUILDER_CONFIGURATION_NAME, "com.liferay", "com.liferay.portal.tools.theme.builder", "latest.release"); } private BuildThemeTask _addTaskBuildTheme( Project project, final Iterable<File> parentThemeFiles, final WarPluginConvention warPluginConvention) { final BuildThemeTask buildThemeTask = GradleUtil.addTask( project, BUILD_THEME_TASK_NAME, BuildThemeTask.class); buildThemeTask.setDescription("Builds the theme files."); buildThemeTask.setDiffsDir( new Callable<File>() { @Override public File call() throws Exception { return warPluginConvention.getWebAppDir(); } }); buildThemeTask.setGroup(BasePlugin.BUILD_GROUP); buildThemeTask.setOutputDir( new Callable<File>() { @Override public File call() throws Exception { Project project = buildThemeTask.getProject(); return new File( project.getBuildDir(), buildThemeTask.getName()); } }); buildThemeTask.setParentFile( new Callable<File>() { @Override public File call() throws Exception { String parentName = buildThemeTask.getParentName(); if (Validator.isNull(parentName)) { return null; } return _getThemeFile(parentThemeFiles, parentName); } }); buildThemeTask.setParentName("_styled"); buildThemeTask.setTemplateExtension("ftl"); buildThemeTask.setThemeName(project.getName()); buildThemeTask.setUnstyledFile( new Callable<File>() { @Override public File call() throws Exception { return _getThemeFile(parentThemeFiles, "_unstyled"); } }); return buildThemeTask; } private void _configureTaskBuildCSS( BuildCSSTask buildCSSTask, final BuildThemeTask buildThemeTask) { buildCSSTask.dependsOn(buildThemeTask); buildCSSTask.setDocrootDir( new Callable<File>() { @Override public File call() throws Exception { return buildThemeTask.getOutputDir(); } }); } private void _configureTasksBuildTheme( Project project, final FileCollection classpath) { TaskContainer taskContainer = project.getTasks(); taskContainer.withType( BuildThemeTask.class, new Action<BuildThemeTask>() { @Override public void execute(BuildThemeTask buildThemeTask) { buildThemeTask.setClasspath(classpath); } }); } private void _configureTaskWar( War war, final BuildCSSTask buildCSSTask, final BuildThemeTask buildThemeTask) { war.dependsOn(buildThemeTask); war.eachFile( new Action<FileCopyDetails>() { @Override public void execute(FileCopyDetails fileCopyDetails) { String dirName = buildCSSTask.getOutputDirName(); dirName = dirName.replace('\\', '/'); if (dirName.charAt(0) != '/') { dirName = '/' + dirName; } if (dirName.charAt(dirName.length() - 1) != '/') { dirName = dirName + '/'; } String path = fileCopyDetails.getPath(); fileCopyDetails.setPath(path.replace(dirName, "/")); } }); war.exclude( new Spec<FileTreeElement>() { @Override public boolean isSatisfiedBy(FileTreeElement fileTreeElement) { File diffsDir = buildThemeTask.getDiffsDir(); if ((diffsDir != null) && FileUtil.isChild(fileTreeElement.getFile(), diffsDir)) { return true; } return false; } }); war.exclude("**/*.scss"); war.from( new Callable<File>() { @Override public File call() throws Exception { return buildThemeTask.getOutputDir(); } }); war.setIncludeEmptyDirs(false); } private File _getThemeFile(Iterable<File> files, String name) throws IOException { for (File file : files) { String fileName = file.getName(); if (fileName.endsWith(".war")) { if (fileName.startsWith(name + "-theme-")) { return file; } } else { try (ZipFile zipFile = new ZipFile(file)) { ZipEntry zipEntry = zipFile.getEntry( "META-INF/resources/" + name + "/"); if (zipEntry != null) { return file; } } } } return null; } }