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