1
2
3
4
5
6
7
8 package org.jdtaus.mojo.resource.model.impl.runtime;
9
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.Hashtable;
13 import java.util.Iterator;
14 import java.util.List;
15
16 import javax.xml.XMLConstants;
17 import javax.xml.bind.JAXBException;
18 import javax.xml.bind.UnmarshalException;
19 import javax.xml.bind.ValidationEvent;
20 import javax.xml.bind.ValidationEventHandler;
21
22 import org.xml.sax.Attributes;
23 import org.xml.sax.Locator;
24 import org.xml.sax.SAXException;
25 import org.xml.sax.SAXParseException;
26 import org.xml.sax.helpers.LocatorImpl;
27
28 import com.sun.xml.bind.JAXBAssertionError;
29 import com.sun.xml.bind.unmarshaller.Messages;
30 import com.sun.xml.bind.unmarshaller.Tracer;
31 import com.sun.xml.bind.util.AttributesImpl;
32
33
34
35
36
37
38
39
40
41
42 public class SAXUnmarshallerHandlerImpl
43 implements SAXUnmarshallerHandler, UnmarshallingContext
44 {
45
46
47
48
49
50
51
52
53 private boolean isUnmarshalInProgress = true;
54
55
56
57 public SAXUnmarshallerHandlerImpl( UnmarshallerImpl _parent, GrammarInfo _gi ) {
58 this.parent = _parent;
59 grammarInfo = _gi;
60 startPrefixMapping("","");
61 }
62
63 private final GrammarInfo grammarInfo;
64 public GrammarInfo getGrammarInfo() { return grammarInfo; }
65
66
67
68
69 private final boolean shouldCollectText() {
70 return collectText[stackTop];
71 }
72
73 public void startDocument() throws SAXException {
74
75 result = null;
76 handlerLen=0;
77 patchers=null;
78 patchersLen=0;
79 aborted = false;
80 isUnmarshalInProgress = true;
81
82 stackTop=0;
83 elementDepth=1;
84 }
85
86 public void endDocument() throws SAXException {
87 runPatchers();
88 isUnmarshalInProgress = false;
89 }
90
91 public void startElement( String uri, String local, String qname, Attributes atts )
92 throws SAXException {
93
94
95 if( uri==null )
96 uri="";
97 if( local==null || local.length()==0 )
98 local=qname;
99 if( qname==null || qname.length()==0 )
100 qname=local;
101
102 if(result==null) {
103
104
105 UnmarshallingEventHandler unmarshaller =
106 grammarInfo.createUnmarshaller(uri,local,this);
107 if(unmarshaller==null) {
108
109
110
111
112
113
114 throw new SAXParseException(
115 Messages.format( Messages.UNEXPECTED_ROOT_ELEMENT2,
116 uri, local, computeExpectedRootElements() ),
117 getLocator() );
118 }
119 result = unmarshaller.owner();
120
121 pushContentHandler(unmarshaller,0);
122 }
123
124 processText(true);
125
126 getCurrentHandler().enterElement(uri,local,qname,atts);
127 }
128
129 public final void endElement( String uri, String local, String qname )
130 throws SAXException {
131
132
133 if( uri==null )
134 uri="";
135 if( local==null || local.length()==0 )
136 local=qname;
137 if( qname==null || qname.length()==0 )
138 qname=local;
139
140 processText(false);
141 getCurrentHandler().leaveElement(uri,local,qname);
142 }
143
144
145
146
147
148
149 private Object result;
150 public Object getResult() throws UnmarshalException {
151 if(isUnmarshalInProgress)
152 throw new IllegalStateException();
153
154 if(!aborted) return result;
155
156
157 throw new UnmarshalException((String)null);
158 }
159
160
161
162
163
164
165
166
167 private UnmarshallingEventHandler[] handlers = new UnmarshallingEventHandler[16];
168 private int[] mementos = new int[16];
169 private int handlerLen=0;
170
171 public void pushContentHandler( UnmarshallingEventHandler handler, int memento ) {
172 if(handlerLen==handlers.length) {
173
174 UnmarshallingEventHandler[] h = new UnmarshallingEventHandler[handlerLen*2];
175 int[] m = new int[handlerLen*2];
176 System.arraycopy(handlers,0,h,0,handlerLen);
177 System.arraycopy(mementos,0,m,0,handlerLen);
178 handlers = h;
179 mementos = m;
180 }
181 handlers[handlerLen] = handler;
182 mementos[handlerLen] = memento;
183 handlerLen++;
184 }
185
186 public void popContentHandler() throws SAXException {
187 handlerLen--;
188 handlers[handlerLen]=null;
189 getCurrentHandler().leaveChild(mementos[handlerLen]);
190 }
191
192 public UnmarshallingEventHandler getCurrentHandler() {
193 return handlers[handlerLen-1];
194 }
195
196
197
198
199
200
201
202 private StringBuffer buffer = new StringBuffer();
203
204 protected void consumeText( String str, boolean ignorable ) throws SAXException {
205 if(ignorable && str.trim().length()==0)
206
207
208 return;
209
210
211 getCurrentHandler().text(str);
212 }
213 private void processText( boolean ignorable ) throws SAXException {
214 if( shouldCollectText() )
215 consumeText(buffer.toString(),ignorable);
216
217
218
219 if(buffer.length()<1024) buffer.setLength(0);
220 else buffer = new StringBuffer();
221 }
222
223 public final void characters( char[] buf, int start, int len ) {
224 if( shouldCollectText() )
225 buffer.append(buf,start,len);
226 }
227
228 public final void ignorableWhitespace( char[] buf, int start, int len ) {
229 characters(buf,start,len);
230 }
231
232
233
234
235
236
237
238
239
240 private String[] nsBind = new String[16];
241 private int nsLen=0;
242
243
244
245
246 private int[] idxStack = new int[16];
247
248 public void startPrefixMapping( String prefix, String uri ) {
249 if(nsBind.length==nsLen) {
250
251 String[] n = new String[nsLen*2];
252 System.arraycopy(nsBind,0,n,0,nsLen);
253 nsBind=n;
254 }
255 nsBind[nsLen++] = prefix;
256 nsBind[nsLen++] = uri;
257 }
258 public void endPrefixMapping( String prefix ) {
259 nsLen-=2;
260 }
261 public String resolveNamespacePrefix( String prefix ) {
262 if(prefix.equals("xml"))
263 return "http://www.w3.org/XML/1998/namespace";
264
265 for( int i=idxStack[stackTop]-2; i>=0; i-=2 ) {
266 if(prefix.equals(nsBind[i]))
267 return nsBind[i+1];
268 }
269 return null;
270 }
271 public String[] getNewlyDeclaredPrefixes() {
272 return getPrefixList( idxStack[stackTop-1] );
273 }
274
275 public String[] getAllDeclaredPrefixes() {
276 return getPrefixList( 2 );
277 }
278
279 private String[] getPrefixList( int startIndex ) {
280 int size = (idxStack[stackTop]-startIndex)/2;
281 String[] r = new String[size];
282 for( int i=0; i<r.length; i++ )
283 r[i] = nsBind[startIndex+i*2];
284 return r;
285 }
286
287
288
289
290
291 public Iterator getPrefixes(String uri) {
292
293
294 return Collections.unmodifiableList(
295 getAllPrefixesInList(uri)).iterator();
296 }
297
298 private List getAllPrefixesInList(String uri) {
299 List a = new ArrayList();
300
301 if( uri.equals(XMLConstants.XML_NS_URI) ) {
302 a.add(XMLConstants.XML_NS_PREFIX);
303 return a;
304 }
305 if( uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI) ) {
306 a.add(XMLConstants.XMLNS_ATTRIBUTE);
307 return a;
308 }
309 if( uri==null )
310 throw new IllegalArgumentException();
311
312 for( int i=nsLen-2; i>=0; i-=2 )
313 if(uri.equals(nsBind[i+1]))
314 if( getNamespaceURI(nsBind[i]).equals(nsBind[i+1]) )
315
316 a.add(nsBind[i]);
317
318 return a;
319 }
320
321 public String getPrefix(String uri) {
322 if( uri.equals(XMLConstants.XML_NS_URI) )
323 return XMLConstants.XML_NS_PREFIX;
324 if( uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI) )
325 return XMLConstants.XMLNS_ATTRIBUTE;
326 if( uri==null )
327 throw new IllegalArgumentException();
328
329 for( int i=idxStack[stackTop]-2; i>=0; i-=2 )
330 if(uri.equals(nsBind[i+1]))
331 if( getNamespaceURI(nsBind[i]).equals(nsBind[i+1]) )
332
333 return nsBind[i];
334
335 return null;
336 }
337
338 public String getNamespaceURI(String prefix) {
339 if( prefix==null )
340 throw new IllegalArgumentException();
341 if( prefix.equals(XMLConstants.XMLNS_ATTRIBUTE) )
342 return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
343
344 return resolveNamespacePrefix(prefix);
345 }
346
347
348
349
350
351
352
353
354
355 private AttributesImpl[] attStack = new AttributesImpl[16];
356
357
358
359 private int elementDepth;
360
361
362
363 private int stackTop;
364
365
366
367
368
369
370
371 private boolean[] collectText = new boolean[16];
372
373 public void pushAttributes( Attributes atts, boolean collectTextFlag ) {
374
375 if( attStack.length==elementDepth ) {
376
377 AttributesImpl[] buf1 = new AttributesImpl[attStack.length*2];
378 System.arraycopy(attStack,0,buf1,0,attStack.length);
379 attStack = buf1;
380
381 int[] buf2 = new int[idxStack.length*2];
382 System.arraycopy(idxStack,0,buf2,0,idxStack.length);
383 idxStack = buf2;
384
385 boolean[] buf3 = new boolean[collectText.length*2];
386 System.arraycopy(collectText,0,buf3,0,collectText.length);
387 collectText = buf3;
388 }
389
390 elementDepth++;
391 stackTop++;
392
393
394 AttributesImpl a = attStack[stackTop];
395 if( a==null )
396 attStack[stackTop] = a = new AttributesImpl();
397 else
398 a.clear();
399
400
401
402
403 for( int i=0; i<atts.getLength(); i++ ) {
404 String auri = atts.getURI(i);
405 String alocal = atts.getLocalName(i);
406 String avalue = atts.getValue(i);
407 String aqname = atts.getQName(i);
408
409
410 if( auri==null )
411 auri="";
412 if( alocal==null || alocal.length()==0 )
413 alocal=aqname;
414 if( aqname==null || aqname.length()==0 )
415 aqname=alocal;
416
417
418
419
420
421
422
423 if( auri=="http://www.w3.org/2001/XMLSchema-instance" && alocal=="nil" ) {
424 String v = avalue.trim();
425 if(v.equals("false") || v.equals("0"))
426 continue;
427 }
428
429
430 a.addAttribute(
431 auri,
432 alocal,
433 aqname,
434 atts.getType(i),
435 avalue );
436 }
437
438
439
440 idxStack[stackTop] = nsLen;
441
442 collectText[stackTop] = collectTextFlag;
443 }
444 public void popAttributes() {
445 stackTop--;
446 elementDepth--;
447 }
448 public Attributes getUnconsumedAttributes() {
449 return attStack[stackTop];
450 }
451
452
453
454
455 public int getAttribute( String uri, String local ) {
456 return attStack[stackTop].getIndexFast(uri,local);
457 }
458 public void consumeAttribute( int idx ) throws SAXException {
459 AttributesImpl a = attStack[stackTop];
460
461 String uri = a.getURI(idx);
462 String local = a.getLocalName(idx);
463 String qname = a.getQName(idx);
464 String value = a.getValue(idx);
465
466
467
468
469 a.removeAttribute(idx);
470
471
472 getCurrentHandler().enterAttribute(uri,local,qname);
473 consumeText(value,false);
474 getCurrentHandler().leaveAttribute(uri,local,qname);
475 }
476 public String eatAttribute( int idx ) throws SAXException {
477 AttributesImpl a = attStack[stackTop];
478
479 String value = a.getValue(idx);
480
481
482 a.removeAttribute(idx);
483
484 return value;
485 }
486
487
488
489
490
491
492
493
494
495
496
497 private Runnable[] patchers = null;
498 private int patchersLen = 0;
499
500 public void addPatcher( Runnable job ) {
501
502 if( patchers==null )
503 patchers = new Runnable[32];
504 if( patchers.length == patchersLen ) {
505 Runnable[] buf = new Runnable[patchersLen*2];
506 System.arraycopy(patchers,0,buf,0,patchersLen);
507 patchers = buf;
508 }
509 patchers[patchersLen++] = job;
510 }
511
512
513 private void runPatchers() {
514 if( patchers!=null ) {
515 for( int i=0; i<patchersLen; i++ )
516 patchers[i].run();
517 }
518 }
519
520
521 private Hashtable idmap = null;
522
523 public String addToIdTable( String id ) {
524 if(idmap==null) idmap = new Hashtable();
525 idmap.put( id, getCurrentHandler().owner() );
526 return id;
527 }
528
529 public Object getObjectFromId( String id ) {
530 if(idmap==null) return null;
531 return idmap.get(id);
532 }
533
534
535
536
537
538
539
540
541 public void skippedEntity( String name ) {
542 }
543 public void processingInstruction( String target, String data ) {
544
545 }
546 public void setDocumentLocator( Locator loc ) {
547 locator = loc;
548 }
549 public Locator getLocator() { return locator; }
550
551 private Locator locator = DUMMY_LOCATOR;
552
553 private static final Locator DUMMY_LOCATOR = new LocatorImpl();
554
555
556
557
558
559
560
561 private final UnmarshallerImpl parent;
562 private boolean aborted = false;
563
564 public void handleEvent(ValidationEvent event, boolean canRecover ) throws SAXException {
565 ValidationEventHandler eventHandler;
566 try {
567 eventHandler = parent.getEventHandler();
568 } catch( JAXBException e ) {
569
570 throw new JAXBAssertionError();
571 }
572
573 boolean recover = eventHandler.handleEvent(event);
574
575
576
577 if(!recover) aborted = true;
578
579 if( !canRecover || !recover )
580 throw new SAXException( new UnmarshalException(
581 event.getMessage(),
582 event.getLinkedException() ) );
583 }
584
585
586
587
588
589
590 public String getBaseUri() { return null; }
591 public boolean isUnparsedEntity(String s) { return true; }
592 public boolean isNotation(String s) { return true; }
593
594
595
596
597
598
599
600 private Tracer tracer;
601 public void setTracer( Tracer t ) {
602 this.tracer = t;
603 }
604 public Tracer getTracer() {
605 if(tracer==null)
606 tracer = new Tracer.Standard();
607 return tracer;
608 }
609
610
611
612
613 private String computeExpectedRootElements() {
614 String r = "";
615
616 String[] probePoints = grammarInfo.getProbePoints();
617 for( int i=0; i<probePoints.length; i+=2 ) {
618 if( grammarInfo.recognize(probePoints[i],probePoints[i+1]) ) {
619 if(r.length()!=0) r+=',';
620 r += "<{"+probePoints[i]+"}"+probePoints[i+1]+">";
621 }
622 }
623
624 return r;
625 }
626 }