Gradle: add Tooling API extra models support.

Related task: IDEA-79466 gradle support should generate web module configuration
This commit is contained in:
Vladislav.Soroka
2013-11-07 17:52:13 +04:00
parent 3c9aa6d628
commit 2f2f008f5a
19 changed files with 764 additions and 25 deletions
@@ -56,6 +56,11 @@ public class DataNode<T> implements Serializable {
myParent = parent;
}
@Nullable
public DataNode<?> getParent() {
return myParent;
}
@NotNull
public <T> DataNode<T> createChild(@NotNull Key<T> key, @NotNull T data) {
DataNode<T> result = new DataNode<T>(key, data, this);
@@ -0,0 +1,8 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.javaee.WebModuleGradleDataService"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<projectResolve implementation="org.jetbrains.plugins.gradle.integrations.javaee.JavaEEGradleProjectResolverExtension"/>
</extensions>
</idea-plugin>
@@ -0,0 +1,16 @@
#
# 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.
#
org.jetbrains.plugins.gradle.model.impl.WarModelBuilderImpl
@@ -0,0 +1,61 @@
/*
* 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.integrations.javaee;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.Order;
import com.intellij.util.containers.ContainerUtil;
import org.gradle.tooling.model.idea.IdeaModule;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.WarModel;
import org.jetbrains.plugins.gradle.model.data.WarModelData;
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import java.util.Set;
/**
* {@link JavaEEGradleProjectResolverExtension} provides JavaEE project info based on gradle tooling API models.
*
* @author Vladislav.Soroka
* @since 10/14/13
*/
@Order(ExternalSystemConstants.UNORDERED)
public class JavaEEGradleProjectResolverExtension extends AbstractProjectResolverExtension {
private static final Logger LOG = Logger.getInstance(JavaEEGradleProjectResolverExtension.class);
@Override
public void populateModuleExtraModels(@NotNull IdeaModule gradleModule, @NotNull DataNode<ModuleData> ideModule) {
WarModel warModel = resolverCtx.getExtraProject(gradleModule, WarModel.class);
if (warModel != null) {
WarModelData warModelData = new WarModelData(GradleConstants.SYSTEM_ID, warModel.getWebAppDirName(), warModel.getWebAppDir());
warModelData.setWebXml(warModel.getWebXml());
warModelData.setWebRoots(warModel.getWebRoots());
ideModule.createChild(WarModelData.KEY, warModelData);
}
nextResolver.populateModuleExtraModels(gradleModule, ideModule);
}
@NotNull
@Override
public Set<Class> getExtraProjectModelClasses() {
return ContainerUtil.<Class>set(WarModel.class);
}
}
@@ -0,0 +1,28 @@
/*
* 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.model;
import org.gradle.api.Project;
/**
* @author Vladislav.Soroka
* @since 11/5/13
*/
public interface ModelBuilderService {
boolean canBuild(String modelName);
Object buildAll(String modelName, Project project);
}
@@ -0,0 +1,35 @@
/*
* 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.model;
import java.io.File;
import java.io.Serializable;
import java.util.Map;
import java.util.Set;
/**
* @author Vladislav.Soroka
* @since 11/5/13
*/
public interface WarModel extends Serializable {
String getWebAppDirName();
File getWebAppDir();
File getWebXml();
Map<String, Set<String>> getWebRoots();
}
@@ -0,0 +1,116 @@
/*
* 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.model.data;
import com.intellij.openapi.externalSystem.model.Key;
import com.intellij.openapi.externalSystem.model.ProjectKeys;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
/**
* @author Vladislav.Soroka
* @since 11/6/13
*/
public class WarModelData extends AbstractExternalEntityData {
private static final long serialVersionUID = 1L;
@NotNull
public static final Key<WarModelData> KEY = Key.create(WarModelData.class, ProjectKeys.MODULE.getProcessingWeight() + 1);
@NotNull
private final String myWebAppDirName;
@Nullable
private final File myWebAppDir;
@Nullable
private File myWebXml;
@NotNull
private Map<String, Set<String>> myWebRoots;
public WarModelData(@NotNull ProjectSystemId owner, @NotNull String webAppDirName, @Nullable File webAppDir) {
super(owner);
myWebAppDirName = webAppDirName;
myWebAppDir = webAppDir;
myWebRoots = Collections.emptyMap();
}
@NotNull
public String getWebAppDirName() {
return myWebAppDirName;
}
@Nullable
public File getWebAppDir() {
return myWebAppDir;
}
public void setWebXml(@Nullable File webXml) {
myWebXml = webXml;
}
@Nullable
public File getWebXml() {
return myWebXml;
}
public void setWebRoots(@Nullable Map<String, Set<String>> webRoots) {
myWebRoots = webRoots == null ? Collections.<String, Set<String>>emptyMap() : webRoots;
}
@NotNull
public Map<String, Set<String>> getWebRoots() {
return myWebRoots;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
WarModelData that = (WarModelData)o;
if (myWebAppDir != null ? !myWebAppDir.equals(that.myWebAppDir) : that.myWebAppDir != null) return false;
if (!myWebAppDirName.equals(that.myWebAppDirName)) return false;
if (!myWebRoots.equals(that.myWebRoots)) return false;
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + myWebAppDirName.hashCode();
result = 31 * result + myWebRoots.hashCode();
return result;
}
@Override
public String toString() {
return "WarModelData{" +
"myWebAppDirName='" + myWebAppDirName + '\'' +
", myWebAppDir=" + myWebAppDir +
", myWebXml=" + myWebXml +
", myWebRoots=" + myWebRoots +
'}';
}
}
@@ -0,0 +1,115 @@
/*
* 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.model.impl;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.file.FileVisitDetails;
import org.gradle.api.file.FileVisitor;
import org.gradle.api.internal.file.copy.CopySpecInternal;
import org.gradle.api.plugins.WarPlugin;
import org.gradle.api.tasks.bundling.War;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.ModelBuilderService;
import org.jetbrains.plugins.gradle.model.WarModel;
import java.io.File;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* @author Vladislav.Soroka
* @since 11/5/13
*/
public class WarModelBuilderImpl implements ModelBuilderService {
private static final String WEB_APP_DIR_PROPERTY = "webAppDir";
private static final String WEB_APP_DIR_NAME_PROPERTY = "webAppDirName";
@Override
public boolean canBuild(String modelName) {
return WarModel.class.getName().equals(modelName);
}
@Nullable
@Override
public Object buildAll(String modelName, Project project) {
final WarPlugin warPlugin = project.getPlugins().findPlugin(WarPlugin.class);
if (warPlugin == null) return null;
final String webAppDirName = !project.hasProperty(WEB_APP_DIR_NAME_PROPERTY) ?
"src/main/webapp" : String.valueOf(project.property(WEB_APP_DIR_NAME_PROPERTY));
final File webAppDir = !project.hasProperty(WEB_APP_DIR_PROPERTY) ? null : (File)project.property(WEB_APP_DIR_PROPERTY);
WarModelImpl warModel = new WarModelImpl(webAppDirName, webAppDir);
for (Task task : project.getTasks()) {
if (task instanceof War) {
final War warTask = (War)task;
warModel.setWebXml(warTask.getWebXml());
final Map<String, Set<String>> webRoots = new HashMap<String, Set<String>>();
warTask.getRootSpec().walk(new Action<CopySpecInternal>() {
@Override
public void execute(CopySpecInternal internal) {
final String relativePath = internal.getDestPath().getPathString();
internal.getSource().visit(new FileVisitor() {
@Override
public void visitDir(FileVisitDetails dirDetails) {
try {
addPath(webRoots, relativePath, dirDetails.getFile().getPath());
}
catch (Exception ignore) {
}
}
@Override
public void visitFile(FileVisitDetails fileDetails) {
try {
if (warTask.getWebXml() == null ||
!fileDetails.getFile().getCanonicalPath().equals(warTask.getWebXml().getCanonicalPath())) {
addPath(webRoots, relativePath, fileDetails.getFile().getParent());
}
}
catch (Exception ignore) {
}
}
});
}
});
warModel.setWebRoots(webRoots);
break;
}
}
return warModel;
}
private static void addPath(Map<String, Set<String>> webRoots, String relativePath, String path) {
relativePath = relativePath == null ? "" : relativePath;
Set<String> paths = webRoots.get(relativePath);
if (paths == null) {
paths = new LinkedHashSet<String>();
webRoots.put(relativePath, paths);
}
paths.add(path);
}
}
@@ -0,0 +1,66 @@
/*
* 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.model.impl;
import org.jetbrains.plugins.gradle.model.WarModel;
import java.io.File;
import java.util.Map;
import java.util.Set;
/**
* @author Vladislav.Soroka
* @since 11/5/13
*/
public class WarModelImpl implements WarModel {
private final String myWebAppDirName;
private final File myWebAppDir;
private File myWebXml;
private Map<String, Set<String>> myWebRoots;
public WarModelImpl(String webAppDirName, File webAppDir) {
myWebAppDirName = webAppDirName;
myWebAppDir = webAppDir;
}
@Override
public String getWebAppDirName() {
return myWebAppDirName;
}
@Override
public File getWebAppDir() {
return myWebAppDir;
}
public void setWebXml(File webXml) {
myWebXml = webXml;
}
@Override
public File getWebXml() {
return myWebXml;
}
@Override
public Map<String, Set<String>> getWebRoots() {
return myWebRoots;
}
public void setWebRoots(Map<String, Set<String>> webRoots) {
myWebRoots = webRoots;
}
}
@@ -0,0 +1,50 @@
/*
* 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.model.internal;
import org.gradle.api.Project;
import org.gradle.tooling.provider.model.ToolingModelBuilder;
import org.jetbrains.plugins.gradle.model.ModelBuilderService;
import java.util.ServiceLoader;
/**
* @author Vladislav.Soroka
* @since 11/5/13
*/
@SuppressWarnings("UnusedDeclaration")
public class ExtraModelBuilder implements ToolingModelBuilder {
private static ServiceLoader<ModelBuilderService> buildersLoader =
ServiceLoader.load(ModelBuilderService.class, ExtraModelBuilder.class.getClassLoader());
@Override
public boolean canBuild(String modelName) {
for (ModelBuilderService service : buildersLoader) {
if (service.canBuild(modelName)) return true;
}
return false;
}
@Override
public Object buildAll(String modelName, Project project) {
for (ModelBuilderService service : buildersLoader) {
if (service.canBuild(modelName)) {
return service.buildAll(modelName, project);
}
}
throw new IllegalArgumentException("Unsupported model: " + modelName);
}
}
@@ -0,0 +1,42 @@
/*
* 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.
*/
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
@SuppressWarnings("GrPackage")
class JetGradlePlugin implements Plugin<Project> {
private final ToolingModelBuilderRegistry registry
@javax.inject.Inject
public JetGradlePlugin(ToolingModelBuilderRegistry registry) {
this.registry = registry
}
public void apply(Project project) {
registry.register(project.jetExtraModelBuilderClass.newInstance())
}
}
try {
URL[] urls = [new File("${JAR_PATH}").toURI().toURL()]
URLClassLoader classLoader = new URLClassLoader(urls, getClass().classLoader)
Class modelClass = classLoader.loadClass('org.jetbrains.plugins.gradle.model.internal.ExtraModelBuilder')
allprojects {
ext.jetExtraModelBuilderClass = modelClass
apply plugin: JetGradlePlugin
}
}
catch (all) {
}
@@ -0,0 +1,155 @@
/*
* 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;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.SimpleJavaParameters;
import com.intellij.externalSystem.JavaProjectData;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.task.TaskData;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.Order;
import com.intellij.openapi.util.KeyValue;
import org.gradle.tooling.model.idea.IdeaModule;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* {@link org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension} provides dummy implementation of Gradle project resolver.
*
* @author Vladislav.Soroka
* @since 10/14/13
*/
@Order(ExternalSystemConstants.UNORDERED)
public abstract class AbstractProjectResolverExtension implements GradleProjectResolverExtension {
@NotNull protected ProjectResolverContext resolverCtx;
@NotNull protected GradleProjectResolverExtension nextResolver;
@Override
public void setProjectResolverContext(@NotNull ProjectResolverContext projectResolverContext) {
resolverCtx = projectResolverContext;
}
@Override
public void setNext(@Nullable GradleProjectResolverExtension next) {
// there always should be at least gradle basic resolver further in the chain
//noinspection ConstantConditions
assert next != null;
nextResolver = next;
}
@Nullable
@Override
public GradleProjectResolverExtension getNext() {
return nextResolver;
}
@NotNull
@Override
public ProjectData createProject() {
return nextResolver.createProject();
}
@NotNull
@Override
public JavaProjectData createJavaProjectData() {
return nextResolver.createJavaProjectData();
}
@NotNull
@Override
public ModuleData createModule(@NotNull IdeaModule gradleModule, @NotNull ProjectData projectData) {
return nextResolver.createModule(gradleModule, projectData);
}
@Override
public void populateModuleExtraModels(@NotNull IdeaModule gradleModule, @NotNull DataNode<ModuleData> ideModule) {
nextResolver.populateModuleExtraModels(gradleModule, ideModule);
}
@Override
public void populateModuleContentRoots(@NotNull IdeaModule gradleModule,
@NotNull DataNode<ModuleData> ideModule) {
nextResolver.populateModuleContentRoots(gradleModule, ideModule);
}
@Override
public void populateModuleCompileOutputSettings(@NotNull IdeaModule gradleModule,
@NotNull DataNode<ModuleData> ideModule) {
nextResolver.populateModuleCompileOutputSettings(gradleModule, ideModule);
}
@Override
public void populateModuleDependencies(@NotNull IdeaModule gradleModule,
@NotNull DataNode<ModuleData> ideModule,
@NotNull DataNode<ProjectData> ideProject) {
nextResolver.populateModuleDependencies(gradleModule, ideModule, ideProject);
}
@NotNull
@Override
public Collection<TaskData> populateModuleTasks(@NotNull IdeaModule gradleModule,
@NotNull DataNode<ModuleData> ideModule,
@NotNull DataNode<ProjectData> ideProject)
throws IllegalArgumentException, IllegalStateException {
return nextResolver.populateModuleTasks(gradleModule, ideModule, ideProject);
}
@NotNull
@Override
public Collection<TaskData> filterRootProjectTasks(@NotNull List<TaskData> allTasks) {
return nextResolver.filterRootProjectTasks(allTasks);
}
@NotNull
@Override
public Set<Class> getExtraProjectModelClasses() {
return Collections.emptySet();
}
@NotNull
@Override
public List<KeyValue<String, String>> getExtraJvmArgs() {
return Collections.emptyList();
}
@NotNull
@Override
public ExternalSystemException getUserFriendlyError(@NotNull Throwable error,
@NotNull String projectPath,
@Nullable String buildFilePath) {
return nextResolver.getUserFriendlyError(error, projectPath, buildFilePath);
}
@Override
public void enhanceRemoteProcessing(@NotNull SimpleJavaParameters parameters) throws ExecutionException {
}
@Override
public void enhanceLocalProcessing(@NotNull List<URL> urls) {
}
}
@@ -127,10 +127,14 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
return new ModuleData(GradleConstants.SYSTEM_ID,
StdModuleTypes.JAVA.getId(),
moduleName,
projectData.getIdeProjectFileDirectoryPath(),
moduleConfigPath,
moduleConfigPath);
}
@Override
public void populateModuleExtraModels(@NotNull IdeaModule gradleModule, @NotNull DataNode<ModuleData> ideModule) {
}
@Override
public void populateModuleContentRoots(@NotNull IdeaModule gradleModule,
@NotNull DataNode<ModuleData> ideModule) {
@@ -139,13 +143,11 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
return;
}
for (IdeaContentRoot gradleContentRoot : contentRoots) {
if (gradleContentRoot == null) {
continue;
}
if (gradleContentRoot == null) continue;
File rootDirectory = gradleContentRoot.getRootDirectory();
if (rootDirectory == null) {
continue;
}
if (rootDirectory == null) continue;
ContentRootData ideContentRoot = new ContentRootData(GradleConstants.SYSTEM_ID, rootDirectory.getAbsolutePath());
ideModule.getData().setModuleFileDirectoryPath(ideContentRoot.getRootPath());
populateContentRoot(ideContentRoot, ExternalSystemSourceType.SOURCE, gradleContentRoot.getSourceDirectories());
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.gradle.service.project;
import com.intellij.execution.configurations.CommandLineTokenizer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationEvent;
@@ -24,6 +25,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.Function;
import com.intellij.util.PathUtil;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
@@ -42,6 +44,7 @@ import org.jetbrains.plugins.gradle.util.GradleUtil;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.List;
@@ -53,6 +56,7 @@ import java.util.concurrent.TimeUnit;
*/
public class GradleExecutionHelper {
private static final Logger LOG = Logger.getInstance(GradleExecutionHelper.class);
@SuppressWarnings("MethodMayBeStatic")
@NotNull
@@ -61,8 +65,7 @@ public class GradleExecutionHelper {
@Nullable GradleExecutionSettings settings,
@NotNull ProjectConnection connection,
@NotNull ExternalSystemTaskNotificationListener listener,
@NotNull List<String> extraJvmArgs)
{
@NotNull List<String> extraJvmArgs) {
ModelBuilder<T> result = connection.model(modelType);
prepare(result, id, settings, listener, extraJvmArgs, connection);
return result;
@@ -74,8 +77,7 @@ public class GradleExecutionHelper {
@NotNull ProjectConnection connection,
@Nullable GradleExecutionSettings settings,
@NotNull ExternalSystemTaskNotificationListener listener,
@Nullable final String vmOptions)
{
@Nullable final String vmOptions) {
BuildLauncher result = connection.newBuild();
List<String> extraJvmArgs = vmOptions == null ? ContainerUtil.<String>emptyList() : ContainerUtil.newArrayList(vmOptions.trim());
prepare(result, id, settings, listener, extraJvmArgs, connection);
@@ -90,8 +92,7 @@ public class GradleExecutionHelper {
@NotNull ExternalSystemTaskNotificationListener listener,
@Nullable final String vmOptions,
@NotNull final OutputStream standardOutput,
@NotNull final OutputStream standardError)
{
@NotNull final OutputStream standardError) {
BuildLauncher result = connection.newBuild();
List<String> extraJvmArgs = vmOptions == null ? ContainerUtil.<String>emptyList() : ContainerUtil.newArrayList(vmOptions.trim());
prepare(result, id, settings, listener, extraJvmArgs, connection, standardOutput, standardError);
@@ -118,8 +119,7 @@ public class GradleExecutionHelper {
@NotNull List<String> extraJvmArgs,
@NotNull ProjectConnection connection,
@NotNull final OutputStream standardOutput,
@NotNull final OutputStream standardError)
{
@NotNull final OutputStream standardError) {
if (settings == null) {
return;
}
@@ -129,7 +129,7 @@ public class GradleExecutionHelper {
String vmOptions = settings.getDaemonVmOptions();
if (!StringUtil.isEmpty(vmOptions)) {
CommandLineTokenizer tokenizer = new CommandLineTokenizer(vmOptions);
while(tokenizer.hasMoreTokens()) {
while (tokenizer.hasMoreTokens()) {
String vmOption = tokenizer.nextToken();
if (!StringUtil.isEmpty(vmOption)) {
jvmArgs.add(vmOption);
@@ -167,14 +167,15 @@ public class GradleExecutionHelper {
if (projectPathFile.isFile() && projectPath.endsWith(GradleConstants.EXTENSION)
&& projectPathFile.getParent() != null) {
projectDir = projectPathFile.getParent();
} else {
}
else {
projectDir = projectPath;
}
// This is a workaround to get right base dir in case of 'PROJECT' setting used in case custom wrapper property file location
// see org.gradle.wrapper.PathAssembler#getBaseDir for details
String userDir = null;
if(settings != null && settings.getDistributionType() == DistributionType.WRAPPED) {
if (settings != null && settings.getDistributionType() == DistributionType.WRAPPED) {
try {
userDir = System.getProperty("user.dir");
System.setProperty("user.dir", projectDir);
@@ -227,7 +228,9 @@ public class GradleExecutionHelper {
"gradle.taskGraph.afterTask { Task task ->",
" if (task instanceof Wrapper) {",
" def wrapperPropertyFileLocation = task.jarFile.getCanonicalPath() - '.jar' + '.properties'",
" new File('" + StringUtil.escapeBackSlashes(wrapperPropertyFileLocation.getCanonicalPath()) + "').write wrapperPropertyFileLocation",
" new File('" +
StringUtil.escapeBackSlashes(wrapperPropertyFileLocation.getCanonicalPath()) +
"').write wrapperPropertyFileLocation",
"}}",
};
FileUtil.writeToFile(tempFile, StringUtil.join(lines, SystemProperties.getLineSeparator()));
@@ -263,21 +266,20 @@ public class GradleExecutionHelper {
/**
* Allows to retrieve gradle api connection to use for the given project.
*
* @param projectPath target project path
* @param settings execution settings to use
* @param projectPath target project path
* @param settings execution settings to use
* @return connection to use
* @throws IllegalStateException if it's not possible to create the connection
*/
@NotNull
private static ProjectConnection getConnection(@NotNull String projectPath,
@Nullable GradleExecutionSettings settings)
throws IllegalStateException
{
throws IllegalStateException {
File projectDir = new File(projectPath);
GradleConnector connector = GradleConnector.newConnector();
int ttl = -1;
if(settings != null) {
if (settings != null) {
//noinspection EnumSwitchStatementWhichMissesCases
switch (settings.getDistributionType()) {
case LOCAL:
@@ -357,4 +359,24 @@ public class GradleExecutionHelper {
field.set(obj, fieldValue);
field.setAccessible(isAccessible);
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
public static void setInitScript(LongRunningOperation longRunningOperation) {
try {
InputStream stream = GradleProjectResolver.class.getResourceAsStream("/org/jetbrains/plugins/gradle/model/internal/init.gradle");
if (stream == null) return;
String jarPath = PathUtil.getCanonicalPath(PathUtil.getJarPathForClass(GradleProjectResolver.class));
String s = FileUtil.loadTextAndClose(stream).replace("${JAR_PATH}", jarPath);
final File tempFile = FileUtil.createTempFile("ijinit", '.' + GradleConstants.EXTENSION, true);
FileUtil.writeToFile(tempFile, s);
String[] buildExecutorArgs = new String[]{"--init-script", tempFile.getAbsolutePath()};
longRunningOperation.withArguments(buildExecutorArgs);
}
catch (Exception e) {
LOG.warn("Can't use IJ gradle init script", e);
}
}
}
@@ -49,6 +49,7 @@ import org.jetbrains.plugins.gradle.remote.impl.GradleLibraryNamesMixer;
import org.jetbrains.plugins.gradle.settings.ClassHolder;
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import org.jetbrains.plugins.gradle.util.GradleEnvironment;
import java.util.*;
@@ -152,6 +153,11 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
resolverCtx.getSettings(), resolverCtx.getListener(),
parametersList.getParameters(), resolverCtx.getConnection());
// TODO [vlad] remove the check
if (GradleEnvironment.USE_ENHANCED_TOOLING_API) {
GradleExecutionHelper.setInitScript(buildActionExecutor);
}
ProjectImportAction.AllModels allModels;
try {
allModels = buildActionExecutor.run();
@@ -220,6 +226,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
for (final Pair<DataNode<ModuleData>, IdeaModule> pair : moduleMap.values()) {
final DataNode<ModuleData> moduleDataNode = pair.first;
final IdeaModule ideaModule = pair.second;
projectResolverChain.populateModuleExtraModels(ideaModule, moduleDataNode);
projectResolverChain.populateModuleContentRoots(ideaModule, moduleDataNode);
projectResolverChain.populateModuleCompileOutputSettings(ideaModule, moduleDataNode);
projectResolverChain.populateModuleDependencies(ideaModule, moduleDataNode, projectDataNode);
@@ -251,7 +258,8 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
private static BuildEnvironment getBuildEnvironment(@NotNull ProjectResolverContext resolverCtx) {
try {
return resolverCtx.getConnection().getModel(BuildEnvironment.class);
} catch (Exception e) {
}
catch (Exception e) {
return null;
}
}
@@ -66,6 +66,13 @@ public interface GradleProjectResolverExtension extends ParametersEnhancer {
@NotNull
ModuleData createModule(@NotNull IdeaModule gradleModule, @NotNull ProjectData projectData);
/**
* Populates extra models of the given ide module on the basis of the information provided by {@link org.jetbrains.plugins.gradle.model.ModelBuilderService}
*
* @param ideModule corresponding module from intellij gradle plugin domain
*/
void populateModuleExtraModels(@NotNull IdeaModule gradleModule, @NotNull DataNode<ModuleData> ideModule);
/**
* Populates {@link com.intellij.openapi.externalSystem.model.ProjectKeys#CONTENT_ROOT) content roots} of the given ide module on the basis of the information
* contained at the given gradle module.
@@ -40,6 +40,7 @@ public final class GradleCommonClassNames {
@NonNls public static final String GRADLE_API_DEFAULT_TASK = "org.gradle.api.DefaultTask";
@NonNls public static final String GRADLE_API_TASKS_DELETE = "org.gradle.api.tasks.Delete";
@NonNls public static final String GRADLE_API_TASKS_BUNDLING_JAR = "org.gradle.api.tasks.bundling.Jar";
@NonNls public static final String GRADLE_API_TASKS_BUNDLING_WAR = "org.gradle.api.tasks.bundling.War";
@NonNls public static final String GRADLE_API_TASKS_COMPILE_JAVA_COMPILE = "org.gradle.api.tasks.compile.JavaCompile";
@NonNls public static final String GRADLE_API_TASKS_WRAPPER_WRAPPER = "org.gradle.api.tasks.wrapper.Wrapper";
@NonNls public static final String GRADLE_API_TASKS_JAVADOC_JAVADOC = "org.gradle.api.tasks.javadoc.Javadoc";
@@ -56,6 +56,7 @@ public class GradleImplicitContributor implements GradleMethodContextContributor
new Pair<String, String>("buildNeeded", GRADLE_API_DEFAULT_TASK),
new Pair<String, String>("clean", GRADLE_API_TASKS_DELETE),
new Pair<String, String>("jar", GRADLE_API_TASKS_BUNDLING_JAR),
new Pair<String, String>("war", GRADLE_API_TASKS_BUNDLING_WAR),
new Pair<String, String>("classes", GRADLE_API_DEFAULT_TASK),
new Pair<String, String>("compileJava", GRADLE_API_TASKS_COMPILE_JAVA_COMPILE),
new Pair<String, String>("compileTestJava", GRADLE_API_DEFAULT_TASK),
@@ -10,6 +10,7 @@ import org.jetbrains.annotations.NonNls;
public class GradleEnvironment {
@NonNls public static final boolean DEBUG_GRADLE_HOME_PROCESSING = Boolean.getBoolean("gradle.debug.home.processing");
@NonNls public static final boolean USE_ENHANCED_TOOLING_API = Boolean.getBoolean("gradle.use.enhanced.tooling.api");
private GradleEnvironment() {
}