2 * Copyright 2000-2013 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.plugins.gradle.service.project.wizard;
18 import com.intellij.ide.fileTemplates.FileTemplate;
19 import com.intellij.ide.fileTemplates.FileTemplateManager;
20 import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
21 import com.intellij.ide.util.projectWizard.ModuleWizardStep;
22 import com.intellij.ide.util.projectWizard.WizardContext;
23 import com.intellij.openapi.Disposable;
24 import com.intellij.openapi.diagnostic.Logger;
25 import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys;
26 import com.intellij.openapi.externalSystem.service.project.wizard.AbstractExternalModuleBuilder;
27 import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep;
28 import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
29 import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
30 import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
31 import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
32 import com.intellij.openapi.fileEditor.FileDocumentManager;
33 import com.intellij.openapi.module.*;
34 import com.intellij.openapi.options.ConfigurationException;
35 import com.intellij.openapi.project.Project;
36 import com.intellij.openapi.projectRoots.JavaSdkType;
37 import com.intellij.openapi.projectRoots.SdkTypeId;
38 import com.intellij.openapi.roots.ContentEntry;
39 import com.intellij.openapi.roots.ModifiableRootModel;
40 import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
41 import com.intellij.openapi.util.io.FileUtil;
42 import com.intellij.openapi.util.io.FileUtilRt;
43 import com.intellij.openapi.util.text.StringUtil;
44 import com.intellij.openapi.vfs.LocalFileSystem;
45 import com.intellij.openapi.vfs.VfsUtil;
46 import com.intellij.openapi.vfs.VfsUtilCore;
47 import com.intellij.openapi.vfs.VirtualFile;
48 import com.intellij.util.containers.ContainerUtil;
49 import org.jetbrains.annotations.NotNull;
50 import org.jetbrains.annotations.Nullable;
51 import org.jetbrains.plugins.gradle.service.settings.GradleProjectSettingsControl;
52 import org.jetbrains.plugins.gradle.settings.DistributionType;
53 import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
54 import org.jetbrains.plugins.gradle.util.GradleConstants;
58 import java.io.IOException;
62 * @author Denis Zhdanov
63 * @since 6/26/13 11:10 AM
65 public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradleProjectSettings> {
67 private static final Logger LOG = Logger.getInstance(GradleModuleBuilder.class);
69 private static final String TEMPLATE_GRADLE_SETTINGS = "Gradle Settings.gradle";
70 private static final String TEMPLATE_GRADLE_SETTINGS_MERGE = "Gradle Settings merge.gradle";
71 private static final String TEMPLATE_GRADLE_BUILD_WITH_WRAPPER = "Gradle Build Script with wrapper.gradle";
72 private static final String DEFAULT_TEMPLATE_GRADLE_BUILD = "Gradle Build Script.gradle";
74 private static final String TEMPLATE_ATTRIBUTE_PROJECT_NAME = "PROJECT_NAME";
75 private static final String TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME = "MODULE_DIR_NAME";
76 private static final String TEMPLATE_ATTRIBUTE_MODULE_NAME = "MODULE_NAME";
78 private @NotNull WizardContext myWizardContext;
80 public GradleModuleBuilder() {
81 super(GradleConstants.SYSTEM_ID, new GradleProjectSettings());
85 public void setupRootModel(final ModifiableRootModel modifiableRootModel) throws ConfigurationException {
86 String contentEntryPath = getContentEntryPath();
87 if (StringUtil.isEmpty(contentEntryPath)) {
90 File contentRootDir = new File(contentEntryPath);
91 FileUtilRt.createDirectory(contentRootDir);
92 LocalFileSystem fileSystem = LocalFileSystem.getInstance();
93 VirtualFile modelContentRootDir = fileSystem.refreshAndFindFileByIoFile(contentRootDir);
94 if (modelContentRootDir == null) {
98 modifiableRootModel.addContentEntry(modelContentRootDir);
99 // todo this should be moved to generic ModuleBuilder
101 modifiableRootModel.setSdk(myJdk);
103 modifiableRootModel.inheritSdk();
106 final Project project = modifiableRootModel.getProject();
108 setupGradleBuildFile(modelContentRootDir);
109 setupGradleSettingsFile(modelContentRootDir, modifiableRootModel);
111 if (myWizardContext.isCreatingNewProject()) {
112 String externalProjectPath = FileUtil.toCanonicalPath(project.getBasePath());
113 getExternalProjectSettings().setExternalProjectPath(externalProjectPath);
114 AbstractExternalSystemSettings settings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID);
115 project.putUserData(ExternalSystemDataKeys.NEWLY_CREATED_PROJECT, Boolean.TRUE);
116 //noinspection unchecked
117 settings.linkProject(getExternalProjectSettings());
120 FileDocumentManager.getInstance().saveAllDocuments();
121 ExternalSystemUtil.refreshProjects(project, GradleConstants.SYSTEM_ID, false);
126 public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull ModulesProvider modulesProvider) {
127 myWizardContext = wizardContext;
128 return super.createWizardSteps(wizardContext, modulesProvider);
133 public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) {
134 if (!myWizardContext.isCreatingNewProject()) return new ModuleWizardStep() {
136 public JComponent getComponent() {
141 public void updateDataModel() {
145 final GradleProjectSettingsControl settingsControl = new GradleProjectSettingsControl(getExternalProjectSettings(), myWizardContext.getProject());
146 return new ExternalModuleSettingsStep<GradleProjectSettings>(this, settingsControl);
150 public boolean isSuitableSdkType(SdkTypeId sdk) {
151 return sdk instanceof JavaSdkType;
155 public String getParentGroup() {
156 return JavaModuleType.BUILD_TOOLS_GROUP;
160 public int getWeight() {
161 return JavaModuleBuilder.BUILD_SYSTEM_WEIGHT;
165 public ModuleType getModuleType() {
166 return StdModuleTypes.JAVA;
170 private VirtualFile setupGradleBuildFile(@NotNull VirtualFile modelContentRootDir) throws ConfigurationException {
171 final VirtualFile file = getExternalProjectConfigFile(modelContentRootDir.getPath(), GradleConstants.DEFAULT_SCRIPT_NAME);
172 final String templateName = getExternalProjectSettings().getDistributionType() == DistributionType.WRAPPED
173 ? TEMPLATE_GRADLE_BUILD_WITH_WRAPPER
174 : DEFAULT_TEMPLATE_GRADLE_BUILD;
176 Map attributes = ContainerUtil.newHashMap();
178 saveFile(file, templateName, attributes);
184 private VirtualFile setupGradleSettingsFile(@NotNull VirtualFile modelContentRootDir, @NotNull ModifiableRootModel model)
185 throws ConfigurationException {
186 VirtualFile file = null;
187 if (myWizardContext.isCreatingNewProject()) {
188 final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, model.getProject().getBaseDir(), '/');
189 file = getExternalProjectConfigFile(model.getProject().getBasePath(), GradleConstants.SETTINGS_FILE_NAME);
190 if (file == null) return null;
192 Map<String, String> attributes = ContainerUtil.newHashMap();
193 final String projectName = model.getProject().getName();
194 attributes.put(TEMPLATE_ATTRIBUTE_PROJECT_NAME, projectName);
195 attributes.put(TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME, moduleDirName);
196 attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, model.getModule().getName());
197 saveFile(file, TEMPLATE_GRADLE_SETTINGS, attributes);
200 Map<String, Module> moduleMap = ContainerUtil.newHashMap();
201 for (Module module : ModuleManager.getInstance(model.getProject()).getModules()) {
202 for (ContentEntry contentEntry : model.getContentEntries()) {
203 if (contentEntry.getFile() != null) {
204 moduleMap.put(contentEntry.getFile().getPath(), module);
209 VirtualFile virtualFile = modelContentRootDir;
210 Module module = null;
211 while (virtualFile != null && module == null) {
212 module = moduleMap.get(virtualFile.getPath());
213 virtualFile = virtualFile.getParent();
216 if (module != null) {
217 String rootProjectPath = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
219 if (!StringUtil.isEmpty(rootProjectPath)) {
220 VirtualFile rootProjectFile = VfsUtil.findFileByIoFile(new File(rootProjectPath), true);
221 if (rootProjectFile == null) return null;
223 final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, rootProjectFile, '/');
224 file = getExternalProjectConfigFile(rootProjectPath, GradleConstants.SETTINGS_FILE_NAME);
225 if (file == null) return null;
227 Map<String, String> attributes = ContainerUtil.newHashMap();
228 attributes.put(TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME, moduleDirName);
229 attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, model.getModule().getName());
230 appendToFile(file, TEMPLATE_GRADLE_SETTINGS_MERGE, attributes);
237 private static void saveFile(@NotNull VirtualFile file, @NotNull String templateName, @Nullable Map templateAttributes)
238 throws ConfigurationException {
239 FileTemplateManager manager = FileTemplateManager.getDefaultInstance();
240 FileTemplate template = manager.getInternalTemplate(templateName);
242 VfsUtil.saveText(file, templateAttributes != null ? template.getText(templateAttributes) : template.getText());
244 catch (IOException e) {
245 LOG.warn(String.format("Unexpected exception on applying template %s config", GradleConstants.SYSTEM_ID.getReadableName()), e);
246 throw new ConfigurationException(
247 e.getMessage(), String.format("Can't apply %s template config text", GradleConstants.SYSTEM_ID.getReadableName())
252 private static void appendToFile(@NotNull VirtualFile file, @NotNull String templateName, @Nullable Map templateAttributes)
253 throws ConfigurationException {
254 FileTemplateManager manager = FileTemplateManager.getDefaultInstance();
255 FileTemplate template = manager.getInternalTemplate(templateName);
257 VfsUtil.saveText(file, VfsUtilCore.loadText(file) +
258 (templateAttributes != null ? template.getText(templateAttributes) : template.getText()));
260 catch (IOException e) {
261 LOG.warn(String.format("Unexpected exception on appending template %s config", GradleConstants.SYSTEM_ID.getReadableName()), e);
262 throw new ConfigurationException(
263 e.getMessage(), String.format("Can't append %s template config text", GradleConstants.SYSTEM_ID.getReadableName())
270 private static VirtualFile getExternalProjectConfigFile(@NotNull String parent, @NotNull String fileName) {
271 File file = new File(parent, fileName);
272 FileUtilRt.createIfNotExists(file);
273 return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);