Java tutorial
/* * Copyright (C) 2016 The Android Open Source Project * * 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 com.android.tools.idea.gradle.util; import com.android.SdkConstants; import com.android.tools.idea.templates.TemplateManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import java.io.File; import java.io.IOException; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.android.SdkConstants.*; import static com.android.tools.idea.gradle.util.PropertiesFiles.savePropertiesToFile; import static com.intellij.openapi.util.io.FileUtil.copyDirContent; import static com.intellij.openapi.util.io.FileUtil.join; import static com.intellij.openapi.util.io.FileUtilRt.extensionEquals; import static com.intellij.openapi.vfs.VfsUtil.findFileByIoFile; import static com.intellij.openapi.vfs.VfsUtilCore.pathToUrl; import static org.gradle.wrapper.WrapperExecutor.DISTRIBUTION_URL_PROPERTY; public final class GradleWrapper { @NonNls public static final String GRADLEW_PROPERTIES_PATH = join(FD_GRADLE_WRAPPER, FN_GRADLE_WRAPPER_PROPERTIES); private static final Pattern GRADLE_DISTRIBUTION_URL_PATTERN = Pattern .compile(".*/gradle-([^-]+)(-[^\\/\\\\]+)?-(bin|all).zip"); @NotNull private final File myPropertiesFilePath; @Nullable private final Project myProject; @Nullable public static GradleWrapper find(@NotNull Project project) { String basePath = project.getBasePath(); if (basePath == null) { // Default project. Unlikely to happen. return null; } File baseDir = new File(basePath); File propertiesFilePath = getDefaultPropertiesFilePath(baseDir); return propertiesFilePath.isFile() ? new GradleWrapper(propertiesFilePath, project) : null; } @NotNull public static GradleWrapper get(@NotNull File propertiesFilePath) { return new GradleWrapper(propertiesFilePath, null); } /** * Creates the Gradle wrapper, using the latest supported version of Gradle, in the project at the given directory. * * @param projectPath the project's root directory. * @return an instance of {@code GradleWrapper} if the project already has the wrapper or the wrapper was successfully created; * {@code null} if the wrapper was not created (e.g. the template files for the wrapper were not found.) * @throws IOException any unexpected I/O error. * @see SdkConstants#GRADLE_LATEST_VERSION */ public static GradleWrapper create(@NotNull File projectPath) throws IOException { return create(projectPath, GRADLE_LATEST_VERSION); } /** * Creates the Gradle wrapper in the project at the given directory. * * @param projectPath the project's root directory. * @param gradleVersion the version of Gradle to use. * @return an instance of {@code GradleWrapper} if the project already has the wrapper or the wrapper was successfully created; * {@code null} if the wrapper was not created (e.g. the template files for the wrapper were not found.) * @throws IOException any unexpected I/O error. * @see SdkConstants#GRADLE_LATEST_VERSION */ public static GradleWrapper create(@NotNull File projectPath, @NotNull String gradleVersion) throws IOException { File wrapperFolderPath = new File(projectPath, FD_GRADLE_WRAPPER); if (!wrapperFolderPath.isDirectory()) { File srcFolderPath = new File(TemplateManager.getTemplateRootFolder(), FD_GRADLE_WRAPPER); if (!srcFolderPath.exists()) { for (File root : TemplateManager.getExtraTemplateRootFolders()) { srcFolderPath = new File(root, FD_GRADLE_WRAPPER); if (srcFolderPath.exists()) { break; } else { srcFolderPath = null; } } } if (srcFolderPath == null) { return null; } copyDirContent(srcFolderPath, projectPath); } File propertiesFilePath = getDefaultPropertiesFilePath(projectPath); GradleWrapper gradleWrapper = get(propertiesFilePath); gradleWrapper.updateDistributionUrl(gradleVersion); return gradleWrapper; } private GradleWrapper(@NotNull File propertiesFilePath, @Nullable Project project) { myProject = project; myPropertiesFilePath = propertiesFilePath; } @NotNull public File getPropertiesFilePath() { return myPropertiesFilePath; } @Nullable public VirtualFile getPropertiesFile() { return findFileByIoFile(myPropertiesFilePath, true); } @NotNull public static File getDefaultPropertiesFilePath(@NotNull File projectPath) { return new File(projectPath, GRADLEW_PROPERTIES_PATH); } /** * Updates the 'distributionUrl' in the Gradle wrapper properties file. An unexpected errors that occur while updating the file will be * displayed in an error dialog. * * @param gradleVersion the Gradle version to update the property to. * @return {@code true} if the property was updated, or {@code false} if no update was necessary because the property already had the * correct value. */ public boolean updateDistributionUrlAndDisplayFailure(@NotNull String gradleVersion) { try { boolean updated = updateDistributionUrl(gradleVersion); if (updated) { VirtualFile virtualFile = findFileByIoFile(myPropertiesFilePath, true); if (virtualFile != null) { virtualFile.refresh(false, false); } return true; } } catch (IOException e) { String msg = String.format("Unable to update Gradle wrapper to use Gradle %1$s\n", gradleVersion); msg += e.getMessage(); Messages.showErrorDialog(myProject, msg, "Unexpected Error"); } return false; } /** * Updates the 'distributionUrl' in the given Gradle wrapper properties file. * * @param gradleVersion the Gradle version to update the property to. * @return {@code true} if the property was updated, or {@code false} if no update was necessary because the property already had the * correct value. * @throws IOException if something goes wrong when saving the file. */ public boolean updateDistributionUrl(@NotNull String gradleVersion) throws IOException { Properties properties = getProperties(); String distributionUrl = getDistributionUrl(gradleVersion, false); String property = properties.getProperty(DISTRIBUTION_URL_PROPERTY); if (property != null && (property.equals(distributionUrl) || property.equals(getDistributionUrl(gradleVersion, true)))) { return false; } properties.setProperty(DISTRIBUTION_URL_PROPERTY, distributionUrl); savePropertiesToFile(properties, myPropertiesFilePath, null); return true; } @TestOnly public void updateDistributionUrl(@NotNull File gradleDistribution) throws IOException { String path = gradleDistribution.getPath(); if (!extensionEquals(path, "zip")) { throw new IllegalArgumentException("'" + path + "' should be a zip file"); } Properties properties = getProperties(); properties.setProperty(DISTRIBUTION_URL_PROPERTY, gradleDistribution.toURI().toURL().toString()); savePropertiesToFile(properties, myPropertiesFilePath, null); } @NotNull public Properties getProperties() throws IOException { return PropertiesFiles.getProperties(myPropertiesFilePath); } @Nullable public String getGradleVersion() throws IOException { String url = getProperties().getProperty(DISTRIBUTION_URL_PROPERTY); if (url != null) { Matcher m = GRADLE_DISTRIBUTION_URL_PATTERN.matcher(url); if (m.matches()) { return m.group(1); } } return null; } @NotNull private static String getDistributionUrl(@NotNull String gradleVersion, boolean binOnly) { String suffix = binOnly ? "bin" : "all"; return String.format("https://services.gradle.org/distributions/gradle-%1$s-" + suffix + ".zip", gradleVersion); } }