diff options
author | Tor Norbye <tnorbye@google.com> | 2013-08-23 09:23:25 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2013-08-23 09:23:30 -0700 |
commit | e47d04f1f804b9e725b768725da436af6788f19b (patch) | |
tree | 16c96885d523fdafb654b2703b4d05befd7cfbf0 /plugins | |
parent | 926bc53d2e5f6a9f66c98baa1624ad809edb1456 (diff) | |
download | idea-e47d04f1f804b9e725b768725da436af6788f19b.tar.gz |
Snapshot 311dce86b8c66d1c59d8b92435689e49873ec50f from master branch of git://git.jetbrains.org/idea/community.git
311dce8: 2013-08-23 Vladislav.Soroka - IDEA-99779 Gradle Wrapper is not recognized in a project if wrapper's .properties and .jar files are located not in default place
90d92ad: 2013-08-23 Sergey Simonchik - ScriptRunnerUtil.executeSafelyOnMac merged into ScriptRunnerUtil.execute; rerun is performed if really needed (I hope)
3bbc5f6: 2013-08-23 Anna Kozlova - Merge remote-tracking branch 'origin/master'
4735aa8: 2013-08-23 Anna Kozlova - Merge remote-tracking branch 'origin/master'
d040858: 2013-08-23 Sergey Evdokimov - Avoid iteration by all SDK roots in GriffonFramework.getSdkRoot() +review CR-IU
16d39f1: 2013-08-23 Anna Kozlova - can be method ref: provide type info in inspection error message (IDEA-112557)
Change-Id: Ie093ba3ac365ad674a4b74ec95e4d4af408bae85
Diffstat (limited to 'plugins')
18 files changed, 457 insertions, 146 deletions
diff --git a/plugins/gradle/resources/i18n/GradleBundle.properties b/plugins/gradle/resources/i18n/GradleBundle.properties index 8252d8be0262..254c04a80c20 100644 --- a/plugins/gradle/resources/i18n/GradleBundle.properties +++ b/plugins/gradle/resources/i18n/GradleBundle.properties @@ -3,6 +3,7 @@ gradle.name=Gradle gradle.settings.text.use.wrapper=Use gradle wrapper (recommended) gradle.settings.text.use.wrapper.disabled=Use gradle wrapper (not configured for the current project) gradle.settings..text.use.local.distribution=Use local gradle distribution +gradle.settings.text.use.bundled.distribution=Use bundled gradle distribution: ({0}) gradle.settings.text.home.path=Gradle home: gradle.settings.text.service.dir.path=Service directory path: diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java index 732e7025418e..dec89c51ab0e 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java @@ -167,10 +167,10 @@ implements ExternalSystemConfigurableAware, ExternalSystemUiAware, ExternalSyste } GradleProjectSettings projectLevelSettings = settings.getLinkedProjectSettings(pair.second); - boolean useWrapper = projectLevelSettings != null && !projectLevelSettings.isPreferLocalInstallationToWrapper(); + DistributionType distributionType = projectLevelSettings == null ? DistributionType.BUNDLED : projectLevelSettings.getDistributionType(); GradleExecutionSettings result = new GradleExecutionSettings(localGradlePath, settings.getServiceDirectoryPath(), - useWrapper, + distributionType, settings.getGradleVmOptions()); for (GradleProjectResolverExtension extension : RESOLVER_EXTENSIONS.getValue()) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/DelegatingGradleSettingsListenerAdapter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/DelegatingGradleSettingsListenerAdapter.java index 13dbd1182304..d72eea0c4127 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/DelegatingGradleSettingsListenerAdapter.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/DelegatingGradleSettingsListenerAdapter.java @@ -19,6 +19,7 @@ import com.intellij.openapi.externalSystem.settings.DelegatingExternalSystemSett import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListener; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.settings.DistributionType; import org.jetbrains.plugins.gradle.settings.GradleProjectSettings; import org.jetbrains.plugins.gradle.settings.GradleSettingsListener; @@ -39,7 +40,7 @@ public class DelegatingGradleSettingsListenerAdapter extends DelegatingExternalS } @Override - public void onPreferLocalGradleDistributionToWrapperChange(boolean currentValue, @NotNull String linkedProjectPath) { + public void onGradleDistributionTypeChange(DistributionType currentValue, @NotNull String linkedProjectPath) { } @Override diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettingsListenerAdapter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettingsListenerAdapter.java index 2f01fe40a05d..9aae216b0470 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettingsListenerAdapter.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettingsListenerAdapter.java @@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.config; import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListenerAdapter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.settings.DistributionType; import org.jetbrains.plugins.gradle.settings.GradleProjectSettings; import org.jetbrains.plugins.gradle.settings.GradleSettingsListener; @@ -19,7 +20,7 @@ public abstract class GradleSettingsListenerAdapter extends ExternalSystemSettin } @Override - public void onPreferLocalGradleDistributionToWrapperChange(boolean currentValue, @NotNull String linkedProjectPath) { + public void onGradleDistributionTypeChange(DistributionType currentValue, @NotNull String linkedProjectPath) { } @Override diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java index 2c3e9ab4581d..544542ffb1d3 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java @@ -16,6 +16,7 @@ import com.intellij.util.containers.ContainerUtilRt; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.settings.DistributionType; import org.jetbrains.plugins.gradle.settings.GradleProjectSettings; import org.jetbrains.plugins.gradle.settings.GradleSettings; import org.jetbrains.plugins.gradle.util.GradleEnvironment; @@ -112,11 +113,7 @@ public class GradleInstallationManager { */ @Nullable public File getGradleHome(@Nullable Project project, @NotNull String linkedProjectPath) { - File result = getWrapperHome(project, linkedProjectPath); - if (result != null) { - return result; - } - result = getManuallyDefinedGradleHome(project, linkedProjectPath); + File result = getManuallyDefinedGradleHome(project, linkedProjectPath); if (result != null) { return result; } @@ -175,60 +172,6 @@ public class GradleInstallationManager { return home == null ? null : LocalFileSystem.getInstance().refreshAndFindFileByIoFile(home); } - @Nullable - public File getWrapperHome(@Nullable Project project, @NotNull String linkedProjectPath) { - if (project == null) { - return null; - } - - GradleProjectSettings settings = GradleSettings.getInstance(project).getLinkedProjectSettings(linkedProjectPath); - if (settings == null) { - return null; - } - - if (settings.isPreferLocalInstallationToWrapper()) { - return null; - } - - String distribution = GradleUtil.getWrapperDistribution(linkedProjectPath); - if (distribution == null) { - return null; - } - File gradleSystemDir = new File(System.getProperty("user.home"), ".gradle"); - if (!gradleSystemDir.isDirectory()) { - return null; - } - - File gradleWrapperDistributionsHome = new File(gradleSystemDir, "wrapper/dists"); - if (!gradleWrapperDistributionsHome.isDirectory()) { - return null; - } - - File targetDistributionHome = new File(gradleWrapperDistributionsHome, distribution); - if (!targetDistributionHome.isDirectory()) { - return null; - } - - File[] files = targetDistributionHome.listFiles(); - if (files == null || files.length != 1) { - // Gradle keeps wrapper at a directory which name is a hash value like '35oej0jnbfh6of4dd05531edaj' - return null; - } - - File[] distFiles = files[0].listFiles(new FileFilter() { - @Override - public boolean accept(File f) { - return f.isDirectory(); - } - }); - if (distFiles == null || distFiles.length != 1) { - // There should exist only the gradle directory in the distribution directory - return null; - } - - return distFiles[0].isDirectory() ? distFiles[0] : null; - } - /** * Allows to ask for user-defined path to gradle. * @@ -344,6 +287,17 @@ public class GradleInstallationManager { } /** + * Allows to answer if given virtual file points to the gradle installation root. + * + * @param file gradle installation root candidate + * @return <code>true</code> if we consider that given file actually points to the gradle installation root; + * <code>false</code> otherwise + */ + public boolean isGradleSdkHome(String gradleHomePath) { + return isGradleSdkHome(new File(gradleHomePath)); + } + + /** * Allows to answer if given files contain the one from gradle installation. * * @param files files to process @@ -411,7 +365,6 @@ public class GradleInstallationManager { if (StringUtil.isEmpty(path)) { continue; } - assert path != null; final Collection<File> libraries = getAllLibraries(project, path); if (libraries == null) { continue; diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DistributionFactoryExt.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DistributionFactoryExt.java new file mode 100644 index 000000000000..0af4476ea1f9 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DistributionFactoryExt.java @@ -0,0 +1,165 @@ +/* + * 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 org.gradle.internal.classpath.ClassPath; +import org.gradle.internal.classpath.DefaultClassPath; +import org.gradle.logging.ProgressLogger; +import org.gradle.logging.ProgressLoggerFactory; +import org.gradle.tooling.GradleConnectionException; +import org.gradle.tooling.internal.consumer.Distribution; +import org.gradle.tooling.internal.consumer.DistributionFactory; +import org.gradle.util.DistributionLocator; +import org.gradle.util.GradleVersion; +import org.gradle.wrapper.*; + +import java.io.File; +import java.io.FileNotFoundException; +import java.net.URI; +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * @author Vladislav.Soroka + * @since 8/23/13 + */ +public class DistributionFactoryExt extends DistributionFactory { + private final File userHomeDir; + + public DistributionFactoryExt(File userHomeDir) { + super(userHomeDir); + this.userHomeDir = userHomeDir; + } + + /** + * Returns the default distribution to use for the specified project. + */ + public Distribution getWrappedDistribution(File propertiesFile) { + //noinspection UseOfSystemOutOrSystemErr + WrapperExecutor wrapper = WrapperExecutor.forWrapperPropertiesFile(propertiesFile, System.out); + if (wrapper.getDistribution() != null) { + return new ZippedDistribution(wrapper.getConfiguration()); + } + return getDownloadedDistribution(GradleVersion.current().getVersion()); + } + + private Distribution getDownloadedDistribution(String gradleVersion) { + URI distUri = new DistributionLocator().getDistributionFor(GradleVersion.version(gradleVersion)); + return getDistribution(distUri); + } + + private static class ProgressReportingDownload implements IDownload { + private final ProgressLoggerFactory progressLoggerFactory; + + private ProgressReportingDownload(ProgressLoggerFactory progressLoggerFactory) { + this.progressLoggerFactory = progressLoggerFactory; + } + + public void download(URI address, File destination) throws Exception { + ProgressLogger progressLogger = progressLoggerFactory.newOperation(DistributionFactory.class); + progressLogger.setDescription(String.format("Download %s", address)); + progressLogger.started(); + try { + new Download("Gradle Tooling API", GradleVersion.current().getVersion()).download(address, destination); + } + finally { + progressLogger.completed(); + } + } + } + + private static class InstalledDistribution implements Distribution { + private final File gradleHomeDir; + private final String displayName; + private final String locationDisplayName; + + public InstalledDistribution(File gradleHomeDir, String displayName, String locationDisplayName) { + this.gradleHomeDir = gradleHomeDir; + this.displayName = displayName; + this.locationDisplayName = locationDisplayName; + } + + public String getDisplayName() { + return displayName; + } + + public ClassPath getToolingImplementationClasspath(ProgressLoggerFactory progressLoggerFactory) { + ProgressLogger progressLogger = progressLoggerFactory.newOperation(DistributionFactory.class); + progressLogger.setDescription("Validate distribution"); + progressLogger.started(); + try { + return getToolingImpl(); + } + finally { + progressLogger.completed(); + } + } + + private ClassPath getToolingImpl() { + if (!gradleHomeDir.exists()) { + throw new IllegalArgumentException(String.format("The specified %s does not exist.", locationDisplayName)); + } + if (!gradleHomeDir.isDirectory()) { + throw new IllegalArgumentException(String.format("The specified %s is not a directory.", locationDisplayName)); + } + File libDir = new File(gradleHomeDir, "lib"); + if (!libDir.isDirectory()) { + throw new IllegalArgumentException( + String.format("The specified %s does not appear to contain a Gradle distribution.", locationDisplayName)); + } + Set<File> files = new LinkedHashSet<File>(); + //noinspection ConstantConditions + for (File file : libDir.listFiles()) { + if (file.getName().endsWith(".jar")) { + files.add(file); + } + } + return new DefaultClassPath(files); + } + } + + private class ZippedDistribution implements Distribution { + private final WrapperConfiguration wrapperConfiguration; + private InstalledDistribution installedDistribution; + + private ZippedDistribution(WrapperConfiguration wrapperConfiguration) { + this.wrapperConfiguration = wrapperConfiguration; + } + + public String getDisplayName() { + return String.format("Gradle distribution '%s'", wrapperConfiguration.getDistribution()); + } + + public ClassPath getToolingImplementationClasspath(ProgressLoggerFactory progressLoggerFactory) { + if (installedDistribution == null) { + File installDir; + try { + Install install = new Install(new ProgressReportingDownload(progressLoggerFactory), new PathAssembler(userHomeDir)); + installDir = install.createDist(wrapperConfiguration); + } + catch (FileNotFoundException e) { + throw new IllegalArgumentException(String.format("The specified %s does not exist.", getDisplayName()), e); + } + catch (Exception e) { + throw new GradleConnectionException( + String.format("Could not install Gradle distribution from '%s'.", wrapperConfiguration.getDistribution()), e); + } + installedDistribution = new InstalledDistribution(installDir, getDisplayName(), getDisplayName()); + } + return installedDistribution.getToolingImplementationClasspath(progressLoggerFactory); + } + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java index 6a0b53ffc45d..694b1a599a26 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java @@ -20,12 +20,16 @@ import com.intellij.openapi.externalSystem.model.ExternalSystemException; import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId; import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationEvent; import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener; +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.SystemProperties; import com.intellij.util.containers.ContainerUtilRt; +import org.gradle.StartParameter; import org.gradle.tooling.*; import org.gradle.tooling.internal.consumer.DefaultGradleConnector; +import org.gradle.tooling.internal.consumer.Distribution; import org.gradle.tooling.model.idea.BasicIdeaProject; import org.gradle.tooling.model.idea.IdeaProject; import org.jetbrains.annotations.NotNull; @@ -34,6 +38,7 @@ import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings; import java.io.File; import java.io.IOException; +import java.lang.reflect.Field; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; @@ -127,6 +132,17 @@ public class GradleExecutionHelper { } public <T> T execute(@NotNull String projectPath, @Nullable GradleExecutionSettings settings, @NotNull Function<ProjectConnection, T> f) { + + String userDir = null; + try { + // This is a workaround to get right base dir in case of 'PROJECT' setting used + // see org.gradle.wrapper.PathAssembler#getBaseDir for details + userDir = System.getProperty("user.dir"); + System.setProperty("user.dir", projectPath); + } + catch (Exception e) { + // ignore + } ProjectConnection connection = getConnection(projectPath, settings); try { return f.fun(connection); @@ -137,6 +153,53 @@ public class GradleExecutionHelper { finally { try { connection.close(); + if (userDir != null) { + // restore original user.dir property + System.setProperty("user.dir", userDir); + } + } + catch (Throwable e) { + // ignore + } + } + } + + public void ensureInstalledWrapper(@NotNull ExternalSystemTaskId id, + @NotNull String projectPath, + @NotNull GradleExecutionSettings settings, + @NotNull ExternalSystemTaskNotificationListener listener) { + ProjectConnection connection = getConnection(projectPath, settings); + try { + BuildLauncher launcher = getBuildLauncher(id, connection, settings, listener); + try { + final File tempFile = FileUtil.createTempFile("wrap", ".gradle"); + tempFile.deleteOnExit(); + final File wrapperPropertyFileLocation = FileUtil.createTempFile("wrap", "loc"); + wrapperPropertyFileLocation.deleteOnExit(); + final String[] lines = { + "gradle.taskGraph.afterTask { Task task ->", + " if (task instanceof Wrapper) {", + " def wrapperPropertyFileLocation = task.jarFile.getCanonicalPath() - '.jar' + '.properties'", + " new File('" + StringUtil.escapeBackSlashes(wrapperPropertyFileLocation.getCanonicalPath()) + "').write wrapperPropertyFileLocation", + "}}", + }; + FileUtil.writeToFile(tempFile, StringUtil.join(lines, SystemProperties.getLineSeparator())); + launcher.withArguments("--init-script", tempFile.getAbsolutePath()); + launcher.forTasks("wrapper"); + launcher.run(); + String wrapperPropertyFile = FileUtil.loadFile(wrapperPropertyFileLocation); + settings.setWrapperPropertyFile(wrapperPropertyFile); + } + catch (IOException e) { + throw new ExternalSystemException(e); + } + } + catch (Throwable e) { + throw new ExternalSystemException(e); + } + finally { + try { + connection.close(); } catch (Throwable e) { // ignore @@ -147,31 +210,48 @@ 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 - * @return connection to use - * @throws IllegalStateException if it's not possible to create the connection + * @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) + private static ProjectConnection getConnection(@NotNull String projectPath, + @Nullable GradleExecutionSettings settings) throws IllegalStateException { File projectDir = new File(projectPath); GradleConnector connector = GradleConnector.newConnector(); - if (settings != null) { - - // Setup wrapper/local installation usage. - if (!settings.isUseWrapper()) { - String gradleHome = settings.getGradleHome(); - if (gradleHome != null) { - try { - // There were problems with symbolic links processing at the gradle side. - connector.useInstallation(new File(gradleHome).getCanonicalFile()); + int ttl = -1; + + if(settings != null) { + //noinspection EnumSwitchStatementWhichMissesCases + switch (settings.getDistributionType()) { + case LOCAL: + String gradleHome = settings.getGradleHome(); + if (gradleHome != null) { + try { + // There were problems with symbolic links processing at the gradle side. + connector.useInstallation(new File(gradleHome).getCanonicalFile()); + } + catch (IOException e) { + connector.useInstallation(new File(settings.getGradleHome())); + } } - catch (IOException e) { - connector.useInstallation(new File(settings.getGradleHome())); + break; + case WRAPPED: + if(settings.getWrapperPropertyFile() != null) { + File propertiesFile = new File(settings.getWrapperPropertyFile()); + Distribution distribution = + new DistributionFactoryExt(StartParameter.DEFAULT_GRADLE_USER_HOME).getWrappedDistribution(propertiesFile); + try { + setField(connector, "distribution", distribution); + } + catch (Exception e) { + throw new ExternalSystemException(e); + } } - } + break; } // Setup service directory if necessary. @@ -184,12 +264,11 @@ public class GradleExecutionHelper { if (settings.isVerboseProcessing() && connector instanceof DefaultGradleConnector) { ((DefaultGradleConnector)connector).setVerboseLogging(true); } + ttl = (int)settings.getRemoteProcessIdleTtlInMs(); + } - // Setup daemon ttl if necessary. - long ttl = settings.getRemoteProcessIdleTtlInMs(); - if (ttl > 0 && connector instanceof DefaultGradleConnector) { - ((DefaultGradleConnector)connector).daemonMaxIdleTime((int)ttl, TimeUnit.MILLISECONDS); - } + if (ttl > 0 && connector instanceof DefaultGradleConnector) { + ((DefaultGradleConnector)connector).daemonMaxIdleTime(ttl, TimeUnit.MILLISECONDS); } connector.forProjectDirectory(projectDir); ProjectConnection connection = connector.connect(); @@ -200,4 +279,27 @@ public class GradleExecutionHelper { } return connection; } + + /** + * Utility to set field in object if there is no public setter for it. + * It's not recommended to use this method. + * FIXME: remove this workaround after gradle API changed + * + * @param obj Object to be modified + * @param fieldName name of object's field + * @param fieldValue value to be set for field + * @throws SecurityException + * @throws NoSuchFieldException + * @throws IllegalArgumentException + * @throws IllegalAccessException + */ + public static void setField(Object obj, String fieldName, Object fieldValue) + throws SecurityException, NoSuchFieldException, + IllegalArgumentException, IllegalAccessException { + final Field field = obj.getClass().getDeclaredField(fieldName); + final boolean isAccessible = field.isAccessible(); + field.setAccessible(true); + field.set(obj, fieldValue); + field.setAccessible(isAccessible); + } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java index 8dde4a838c78..57f00e566af8 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java @@ -20,8 +20,7 @@ import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.text.CharArrayUtil; import gnu.trove.TObjectIntHashMap; import gnu.trove.TObjectIntProcedure; -import org.gradle.tooling.ModelBuilder; -import org.gradle.tooling.ProjectConnection; +import org.gradle.tooling.*; import org.gradle.tooling.model.DomainObjectSet; import org.gradle.tooling.model.GradleTask; import org.gradle.tooling.model.idea.*; @@ -30,6 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.remote.impl.GradleLibraryNamesMixer; import org.jetbrains.plugins.gradle.settings.ClassHolder; +import org.jetbrains.plugins.gradle.settings.DistributionType; import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings; import org.jetbrains.plugins.gradle.util.GradleConstants; import org.jetbrains.plugins.gradle.util.GradleUtil; @@ -62,6 +62,9 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad throws ExternalSystemException, IllegalArgumentException, IllegalStateException { if (settings != null) { + if(settings.getDistributionType() == DistributionType.WRAPPED) { + myHelper.ensureInstalledWrapper(id, projectPath, settings, listener); + } List<ClassHolder<? extends GradleProjectResolverExtension>> extensionClasses = settings.getResolverExtensions(); if (myCachedExtensions == null || !myCachedExtensions.first.equals(extensionClasses)) { List<GradleProjectResolverExtension> extensions = ContainerUtilRt.newArrayList(); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java index 37f38ea4c8f3..669bc3a5317b 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java @@ -30,9 +30,11 @@ import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBRadioButton; import com.intellij.util.Alarm; import com.intellij.util.Consumer; +import org.gradle.util.GradleVersion; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.service.GradleInstallationManager; +import org.jetbrains.plugins.gradle.settings.DistributionType; import org.jetbrains.plugins.gradle.settings.GradleProjectSettings; import org.jetbrains.plugins.gradle.util.GradleBundle; import org.jetbrains.plugins.gradle.util.GradleConstants; @@ -68,6 +70,7 @@ public class GradleProjectSettingsControl extends AbstractExternalProjectSetting private TextFieldWithBrowseButton myGradleHomePathField; private JBRadioButton myUseWrapperButton; private JBRadioButton myUseLocalDistributionButton; + private JBRadioButton myUseBundledDistributionButton; private boolean myShowBalloonIfNecessary; private boolean myGradleHomeModifiedByUser; @@ -106,21 +109,32 @@ public class GradleProjectSettingsControl extends AbstractExternalProjectSetting myGradleHomeLabel = new JBLabel(GradleBundle.message("gradle.settings.text.home.path")); initGradleHome(); - initWrapperControls(); + initControls(); content.add(myUseWrapperButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); content.add(myUseLocalDistributionButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); + content.add(myUseBundledDistributionButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); content.add(myGradleHomeLabel, ExternalSystemUiUtil.getLabelConstraints(indentLevel)); content.add(myGradleHomePathField, ExternalSystemUiUtil.getFillLineConstraints(0)); } - private void initWrapperControls() { + private void initControls() { ActionListener listener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - boolean enabled = e.getSource() == myUseLocalDistributionButton; - myGradleHomePathField.setEnabled(enabled); - if (enabled) { + boolean localDistributionEnabled = e.getSource() == myUseLocalDistributionButton; + myGradleHomePathField.setEnabled(localDistributionEnabled); + if (localDistributionEnabled) { + if(myGradleHomePathField.getText().isEmpty()){ + deduceGradleHomeIfPossible(); + } else { + if(myInstallationManager.isGradleSdkHome(myGradleHomePathField.getText())){ + myGradleHomeSettingType = LocationSettingType.EXPLICIT_CORRECT; + } else { + myGradleHomeSettingType = LocationSettingType.EXPLICIT_INCORRECT; + myShowBalloonIfNecessary = true; + } + } showBalloonIfNecessary(); } else { @@ -128,12 +142,18 @@ public class GradleProjectSettingsControl extends AbstractExternalProjectSetting } } }; - myUseWrapperButton = new JBRadioButton(GradleBundle.message("gradle.settings.text.use.wrapper"), true); + myUseWrapperButton = new JBRadioButton(GradleBundle.message("gradle.settings.text.use.wrapper")); myUseWrapperButton.addActionListener(listener); myUseLocalDistributionButton = new JBRadioButton(GradleBundle.message("gradle.settings..text.use.local.distribution")); myUseLocalDistributionButton.addActionListener(listener); + + myUseBundledDistributionButton = new JBRadioButton( + GradleBundle.message("gradle.settings.text.use.bundled.distribution", GradleVersion.current().getVersion())); + myUseBundledDistributionButton.addActionListener(listener); + ButtonGroup buttonGroup = new ButtonGroup(); buttonGroup.add(myUseWrapperButton); + buttonGroup.add(myUseBundledDistributionButton); buttonGroup.add(myUseLocalDistributionButton); } @@ -195,14 +215,30 @@ public class GradleProjectSettingsControl extends AbstractExternalProjectSetting new DelayedBalloonInfo(MessageType.ERROR, myGradleHomeSettingType, 0).run(); return GradleBundle.message("gradle.home.setting.type.explicit.incorrect", gradleHomePath); } + settings.setDistributionType(DistributionType.LOCAL); + } else if (myUseWrapperButton.isSelected()) { + settings.setDistributionType(DistributionType.WRAPPED); + } else { + settings.setDistributionType(DistributionType.BUNDLED); } - settings.setPreferLocalInstallationToWrapper(myUseLocalDistributionButton.isSelected()); + return null; } @Override protected boolean isExtraSettingModified() { - if (myUseLocalDistributionButton.isSelected() != getInitialSettings().isPreferLocalInstallationToWrapper()) { + if (myUseBundledDistributionButton.isSelected() && + getInitialSettings().getDistributionType() != DistributionType.BUNDLED) { + return true; + } + + if (myUseWrapperButton.isSelected() && + getInitialSettings().getDistributionType() != DistributionType.WRAPPED) { + return true; + } + + if (myUseLocalDistributionButton.isSelected() && + getInitialSettings().getDistributionType() != DistributionType.LOCAL) { return true; } @@ -233,35 +269,32 @@ public class GradleProjectSettingsControl extends AbstractExternalProjectSetting deduceGradleHomeIfPossible(); } else { - assert gradleHome != null; myGradleHomeSettingType = myInstallationManager.isGradleSdkHome(new File(gradleHome)) ? LocationSettingType.EXPLICIT_CORRECT : LocationSettingType.EXPLICIT_INCORRECT; myAlarm.cancelAllRequests(); - if (myGradleHomeSettingType == LocationSettingType.EXPLICIT_INCORRECT && getInitialSettings().isPreferLocalInstallationToWrapper()) { + if (myGradleHomeSettingType == LocationSettingType.EXPLICIT_INCORRECT && + getInitialSettings().getDistributionType() == DistributionType.LOCAL) { new DelayedBalloonInfo(MessageType.ERROR, myGradleHomeSettingType, 0).run(); } } } public void updateWrapperControls(@Nullable String linkedProjectPath) { - if (linkedProjectPath != null && GradleUtil.isGradleWrapperDefined(linkedProjectPath)) { - myUseWrapperButton.setEnabled(true); - myUseWrapperButton.setText(GradleBundle.message("gradle.settings.text.use.wrapper")); - if (getInitialSettings().isPreferLocalInstallationToWrapper()) { + myUseWrapperButton.setText(GradleBundle.message("gradle.settings.text.use.wrapper")); + switch (getInitialSettings().getDistributionType()) { + case LOCAL: myGradleHomePathField.setEnabled(true); myUseLocalDistributionButton.setSelected(true); - } - else { + break; + case WRAPPED: myGradleHomePathField.setEnabled(false); myUseWrapperButton.setSelected(true); - } - } - else { - myUseWrapperButton.setText(GradleBundle.message("gradle.settings.text.use.wrapper.disabled")); - myUseWrapperButton.setEnabled(false); - myGradleHomePathField.setEnabled(true); - myUseLocalDistributionButton.setSelected(true); + break; + case BUNDLED: + myGradleHomePathField.setEnabled(false); + myUseBundledDistributionButton.setSelected(true); + break; } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java index 721140dde838..22c287ca1d36 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java @@ -114,7 +114,6 @@ public class GradleSystemSettingsControl implements ExternalSystemSettingsContro deduceServiceDirectoryIfPossible(); } else { - assert path != null; myServiceDirectoryPathField.setText(path); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java index 5fa7ca40e7af..2ff5ffbed801 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java @@ -29,6 +29,7 @@ import org.gradle.tooling.ProjectConnection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.service.project.GradleExecutionHelper; +import org.jetbrains.plugins.gradle.settings.DistributionType; import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings; import java.io.File; @@ -50,6 +51,11 @@ public class GradleTaskManager implements ExternalSystemTaskManager<GradleExecut @Nullable final GradleExecutionSettings settings, @Nullable final String vmOptions, @NotNull final ExternalSystemTaskNotificationListener listener) throws ExternalSystemException { + + if(settings != null && settings.getDistributionType() == DistributionType.WRAPPED) { + myHelper.ensureInstalledWrapper(id, projectPath, settings, listener); + } + Function<ProjectConnection, Void> f = new Function<ProjectConnection, Void>() { @Override public Void fun(ProjectConnection connection) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/DistributionType.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/DistributionType.java new file mode 100644 index 000000000000..3540abe23943 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/DistributionType.java @@ -0,0 +1,24 @@ +/* + * 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.settings; + +/** + * @author Vladislav.Soroka + * @since 8/23/13 + */ +public enum DistributionType { + BUNDLED, WRAPPED, LOCAL +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExecutionSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExecutionSettings.java index 71f334db5c70..82cd84cdd682 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExecutionSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExecutionSettings.java @@ -41,18 +41,19 @@ public class GradleExecutionSettings extends ExternalSystemExecutionSettings { @Nullable private final String myDaemonVmOptions; - private final boolean myUseWrapper; + @NotNull final DistributionType myDistributionType; + @Nullable private String wrapperPropertyFile; @Nullable private String myJavaHome; public GradleExecutionSettings(@Nullable String gradleHome, @Nullable String serviceDirectory, - boolean wrapper, + @NotNull DistributionType distributionType, @Nullable String daemonVmOptions) { myGradleHome = gradleHome; myServiceDirectory = serviceDirectory; - myUseWrapper = wrapper; + myDistributionType = distributionType; if (daemonVmOptions != null && !daemonVmOptions.contains("-Xmx")) { daemonVmOptions += String.format(" -Xmx%dm", SystemInfo.is32Bit ? 512 : 1024); } @@ -70,10 +71,6 @@ public class GradleExecutionSettings extends ExternalSystemExecutionSettings { return myServiceDirectory; } - public boolean isUseWrapper() { - return myUseWrapper; - } - @Nullable public String getJavaHome() { return myJavaHome; @@ -100,12 +97,26 @@ public class GradleExecutionSettings extends ExternalSystemExecutionSettings { return myDaemonVmOptions; } + @Nullable + public String getWrapperPropertyFile() { + return wrapperPropertyFile; + } + + public void setWrapperPropertyFile(@Nullable String wrapperPropertyFile) { + this.wrapperPropertyFile = wrapperPropertyFile; + } + + @NotNull + public DistributionType getDistributionType() { + return myDistributionType; + } + @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + (myGradleHome != null ? myGradleHome.hashCode() : 0); result = 31 * result + (myServiceDirectory != null ? myServiceDirectory.hashCode() : 0); - result = 31 * result + (myUseWrapper ? 1 : 0); + result = 31 * result + myDistributionType.hashCode(); result = 31 * result + (myJavaHome != null ? myJavaHome.hashCode() : 0); result = 31 * result + (myDaemonVmOptions == null ? 0 : myDaemonVmOptions.hashCode()); return result; @@ -117,7 +128,7 @@ public class GradleExecutionSettings extends ExternalSystemExecutionSettings { GradleExecutionSettings that = (GradleExecutionSettings)o; - if (myUseWrapper != that.myUseWrapper) return false; + if (myDistributionType != that.myDistributionType) return false; if (!Comparing.equal(myDaemonVmOptions, that.myDaemonVmOptions)) return false; if (myGradleHome != null ? !myGradleHome.equals(that.myGradleHome) : that.myGradleHome != null) return false; if (myJavaHome != null ? !myJavaHome.equals(that.myJavaHome) : that.myJavaHome != null) return false; @@ -130,6 +141,6 @@ public class GradleExecutionSettings extends ExternalSystemExecutionSettings { @Override public String toString() { - return "home: " + myGradleHome + ", use wrapper: " + myUseWrapper; + return "home: " + myGradleHome + ", distributionType: " + myDistributionType; } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java index a254be804b50..6039e6fadc98 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java @@ -26,8 +26,11 @@ import org.jetbrains.annotations.Nullable; public class GradleProjectSettings extends ExternalProjectSettings { @Nullable private String myGradleHome; + @NotNull private DistributionType distributionType; - private boolean myPreferLocalInstallationToWrapper; + public GradleProjectSettings() { + this.distributionType = DistributionType.BUNDLED; + } @Nullable public String getGradleHome() { @@ -38,12 +41,13 @@ public class GradleProjectSettings extends ExternalProjectSettings { myGradleHome = gradleHome; } - public boolean isPreferLocalInstallationToWrapper() { - return myPreferLocalInstallationToWrapper; + @NotNull + public DistributionType getDistributionType() { + return distributionType; } - public void setPreferLocalInstallationToWrapper(boolean preferLocalInstallationToWrapper) { - myPreferLocalInstallationToWrapper = preferLocalInstallationToWrapper; + public void setDistributionType(@NotNull DistributionType distributionType) { + this.distributionType = distributionType; } @NotNull @@ -52,7 +56,7 @@ public class GradleProjectSettings extends ExternalProjectSettings { GradleProjectSettings result = new GradleProjectSettings(); copyTo(result); result.myGradleHome = myGradleHome; - result.myPreferLocalInstallationToWrapper = myPreferLocalInstallationToWrapper; + result.distributionType = distributionType; return result; } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java index a1e530dfb264..655a05f0afbf 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java @@ -121,9 +121,8 @@ public class GradleSettings extends AbstractExternalSystemSettings<GradleSetting if (!Comparing.equal(old.getGradleHome(), current.getGradleHome())) { getPublisher().onGradleHomeChange(old.getGradleHome(), current.getGradleHome(), current.getExternalProjectPath()); } - if (old.isPreferLocalInstallationToWrapper() != current.isPreferLocalInstallationToWrapper()) { - getPublisher().onPreferLocalGradleDistributionToWrapperChange(current.isPreferLocalInstallationToWrapper(), - current.getExternalProjectPath()); + if (old.getDistributionType() != current.getDistributionType()) { + getPublisher().onGradleDistributionTypeChange(current.getDistributionType(), current.getExternalProjectPath()); } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettingsListener.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettingsListener.java index 77b3a333c39b..9b17befca9cd 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettingsListener.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettingsListener.java @@ -29,15 +29,15 @@ public interface GradleSettingsListener extends ExternalSystemSettingsListener<G void onGradleHomeChange(@Nullable String oldPath, @Nullable String newPath, @NotNull String linkedProjectPath); /** - * Is expected to be invoked when 'prefer local gradle distribution to wrapper' setting is changed (generally this + * Is expected to be invoked when 'gradle distribution type' setting is changed (generally this * switches tooling api to different gradle version). * <p/> * <b>Note:</b> this callback is executed <b>after</b> the actual config change. - * + * * @param currentValue current value * @param linkedProjectPath target linked gradle project path */ - void onPreferLocalGradleDistributionToWrapperChange(boolean currentValue, @NotNull String linkedProjectPath); + void onGradleDistributionTypeChange(DistributionType currentValue, @NotNull String linkedProjectPath); /** * Is expected to be invoked when service directory path is changed. diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java index 5e9ccae44555..9808af8a22f6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java @@ -202,18 +202,13 @@ public class GriffonFramework extends MvcFramework { @Override public VirtualFile getSdkRoot(@Nullable Module module) { - if (module == null) return null; - final VirtualFile[] classRoots = ModuleRootManager.getInstance(module).orderEntries().librariesOnly().getClassesRoots(); - for (VirtualFile file : classRoots) { - if (GriffonLibraryPresentationProvider.isGriffonCoreJar(file)) { - final VirtualFile localFile = JarFileSystem.getInstance().getVirtualFileForJar(file); - if (localFile != null) { - final VirtualFile parent = localFile.getParent(); - if (parent != null) { - return parent.getParent(); - } - } - return null; + VirtualFile coreJar = findCoreJar(module); + if (coreJar == null) return null; + + if (GriffonLibraryPresentationProvider.isGriffonCoreJar(coreJar)) { + final VirtualFile parent = coreJar.getParent(); + if (parent != null) { + return parent.getParent(); } } return null; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java index 75686574f06a..a3ccb230688e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java @@ -226,6 +226,20 @@ public abstract class MvcFramework { public abstract String getUserLibraryName(); + @Nullable + protected VirtualFile findCoreJar(@Nullable Module module) { + if (module == null) return null; + + JavaPsiFacade javaFacade = JavaPsiFacade.getInstance(module.getProject()); + PsiClass aClass = javaFacade.findClass(getSomeFrameworkClass(), GlobalSearchScope.moduleWithLibrariesScope(module)); + if (aClass == null) return null; + + VirtualFile virtualFile = aClass.getContainingFile().getVirtualFile(); + if (virtualFile == null || !(virtualFile.getFileSystem() instanceof JarFileSystem)) return null; + + return PathUtil.getLocalFile(virtualFile); + } + protected List<File> getImplicitClasspathRoots(@NotNull Module module) { final List<File> toExclude = new ArrayList<File>(); |