Source Code Cross Referenced for UnmarshallingContext.java in  » 6.0-JDK-Modules » jaxb-impl » com » sun » xml » bind » v2 » runtime » unmarshaller » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » jaxb impl » com.sun.xml.bind.v2.runtime.unmarshaller 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         * 
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         * 
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common Development
0008:         * and Distribution License("CDDL") (collectively, the "License").  You
0009:         * may not use this file except in compliance with the License. You can obtain
0010:         * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
0011:         * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
0012:         * language governing permissions and limitations under the License.
0013:         * 
0014:         * When distributing the software, include this License Header Notice in each
0015:         * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
0016:         * Sun designates this particular file as subject to the "Classpath" exception
0017:         * as provided by Sun in the GPL Version 2 section of the License file that
0018:         * accompanied this code.  If applicable, add the following below the License
0019:         * Header, with the fields enclosed by brackets [] replaced by your own
0020:         * identifying information: "Portions Copyrighted [year]
0021:         * [name of copyright owner]"
0022:         * 
0023:         * Contributor(s):
0024:         * 
0025:         * If you wish your version of this file to be governed by only the CDDL or
0026:         * only the GPL Version 2, indicate your decision by adding "[Contributor]
0027:         * elects to include this software in this distribution under the [CDDL or GPL
0028:         * Version 2] license."  If you don't indicate a single choice of license, a
0029:         * recipient has the option to distribute your version of this file under
0030:         * either the CDDL, the GPL Version 2 or to extend the choice of license to
0031:         * its licensees as provided above.  However, if you add GPL Version 2 code
0032:         * and therefore, elected the GPL Version 2 license, then the option applies
0033:         * only if the new code is made subject to such option by the copyright
0034:         * holder.
0035:         */
0036:
0037:        package com.sun.xml.bind.v2.runtime.unmarshaller;
0038:
0039:        import java.lang.reflect.InvocationTargetException;
0040:        import java.lang.reflect.Method;
0041:        import java.util.ArrayList;
0042:        import java.util.Collection;
0043:        import java.util.Collections;
0044:        import java.util.HashMap;
0045:        import java.util.Iterator;
0046:        import java.util.List;
0047:        import java.util.Map;
0048:        import java.util.concurrent.Callable;
0049:
0050:        import javax.xml.XMLConstants;
0051:        import javax.xml.bind.JAXBElement;
0052:        import javax.xml.bind.UnmarshalException;
0053:        import javax.xml.bind.Unmarshaller;
0054:        import javax.xml.bind.ValidationEvent;
0055:        import javax.xml.bind.ValidationEventHandler;
0056:        import javax.xml.bind.ValidationEventLocator;
0057:        import javax.xml.bind.helpers.ValidationEventImpl;
0058:        import javax.xml.namespace.NamespaceContext;
0059:        import javax.xml.namespace.QName;
0060:
0061:        import com.sun.istack.NotNull;
0062:        import com.sun.istack.Nullable;
0063:        import com.sun.istack.SAXParseException2;
0064:        import com.sun.xml.bind.IDResolver;
0065:        import com.sun.xml.bind.api.AccessorException;
0066:        import com.sun.xml.bind.api.ClassResolver;
0067:        import com.sun.xml.bind.unmarshaller.InfosetScanner;
0068:        import com.sun.xml.bind.v2.ClassFactory;
0069:        import com.sun.xml.bind.v2.runtime.AssociationMap;
0070:        import com.sun.xml.bind.v2.runtime.Coordinator;
0071:        import com.sun.xml.bind.v2.runtime.JAXBContextImpl;
0072:        import com.sun.xml.bind.v2.runtime.JaxBeanInfo;
0073:
0074:        import org.xml.sax.ErrorHandler;
0075:        import org.xml.sax.Locator;
0076:        import org.xml.sax.SAXException;
0077:        import org.xml.sax.helpers.LocatorImpl;
0078:
0079:        /**
0080:         * Center of the unmarshalling.
0081:         *
0082:         * <p>
0083:         * This object is responsible for coordinating {@link Loader}s to
0084:         * perform the whole unmarshalling.
0085:         *
0086:         * @author Kohsuke Kawaguchi
0087:         */
0088:        public final class UnmarshallingContext extends Coordinator implements 
0089:                NamespaceContext, ValidationEventHandler, ErrorHandler,
0090:                XmlVisitor, XmlVisitor.TextPredictor {
0091:
0092:            /**
0093:             * Root state.
0094:             */
0095:            private final State root;
0096:
0097:            /**
0098:             * The currently active state.
0099:             */
0100:            private State current;
0101:
0102:            private static final LocatorEx DUMMY_INSTANCE;
0103:
0104:            static {
0105:                LocatorImpl loc = new LocatorImpl();
0106:                loc.setPublicId(null);
0107:                loc.setSystemId(null);
0108:                loc.setLineNumber(-1);
0109:                loc.setColumnNumber(-1);
0110:                DUMMY_INSTANCE = new LocatorExWrapper(loc);
0111:            }
0112:
0113:            private @NotNull
0114:            LocatorEx locator = DUMMY_INSTANCE;
0115:
0116:            /** Root object that is being unmarshalled. */
0117:            private Object result;
0118:
0119:            /**
0120:             * If non-null, this unmarshaller will unmarshal {@code JAXBElement<EXPECTEDTYPE>}
0121:             * regardless of the tag name, as opposed to deciding the root object by using
0122:             * the tag name.
0123:             *
0124:             * The property has a package-level access, because we cannot copy this value
0125:             * to {@link UnmarshallingContext} when it is created. The property
0126:             * on {@link Unmarshaller} could be changed after the handler is created.
0127:             */
0128:            private JaxBeanInfo expectedType;
0129:
0130:            /**
0131:             * Handles ID/IDREF.
0132:             */
0133:            private IDResolver idResolver;
0134:
0135:            /**
0136:             * This flag is set to true at the startDocument event
0137:             * and false at the endDocument event.
0138:             *
0139:             * Until the first document is unmarshalled, we don't
0140:             * want to return an object. So this variable is initialized
0141:             * to true.
0142:             */
0143:            private boolean isUnmarshalInProgress = true;
0144:            private boolean aborted = false;
0145:
0146:            public final UnmarshallerImpl parent;
0147:
0148:            /**
0149:             * If the unmarshaller is doing associative unmarshalling,
0150:             * this field is initialized to non-null.
0151:             */
0152:            private final AssociationMap assoc;
0153:
0154:            /**
0155:             * Indicates whether we are doing in-place unmarshalling
0156:             * or not.
0157:             *
0158:             * <p>
0159:             * This flag is unused when {@link #assoc}==null.
0160:             * If it's non-null, then <tt>true</tt> indicates
0161:             * that we are doing in-place associative unmarshalling.
0162:             * If <tt>false</tt>, then we are doing associative unmarshalling
0163:             * without object reuse.
0164:             */
0165:            private boolean isInplaceMode;
0166:
0167:            /**
0168:             * This object is consulted to get the element object for
0169:             * the current element event.
0170:             *
0171:             * This is used when we are building an association map.
0172:             */
0173:            private InfosetScanner scanner;
0174:
0175:            private Object currentElement;
0176:
0177:            /**
0178:             * @see XmlVisitor#startDocument(LocatorEx, NamespaceContext)
0179:             */
0180:            private NamespaceContext environmentNamespaceContext;
0181:
0182:            /**
0183:             * Used to discover additional classes when we hit unknown elements/types.
0184:             */
0185:            public @Nullable
0186:            ClassResolver classResolver;
0187:
0188:            /**
0189:             * State information for each element.
0190:             */
0191:            public final class State {
0192:                /**
0193:                 * Loader that owns this element.
0194:                 */
0195:                public Loader loader;
0196:                /**
0197:                 * Once {@link #loader} is completed, this receiver
0198:                 * receives the result.
0199:                 */
0200:                public Receiver receiver;
0201:
0202:                public Intercepter intercepter;
0203:
0204:                /**
0205:                 * Object being unmarshalled by this {@link #loader}.
0206:                 */
0207:                public Object target;
0208:
0209:                /**
0210:                 * Hack for making JAXBElement unmarshalling work.
0211:                 */
0212:                public Object backup;
0213:
0214:                /**
0215:                 * Number of {@link UnmarshallingContext#nsBind}s declared thus far.
0216:                 * (The value of {@link UnmarshallingContext#nsLen} when this state is pushed.
0217:                 */
0218:                private int numNsDecl;
0219:
0220:                /**
0221:                 * If this element has an element default value.
0222:                 *
0223:                 * This should be set by either a parent {@link Loader} when
0224:                 * {@link Loader#childElement(State, TagName)} is called
0225:                 * or by a child {@link Loader} when
0226:                 * {@link Loader#startElement(State, TagName)} is called.
0227:                 */
0228:                public String elementDefaultValue;
0229:
0230:                /**
0231:                 * {@link State} for the parent element
0232:                 *
0233:                 * {@link State} objects form a doubly linked list.
0234:                 */
0235:                public final State prev;
0236:                private State next;
0237:
0238:                /**
0239:                 * Gets the context.
0240:                 */
0241:                public UnmarshallingContext getContext() {
0242:                    return UnmarshallingContext.this ;
0243:                }
0244:
0245:                private State(State prev) {
0246:                    this .prev = prev;
0247:                    if (prev != null)
0248:                        prev.next = this ;
0249:                }
0250:
0251:                private void push() {
0252:                    if (next == null)
0253:                        allocateMoreStates();
0254:                    State n = next;
0255:                    n.numNsDecl = nsLen;
0256:                    current = n;
0257:                }
0258:
0259:                private void pop() {
0260:                    assert prev != null;
0261:                    loader = null;
0262:                    receiver = null;
0263:                    intercepter = null;
0264:                    elementDefaultValue = null;
0265:                    target = null;
0266:                    current = prev;
0267:                }
0268:            }
0269:
0270:            /**
0271:             * Stub to the user-specified factory method.
0272:             */
0273:            private static class Factory {
0274:                private final Object factorInstance;
0275:                private final Method method;
0276:
0277:                public Factory(Object factorInstance, Method method) {
0278:                    this .factorInstance = factorInstance;
0279:                    this .method = method;
0280:                }
0281:
0282:                public Object createInstance() throws SAXException {
0283:                    try {
0284:                        return method.invoke(factorInstance);
0285:                    } catch (IllegalAccessException e) {
0286:                        getInstance().handleError(e, false);
0287:                    } catch (InvocationTargetException e) {
0288:                        getInstance().handleError(e, false);
0289:                    }
0290:                    return null; // can never be executed
0291:                }
0292:            }
0293:
0294:            /**
0295:             * Creates a new unmarshaller.
0296:             *
0297:             * @param assoc
0298:             *      Must be both non-null when the unmarshaller does the
0299:             *      in-place unmarshalling. Otherwise must be both null.
0300:             */
0301:            public UnmarshallingContext(UnmarshallerImpl _parent,
0302:                    AssociationMap assoc) {
0303:                this .parent = _parent;
0304:                this .assoc = assoc;
0305:                this .root = this .current = new State(null);
0306:                allocateMoreStates();
0307:            }
0308:
0309:            public void reset(InfosetScanner scanner, boolean isInplaceMode,
0310:                    JaxBeanInfo expectedType, IDResolver idResolver) {
0311:                this .scanner = scanner;
0312:                this .isInplaceMode = isInplaceMode;
0313:                this .expectedType = expectedType;
0314:                this .idResolver = idResolver;
0315:            }
0316:
0317:            public JAXBContextImpl getJAXBContext() {
0318:                return parent.context;
0319:            }
0320:
0321:            public State getCurrentState() {
0322:                return current;
0323:            }
0324:
0325:            /**
0326:             * On top of {@link JAXBContextImpl#selectRootLoader(State, TagName)},
0327:             * this method also consults {@link ClassResolver}.
0328:             *
0329:             * @throws SAXException
0330:             *      if {@link ValidationEventHandler} reported a failure.
0331:             */
0332:            public Loader selectRootLoader(State state, TagName tag)
0333:                    throws SAXException {
0334:                try {
0335:                    Loader l = getJAXBContext().selectRootLoader(state, tag);
0336:                    if (l != null)
0337:                        return l;
0338:
0339:                    if (classResolver != null) {
0340:                        Class<?> clazz = classResolver.resolveElementName(
0341:                                tag.uri, tag.local);
0342:                        if (clazz != null) {
0343:                            JAXBContextImpl enhanced = getJAXBContext()
0344:                                    .createAugmented(clazz);
0345:                            JaxBeanInfo<?> bi = enhanced.getBeanInfo(clazz);
0346:                            return bi.getLoader(enhanced, true);
0347:                        }
0348:                    }
0349:                } catch (RuntimeException e) {
0350:                    throw e;
0351:                } catch (Exception e) {
0352:                    handleError(e);
0353:                }
0354:
0355:                return null;
0356:            }
0357:
0358:            /**
0359:             * Allocates a few more {@link State}s.
0360:             *
0361:             * Allocating multiple {@link State}s at once allows those objects
0362:             * to be allocated near each other, which reduces the working set
0363:             * of CPU. It improves the chance the relevant data is in the cache.
0364:             */
0365:            private void allocateMoreStates() {
0366:                // this method should be used only when we run out of a state.
0367:                assert current.next == null;
0368:
0369:                State s = current;
0370:                for (int i = 0; i < 8; i++)
0371:                    s = new State(s);
0372:            }
0373:
0374:            /**
0375:             * User-specified factory methods.
0376:             */
0377:            private final Map<Class, Factory> factories = new HashMap<Class, Factory>();
0378:
0379:            public void setFactories(Object factoryInstances) {
0380:                factories.clear();
0381:                if (factoryInstances == null) {
0382:                    return;
0383:                }
0384:                if (factoryInstances instanceof  Object[]) {
0385:                    for (Object factory : (Object[]) factoryInstances) {
0386:                        // look for all the public methods inlcuding derived ones
0387:                        addFactory(factory);
0388:                    }
0389:                } else {
0390:                    addFactory(factoryInstances);
0391:                }
0392:            }
0393:
0394:            private void addFactory(Object factory) {
0395:                for (Method m : factory.getClass().getMethods()) {
0396:                    // look for methods whose signature is T createXXX()
0397:                    if (!m.getName().startsWith("create"))
0398:                        continue;
0399:                    if (m.getParameterTypes().length > 0)
0400:                        continue;
0401:
0402:                    Class type = m.getReturnType();
0403:
0404:                    factories.put(type, new Factory(factory, m));
0405:                }
0406:            }
0407:
0408:            public void startDocument(LocatorEx locator,
0409:                    NamespaceContext nsContext) throws SAXException {
0410:                if (locator != null)
0411:                    this .locator = locator;
0412:                this .environmentNamespaceContext = nsContext;
0413:                // reset the object
0414:                result = null;
0415:                current = root;
0416:
0417:                patchersLen = 0;
0418:                aborted = false;
0419:                isUnmarshalInProgress = true;
0420:                nsLen = 0;
0421:
0422:                setThreadAffinity();
0423:
0424:                if (expectedType != null)
0425:                    root.loader = EXPECTED_TYPE_ROOT_LOADER;
0426:                else
0427:                    root.loader = DEFAULT_ROOT_LOADER;
0428:
0429:                idResolver.startDocument(this );
0430:            }
0431:
0432:            public void startElement(TagName tagName) throws SAXException {
0433:                pushCoordinator();
0434:                try {
0435:                    _startElement(tagName);
0436:                } finally {
0437:                    popCoordinator();
0438:                }
0439:            }
0440:
0441:            private void _startElement(TagName tagName) throws SAXException {
0442:
0443:                // remember the current element if we are interested in it.
0444:                // because the inner peer might not be found while we consume
0445:                // the enter element token, we need to keep this information
0446:                // longer than this callback. That's why we assign it to a field.
0447:                if (assoc != null)
0448:                    currentElement = scanner.getCurrentElement();
0449:
0450:                Loader h = current.loader;
0451:                current.push();
0452:
0453:                // tell the parent about the new child
0454:                h.childElement(current, tagName);
0455:                assert current.loader != null; // the childElement should register this
0456:                // and tell the new child that you are activated
0457:                current.loader.startElement(current, tagName);
0458:            }
0459:
0460:            public void text(CharSequence pcdata) throws SAXException {
0461:                State cur = current;
0462:                pushCoordinator();
0463:                try {
0464:                    if (cur.elementDefaultValue != null) {
0465:                        if (pcdata.length() == 0) {
0466:                            // send the default value into the unmarshaller instead
0467:                            pcdata = cur.elementDefaultValue;
0468:                        }
0469:                    }
0470:                    cur.loader.text(cur, pcdata);
0471:                } finally {
0472:                    popCoordinator();
0473:                }
0474:            }
0475:
0476:            public final void endElement(TagName tagName) throws SAXException {
0477:                pushCoordinator();
0478:                try {
0479:                    State child = current;
0480:
0481:                    // tell the child that your time is up
0482:                    child.loader.leaveElement(child, tagName);
0483:
0484:                    // child.pop will erase them so store them now
0485:                    Object target = child.target;
0486:                    Receiver recv = child.receiver;
0487:                    Intercepter intercepter = child.intercepter;
0488:                    child.pop();
0489:
0490:                    // then let the parent know
0491:                    if (intercepter != null)
0492:                        target = intercepter.intercept(current, target);
0493:                    if (recv != null)
0494:                        recv.receive(current, target);
0495:                } finally {
0496:                    popCoordinator();
0497:                }
0498:            }
0499:
0500:            public void endDocument() throws SAXException {
0501:                runPatchers();
0502:                idResolver.endDocument();
0503:
0504:                isUnmarshalInProgress = false;
0505:                currentElement = null;
0506:                locator = DUMMY_INSTANCE;
0507:                environmentNamespaceContext = null;
0508:
0509:                // at the successful completion, scope must be all closed
0510:                assert root == current;
0511:
0512:                resetThreadAffinity();
0513:            }
0514:
0515:            /**
0516:             * You should be always calling this through {@link TextPredictor}.
0517:             */
0518:            @Deprecated
0519:            public boolean expectText() {
0520:                return current.loader.expectText;
0521:            }
0522:
0523:            /**
0524:             * You should be always getting {@link TextPredictor} from {@link XmlVisitor}.
0525:             */
0526:            @Deprecated
0527:            public TextPredictor getPredictor() {
0528:                return this ;
0529:            }
0530:
0531:            public UnmarshallingContext getContext() {
0532:                return this ;
0533:            }
0534:
0535:            /**
0536:             * Gets the result of the unmarshalling
0537:             */
0538:            public Object getResult() throws UnmarshalException {
0539:                if (isUnmarshalInProgress)
0540:                    throw new IllegalStateException();
0541:
0542:                if (!aborted)
0543:                    return result;
0544:
0545:                // there was an error.
0546:                throw new UnmarshalException((String) null);
0547:            }
0548:
0549:            /**
0550:             * Creates a new instance of the specified class.
0551:             * In the unmarshaller, we need to check the user-specified factory class.
0552:             */
0553:            public Object createInstance(Class<?> clazz) throws SAXException {
0554:                if (!factories.isEmpty()) {
0555:                    Factory factory = factories.get(clazz);
0556:                    if (factory != null)
0557:                        return factory.createInstance();
0558:                }
0559:                return ClassFactory.create(clazz);
0560:            }
0561:
0562:            /**
0563:             * Creates a new instance of the specified class.
0564:             * In the unmarshaller, we need to check the user-specified factory class.
0565:             */
0566:            public Object createInstance(JaxBeanInfo beanInfo)
0567:                    throws SAXException {
0568:                if (!factories.isEmpty()) {
0569:                    Factory factory = factories.get(beanInfo.jaxbType);
0570:                    if (factory != null)
0571:                        return factory.createInstance();
0572:                }
0573:                try {
0574:                    return beanInfo.createInstance(this );
0575:                } catch (IllegalAccessException e) {
0576:                    Loader.reportError("Unable to create an instance of "
0577:                            + beanInfo.jaxbType.getName(), e, false);
0578:                } catch (InvocationTargetException e) {
0579:                    Loader.reportError("Unable to create an instance of "
0580:                            + beanInfo.jaxbType.getName(), e, false);
0581:                } catch (InstantiationException e) {
0582:                    Loader.reportError("Unable to create an instance of "
0583:                            + beanInfo.jaxbType.getName(), e, false);
0584:                }
0585:                return null; // can never be here
0586:            }
0587:
0588:            //
0589:            //
0590:            // error handling
0591:            //
0592:            //
0593:
0594:            /**
0595:             * Reports an error to the user, and asks if s/he wants
0596:             * to recover. If the canRecover flag is false, regardless
0597:             * of the client instruction, an exception will be thrown.
0598:             *
0599:             * Only if the flag is true and the user wants to recover from an error,
0600:             * the method returns normally.
0601:             *
0602:             * The thrown exception will be catched by the unmarshaller.
0603:             */
0604:            public void handleEvent(ValidationEvent event, boolean canRecover)
0605:                    throws SAXException {
0606:                ValidationEventHandler eventHandler = parent.getEventHandler();
0607:
0608:                boolean recover = eventHandler.handleEvent(event);
0609:
0610:                // if the handler says "abort", we will not return the object
0611:                // from the unmarshaller.getResult()
0612:                if (!recover)
0613:                    aborted = true;
0614:
0615:                if (!canRecover || !recover)
0616:                    throw new SAXParseException2(event.getMessage(), locator,
0617:                            new UnmarshalException(event.getMessage(), event
0618:                                    .getLinkedException()));
0619:            }
0620:
0621:            public boolean handleEvent(ValidationEvent event) {
0622:                try {
0623:                    // if the handler says "abort", we will not return the object.
0624:                    boolean recover = parent.getEventHandler().handleEvent(
0625:                            event);
0626:                    if (!recover)
0627:                        aborted = true;
0628:                    return recover;
0629:                } catch (RuntimeException re) {
0630:                    // if client event handler causes a runtime exception, then we
0631:                    // have to return false.
0632:                    return false;
0633:                }
0634:            }
0635:
0636:            /**
0637:             * Reports an exception found during the unmarshalling to the user.
0638:             * This method is a convenience method that calls into
0639:             * {@link #handleEvent(ValidationEvent, boolean)}
0640:             */
0641:            public void handleError(Exception e) throws SAXException {
0642:                handleError(e, true);
0643:            }
0644:
0645:            public void handleError(Exception e, boolean canRecover)
0646:                    throws SAXException {
0647:                handleEvent(new ValidationEventImpl(ValidationEvent.ERROR, e
0648:                        .getMessage(), locator.getLocation(), e), canRecover);
0649:            }
0650:
0651:            public void handleError(String msg) {
0652:                handleEvent(new ValidationEventImpl(ValidationEvent.ERROR, msg,
0653:                        locator.getLocation()));
0654:            }
0655:
0656:            protected ValidationEventLocator getLocation() {
0657:                return locator.getLocation();
0658:            }
0659:
0660:            /**
0661:             * Gets the current source location information in SAX {@link Locator}.
0662:             * <p>
0663:             * Sometimes the unmarshaller works against a different kind of XML source,
0664:             * making this information meaningless.
0665:             */
0666:            public LocatorEx getLocator() {
0667:                return locator;
0668:            }
0669:
0670:            /**
0671:             * Called when there's no corresponding ID value.
0672:             */
0673:            public void errorUnresolvedIDREF(Object bean, String idref,
0674:                    LocatorEx loc) throws SAXException {
0675:                handleEvent(new ValidationEventImpl(ValidationEvent.ERROR,
0676:                        Messages.UNRESOLVED_IDREF.format(idref), loc
0677:                                .getLocation()), true);
0678:            }
0679:
0680:            //
0681:            //
0682:            // ID/IDREF related code
0683:            //
0684:            //
0685:            /**
0686:             * Submitted patchers in the order they've submitted.
0687:             * Many XML vocabulary doesn't use ID/IDREF at all, so we
0688:             * initialize it with null.
0689:             */
0690:            private Patcher[] patchers = null;
0691:            private int patchersLen = 0;
0692:
0693:            /**
0694:             * Adds a job that will be executed at the last of the unmarshalling.
0695:             * This method is used to support ID/IDREF feature, but it can be used
0696:             * for other purposes as well.
0697:             *
0698:             * @param   job
0699:             *      The run method of this object is called.
0700:             */
0701:            public void addPatcher(Patcher job) {
0702:                // re-allocate buffer if necessary
0703:                if (patchers == null)
0704:                    patchers = new Patcher[32];
0705:                if (patchers.length == patchersLen) {
0706:                    Patcher[] buf = new Patcher[patchersLen * 2];
0707:                    System.arraycopy(patchers, 0, buf, 0, patchersLen);
0708:                    patchers = buf;
0709:                }
0710:                patchers[patchersLen++] = job;
0711:            }
0712:
0713:            /** Executes all the patchers. */
0714:            private void runPatchers() throws SAXException {
0715:                if (patchers != null) {
0716:                    for (int i = 0; i < patchersLen; i++) {
0717:                        patchers[i].run();
0718:                        patchers[i] = null; // free memory
0719:                    }
0720:                }
0721:            }
0722:
0723:            /**
0724:             * Adds the object which is currently being unmarshalled
0725:             * to the ID table.
0726:             *
0727:             * @return
0728:             *      Returns the value passed as the parameter.
0729:             *      This is a hack, but this makes it easier for ID
0730:             *      transducer to do its job.
0731:             */
0732:            // TODO: what shall we do if the ID is already declared?
0733:            //
0734:            // throwing an exception is one way. Overwriting the previous one
0735:            // is another way. The latter allows us to process invalid documents,
0736:            // while the former makes it impossible to handle them.
0737:            //
0738:            // I prefer to be flexible in terms of invalid document handling,
0739:            // so chose not to throw an exception.
0740:            //
0741:            // I believe this is an implementation choice, not the spec issue.
0742:            // -kk
0743:            public String addToIdTable(String id) throws SAXException {
0744:                // Hmm...
0745:                // in cases such as when ID is used as an attribute, or as @XmlValue
0746:                // the target wilil be current.target.
0747:                // but in some other cases, such as when ID is used as a child element
0748:                // or a value of JAXBElement, it's current.prev.target.
0749:                // I don't know if this detection logic is complete
0750:                Object o = current.target;
0751:                if (o == null)
0752:                    o = current.prev.target;
0753:                idResolver.bind(id, o);
0754:                return id;
0755:            }
0756:
0757:            /**
0758:             * Looks up the ID table and gets associated object.
0759:             *
0760:             * <p>
0761:             * The exception thrown from {@link Callable#call()} means the unmarshaller should abort
0762:             * right away.
0763:             *
0764:             * @see IDResolver#resolve(String, Class)
0765:             */
0766:            public Callable getObjectFromId(String id, Class targetType)
0767:                    throws SAXException {
0768:                return idResolver.resolve(id, targetType);
0769:            }
0770:
0771:            //
0772:            //
0773:            // namespace binding maintainance
0774:            //
0775:            //
0776:            private String[] nsBind = new String[16];
0777:            private int nsLen = 0;
0778:
0779:            public void startPrefixMapping(String prefix, String uri) {
0780:                if (nsBind.length == nsLen) {
0781:                    // expand the buffer
0782:                    String[] n = new String[nsLen * 2];
0783:                    System.arraycopy(nsBind, 0, n, 0, nsLen);
0784:                    nsBind = n;
0785:                }
0786:                nsBind[nsLen++] = prefix;
0787:                nsBind[nsLen++] = uri;
0788:            }
0789:
0790:            public void endPrefixMapping(String prefix) {
0791:                nsLen -= 2;
0792:            }
0793:
0794:            private String resolveNamespacePrefix(String prefix) {
0795:                if (prefix.equals("xml"))
0796:                    return "http://www.w3.org/XML/1998/namespace";
0797:
0798:                for (int i = nsLen - 2; i >= 0; i -= 2) {
0799:                    if (prefix.equals(nsBind[i]))
0800:                        return nsBind[i + 1];
0801:                }
0802:
0803:                if (environmentNamespaceContext != null)
0804:                    // temporary workaround until Zephyr fixes 6337180
0805:                    return environmentNamespaceContext.getNamespaceURI(prefix
0806:                            .intern());
0807:
0808:                // by default, the default ns is bound to "".
0809:                // but allow environmentNamespaceContext to take precedence
0810:                if (prefix.equals(""))
0811:                    return "";
0812:
0813:                // unresolved. error.
0814:                return null;
0815:            }
0816:
0817:            /**
0818:             * Returns a list of prefixes newly declared on the current element.
0819:             *
0820:             * @return
0821:             *      A possible zero-length array of prefixes. The default prefix
0822:             *      is represented by the empty string.
0823:             */
0824:            public String[] getNewlyDeclaredPrefixes() {
0825:                return getPrefixList(current.prev.numNsDecl);
0826:            }
0827:
0828:            /**
0829:             * Returns a list of all in-scope prefixes.
0830:             *
0831:             * @return
0832:             *      A possible zero-length array of prefixes. The default prefix
0833:             *      is represented by the empty string.
0834:             */
0835:            public String[] getAllDeclaredPrefixes() {
0836:                return getPrefixList(0);
0837:            }
0838:
0839:            private String[] getPrefixList(int startIndex) {
0840:                int size = (current.numNsDecl - startIndex) / 2;
0841:                String[] r = new String[size];
0842:                for (int i = 0; i < r.length; i++)
0843:                    r[i] = nsBind[startIndex + i * 2];
0844:                return r;
0845:            }
0846:
0847:            //
0848:            //  NamespaceContext2 implementation
0849:            //
0850:            public Iterator<String> getPrefixes(String uri) {
0851:                // TODO: could be implemented much faster
0852:                // wrap it into unmodifiable list so that the remove method
0853:                // will throw UnsupportedOperationException.
0854:                return Collections.unmodifiableList(getAllPrefixesInList(uri))
0855:                        .iterator();
0856:            }
0857:
0858:            private List<String> getAllPrefixesInList(String uri) {
0859:                List<String> a = new ArrayList<String>();
0860:
0861:                if (uri == null)
0862:                    throw new IllegalArgumentException();
0863:                if (uri.equals(XMLConstants.XML_NS_URI)) {
0864:                    a.add(XMLConstants.XML_NS_PREFIX);
0865:                    return a;
0866:                }
0867:                if (uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
0868:                    a.add(XMLConstants.XMLNS_ATTRIBUTE);
0869:                    return a;
0870:                }
0871:
0872:                for (int i = nsLen - 2; i >= 0; i -= 2)
0873:                    if (uri.equals(nsBind[i + 1]))
0874:                        if (getNamespaceURI(nsBind[i]).equals(nsBind[i + 1]))
0875:                            // make sure that this prefix is still effective.
0876:                            a.add(nsBind[i]);
0877:
0878:                return a;
0879:            }
0880:
0881:            public String getPrefix(String uri) {
0882:                if (uri == null)
0883:                    throw new IllegalArgumentException();
0884:                if (uri.equals(XMLConstants.XML_NS_URI))
0885:                    return XMLConstants.XML_NS_PREFIX;
0886:                if (uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI))
0887:                    return XMLConstants.XMLNS_ATTRIBUTE;
0888:
0889:                for (int i = nsLen - 2; i >= 0; i -= 2)
0890:                    if (uri.equals(nsBind[i + 1]))
0891:                        if (getNamespaceURI(nsBind[i]).equals(nsBind[i + 1]))
0892:                            // make sure that this prefix is still effective.
0893:                            return nsBind[i];
0894:
0895:                if (environmentNamespaceContext != null)
0896:                    return environmentNamespaceContext.getPrefix(uri);
0897:
0898:                return null;
0899:            }
0900:
0901:            public String getNamespaceURI(String prefix) {
0902:                if (prefix == null)
0903:                    throw new IllegalArgumentException();
0904:                if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE))
0905:                    return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
0906:
0907:                return resolveNamespacePrefix(prefix);
0908:            }
0909:
0910:            //
0911:            //
0912:            //
0913:            // scope management
0914:            //
0915:            //
0916:            //
0917:            private Scope[] scopes = new Scope[16];
0918:            /**
0919:             * Points to the top of the scope stack (=size-1).
0920:             */
0921:            private int scopeTop = 0;
0922:
0923:            {
0924:                for (int i = 0; i < scopes.length; i++)
0925:                    scopes[i] = new Scope(this );
0926:            }
0927:
0928:            /**
0929:             * Starts a new packing scope.
0930:             *
0931:             * <p>
0932:             * This method allocates a specified number of fresh {@link Scope} objects.
0933:             * They can be accessed by the {@link #getScope} method until the corresponding
0934:             * {@link #endScope} method is invoked.
0935:             *
0936:             * <p>
0937:             * A new scope will mask the currently active scope. Only one frame of {@link Scope}s
0938:             * can be accessed at any given time.
0939:             *
0940:             * @param frameSize
0941:             *      The # of slots to be allocated.
0942:             */
0943:            public void startScope(int frameSize) {
0944:                scopeTop += frameSize;
0945:
0946:                // reallocation
0947:                if (scopeTop >= scopes.length) {
0948:                    Scope[] s = new Scope[Math.max(scopeTop + 1,
0949:                            scopes.length * 2)];
0950:                    System.arraycopy(scopes, 0, s, 0, scopes.length);
0951:                    for (int i = scopes.length; i < s.length; i++)
0952:                        s[i] = new Scope(this );
0953:                    scopes = s;
0954:                }
0955:            }
0956:
0957:            /**
0958:             * Ends the current packing scope.
0959:             *
0960:             * <p>
0961:             * If any packing in progress will be finalized by this method.
0962:             *
0963:             * @param frameSize
0964:             *      The same size that gets passed to the {@link #startScope(int)}
0965:             *      method.
0966:             */
0967:            public void endScope(int frameSize) throws SAXException {
0968:                try {
0969:                    for (; frameSize > 0; frameSize--, scopeTop--)
0970:                        scopes[scopeTop].finish();
0971:                } catch (AccessorException e) {
0972:                    handleError(e);
0973:
0974:                    // the error might have left scopes in inconsistent state,
0975:                    // so replace them by fresh ones
0976:                    for (; frameSize > 0; frameSize--)
0977:                        scopes[scopeTop--] = new Scope(this );
0978:                }
0979:            }
0980:
0981:            /**
0982:             * Gets the currently active {@link Scope}.
0983:             *
0984:             * @param offset
0985:             *      a number between [0,frameSize)
0986:             *
0987:             * @return
0988:             *      always a valid {@link Scope} object.
0989:             */
0990:            public Scope getScope(int offset) {
0991:                return scopes[scopeTop - offset];
0992:            }
0993:
0994:            //
0995:            //
0996:            //
0997:            //
0998:            //
0999:            //
1000:            //
1001:
1002:            private static final Loader DEFAULT_ROOT_LOADER = new DefaultRootLoader();
1003:            private static final Loader EXPECTED_TYPE_ROOT_LOADER = new ExpectedTypeRootLoader();
1004:
1005:            /**
1006:             * Root loader that uses the tag name and possibly its @xsi:type
1007:             * to decide how to start unmarshalling.
1008:             */
1009:            private static final class DefaultRootLoader extends Loader
1010:                    implements  Receiver {
1011:                /**
1012:                 * Receives the root element and determines how to start
1013:                 * unmarshalling.
1014:                 */
1015:                public void childElement(UnmarshallingContext.State state,
1016:                        TagName ea) throws SAXException {
1017:                    Loader loader = state.getContext().selectRootLoader(state,
1018:                            ea);
1019:                    if (loader != null) {
1020:                        state.loader = loader;
1021:                        state.receiver = this ;
1022:                        return;
1023:                    }
1024:
1025:                    // the registry doesn't know about this element.
1026:                    // try its xsi:type
1027:                    JaxBeanInfo beanInfo = XsiTypeLoader.parseXsiType(state,
1028:                            ea, null);
1029:                    if (beanInfo == null) {
1030:                        // we don't even know its xsi:type
1031:                        reportUnexpectedChildElement(ea, false);
1032:                        return;
1033:                    }
1034:
1035:                    state.loader = beanInfo.getLoader(null, false);
1036:                    state.prev.backup = new JAXBElement<Object>(ea
1037:                            .createQName(), Object.class, null);
1038:                    state.receiver = this ;
1039:                }
1040:
1041:                @Override
1042:                public Collection<QName> getExpectedChildElements() {
1043:                    return getInstance().getJAXBContext().getValidRootNames();
1044:                }
1045:
1046:                public void receive(State state, Object o) {
1047:                    if (state.backup != null) {
1048:                        ((JAXBElement<Object>) state.backup).setValue(o);
1049:                        o = state.backup;
1050:                    }
1051:                    state.getContext().result = o;
1052:                }
1053:            }
1054:
1055:            /**
1056:             * Root loader that uses {@link UnmarshallingContext#expectedType}
1057:             * to decide how to start unmarshalling.
1058:             */
1059:            private static final class ExpectedTypeRootLoader extends Loader
1060:                    implements  Receiver {
1061:                /**
1062:                 * Receives the root element and determines how to start
1063:                 * unmarshalling.
1064:                 */
1065:                public void childElement(UnmarshallingContext.State state,
1066:                        TagName ea) {
1067:                    UnmarshallingContext context = state.getContext();
1068:
1069:                    // unmarshals the specified type
1070:                    QName qn = new QName(ea.uri, ea.local);
1071:                    state.prev.target = new JAXBElement(qn,
1072:                            context.expectedType.jaxbType, null, null);
1073:                    state.receiver = this ;
1074:                    // this is bit wasteful, as in theory we should have each expectedType keep
1075:                    // nillable version --- but that increases the combination from two to four,
1076:                    // which adds the resident memory footprint. Since XsiNilLoader is small,
1077:                    // I intentionally allocate a new instance freshly.
1078:                    state.loader = new XsiNilLoader(context.expectedType
1079:                            .getLoader(null, true));
1080:                }
1081:
1082:                public void receive(State state, Object o) {
1083:                    JAXBElement e = (JAXBElement) state.target;
1084:                    e.setValue(o);
1085:                    state.getContext().recordOuterPeer(e);
1086:                    state.getContext().result = e;
1087:                }
1088:            }
1089:
1090:            //
1091:            // in-place unmarshalling related capabilities
1092:            //
1093:            /**
1094:             * Notifies the context about the inner peer of the current element.
1095:             *
1096:             * <p>
1097:             * If the unmarshalling is building the association, the context
1098:             * will use this information. Otherwise it will be just ignored.
1099:             */
1100:            public void recordInnerPeer(Object innerPeer) {
1101:                if (assoc != null)
1102:                    assoc.addInner(currentElement, innerPeer);
1103:            }
1104:
1105:            /**
1106:             * Gets the inner peer JAXB object associated with the current element.
1107:             *
1108:             * @return
1109:             *      null if the current element doesn't have an inner peer,
1110:             *      or if we are not doing the in-place unmarshalling.
1111:             */
1112:            public Object getInnerPeer() {
1113:                if (assoc != null && isInplaceMode)
1114:                    return assoc.getInnerPeer(currentElement);
1115:                else
1116:                    return null;
1117:            }
1118:
1119:            /**
1120:             * Notifies the context about the outer peer of the current element.
1121:             *
1122:             * <p>
1123:             * If the unmarshalling is building the association, the context
1124:             * will use this information. Otherwise it will be just ignored.
1125:             */
1126:            public void recordOuterPeer(Object outerPeer) {
1127:                if (assoc != null)
1128:                    assoc.addOuter(currentElement, outerPeer);
1129:            }
1130:
1131:            /**
1132:             * Gets the outer peer JAXB object associated with the current element.
1133:             *
1134:             * @return
1135:             *      null if the current element doesn't have an inner peer,
1136:             *      or if we are not doing the in-place unmarshalling.
1137:             */
1138:            public Object getOuterPeer() {
1139:                if (assoc != null && isInplaceMode)
1140:                    return assoc.getOuterPeer(currentElement);
1141:                else
1142:                    return null;
1143:            }
1144:
1145:            /**
1146:             * Gets the xmime:contentType value for the current object.
1147:             *
1148:             * @see JAXBContextImpl#getXMIMEContentType(Object)
1149:             */
1150:            public String getXMIMEContentType() {
1151:                /*
1152:                    this won't work when the class is like
1153:
1154:                    class Foo {
1155:                        @XmlValue Image img;
1156:                    }
1157:
1158:                    because the target will return Foo, not the class enclosing Foo
1159:                    which will have xmime:contentType
1160:                 */
1161:                Object t = current.target;
1162:                if (t == null)
1163:                    return null;
1164:                return getJAXBContext().getXMIMEContentType(t);
1165:            }
1166:
1167:            /**
1168:             * When called from within the realm of the unmarshaller, this method
1169:             * returns the current {@link UnmarshallingContext} in charge.
1170:             */
1171:            public static UnmarshallingContext getInstance() {
1172:                return (UnmarshallingContext) Coordinator._getInstance();
1173:            }
1174:        }
ww_w__.__jav__a___2_s___.c___o_m__ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.