Thu, 31 Aug 2017 15:18:52 +0800
merge
1 /*
2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package javax.xml.bind.util;
28 import org.xml.sax.ContentHandler;
29 import org.xml.sax.DTDHandler;
30 import org.xml.sax.EntityResolver;
31 import org.xml.sax.ErrorHandler;
32 import org.xml.sax.InputSource;
33 import org.xml.sax.SAXException;
34 import org.xml.sax.SAXNotRecognizedException;
35 import org.xml.sax.SAXParseException;
36 import org.xml.sax.XMLReader;
37 import org.xml.sax.ext.LexicalHandler;
38 import org.xml.sax.helpers.XMLFilterImpl;
40 import javax.xml.bind.JAXBContext;
41 import javax.xml.bind.JAXBException;
42 import javax.xml.bind.Marshaller;
43 import javax.xml.transform.sax.SAXSource;
44 import org.xml.sax.XMLFilter;
46 /**
47 * JAXP {@link javax.xml.transform.Source} implementation
48 * that marshals a JAXB-generated object.
49 *
50 * <p>
51 * This utility class is useful to combine JAXB with
52 * other Java/XML technologies.
53 *
54 * <p>
55 * The following example shows how to use JAXB to marshal a document
56 * for transformation by XSLT.
57 *
58 * <blockquote>
59 * <pre>
60 * MyObject o = // get JAXB content tree
61 *
62 * // jaxbContext is a JAXBContext object from which 'o' is created.
63 * JAXBSource source = new JAXBSource( jaxbContext, o );
64 *
65 * // set up XSLT transformation
66 * TransformerFactory tf = TransformerFactory.newInstance();
67 * Transformer t = tf.newTransformer(new StreamSource("test.xsl"));
68 *
69 * // run transformation
70 * t.transform(source,new StreamResult(System.out));
71 * </pre>
72 * </blockquote>
73 *
74 * <p>
75 * The fact that JAXBSource derives from SAXSource is an implementation
76 * detail. Thus in general applications are strongly discouraged from
77 * accessing methods defined on SAXSource. In particular,
78 * the setXMLReader and setInputSource methods shall never be called.
79 * The XMLReader object obtained by the getXMLReader method shall
80 * be used only for parsing the InputSource object returned by
81 * the getInputSource method.
82 *
83 * <p>
84 * Similarly the InputSource object obtained by the getInputSource
85 * method shall be used only for being parsed by the XMLReader object
86 * returned by the getXMLReader.
87 *
88 * @author
89 * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
90 */
91 public class JAXBSource extends SAXSource {
93 /**
94 * Creates a new {@link javax.xml.transform.Source} for the given content object.
95 *
96 * @param context
97 * JAXBContext that was used to create
98 * <code>contentObject</code>. This context is used
99 * to create a new instance of marshaller and must not be null.
100 * @param contentObject
101 * An instance of a JAXB-generated class, which will be
102 * used as a {@link javax.xml.transform.Source} (by marshalling it into XML). It must
103 * not be null.
104 * @throws JAXBException if an error is encountered while creating the
105 * JAXBSource or if either of the parameters are null.
106 */
107 public JAXBSource( JAXBContext context, Object contentObject )
108 throws JAXBException {
110 this(
111 ( context == null ) ?
112 assertionFailed( Messages.format( Messages.SOURCE_NULL_CONTEXT ) ) :
113 context.createMarshaller(),
115 ( contentObject == null ) ?
116 assertionFailed( Messages.format( Messages.SOURCE_NULL_CONTENT ) ) :
117 contentObject);
118 }
120 /**
121 * Creates a new {@link javax.xml.transform.Source} for the given content object.
122 *
123 * @param marshaller
124 * A marshaller instance that will be used to marshal
125 * <code>contentObject</code> into XML. This must be
126 * created from a JAXBContext that was used to build
127 * <code>contentObject</code> and must not be null.
128 * @param contentObject
129 * An instance of a JAXB-generated class, which will be
130 * used as a {@link javax.xml.transform.Source} (by marshalling it into XML). It must
131 * not be null.
132 * @throws JAXBException if an error is encountered while creating the
133 * JAXBSource or if either of the parameters are null.
134 */
135 public JAXBSource( Marshaller marshaller, Object contentObject )
136 throws JAXBException {
138 if( marshaller == null )
139 throw new JAXBException(
140 Messages.format( Messages.SOURCE_NULL_MARSHALLER ) );
142 if( contentObject == null )
143 throw new JAXBException(
144 Messages.format( Messages.SOURCE_NULL_CONTENT ) );
146 this.marshaller = marshaller;
147 this.contentObject = contentObject;
149 super.setXMLReader(pseudoParser);
150 // pass a dummy InputSource. We don't care
151 super.setInputSource(new InputSource());
152 }
154 private final Marshaller marshaller;
155 private final Object contentObject;
157 // this object will pretend as an XMLReader.
158 // no matter what parameter is specified to the parse method,
159 // it just parse the contentObject.
160 private final XMLReader pseudoParser = new XMLReader() {
161 public boolean getFeature(String name) throws SAXNotRecognizedException {
162 if(name.equals("http://xml.org/sax/features/namespaces"))
163 return true;
164 if(name.equals("http://xml.org/sax/features/namespace-prefixes"))
165 return false;
166 throw new SAXNotRecognizedException(name);
167 }
169 public void setFeature(String name, boolean value) throws SAXNotRecognizedException {
170 if(name.equals("http://xml.org/sax/features/namespaces") && value)
171 return;
172 if(name.equals("http://xml.org/sax/features/namespace-prefixes") && !value)
173 return;
174 throw new SAXNotRecognizedException(name);
175 }
177 public Object getProperty(String name) throws SAXNotRecognizedException {
178 if( "http://xml.org/sax/properties/lexical-handler".equals(name) ) {
179 return lexicalHandler;
180 }
181 throw new SAXNotRecognizedException(name);
182 }
184 public void setProperty(String name, Object value) throws SAXNotRecognizedException {
185 if( "http://xml.org/sax/properties/lexical-handler".equals(name) ) {
186 this.lexicalHandler = (LexicalHandler)value;
187 return;
188 }
189 throw new SAXNotRecognizedException(name);
190 }
192 private LexicalHandler lexicalHandler;
194 // we will store this value but never use it by ourselves.
195 private EntityResolver entityResolver;
196 public void setEntityResolver(EntityResolver resolver) {
197 this.entityResolver = resolver;
198 }
199 public EntityResolver getEntityResolver() {
200 return entityResolver;
201 }
203 private DTDHandler dtdHandler;
204 public void setDTDHandler(DTDHandler handler) {
205 this.dtdHandler = handler;
206 }
207 public DTDHandler getDTDHandler() {
208 return dtdHandler;
209 }
211 // SAX allows ContentHandler to be changed during the parsing,
212 // but JAXB doesn't. So this repeater will sit between those
213 // two components.
214 private XMLFilter repeater = new XMLFilterImpl();
216 public void setContentHandler(ContentHandler handler) {
217 repeater.setContentHandler(handler);
218 }
219 public ContentHandler getContentHandler() {
220 return repeater.getContentHandler();
221 }
223 private ErrorHandler errorHandler;
224 public void setErrorHandler(ErrorHandler handler) {
225 this.errorHandler = handler;
226 }
227 public ErrorHandler getErrorHandler() {
228 return errorHandler;
229 }
231 public void parse(InputSource input) throws SAXException {
232 parse();
233 }
235 public void parse(String systemId) throws SAXException {
236 parse();
237 }
239 public void parse() throws SAXException {
240 // parses a content object by using the given marshaller
241 // SAX events will be sent to the repeater, and the repeater
242 // will further forward it to an appropriate component.
243 try {
244 marshaller.marshal( contentObject, (XMLFilterImpl)repeater );
245 } catch( JAXBException e ) {
246 // wrap it to a SAXException
247 SAXParseException se =
248 new SAXParseException( e.getMessage(),
249 null, null, -1, -1, e );
251 // if the consumer sets an error handler, it is our responsibility
252 // to notify it.
253 if(errorHandler!=null)
254 errorHandler.fatalError(se);
256 // this is a fatal error. Even if the error handler
257 // returns, we will abort anyway.
258 throw se;
259 }
260 }
261 };
263 /**
264 * Hook to throw exception from the middle of a contructor chained call
265 * to this
266 */
267 private static Marshaller assertionFailed( String message )
268 throws JAXBException {
270 throw new JAXBException( message );
271 }
272 }