aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java642
1 files changed, 642 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java
new file mode 100644
index 000000000..d3df0584f
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.internal.wizards.exportgradle;
+
+import static com.android.SdkConstants.GRADLE_LATEST_VERSION;
+import static com.android.SdkConstants.GRADLE_PLUGIN_LATEST_VERSION;
+import static com.android.SdkConstants.GRADLE_PLUGIN_NAME;
+import static com.android.tools.lint.checks.GradleDetector.APP_PLUGIN_ID;
+import static com.android.tools.lint.checks.GradleDetector.LIB_PLUGIN_ID;
+
+import com.android.SdkConstants;
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
+import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
+import com.android.ide.eclipse.adt.internal.sdk.Sdk;
+import com.android.ide.eclipse.adt.io.IFolderWrapper;
+import com.android.io.IAbstractFile;
+import com.android.sdklib.io.FileOp;
+import com.android.xml.AndroidManifest;
+import com.google.common.base.Charsets;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+import com.google.common.io.Closeables;
+import com.google.common.io.Files;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Shell;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Creates build.gradle and settings.gradle files for a set of projects.
+ * <p>
+ * Based on {@link org.eclipse.ant.internal.ui.datatransfer.BuildFileCreator}
+ */
+public class BuildFileCreator {
+ static final String BUILD_FILE = "build.gradle"; //$NON-NLS-1$
+ static final String SETTINGS_FILE = "settings.gradle"; //$NON-NLS-1$
+ private static final String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$
+ private static final String GRADLE_WRAPPER_LOCATION =
+ "tools/templates/gradle/wrapper"; //$NON-NLS-1$
+ static final String PLUGIN_CLASSPATH =
+ "classpath '" + GRADLE_PLUGIN_NAME + GRADLE_PLUGIN_LATEST_VERSION + "'"; //$NON-NLS-1$
+ static final String MAVEN_REPOSITORY = "jcenter()"; //$NON-NLS-1$
+
+ private static final String[] GRADLE_WRAPPER_FILES = new String[] {
+ "gradlew", //$NON-NLS-1$
+ "gradlew.bat", //$NON-NLS-1$
+ "gradle/wrapper/gradle-wrapper.jar", //$NON-NLS-1$
+ "gradle/wrapper/gradle-wrapper.properties" //$NON-NLS-1$
+ };
+
+ private static final Comparator<IFile> FILE_COMPARATOR = new Comparator<IFile>() {
+ @Override
+ public int compare(IFile o1, IFile o2) {
+ return o1.toString().compareTo(o2.toString());
+ }
+ };
+
+ private final GradleModule mModule;
+ private final StringBuilder mBuildFile = new StringBuilder();
+
+ /**
+ * Create buildfile for the projects.
+ *
+ * @param shell parent instance for dialogs
+ * @return project names for which buildfiles were created
+ * @throws InterruptedException thrown when user cancels task
+ */
+ public static void createBuildFiles(
+ @NonNull ProjectSetupBuilder builder,
+ @NonNull Shell shell,
+ @NonNull IProgressMonitor pm) {
+
+ File gradleLocation = new File(Sdk.getCurrent().getSdkOsLocation(), GRADLE_WRAPPER_LOCATION);
+ SubMonitor localmonitor = null;
+
+ try {
+ // See if we have a Gradle wrapper in the SDK templates directory. If so, we can copy
+ // it over.
+ boolean hasGradleWrapper = true;
+ for (File wrapperFile : getGradleWrapperFiles(gradleLocation)) {
+ if (!wrapperFile.exists()) {
+ hasGradleWrapper = false;
+ }
+ }
+
+ Collection<GradleModule> modules = builder.getModules();
+ boolean multiModules = modules.size() > 1;
+
+ // determine files to create/change
+ List<IFile> files = new ArrayList<IFile>();
+
+ // add the build.gradle file for all modules.
+ for (GradleModule module : modules) {
+ // build.gradle file
+ IFile file = module.getProject().getFile(BuildFileCreator.BUILD_FILE);
+ files.add(file);
+ }
+
+ // get the commonRoot for all modules. If only one module, this returns the path
+ // of the project.
+ IPath commonRoot = builder.getCommonRoot();
+
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IPath workspaceLocation = workspaceRoot.getLocation();
+
+ IPath relativePath = commonRoot.makeRelativeTo(workspaceLocation);
+ // if makeRelativePath to returns the same path, then commonRoot is not in the
+ // workspace.
+ boolean rootInWorkspace = !relativePath.equals(commonRoot);
+ // we only care if the root is a workspace project. if it's the workspace folder itself,
+ // then the files won't be handled by the workspace.
+ rootInWorkspace = rootInWorkspace && relativePath.segmentCount() > 0;
+
+ File settingsFile = new File(commonRoot.toFile(), SETTINGS_FILE);
+
+ // more than one modules -> generate settings.gradle
+ if (multiModules && rootInWorkspace) {
+
+ // Locate the settings.gradle file and add it to the changed files list
+ IPath settingsGradle = Path.fromOSString(settingsFile.getAbsolutePath());
+
+ // different path, means commonRoot is inside the workspace, which means we have
+ // to add settings.gradle and wrapper files to the list of files to add.
+ IFile iFile = workspaceRoot.getFile(settingsGradle);
+ if (iFile != null) {
+ files.add(iFile);
+ }
+ }
+
+ // Gradle wrapper files
+ if (hasGradleWrapper && rootInWorkspace) {
+ // See if there already wrapper files there and only mark nonexistent ones for
+ // creation.
+ for (File wrapperFile : getGradleWrapperFiles(commonRoot.toFile())) {
+ if (!wrapperFile.exists()) {
+ IPath path = Path.fromOSString(wrapperFile.getAbsolutePath());
+ IFile file = workspaceRoot.getFile(path);
+ files.add(file);
+ }
+ }
+ }
+
+ ExportStatus status = new ExportStatus();
+ builder.setStatus(status);
+
+ // Trigger checkout of changed files
+ Set<IFile> confirmedFiles = validateEdit(files, status, shell);
+
+ if (status.hasError()) {
+ return;
+ }
+
+ // Now iterate over all the modules and generate the build files.
+ localmonitor = SubMonitor.convert(pm, ExportMessages.PageTitle,
+ confirmedFiles.size());
+ List<String> projectSettingsPath = Lists.newArrayList();
+ for (GradleModule currentModule : modules) {
+ IProject moduleProject = currentModule.getProject();
+
+ IFile file = moduleProject.getFile(BuildFileCreator.BUILD_FILE);
+ if (!confirmedFiles.contains(file)) {
+ continue;
+ }
+
+ localmonitor.setTaskName(NLS.bind(ExportMessages.FileStatusMessage,
+ moduleProject.getName()));
+
+ ProjectState projectState = Sdk.getProjectState(moduleProject);
+ BuildFileCreator instance = new BuildFileCreator(currentModule, shell);
+ if (projectState != null) {
+ // This is an Android project
+ if (!multiModules) {
+ instance.appendBuildScript();
+ }
+ instance.appendHeader(projectState.isLibrary());
+ instance.appendDependencies();
+ instance.startAndroidTask(projectState);
+ //instance.appendDefaultConfig();
+ instance.createAndroidSourceSets();
+ instance.finishAndroidTask();
+ } else {
+ // This is a plain Java project
+ instance.appendJavaHeader();
+ instance.createJavaSourceSets();
+ }
+
+ try {
+ // Write the build file
+ String buildfile = instance.mBuildFile.toString();
+ InputStream is =
+ new ByteArrayInputStream(buildfile.getBytes("UTF-8")); //$NON-NLS-1$
+ if (file.exists()) {
+ file.setContents(is, true, true, null);
+ } else {
+ file.create(is, true, null);
+ }
+ } catch (Exception e) {
+ status.addFileStatus(ExportStatus.FileStatus.IO_FAILURE,
+ file.getLocation().toFile());
+ status.setErrorMessage(e.getMessage());
+ return;
+ }
+
+ if (localmonitor.isCanceled()) {
+ return;
+ }
+ localmonitor.worked(1);
+
+ // get the project path to add it to the settings.gradle.
+ projectSettingsPath.add(currentModule.getPath());
+ }
+
+ // write the settings file.
+ if (multiModules) {
+ try {
+ writeGradleSettingsFile(settingsFile, projectSettingsPath);
+ } catch (IOException e) {
+ status.addFileStatus(ExportStatus.FileStatus.IO_FAILURE, settingsFile);
+ status.setErrorMessage(e.getMessage());
+ return;
+ }
+ File mainBuildFile = new File(commonRoot.toFile(), BUILD_FILE);
+ try {
+ writeRootBuildGradle(mainBuildFile);
+ } catch (IOException e) {
+ status.addFileStatus(ExportStatus.FileStatus.IO_FAILURE, mainBuildFile);
+ status.setErrorMessage(e.getMessage());
+ return;
+ }
+ }
+
+ // finally write the wrapper
+ // TODO check we can based on where it is
+ if (hasGradleWrapper) {
+ copyGradleWrapper(gradleLocation, commonRoot.toFile(), status);
+ if (status.hasError()) {
+ return;
+ }
+ }
+
+ } finally {
+ if (localmonitor != null && !localmonitor.isCanceled()) {
+ localmonitor.done();
+ }
+ if (pm != null) {
+ pm.done();
+ }
+ }
+ }
+
+ /**
+ * @param GradleModule create buildfile for this project
+ * @param shell parent instance for dialogs
+ */
+ private BuildFileCreator(GradleModule module, Shell shell) {
+ mModule = module;
+ }
+
+ /**
+ * Return the files that comprise the Gradle wrapper as a collection of {@link File} instances.
+ * @param root
+ * @return
+ */
+ private static List<File> getGradleWrapperFiles(File root) {
+ List<File> files = new ArrayList<File>(GRADLE_WRAPPER_FILES.length);
+ for (String file : GRADLE_WRAPPER_FILES) {
+ files.add(new File(root, file));
+ }
+ return files;
+ }
+
+ /**
+ * Copy the Gradle wrapper files from one directory to another.
+ */
+ private static void copyGradleWrapper(File from, File to, ExportStatus status) {
+ for (String file : GRADLE_WRAPPER_FILES) {
+ File dest = new File(to, file);
+ try {
+ File src = new File(from, file);
+ dest.getParentFile().mkdirs();
+ new FileOp().copyFile(src, dest);
+
+ if (src.getName().equals(GRADLE_PROPERTIES)) {
+ updateGradleDistributionUrl(GRADLE_LATEST_VERSION, dest);
+ }
+ dest.setExecutable(src.canExecute());
+ status.addFileStatus(ExportStatus.FileStatus.OK, dest);
+ } catch (IOException e) {
+ status.addFileStatus(ExportStatus.FileStatus.IO_FAILURE, dest);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Outputs boilerplate buildscript information common to all Gradle build files.
+ */
+ private void appendBuildScript() {
+ appendBuildScript(mBuildFile);
+ }
+
+ /**
+ * Outputs boilerplate header information common to all Gradle build files.
+ */
+ private static void appendBuildScript(StringBuilder builder) {
+ builder.append("buildscript {\n"); //$NON-NLS-1$
+ builder.append(" repositories {\n"); //$NON-NLS-1$
+ builder.append(" " + MAVEN_REPOSITORY + "\n"); //$NON-NLS-1$
+ builder.append(" }\n"); //$NON-NLS-1$
+ builder.append(" dependencies {\n"); //$NON-NLS-1$
+ builder.append(" " + PLUGIN_CLASSPATH + "\n"); //$NON-NLS-1$
+ builder.append(" }\n"); //$NON-NLS-1$
+ builder.append("}\n"); //$NON-NLS-1$
+ }
+
+ /**
+ * Outputs boilerplate header information common to all Gradle build files.
+ */
+ private void appendHeader(boolean isLibrary) {
+ if (isLibrary) {
+ mBuildFile.append("apply plugin: '").append(LIB_PLUGIN_ID).append("'\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ mBuildFile.append("apply plugin: '").append(APP_PLUGIN_ID).append("'\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ mBuildFile.append("\n"); //$NON-NLS-1$
+ }
+
+ /**
+ * Outputs a block which sets up library and project dependencies.
+ */
+ private void appendDependencies() {
+ mBuildFile.append("dependencies {\n"); //$NON-NLS-1$
+
+ // first the local jars.
+ // TODO: Fix
+ mBuildFile.append(" compile fileTree(dir: 'libs', include: '*.jar')\n"); //$NON-NLS-1$
+
+ for (GradleModule dep : mModule.getDependencies()) {
+ mBuildFile.append(" compile project('" + dep.getPath() + "')\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ mBuildFile.append("}\n"); //$NON-NLS-1$
+ mBuildFile.append("\n"); //$NON-NLS-1$
+ }
+
+ /**
+ * Outputs the beginning of an Android task in the build file.
+ */
+ private void startAndroidTask(ProjectState projectState) {
+ int buildApi = projectState.getTarget().getVersion().getApiLevel();
+ String toolsVersion = projectState.getTarget().getBuildToolInfo().getRevision().toString();
+ mBuildFile.append("android {\n"); //$NON-NLS-1$
+ mBuildFile.append(" compileSdkVersion " + buildApi + "\n"); //$NON-NLS-1$
+ mBuildFile.append(" buildToolsVersion \"" + toolsVersion + "\"\n"); //$NON-NLS-1$
+ mBuildFile.append("\n"); //$NON-NLS-1$
+
+ try {
+ IJavaProject javaProject = BaseProjectHelper.getJavaProject(projectState.getProject());
+ // otherwise we check source compatibility
+ String source = javaProject.getOption(JavaCore.COMPILER_SOURCE, true);
+ if (JavaCore.VERSION_1_7.equals(source)) {
+ mBuildFile.append(
+ " compileOptions {\n" + //$NON-NLS-1$
+ " sourceCompatibility JavaVersion.VERSION_1_7\n" + //$NON-NLS-1$
+ " targetCompatibility JavaVersion.VERSION_1_7\n" + //$NON-NLS-1$
+ " }\n" + //$NON-NLS-1$
+ "\n"); //$NON-NLS-1$
+ }
+ } catch (CoreException e) {
+ // Ignore compliance level, go with default
+ }
+ }
+
+ /**
+ * Outputs a sourceSets block to the Android task that locates all of the various source
+ * subdirectories in the project.
+ */
+ private void createAndroidSourceSets() {
+ IFolderWrapper projectFolder = new IFolderWrapper(mModule.getProject());
+ IAbstractFile mManifestFile = AndroidManifest.getManifest(projectFolder);
+ if (mManifestFile == null) {
+ return;
+ }
+ List<String> srcDirs = new ArrayList<String>();
+ for (IClasspathEntry entry : mModule.getJavaProject().readRawClasspath()) {
+ if (entry.getEntryKind() != IClasspathEntry.CPE_SOURCE ||
+ SdkConstants.FD_GEN_SOURCES.equals(entry.getPath().lastSegment())) {
+ continue;
+ }
+ IPath path = entry.getPath().removeFirstSegments(1);
+ srcDirs.add("'" + path.toOSString() + "'"); //$NON-NLS-1$
+ }
+
+ String srcPaths = Joiner.on(",").join(srcDirs);
+
+ mBuildFile.append(" sourceSets {\n"); //$NON-NLS-1$
+ mBuildFile.append(" main {\n"); //$NON-NLS-1$
+ mBuildFile.append(" manifest.srcFile '" + SdkConstants.FN_ANDROID_MANIFEST_XML + "'\n"); //$NON-NLS-1$
+ mBuildFile.append(" java.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
+ mBuildFile.append(" resources.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
+ mBuildFile.append(" aidl.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
+ mBuildFile.append(" renderscript.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
+ mBuildFile.append(" res.srcDirs = ['res']\n"); //$NON-NLS-1$
+ mBuildFile.append(" assets.srcDirs = ['assets']\n"); //$NON-NLS-1$
+ mBuildFile.append(" }\n"); //$NON-NLS-1$
+ mBuildFile.append("\n"); //$NON-NLS-1$
+ mBuildFile.append(" // Move the tests to tests/java, tests/res, etc...\n"); //$NON-NLS-1$
+ mBuildFile.append(" instrumentTest.setRoot('tests')\n"); //$NON-NLS-1$
+ if (srcDirs.contains("'src'")) {
+ mBuildFile.append("\n"); //$NON-NLS-1$
+ mBuildFile.append(" // Move the build types to build-types/<type>\n"); //$NON-NLS-1$
+ mBuildFile.append(" // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...\n"); //$NON-NLS-1$
+ mBuildFile.append(" // This moves them out of them default location under src/<type>/... which would\n"); //$NON-NLS-1$
+ mBuildFile.append(" // conflict with src/ being used by the main source set.\n"); //$NON-NLS-1$
+ mBuildFile.append(" // Adding new build types or product flavors should be accompanied\n"); //$NON-NLS-1$
+ mBuildFile.append(" // by a similar customization.\n"); //$NON-NLS-1$
+ mBuildFile.append(" debug.setRoot('build-types/debug')\n"); //$NON-NLS-1$
+ mBuildFile.append(" release.setRoot('build-types/release')\n"); //$NON-NLS-1$
+ }
+ mBuildFile.append(" }\n"); //$NON-NLS-1$
+ }
+
+ /**
+ * Outputs the completion of the Android task in the build file.
+ */
+ private void finishAndroidTask() {
+ mBuildFile.append("}\n"); //$NON-NLS-1$
+ }
+
+ /**
+ * Outputs a boilerplate header for non-Android projects
+ */
+ private void appendJavaHeader() {
+ mBuildFile.append("apply plugin: 'java'\n"); //$NON-NLS-1$
+ }
+
+ /**
+ * Outputs a sourceSets block for non-Android projects to locate the source directories.
+ */
+ private void createJavaSourceSets() {
+ List<String> dirs = new ArrayList<String>();
+ for (IClasspathEntry entry : mModule.getJavaProject().readRawClasspath()) {
+ if (entry.getEntryKind() != IClasspathEntry.CPE_SOURCE) {
+ continue;
+ }
+ IPath path = entry.getPath().removeFirstSegments(1);
+ dirs.add("'" + path.toOSString() + "'"); //$NON-NLS-1$
+ }
+
+ String srcPaths = Joiner.on(",").join(dirs);
+
+ mBuildFile.append("sourceSets {\n"); //$NON-NLS-1$
+ mBuildFile.append(" main.java.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
+ mBuildFile.append(" main.resources.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
+ mBuildFile.append(" test.java.srcDirs = ['tests/java']\n"); //$NON-NLS-1$
+ mBuildFile.append(" test.resources.srcDirs = ['tests/resources']\n"); //$NON-NLS-1$
+ mBuildFile.append("}\n"); //$NON-NLS-1$
+ }
+
+ /**
+ * Merges the new subproject dependencies into the settings.gradle file if it already exists,
+ * and creates one if it does not.
+ * @throws IOException
+ */
+ private static void writeGradleSettingsFile(File settingsFile, List<String> projectPaths)
+ throws IOException {
+ StringBuilder contents = new StringBuilder();
+ for (String path : projectPaths) {
+ contents.append("include '").append(path).append("'\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ Files.write(contents.toString(), settingsFile, Charsets.UTF_8);
+ }
+
+ private static void writeRootBuildGradle(File buildFile) throws IOException {
+ StringBuilder sb = new StringBuilder(
+ "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n");
+
+ appendBuildScript(sb);
+
+ Files.write(sb.toString(), buildFile, Charsets.UTF_8);
+ }
+
+ /**
+ * Request write access to given files. Depending on the version control
+ * plug-in opens a confirm checkout dialog.
+ *
+ * @param shell
+ * parent instance for dialogs
+ * @return <code>IFile</code> objects for which user confirmed checkout
+ * @throws CoreException
+ * thrown if project is under version control, but not connected
+ */
+ static Set<IFile> validateEdit(
+ @NonNull List<IFile> files,
+ @NonNull ExportStatus exportStatus,
+ @NonNull Shell shell) {
+ Set<IFile> confirmedFiles = new TreeSet<IFile>(FILE_COMPARATOR);
+ if (files.size() == 0) {
+ return confirmedFiles;
+ }
+ IStatus status = (files.get(0)).getWorkspace().validateEdit(
+ files.toArray(new IFile[files.size()]), shell);
+ if (status.isMultiStatus() && status.getChildren().length > 0) {
+ for (int i = 0; i < status.getChildren().length; i++) {
+ IStatus statusChild = status.getChildren()[i];
+ if (statusChild.isOK()) {
+ confirmedFiles.add(files.get(i));
+ } else {
+ exportStatus.addFileStatus(
+ ExportStatus.FileStatus.VCS_FAILURE,
+ files.get(i).getLocation().toFile());
+ }
+ }
+ } else if (status.isOK()) {
+ confirmedFiles.addAll(files);
+ }
+ if (status.getSeverity() == IStatus.ERROR) {
+ // not possible to checkout files: not connected to version
+ // control plugin or hijacked files and made read-only, so
+ // collect error messages provided by validator and re-throw
+ StringBuffer message = new StringBuffer(status.getPlugin() + ": " //$NON-NLS-1$
+ + status.getMessage() + NEWLINE);
+ if (status.isMultiStatus()) {
+ for (int i = 0; i < status.getChildren().length; i++) {
+ IStatus statusChild = status.getChildren()[i];
+ message.append(statusChild.getMessage() + NEWLINE);
+ }
+ }
+ String s = message.toString();
+ exportStatus.setErrorMessage(s);
+ }
+
+ return confirmedFiles;
+ }
+
+ // -------------------------------------------------------------------------------
+ // Fix gradle wrapper version. This code is from GradleUtil in the Studio plugin:
+ // -------------------------------------------------------------------------------
+
+ private static final String GRADLE_PROPERTIES = "gradle-wrapper.properties";
+ private static final String GRADLEW_PROPERTIES_PATH =
+ "gradle" + File.separator + "wrapper" + File.separator + GRADLE_PROPERTIES;
+ private static final String GRADLEW_DISTRIBUTION_URL_PROPERTY_NAME = "distributionUrl";
+
+ @NonNull
+ private static File getGradleWrapperPropertiesFilePath(@NonNull File projectRootDir) {
+ return new File(projectRootDir, GRADLEW_PROPERTIES_PATH);
+ }
+
+ @Nullable
+ public static File findWrapperPropertiesFile(@NonNull File projectRootDir) {
+ File wrapperPropertiesFile = getGradleWrapperPropertiesFilePath(projectRootDir);
+ return wrapperPropertiesFile.isFile() ? wrapperPropertiesFile : null;
+ }
+
+ private static boolean updateGradleDistributionUrl(
+ @NonNull String gradleVersion,
+ @NonNull File propertiesFile) throws IOException {
+ Properties properties = loadGradleWrapperProperties(propertiesFile);
+ String gradleDistributionUrl = getGradleDistributionUrl(gradleVersion, false);
+ String property = properties.getProperty(GRADLEW_DISTRIBUTION_URL_PROPERTY_NAME);
+ if (property != null
+ && (property.equals(gradleDistributionUrl) || property
+ .equals(getGradleDistributionUrl(gradleVersion, true)))) {
+ return false;
+ }
+ properties.setProperty(GRADLEW_DISTRIBUTION_URL_PROPERTY_NAME, gradleDistributionUrl);
+ FileOutputStream out = null;
+ try {
+ out = new FileOutputStream(propertiesFile);
+ properties.store(out, null);
+ return true;
+ } finally {
+ Closeables.close(out, true);
+ }
+ }
+
+ @NonNull
+ private static Properties loadGradleWrapperProperties(@NonNull File propertiesFile)
+ throws IOException {
+ Properties properties = new Properties();
+ FileInputStream fileInputStream = null;
+ try {
+ fileInputStream = new FileInputStream(propertiesFile);
+ properties.load(fileInputStream);
+ return properties;
+ } finally {
+ Closeables.close(fileInputStream, true);
+ }
+ }
+
+ @NonNull
+ private static String getGradleDistributionUrl(@NonNull String gradleVersion,
+ boolean binOnly) {
+ String suffix = binOnly ? "bin" : "all";
+ return String.format("https://services.gradle.org/distributions/gradle-%1$s-" + suffix
+ + ".zip", gradleVersion);
+ }
+}