1 package com.simpligility.maven.plugins.android.standalonemojos;
2
3 import com.simpligility.maven.plugins.android.AbstractAndroidMojo;
4 import com.simpligility.maven.plugins.android.common.AndroidExtension;
5 import com.simpligility.maven.plugins.android.common.XmlHelper;
6 import com.simpligility.maven.plugins.android.configuration.Manifest;
7 import com.simpligility.maven.plugins.android.configuration.UsesSdk;
8 import com.simpligility.maven.plugins.android.configuration.VersionGenerator;
9
10 import org.apache.commons.io.IOUtils;
11 import org.apache.commons.lang3.BooleanUtils;
12 import org.apache.commons.lang3.StringUtils;
13 import org.apache.commons.lang3.math.NumberUtils;
14 import org.apache.maven.plugin.MojoExecutionException;
15 import org.apache.maven.plugin.MojoFailureException;
16 import org.apache.maven.plugins.annotations.LifecyclePhase;
17 import org.apache.maven.plugins.annotations.Mojo;
18 import org.apache.maven.plugins.annotations.Parameter;
19 import org.w3c.dom.Attr;
20 import org.w3c.dom.Document;
21 import org.w3c.dom.Element;
22 import org.w3c.dom.Node;
23 import org.w3c.dom.NodeList;
24 import org.xml.sax.SAXException;
25
26 import javax.xml.parsers.DocumentBuilder;
27 import javax.xml.parsers.DocumentBuilderFactory;
28 import javax.xml.parsers.ParserConfigurationException;
29 import javax.xml.transform.OutputKeys;
30 import javax.xml.transform.Result;
31 import javax.xml.transform.Source;
32 import javax.xml.transform.Transformer;
33 import javax.xml.transform.TransformerException;
34 import javax.xml.transform.TransformerFactory;
35 import javax.xml.transform.dom.DOMSource;
36 import javax.xml.transform.stream.StreamResult;
37
38 import java.io.File;
39 import java.io.FileOutputStream;
40 import java.io.IOException;
41 import java.io.OutputStreamWriter;
42 import java.util.ArrayList;
43 import java.util.HashSet;
44 import java.util.List;
45 import java.util.Properties;
46
47
48
49
50
51
52
53
54
55
56 @Deprecated
57 @Mojo( name = "manifest-update", defaultPhase = LifecyclePhase.PROCESS_RESOURCES )
58 public class ManifestUpdateMojo extends AbstractAndroidMojo
59 {
60
61 private static final String ATTR_VERSION_NAME = "android:versionName";
62 private static final String ATTR_VERSION_CODE = "android:versionCode";
63 private static final String ATTR_SHARED_USER_ID = "android:sharedUserId";
64 private static final String ATTR_DEBUGGABLE = "android:debuggable";
65
66
67 private static final String ATTR_SCREEN_DENSITY = "android:screenDensity";
68 private static final String ATTR_SCREEN_SIZE = "android:screenSize";
69
70
71 private static final String ATTR_ANY_DENSITY = "android:anyDensity";
72 private static final String ATTR_SMALL_SCREENS = "android:smallScreens";
73 private static final String ATTR_NORMAL_SCREENS = "android:normalScreens";
74 private static final String ATTR_LARGE_SCREENS = "android:largeScreens";
75 private static final String ATTR_XLARGE_SCREENS = "android:xlargeScreens";
76 private static final String ATTR_RESIZEABLE = "android:resizeable";
77 private static final String ATTR_REQUIRES_SMALLEST_WIDTH_DP = "android:requiresSmallestWidthDp";
78 private static final String ATTR_LARGEST_WIDTH_LIMIT_DP = "android:largestWidthLimitDp";
79 private static final String ATTR_COMPATIBLE_WIDTH_LIMIT_DP = "android:compatibleWidthLimitDp";
80
81
82 private static final String ATTR_MIN_SDK_VERSION = "android:minSdkVersion";
83 private static final String ATTR_MAX_SDK_VERSION = "android:maxSdkVersion";
84 private static final String ATTR_TARGET_SDK_VERSION = "android:targetSdkVersion";
85
86
87 private static final String ATTR_NAME = "android:name";
88 private static final String ATTR_AUTHORITIES = "android:authorities";
89
90 private static final String ATTR_APPLICATION_ICON = "android:icon";
91 private static final String ATTR_APPLICATION_LABEL = "android:label";
92 private static final String ATTR_APPLICATION_THEME = "android:theme";
93
94 private static final String ELEM_APPLICATION = "application";
95 private static final String ELEM_PROVIDER = "provider";
96 private static final String ELEM_SUPPORTS_SCREENS = "supports-screens";
97 private static final String ELEM_COMPATIBLE_SCREENS = "compatible-screens";
98 private static final String ELEM_SCREEN = "screen";
99 private static final String ELEM_USES_SDK = "uses-sdk";
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168 @Parameter
169 private Manifest manifest;
170
171
172
173
174
175
176 @Parameter( property = "android.manifest.versionName", defaultValue = "${project.version}" )
177 protected String manifestVersionName;
178
179
180
181
182
183 @Parameter( property = "android.manifest.versionCode" )
184 protected Integer manifestVersionCode;
185
186
187
188
189
190
191 @Parameter( property = "android.manifest.versionCodeAutoIncrement", defaultValue = "false" )
192 private Boolean manifestVersionCodeAutoIncrement = false;
193
194
195
196
197
198 @Parameter( property = "android.manifest.applicationIcon" )
199 private String manifestApplicationIcon;
200
201
202
203
204
205 @Parameter( property = "android.manifest.applicationLabel" )
206 private String manifestApplicationLabel;
207
208
209
210
211
212 @Parameter( property = "android.manifest.applicationTheme" )
213 private String manifestApplicationTheme;
214
215
216
217
218
219
220
221
222
223
224
225
226
227 @Parameter( property = "android.manifest.versionCodeUpdateFromVersion", defaultValue = "false" )
228 protected Boolean manifestVersionCodeUpdateFromVersion = false;
229
230
231
232
233
234 @Parameter( property = "android.manifest.sharedUserId" )
235 protected String manifestSharedUserId;
236
237
238
239
240
241 @Parameter( property = "android.manifest.debuggable" )
242 protected Boolean manifestDebuggable;
243
244
245
246
247
248 @Parameter( property = "android.manifest.providerAuthorities" )
249 protected Properties manifestProviderAuthorities;
250
251 protected SupportsScreens manifestSupportsScreens;
252
253 protected List<CompatibleScreen> manifestCompatibleScreens;
254
255
256
257
258
259 protected UsesSdk manifestUsesSdk;
260
261 private String parsedVersionName;
262 private Integer parsedVersionCode;
263 private boolean parsedVersionCodeAutoIncrement;
264 private String parsedApplicationIcon;
265 private String parsedApplicationLabel;
266 private String parsedApplicationTheme;
267 private Boolean parsedVersionCodeUpdateFromVersion;
268 private String parsedSharedUserId;
269 private Boolean parsedDebuggable;
270 private SupportsScreens parsedSupportsScreens;
271 private List<CompatibleScreen> parsedCompatibleScreens;
272 private Properties parsedProviderAuthorities;
273 private UsesSdk parsedUsesSdk;
274
275
276
277
278
279 public void execute() throws MojoExecutionException, MojoFailureException
280 {
281 if ( ! AndroidExtension.isAndroidPackaging( project.getPackaging() ) )
282 {
283 return;
284 }
285
286 if ( destinationManifestFile == null )
287 {
288 return;
289 }
290
291 parseConfiguration();
292
293 getLog().info( "Attempting to update manifest " + destinationManifestFile );
294 getLog().debug( " usesSdk=" + parsedUsesSdk );
295 getLog().debug( " versionName=" + parsedVersionName );
296 getLog().debug( " versionCode=" + parsedVersionCode );
297 getLog().debug( " versionCodeAutoIncrement=" + parsedVersionCodeAutoIncrement );
298 getLog().debug( " versionCodeUpdateFromVersion=" + parsedVersionCodeUpdateFromVersion );
299
300 getLog().debug( " applicationIcon=" + parsedApplicationIcon );
301 getLog().debug( " applicationLabel=" + parsedApplicationLabel );
302 getLog().debug( " applicationTheme=" + parsedApplicationTheme );
303
304 getLog().debug( " sharedUserId=" + parsedSharedUserId );
305 getLog().debug( " debuggable=" + parsedDebuggable );
306 getLog().debug( " providerAuthorities: " + parsedProviderAuthorities );
307 getLog().debug( " supports-screens: " + ( parsedSupportsScreens == null ? "not set" : "set" ) );
308 getLog().debug( " compatible-screens: " + ( parsedCompatibleScreens == null ? "not set" : "set" ) );
309
310 if ( ! destinationManifestFile.exists() )
311 {
312 return;
313 }
314
315 try
316 {
317 updateManifest( destinationManifestFile );
318 }
319 catch ( IOException e )
320 {
321 throw new MojoFailureException( "XML I/O error: " + destinationManifestFile, e );
322 }
323 catch ( ParserConfigurationException e )
324 {
325 throw new MojoFailureException( "Unable to prepare XML parser", e );
326 }
327 catch ( SAXException e )
328 {
329 throw new MojoFailureException( "Unable to parse XML: " + destinationManifestFile, e );
330 }
331 catch ( TransformerException e )
332 {
333 throw new MojoFailureException( "Unable write XML: " + destinationManifestFile, e );
334 }
335 }
336
337 private void parseConfiguration()
338 {
339
340 if ( manifest != null )
341 {
342 if ( StringUtils.isNotEmpty( manifest.getVersionName() ) )
343 {
344 parsedVersionName = manifest.getVersionName();
345 }
346 else
347 {
348 parsedVersionName = manifestVersionName;
349 }
350 if ( manifest.getVersionCode() != null )
351 {
352 parsedVersionCode = manifest.getVersionCode();
353 }
354 else
355 {
356 parsedVersionCode = manifestVersionCode;
357 }
358 if ( manifest.getVersionCodeAutoIncrement() != null )
359 {
360 parsedVersionCodeAutoIncrement = manifest.getVersionCodeAutoIncrement();
361 }
362 else
363 {
364 parsedVersionCodeAutoIncrement = manifestVersionCodeAutoIncrement;
365 }
366 if ( manifest.getVersionCodeUpdateFromVersion() != null )
367 {
368 parsedVersionCodeUpdateFromVersion = manifest.getVersionCodeUpdateFromVersion();
369 }
370 else
371 {
372 parsedVersionCodeUpdateFromVersion = manifestVersionCodeUpdateFromVersion;
373 }
374
375 if ( StringUtils.isNotEmpty( manifest.getApplicationIcon() ) )
376 {
377 parsedApplicationIcon = manifest.getApplicationIcon();
378 }
379 else
380 {
381 parsedApplicationIcon = manifestApplicationIcon;
382 }
383
384 if ( StringUtils.isNotEmpty( manifest.getApplicationLabel() ) )
385 {
386 parsedApplicationLabel = manifest.getApplicationLabel();
387 }
388 else
389 {
390 parsedApplicationLabel = manifestApplicationLabel;
391 }
392
393 if ( StringUtils.isNotEmpty( manifest.getApplicationTheme() ) )
394 {
395 parsedApplicationTheme = manifest.getApplicationTheme();
396 }
397 else
398 {
399 parsedApplicationTheme = manifestApplicationTheme;
400 }
401
402
403 if ( StringUtils.isNotEmpty( manifest.getSharedUserId() ) )
404 {
405 parsedSharedUserId = manifest.getSharedUserId();
406 }
407 else
408 {
409 parsedSharedUserId = manifestSharedUserId;
410 }
411 if ( manifest.getDebuggable() != null )
412 {
413 parsedDebuggable = manifest.getDebuggable();
414 }
415 else
416 {
417 parsedDebuggable = manifestDebuggable;
418 }
419 if ( manifest.getSupportsScreens() != null )
420 {
421 parsedSupportsScreens = manifest.getSupportsScreens();
422 }
423 else
424 {
425 parsedSupportsScreens = manifestSupportsScreens;
426 }
427 if ( manifest.getCompatibleScreens() != null )
428 {
429 parsedCompatibleScreens = manifest.getCompatibleScreens();
430 }
431 else
432 {
433 parsedCompatibleScreens = manifestCompatibleScreens;
434 }
435 if ( manifest.getProviderAuthorities() != null )
436 {
437 parsedProviderAuthorities = manifest.getProviderAuthorities();
438 }
439 else
440 {
441 parsedProviderAuthorities = manifestProviderAuthorities;
442 }
443 if ( manifest.getUsesSdk() != null )
444 {
445 parsedUsesSdk = manifest.getUsesSdk();
446 }
447 else
448 {
449 parsedUsesSdk = manifestUsesSdk;
450 }
451 }
452 else
453 {
454 parsedVersionName = manifestVersionName;
455 parsedVersionCode = manifestVersionCode;
456 parsedVersionCodeAutoIncrement = manifestVersionCodeAutoIncrement;
457 parsedVersionCodeUpdateFromVersion = manifestVersionCodeUpdateFromVersion;
458 parsedApplicationIcon = manifestApplicationIcon;
459 parsedApplicationLabel = manifestApplicationLabel;
460 parsedApplicationTheme = manifestApplicationTheme;
461 parsedSharedUserId = manifestSharedUserId;
462 parsedDebuggable = manifestDebuggable;
463 parsedSupportsScreens = manifestSupportsScreens;
464 parsedCompatibleScreens = manifestCompatibleScreens;
465 parsedProviderAuthorities = manifestProviderAuthorities;
466 parsedUsesSdk = manifestUsesSdk;
467 }
468 }
469
470
471
472
473 private Document readManifest( File manifestFile ) throws IOException, ParserConfigurationException, SAXException
474 {
475 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
476 DocumentBuilder db = dbf.newDocumentBuilder();
477 Document doc = db.parse( manifestFile );
478 return doc;
479 }
480
481
482
483
484 private void writeManifest( File manifestFile, Document doc ) throws IOException, TransformerException
485 {
486 TransformerFactory xfactory = TransformerFactory.newInstance();
487 Transformer xformer = xfactory.newTransformer();
488 xformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "yes" );
489 Source source = new DOMSource( doc );
490
491 OutputStreamWriter writer = null;
492 try
493 {
494 manifestFile.getParentFile().mkdirs();
495
496 String encoding = doc.getXmlEncoding() != null ? doc.getXmlEncoding() : "UTF-8";
497 writer = new OutputStreamWriter( new FileOutputStream( manifestFile, false ), encoding );
498 if ( doc.getXmlEncoding() != null && doc.getXmlVersion() != null )
499 {
500 String xmldecl = String
501 .format( "<?xml version=\"%s\" encoding=\"%s\"?>%n", doc.getXmlVersion(), doc.getXmlEncoding() );
502 writer.write( xmldecl );
503 }
504 Result result = new StreamResult( writer );
505
506 xformer.transform( source, result );
507 }
508 finally
509 {
510 IOUtils.closeQuietly( writer );
511 }
512 }
513
514
515
516
517
518
519
520
521
522
523
524 public void updateManifest( File manifestFile )
525 throws IOException, ParserConfigurationException, SAXException, TransformerException,
526 MojoFailureException, MojoExecutionException
527 {
528 Document doc = readManifest( manifestFile );
529 Element manifestElement = doc.getDocumentElement();
530 boolean dirty = false;
531
532 if ( StringUtils.isEmpty( parsedVersionName ) )
533 {
534 parsedVersionName = project.getVersion();
535 }
536 Attr versionNameAttrib = manifestElement.getAttributeNode( ATTR_VERSION_NAME );
537 if ( versionNameAttrib == null || ! StringUtils.equals( parsedVersionName, versionNameAttrib.getValue() ) )
538 {
539 getLog().info( "Setting " + ATTR_VERSION_NAME + " to " + parsedVersionName );
540 manifestElement.setAttribute( ATTR_VERSION_NAME, parsedVersionName );
541 dirty = true;
542 }
543 if ( ( parsedVersionCodeAutoIncrement && parsedVersionCode != null )
544 || ( parsedVersionCodeUpdateFromVersion && parsedVersionCode != null )
545 || ( parsedVersionCodeAutoIncrement && parsedVersionCodeUpdateFromVersion ) )
546 {
547 throw new MojoFailureException( "versionCodeAutoIncrement, versionCodeUpdateFromVersion and versionCode "
548 + "are mutual exclusive. They cannot be specified at the same time. Please specify either "
549 + "versionCodeAutoIncrement, versionCodeUpdateFromVersion or versionCode!" );
550 }
551 exportProperties();
552 if ( parsedVersionCodeAutoIncrement )
553 {
554 performVersioCodeAutoIncrement( manifestElement );
555 dirty = true;
556 }
557 if ( parsedVersionCodeUpdateFromVersion )
558 {
559 performVersionCodeUpdateFromVersion( manifestElement );
560 dirty = true;
561 }
562 if ( parsedVersionCode != null )
563 {
564 Attr versionCodeAttr = manifestElement.getAttributeNode( ATTR_VERSION_CODE );
565 int currentVersionCode = 0;
566 if ( versionCodeAttr != null )
567 {
568 currentVersionCode = NumberUtils.toInt( versionCodeAttr.getValue(), 0 );
569 }
570 if ( currentVersionCode != parsedVersionCode )
571 {
572 getLog().info( "Setting " + ATTR_VERSION_CODE + " to " + parsedVersionCode );
573 manifestElement.setAttribute( ATTR_VERSION_CODE, String.valueOf( parsedVersionCode ) );
574 dirty = true;
575 }
576 project.getProperties().setProperty( "android.manifest.versionCode", String.valueOf( parsedVersionCode ) );
577 }
578 if ( !StringUtils.isEmpty( parsedApplicationIcon ) )
579 {
580 dirty = updateApplicationAttribute( manifestElement, ATTR_APPLICATION_ICON, parsedApplicationIcon, dirty );
581 project.getProperties()
582 .setProperty( "android.manifest.applicationIcon", String.valueOf( parsedApplicationIcon ) );
583 }
584
585 if ( ! StringUtils.isEmpty( parsedApplicationLabel ) )
586 {
587 dirty =
588 updateApplicationAttribute( manifestElement, ATTR_APPLICATION_LABEL, parsedApplicationLabel, dirty );
589 project.getProperties()
590 .setProperty( "android.manifest.applicationLabel", String.valueOf( parsedApplicationLabel ) );
591 }
592
593 if ( ! StringUtils.isEmpty( parsedApplicationTheme ) )
594 {
595 dirty =
596 updateApplicationAttribute( manifestElement, ATTR_APPLICATION_THEME, parsedApplicationTheme, dirty );
597 project.getProperties()
598 .setProperty( "android.manifest.applicationTheme", String.valueOf( parsedApplicationTheme ) );
599 }
600
601 if ( ! StringUtils.isEmpty( parsedSharedUserId ) )
602 {
603 Attr sharedUserIdAttrib = manifestElement.getAttributeNode( ATTR_SHARED_USER_ID );
604
605 if ( sharedUserIdAttrib == null || ! StringUtils
606 .equals( parsedSharedUserId, sharedUserIdAttrib.getValue() ) )
607 {
608 getLog().info( "Setting " + ATTR_SHARED_USER_ID + " to " + parsedSharedUserId );
609 manifestElement.setAttribute( ATTR_SHARED_USER_ID, parsedSharedUserId );
610 dirty = true;
611 }
612 }
613
614 if ( parsedDebuggable != null )
615 {
616 NodeList appElems = manifestElement.getElementsByTagName( ELEM_APPLICATION );
617
618
619 for ( int i = 0; i < appElems.getLength(); ++ i )
620 {
621 Node node = appElems.item( i );
622 getLog().info( "Testing if node " + node.getNodeName() + " is application" );
623 if ( node.getNodeType() == Node.ELEMENT_NODE )
624 {
625 Element element = ( Element ) node;
626 Attr debuggableAttrib = element.getAttributeNode( ATTR_DEBUGGABLE );
627 if ( debuggableAttrib == null || parsedDebuggable != BooleanUtils
628 .toBoolean( debuggableAttrib.getValue() ) )
629 {
630 getLog().info( "Setting " + ATTR_DEBUGGABLE + " to " + parsedDebuggable );
631 element.setAttribute( ATTR_DEBUGGABLE, String.valueOf( parsedDebuggable ) );
632 dirty = true;
633 }
634 }
635 }
636 }
637
638 if ( parsedSupportsScreens != null )
639 {
640 boolean madeDirty = performSupportScreenModification( doc, manifestElement );
641 if ( madeDirty )
642 {
643 dirty = true;
644 }
645 }
646
647 if ( parsedCompatibleScreens != null )
648 {
649 getLog().info( "Setting " + ELEM_COMPATIBLE_SCREENS );
650 updateCompatibleScreens( doc, manifestElement );
651 dirty = true;
652 }
653
654 dirty = processProviderAuthorities( manifestElement, dirty );
655 dirty = processUsesSdk( doc, manifestElement, dirty );
656
657 if ( dirty )
658 {
659 if ( manifestFile.exists() && ! manifestFile.delete() )
660 {
661 getLog().warn( "Could not remove old " + manifestFile );
662 }
663 getLog().info( "Made changes to manifest file, updating " + manifestFile );
664 writeManifest( manifestFile, doc );
665 }
666 else
667 {
668 getLog().info( "No changes found to write to manifest file" );
669 }
670 }
671
672 private boolean processProviderAuthorities( Element manifestElement, boolean dirty )
673 {
674 if ( parsedProviderAuthorities != null )
675 {
676 boolean madeDirty = updateProviderAuthorities( manifestElement );
677 if ( madeDirty )
678 {
679 dirty = true;
680 }
681 }
682 return dirty;
683 }
684
685 private boolean processUsesSdk( Document doc, Element manifestElement, boolean dirty )
686 {
687 if ( parsedUsesSdk != null )
688 {
689 boolean madeDirty = performUsesSdkModification( doc, manifestElement );
690 if ( madeDirty )
691 {
692 dirty = true;
693 }
694 }
695 return dirty;
696 }
697
698 private boolean updateApplicationAttribute( Element manifestElement,
699 String attribute, String value, boolean dirty )
700 {
701 NodeList appElements =
702 manifestElement.getElementsByTagName( ELEM_APPLICATION );
703
704
705 for ( int i = 0; i < appElements.getLength(); ++i )
706 {
707 Node node = appElements.item( i );
708 getLog().info( "Testing if node " + node.getNodeName()
709 + " is application" );
710 if ( node.getNodeType() == Node.ELEMENT_NODE )
711 {
712 Element element = (Element) node;
713 Attr labelAttrib = element.getAttributeNode( attribute );
714 if ( labelAttrib == null
715 || !value.equals( labelAttrib.getValue() ) )
716 {
717 getLog().info( "Setting " + attribute + " to " + value );
718 element.setAttribute( attribute, String.valueOf( value ) );
719 dirty = true;
720 }
721 }
722 }
723 return dirty;
724 }
725
726
727
728
729 private void exportProperties()
730 {
731 project.getProperties().setProperty( "android.manifest.versionName", parsedVersionName );
732 project.getProperties().setProperty( "android.manifest.versionCodeAutoIncrement",
733 String.valueOf( parsedVersionCodeAutoIncrement ) );
734 project.getProperties().setProperty( "android.manifest.versionCodeUpdateFromVersion",
735 String.valueOf( parsedVersionCodeUpdateFromVersion ) );
736 project.getProperties().setProperty( "android.manifest.debuggable", String.valueOf( parsedDebuggable ) );
737 if ( parsedSharedUserId != null )
738 {
739 project.getProperties().setProperty( "android.manifest.sharedUserId", parsedSharedUserId );
740 }
741 }
742
743 private void performVersioCodeAutoIncrement( Element manifestElement )
744 {
745 Attr versionCode = manifestElement.getAttributeNode( ATTR_VERSION_CODE );
746 int currentVersionCode = 0;
747 if ( versionCode != null )
748 {
749 currentVersionCode = NumberUtils.toInt( versionCode.getValue(), 0 );
750 }
751 currentVersionCode++;
752 manifestElement.setAttribute( ATTR_VERSION_CODE, String.valueOf( currentVersionCode ) );
753 project.getProperties().setProperty( "android.manifest.versionCode", String.valueOf( currentVersionCode ) );
754 }
755
756
757
758
759
760
761
762
763
764 private void performVersionCodeUpdateFromVersion( Element manifestElement ) throws MojoExecutionException
765 {
766 String verString = project.getVersion();
767 getLog().debug( "Generating versionCode for " + verString );
768 String verCode = generateVersionCodeFromVersionName( verString );
769 getLog().info( "Setting " + ATTR_VERSION_CODE + " to " + verCode );
770 manifestElement.setAttribute( ATTR_VERSION_CODE, verCode );
771 project.getProperties().setProperty( "android.manifest.versionCode", String.valueOf( verCode ) );
772 }
773
774 private String generateVersionCodeFromVersionName( String versionName ) throws MojoExecutionException
775 {
776
777 VersionGenerator gen = new VersionGenerator();
778
779 return Integer.toString( gen.generate( versionName ) );
780 }
781
782 private boolean performSupportScreenModification( Document doc, Element manifestElement )
783 {
784 boolean dirty = false;
785 Element supportsScreensElem = XmlHelper.getOrCreateElement( doc, manifestElement,
786 ELEM_SUPPORTS_SCREENS );
787
788 getLog().info( "Setting " + ELEM_SUPPORTS_SCREENS );
789
790 if ( parsedSupportsScreens.getAnyDensity() != null )
791 {
792 supportsScreensElem.setAttribute( ATTR_ANY_DENSITY, parsedSupportsScreens.getAnyDensity() );
793 dirty = true;
794 }
795 if ( parsedSupportsScreens.getSmallScreens() != null )
796 {
797 supportsScreensElem.setAttribute( ATTR_SMALL_SCREENS, parsedSupportsScreens.getSmallScreens() );
798 dirty = true;
799 }
800 if ( parsedSupportsScreens.getNormalScreens() != null )
801 {
802 supportsScreensElem.setAttribute( ATTR_NORMAL_SCREENS, parsedSupportsScreens.getNormalScreens() );
803 dirty = true;
804 }
805 if ( parsedSupportsScreens.getLargeScreens() != null )
806 {
807 supportsScreensElem.setAttribute( ATTR_LARGE_SCREENS, parsedSupportsScreens.getLargeScreens() );
808 dirty = true;
809 }
810 if ( parsedSupportsScreens.getXlargeScreens() != null )
811 {
812 supportsScreensElem.setAttribute( ATTR_XLARGE_SCREENS, parsedSupportsScreens.getXlargeScreens() );
813 dirty = true;
814 }
815 if ( parsedSupportsScreens.getCompatibleWidthLimitDp() != null )
816 {
817 supportsScreensElem.setAttribute( ATTR_COMPATIBLE_WIDTH_LIMIT_DP,
818 parsedSupportsScreens.getCompatibleWidthLimitDp() );
819 dirty = true;
820 }
821 if ( parsedSupportsScreens.getLargestWidthLimitDp() != null )
822 {
823 supportsScreensElem
824 .setAttribute( ATTR_LARGEST_WIDTH_LIMIT_DP, parsedSupportsScreens.getLargestWidthLimitDp() );
825 dirty = true;
826 }
827 if ( parsedSupportsScreens.getRequiresSmallestWidthDp() != null )
828 {
829 supportsScreensElem.setAttribute( ATTR_REQUIRES_SMALLEST_WIDTH_DP,
830 parsedSupportsScreens.getRequiresSmallestWidthDp() );
831 dirty = true;
832 }
833 if ( parsedSupportsScreens.getResizeable() != null )
834 {
835 supportsScreensElem.setAttribute( ATTR_RESIZEABLE, parsedSupportsScreens.getResizeable() );
836 dirty = true;
837 }
838 return dirty;
839 }
840
841 private boolean performUsesSdkModification ( Document doc, Element manifestElement )
842 {
843 boolean dirty = false;
844 Element usesSdkElem = XmlHelper.getOrCreateElement( doc, manifestElement,
845 ELEM_USES_SDK );
846
847 if ( parsedUsesSdk.getMinSdkVersion() != null )
848 {
849 usesSdkElem.setAttribute( ATTR_MIN_SDK_VERSION, parsedUsesSdk.getMinSdkVersion() );
850 dirty = true;
851 }
852 if ( parsedUsesSdk.getMaxSdkVersion() != null )
853 {
854 usesSdkElem.setAttribute( ATTR_MAX_SDK_VERSION, parsedUsesSdk.getMaxSdkVersion() );
855 dirty = true;
856 }
857 if ( parsedUsesSdk.getTargetSdkVersion() != null )
858 {
859 usesSdkElem.setAttribute( ATTR_TARGET_SDK_VERSION, parsedUsesSdk.getTargetSdkVersion() );
860 dirty = true;
861 }
862
863 return dirty;
864 }
865
866 private void updateCompatibleScreens( Document doc, Element manifestElement )
867 {
868 Element compatibleScreensElem = XmlHelper.getOrCreateElement( doc, manifestElement, ELEM_COMPATIBLE_SCREENS );
869
870
871 NodeList manifestScreenElems = compatibleScreensElem.getElementsByTagName( ELEM_SCREEN );
872 int numManifestScreens = manifestScreenElems.getLength();
873 ArrayList<CompatibleScreen> manifestScreens = new ArrayList<CompatibleScreen>( numManifestScreens );
874 for ( int i = 0; i < numManifestScreens; i++ )
875 {
876 Element screenElem = ( Element ) manifestScreenElems.item( i );
877
878 CompatibleScreen screen = new CompatibleScreen();
879 screen.setScreenDensity( screenElem.getAttribute( ATTR_SCREEN_DENSITY ) );
880 screen.setScreenSize( screenElem.getAttribute( ATTR_SCREEN_SIZE ) );
881
882 manifestScreens.add( screen );
883 getLog().debug( "Found Manifest compatible-screen: " + screen );
884 }
885
886
887 XmlHelper.removeDirectChildren( compatibleScreensElem );
888
889 for ( CompatibleScreen screen : parsedCompatibleScreens )
890 {
891 getLog().debug( "Found POM compatible-screen: " + screen );
892 }
893
894
895
896 HashSet<CompatibleScreen> mergedScreens = new HashSet<CompatibleScreen>();
897 mergedScreens.addAll( manifestScreens );
898 mergedScreens.addAll( parsedCompatibleScreens );
899
900 for ( CompatibleScreen screen : mergedScreens )
901 {
902 getLog().debug( "Using compatible-screen: " + screen );
903 Element screenElem = doc.createElement( ELEM_SCREEN );
904 screenElem.setAttribute( ATTR_SCREEN_SIZE, screen.getScreenSize() );
905 screenElem.setAttribute( ATTR_SCREEN_DENSITY, screen.getScreenDensity() );
906
907 compatibleScreensElem.appendChild( screenElem );
908 }
909 }
910
911 private boolean updateProviderAuthorities( Element manifestElement )
912 {
913 boolean dirty = false;
914 NodeList appElems = manifestElement.getElementsByTagName( ELEM_APPLICATION );
915
916
917 for ( int i = 0; i < appElems.getLength(); ++ i )
918 {
919 Node node = appElems.item( i );
920 if ( node.getNodeType() == Node.ELEMENT_NODE )
921 {
922 NodeList providerElems = manifestElement.getElementsByTagName( ELEM_PROVIDER );
923 for ( int j = 0; j < providerElems.getLength(); ++ j )
924 {
925 Node providerNode = providerElems.item( j );
926 if ( providerNode.getNodeType() == Node.ELEMENT_NODE )
927 {
928 Element providerElem = (Element) providerNode;
929 Attr providerName = providerElem.getAttributeNode( ATTR_NAME );
930 getLog().debug( "Checking provider " + providerName.getValue() );
931 if ( shouldPerformProviderUpdate( providerName ) )
932 {
933 dirty = true;
934 String name = providerName.getValue();
935 String newAuthorities = parsedProviderAuthorities.getProperty( name );
936 getLog().info( "Updating provider " + name + " authorities attr to " + newAuthorities );
937 performProviderUpdate( providerElem, newAuthorities );
938 }
939 }
940 }
941 }
942 }
943
944 return dirty;
945 }
946
947 private boolean shouldPerformProviderUpdate( Attr providerName )
948 {
949 if ( providerName == null )
950 {
951 return false;
952 }
953
954 for ( String propName: parsedProviderAuthorities.stringPropertyNames() )
955 {
956 if ( propName.equals( providerName.getValue() ) )
957 {
958 return true;
959 }
960 }
961 return false;
962 }
963
964 private void performProviderUpdate( Element providerElem, String newAuthorities )
965 {
966 Attr providerAuthorities = providerElem.getAttributeNode( ATTR_AUTHORITIES );
967 providerAuthorities.setValue( newAuthorities );
968 }
969
970 }