| /* |
| * Copyright (C) 2017 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.lint.checks |
| |
| import com.android.tools.lint.detector.api.Project |
| import com.android.tools.lint.model.LintModelDependency |
| import java.util.ArrayDeque |
| |
| /** |
| * This class finds blacklisted dependencies in a project by looking |
| * transitively |
| */ |
| class BlacklistedDeps(val project: Project) { |
| |
| private var map: MutableMap<String, List<LintModelDependency>>? = null |
| |
| init { |
| // TODO: Should skip provided |
| project.buildVariant?.mainArtifact?.dependencies?.compileDependencies?.let { |
| visitLibraries(ArrayDeque(), it.roots) |
| } |
| } |
| |
| /** |
| * Returns the path from this dependency to one of the blacklisted dependencies, |
| * or null if this dependency is not blacklisted. If [remove] is true, the |
| * dependency is removed from the map after this. |
| */ |
| fun checkDependency(groupId: String, artifactId: String, remove: Boolean): List<LintModelDependency>? { |
| val map = this.map ?: return null |
| val coordinate = "$groupId:$artifactId" |
| val path = map[coordinate] ?: return null |
| if (remove) { |
| map.remove(coordinate) |
| } |
| return path |
| } |
| |
| /** |
| * Returns all the dependencies found in this project that lead to a |
| * blacklisted dependency. Each list is a list from the root dependency |
| * to the blacklisted dependency. |
| */ |
| fun getBlacklistedDependencies(): List<List<LintModelDependency>> { |
| val map = this.map ?: return emptyList() |
| return map.values.toMutableList().sortedBy { it[0].artifactName } |
| } |
| |
| private fun visitLibraries( |
| stack: ArrayDeque<LintModelDependency>, |
| libraries: List<LintModelDependency> |
| ) { |
| for (library in libraries) { |
| visitLibrary(stack, library) |
| } |
| } |
| |
| private fun visitLibrary(stack: ArrayDeque<LintModelDependency>, library: LintModelDependency) { |
| stack.addLast(library) |
| checkLibrary(stack, library) |
| visitLibraries(stack, library.dependencies) |
| stack.removeLast() |
| } |
| |
| private fun checkLibrary(stack: ArrayDeque<LintModelDependency>, library: LintModelDependency) { |
| if (isBlacklistedDependency(library.artifactName)) { |
| if (map == null) { |
| map = HashMap() |
| } |
| val root = stack.first.artifactName |
| map?.put(root, ArrayList(stack)) |
| } |
| } |
| |
| private fun isBlacklistedDependency(mavenName: String): Boolean { |
| when (mavenName) { |
| // org.apache.http.* |
| "org.apache.httpcomponents:httpclient", |
| |
| // org.xmlpull.v1.* |
| "xpp3:xpp3", |
| |
| // org.apache.commons.logging |
| "commons-logging:commons-logging", |
| |
| // org.xml.sax.*, org.w3c.dom.* |
| "xerces:xmlParserAPIs", |
| |
| // org.json.* |
| "org.json:json", |
| |
| // javax.microedition.khronos.* |
| "org.khronos:opengl-api", |
| |
| // all of the above |
| "com.google.android:android" -> return true |
| else -> return false |
| } |
| } |
| } |