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