com.photon.maven.plugins.android.phase09package.ApklibMojo.java Source code

Java tutorial

Introduction

Here is the source code for com.photon.maven.plugins.android.phase09package.ApklibMojo.java

Source

/*
 * ###
 * Android Maven Plugin - android-maven-plugin
 * 
 * Copyright (C) 1999 - 2012 Photon Infotech Inc.
 * 
 * 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.
 * ###
 */
/*
 * Copyright (C) 2009 Jayway AB
 *
 * 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.photon.maven.plugins.android.phase09package;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.jar.JarArchiver;
import org.codehaus.plexus.archiver.util.DefaultFileSet;
import com.photon.phresco.plugin.commons.PluginUtils;
import com.photon.maven.plugins.android.AbstractAndroidMojo;
import com.photon.maven.plugins.android.CommandExecutor;
import com.photon.maven.plugins.android.ExecutionException;

import static com.photon.maven.plugins.android.common.AndroidExtension.APKLIB;

/**
 * Creates the apklib file.<br/>
 * apklib files do not generate deployable artifacts.
 *
 * @goal apklib
 * @phase package
 * @requiresDependencyResolution compile
 */
public class ApklibMojo extends AbstractAndroidMojo {

    public void execute() throws MojoExecutionException, MojoFailureException {
        generateIntermediateAp_();

        CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor();
        executor.setLogger(this.getLog());

        File outputFile = createApkLibraryFile();

        // Set the generated .apklib file as the main artifact (because the pom states <packaging>apklib</packaging>)
        project.getArtifact().setFile(outputFile);
    }

    protected File createApkLibraryFile() throws MojoExecutionException {
        final File apklibrary = new File(project.getBuild().getDirectory(),
                project.getBuild().getFinalName() + "." + APKLIB);
        FileUtils.deleteQuietly(apklibrary);

        try {
            JarArchiver jarArchiver = new JarArchiver();
            jarArchiver.setDestFile(apklibrary);

            jarArchiver.addFile(androidManifestFile, "AndroidManifest.xml");
            addDirectory(jarArchiver, assetsDirectory, "assets");
            addDirectory(jarArchiver, resourceDirectory, "res");
            addDirectory(jarArchiver, sourceDirectory, "src");
            addJavaResources(jarArchiver, project.getBuild().getResources(), "src");

            // Lastly, add any native libraries
            addNativeLibraries(jarArchiver);

            jarArchiver.createArchive();
        } catch (ArchiverException e) {
            throw new MojoExecutionException("ArchiverException while creating ." + APKLIB + " file.", e);
        } catch (IOException e) {
            throw new MojoExecutionException("IOException while creating ." + APKLIB + " file.", e);
        }

        return apklibrary;
    }

    private void addNativeLibraries(final JarArchiver jarArchiver) throws MojoExecutionException {

        try {
            addDirectory(jarArchiver, nativeLibrariesDirectory, "libs");
        } catch (ArchiverException e) {
            throw new MojoExecutionException("IOException while creating ." + APKLIB + " file.", e);
        }
        // TODO: Next is to check for any:
        // TODO: - compiled in (as part of this build) libs
        // TODO:    - That is of course easy if the artifact is indeed attached
        // TODO:    - If not attached, it gets a little trickier  - check the target dir for any compiled .so files (generated by NDK mojo)
        // TODO:        - But where is that directory configured?
    }

    protected void addJavaResources(JarArchiver jarArchiver, List<Resource> javaResources, String prefix)
            throws IOException {
        for (Resource javaResource : javaResources) {
            addJavaResource(jarArchiver, javaResource, prefix);
        }
    }

    /**
     * Adds a Java Resources directory (typically "src/main/resources") to a {@link JarArchiver}.
     *
     * @param jarArchiver
     * @param javaResource The Java resource to add.
     * @param prefix An optional prefix for where in the Jar file the directory's contents should go.
     * @throws ArchiverException
     * @throws java.io.IOException in case the resource path can not be resolved
     */
    protected void addJavaResource(JarArchiver jarArchiver, Resource javaResource, String prefix)
            throws IOException {
        if (javaResource != null) {
            final File javaResourceDirectory = new File(javaResource.getDirectory());
            if (javaResourceDirectory.exists()) {
                final String resourcePath = javaResourceDirectory.getCanonicalPath();
                final String apkLibUnpackBasePath = unpackedApkLibsDirectory.getCanonicalPath();
                // Don't include our dependencies' resource dirs.
                if (!resourcePath.startsWith(apkLibUnpackBasePath)) {
                    final DefaultFileSet javaResourceFileSet = new DefaultFileSet();
                    javaResourceFileSet.setDirectory(javaResourceDirectory);
                    javaResourceFileSet.setPrefix(endWithSlash(prefix));
                    jarArchiver.addFileSet(javaResourceFileSet);
                }
            }
        }
    }

    /**
     * Makes sure the string ends with "/"
     *
     * @param prefix any string, or null.
     * @return the prefix with a "/" at the end, never null.
     */
    protected String endWithSlash(String prefix) {
        prefix = StringUtils.defaultIfEmpty(prefix, "/");
        if (!prefix.endsWith("/")) {
            prefix = prefix + "/";
        }
        return prefix;
    }

    /**
     * Adds a directory to a {@link JarArchiver} with a directory prefix.
     *
     * @param jarArchiver
     * @param directory   The directory to add.
     * @param prefix      An optional prefix for where in the Jar file the directory's contents should go.
     * @throws ArchiverException
     */
    protected void addDirectory(JarArchiver jarArchiver, File directory, String prefix) {
        if (directory != null && directory.exists()) {
            final DefaultFileSet fileSet = new DefaultFileSet();
            fileSet.setPrefix(endWithSlash(prefix));
            fileSet.setDirectory(directory);
            jarArchiver.addFileSet(fileSet);
        }
    }

    /**
     * Generates an intermediate apk file (actually .ap_) containing the resources and assets.
     *
     * @throws MojoExecutionException
     */
    private void generateIntermediateAp_() throws MojoExecutionException {

        CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor();
        executor.setLogger(this.getLog());
        File[] overlayDirectories;

        if (resourceOverlayDirectories == null || resourceOverlayDirectories.length == 0) {
            overlayDirectories = new File[] { resourceOverlayDirectory };
        } else {
            overlayDirectories = resourceOverlayDirectories;
        }

        File androidJar = getAndroidSdk().getAndroidJar();
        File outputFile = new File(project.getBuild().getDirectory(), project.getBuild().getFinalName() + ".ap_");

        List<String> commands = new ArrayList<String>();
        commands.add("package");
        commands.add("-f");
        commands.add("-M");
        commands.add(androidManifestFile.getAbsolutePath());
        for (File resOverlayDir : overlayDirectories) {
            if (resOverlayDir != null && resOverlayDir.exists()) {
                commands.add("-S");
                commands.add(resOverlayDir.getAbsolutePath());
            }
        }
        if (combinedRes.exists()) {
            commands.add("-S");
            commands.add(combinedRes.getAbsolutePath());
        } else {
            if (resourceDirectory.exists()) {
                commands.add("-S");
                commands.add(resourceDirectory.getAbsolutePath());
            }
        }
        for (Artifact apkLibraryArtifact : getRelevantDependencyArtifacts()) {
            if (apkLibraryArtifact.getType().equals(APKLIB)) {
                commands.add("-S");
                commands.add(getLibraryUnpackDirectory(apkLibraryArtifact) + "/res");
            }
        }
        commands.add("--auto-add-overlay");
        if (assetsDirectory.exists()) {
            commands.add("-A");
            commands.add(assetsDirectory.getAbsolutePath());
        }
        if (extractedDependenciesAssets.exists()) {
            commands.add("-A");
            commands.add(extractedDependenciesAssets.getAbsolutePath());
        }
        commands.add("-I");
        commands.add(androidJar.getAbsolutePath());
        commands.add("-F");
        commands.add(outputFile.getAbsolutePath());
        if (StringUtils.isNotBlank(configurations)) {
            commands.add("-c");
            commands.add(configurations);
        }
        getLog().info(getAndroidSdk().getPathForTool("aapt") + " " + commands.toString());
        try {
            executor.executeCommand(getAndroidSdk().getPathForTool("aapt"), commands, project.getBasedir(), false);
        } catch (ExecutionException e) {
            throw new MojoExecutionException("", e);
        }
    }

}