| package org.jetbrains.jps.android.builder; |
| |
| import com.android.tools.idea.jps.AndroidTargetBuilder; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.openapi.util.io.FileUtilRt; |
| import com.intellij.util.Processor; |
| import com.intellij.util.io.ZipUtil; |
| import org.jetbrains.android.util.AndroidBuildTestingManager; |
| import org.jetbrains.android.util.AndroidCommonUtils; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.jps.android.AndroidJpsBundle; |
| import org.jetbrains.jps.android.AndroidJpsUtil; |
| import org.jetbrains.jps.android.model.JpsAndroidModuleExtension; |
| import org.jetbrains.jps.builders.BuildOutputConsumer; |
| import org.jetbrains.jps.builders.BuildRootDescriptor; |
| import org.jetbrains.jps.builders.DirtyFilesHolder; |
| import org.jetbrains.jps.incremental.CompileContext; |
| import org.jetbrains.jps.incremental.ProjectBuildException; |
| import org.jetbrains.jps.incremental.StopBuildException; |
| import org.jetbrains.jps.incremental.messages.ProgressMessage; |
| import org.jetbrains.jps.model.module.JpsModule; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.jar.JarOutputStream; |
| |
| /** |
| * @author Eugene.Kudelevsky |
| */ |
| public class AndroidAarDepsBuilder extends AndroidTargetBuilder<BuildRootDescriptor, AndroidAarDepsBuildTarget> { |
| @NonNls private static final String BUILDER_NAME = "Android AAR Dependencies Packaging"; |
| |
| public AndroidAarDepsBuilder() { |
| super(Collections.singleton(AndroidAarDepsBuildTarget.MyTargetType.INSTANCE)); |
| } |
| |
| @Override |
| protected void buildTarget(@NotNull AndroidAarDepsBuildTarget target, |
| @NotNull DirtyFilesHolder<BuildRootDescriptor, AndroidAarDepsBuildTarget> holder, |
| @NotNull BuildOutputConsumer outputConsumer, |
| @NotNull CompileContext context) throws ProjectBuildException, IOException { |
| if (!holder.hasDirtyFiles() && !holder.hasRemovedFiles()) { |
| return; |
| } |
| assert !AndroidJpsUtil.isLightBuild(context); |
| |
| if (!doBuild(context, target, outputConsumer)) { |
| throw new StopBuildException(); |
| } |
| } |
| |
| private static boolean doBuild(final CompileContext context, |
| AndroidAarDepsBuildTarget target, |
| BuildOutputConsumer outputConsumer) { |
| final JpsModule module = target.getModule(); |
| final JpsAndroidModuleExtension extension = AndroidJpsUtil.getExtension(module); |
| if (extension == null || extension.isLibrary()) { |
| return true; |
| } |
| |
| File outputDir = AndroidJpsUtil.getDirectoryForIntermediateArtifacts(context, module); |
| outputDir = AndroidJpsUtil.createDirIfNotExist(outputDir, context, BUILDER_NAME); |
| if (outputDir == null) { |
| return false; |
| } |
| final List<String> srcJarFiles = new ArrayList<String>(); |
| |
| for (BuildRootDescriptor descriptor : context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context)) { |
| final File file = descriptor.getRootFile(); |
| |
| if (file.exists()) { |
| srcJarFiles.add(file.getPath()); |
| } |
| } |
| if (srcJarFiles.size() == 0) { |
| return true; |
| } |
| context.processMessage(new ProgressMessage(AndroidJpsBundle.message( |
| "android.jps.progress.aar.dependencies.packaging", module.getName()))); |
| |
| File tempDir = null; |
| |
| try { |
| tempDir = FileUtil.createTempDirectory("extracted_aar_deps", "tmp"); |
| |
| for (int i = srcJarFiles.size() - 1; i >= 0; i--) { |
| ZipUtil.extract(new File(srcJarFiles.get(i)), tempDir, null, true); |
| } |
| final File outputJarFile = new File(outputDir, AndroidCommonUtils.AAR_DEPS_JAR_FILE_NAME); |
| |
| if (!packDirectoryIntoJar(tempDir, outputJarFile, context)) { |
| return false; |
| } |
| final AndroidBuildTestingManager testingManager = AndroidBuildTestingManager.getTestingManager(); |
| |
| if (testingManager != null && outputJarFile.isFile()) { |
| testingManager.getCommandExecutor().checkJarContent("aar_dependencies_package_jar", outputJarFile.getPath()); |
| } |
| outputConsumer.registerOutputFile(outputJarFile, srcJarFiles); |
| return true; |
| } |
| catch (IOException e) { |
| AndroidJpsUtil.reportExceptionError(context, null, e, BUILDER_NAME); |
| return false; |
| } |
| finally { |
| if (tempDir != null) { |
| FileUtil.delete(tempDir); |
| } |
| } |
| } |
| |
| private static boolean packDirectoryIntoJar(final File srcDir, File dstJar, final CompileContext context) throws IOException { |
| final JarOutputStream jos = new JarOutputStream(new FileOutputStream(dstJar)); |
| |
| try { |
| return FileUtil.processFilesRecursively(srcDir, new Processor<File>() { |
| @Override |
| public boolean process(File file) { |
| if (FileUtilRt.extensionEquals(file.getName(), "class")) { |
| final String relPath = FileUtil.getRelativePath(srcDir, file); |
| |
| if (relPath != null) { |
| try { |
| AndroidCommonUtils.packIntoJar(jos, file, relPath); |
| } |
| catch (IOException e) { |
| AndroidJpsUtil.reportExceptionError(context, null, e, BUILDER_NAME); |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| }); |
| } |
| finally { |
| jos.close(); |
| } |
| } |
| |
| @NotNull |
| @Override |
| public String getPresentableName() { |
| return BUILDER_NAME; |
| } |
| } |