com.simpligility.maven.plugins.androidndk.common.UnpackedLibHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.simpligility.maven.plugins.androidndk.common.UnpackedLibHelper.java

Source

/*******************************************************************************
 * Copyright (c) 2008, 2011 Sonatype Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Sonatype Inc. - initial API and implementation
 *******************************************************************************/
package com.simpligility.maven.plugins.androidndk.common;

import java.io.File;
import java.io.IOException;

import com.android.SdkConstants;
import com.google.common.io.PatternFilenameFilter;
import org.apache.commons.io.FileUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.UnArchiver;
import org.codehaus.plexus.archiver.zip.ZipUnArchiver;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.console.ConsoleLogger;

/**
 * Provides convenience methods for unpacking Android libraries so that their contents can be used in the build.
 */
public final class UnpackedLibHelper {
    private final ArtifactResolverHelper artifactResolverHelper;
    private final Logger log;

    public static final String AAR_NATIVE_LIBRARIES_FOLDER = "jni";
    public static final String APKLIB_NATIVE_LIBRARIES_FOLDER = "libs";

    // ${project.build.directory}/unpacked-libs
    private final File unpackedLibsDirectory;

    public UnpackedLibHelper(ArtifactResolverHelper artifactResolverHelper, MavenProject project, Logger log,
            File unpackedLibsFolder) {
        this.artifactResolverHelper = artifactResolverHelper;
        if (unpackedLibsFolder != null) {
            // if absolute then use it.
            // if relative then make it relative to the basedir of the project.
            this.unpackedLibsDirectory = unpackedLibsFolder.isAbsolute() ? unpackedLibsFolder
                    : new File(project.getBasedir(), unpackedLibsFolder.getPath());
        } else {
            // If not specified then default to target/unpacked-libs
            final File targetFolder = new File(project.getBuild().getDirectory());
            this.unpackedLibsDirectory = new File(targetFolder, "unpacked-libs");
        }
        this.log = log;
    }

    public void extractApklib(Artifact apklibArtifact) throws MojoExecutionException {
        final File apkLibFile = artifactResolverHelper.resolveArtifactToFile(apklibArtifact);
        if (apkLibFile.isDirectory()) {
            log.warn("The apklib artifact points to '" + apkLibFile
                    + "' which is a directory; skipping unpacking it.");
            return;
        }

        final UnArchiver unArchiver = new ZipUnArchiver(apkLibFile) {
            @Override
            protected Logger getLogger() {
                return new ConsoleLogger(log.getThreshold(), "dependencies-unarchiver");
            }
        };

        final File apklibDirectory = getUnpackedLibFolder(apklibArtifact);
        apklibDirectory.mkdirs();
        unArchiver.setDestDirectory(apklibDirectory);
        log.debug("Extracting APKLIB to " + apklibDirectory);
        try {
            unArchiver.extract();
        } catch (ArchiverException e) {
            throw new MojoExecutionException("ArchiverException while extracting " + apklibDirectory + ". Message: "
                    + e.getLocalizedMessage(), e);
        }
    }

    public void extractAarLib(Artifact aarArtifact) throws MojoExecutionException {
        final File aarFile = artifactResolverHelper.resolveArtifactToFile(aarArtifact);
        if (aarFile.isDirectory()) {
            log.warn("The aar artifact points to '" + aarFile + "' which is a directory; skipping unpacking it.");
            return;
        }

        final UnArchiver unArchiver = new ZipUnArchiver(aarFile) {
            @Override
            protected Logger getLogger() {
                return new ConsoleLogger(log.getThreshold(), "dependencies-unarchiver");
            }
        };

        final File aarDirectory = getUnpackedLibFolder(aarArtifact);
        aarDirectory.mkdirs();
        unArchiver.setDestDirectory(aarDirectory);
        log.debug("Extracting AAR to " + aarDirectory);
        try {
            unArchiver.extract();
        } catch (ArchiverException e) {
            throw new MojoExecutionException("ArchiverException while extracting " + aarDirectory.getAbsolutePath()
                    + ". Message: " + e.getLocalizedMessage(), e);
        }

        // Move native libraries from libs to jni folder for legacy AARs.
        // This ensures backward compatibility with older AARs where libs are in "libs" folder.
        final File jniFolder = new File(aarDirectory, UnpackedLibHelper.AAR_NATIVE_LIBRARIES_FOLDER);
        final File libsFolder = new File(aarDirectory, UnpackedLibHelper.APKLIB_NATIVE_LIBRARIES_FOLDER);
        if (!jniFolder.exists() && libsFolder.isDirectory() && libsFolder.exists()) {
            String[] natives = libsFolder.list(new PatternFilenameFilter("^.*(?<!(?i)\\.jar)$"));
            if (natives.length > 0) {
                log.debug("Moving AAR native libraries from libs to jni folder");
                for (String nativeLibPath : natives) {
                    try {
                        FileUtils.moveToDirectory(new File(libsFolder, nativeLibPath), jniFolder, true);
                    } catch (IOException e) {
                        throw new MojoExecutionException("Could not move native libraries from " + libsFolder, e);
                    }
                }
            }
        }
    }

    public File getArtifactToFile(Artifact artifact) throws MojoExecutionException {
        final File artifactFile = artifactResolverHelper.resolveArtifactToFile(artifact);
        return artifactFile;
    }

    public File getUnpackedLibsFolder() {
        return unpackedLibsDirectory;
    }

    public File getUnpackedLibFolder(Artifact artifact) {
        return new File(unpackedLibsDirectory.getAbsolutePath(), getShortenedGroupId(artifact.getGroupId()) + "_"
                + artifact.getArtifactId() + "_" + artifact.getBaseVersion());
    }

    public File getUnpackedClassesJar(Artifact artifact) {
        return new File(getUnpackedLibFolder(artifact), SdkConstants.FN_CLASSES_JAR);
    }

    public File getUnpackedApkLibSourceFolder(Artifact artifact) {
        return new File(getUnpackedLibFolder(artifact), "src");
    }

    public File getUnpackedLibResourceFolder(Artifact artifact) {
        return new File(getUnpackedLibFolder(artifact), "res");
    }

    public File getUnpackedLibAssetsFolder(Artifact artifact) {
        return new File(getUnpackedLibFolder(artifact), "assets");
    }

    /**
     * @param artifact  Android dependency that is being referenced.
     * @return Folder where the unpacked native libraries are located.
     * @see http://tools.android.com/tech-docs/new-build-system/aar-format
     */
    public File getUnpackedLibNativesFolder(Artifact artifact) {
        if (AndroidExtension.AAR.equals(artifact.getType())) {
            return new File(getUnpackedLibFolder(artifact), UnpackedLibHelper.AAR_NATIVE_LIBRARIES_FOLDER);
        } else {
            return new File(getUnpackedLibFolder(artifact), UnpackedLibHelper.APKLIB_NATIVE_LIBRARIES_FOLDER);
        }
    }

    public File getJarFileForApk(Artifact artifact) {
        final String fileName = artifact.getFile().getName();
        final String modifiedFileName = fileName.substring(0, fileName.lastIndexOf(".")) + ".jar";
        return new File(artifact.getFile().getParentFile(), modifiedFileName);
    }

    /**
     * @param groupId   An a dot separated groupId (eg org.apache.maven)
     * @return A shortened (and potentially non-unique) version of the groupId, that consists of the first letter
     *      of each part of the groupId. Eg oam for org.apache.maven
     */
    private String getShortenedGroupId(String groupId) {
        final String[] parts = groupId.split("\\.");
        final StringBuilder sb = new StringBuilder();
        for (final String part : parts) {
            sb.append(part.charAt(0));
        }
        return sb.toString();
    }

    /**
     * @return True if this project constructs an APK as opposed to an AAR or APKLIB.
     */
    public boolean isAPKBuild(MavenProject project) {
        return AndroidExtension.APK.equals(project.getPackaging());
    }
}