blob: f9429302bc0c34c8febc7db782a05d002ecb8b25 [file] [log] [blame]
/*
* 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.dependency;
import static com.android.SdkConstants.FD_AIDL;
import static com.android.SdkConstants.FD_ASSETS;
import static com.android.SdkConstants.FD_JARS;
import static com.android.SdkConstants.FD_JNI;
import static com.android.SdkConstants.FD_RENDERSCRIPT;
import static com.android.SdkConstants.FD_RES;
import static com.android.SdkConstants.FN_ANDROID_MANIFEST_XML;
import static com.android.SdkConstants.FN_ANNOTATIONS_ZIP;
import static com.android.SdkConstants.FN_CLASSES_JAR;
import static com.android.SdkConstants.FN_LINT_JAR;
import static com.android.SdkConstants.FN_PROGUARD_TXT;
import static com.android.SdkConstants.FN_PUBLIC_TXT;
import static com.android.SdkConstants.FN_RESOURCE_STATIC_LIBRARY;
import static com.android.SdkConstants.FN_RESOURCE_TEXT;
import static com.android.SdkConstants.FN_R_CLASS_JAR;
import static com.android.SdkConstants.FN_SHARED_LIBRARY_ANDROID_MANIFEST_XML;
import android.databinding.tool.DataBindingBuilder;
import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactType;
import com.android.utils.FileUtils;
import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.inject.Inject;
import org.gradle.api.artifacts.transform.ArtifactTransform;
/** Transform that returns the content of an extracted AAR folder. */
public class AarTransform extends ArtifactTransform {
@NonNull private final ArtifactType targetType;
private final boolean sharedLibSupport;
private final boolean autoNamespaceDependencies;
@Inject
public AarTransform(
@NonNull ArtifactType targetType,
boolean sharedLibSupport,
boolean autoNamespaceDependencies) {
this.targetType = targetType;
this.sharedLibSupport = sharedLibSupport;
this.autoNamespaceDependencies = autoNamespaceDependencies;
}
@NonNull
public static ArtifactType[] getTransformTargets() {
// Note that these transform targets come from TYPE_EXPLODED_AAR, which comes from
// TYPE_PROCESSED_AAR (see VariantManager), meaning that the aar has been processed, and
// therefore the jar inside the aar can also be considered processed. However, because a few
// places in the plugin still need to query for JAR instead of PROCESSED_JAR, we need to
// publish JAR instead of PROCESSED_JAR below. (Consequently, the jar may be processed
// twice, but it's probably okay since the ArtifactTransforms are cached.)
return new ArtifactType[] {
// For CLASSES, this transform is ues for runtime, and AarCompileClassesTransform is
// used for compile
ArtifactType.NON_NAMESPACED_CLASSES,
ArtifactType.SHARED_CLASSES,
ArtifactType.JAVA_RES,
ArtifactType.SHARED_JAVA_RES,
ArtifactType.JAR, /* Publish JAR instead of PROCESSED_JAR (see explanation above). */
ArtifactType.MANIFEST,
ArtifactType.NON_NAMESPACED_MANIFEST,
ArtifactType.ANDROID_RES,
ArtifactType.ASSETS,
ArtifactType.SHARED_ASSETS,
ArtifactType.JNI,
ArtifactType.SHARED_JNI,
ArtifactType.AIDL,
ArtifactType.RENDERSCRIPT,
ArtifactType.UNFILTERED_PROGUARD_RULES,
ArtifactType.LINT,
ArtifactType.ANNOTATIONS,
ArtifactType.PUBLIC_RES,
ArtifactType.SYMBOL_LIST,
ArtifactType.DATA_BINDING_ARTIFACT,
ArtifactType.DATA_BINDING_BASE_CLASS_LOG_ARTIFACT,
ArtifactType.COMPILE_ONLY_NAMESPACED_R_CLASS_JAR,
ArtifactType.RES_STATIC_LIBRARY,
ArtifactType.RES_SHARED_STATIC_LIBRARY,
};
}
@Override
@NonNull
public List<File> transform(@NonNull File input) {
switch (targetType) {
case CLASSES:
return (AarTransformUtil.shouldBeAutoNamespaced(input, autoNamespaceDependencies)
|| isShared(input))
? Collections.emptyList()
: AarTransformUtil.getJars(input);
case NON_NAMESPACED_CLASSES:
return AarTransformUtil.shouldBeAutoNamespaced(input, autoNamespaceDependencies)
? AarTransformUtil.getJars(input)
: Collections.emptyList();
case JAVA_RES:
case JAR:
// even though resources are supposed to only be in the main jar of the AAR, this
// is not necessarily enforced by all build systems generating AAR so it's safer to
// read all jars from the manifest.
// For shared libraries, these are provided via SHARED_CLASSES and SHARED_JAVA_RES.
return isShared(input) ? Collections.emptyList() : AarTransformUtil.getJars(input);
case SHARED_CLASSES:
case SHARED_JAVA_RES:
return isShared(input) ? AarTransformUtil.getJars(input) : Collections.emptyList();
case LINT:
return listIfExists(FileUtils.join(input, FD_JARS, FN_LINT_JAR));
case MANIFEST:
if (AarTransformUtil.shouldBeAutoNamespaced(input, autoNamespaceDependencies)) {
return Collections.emptyList();
}
if (isShared(input)) {
// Return both the manifest and the extra snippet for the shared library.
return listIfExists(
Stream.of(
new File(input, FN_ANDROID_MANIFEST_XML),
new File(input, FN_SHARED_LIBRARY_ANDROID_MANIFEST_XML)));
} else {
return listIfExists(new File(input, FN_ANDROID_MANIFEST_XML));
}
case NON_NAMESPACED_MANIFEST:
// Non-namespaced libraries cannot be shared, so if it needs rewriting return only
// the manifest.
return (AarTransformUtil.shouldBeAutoNamespaced(input, autoNamespaceDependencies))
? listIfExists(new File(input, FN_ANDROID_MANIFEST_XML))
: Collections.emptyList();
case ANDROID_RES:
return listIfExists(new File(input, FD_RES));
case ASSETS:
return listIfExists(new File(input, FD_ASSETS));
case JNI:
return listIfExists(new File(input, FD_JNI));
case AIDL:
return listIfExists(new File(input, FD_AIDL));
case RENDERSCRIPT:
return listIfExists(new File(input, FD_RENDERSCRIPT));
case UNFILTERED_PROGUARD_RULES:
List<File> list =
ExtractProGuardRulesTransform.performTransform(
FileUtils.join(input, FD_JARS, FN_CLASSES_JAR),
getOutputDirectory(),
false);
return list.isEmpty() ? listIfExists(new File(input, FN_PROGUARD_TXT)) : list;
case ANNOTATIONS:
return listIfExists(new File(input, FN_ANNOTATIONS_ZIP));
case PUBLIC_RES:
return listIfExists(new File(input, FN_PUBLIC_TXT));
case SYMBOL_LIST:
return listIfExists(new File(input, FN_RESOURCE_TEXT));
case RES_STATIC_LIBRARY:
return isShared(input)
? Collections.emptyList()
: listIfExists(new File(input, FN_RESOURCE_STATIC_LIBRARY));
case RES_SHARED_STATIC_LIBRARY:
return isShared(input)
? listIfExists(
new File(input, SdkConstants.FN_RESOURCE_SHARED_STATIC_LIBRARY))
: Collections.emptyList();
case COMPILE_ONLY_NAMESPACED_R_CLASS_JAR:
return listIfExists(new File(input, FN_R_CLASS_JAR));
case DATA_BINDING_ARTIFACT:
return listIfExists(
new File(input, DataBindingBuilder.DATA_BINDING_ROOT_FOLDER_IN_AAR));
case DATA_BINDING_BASE_CLASS_LOG_ARTIFACT:
return listIfExists(
new File(
input,
DataBindingBuilder.DATA_BINDING_CLASS_LOG_ROOT_FOLDER_IN_AAR));
default:
throw new RuntimeException("Unsupported type in AarTransform: " + targetType);
}
}
private boolean isShared(@NonNull File explodedAar) {
return sharedLibSupport
&& new File(explodedAar, FN_SHARED_LIBRARY_ANDROID_MANIFEST_XML).exists();
}
@NonNull
private static List<File> listIfExists(@NonNull File file) {
return file.exists() ? Collections.singletonList(file) : Collections.emptyList();
}
@NonNull
private static List<File> listIfExists(@NonNull Stream<File> files) {
return files.filter(File::exists).collect(Collectors.toList());
}
}