Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.build.gradle.internal;
import static com.android.SdkConstants.DOT_JAR;
import static com.android.SdkConstants.EXT_ANDROID_PACKAGE;
import static com.android.SdkConstants.EXT_JAR;
import static com.android.build.gradle.internal.TaskManager.DIR_ATOMBUNDLES;
import static com.android.build.gradle.internal.TaskManager.DIR_BUNDLES;
import static com.android.builder.core.BuilderConstants.EXT_ATOMBUNDLE_ARCHIVE;
import static com.android.builder.core.BuilderConstants.EXT_LIB_ARCHIVE;
import static com.android.builder.core.ErrorReporter.EvaluationMode.STANDARD;
import static com.android.builder.model.AndroidProject.FD_INTERMEDIATES;
import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.build.gradle.AndroidGradleOptions;
import com.android.build.gradle.internal.dependency.DependencyGraph;
import com.android.build.gradle.internal.dependency.MutableDependencyDataMap;
import com.android.build.gradle.internal.dependency.VariantDependencies;
import com.android.build.gradle.internal.scope.AndroidTask;
import com.android.build.gradle.internal.tasks.PrepareDependenciesTask;
import com.android.build.gradle.internal.tasks.PrepareLibraryTask;
import com.android.build.gradle.internal.variant.BaseVariantData;
import com.android.build.gradle.internal.variant.BaseVariantOutputData;
import com.android.builder.dependency.MavenCoordinatesImpl;
import com.android.builder.dependency.level2.AndroidDependency;
import com.android.builder.dependency.level2.AtomDependency;
import com.android.builder.dependency.level2.Dependency;
import com.android.builder.dependency.level2.DependencyNode;
import com.android.builder.dependency.level2.DependencyNode.NodeType;
import com.android.builder.dependency.level2.JavaDependency;
import com.android.builder.model.AndroidProject;
import com.android.builder.model.SyncIssue;
import com.android.builder.sdk.SdkLibData;
import com.android.builder.utils.FileCache;
import com.android.sdklib.repository.meta.DetailsTypes;
import com.android.utils.FileUtils;
import com.android.utils.ILogger;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.gradle.api.CircularReferenceException;
import org.gradle.api.DefaultTask;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.artifacts.ResolvedArtifact;
import org.gradle.api.artifacts.SelfResolvingDependency;
import org.gradle.api.artifacts.UnresolvedDependency;
import org.gradle.api.artifacts.component.ComponentIdentifier;
import org.gradle.api.artifacts.component.ComponentSelector;
import org.gradle.api.artifacts.component.ProjectComponentIdentifier;
import org.gradle.api.artifacts.result.DependencyResult;
import org.gradle.api.artifacts.result.ResolvedComponentResult;
import org.gradle.api.artifacts.result.ResolvedDependencyResult;
import org.gradle.api.artifacts.result.UnresolvedDependencyResult;
import org.gradle.api.logging.Logging;
import org.gradle.api.specs.Specs;
import org.gradle.util.GUtil;
/**
* A manager to resolve configuration dependencies.
*/
public class DependencyManager {
private static final boolean DEBUG_DEPENDENCY = false;
public static final String EXPLODED_AAR = "exploded-aar";
private final Project project;
private final ExtraModelInfo extraModelInfo;
private final ILogger logger;
private final SdkHandler sdkHandler;
private SdkLibData sdkLibData = SdkLibData.dontDownload();
private boolean repositoriesUpdated = false;
private final Map prepareLibTaskMap = Maps.newHashMap();
public DependencyManager(
@NonNull Project project,
@NonNull ExtraModelInfo extraModelInfo,
@NonNull SdkHandler sdkHandler) {
this.project = project;
this.extraModelInfo = extraModelInfo;
this.sdkHandler = sdkHandler;
logger = new LoggerWrapper(Logging.getLogger(DependencyManager.class));
}
public void addDependenciesToPrepareTask(
@NonNull TaskFactory tasks,
@NonNull BaseVariantData extends BaseVariantOutputData> variantData,
@NonNull AndroidTask prepareDependenciesTask) {
VariantDependencies variantDeps = variantData.getVariantDependency();
final AndroidTask preBuildTask = variantData.getScope().getPreBuildTask();
final ImmutableList compileLibraries = variantDeps
.getCompileDependencies().getAllAndroidDependencies();
final ImmutableList packageLibraries = variantDeps
.getPackageDependencies().getAllAndroidDependencies();
// gather all the libraries first, then make the task depend on the list in a single
// pass.
List prepareLibraryTasks = Lists
.newArrayListWithCapacity(compileLibraries.size() + packageLibraries.size());
for (AndroidDependency dependency : Iterables.concat(compileLibraries, packageLibraries)) {
// skip sub-module since we don't extract them anymore.
if (dependency.getProjectPath() == null) {
PrepareLibraryTask prepareLibTask = prepareLibTaskMap
.get(dependency.getCoordinates().toString());
if (prepareLibTask != null) {
prepareLibraryTasks.add(prepareLibTask);
prepareLibTask.dependsOn(preBuildTask.getName());
}
}
}
if (!prepareLibraryTasks.isEmpty()) {
prepareDependenciesTask.dependsOn(tasks, prepareLibraryTasks.toArray());
}
}
public Set resolveDependencies(
@NonNull VariantDependencies variantDeps,
@Nullable String testedProjectPath) {
// set of Android Libraries to explode. This only concerns remote libraries, as modules
// are now used through their staging folders rather than their bundled AARs.
// Therefore there is no dependency on these exploded tasks since remote AARs are
// downloaded during the dependency resolution process.
// because they are not immutable (them or the children could be skipped()), we use
// an identity set.
Set libsToExplode = Sets.newIdentityHashSet();
resolveDependencies(
variantDeps,
testedProjectPath,
libsToExplode);
return libsToExplode;
}
public void processLibraries(@NonNull Set libsToExplode) {
for (AndroidDependency lib: libsToExplode) {
maybeCreatePrepareLibraryTask(lib, project);
}
}
/**
* Handles the library and returns a task to "prepare" the library (ie unarchive it). The task
* will be reused for all projects using the same library.
*
* @param library the library.
* @param project the project
* @return the prepare task.
*/
private PrepareLibraryTask maybeCreatePrepareLibraryTask(
@NonNull AndroidDependency library,
@NonNull Project project) {
if (library.isSubModule()) {
throw new RuntimeException("Creating PrepareLib task for submodule: " + library.getCoordinates());
}
// create proper key for the map. library here contains all the dependencies which
// are not relevant for the task (since the task only extract the aar which does not
// include the dependencies.
// However there is a possible case of a rewritten dependencies (with resolution strategy)
// where the aar here could have different dependencies, in which case we would still
// need the same task.
// So we extract a AbstractBundleDependency (no dependencies) from the AndroidDependency to
// make the map key that doesn't take into account the dependencies.
String key = library.getCoordinates().toString();
PrepareLibraryTask prepareLibraryTask = prepareLibTaskMap.get(key);
if (prepareLibraryTask == null) {
String bundleName = GUtil.toCamelCase(library.getName().replaceAll("\\:", " "));
prepareLibraryTask = project.getTasks().create(
"prepare" + bundleName + "Library", PrepareLibraryTask.class);
prepareLibraryTask.setDescription("Prepare " + library.getName());
prepareLibraryTask.setVariantName("");
prepareLibraryTask.init(
library.getArtifactFile(),
library.getExtractedFolder(),
AndroidGradleOptions.getBuildCache(project),
library.getCoordinates());
prepareLibTaskMap.put(key, prepareLibraryTask);
}
return prepareLibraryTask;
}
private void resolveDependencies(
@NonNull final VariantDependencies variantDeps,
@Nullable String testedProjectPath,
@NonNull Set libsToExplodeOut) {
boolean needPackageScope = true;
if (AndroidGradleOptions.buildModelOnly(project)) {
// if we're only syncing (building the model), then we only need the package
// scope if we will actually pass it to the IDE.
Integer modelLevelInt = AndroidGradleOptions.buildModelOnlyVersion(project);
int modelLevel = AndroidProject.MODEL_LEVEL_0_ORIGINAL;
if (modelLevelInt != null) {
modelLevel = modelLevelInt;
}
if (modelLevel > AndroidProject.MODEL_LEVEL_2_DONT_USE) {
needPackageScope = AndroidGradleOptions.buildModelWithFullDependencies(project);
}
}
Configuration compileClasspath = variantDeps.getCompileConfiguration();
Configuration packageClasspath = variantDeps.getPackageConfiguration();
if (DEBUG_DEPENDENCY) {
System.out.println(">>>>>>>>>>");
System.out.println(
project.getName() + ":" +
compileClasspath.getName() + "/" +
packageClasspath.getName());
}
Set currentUnresolvedDependencies = Sets.newHashSet();
// records the artifact we find during package, to detect provided only dependencies.
Set artifactSet = Sets.newHashSet();
// start with package dependencies, record the artifacts
DependencyGraph packagedGraph;
if (needPackageScope) {
packagedGraph = resolveConfiguration(
packageClasspath,
variantDeps,
libsToExplodeOut,
currentUnresolvedDependencies,
testedProjectPath,
artifactSet,
ScopeType.PACKAGE);
} else {
packagedGraph = DependencyGraph.getEmpty();
}
// then the compile dependencies, comparing against the record package dependencies
// to set the provided flag.
// if we have not compute the package scope, we disable the computation of
// provided bits. This disables the checks on impossible provided libs (provided aar in
// apk project).
ScopeType scopeType = needPackageScope ? ScopeType.COMPILE : ScopeType.COMPILE_ONLY;
DependencyGraph compileDependencies = resolveConfiguration(
compileClasspath,
variantDeps,
libsToExplodeOut,
currentUnresolvedDependencies,
testedProjectPath,
artifactSet,
scopeType);
if (extraModelInfo.getMode() != STANDARD &&
compileClasspath.getResolvedConfiguration().hasError()) {
for (String dependency : currentUnresolvedDependencies) {
extraModelInfo.handleSyncError(
dependency,
SyncIssue.TYPE_UNRESOLVED_DEPENDENCY,
String.format(
"Unable to resolve dependency '%s'",
dependency));
}
}
variantDeps.setDependencies(compileDependencies, packagedGraph, needPackageScope);
if (DEBUG_DEPENDENCY) {
System.out.println("*** COMPILE DEPS ***");
/*
for (AndroidLibrary lib : compileDependencies.getAndroidDependencies()) {
System.out.println("LIB: " + lib);
}
for (AndroidAtom atom : compileDependencies.getAtomDependencies()) {
System.out.println("ATOM: " + atom);
}
for (JavaLibrary jar : compileDependencies.getJarDependencies()) {
System.out.println("JAR: " + jar);
}
for (JavaLibrary jar : compileDependencies.getLocalDependencies()) {
System.out.println("LOCAL-JAR: " + jar);
}
System.out.println("*** PACKAGE DEPS ***");
for (AndroidLibrary lib : packagedGraph.getAndroidDependencies()) {
System.out.println("LIB: " + lib);
}
for (JavaLibrary jar : packagedGraph.getJarDependencies()) {
System.out.println("JAR: " + jar);
}
for (JavaLibrary jar : packagedGraph.getLocalDependencies()) {
System.out.println("LOCAL-JAR: " + jar);
}
System.out.println("***");
*/
System.out.println(project.getName() + ":" + compileClasspath.getName() + "/" +packageClasspath.getName());
System.out.println("<<<<<<<<<<");
}
}
enum ScopeType {
PACKAGE,
COMPILE,
COMPILE_ONLY;
}
@NonNull
private DependencyGraph resolveConfiguration(
@NonNull Configuration configuration,
@NonNull final VariantDependencies variantDeps,
@NonNull Set libsToExplodeOut,
@NonNull Set currentUnresolvedDependencies,
@Nullable String testedProjectPath,
@NonNull Set artifactSet,
@NonNull ScopeType scopeType) {
// collect the artifacts first.
Map> artifacts = Maps.newHashMap();
configuration = collectArtifacts(configuration, artifacts);
// keep a map of modules already processed so that we don't go through sections of the
// graph that have been seen elsewhere.
// TODO this is not correct if the requested coordinate is different but keep as is for now
Map> foundNodes = Maps.newHashMap();
// get the graph for the Android and Jar dependencies. This does not include
// local jars.
Map