Source Code Cross Referenced for XMLSerializer.java in  » 6.0-JDK-Modules-com.sun » xml » com » sun » xml » internal » bind » v2 » runtime » 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 com.sun » xml » com.sun.xml.internal.bind.v2.runtime 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package com.sun.xml.internal.bind.v2.runtime;
0027:
0028:        import java.io.IOException;
0029:        import java.lang.reflect.Method;
0030:        import java.util.HashSet;
0031:        import java.util.Map;
0032:        import java.util.Set;
0033:
0034:        import javax.activation.MimeType;
0035:        import javax.xml.bind.DatatypeConverter;
0036:        import javax.xml.bind.JAXBException;
0037:        import javax.xml.bind.Marshaller;
0038:        import javax.xml.bind.ValidationEvent;
0039:        import javax.xml.bind.ValidationEventHandler;
0040:        import javax.xml.bind.ValidationEventLocator;
0041:        import javax.xml.bind.annotation.DomHandler;
0042:        import javax.xml.bind.annotation.XmlSchemaType;
0043:        import javax.xml.bind.attachment.AttachmentMarshaller;
0044:        import javax.xml.bind.helpers.NotIdentifiableEventImpl;
0045:        import javax.xml.bind.helpers.ValidationEventImpl;
0046:        import javax.xml.bind.helpers.ValidationEventLocatorImpl;
0047:        import javax.xml.namespace.QName;
0048:        import javax.xml.stream.XMLStreamException;
0049:        import javax.xml.transform.Source;
0050:        import javax.xml.transform.Transformer;
0051:        import javax.xml.transform.TransformerException;
0052:        import javax.xml.transform.sax.SAXResult;
0053:
0054:        import com.sun.istack.internal.SAXException2;
0055:        import com.sun.xml.internal.bind.api.AccessorException;
0056:        import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;
0057:        import com.sun.xml.internal.bind.util.ValidationEventLocatorExImpl;
0058:        import com.sun.xml.internal.bind.v2.WellKnownNamespace;
0059:        import com.sun.xml.internal.bind.v2.model.runtime.RuntimeBuiltinLeafInfo;
0060:        import com.sun.xml.internal.bind.v2.runtime.output.MTOMXmlOutput;
0061:        import com.sun.xml.internal.bind.v2.runtime.output.NamespaceContextImpl;
0062:        import com.sun.xml.internal.bind.v2.runtime.output.Pcdata;
0063:        import com.sun.xml.internal.bind.v2.runtime.output.XmlOutput;
0064:        import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data;
0065:        import com.sun.xml.internal.bind.v2.runtime.unmarshaller.IntData;
0066:        import com.sun.xml.internal.bind.v2.util.CollisionCheckStack;
0067:
0068:        import org.xml.sax.SAXException;
0069:
0070:        /**
0071:         * Receives XML serialization event and writes to {@link XmlOutput}.
0072:         * 
0073:         * <p>
0074:         * This object coordinates the overall marshalling efforts across different
0075:         * content-tree objects and different target formats.
0076:         * 
0077:         * <p>
0078:         * The following CFG gives the proper sequence of method invocation.
0079:         * 
0080:         * <pre>
0081:         * MARSHALLING  :=  ELEMENT
0082:         * ELEMENT      :=  "startElement" NSDECL* "endNamespaceDecls"
0083:         *                        ATTRIBUTE* "endAttributes" BODY "endElement"
0084:         * 
0085:         * NSDECL       :=  "declareNamespace"
0086:         * 
0087:         * ATTRIBUTE    :=  "attribute"
0088:         * ATTVALUES    :=  "text"*
0089:         * 
0090:         * 
0091:         * BODY         :=  ( "text" | ELEMENT )*
0092:         * </pre>
0093:         * 
0094:         * <p>
0095:         * A marshalling of one element consists of two stages. The first stage is
0096:         * for marshalling attributes and collecting namespace declarations.
0097:         * The second stage is for marshalling characters/child elements of that element.
0098:         * 
0099:         * <p>
0100:         * Observe that multiple invocation of "text" is allowed.
0101:         * 
0102:         * <p>
0103:         * Also observe that the namespace declarations are allowed only between
0104:         * "startElement" and "endAttributes".
0105:         * 
0106:         * <h2>Exceptions in marshaller</h2>
0107:         * <p>
0108:         * {@link IOException}, {@link SAXException}, and {@link XMLStreamException}
0109:         * are thrown from {@link XmlOutput}. They are always considered fatal, and
0110:         * therefore caught only by {@link MarshallerImpl}.
0111:         * <p>
0112:         * {@link AccessorException} can be thrown when an access to a property/field
0113:         * fails, and this is considered as a recoverable error, so it's caught everywhere.
0114:         *
0115:         * @author  Kohsuke Kawaguchi
0116:         */
0117:        public final class XMLSerializer extends Coordinator {
0118:            public final JAXBContextImpl grammar;
0119:
0120:            /** The XML printer. */
0121:            private XmlOutput out;
0122:
0123:            // TODO: fix the access modifier
0124:            public final NameList nameList;
0125:
0126:            // TODO: fix the access modifier
0127:            public final int[] knownUri2prefixIndexMap;
0128:
0129:            private final NamespaceContextImpl nsContext;
0130:
0131:            private NamespaceContextImpl.Element nse;
0132:
0133:            /**
0134:             * Set to true if a text is already written,
0135:             * and we need to print ' ' for additional text methods.
0136:             */
0137:            private boolean textHasAlreadyPrinted = false;
0138:
0139:            /**
0140:             * Set to false once we see the start tag of the root element.
0141:             */
0142:            private boolean seenRoot = false;
0143:
0144:            /** Marshaller object to which this object belongs. */
0145:            private final MarshallerImpl marshaller;
0146:
0147:            /** Objects referenced through IDREF. */
0148:            private final Set<Object> idReferencedObjects = new HashSet<Object>();
0149:
0150:            /** Objects with ID. */
0151:            private final Set<Object> objectsWithId = new HashSet<Object>();
0152:
0153:            /**
0154:             * Used to detect cycles in the object.
0155:             * Also used to learn what's being marshalled.
0156:             */
0157:            private final CollisionCheckStack<Object> cycleDetectionStack = new CollisionCheckStack<Object>();
0158:
0159:            /** Optional attributes to go with root element. */
0160:            private String schemaLocation;
0161:            private String noNsSchemaLocation;
0162:
0163:            /** Lazily created identitiy transformer. */
0164:            private Transformer identityTransformer;
0165:
0166:            /** Lazily created. */
0167:            private ContentHandlerAdaptor contentHandlerAdapter;
0168:
0169:            private boolean fragment;
0170:
0171:            /**
0172:             * Cached instance of {@link Base64Data}.
0173:             */
0174:            private Base64Data base64Data;
0175:
0176:            /**
0177:             * Cached instance of {@link IntData}.
0178:             */
0179:            private final IntData intData = new IntData();
0180:
0181:            public AttachmentMarshaller attachmentMarshaller;
0182:
0183:            /*package*/XMLSerializer(MarshallerImpl _owner) {
0184:                this .marshaller = _owner;
0185:                this .grammar = marshaller.context;
0186:                nsContext = new NamespaceContextImpl(this );
0187:                nameList = marshaller.context.nameList;
0188:                knownUri2prefixIndexMap = new int[nameList.namespaceURIs.length];
0189:            }
0190:
0191:            /**
0192:             * Gets the cached instance of {@link Base64Data}.
0193:             */
0194:            public Base64Data getCachedBase64DataInstance() {
0195:                if (base64Data == null)
0196:                    base64Data = new Base64Data();
0197:                return base64Data;
0198:            }
0199:
0200:            /**
0201:             * Gets the ID value from an identifiable object.
0202:             */
0203:            private String getIdFromObject(Object identifiableObject)
0204:                    throws SAXException, JAXBException {
0205:                return grammar.getBeanInfo(identifiableObject, true).getId(
0206:                        identifiableObject, this );
0207:            }
0208:
0209:            private void handleMissingObjectError(String fieldName)
0210:                    throws SAXException, IOException, XMLStreamException {
0211:                reportMissingObjectError(fieldName);
0212:                // as a marshaller, we should be robust, so we'll continue to marshal
0213:                // this document by skipping this missing object.
0214:                endNamespaceDecls(null);
0215:                endAttributes();
0216:            }
0217:
0218:            public void reportError(ValidationEvent ve) throws SAXException {
0219:                ValidationEventHandler handler;
0220:
0221:                try {
0222:                    handler = marshaller.getEventHandler();
0223:                } catch (JAXBException e) {
0224:                    throw new SAXException2(e);
0225:                }
0226:
0227:                if (!handler.handleEvent(ve)) {
0228:                    if (ve.getLinkedException() instanceof  Exception)
0229:                        throw new SAXException2((Exception) ve
0230:                                .getLinkedException());
0231:                    else
0232:                        throw new SAXException2(ve.getMessage());
0233:                }
0234:            }
0235:
0236:            /**
0237:             * Report an error found as an exception.
0238:             *
0239:             * @param fieldName
0240:             *      the name of the property being processed when an error is found.
0241:             */
0242:            public final void reportError(String fieldName, Throwable t)
0243:                    throws SAXException {
0244:                ValidationEvent ve = new ValidationEventImpl(
0245:                        ValidationEvent.ERROR, t.getMessage(),
0246:                        getCurrentLocation(fieldName), t);
0247:                reportError(ve);
0248:            }
0249:
0250:            public void startElement(Name tagName, Object outerPeer) {
0251:                startElement();
0252:                nse.setTagName(tagName, outerPeer);
0253:            }
0254:
0255:            public void startElement(String nsUri, String localName,
0256:                    String preferredPrefix, Object outerPeer) {
0257:                startElement();
0258:                int idx = nsContext.declareNsUri(nsUri, preferredPrefix, false);
0259:                nse.setTagName(idx, localName, outerPeer);
0260:            }
0261:
0262:            public void endNamespaceDecls(Object innerPeer) throws IOException,
0263:                    XMLStreamException {
0264:                nsContext.collectionMode = false;
0265:                nse.startElement(out, innerPeer);
0266:            }
0267:
0268:            /**
0269:             * Switches to the "marshal child texts/elements" mode.
0270:             * This method has to be called after the 1st pass is completed.
0271:             */
0272:            public void endAttributes() throws SAXException, IOException,
0273:                    XMLStreamException {
0274:                if (!seenRoot) {
0275:                    seenRoot = true;
0276:                    if (schemaLocation != null || noNsSchemaLocation != null) {
0277:                        int p = nsContext
0278:                                .getPrefixIndex(WellKnownNamespace.XML_SCHEMA_INSTANCE);
0279:                        if (schemaLocation != null)
0280:                            out.attribute(p, "schemaLocation", schemaLocation);
0281:                        if (noNsSchemaLocation != null)
0282:                            out.attribute(p, "noNamespaceSchemaLocation",
0283:                                    noNsSchemaLocation);
0284:                    }
0285:                }
0286:
0287:                out.endStartTag();
0288:            }
0289:
0290:            /**
0291:             * Ends marshalling of an element.
0292:             * Pops the internal stack.
0293:             */
0294:            public void endElement() throws SAXException, IOException,
0295:                    XMLStreamException {
0296:                nse.endElement(out);
0297:                nse = nse.pop();
0298:                textHasAlreadyPrinted = false;
0299:            }
0300:
0301:            public void leafElement(Name tagName, String data, String fieldName)
0302:                    throws SAXException, IOException, XMLStreamException {
0303:                if (seenRoot) {
0304:                    textHasAlreadyPrinted = false;
0305:                    nse = nse.push();
0306:                    out.beginStartTag(tagName);
0307:                    out.endStartTag();
0308:                    out.text(data, false);
0309:                    out.endTag(tagName);
0310:                    nse = nse.pop();
0311:                } else {
0312:                    // root element has additional processing like xsi:schemaLocation,
0313:                    // so we need to go the slow way
0314:                    startElement(tagName, null);
0315:                    endNamespaceDecls(null);
0316:                    endAttributes();
0317:                    out.text(data, false);
0318:                    endElement();
0319:                }
0320:            }
0321:
0322:            public void leafElement(Name tagName, Pcdata data, String fieldName)
0323:                    throws SAXException, IOException, XMLStreamException {
0324:                if (seenRoot) {
0325:                    textHasAlreadyPrinted = false;
0326:                    nse = nse.push();
0327:                    out.beginStartTag(tagName);
0328:                    out.endStartTag();
0329:                    out.text(data, false);
0330:                    out.endTag(tagName);
0331:                    nse = nse.pop();
0332:                } else {
0333:                    // root element has additional processing like xsi:schemaLocation,
0334:                    // so we need to go the slow way
0335:                    startElement(tagName, null);
0336:                    endNamespaceDecls(null);
0337:                    endAttributes();
0338:                    out.text(data, false);
0339:                    endElement();
0340:                }
0341:            }
0342:
0343:            public void leafElement(Name tagName, int data, String fieldName)
0344:                    throws SAXException, IOException, XMLStreamException {
0345:                intData.reset(data);
0346:                leafElement(tagName, intData, fieldName);
0347:            }
0348:
0349:            // TODO: consider some of these in future if we expand the writer to use something other than SAX
0350:            //    void leafElement( QName tagName, byte value, String fieldName ) throws SAXException;
0351:            //    void leafElement( QName tagName, char value, String fieldName ) throws SAXException;
0352:            //    void leafElement( QName tagName, short value, String fieldName ) throws SAXException;
0353:            //    void leafElement( QName tagName, int value, String fieldName ) throws SAXException;
0354:            //    void leafElement( QName tagName, long value, String fieldName ) throws SAXException;
0355:            //    void leafElement( QName tagName, float value, String fieldName ) throws SAXException;
0356:            //    void leafElement( QName tagName, double value, String fieldName ) throws SAXException;
0357:            //    void leafElement( QName tagName, boolean value, String fieldName ) throws SAXException;
0358:
0359:            /**
0360:             * Marshalls text.
0361:             *
0362:             * <p>
0363:             * This method can be called after the {@link #endAttributes()}
0364:             * method to marshal texts inside elements.
0365:             * If the method is called more than once, those texts are considered
0366:             * as separated by whitespaces. For example,
0367:             *
0368:             * <pre>
0369:             * c.startElement("","foo");
0370:             * c.endAttributes();
0371:             * c.text("abc");
0372:             * c.text("def");
0373:             *   c.startElement("","bar");
0374:             *   c.endAttributes();
0375:             *   c.endElement();
0376:             * c.text("ghi");
0377:             * c.endElement();
0378:             * </pre>
0379:             *
0380:             * will generate <code>&lt;foo>abc def&lt;bar/>ghi&lt;/foo></code>.
0381:             */
0382:            public void text(String text, String fieldName)
0383:                    throws SAXException, IOException, XMLStreamException {
0384:                // If the assertion fails, it must be a bug of xjc.
0385:                // right now, we are not expecting the text method to be called.
0386:                if (text == null) {
0387:                    reportMissingObjectError(fieldName);
0388:                    return;
0389:                }
0390:
0391:                out.text(text, textHasAlreadyPrinted);
0392:                textHasAlreadyPrinted = true;
0393:            }
0394:
0395:            /**
0396:             * The {@link #text(String, String)} method that takes {@link Pcdata}.
0397:             */
0398:            public void text(Pcdata text, String fieldName)
0399:                    throws SAXException, IOException, XMLStreamException {
0400:                // If the assertion fails, it must be a bug of xjc.
0401:                // right now, we are not expecting the text method to be called.
0402:                if (text == null) {
0403:                    reportMissingObjectError(fieldName);
0404:                    return;
0405:                }
0406:
0407:                out.text(text, textHasAlreadyPrinted);
0408:                textHasAlreadyPrinted = true;
0409:            }
0410:
0411:            public void attribute(String uri, String local, String value)
0412:                    throws SAXException {
0413:                int prefix;
0414:                if (uri.length() == 0) {
0415:                    // default namespace. don't need prefix
0416:                    prefix = -1;
0417:                } else {
0418:                    prefix = nsContext.getPrefixIndex(uri);
0419:                }
0420:
0421:                try {
0422:                    out.attribute(prefix, local, value);
0423:                } catch (IOException e) {
0424:                    throw new SAXException2(e);
0425:                } catch (XMLStreamException e) {
0426:                    throw new SAXException2(e);
0427:                }
0428:            }
0429:
0430:            public void attribute(Name name, CharSequence value)
0431:                    throws IOException, XMLStreamException {
0432:                // TODO: consider having the version that takes Pcdata.
0433:                // it's common for an element to have int attributes
0434:                out.attribute(name, value.toString());
0435:            }
0436:
0437:            public NamespaceContext2 getNamespaceContext() {
0438:                return nsContext;
0439:            }
0440:
0441:            public String onID(Object owner, String value) {
0442:                objectsWithId.add(owner);
0443:                return value;
0444:            }
0445:
0446:            public String onIDREF(Object obj) throws SAXException {
0447:                String id;
0448:                try {
0449:                    id = getIdFromObject(obj);
0450:                } catch (JAXBException e) {
0451:                    reportError(null, e);
0452:                    return null; // recover by returning null
0453:                }
0454:                idReferencedObjects.add(obj);
0455:                if (id == null) {
0456:                    reportError(new NotIdentifiableEventImpl(
0457:                            ValidationEvent.ERROR, Messages.NOT_IDENTIFIABLE
0458:                                    .format(), new ValidationEventLocatorImpl(
0459:                                    obj)));
0460:                }
0461:                return id;
0462:            }
0463:
0464:            // TODO: think about the exception handling.
0465:            // I suppose we don't want to use SAXException. -kk
0466:
0467:            public void childAsRoot(Object obj) throws JAXBException,
0468:                    IOException, SAXException, XMLStreamException {
0469:                final JaxBeanInfo beanInfo = grammar.getBeanInfo(obj, true);
0470:
0471:                // since the same object will be reported to childAsRoot or
0472:                // childAsXsiType, don't make it a part of the collision check.
0473:                // but we do need to push it so that getXMIMEContentType will work.
0474:                cycleDetectionStack.pushNocheck(obj);
0475:
0476:                final boolean lookForLifecycleMethods = beanInfo
0477:                        .lookForLifecycleMethods();
0478:                if (lookForLifecycleMethods) {
0479:                    fireBeforeMarshalEvents(beanInfo, obj);
0480:                }
0481:
0482:                beanInfo.serializeRoot(obj, this );
0483:
0484:                if (lookForLifecycleMethods) {
0485:                    fireAfterMarshalEvents(beanInfo, obj);
0486:                }
0487:
0488:                cycleDetectionStack.pop();
0489:            }
0490:
0491:            private void pushObject(Object obj, String fieldName)
0492:                    throws SAXException {
0493:                if (cycleDetectionStack.push(obj)) {
0494:                    // cycle detected
0495:                    StringBuilder sb = new StringBuilder();
0496:                    sb.append(obj);
0497:                    int i = cycleDetectionStack.size() - 1;
0498:                    Object x;
0499:                    do {
0500:                        sb.append(" -> ");
0501:                        x = cycleDetectionStack.get(--i);
0502:                        sb.append(x);
0503:                    } while (obj != x);
0504:
0505:                    reportError(new ValidationEventImpl(ValidationEvent.ERROR,
0506:                            Messages.CYCLE_IN_MARSHALLER.format(sb),
0507:                            getCurrentLocation(fieldName), null));
0508:                }
0509:            }
0510:
0511:            /**
0512:             * The equivalent of:
0513:             * 
0514:             * <pre>
0515:             * childAsURIs(child, fieldName);
0516:             * endNamespaceDecls();
0517:             * childAsAttributes(child, fieldName);
0518:             * endAttributes();
0519:             * childAsBody(child, fieldName);
0520:             * </pre>
0521:             * 
0522:             * This produces the given child object as the sole content of
0523:             * an element.
0524:             * Used to reduce the code size in the generated marshaller.
0525:             */
0526:            public final void childAsSoleContent(Object child, String fieldName)
0527:                    throws SAXException, IOException, XMLStreamException {
0528:                if (child == null) {
0529:                    handleMissingObjectError(fieldName);
0530:                } else {
0531:                    JaxBeanInfo beanInfo;
0532:                    try {
0533:                        beanInfo = grammar.getBeanInfo(child, true);
0534:                    } catch (JAXBException e) {
0535:                        reportError(fieldName, e);
0536:                        // recover by ignore
0537:                        endNamespaceDecls(null);
0538:                        endAttributes();
0539:                        return;
0540:                    }
0541:
0542:                    pushObject(child, fieldName);
0543:
0544:                    final boolean lookForLifecycleMethods = beanInfo
0545:                            .lookForLifecycleMethods();
0546:                    if (lookForLifecycleMethods) {
0547:                        fireBeforeMarshalEvents(beanInfo, child);
0548:                    }
0549:
0550:                    beanInfo.serializeURIs(child, this );
0551:                    endNamespaceDecls(child);
0552:                    beanInfo.serializeAttributes(child, this );
0553:                    endAttributes();
0554:                    beanInfo.serializeBody(child, this );
0555:
0556:                    if (lookForLifecycleMethods) {
0557:                        fireAfterMarshalEvents(beanInfo, child);
0558:                    }
0559:
0560:                    cycleDetectionStack.pop();
0561:                }
0562:            }
0563:
0564:            // the version of childAsXXX where it produces @xsi:type if the expected type name
0565:            // and the actual type name differs.
0566:
0567:            /**
0568:             * This method is called when a type child object is found.
0569:             * 
0570:             * <p>
0571:             * This method produces events of the following form:
0572:             * <pre>
0573:             * NSDECL* "endNamespaceDecls" ATTRIBUTE* "endAttributes" BODY
0574:             * </pre>
0575:             * optionally including @xsi:type if necessary.
0576:             * 
0577:             * @param child
0578:             *      Object to be marshalled. The {@link JaxBeanInfo} for
0579:             *      this object must return a type name.
0580:             * @param expected
0581:             *      Expected type of the object.
0582:             * @param fieldName
0583:             *      property name of the parent objeect from which 'o' comes.
0584:             *      Used as a part of the error message in case anything goes wrong
0585:             *      with 'o'. 
0586:             */
0587:            public final void childAsXsiType(Object child, String fieldName,
0588:                    JaxBeanInfo expected) throws SAXException, IOException,
0589:                    XMLStreamException {
0590:                if (child == null) {
0591:                    handleMissingObjectError(fieldName);
0592:                } else {
0593:                    boolean asExpected = child.getClass() == expected.jaxbType;
0594:                    JaxBeanInfo actual = expected;
0595:                    QName actualTypeName = null;
0596:
0597:                    pushObject(child, fieldName);
0598:
0599:                    if ((asExpected) && (actual.lookForLifecycleMethods())) {
0600:                        fireBeforeMarshalEvents(actual, child);
0601:                    }
0602:
0603:                    if (!asExpected) {
0604:                        try {
0605:                            actual = grammar.getBeanInfo(child, true);
0606:                            if (actual.lookForLifecycleMethods()) {
0607:                                fireBeforeMarshalEvents(actual, child);
0608:                            }
0609:                        } catch (JAXBException e) {
0610:                            reportError(fieldName, e);
0611:                            endNamespaceDecls(null);
0612:                            endAttributes();
0613:                            return; // recover by ignore
0614:                        }
0615:                        if (actual == expected)
0616:                            asExpected = true;
0617:                        else {
0618:                            actualTypeName = actual.getTypeName(child);
0619:                            if (actualTypeName == null) {
0620:                                reportError(new ValidationEventImpl(
0621:                                        ValidationEvent.ERROR,
0622:                                        Messages.SUBSTITUTED_BY_ANONYMOUS_TYPE
0623:                                                .format(expected.jaxbType
0624:                                                        .getName(), child
0625:                                                        .getClass().getName(),
0626:                                                        actual.jaxbType
0627:                                                                .getName()),
0628:                                        getCurrentLocation(fieldName)));
0629:                                // recover by not printing @xsi:type
0630:                            } else {
0631:                                getNamespaceContext().declareNamespace(
0632:                                        WellKnownNamespace.XML_SCHEMA_INSTANCE,
0633:                                        "xsi", true);
0634:                                getNamespaceContext().declareNamespace(
0635:                                        actualTypeName.getNamespaceURI(), null,
0636:                                        false);
0637:                            }
0638:                        }
0639:                    }
0640:                    actual.serializeURIs(child, this );
0641:                    endNamespaceDecls(child);
0642:                    if (!asExpected) {
0643:                        attribute(WellKnownNamespace.XML_SCHEMA_INSTANCE,
0644:                                "type", DatatypeConverter.printQName(
0645:                                        actualTypeName, getNamespaceContext()));
0646:                    }
0647:                    actual.serializeAttributes(child, this );
0648:                    endAttributes();
0649:                    actual.serializeBody(child, this );
0650:
0651:                    if (actual.lookForLifecycleMethods()) {
0652:                        fireAfterMarshalEvents(actual, child);
0653:                    }
0654:
0655:                    cycleDetectionStack.pop();
0656:                }
0657:            }
0658:
0659:            /**
0660:             * Invoke the afterMarshal api on the external listener (if it exists) and on the bean embedded
0661:             * afterMarshal api(if it exists).
0662:             *
0663:             * This method is called only after the callee has determined that beanInfo.lookForLifecycleMethods == true.
0664:             *
0665:             * @param beanInfo
0666:             * @param currentTarget
0667:             */
0668:            private void fireAfterMarshalEvents(final JaxBeanInfo beanInfo,
0669:                    Object currentTarget) {
0670:                // first invoke bean embedded listener
0671:                if (beanInfo.hasAfterMarshalMethod()) {
0672:                    Method m = beanInfo.getLifecycleMethods().getAfterMarshal();
0673:                    fireMarshalEvent(currentTarget, m);
0674:                }
0675:
0676:                // then invoke external listener before bean embedded listener
0677:                Marshaller.Listener externalListener = marshaller.getListener();
0678:                if (externalListener != null) {
0679:                    externalListener.afterMarshal(currentTarget);
0680:                }
0681:
0682:            }
0683:
0684:            /**
0685:             * Invoke the beforeMarshal api on the external listener (if it exists) and on the bean embedded
0686:             * beforeMarshal api(if it exists).
0687:             *
0688:             * This method is called only after the callee has determined that beanInfo.lookForLifecycleMethods == true.
0689:             *
0690:             * @param beanInfo
0691:             * @param currentTarget
0692:             */
0693:            private void fireBeforeMarshalEvents(final JaxBeanInfo beanInfo,
0694:                    Object currentTarget) {
0695:                // first invoke bean embedded listener
0696:                if (beanInfo.hasBeforeMarshalMethod()) {
0697:                    Method m = beanInfo.getLifecycleMethods()
0698:                            .getBeforeMarshal();
0699:                    fireMarshalEvent(currentTarget, m);
0700:                }
0701:
0702:                // then invoke external listener
0703:                Marshaller.Listener externalListener = marshaller.getListener();
0704:                if (externalListener != null) {
0705:                    externalListener.beforeMarshal(currentTarget);
0706:                }
0707:            }
0708:
0709:            private void fireMarshalEvent(Object target, Method m) {
0710:                try {
0711:                    m.invoke(target, marshaller);
0712:                } catch (Exception e) {
0713:                    // this really only happens if there is a bug in the ri
0714:                    throw new IllegalStateException(e);
0715:                }
0716:            }
0717:
0718:            public void attWildcardAsURIs(Map<QName, String> attributes,
0719:                    String fieldName) {
0720:                if (attributes == null)
0721:                    return;
0722:                for (Map.Entry<QName, String> e : attributes.entrySet()) {
0723:                    QName n = e.getKey();
0724:                    String nsUri = n.getNamespaceURI();
0725:                    if (nsUri.length() > 0) {
0726:                        String p = n.getPrefix();
0727:                        if (p.length() == 0)
0728:                            p = null;
0729:                        nsContext.declareNsUri(nsUri, p, true);
0730:                    }
0731:                }
0732:            }
0733:
0734:            public void attWildcardAsAttributes(Map<QName, String> attributes,
0735:                    String fieldName) throws SAXException {
0736:                if (attributes == null)
0737:                    return;
0738:                for (Map.Entry<QName, String> e : attributes.entrySet()) {
0739:                    QName n = e.getKey();
0740:                    attribute(n.getNamespaceURI(), n.getLocalPart(), e
0741:                            .getValue());
0742:                }
0743:            }
0744:
0745:            /**
0746:             * Short for the following call sequence:
0747:             *
0748:             * <pre>
0749:                 getNamespaceContext().declareNamespace(WellKnownNamespace.XML_SCHEMA_INSTANCE,"xsi",true);
0750:                 endNamespaceDecls();
0751:                 attribute(WellKnownNamespace.XML_SCHEMA_INSTANCE,"nil","true");
0752:                 endAttributes();
0753:             * </pre>
0754:             */
0755:            public final void writeXsiNilTrue() throws SAXException,
0756:                    IOException, XMLStreamException {
0757:                getNamespaceContext().declareNamespace(
0758:                        WellKnownNamespace.XML_SCHEMA_INSTANCE, "xsi", true);
0759:                endNamespaceDecls(null);
0760:                attribute(WellKnownNamespace.XML_SCHEMA_INSTANCE, "nil", "true");
0761:                endAttributes();
0762:            }
0763:
0764:            public <E> void writeDom(E element, DomHandler<E, ?> domHandler,
0765:                    Object parentBean, String fieldName) throws SAXException {
0766:                Source source = domHandler.marshal(element, this );
0767:                if (contentHandlerAdapter == null)
0768:                    contentHandlerAdapter = new ContentHandlerAdaptor(this );
0769:                try {
0770:                    getIdentityTransformer().transform(source,
0771:                            new SAXResult(contentHandlerAdapter));
0772:                } catch (TransformerException e) {
0773:                    reportError(fieldName, e);
0774:                }
0775:            }
0776:
0777:            public Transformer getIdentityTransformer() {
0778:                if (identityTransformer == null)
0779:                    identityTransformer = JAXBContextImpl.createTransformer();
0780:                return identityTransformer;
0781:            }
0782:
0783:            public void setPrefixMapper(NamespacePrefixMapper prefixMapper) {
0784:                nsContext.setPrefixMapper(prefixMapper);
0785:            }
0786:
0787:            /**
0788:             * Reset this object to write to the specified output.
0789:             *
0790:             * @param schemaLocation
0791:             *      if non-null, this value is printed on the root element as xsi:schemaLocation
0792:             * @param noNsSchemaLocation
0793:             *      Similar to 'schemaLocation' but this one works for xsi:noNamespaceSchemaLocation
0794:             */
0795:            public void startDocument(XmlOutput out, boolean fragment,
0796:                    String schemaLocation, String noNsSchemaLocation)
0797:                    throws IOException, SAXException, XMLStreamException {
0798:                setThreadAffinity();
0799:                pushCoordinator();
0800:                nsContext.reset();
0801:                nse = nsContext.getCurrent();
0802:                if (attachmentMarshaller != null
0803:                        && attachmentMarshaller.isXOPPackage())
0804:                    out = new MTOMXmlOutput(out);
0805:                this .out = out;
0806:                objectsWithId.clear();
0807:                idReferencedObjects.clear();
0808:                textHasAlreadyPrinted = false;
0809:                seenRoot = false;
0810:                this .schemaLocation = schemaLocation;
0811:                this .noNsSchemaLocation = noNsSchemaLocation;
0812:                this .fragment = fragment;
0813:                this .inlineBinaryFlag = false;
0814:                this .expectedMimeType = null;
0815:                cycleDetectionStack.reset();
0816:
0817:                out.startDocument(this , fragment, knownUri2prefixIndexMap,
0818:                        nsContext);
0819:            }
0820:
0821:            public void endDocument() throws IOException, SAXException,
0822:                    XMLStreamException {
0823:                out.endDocument(fragment);
0824:            }
0825:
0826:            public void close() {
0827:                popCoordinator();
0828:                resetThreadAffinity();
0829:            }
0830:
0831:            /**
0832:             * This method can be called after {@link #startDocument} is called
0833:             * but before the marshalling begins, to set the currently in-scope namespace
0834:             * bindings.
0835:             *
0836:             * <p>
0837:             * This method is useful to avoid redundant namespace declarations when
0838:             * the marshalling is producing a sub-document.
0839:             */
0840:            public void addInscopeBinding(String nsUri, String prefix) {
0841:                nsContext.put(nsUri, prefix);
0842:            }
0843:
0844:            /**
0845:             * Gets the MIME type with which the binary content shall be printed.
0846:             *
0847:             * <p>
0848:             * This method shall be used from those {@link RuntimeBuiltinLeafInfo} that are
0849:             * bound to base64Binary.
0850:             *
0851:             * @see JAXBContextImpl#getXMIMEContentType(Object)
0852:             */
0853:            public String getXMIMEContentType() {
0854:                // xmime:contentType takes precedence
0855:                String v = grammar.getXMIMEContentType(cycleDetectionStack
0856:                        .peek());
0857:                if (v != null)
0858:                    return v;
0859:
0860:                // then look for the current in-scope @XmlMimeType
0861:                if (expectedMimeType != null)
0862:                    return expectedMimeType.toString();
0863:
0864:                return null;
0865:            }
0866:
0867:            private void startElement() {
0868:                nse = nse.push();
0869:
0870:                if (!seenRoot) {
0871:                    // seenRoot set to true in endAttributes
0872:                    // first declare all known URIs
0873:                    String[] knownUris = nameList.namespaceURIs;
0874:                    for (int i = 0; i < knownUris.length; i++)
0875:                        knownUri2prefixIndexMap[i] = nsContext.declareNsUri(
0876:                                knownUris[i], null,
0877:                                nameList.nsUriCannotBeDefaulted[i]);
0878:
0879:                    // then declare user-specified namespace URIs.
0880:                    // work defensively. we are calling an user-defined method.
0881:                    String[] uris = nsContext.getPrefixMapper()
0882:                            .getPreDeclaredNamespaceUris();
0883:                    if (uris != null) {
0884:                        for (String uri : uris) {
0885:                            if (uri != null)
0886:                                nsContext.declareNsUri(uri, null, false);
0887:                        }
0888:                    }
0889:                    String[] pairs = nsContext.getPrefixMapper()
0890:                            .getPreDeclaredNamespaceUris2();
0891:                    if (pairs != null) {
0892:                        for (int i = 0; i < pairs.length; i += 2) {
0893:                            String prefix = pairs[i];
0894:                            String nsUri = pairs[i + 1];
0895:                            if (prefix != null && nsUri != null)
0896:                                // in this case, we don't want the redundant binding consolidation
0897:                                // to happen (such as declaring the same namespace URI twice with
0898:                                // different prefixes.) Hence we call the put method directly.
0899:                                nsContext.put(nsUri, prefix);
0900:                        }
0901:                    }
0902:
0903:                    if (schemaLocation != null || noNsSchemaLocation != null) {
0904:                        nsContext.declareNsUri(
0905:                                WellKnownNamespace.XML_SCHEMA_INSTANCE, "xsi",
0906:                                true);
0907:                    }
0908:                }
0909:
0910:                nsContext.collectionMode = true;
0911:                textHasAlreadyPrinted = false;
0912:            }
0913:
0914:            private MimeType expectedMimeType;
0915:
0916:            /**
0917:             * This method is used by {@link MimeTypedTransducer} to set the expected MIME type
0918:             * for the encapsulated {@link Transducer}.
0919:             */
0920:            public MimeType setExpectedMimeType(MimeType expectedMimeType) {
0921:                MimeType old = this .expectedMimeType;
0922:                this .expectedMimeType = expectedMimeType;
0923:                return old;
0924:            }
0925:
0926:            /**
0927:             * True to force inlining.
0928:             */
0929:            private boolean inlineBinaryFlag;
0930:
0931:            public boolean setInlineBinaryFlag(boolean value) {
0932:                boolean old = inlineBinaryFlag;
0933:                this .inlineBinaryFlag = value;
0934:                return old;
0935:            }
0936:
0937:            public boolean getInlineBinaryFlag() {
0938:                return inlineBinaryFlag;
0939:            }
0940:
0941:            /**
0942:             * Field used to support an {@link XmlSchemaType} annotation.
0943:             *
0944:             * <p>
0945:             * When we are marshalling a property with an effective {@link XmlSchemaType},
0946:             * this field is set to hold the QName of that type. The {@link Transducer} that
0947:             * actually converts a Java object into XML can look this property to decide
0948:             * how to marshal the value.
0949:             */
0950:            private QName schemaType;
0951:
0952:            public QName setSchemaType(QName st) {
0953:                QName old = schemaType;
0954:                schemaType = st;
0955:                return old;
0956:            }
0957:
0958:            public QName getSchemaType() {
0959:                return schemaType;
0960:            }
0961:
0962:            void reconcileID() throws SAXException {
0963:                // find objects that were not a part of the object graph
0964:                idReferencedObjects.removeAll(objectsWithId);
0965:
0966:                for (Object idObj : idReferencedObjects) {
0967:                    try {
0968:                        String id = getIdFromObject(idObj);
0969:                        reportError(new NotIdentifiableEventImpl(
0970:                                ValidationEvent.ERROR, Messages.DANGLING_IDREF
0971:                                        .format(id),
0972:                                new ValidationEventLocatorImpl(idObj)));
0973:                    } catch (JAXBException e) {
0974:                        // this error should have been reported already. just ignore here.
0975:                    }
0976:                }
0977:
0978:                // clear the garbage
0979:                idReferencedObjects.clear();
0980:                objectsWithId.clear();
0981:            }
0982:
0983:            public boolean handleError(Exception e) {
0984:                return handleError(e, cycleDetectionStack.peek(), null);
0985:            }
0986:
0987:            public boolean handleError(Exception e, Object source,
0988:                    String fieldName) {
0989:                return handleEvent(new ValidationEventImpl(
0990:                        ValidationEvent.ERROR, e.getMessage(),
0991:                        new ValidationEventLocatorExImpl(source, fieldName), e));
0992:            }
0993:
0994:            public boolean handleEvent(ValidationEvent event) {
0995:                try {
0996:                    return marshaller.getEventHandler().handleEvent(event);
0997:                } catch (JAXBException e) {
0998:                    // impossible
0999:                    throw new Error(e);
1000:                }
1001:            }
1002:
1003:            private void reportMissingObjectError(String fieldName)
1004:                    throws SAXException {
1005:                reportError(new ValidationEventImpl(ValidationEvent.ERROR,
1006:                        Messages.MISSING_OBJECT.format(fieldName),
1007:                        getCurrentLocation(fieldName),
1008:                        new NullPointerException()));
1009:            }
1010:
1011:            /**
1012:             * Called when a referenced object doesn't have an ID.
1013:             */
1014:            public void errorMissingId(Object obj) throws SAXException {
1015:                reportError(new ValidationEventImpl(ValidationEvent.ERROR,
1016:                        Messages.MISSING_ID.format(obj),
1017:                        new ValidationEventLocatorImpl(obj)));
1018:            }
1019:
1020:            public ValidationEventLocator getCurrentLocation(String fieldName) {
1021:                return new ValidationEventLocatorExImpl(cycleDetectionStack
1022:                        .peek(), fieldName);
1023:            }
1024:
1025:            protected ValidationEventLocator getLocation() {
1026:                return getCurrentLocation(null);
1027:            }
1028:
1029:            /**
1030:             * When called from within the realm of the marshaller, this method
1031:             * returns the current {@link XMLSerializer} in charge.
1032:             */
1033:            public static XMLSerializer getInstance() {
1034:                return (XMLSerializer) Coordinator._getInstance();
1035:            }
1036:        }
w__ww__._jav___a2__s___.___com_ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.