1 package com.simpligility.maven.plugins.android.standalonemojos;
2
3 import com.simpligility.maven.plugins.android.AbstractAndroidMojo;
4 import com.simpligility.maven.plugins.android.CommandExecutor;
5 import com.simpligility.maven.plugins.android.ExecutionException;
6 import com.simpligility.maven.plugins.android.config.ConfigHandler;
7 import com.simpligility.maven.plugins.android.config.ConfigPojo;
8 import com.simpligility.maven.plugins.android.config.PullParameter;
9 import com.simpligility.maven.plugins.android.configuration.Zipalign;
10
11 import org.apache.commons.io.FilenameUtils;
12 import org.apache.maven.plugin.MojoExecutionException;
13 import org.apache.maven.plugin.MojoFailureException;
14 import org.apache.maven.plugins.annotations.Mojo;
15 import org.apache.maven.plugins.annotations.Parameter;
16 import org.codehaus.plexus.util.FileUtils;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import static com.simpligility.maven.plugins.android.common.AndroidExtension.APK;
24
25
26
27
28
29
30
31 @Mojo( name = "zipalign" )
32 public class ZipalignMojo extends AbstractAndroidMojo
33 {
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 @Parameter
53 @ConfigPojo
54 private Zipalign zipalign;
55
56
57
58
59
60 @Parameter( property = "android.zipalign.skip" )
61 private Boolean zipalignSkip;
62
63 @PullParameter( defaultValue = "true" )
64 private Boolean parsedSkip;
65
66
67
68
69
70 @Parameter( property = "android.zipalign.verbose" )
71 private Boolean zipalignVerbose;
72
73 @PullParameter( defaultValue = "false" )
74 private Boolean parsedVerbose;
75
76
77
78
79
80
81
82 @Parameter( property = "android.zipalign.inputApk" )
83 private String zipalignInputApk;
84
85 @PullParameter ( defaultValueGetterMethod = "getInputApkPath" )
86 private String parsedInputApk;
87
88
89
90
91
92
93
94 @Parameter( property = "android.zipalign.outputApk" )
95 private String zipalignOutputApk;
96
97 @PullParameter( defaultValueGetterMethod = "getOutputApkPath" )
98 private String parsedOutputApk;
99
100
101
102
103 private File apkFile;
104
105
106
107 private File alignedApkFile;
108
109
110
111
112 @Parameter ( property = "android.zipalign.classifier" )
113 private String zipalignClassifier;
114
115 @PullParameter( defaultValue = "aligned" )
116 private String parsedClassifier;
117
118
119
120
121
122
123 public void execute() throws MojoExecutionException, MojoFailureException
124 {
125
126
127
128 if ( ! SUPPORTED_PACKAGING_TYPES.contains( project.getPackaging() ) )
129 {
130 getLog().info( "Skipping zipalign on " + project.getPackaging() );
131 return;
132 }
133
134 ConfigHandler configHandler = new ConfigHandler( this, this.session, this.execution );
135 configHandler.parseConfiguration();
136
137 parsedInputApk = FilenameUtils.separatorsToSystem( parsedInputApk );
138 parsedOutputApk = FilenameUtils.separatorsToSystem( parsedOutputApk );
139
140 getLog().debug( "skip:" + parsedSkip );
141 getLog().debug( "verbose:" + parsedVerbose );
142 getLog().debug( "inputApk:" + parsedInputApk );
143 getLog().debug( "outputApk:" + parsedOutputApk );
144 getLog().debug( "classifier:" + parsedClassifier );
145
146 if ( parsedSkip )
147 {
148 getLog().info( "Skipping zipalign" );
149 }
150 else
151 {
152 boolean outputToSameFile = sameOutputAsInput();
153
154 CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor();
155 executor.setLogger( this.getLog() );
156
157 String command = getAndroidSdk().getZipalignPath();
158
159 List<String> parameters = new ArrayList<String>();
160 if ( parsedVerbose )
161 {
162 parameters.add( "-v" );
163 }
164 parameters.add( "-f" );
165 parameters.add( "4" );
166 parameters.add( parsedInputApk );
167 String outputApk = outputToSameFile ? getTemporaryOutputApkFilename() : parsedOutputApk;
168 parameters.add( outputApk );
169
170 try
171 {
172 getLog().info( "Running command: " + command );
173 getLog().info( "with parameters: " + parameters );
174 executor.setCaptureStdOut( true );
175 executor.executeCommand( command, parameters );
176
177 if ( FileUtils.fileExists( outputApk ) )
178 {
179 if ( outputToSameFile )
180 {
181
182 try
183 {
184 FileUtils.rename( new File( outputApk ), new File( parsedInputApk ) );
185 }
186 catch ( IOException e )
187 {
188 getLog().error( "Failed to replace original apk with aligned "
189 + getFullPathWithName( outputApk ), e );
190 }
191 }
192 else
193 {
194
195
196 projectHelper.attachArtifact( project, APK, parsedClassifier, new File( outputApk ) );
197 getLog().info( "Attach " + getFullPathWithName( outputApk ) + " as '"
198 + parsedClassifier + "' to the project" );
199 }
200 }
201 else
202 {
203 getLog().error( "Cannot attach " + getFullPathWithName( outputApk ) + " to the project"
204 + " - The file does not exist" );
205 }
206 }
207 catch ( ExecutionException e )
208 {
209 throw new MojoExecutionException( "", e );
210 }
211 }
212 }
213
214 private String getFullPathWithName( String filename )
215 {
216 return FilenameUtils.getFullPath( filename ) + FilenameUtils.getName( filename );
217 }
218
219 private boolean sameOutputAsInput()
220 {
221 return getFullPathWithName( parsedInputApk ).equals( getFullPathWithName( parsedOutputApk ) );
222 }
223
224
225 private String getTemporaryOutputApkFilename()
226 {
227 return parsedOutputApk.substring( 0, parsedOutputApk.lastIndexOf( '.' ) ) + "-aligned-temp.apk";
228 }
229
230
231
232
233
234
235
236 private String getInputApkPath()
237 {
238 if ( apkFile == null )
239 {
240 apkFile = new File( targetDirectory, finalName + "." + APK );
241 }
242 return apkFile.getAbsolutePath();
243 }
244
245
246
247
248
249
250
251
252 private String getOutputApkPath()
253 {
254 if ( alignedApkFile == null )
255 {
256 alignedApkFile = new File( targetDirectory,
257 finalName + "-aligned." + APK );
258 }
259 return alignedApkFile.getAbsolutePath();
260 }
261 }