Package net.flexmojos.oss.plugin.air

Source Code of net.flexmojos.oss.plugin.air.SignAirMojo

/**
* Flexmojos is a set of maven goals to allow maven users to compile, optimize and test Flex SWF, Flex SWC, Air SWF and Air SWC.
* Copyright (C) 2008-2012  Marvin Froeder <marvin@flexmojos.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package net.flexmojos.oss.plugin.air;

import static net.flexmojos.oss.plugin.common.FlexExtension.AIR;
import static net.flexmojos.oss.plugin.common.FlexExtension.SWC;
import static net.flexmojos.oss.plugin.common.FlexExtension.SWF;
import static net.flexmojos.oss.util.PathUtil.file;
import static net.flexmojos.oss.util.PathUtil.path;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.FileSet;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import net.flexmojos.oss.plugin.AbstractMavenMojo;
import net.flexmojos.oss.plugin.air.packager.FlexmojosAIRPackager;
import net.flexmojos.oss.plugin.utilities.FileInterpolationUtil;
import net.flexmojos.oss.util.PathUtil;

import com.adobe.air.Listener;
import com.adobe.air.Message;

/**
* @goal sign-air
* @phase package
* @requiresDependencyResolution compile
* @author Marvin Froeder
*/
public class SignAirMojo
    extends AbstractMavenMojo
{

    private static String TIMESTAMP_NONE = "none";

    /**
     * @parameter default-value="${project.build.directory}/air"
     */
    private File airOutput;

    /**
     * Classifier to add to the artifact generated. If given, the artifact will be an attachment instead.
     *
     * @parameter expression="${flexmojos.classifier}"
     */
    private String classifier;

    /**
     * @parameter default-value="${basedir}/src/main/resources/descriptor.xml"
     * @required
     */
    private File descriptorTemplate;

    /**
     * Ideally Adobe would have used some parseable token, not a huge pass-phrase on the descriptor output. They did
     * prefer to reinvent wheel, so more work to all of us.
     *
     * @parameter expression="${flexmojos.flexbuilderCompatibility}"
     */
    private boolean flexBuilderCompatibility;

    /**
     * Include specified files in AIR package.
     *
     * @parameter
     */
    private List<String> includeFiles;

    /**
     * Include specified files or directories in AIR package.
     *
     * @parameter
     */
    private FileSet[] includeFileSets;

    /**
     * @parameter default-value="${basedir}/src/main/resources/sign.p12"
     */
    private File keystore;

    /**
     * @parameter expression="${project}"
     */
    private MavenProject project;

    /**
     * @component
     * @required
     * @readonly
     */
    protected MavenProjectHelper projectHelper;

    /**
     * @parameter
     * @required
     */
    private String storepass;

    /**
     * The type of keystore, determined by the keystore implementation.
     *
     * @parameter default-value="pkcs12"
     */
    private String storetype;

    /**
     * Strip artifact version during copy of dependencies.
     *
     * @parameter default-value="false"
     */
    private boolean stripVersion;

    /**
     * The URL for the timestamp server. If 'none', no timestamp will be used.
     *
     * @parameter
     */
    private String timestampURL;

    private void addSourceWithPath( FlexmojosAIRPackager packager, File directory, String includePath )
        throws MojoFailureException
    {
        if ( includePath == null )
        {
            throw new MojoFailureException( "Cannot include a null file" );
        }

        // get file from output directory to allow filtered resources
        File includeFile = new File( directory, includePath );
        if ( !includeFile.isFile() )
        {
            throw new MojoFailureException( "Include files only accept files as parameters: " + includePath );
        }

        // don't include the app descriptor or the cert
        if ( path( includeFile ).equals( path( this.descriptorTemplate ) )
            || path( includeFile ).equals( path( this.keystore ) ) )
        {
            return;
        }

        getLog().debug( "  adding source " + includeFile + " with path " + includePath );
        packager.addSourceWithPath( includeFile, includePath );
    }

    private void appendArtifacts( FlexmojosAIRPackager packager, Collection<Artifact> deps )
    {
        for ( Artifact artifact : deps )
        {
            if ( SWF.equals( artifact.getType() ) )
            {
                File source = artifact.getFile();
                String path = source.getName();
                if ( stripVersion && path.contains( artifact.getVersion() ) )
                {
                    path = path.replace( "-" + artifact.getVersion(), "" );
                }
                getLog().debug( "  adding source " + source + " with path " + path );
                packager.addSourceWithPath( source, path );
            }
        }
    }

    protected void doPackage( String packagerName, FlexmojosAIRPackager packager )
        throws MojoExecutionException
    {
        try
        {
            KeyStore keyStore = KeyStore.getInstance( storetype );
            keyStore.load( new FileInputStream( keystore.getAbsolutePath() ), storepass.toCharArray() );
            String alias = keyStore.aliases().nextElement();
            PrivateKey key = (PrivateKey) keyStore.getKey( alias, storepass.toCharArray() );
            packager.setPrivateKey( key );

            String c = this.classifier == null ? "" : "-" + this.classifier;
            File output =
                new File( project.getBuild().getDirectory(), project.getBuild().getFinalName() + c + "." + packagerName );
            packager.setOutput( output );
            packager.setDescriptor( getAirDescriptor() );

            Certificate certificate = keyStore.getCertificate( alias );
            packager.setSignerCertificate( certificate );
            Certificate[] certificateChain = keyStore.getCertificateChain( alias );
            packager.setCertificateChain( certificateChain );
            if ( this.timestampURL != null )
            {
                packager.setTimestampURL( TIMESTAMP_NONE.equals( this.timestampURL ) ? null : this.timestampURL );
            }

            String packaging = project.getPackaging();
            if ( AIR.equals( packaging ) )
            {
                appendArtifacts( packager, project.getDependencyArtifacts() );
                appendArtifacts( packager, project.getAttachedArtifacts() );
            }
            else if ( SWF.equals( packaging ) )
            {
                File source = project.getArtifact().getFile();
                String path = source.getName();
                getLog().debug( "  adding source " + source + " with path " + path );
                packager.addSourceWithPath( source, path );
            }
            else
            {
                throw new MojoFailureException( "Unexpected project packaging " + packaging );
            }

            if ( includeFiles == null && includeFileSets == null )
            {
                includeFileSets = resources.toArray( new FileSet[0] );
            }

            if ( includeFiles != null )
            {
                for ( final String includePath : includeFiles )
                {
                    File directory = file( project.getBuild().getOutputDirectory() );
                    addSourceWithPath( packager, directory, includePath );
                }
            }

            if ( includeFileSets != null )
            {
                for ( FileSet set : includeFileSets )
                {
                    DirectoryScanner scanner;
                    if ( set instanceof Resource )
                    {
                        scanner = scan( (Resource) set );
                    }
                    else
                    {
                        scanner = scan( set );
                    }

                    File directory = file( set.getDirectory(), project.getBasedir() );

                    String[] files = scanner.getIncludedFiles();
                    for ( String path : files )
                    {
                        addSourceWithPath( packager, directory, path );
                    }
                }
            }

            if ( classifier != null )
            {
                projectHelper.attachArtifact( project, packagerName, classifier, output );
            }
            else if ( SWF.equals( packaging ) )
            {
                projectHelper.attachArtifact( project, packagerName, output );
            }
            else
            {
                if ( AIR.equals( packagerName ) && AIR.equals( packaging ) )
                {
                    project.getArtifact().setFile( output );
                }
                else
                {
                    projectHelper.attachArtifact( project, packagerName, output );
                }
            }

            final List<Message> messages = new ArrayList<Message>();

            try
            {
                packager.setListener( new Listener()
                {
                    public void message( final Message message )
                    {
                        messages.add( message );
                    }

                    public void progress( final int soFar, final int total )
                    {
                        getLog().info( "  completed " + soFar + " of " + total );
                    }
                } );
            }
            catch ( NullPointerException e )
            {
                // this is a ridiculous workaround, but I have no means to prevent the NPE nor to check if it will
                // happen on AIR 2.5
                if ( getLog().isDebugEnabled() )
                {
                    getLog().error( e.getMessage() );
                }
            }

            packager.createPackage();

            if ( messages.size() > 0 )
            {
                for ( final Message message : messages )
                {
                    getLog().error( "  " + message.errorDescription );
                }

                throw new MojoExecutionException( "Error creating AIR application" );
            }
            else
            {
                getLog().info( "  AIR package created: " + output.getAbsolutePath() );
            }
        }
        catch ( MojoExecutionException e )
        {
            // do not handle
            throw e;
        }
        catch ( Exception e )
        {
            if ( getLog().isDebugEnabled() )
            {
                getLog().error( e.getMessage(), e );
            }
            throw new MojoExecutionException( "Error invoking AIR api", e );
        }
        finally
        {
            packager.close();
        }
    }

    public void execute()
        throws MojoExecutionException, MojoFailureException
    {
        doPackage( AIR, new FlexmojosAIRPackager() );
    }

    private File getAirDescriptor()
        throws MojoExecutionException
    {
        File output = getOutput();

        String version;
        if ( project.getArtifact().isSnapshot() )
        {
            version =
                project.getVersion().replace( "SNAPSHOT", new SimpleDateFormat( "yyyyMMdd.HHmmss" ).format( new Date() ) );
        }
        else
        {
            version = project.getVersion();
        }

        File dest = new File( airOutput, project.getBuild().getFinalName() + "-descriptor.xml" );
        try
        {
            Map<String, String> props = new HashMap<String, String>();
            props.put( "output", output.getName() );
            props.put( "version", version );

            FileInterpolationUtil.copyFile( descriptorTemplate, dest, props );

            if ( flexBuilderCompatibility )
            {
                // Workaround Flexbuilder/Flashbuilder weirdness
                String str = FileUtils.fileRead( dest );
                str =
                    str.replace( "[This value will be overwritten by Flex Builder in the output app.xml]",
                                 output.getName() );
                str =
                    str.replace( "[This value will be overwritten by Flash Builder in the output app.xml]",
                                 output.getName() );
                FileUtils.fileWrite( PathUtil.path( dest ), str );
            }
        }
        catch ( IOException e )
        {
            throw new MojoExecutionException( "Failed to copy air template", e );
        }

        return dest;
    }

    private File getOutput()
    {
        File output = null;
        if ( project.getPackaging().equals( AIR ) )
        {
            List<Artifact> attach = project.getAttachedArtifacts();
            for ( Artifact artifact : attach )
            {
                if ( SWF.equals( artifact.getType() ) || SWC.equals( artifact.getType() ) )
                {
                    return artifact.getFile();
                }
            }
            Set<Artifact> deps = project.getDependencyArtifacts();
            for ( Artifact artifact : deps )
            {
                if ( SWF.equals( artifact.getType() ) || SWC.equals( artifact.getType() ) )
                {
                    return artifact.getFile();
                }
            }
        }
        else
        {
            output = project.getArtifact().getFile();
        }
        return output;
    }

}
TOP

Related Classes of net.flexmojos.oss.plugin.air.SignAirMojo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.