blob: e5951134e52333bfdf0850a05f92d4d24989a21b [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.gradle.service.project.wizard;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys;
import com.intellij.openapi.externalSystem.service.project.wizard.AbstractExternalModuleBuilder;
import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.*;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.SdkTypeId;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.service.settings.GradleProjectSettingsControl;
import org.jetbrains.plugins.gradle.settings.DistributionType;
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.util.Map;
/**
* @author Denis Zhdanov
* @since 6/26/13 11:10 AM
*/
public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradleProjectSettings> {
private static final Logger LOG = Logger.getInstance(GradleModuleBuilder.class);
private static final String TEMPLATE_GRADLE_SETTINGS = "Gradle Settings.gradle";
private static final String TEMPLATE_GRADLE_SETTINGS_MERGE = "Gradle Settings merge.gradle";
private static final String TEMPLATE_GRADLE_BUILD_WITH_WRAPPER = "Gradle Build Script with wrapper.gradle";
private static final String DEFAULT_TEMPLATE_GRADLE_BUILD = "Gradle Build Script.gradle";
private static final String TEMPLATE_ATTRIBUTE_PROJECT_NAME = "PROJECT_NAME";
private static final String TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME = "MODULE_DIR_NAME";
private static final String TEMPLATE_ATTRIBUTE_MODULE_NAME = "MODULE_NAME";
private @NotNull WizardContext myWizardContext;
public GradleModuleBuilder() {
super(GradleConstants.SYSTEM_ID, new GradleProjectSettings());
}
@Override
public void setupRootModel(final ModifiableRootModel modifiableRootModel) throws ConfigurationException {
String contentEntryPath = getContentEntryPath();
if (StringUtil.isEmpty(contentEntryPath)) {
return;
}
File contentRootDir = new File(contentEntryPath);
FileUtilRt.createDirectory(contentRootDir);
LocalFileSystem fileSystem = LocalFileSystem.getInstance();
VirtualFile modelContentRootDir = fileSystem.refreshAndFindFileByIoFile(contentRootDir);
if (modelContentRootDir == null) {
return;
}
modifiableRootModel.addContentEntry(modelContentRootDir);
// todo this should be moved to generic ModuleBuilder
if (myJdk != null){
modifiableRootModel.setSdk(myJdk);
} else {
modifiableRootModel.inheritSdk();
}
final Project project = modifiableRootModel.getProject();
setupGradleBuildFile(modelContentRootDir);
setupGradleSettingsFile(modelContentRootDir, modifiableRootModel);
if (myWizardContext.isCreatingNewProject()) {
String externalProjectPath = FileUtil.toCanonicalPath(project.getBasePath());
getExternalProjectSettings().setExternalProjectPath(externalProjectPath);
AbstractExternalSystemSettings settings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID);
project.putUserData(ExternalSystemDataKeys.NEWLY_CREATED_PROJECT, Boolean.TRUE);
//noinspection unchecked
settings.linkProject(getExternalProjectSettings());
}
else {
FileDocumentManager.getInstance().saveAllDocuments();
ExternalSystemUtil.refreshProjects(project, GradleConstants.SYSTEM_ID, false);
}
}
@Override
public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull ModulesProvider modulesProvider) {
myWizardContext = wizardContext;
return super.createWizardSteps(wizardContext, modulesProvider);
}
@Nullable
@Override
public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) {
if (!myWizardContext.isCreatingNewProject()) return new ModuleWizardStep() {
@Override
public JComponent getComponent() {
return new JPanel();
}
@Override
public void updateDataModel() {
}
};
final GradleProjectSettingsControl settingsControl = new GradleProjectSettingsControl(getExternalProjectSettings());
return new ExternalModuleSettingsStep<GradleProjectSettings>(this, settingsControl);
}
@Override
public boolean isSuitableSdkType(SdkTypeId sdk) {
return sdk instanceof JavaSdkType;
}
@Override
public String getParentGroup() {
return JavaModuleType.BUILD_TOOLS_GROUP;
}
@Override
public int getWeight() {
return JavaModuleBuilder.BUILD_SYSTEM_WEIGHT;
}
@Override
public ModuleType getModuleType() {
return StdModuleTypes.JAVA;
}
@Nullable
private VirtualFile setupGradleBuildFile(@NotNull VirtualFile modelContentRootDir) throws ConfigurationException {
final VirtualFile file = getExternalProjectConfigFile(modelContentRootDir.getPath(), GradleConstants.DEFAULT_SCRIPT_NAME);
final String templateName = getExternalProjectSettings().getDistributionType() == DistributionType.WRAPPED
? TEMPLATE_GRADLE_BUILD_WITH_WRAPPER
: DEFAULT_TEMPLATE_GRADLE_BUILD;
Map attributes = ContainerUtil.newHashMap();
if (file != null) {
saveFile(file, templateName, attributes);
}
return file;
}
@Nullable
private VirtualFile setupGradleSettingsFile(@NotNull VirtualFile modelContentRootDir, @NotNull ModifiableRootModel model)
throws ConfigurationException {
VirtualFile file = null;
if (myWizardContext.isCreatingNewProject()) {
final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, model.getProject().getBaseDir(), '/');
file = getExternalProjectConfigFile(model.getProject().getBasePath(), GradleConstants.SETTINGS_FILE_NAME);
if (file == null) return null;
Map<String, String> attributes = ContainerUtil.newHashMap();
final String projectName = model.getProject().getName();
attributes.put(TEMPLATE_ATTRIBUTE_PROJECT_NAME, projectName);
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME, moduleDirName);
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, model.getModule().getName());
saveFile(file, TEMPLATE_GRADLE_SETTINGS, attributes);
}
else {
Map<String, Module> moduleMap = ContainerUtil.newHashMap();
for (Module module : ModuleManager.getInstance(model.getProject()).getModules()) {
for (ContentEntry contentEntry : model.getContentEntries()) {
if (contentEntry.getFile() != null) {
moduleMap.put(contentEntry.getFile().getPath(), module);
}
}
}
VirtualFile virtualFile = modelContentRootDir;
Module module = null;
while (virtualFile != null && module == null) {
module = moduleMap.get(virtualFile.getPath());
virtualFile = virtualFile.getParent();
}
if (module != null) {
String rootProjectPath = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
if (!StringUtil.isEmpty(rootProjectPath)) {
VirtualFile rootProjectFile = VfsUtil.findFileByIoFile(new File(rootProjectPath), true);
if (rootProjectFile == null) return null;
final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, rootProjectFile, '/');
file = getExternalProjectConfigFile(rootProjectPath, GradleConstants.SETTINGS_FILE_NAME);
if (file == null) return null;
Map<String, String> attributes = ContainerUtil.newHashMap();
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME, moduleDirName);
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, model.getModule().getName());
appendToFile(file, TEMPLATE_GRADLE_SETTINGS_MERGE, attributes);
}
}
}
return file;
}
private static void saveFile(@NotNull VirtualFile file, @NotNull String templateName, @Nullable Map templateAttributes)
throws ConfigurationException {
FileTemplateManager manager = FileTemplateManager.getInstance();
FileTemplate template = manager.getInternalTemplate(templateName);
try {
VfsUtil.saveText(file, templateAttributes != null ? template.getText(templateAttributes) : template.getText());
}
catch (IOException e) {
LOG.warn(String.format("Unexpected exception on applying template %s config", GradleConstants.SYSTEM_ID.getReadableName()), e);
throw new ConfigurationException(
e.getMessage(), String.format("Can't apply %s template config text", GradleConstants.SYSTEM_ID.getReadableName())
);
}
}
private static void appendToFile(@NotNull VirtualFile file, @NotNull String templateName, @Nullable Map templateAttributes)
throws ConfigurationException {
FileTemplateManager manager = FileTemplateManager.getInstance();
FileTemplate template = manager.getInternalTemplate(templateName);
try {
VfsUtil.saveText(file, VfsUtilCore.loadText(file) +
(templateAttributes != null ? template.getText(templateAttributes) : template.getText()));
}
catch (IOException e) {
LOG.warn(String.format("Unexpected exception on appending template %s config", GradleConstants.SYSTEM_ID.getReadableName()), e);
throw new ConfigurationException(
e.getMessage(), String.format("Can't append %s template config text", GradleConstants.SYSTEM_ID.getReadableName())
);
}
}
@Nullable
private static VirtualFile getExternalProjectConfigFile(@NotNull String parent, @NotNull String fileName) {
File file = new File(parent, fileName);
FileUtilRt.createIfNotExists(file);
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
}
}