Search in sources :

Example 11 with AndroidCompilerMessageKind

use of org.jetbrains.android.util.AndroidCompilerMessageKind in project android by JetBrains.

the class AndroidPackagingBuilder method doPackagingForModule.

private static boolean doPackagingForModule(@NotNull CompileContext context, @NotNull JpsModule module, @NotNull AndroidApkBuilderConfigStateStorage apkBuilderConfigStateStorage, @NotNull AndroidPackagingStateStorage packagingStateStorage, boolean release, boolean hasDirtyFiles, @NotNull BuildOutputConsumer outputConsumer) throws IOException {
    final JpsAndroidModuleExtension extension = AndroidJpsUtil.getExtension(module);
    if (extension == null || extension.isLibrary()) {
        return true;
    }
    final String[] resourceRoots = AndroidJpsUtil.toPaths(AndroidJpsUtil.getJavaOutputRootsForModuleAndDependencies(module));
    Arrays.sort(resourceRoots);
    final File moduleOutputDir = ProjectPaths.getModuleOutputDir(module, false);
    if (moduleOutputDir == null) {
        context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, AndroidJpsBundle.message("android.jps.errors.output.dir.not.specified", module.getName())));
        return false;
    }
    final AndroidPlatform platform = AndroidJpsUtil.getAndroidPlatform(module, context, BUILDER_NAME);
    if (platform == null) {
        return false;
    }
    final Set<String> externalJarsSet = new HashSet<String>();
    for (String jarPath : AndroidJpsUtil.getExternalLibraries(context, module, platform)) {
        if (new File(jarPath).exists()) {
            externalJarsSet.add(jarPath);
        }
    }
    final BuildDataPaths dataPaths = context.getProjectDescriptor().dataManager.getDataPaths();
    final File resPackage = AndroidResourcePackagingBuildTarget.getOutputFile(dataPaths, module);
    final File classesDexFile = AndroidDexBuildTarget.getOutputFile(dataPaths, module);
    final String sdkPath = platform.getSdk().getHomePath();
    final String outputPath = AndroidJpsUtil.getApkPath(extension, moduleOutputDir);
    if (outputPath == null) {
        context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, AndroidJpsBundle.message("android.jps.errors.cannot.compute.output.apk", module.getName())));
        return false;
    }
    final String customKeyStorePath = FileUtil.toSystemDependentName(extension.getCustomDebugKeyStorePath());
    final String[] nativeLibDirs = AndroidPackagingBuildTarget.collectNativeLibsFolders(extension, true);
    final String resPackagePath = resPackage.getPath();
    final String classesDexFilePath = classesDexFile.getPath();
    final String[] externalJars = ArrayUtil.toStringArray(externalJarsSet);
    Arrays.sort(externalJars);
    final List<AndroidNativeLibData> additionalNativeLibs = extension.getAdditionalNativeLibs();
    final AndroidApkBuilderConfigState currentApkBuilderConfigState = new AndroidApkBuilderConfigState(outputPath, customKeyStorePath, additionalNativeLibs);
    if (!hasDirtyFiles) {
        final AndroidApkBuilderConfigState savedApkBuilderConfigState = apkBuilderConfigStateStorage.getState(module.getName());
        final AndroidPackagingStateStorage.MyState packagingState = packagingStateStorage.read();
        if (currentApkBuilderConfigState.equalsTo(savedApkBuilderConfigState) && packagingState != null && packagingState.isRelease() == release) {
            return true;
        }
    }
    context.processMessage(new ProgressMessage(AndroidJpsBundle.message("android.jps.progress.packaging", AndroidJpsUtil.getApkName(module))));
    final Map<AndroidCompilerMessageKind, List<String>> messages = AndroidApkBuilder.execute(resPackagePath, classesDexFilePath, resourceRoots, externalJars, nativeLibDirs, additionalNativeLibs, outputPath, release, sdkPath, platform.getTarget(), customKeyStorePath, new MyExcludedSourcesFilter(context.getProjectDescriptor().getProject()));
    if (messages.get(AndroidCompilerMessageKind.ERROR).size() == 0) {
        final List<String> srcFiles = new ArrayList<String>();
        srcFiles.add(resPackagePath);
        srcFiles.add(classesDexFilePath);
        for (String resourceRoot : resourceRoots) {
            FileUtil.processFilesRecursively(new File(resourceRoot), new Processor<File>() {

                @Override
                public boolean process(File file) {
                    if (file.isFile() && AndroidApkBuilder.checkFileForPackaging(file)) {
                        srcFiles.add(file.getPath());
                    }
                    return true;
                }
            });
        }
        Collections.addAll(srcFiles, externalJars);
        for (String nativeLibDir : nativeLibDirs) {
            FileUtil.processFilesRecursively(new File(nativeLibDir), new Processor<File>() {

                @Override
                public boolean process(File file) {
                    if (file.isFile()) {
                        srcFiles.add(file.getPath());
                    }
                    return true;
                }
            });
        }
        outputConsumer.registerOutputFile(new File(outputPath), srcFiles);
    }
    AndroidJpsUtil.addMessages(context, messages, BUILDER_NAME, module.getName());
    final boolean success = messages.get(AndroidCompilerMessageKind.ERROR).isEmpty();
    apkBuilderConfigStateStorage.update(module.getName(), success ? currentApkBuilderConfigState : null);
    packagingStateStorage.saveState(new AndroidPackagingStateStorage.MyState(release));
    return success;
}
Also used : ProgressMessage(org.jetbrains.jps.incremental.messages.ProgressMessage) CompilerMessage(org.jetbrains.jps.incremental.messages.CompilerMessage) AndroidCompilerMessageKind(org.jetbrains.android.util.AndroidCompilerMessageKind) AndroidNativeLibData(org.jetbrains.android.util.AndroidNativeLibData) BuildDataPaths(org.jetbrains.jps.builders.storage.BuildDataPaths) JpsAndroidModuleExtension(org.jetbrains.jps.android.model.JpsAndroidModuleExtension) File(java.io.File) HashSet(com.intellij.util.containers.HashSet)

Example 12 with AndroidCompilerMessageKind

use of org.jetbrains.android.util.AndroidCompilerMessageKind in project android by JetBrains.

the class AndroidApkBuilder method finalPackage.

private static Map<AndroidCompilerMessageKind, List<String>> finalPackage(@NotNull String dexPath, @NotNull String[] javaResourceRoots, @NotNull String[] externalJars, @NotNull String[] nativeLibsFolders, @NotNull String outputApk, @NotNull String apkPath, @Nullable String customKeystorePath, boolean signed, @NotNull Condition<File> resourceFilter) {
    final Map<AndroidCompilerMessageKind, List<String>> result = new HashMap<AndroidCompilerMessageKind, List<String>>();
    result.put(ERROR, new ArrayList<String>());
    result.put(INFORMATION, new ArrayList<String>());
    result.put(WARNING, new ArrayList<String>());
    FileOutputStream fos = null;
    SignedJarBuilder builder = null;
    try {
        String keyStoreOsPath = customKeystorePath != null && customKeystorePath.length() > 0 ? customKeystorePath : DebugKeyProvider.getDefaultKeyStoreOsPath();
        DebugKeyProvider provider = createDebugKeyProvider(result, keyStoreOsPath);
        X509Certificate certificate = signed ? (X509Certificate) provider.getCertificate() : null;
        if (certificate != null && certificate.getNotAfter().compareTo(new Date()) < 0) {
            // generate a new one
            File keyStoreFile = new File(keyStoreOsPath);
            if (keyStoreFile.exists()) {
                keyStoreFile.delete();
            }
            provider = createDebugKeyProvider(result, keyStoreOsPath);
            certificate = (X509Certificate) provider.getCertificate();
        }
        if (certificate != null && certificate.getNotAfter().compareTo(new Date()) < 0) {
            String date = DateFormatUtil.formatPrettyDateTime(certificate.getNotAfter());
            result.get(ERROR).add(("Debug certificate expired on " + date + ". Cannot regenerate it, please delete file \"" + keyStoreOsPath + "\" manually."));
            return result;
        }
        PrivateKey key = provider.getDebugKey();
        if (key == null) {
            result.get(ERROR).add("Cannot create new key or keystore");
            return result;
        }
        if (!new File(apkPath).exists()) {
            result.get(ERROR).add("File " + apkPath + " not found. Try to rebuild project");
            return result;
        }
        File dexEntryFile = new File(dexPath);
        if (!dexEntryFile.exists()) {
            result.get(ERROR).add("File " + dexEntryFile.getPath() + " not found. Try to rebuild project");
            return result;
        }
        for (String externalJar : externalJars) {
            if (new File(externalJar).isDirectory()) {
                result.get(ERROR).add(externalJar + " is directory. Directory libraries are not supported");
            }
        }
        if (result.get(ERROR).size() > 0) {
            return result;
        }
        fos = new FileOutputStream(outputApk);
        builder = new SafeSignedJarBuilder(fos, key, certificate, outputApk);
        FileInputStream fis = new FileInputStream(apkPath);
        try {
            builder.writeZip(fis, null);
        } finally {
            fis.close();
        }
        builder.writeFile(dexEntryFile, AndroidCommonUtils.CLASSES_FILE_NAME);
        final HashSet<String> added = new HashSet<String>();
        for (String resourceRootPath : javaResourceRoots) {
            final HashSet<File> javaResources = new HashSet<File>();
            final File resourceRoot = new File(resourceRootPath);
            collectStandardJavaResources(resourceRoot, javaResources, resourceFilter);
            writeStandardJavaResources(javaResources, resourceRoot, builder, added);
        }
        Set<String> duplicates = new HashSet<String>();
        Set<String> entries = new HashSet<String>();
        for (String externalJar : externalJars) {
            collectDuplicateEntries(externalJar, entries, duplicates);
        }
        for (String duplicate : duplicates) {
            result.get(WARNING).add("Duplicate entry " + duplicate + ". The file won't be added");
        }
        MyResourceFilter filter = new MyResourceFilter(duplicates);
        for (String externalJar : externalJars) {
            fis = new FileInputStream(externalJar);
            try {
                builder.writeZip(fis, filter);
            } finally {
                fis.close();
            }
        }
        final HashSet<String> nativeLibs = new HashSet<String>();
        for (String nativeLibsFolderPath : nativeLibsFolders) {
            final File nativeLibsFolder = new File(nativeLibsFolderPath);
            final File[] children = nativeLibsFolder.listFiles();
            if (children != null) {
                for (File child : children) {
                    writeNativeLibraries(builder, nativeLibsFolder, child, signed, nativeLibs);
                }
            }
        }
    } catch (IOException e) {
        return addExceptionMessage(e, result);
    } catch (CertificateException e) {
        return addExceptionMessage(e, result);
    } catch (DebugKeyProvider.KeytoolException e) {
        return addExceptionMessage(e, result);
    } catch (AndroidLocation.AndroidLocationException e) {
        return addExceptionMessage(e, result);
    } catch (NoSuchAlgorithmException e) {
        return addExceptionMessage(e, result);
    } catch (UnrecoverableEntryException e) {
        return addExceptionMessage(e, result);
    } catch (KeyStoreException e) {
        return addExceptionMessage(e, result);
    } catch (GeneralSecurityException e) {
        return addExceptionMessage(e, result);
    } finally {
        if (builder != null) {
            try {
                builder.close();
            } catch (IOException e) {
                addExceptionMessage(e, result);
            } catch (GeneralSecurityException e) {
                addExceptionMessage(e, result);
            }
        }
        if (fos != null) {
            try {
                fos.close();
            } catch (IOException ignored) {
            }
        }
    }
    return result;
}
Also used : HashMap(com.intellij.util.containers.HashMap) CertificateException(java.security.cert.CertificateException) AndroidCompilerMessageKind(org.jetbrains.android.util.AndroidCompilerMessageKind) DebugKeyProvider(com.android.jarutils.DebugKeyProvider) HashSet(com.intellij.util.containers.HashSet) AndroidLocation(com.android.prefs.AndroidLocation) IOException(java.io.IOException) X509Certificate(java.security.cert.X509Certificate) FileInputStream(java.io.FileInputStream) SignedJarBuilder(com.android.jarutils.SignedJarBuilder) FileOutputStream(java.io.FileOutputStream) File(java.io.File)

Aggregations

AndroidCompilerMessageKind (org.jetbrains.android.util.AndroidCompilerMessageKind)12 File (java.io.File)10 HashMap (com.intellij.util.containers.HashMap)7 CompilerMessage (org.jetbrains.jps.incremental.messages.CompilerMessage)5 ArrayList (java.util.ArrayList)4 List (java.util.List)4 BuildToolInfo (com.android.sdklib.BuildToolInfo)3 HashSet (com.intellij.util.containers.HashSet)3 IOException (java.io.IOException)3 JpsAndroidModuleExtension (org.jetbrains.jps.android.model.JpsAndroidModuleExtension)3 FileUtilRt (com.intellij.openapi.util.io.FileUtilRt)2 AndroidBuildTestingManager (org.jetbrains.android.util.AndroidBuildTestingManager)2 JpsAndroidDexCompilerConfiguration (org.jetbrains.jps.android.model.JpsAndroidDexCompilerConfiguration)2 BuildRootDescriptor (org.jetbrains.jps.builders.BuildRootDescriptor)2 ProgressMessage (org.jetbrains.jps.incremental.messages.ProgressMessage)2 JpsModule (org.jetbrains.jps.model.module.JpsModule)2 DebugKeyProvider (com.android.jarutils.DebugKeyProvider)1 SignedJarBuilder (com.android.jarutils.SignedJarBuilder)1 AndroidLocation (com.android.prefs.AndroidLocation)1 IAndroidTarget (com.android.sdklib.IAndroidTarget)1