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