All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.android.build.api.transform.Transform Maven / Gradle / Ivy

There is a newer version: 2.3.0
Show newest version
/*
 * Copyright (C) 2015 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.api.transform;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.build.api.transform.QualifiedContent.ContentType;
import com.android.build.api.transform.QualifiedContent.Scope;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

/**
 * A Transform that processes intermediary build artifacts.
 * 

* For each added transform, a new task is created. The action of adding a transform takes * care of handling dependencies between the tasks. This is done based on what the transform * processes. The output of the transform becomes consumable by other transforms and these * tasks get automatically linked together. *

* The Transform indicates what it applies to (content, scope) and what it generates (content). *

* A transform receives input as a collection {@link TransformInput}, which is composed of * {@link JarInput}s and {@link DirectoryInput}s. * Both provide information about the {@link Scope}s and {@link ContentType}s associated with their * particular content. *

* The output is handled by {@link TransformOutputProvider} which allows creating new self-contained * content, each associated with their own Scopes and Content Types. * The content handled by TransformInput/Output is managed by the transform system, and their * location is not configurable. *

* It is best practice to write into as many outputs as Jar/Folder Inputs have been received by the * transform. Combining all the inputs into a single output prevents downstream transform from * processing limited scopes. *

* While it's possible to differentiate different Content Types by file extension, it's not possible * to do so for Scopes. Therefore if a transform request a Scope but the only available Output * contains more than the requested Scope, the build will fail.
* If a transform request a single content type but the only available content includes more than * the requested type, the input file/folder will contain all the files of all the types, but * the transform should only read, process and output the type(s) it requested. * *

* Additionally, a transform can indicate secondary inputs/outputs. These are not handled by * upstream or downstream transforms, and are not restricted by type handled by transform. They can * be anything. * It's up to each transform to manage where these files are, and to make sure that these files * are generated before the transform is called. This is done through additional parameters * when register the transform. *

These secondary inputs/outputs allow a transform to read but not process any content. This * can be achieved by having {@link #getScopes()} return an empty list and use * {@link #getReferencedScopes()} to indicate what to read instead. * *

* This API is non final and is subject to change. We are looking for feedback, and will * attempt to stabilize it in the 1.6 time frame. */ @Beta @SuppressWarnings("MethodMayBeStatic") public abstract class Transform { /** * Returns the unique name of the transform. * *

* This is associated with the type of work that the transform does. It does not have to be * unique per variant. */ @NonNull public abstract String getName(); /** * Returns the type(s) of data that is consumed by the Transform. This may be more than * one type. * * This must be of type {@link QualifiedContent.DefaultContentType} */ @NonNull public abstract Set getInputTypes(); /** * Returns the type(s) of data that is generated by the Transform. This may be more than * one type. * *

* The default implementation returns {@link #getInputTypes()}. *

* This must be of type {@link QualifiedContent.DefaultContentType} */ @NonNull public Set getOutputTypes() { return getInputTypes(); } /** * Returns the scope(s) of the Transform. This indicates which scopes the transform consumes. */ @NonNull public abstract Set getScopes(); /** * Returns the referenced scope(s) for the Transform. These scopes are not consumed by * the Transform. They are provided as inputs, but are still available as inputs for * other Transforms to consume. * *

* The default implementation returns an empty Set. */ @NonNull public Set getReferencedScopes() { return ImmutableSet.of(); } /** * Returns a list of additional file(s) that this Transform needs to run. Preferably, use * {@link #getSecondaryFiles()} API which allow eah secondary file to indicate if changes * can be handled incrementally or not. This API will treat all additional file change as * a non incremental event. * *

* Changes to files returned in this list will trigger a new execution of the Transform * even if the qualified-content inputs haven't been touched. *

* Any changes to these files will trigger a non incremental execution. * *

* The default implementation returns an empty collection. * @deprecated */ @Deprecated @NonNull public Collection getSecondaryFileInputs() { return ImmutableList.of(); } /** * Returns a list of additional file(s) that this Transform needs to run. * *

* Changes to files returned in this list will trigger a new execution of the Transform * even if the qualified-content inputs haven't been touched. *

* Each secondary input has the ability to be declared as necessitating a non incremental * execution in case of change. This Transform can therefore declare which secondary file * changes it supports in incremental mode. * *

* The default implementation returns an empty collection. * * @return */ @NonNull public Collection getSecondaryFiles() { return ImmutableList.of(); } /** * Returns a list of additional (out of streams) file(s) that this Transform creates. * *

* These File instances can only represent files, not directories. For directories, use * {@link #getSecondaryDirectoryOutputs()} * *

* Changes to files returned in this list will trigger a new execution of the Transform * even if the qualified-content inputs haven't been touched. *

* Changes to these output files force a non incremental execution. * *

* The default implementation returns an empty collection. */ @NonNull public Collection getSecondaryFileOutputs() { return ImmutableList.of(); } /** * Returns a list of additional (out of streams) directory(ies) that this Transform creates. * *

* These File instances can only represent directories. For files, use * {@link #getSecondaryFileOutputs()} * *

* Changes to directories returned in this list will trigger a new execution of the Transform * even if the qualified-content inputs haven't been touched. *

* Changes to these output directories force a non incremental execution. * *

* The default implementation returns an empty collection. */ @NonNull public Collection getSecondaryDirectoryOutputs() { return ImmutableList.of(); } /** * Returns a map of non-file input parameters using a unique identifier as the map key. * *

* Changes to values returned in this map will trigger a new execution of the Transform * even if the content inputs haven't been touched. *

* Changes to these values force a non incremental execution. * *

* The default implementation returns an empty Map. */ @NonNull public Map getParameterInputs() { return ImmutableMap.of(); } /** * Returns whether the Transform can perform incremental work. * *

* If it does, then the TransformInput may contain a list of changed/removed/added files, unless * something else triggers a non incremental run. */ public abstract boolean isIncremental(); /** * @deprecated */ @Deprecated public void transform( @NonNull Context context, @NonNull Collection inputs, @NonNull Collection referencedInputs, @Nullable TransformOutputProvider outputProvider, boolean isIncremental) throws IOException, TransformException, InterruptedException { } /** * Executes the Transform. * *

* The inputs are packaged as an instance of {@link TransformInvocation} *

    *
  • The inputs collection of {@link TransformInput}. These are the inputs * that are consumed by this Transform. A transformed version of these inputs must * be written into the output. What is received is controlled through * {@link #getInputTypes()}, and {@link #getScopes()}.
  • *
  • The referencedInputs collection of {@link TransformInput}. This is * for reference only and should be not be transformed. What is received is controlled * through {@link #getReferencedScopes()}.
  • *
* * A transform that does not want to consume anything but instead just wants to see the content * of some inputs should return an empty set in {@link #getScopes()}, and what it wants to * see in {@link #getReferencedScopes()}. * *

* Even though a transform's {@link Transform#isIncremental()} returns true, this method may * be receive false in isIncremental. This can be due to *

    *
  • a change in secondary files ({@link #getSecondaryFiles()}, * {@link #getSecondaryFileOutputs()}, {@link #getSecondaryDirectoryOutputs()})
  • *
  • a change to a non file input ({@link #getParameterInputs()})
  • *
  • an unexpected change to the output files/directories. This should not happen unless * tasks are improperly configured and clobber each other's output.
  • *
  • a file deletion that the transform mechanism could not match to a previous input. * This should not happen in most case, except in some cases where dependencies have * changed.
  • *
* In such an event, when isIncremental is false, the inputs will not have any * incremental change information: *
    *
  • {@link JarInput#getStatus()} will return {@link Status#NOTCHANGED} even though * the file may be added/changed.
  • *
  • {@link DirectoryInput#getChangedFiles()} will return an empty map even though * some files may be added/changed.
  • *
* * @param transformInvocation the invocation object containing the transform inputs. * @throws IOException if an IO error occurs. * @throws InterruptedException * @throws TransformException Generic exception encapsulating the cause. */ public void transform(@NonNull TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException { transform(transformInvocation.getContext(), transformInvocation.getInputs(), transformInvocation.getReferencedInputs(), transformInvocation.getOutputProvider(), transformInvocation.isIncremental()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy