| /* |
| * 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); |
| } |
| } |