1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.apache.maven.plugin.lifecycle.io.xpp3;
25
26
27
28
29
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.Reader;
33 import java.text.DateFormat;
34 import org.apache.maven.plugin.lifecycle.Execution;
35 import org.apache.maven.plugin.lifecycle.Lifecycle;
36 import org.apache.maven.plugin.lifecycle.LifecycleConfiguration;
37 import org.apache.maven.plugin.lifecycle.Phase;
38 import org.codehaus.plexus.util.xml.XmlStreamReader;
39 import org.codehaus.plexus.util.xml.pull.EntityReplacementMap;
40 import org.codehaus.plexus.util.xml.pull.MXParser;
41 import org.codehaus.plexus.util.xml.pull.XmlPullParser;
42 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
43
44
45
46
47
48
49 @SuppressWarnings( "all" )
50 public class LifecycleMappingsXpp3Reader
51 {
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 private boolean addDefaultEntities = true;
68
69
70
71
72 public final ContentTransformer contentTransformer;
73
74
75
76
77
78
79 public LifecycleMappingsXpp3Reader()
80 {
81 this( new ContentTransformer()
82 {
83 public String transform( String source, String fieldName )
84 {
85 return source;
86 }
87 } );
88 }
89
90 public LifecycleMappingsXpp3Reader(ContentTransformer contentTransformer)
91 {
92 this.contentTransformer = contentTransformer;
93 }
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, java.util.Set<String> parsed )
112 throws XmlPullParserException
113 {
114 if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) )
115 {
116 return false;
117 }
118 if ( !parsed.add( tagName ) )
119 {
120 throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null );
121 }
122 return true;
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136 private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict )
137 throws XmlPullParserException, IOException
138 {
139
140 if ( strict )
141 {
142 throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null );
143 }
144 }
145
146
147
148
149
150
151
152
153
154
155 private void checkUnknownElement( XmlPullParser parser, boolean strict )
156 throws XmlPullParserException, IOException
157 {
158 if ( strict )
159 {
160 throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null );
161 }
162
163 for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; )
164 {
165 int eventType = parser.next();
166 if ( eventType == XmlPullParser.START_TAG )
167 {
168 unrecognizedTagCount++;
169 }
170 else if ( eventType == XmlPullParser.END_TAG )
171 {
172 unrecognizedTagCount--;
173 }
174 }
175 }
176
177
178
179
180
181
182 public boolean getAddDefaultEntities()
183 {
184 return addDefaultEntities;
185 }
186
187
188
189
190
191
192
193
194
195
196
197 private boolean getBooleanValue( String s, String attribute, XmlPullParser parser )
198 throws XmlPullParserException
199 {
200 return getBooleanValue( s, attribute, parser, null );
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214 private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue )
215 throws XmlPullParserException
216 {
217 if ( s != null && s.length() != 0 )
218 {
219 return Boolean.valueOf( s ).booleanValue();
220 }
221 if ( defaultValue != null )
222 {
223 return Boolean.valueOf( defaultValue ).booleanValue();
224 }
225 return false;
226 }
227
228
229
230
231
232
233
234
235
236
237
238
239 private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict )
240 throws XmlPullParserException
241 {
242 if ( s != null )
243 {
244 try
245 {
246 return Byte.valueOf( s ).byteValue();
247 }
248 catch ( NumberFormatException nfe )
249 {
250 if ( strict )
251 {
252 throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe );
253 }
254 }
255 }
256 return 0;
257 }
258
259
260
261
262
263
264
265
266
267
268
269 private char getCharacterValue( String s, String attribute, XmlPullParser parser )
270 throws XmlPullParserException
271 {
272 if ( s != null )
273 {
274 return s.charAt( 0 );
275 }
276 return 0;
277 }
278
279
280
281
282
283
284
285
286
287
288
289 private java.util.Date getDateValue( String s, String attribute, XmlPullParser parser )
290 throws XmlPullParserException
291 {
292 return getDateValue( s, attribute, null, parser );
293 }
294
295
296
297
298
299
300
301
302
303
304
305
306 private java.util.Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser )
307 throws XmlPullParserException
308 {
309 if ( s != null )
310 {
311 String effectiveDateFormat = dateFormat;
312 if ( dateFormat == null )
313 {
314 effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS";
315 }
316 if ( "long".equals( effectiveDateFormat ) )
317 {
318 try
319 {
320 return new java.util.Date( Long.parseLong( s ) );
321 }
322 catch ( NumberFormatException e )
323 {
324 throw new XmlPullParserException( e.getMessage(), parser, e );
325 }
326 }
327 else
328 {
329 try
330 {
331 DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US );
332 return dateParser.parse( s );
333 }
334 catch ( java.text.ParseException e )
335 {
336 throw new XmlPullParserException( e.getMessage(), parser, e );
337 }
338 }
339 }
340 return null;
341 }
342
343
344
345
346
347
348
349
350
351
352
353
354 private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict )
355 throws XmlPullParserException
356 {
357 if ( s != null )
358 {
359 try
360 {
361 return Double.valueOf( s ).doubleValue();
362 }
363 catch ( NumberFormatException nfe )
364 {
365 if ( strict )
366 {
367 throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe );
368 }
369 }
370 }
371 return 0;
372 }
373
374
375
376
377
378
379
380
381
382
383
384
385 private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict )
386 throws XmlPullParserException
387 {
388 if ( s != null )
389 {
390 try
391 {
392 return Float.valueOf( s ).floatValue();
393 }
394 catch ( NumberFormatException nfe )
395 {
396 if ( strict )
397 {
398 throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe );
399 }
400 }
401 }
402 return 0;
403 }
404
405
406
407
408
409
410
411
412
413
414
415
416 private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict )
417 throws XmlPullParserException
418 {
419 if ( s != null )
420 {
421 try
422 {
423 return Integer.valueOf( s ).intValue();
424 }
425 catch ( NumberFormatException nfe )
426 {
427 if ( strict )
428 {
429 throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe );
430 }
431 }
432 }
433 return 0;
434 }
435
436
437
438
439
440
441
442
443
444
445
446
447 private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict )
448 throws XmlPullParserException
449 {
450 if ( s != null )
451 {
452 try
453 {
454 return Long.valueOf( s ).longValue();
455 }
456 catch ( NumberFormatException nfe )
457 {
458 if ( strict )
459 {
460 throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe );
461 }
462 }
463 }
464 return 0;
465 }
466
467
468
469
470
471
472
473
474
475
476
477
478 private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict )
479 throws XmlPullParserException
480 {
481 if ( s == null )
482 {
483 if ( strict )
484 {
485 throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null );
486 }
487 }
488 return s;
489 }
490
491
492
493
494
495
496
497
498
499
500
501
502 private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict )
503 throws XmlPullParserException
504 {
505 if ( s != null )
506 {
507 try
508 {
509 return Short.valueOf( s ).shortValue();
510 }
511 catch ( NumberFormatException nfe )
512 {
513 if ( strict )
514 {
515 throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe );
516 }
517 }
518 }
519 return 0;
520 }
521
522
523
524
525
526
527
528 private String getTrimmedValue( String s )
529 {
530 if ( s != null )
531 {
532 s = s.trim();
533 }
534 return s;
535 }
536
537
538
539
540
541
542
543
544 private String interpolatedTrimmed( String value, String context )
545 {
546 return getTrimmedValue( contentTransformer.transform( value, context ) );
547 }
548
549
550
551
552
553
554
555
556
557
558 private int nextTag( XmlPullParser parser )
559 throws IOException, XmlPullParserException
560 {
561 int eventType = parser.next();
562 if ( eventType == XmlPullParser.TEXT )
563 {
564 eventType = parser.next();
565 }
566 if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG )
567 {
568 throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null );
569 }
570 return eventType;
571 }
572
573
574
575
576
577
578
579
580
581
582
583 public LifecycleConfiguration read( XmlPullParser parser, boolean strict )
584 throws IOException, XmlPullParserException
585 {
586 LifecycleConfiguration lifecycleConfiguration = null;
587 int eventType = parser.getEventType();
588 boolean parsed = false;
589 while ( eventType != XmlPullParser.END_DOCUMENT )
590 {
591 if ( eventType == XmlPullParser.START_TAG )
592 {
593 if ( strict && ! "lifecycles".equals( parser.getName() ) )
594 {
595 throw new XmlPullParserException( "Expected root element 'lifecycles' but found '" + parser.getName() + "'", parser, null );
596 }
597 else if ( parsed )
598 {
599
600 throw new XmlPullParserException( "Duplicated tag: 'lifecycles'", parser, null );
601 }
602 lifecycleConfiguration = parseLifecycleConfiguration( parser, strict );
603 lifecycleConfiguration.setModelEncoding( parser.getInputEncoding() );
604 parsed = true;
605 }
606 eventType = parser.next();
607 }
608 if ( parsed )
609 {
610 return lifecycleConfiguration;
611 }
612 throw new XmlPullParserException( "Expected root element 'lifecycles' but found no element at all: invalid XML document", parser, null );
613 }
614
615
616
617
618
619
620
621
622
623
624
625 public LifecycleConfiguration read( Reader reader, boolean strict )
626 throws IOException, XmlPullParserException
627 {
628 XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( );
629
630 parser.setInput( reader );
631
632
633 return read( parser, strict );
634 }
635
636
637
638
639
640
641
642
643
644
645 public LifecycleConfiguration read( Reader reader )
646 throws IOException, XmlPullParserException
647 {
648 return read( reader, true );
649 }
650
651
652
653
654
655
656
657
658
659
660
661 public LifecycleConfiguration read( InputStream in, boolean strict )
662 throws IOException, XmlPullParserException
663 {
664 return read( new XmlStreamReader( in ), strict );
665 }
666
667
668
669
670
671
672
673
674
675
676 public LifecycleConfiguration read( InputStream in )
677 throws IOException, XmlPullParserException
678 {
679 return read( new XmlStreamReader( in ) );
680 }
681
682
683
684
685
686
687
688
689
690
691
692 private Execution parseExecution( XmlPullParser parser, boolean strict )
693 throws IOException, XmlPullParserException
694 {
695 String tagName = parser.getName();
696 Execution execution = new Execution();
697 for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
698 {
699 String name = parser.getAttributeName( i );
700 String value = parser.getAttributeValue( i );
701
702 if ( name.indexOf( ':' ) >= 0 )
703 {
704
705 }
706 else
707 {
708 checkUnknownAttribute( parser, name, tagName, strict );
709 }
710 }
711 java.util.Set<String> parsed = new java.util.HashSet<String>();
712 while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
713 {
714 if ( checkFieldWithDuplicate( parser, "configuration", null, parsed ) )
715 {
716 execution.setConfiguration( org.codehaus.plexus.util.xml.Xpp3DomBuilder.build( parser, true ) );
717 }
718 else if ( checkFieldWithDuplicate( parser, "goals", null, parsed ) )
719 {
720 java.util.List<String> goals = new java.util.ArrayList<String>();
721 while ( parser.nextTag() == XmlPullParser.START_TAG )
722 {
723 if ( "goal".equals( parser.getName() ) )
724 {
725 goals.add( interpolatedTrimmed( parser.nextText(), "goals" ) );
726 }
727 else
728 {
729 checkUnknownElement( parser, strict );
730 }
731 }
732 execution.setGoals( goals );
733 }
734 else
735 {
736 checkUnknownElement( parser, strict );
737 }
738 }
739 return execution;
740 }
741
742
743
744
745
746
747
748
749
750
751
752 private Lifecycle parseLifecycle( XmlPullParser parser, boolean strict )
753 throws IOException, XmlPullParserException
754 {
755 String tagName = parser.getName();
756 Lifecycle lifecycle = new Lifecycle();
757 for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
758 {
759 String name = parser.getAttributeName( i );
760 String value = parser.getAttributeValue( i );
761
762 if ( name.indexOf( ':' ) >= 0 )
763 {
764
765 }
766 else
767 {
768 checkUnknownAttribute( parser, name, tagName, strict );
769 }
770 }
771 java.util.Set<String> parsed = new java.util.HashSet<String>();
772 while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
773 {
774 if ( checkFieldWithDuplicate( parser, "id", null, parsed ) )
775 {
776 lifecycle.setId( interpolatedTrimmed( parser.nextText(), "id" ) );
777 }
778 else if ( checkFieldWithDuplicate( parser, "phases", null, parsed ) )
779 {
780 java.util.List<Phase> phases = new java.util.ArrayList<Phase>();
781 while ( parser.nextTag() == XmlPullParser.START_TAG )
782 {
783 if ( "phase".equals( parser.getName() ) )
784 {
785 phases.add( parsePhase( parser, strict ) );
786 }
787 else
788 {
789 checkUnknownElement( parser, strict );
790 }
791 }
792 lifecycle.setPhases( phases );
793 }
794 else
795 {
796 checkUnknownElement( parser, strict );
797 }
798 }
799 return lifecycle;
800 }
801
802
803
804
805
806
807
808
809
810
811
812 private LifecycleConfiguration parseLifecycleConfiguration( XmlPullParser parser, boolean strict )
813 throws IOException, XmlPullParserException
814 {
815 String tagName = parser.getName();
816 LifecycleConfiguration lifecycleConfiguration = new LifecycleConfiguration();
817 for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
818 {
819 String name = parser.getAttributeName( i );
820 String value = parser.getAttributeValue( i );
821
822 if ( name.indexOf( ':' ) >= 0 )
823 {
824
825 }
826 else if ( "xmlns".equals( name ) )
827 {
828
829 }
830 else
831 {
832 checkUnknownAttribute( parser, name, tagName, strict );
833 }
834 }
835 java.util.Set<String> parsed = new java.util.HashSet<String>();
836 while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
837 {
838 if ( "lifecycle".equals( parser.getName() ) )
839 {
840 java.util.List<Lifecycle> lifecycles = lifecycleConfiguration.getLifecycles();
841 if ( lifecycles == null )
842 {
843 lifecycles = new java.util.ArrayList<Lifecycle>();
844 }
845 lifecycles.add( parseLifecycle( parser, strict ) );
846 lifecycleConfiguration.setLifecycles( lifecycles );
847 }
848 else
849 {
850 checkUnknownElement( parser, strict );
851 }
852 }
853 return lifecycleConfiguration;
854 }
855
856
857
858
859
860
861
862
863
864
865
866 private Phase parsePhase( XmlPullParser parser, boolean strict )
867 throws IOException, XmlPullParserException
868 {
869 String tagName = parser.getName();
870 Phase phase = new Phase();
871 for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
872 {
873 String name = parser.getAttributeName( i );
874 String value = parser.getAttributeValue( i );
875
876 if ( name.indexOf( ':' ) >= 0 )
877 {
878
879 }
880 else
881 {
882 checkUnknownAttribute( parser, name, tagName, strict );
883 }
884 }
885 java.util.Set<String> parsed = new java.util.HashSet<String>();
886 while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
887 {
888 if ( checkFieldWithDuplicate( parser, "id", null, parsed ) )
889 {
890 phase.setId( interpolatedTrimmed( parser.nextText(), "id" ) );
891 }
892 else if ( checkFieldWithDuplicate( parser, "executions", null, parsed ) )
893 {
894 java.util.List<Execution> executions = new java.util.ArrayList<Execution>();
895 while ( parser.nextTag() == XmlPullParser.START_TAG )
896 {
897 if ( "execution".equals( parser.getName() ) )
898 {
899 executions.add( parseExecution( parser, strict ) );
900 }
901 else
902 {
903 checkUnknownElement( parser, strict );
904 }
905 }
906 phase.setExecutions( executions );
907 }
908 else if ( checkFieldWithDuplicate( parser, "configuration", null, parsed ) )
909 {
910 phase.setConfiguration( org.codehaus.plexus.util.xml.Xpp3DomBuilder.build( parser, true ) );
911 }
912 else
913 {
914 checkUnknownElement( parser, strict );
915 }
916 }
917 return phase;
918 }
919
920
921
922
923
924
925 public void setAddDefaultEntities( boolean addDefaultEntities )
926 {
927 this.addDefaultEntities = addDefaultEntities;
928 }
929
930 public static interface ContentTransformer
931 {
932
933
934
935
936
937
938
939 String transform( String source, String fieldName );
940 }
941
942 }