1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package android.databinding 17 18import org.gradle.api.DefaultTask; 19import org.gradle.api.artifacts.ResolvedArtifact 20import org.gradle.api.tasks.TaskAction; 21 22class ExportLicensesTask extends DefaultTask { 23 List<ResolvedArtifact> artifacts = new ArrayList(); 24 25 static def knownLicenses = [ 26 [ 27 libraries: ["kotlin-stdlib", "kotlin-runtime", "kotlin-annotation-processing", "kotlin-gradle-plugin", "kotlin-gradle-plugin-api", 28 "kdoc", "kotlin-gradle-plugin-core", "kotlin-jdk-annotations", "kotlin-compiler", "kotlin-compiler-embeddable"], 29 licenses : ["https://raw.githubusercontent.com/JetBrains/kotlin/master/license/LICENSE.txt", 30 "http://www.apache.org/licenses/LICENSE-2.0.txt"], 31 notices : ["https://raw.githubusercontent.com/JetBrains/kotlin/master/license/NOTICE.txt"] 32 ], 33 [ 34 libraries: ["antlr4", "antlr4-runtime", "antlr-runtime", "antlr4-annotations"], 35 licenses : ["https://raw.githubusercontent.com/antlr/antlr4/master/LICENSE.txt"] 36 ], 37 [ 38 libraries: ["antlr"], 39 licenses: ["http://www.antlr3.org/license.html", "http://www.antlr2.org/license.html"] 40 ], 41 [ 42 libraries: ["java.g4"], 43 licenses : ["https://raw.githubusercontent.com/antlr/antlr4/master/LICENSE.txt"] 44 ], 45 [ 46 libraries: ["ST4", "stringtemplate"], 47 licenses : ["https://raw.githubusercontent.com/antlr/stringtemplate4/master/LICENSE.txt"] 48 ], 49 [ 50 libraries: ["org.abego.treelayout.core"], 51 licenses : ["http://treelayout.googlecode.com/files/LICENSE.TXT"] 52 ], 53 [ 54 libraries: ["junit"], 55 licenses : ["https://raw.githubusercontent.com/junit-team/junit/master/LICENSE-junit.txt"], 56 notices : ["https://raw.githubusercontent.com/junit-team/junit/master/NOTICE.txt"] 57 ], 58 [ 59 libraries: ["commons-io"], 60 licenses : ["http://svn.apache.org/viewvc/commons/proper/io/trunk/LICENSE.txt?view=co"], 61 notices : ["http://svn.apache.org/viewvc/commons/proper/io/trunk/NOTICE.txt?view=co"] 62 ], 63 [ 64 libraries: ["commons-codec"], 65 licenses: ["http://svn.apache.org/viewvc/commons/proper/codec/trunk/LICENSE.txt?view=co"], 66 notices: ["http://svn.apache.org/viewvc/commons/proper/codec/trunk/NOTICE.txt?view=co"] 67 ], 68 [ 69 libraries: ["commons-lang3"], 70 licenses : ["https://git-wip-us.apache.org/repos/asf?p=commons-lang.git;a=blob_plain;f=LICENSE.txt;hb=refs/heads/master"], 71 notices : ["https://git-wip-us.apache.org/repos/asf?p=commons-lang.git;a=blob_plain;f=NOTICE.txt;hb=refs/heads/master"] 72 ], 73 [ 74 libraries: ["guava"], 75 licenses : ["http://www.apache.org/licenses/LICENSE-2.0.txt"] 76 ], 77 [ 78 libraries: ["hamcrest-core"], 79 licenses : ["https://raw.githubusercontent.com/hamcrest/JavaHamcrest/master/LICENSE.txt"] 80 ], 81 [ 82 libraries: ["avalon-framework"], 83 licenses : ["http://archive.apache.org/dist/avalon/LICENSE.txt"] 84 ], 85 [ 86 libraries: ["log4j"], 87 licenses: ["https://git-wip-us.apache.org/repos/asf?p=logging-log4j2.git;a=blob_plain;f=LICENSE.txt;hb=HEAD"], 88 notices: ["https://git-wip-us.apache.org/repos/asf?p=logging-log4j2.git;a=blob_plain;f=NOTICE.txt;hb=HEAD"] 89 ], 90 [ 91 libraries: ["ant", "ant-launcher"], 92 licenses: ["http://www.apache.org/licenses/LICENSE-2.0.html"] 93 ], 94 [ 95 libraries: ["xz"], 96 licenses: ["http://git.tukaani.org/?p=xz-java.git;a=blob_plain;f=COPYING;hb=HEAD"] 97 ], 98 [ 99 libraries: ["logkit"], 100 licenseText: ["unknown. see: http://commons.apache.org/proper/commons-logging/dependencies.html"] 101 ], 102 [ 103 libraries: ["juniversalchardet"], 104 licenses: ["https://mozorg.cdn.mozilla.net/media/MPL/1.1/index.0c5913925d40.txt"] 105 ], 106 ] 107 108 Map<String, Object> usedLicenses = new HashMap<>(); 109 static Map<String, Object> licenseLookup = new HashMap<>(); 110 static { 111 knownLicenses.each {license -> 112 license.libraries.each { 113 licenseLookup.put(it, license) 114 } 115 } 116 } 117 118 ExportLicensesTask() { 119 } 120 121 public void add(ResolvedArtifact artifact) { 122 artifacts.add(artifact) 123 println("adding artifact $artifact") 124 } 125 126 @TaskAction 127 public void exportNotice() { 128 project.configurations.compile.getResolvedConfiguration() 129 .getFirstLevelModuleDependencies().each { 130 if (!it.getModuleGroup().equals("com.android.tools.build")) { 131 it.getAllModuleArtifacts().each { add(it) } 132 } 133 } 134 resolveLicenses() 135 def notice = buildNotice(usedLicenses) 136 def noticeFile = new File("${project.projectDir}/src/main/resources",'NOTICE.txt') 137 noticeFile.delete() 138 println ("writing notice file to: ${noticeFile.getAbsolutePath()}") 139 noticeFile << notice 140 } 141 142 public void resolveLicenses() { 143 artifacts.each { artifact -> 144 if (!shouldSkip(artifact)) { 145 def license = licenseLookup.get(artifact.name) 146 if (license == null) { 147 throw new RuntimeException("Cannot find license for ${artifact.getModuleVersion().id} in ${artifact.getFile()}") 148 } 149 usedLicenses.put(artifact, license) 150 } 151 } 152 } 153 154 public static Object findLicenseFor(String artifactId) { 155 return licenseLookup.get(artifactId) 156 } 157 158 public static String urlToText(String url) { 159 return new URL(url).getText() 160 } 161 162 public boolean shouldSkip(ResolvedArtifact artifact) { 163 return artifact.getModuleVersion().id.group.startsWith("com.android"); 164 } 165 166 public static String buildNotice(Map<String, Object> licenses) { 167 // now build the output 168 StringBuilder notice = new StringBuilder(); 169 notice.append("List of 3rd party licenses:") 170 licenses.each { 171 notice.append("\n-----------------------------------------------------------------------------") 172 notice.append("\n* ${it.key}") 173 notice.append("\n") 174 def license = it.value 175 if (license.notices != null) { 176 license.notices.each { 177 notice.append("\n ****** NOTICE:\n${urlToText(it)}") 178 } 179 } 180 license.licenses.each { 181 notice.append("\n ****** LICENSE:\n${urlToText(it)}") 182 } 183 license.licenseText.each { 184 notice.append("\n ****** LICENSE:\n${it}") 185 } 186 notice.append("\n\n\n") 187 } 188 return notice.toString() 189 } 190}