001: //
002: // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v1.0.4-b18-fcs
003: // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
004: // Any modifications to this file will be lost upon recompilation of the source schema.
005: // Generated on: 2005.03.04 at 10:20:40 PST
006: //
007:
008: package com.nabhinc.portal.config.impl.runtime;
009:
010: import java.util.ArrayList;
011: import java.util.Collections;
012: import java.util.Hashtable;
013: import java.util.Iterator;
014: import java.util.List;
015:
016: import javax.xml.XMLConstants;
017: import javax.xml.bind.JAXBException;
018: import javax.xml.bind.UnmarshalException;
019: import javax.xml.bind.ValidationEvent;
020: import javax.xml.bind.ValidationEventHandler;
021:
022: import org.xml.sax.Attributes;
023: import org.xml.sax.Locator;
024: import org.xml.sax.SAXException;
025: import org.xml.sax.SAXParseException;
026:
027: import com.sun.xml.bind.JAXBAssertionError;
028: import com.sun.xml.bind.unmarshaller.Messages;
029: import com.sun.xml.bind.unmarshaller.Tracer;
030: import com.sun.xml.bind.util.AttributesImpl;
031:
032: /**
033: * Implementation of {@link UnmarshallerHandler}.
034: *
035: * This object converts SAX events into unmarshaller events and
036: * cooridnates the entire unmarshalling process.
037: *
038: * @author
039: * <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a>
040: */
041: public class SAXUnmarshallerHandlerImpl implements
042: SAXUnmarshallerHandler, UnmarshallingContext {
043: /**
044: * This flag is set to true at the startDocument event
045: * and false at the endDocument event.
046: *
047: * Until the first document is unmarshalled, we don't
048: * want to return an object. So this variable is initialized
049: * to true.
050: */
051: private boolean isUnmarshalInProgress = true;
052:
053: public SAXUnmarshallerHandlerImpl(UnmarshallerImpl _parent,
054: GrammarInfo _gi) {
055: this .parent = _parent;
056: grammarInfo = _gi;
057: startPrefixMapping("", ""); // by default, the default ns is bound to "".
058: }
059:
060: private final GrammarInfo grammarInfo;
061:
062: public GrammarInfo getGrammarInfo() {
063: return grammarInfo;
064: }
065:
066: /**
067: * Returns true if we should be collecting characters in the current element.
068: */
069: private final boolean shouldCollectText() {
070: return collectText[stackTop];
071: }
072:
073: public void startDocument() throws SAXException {
074: // reset the object
075: result = null;
076: handlerLen = 0;
077: patchers = null;
078: patchersLen = 0;
079: aborted = false;
080: isUnmarshalInProgress = true;
081:
082: stackTop = 0;
083: elementDepth = 1;
084: }
085:
086: public void endDocument() throws SAXException {
087: runPatchers();
088: isUnmarshalInProgress = false;
089: }
090:
091: public void startElement(String uri, String local, String qname,
092: Attributes atts) throws SAXException {
093:
094: // work gracefully with misconfigured parsers that don't support namespaces
095: if (uri == null)
096: uri = "";
097: if (local == null || local.length() == 0)
098: local = qname;
099: if (qname == null || qname.length() == 0)
100: qname = local;
101:
102: if (result == null) {
103: // this is the root element.
104: // create a root object and start unmarshalling
105: UnmarshallingEventHandler unmarshaller = grammarInfo
106: .createUnmarshaller(uri, local, this );
107: if (unmarshaller == null) {
108: // the registry doesn't know about this element.
109: //
110: // the no.1 cause of this problem is that your application is configuring
111: // an XML parser by your self and you forgot to call
112: // the SAXParserFactory.setNamespaceAware(true). When this happens, you see
113: // the namespace URI is reported as empty whereas you expect something else.
114: throw new SAXParseException(Messages.format(
115: Messages.UNEXPECTED_ROOT_ELEMENT2, uri, local,
116: computeExpectedRootElements()), getLocator());
117: }
118: result = unmarshaller.owner();
119:
120: pushContentHandler(unmarshaller, 0);
121: }
122:
123: processText(true);
124:
125: getCurrentHandler().enterElement(uri, local, qname, atts);
126: }
127:
128: public final void endElement(String uri, String local, String qname)
129: throws SAXException {
130:
131: // work gracefully with misconfigured parsers that don't support namespaces
132: if (uri == null)
133: uri = "";
134: if (local == null || local.length() == 0)
135: local = qname;
136: if (qname == null || qname.length() == 0)
137: qname = local;
138:
139: processText(false);
140: getCurrentHandler().leaveElement(uri, local, qname);
141: }
142:
143: /** Root object that is being unmarshalled. */
144: private Object result;
145:
146: public Object getResult() throws UnmarshalException {
147: if (isUnmarshalInProgress)
148: throw new IllegalStateException();
149:
150: if (!aborted)
151: return result;
152:
153: // there was an error.
154: throw new UnmarshalException((String) null);
155: }
156:
157: //
158: //
159: // handler stack maintainance
160: //
161: //
162: private UnmarshallingEventHandler[] handlers = new UnmarshallingEventHandler[16];
163: private int[] mementos = new int[16];
164: private int handlerLen = 0;
165:
166: public void pushContentHandler(UnmarshallingEventHandler handler,
167: int memento) {
168: if (handlerLen == handlers.length) {
169: // expand buffer
170: UnmarshallingEventHandler[] h = new UnmarshallingEventHandler[handlerLen * 2];
171: int[] m = new int[handlerLen * 2];
172: System.arraycopy(handlers, 0, h, 0, handlerLen);
173: System.arraycopy(mementos, 0, m, 0, handlerLen);
174: handlers = h;
175: mementos = m;
176: }
177: handlers[handlerLen] = handler;
178: mementos[handlerLen] = memento;
179: handlerLen++;
180: }
181:
182: public void popContentHandler() throws SAXException {
183: handlerLen--;
184: handlers[handlerLen] = null; // this handler is removed
185: getCurrentHandler().leaveChild(mementos[handlerLen]);
186: }
187:
188: public UnmarshallingEventHandler getCurrentHandler() {
189: return handlers[handlerLen - 1];
190: }
191:
192: //
193: //
194: // text handling
195: //
196: //
197: private StringBuffer buffer = new StringBuffer();
198:
199: protected void consumeText(String str, boolean ignorable)
200: throws SAXException {
201: if (ignorable && str.trim().length() == 0)
202: // if we are allowed to ignore text and
203: // the text is ignorable, ignore.
204: return;
205:
206: // otherwise perform a transition by this token.
207: getCurrentHandler().text(str);
208: }
209:
210: private void processText(boolean ignorable) throws SAXException {
211: if (shouldCollectText())
212: consumeText(buffer.toString(), ignorable);
213:
214: // avoid excessive object allocation, but also avoid
215: // keeping a huge array inside StringBuffer.
216: if (buffer.length() < 1024)
217: buffer.setLength(0);
218: else
219: buffer = new StringBuffer();
220: }
221:
222: public final void characters(char[] buf, int start, int len) {
223: if (shouldCollectText())
224: buffer.append(buf, start, len);
225: }
226:
227: public final void ignorableWhitespace(char[] buf, int start, int len) {
228: characters(buf, start, len);
229: }
230:
231: //
232: //
233: // namespace binding maintainance
234: //
235: //
236: private String[] nsBind = new String[16];
237: private int nsLen = 0;
238:
239: // in the current scope, nsBind[0] - nsBind[idxStack[idxStackTop]-1]
240: // are active.
241: // use {@link #elementDepth} and {@link stackTop} to access.
242: private int[] idxStack = new int[16];
243:
244: public void startPrefixMapping(String prefix, String uri) {
245: if (nsBind.length == nsLen) {
246: // expand the buffer
247: String[] n = new String[nsLen * 2];
248: System.arraycopy(nsBind, 0, n, 0, nsLen);
249: nsBind = n;
250: }
251: nsBind[nsLen++] = prefix;
252: nsBind[nsLen++] = uri;
253: }
254:
255: public void endPrefixMapping(String prefix) {
256: nsLen -= 2;
257: }
258:
259: public String resolveNamespacePrefix(String prefix) {
260: if (prefix.equals("xml"))
261: return "http://www.w3.org/XML/1998/namespace";
262:
263: for (int i = idxStack[stackTop] - 2; i >= 0; i -= 2) {
264: if (prefix.equals(nsBind[i]))
265: return nsBind[i + 1];
266: }
267: return null;
268: }
269:
270: public String[] getNewlyDeclaredPrefixes() {
271: return getPrefixList(idxStack[stackTop - 1]);
272: }
273:
274: public String[] getAllDeclaredPrefixes() {
275: return getPrefixList(2); // skip the default ""->"" mapping
276: }
277:
278: private String[] getPrefixList(int startIndex) {
279: int size = (idxStack[stackTop] - startIndex) / 2;
280: String[] r = new String[size];
281: for (int i = 0; i < r.length; i++)
282: r[i] = nsBind[startIndex + i * 2];
283: return r;
284: }
285:
286: //
287: // NamespaceContext2 implementation
288: //
289: public Iterator getPrefixes(String uri) {
290: // wrap it into unmodifiable list so that the remove method
291: // will throw UnsupportedOperationException.
292: return Collections.unmodifiableList(getAllPrefixesInList(uri))
293: .iterator();
294: }
295:
296: private List getAllPrefixesInList(String uri) {
297: List a = new ArrayList();
298:
299: if (uri.equals(XMLConstants.XML_NS_URI)) {
300: a.add(XMLConstants.XML_NS_PREFIX);
301: return a;
302: }
303: if (uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
304: a.add(XMLConstants.XMLNS_ATTRIBUTE);
305: return a;
306: }
307: if (uri == null)
308: throw new IllegalArgumentException();
309:
310: for (int i = nsLen - 2; i >= 0; i -= 2)
311: if (uri.equals(nsBind[i + 1]))
312: if (getNamespaceURI(nsBind[i]).equals(nsBind[i + 1]))
313: // make sure that this prefix is still effective.
314: a.add(nsBind[i]);
315:
316: return a;
317: }
318:
319: public String getPrefix(String uri) {
320: if (uri.equals(XMLConstants.XML_NS_URI))
321: return XMLConstants.XML_NS_PREFIX;
322: if (uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI))
323: return XMLConstants.XMLNS_ATTRIBUTE;
324: if (uri == null)
325: throw new IllegalArgumentException();
326:
327: for (int i = idxStack[stackTop] - 2; i >= 0; i -= 2)
328: if (uri.equals(nsBind[i + 1]))
329: if (getNamespaceURI(nsBind[i]).equals(nsBind[i + 1]))
330: // make sure that this prefix is still effective.
331: return nsBind[i];
332:
333: return null;
334: }
335:
336: public String getNamespaceURI(String prefix) {
337: if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE))
338: return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
339: if (prefix == null)
340: throw new IllegalArgumentException();
341:
342: return resolveNamespacePrefix(prefix);
343: }
344:
345: //
346: //
347: // Attribute handling
348: //
349: //
350: /**
351: * Attributes stack.
352: */
353: private AttributesImpl[] attStack = new AttributesImpl[16];
354: /**
355: * Element nesting level.
356: */
357: private int elementDepth;
358: /**
359: * Always {@link #elementDepth}-1.
360: */
361: private int stackTop;
362:
363: /**
364: * Stack of collectText flag.
365: * False means text can be ignored for this element.
366: *
367: * Use {@link #elementDepth} and {@link #stackTop} to access the array.
368: */
369: private boolean[] collectText = new boolean[16];
370:
371: public void pushAttributes(Attributes atts, boolean collectTextFlag) {
372:
373: if (attStack.length == elementDepth) {
374: // reallocate the buffer
375: AttributesImpl[] buf1 = new AttributesImpl[attStack.length * 2];
376: System.arraycopy(attStack, 0, buf1, 0, attStack.length);
377: attStack = buf1;
378:
379: int[] buf2 = new int[idxStack.length * 2];
380: System.arraycopy(idxStack, 0, buf2, 0, idxStack.length);
381: idxStack = buf2;
382:
383: boolean[] buf3 = new boolean[collectText.length * 2];
384: System.arraycopy(collectText, 0, buf3, 0,
385: collectText.length);
386: collectText = buf3;
387: }
388:
389: elementDepth++;
390: stackTop++;
391:
392: // push the stack
393: AttributesImpl a = attStack[stackTop];
394: if (a == null)
395: attStack[stackTop] = a = new AttributesImpl();
396: else
397: a.clear();
398:
399: // since Attributes object is mutable, it is criticall important
400: // to make a copy.
401: // also symbolize attribute names
402: for (int i = 0; i < atts.getLength(); i++) {
403: String auri = atts.getURI(i);
404: String alocal = atts.getLocalName(i);
405: String avalue = atts.getValue(i);
406: String aqname = atts.getQName(i);
407:
408: // work gracefully with misconfigured parsers that don't support namespaces
409: if (auri == null)
410: auri = "";
411: if (alocal == null || alocal.length() == 0)
412: alocal = aqname;
413: if (aqname == null || aqname.length() == 0)
414: aqname = alocal;
415:
416: // <foo xsi:nil="false">some value</foo> is a valid fragment, however
417: // we need a look ahead to correctly handle this case.
418: // (because when we process @xsi:nil, we don't know what the value is,
419: // and by the time we read "false", we can't cancel this attribute anymore.)
420: //
421: // as a quick workaround, we remove @xsi:nil if the value is false.
422: if (auri == "http://www.w3.org/2001/XMLSchema-instance"
423: && alocal == "nil") {
424: String v = avalue.trim();
425: if (v.equals("false") || v.equals("0"))
426: continue; // skip this attribute
427: }
428:
429: // otherwise just add it.
430: a.addAttribute(auri, alocal, aqname, atts.getType(i),
431: avalue);
432: }
433:
434: // start a new namespace scope
435: idxStack[stackTop] = nsLen;
436:
437: collectText[stackTop] = collectTextFlag;
438: }
439:
440: public void popAttributes() {
441: stackTop--;
442: elementDepth--;
443: }
444:
445: public Attributes getUnconsumedAttributes() {
446: return attStack[stackTop];
447: }
448:
449: /**
450: * @param uri,local
451: * has to be interned.
452: */
453: public int getAttribute(String uri, String local) {
454: return attStack[stackTop].getIndexFast(uri, local);
455: }
456:
457: public void consumeAttribute(int idx) throws SAXException {
458: AttributesImpl a = attStack[stackTop];
459:
460: String uri = a.getURI(idx);
461: String local = a.getLocalName(idx);
462: String qname = a.getQName(idx);
463: String value = a.getValue(idx);
464:
465: // mark the attribute as consumed
466: // we need to remove the attribute before we process it
467: // because the event handler might access attributes.
468: a.removeAttribute(idx);
469:
470: getCurrentHandler().enterAttribute(uri, local, qname);
471: consumeText(value, false);
472: getCurrentHandler().leaveAttribute(uri, local, qname);
473: }
474:
475: public String eatAttribute(int idx) throws SAXException {
476: AttributesImpl a = attStack[stackTop];
477:
478: String value = a.getValue(idx);
479:
480: // mark the attribute as consumed
481: a.removeAttribute(idx);
482:
483: return value;
484: }
485:
486: //
487: //
488: // ID/IDREF related code
489: //
490: //
491: /**
492: * Submitted patchers in the order they've submitted.
493: * Many XML vocabulary doesn't use ID/IDREF at all, so we
494: * initialize it with null.
495: */
496: private Runnable[] patchers = null;
497: private int patchersLen = 0;
498:
499: public void addPatcher(Runnable job) {
500: // re-allocate buffer if necessary
501: if (patchers == null)
502: patchers = new Runnable[32];
503: if (patchers.length == patchersLen) {
504: Runnable[] buf = new Runnable[patchersLen * 2];
505: System.arraycopy(patchers, 0, buf, 0, patchersLen);
506: patchers = buf;
507: }
508: patchers[patchersLen++] = job;
509: }
510:
511: /** Executes all the patchers. */
512: private void runPatchers() {
513: if (patchers != null) {
514: for (int i = 0; i < patchersLen; i++)
515: patchers[i].run();
516: }
517: }
518:
519: /** Records ID->Object map. */
520: private Hashtable idmap = null;
521:
522: public String addToIdTable(String id) {
523: if (idmap == null)
524: idmap = new Hashtable();
525: idmap.put(id, getCurrentHandler().owner());
526: return id;
527: }
528:
529: public Object getObjectFromId(String id) {
530: if (idmap == null)
531: return null;
532: return idmap.get(id);
533: }
534:
535: //
536: //
537: // Other SAX callbacks
538: //
539: //
540: public void skippedEntity(String name) {
541: }
542:
543: public void processingInstruction(String target, String data) {
544: // just ignore
545: }
546:
547: public void setDocumentLocator(Locator loc) {
548: locator = loc;
549: }
550:
551: public Locator getLocator() {
552: return locator;
553: }
554:
555: private Locator locator;
556:
557: //
558: //
559: // error handling
560: //
561: //
562: private final UnmarshallerImpl parent;
563: private boolean aborted = false;
564:
565: public void handleEvent(ValidationEvent event, boolean canRecover)
566: throws SAXException {
567: ValidationEventHandler eventHandler;
568: try {
569: eventHandler = parent.getEventHandler();
570: } catch (JAXBException e) {
571: // impossible.
572: throw new JAXBAssertionError();
573: }
574:
575: boolean recover = eventHandler.handleEvent(event);
576:
577: // if the handler says "abort", we will not return the object
578: // from the unmarshaller.getResult()
579: if (!recover)
580: aborted = true;
581:
582: if (!canRecover || !recover)
583: throw new SAXException(new UnmarshalException(event
584: .getMessage(), event.getLinkedException()));
585: }
586:
587: //
588: //
589: // ValidationContext implementation
590: //
591: //
592: public String getBaseUri() {
593: return null;
594: }
595:
596: public boolean isUnparsedEntity(String s) {
597: return true;
598: }
599:
600: public boolean isNotation(String s) {
601: return true;
602: }
603:
604: //
605: //
606: // debug trace methods
607: //
608: //
609: private Tracer tracer;
610:
611: public void setTracer(Tracer t) {
612: this .tracer = t;
613: }
614:
615: public Tracer getTracer() {
616: if (tracer == null)
617: tracer = new Tracer.Standard();
618: return tracer;
619: }
620:
621: /**
622: * Computes the names of possible root elements for a better error diagnosis.
623: */
624: private String computeExpectedRootElements() {
625: String r = "";
626:
627: String[] probePoints = grammarInfo.getProbePoints();
628: for (int i = 0; i < probePoints.length; i += 2) {
629: if (grammarInfo.recognize(probePoints[i],
630: probePoints[i + 1])) {
631: if (r.length() != 0)
632: r += ',';
633: r += "<{" + probePoints[i] + "}" + probePoints[i + 1]
634: + ">";
635: }
636: }
637:
638: return r;
639: }
640: }
|