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