001: /*
002: * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Adam Megacz
028: */
029:
030: package com.caucho.jaxb;
031:
032: import com.caucho.jaxb.adapters.BeanAdapter;
033: import com.caucho.jaxb.skeleton.ClassSkeleton;
034: import com.caucho.jaxb.property.Property;
035: import com.caucho.util.L10N;
036: import com.caucho.vfs.*;
037: import com.caucho.xml.stream.*;
038:
039: import org.w3c.dom.*;
040: import org.xml.sax.*;
041:
042: import javax.xml.bind.*;
043: import javax.xml.bind.annotation.adapters.*;
044: import javax.xml.bind.attachment.*;
045: import javax.xml.bind.helpers.*;
046: import javax.xml.namespace.QName;
047: import javax.xml.stream.*;
048: import javax.xml.stream.events.*;
049: import javax.xml.transform.*;
050: import javax.xml.transform.dom.*;
051: import javax.xml.transform.sax.*;
052: import javax.xml.validation.*;
053:
054: import java.net.URL;
055: import java.io.*;
056: import java.util.*;
057:
058: // XXX extends AbstractUnmarshallerImpl
059: public class UnmarshallerImpl implements Unmarshaller {
060: private static final L10N L = new L10N(UnmarshallerImpl.class);
061:
062: private JAXBContextImpl _context;
063:
064: protected boolean validating;
065:
066: private AttachmentUnmarshaller _attachmentUnmarshaller = null;
067: private ValidationEventHandler _validationEventHandler = null;
068: private Listener _listener = null;
069: private HashMap<String, Object> _properties = new HashMap<String, Object>();
070: private Schema _schema = null;
071: private XMLReader _xmlreader = null;
072: private XmlAdapter _adapter = null;
073: private HashMap<Class, XmlAdapter> _adapters = new HashMap<Class, XmlAdapter>();
074:
075: UnmarshallerImpl(JAXBContextImpl context) throws JAXBException {
076: _context = context;
077: setEventHandler(JAXBContextImpl.DEFAULT_VALIDATION_EVENT_HANDLER);
078: }
079:
080: //
081: // unmarshallers.
082: //
083:
084: /**
085: * Unmarshall from a DOM node.
086: */
087: public Object unmarshal(Node node) throws JAXBException {
088: try {
089: XMLInputFactory factory = _context.getXMLInputFactory();
090:
091: return unmarshal(factory
092: .createXMLStreamReader(new DOMSource(node)));
093: } catch (XMLStreamException e) {
094: throw new JAXBException(e);
095: }
096: }
097:
098: /**
099: * Unmarshall from an input source.
100: */
101: protected Object unmarshal(XMLReader reader, InputSource source)
102: throws JAXBException {
103: throw new UnsupportedOperationException();
104: }
105:
106: /**
107: * Unmarshall from an event reader.
108: */
109: public Object unmarshal(XMLEventReader reader) throws JAXBException {
110: throw new UnsupportedOperationException();
111:
112: /*
113: try {
114: XMLEvent event = null;
115:
116: while (reader.hasNext()) {
117: event = reader.peek();
118:
119: if (event.isStartElement()) {
120: StartElement start = (StartElement) event;
121:
122: ClassSkeleton skel = _context.getRootElement(start.getName());
123:
124: if (skel == null)
125: throw new JAXBException(L.l("'{0}' is an unknown root element",
126: start.getName()));
127:
128: return skel.read(this, reader);
129: }
130:
131: event = reader.nextEvent();
132: }
133:
134: throw new JAXBException(L.l("Expected root element"));
135: }
136: catch (JAXBException e) {
137: throw e;
138: }
139: catch (Exception e) {
140: throw new RuntimeException(e);
141: }*/
142: }
143:
144: public <T> JAXBElement<T> unmarshal(XMLEventReader xmlEventReader,
145: Class<T> declaredType) throws JAXBException {
146: throw new UnsupportedOperationException();
147: }
148:
149: public Object unmarshal(XMLStreamReader reader)
150: throws JAXBException {
151: try {
152: if (reader.nextTag() != XMLStreamReader.START_ELEMENT)
153: throw new JAXBException(L.l("Expected root element"));
154:
155: ClassSkeleton skel = _context.getRootElement(reader
156: .getName());
157:
158: if (skel == null)
159: throw new JAXBException(L.l(
160: "'{0}' is an unknown root element", reader
161: .getName()));
162:
163: return skel.read(this , reader);
164: } catch (JAXBException e) {
165: throw e;
166: } catch (Exception e) {
167: throw new RuntimeException(e);
168: }
169: }
170:
171: /**
172: * Parses the XML based on an InputStream
173: */
174: public Object unmarshal(InputStream is) throws JAXBException {
175: try {
176: XMLStreamReader reader = new XMLStreamReaderImpl(is);
177:
178: try {
179: return unmarshal(reader);
180: } finally {
181: reader.close();
182: }
183: } catch (XMLStreamException e) {
184: throw new JAXBException(e);
185: }
186: }
187:
188: public <T> JAXBElement<T> unmarshal(XMLStreamReader reader,
189: Class<T> declaredType) throws JAXBException {
190: try {
191: while (reader.getEventType() != XMLStreamReader.START_ELEMENT)
192: reader.next();
193:
194: QName name = reader.getName();
195:
196: Property property = _context.createProperty(declaredType);
197:
198: T val = (T) property.read(this , reader, null);
199:
200: return new JAXBElement<T>(name, declaredType, val);
201: } catch (Exception e) {
202: throw new RuntimeException(e);
203: }
204: }
205:
206: //
207: // From AbstractUnmarshallerImpl
208: //
209:
210: public UnmarshallerHandler getUnmarshallerHandler() {
211: // The idea here is that we return a SAX ContentHandler which the
212: // user writes to and we use those writes to construct an object.
213: // The object is retrieved using UnmarshallerHandler.getResult().
214: // This is a "reusable" operation, so we should return a new handler
215: // (or at least a reset one) for each call of this function.
216:
217: return new UnmarshallerHandlerImpl();
218: }
219:
220: protected UnmarshalException createUnmarshalException(SAXException e) {
221: return new UnmarshalException(e);
222: }
223:
224: public <A extends XmlAdapter> A getAdapter(Class<A> type) {
225: A a = (A) _adapters.get(type);
226:
227: if (a == null)
228: return (A) new BeanAdapter();
229:
230: return a;
231: }
232:
233: public AttachmentUnmarshaller getAttachmentUnmarshaller() {
234: return _attachmentUnmarshaller;
235: }
236:
237: public ValidationEventHandler getEventHandler()
238: throws JAXBException {
239: return _validationEventHandler;
240: }
241:
242: public Listener getListener() {
243: return _listener;
244: }
245:
246: public Object getProperty(String name) throws PropertyException {
247: return _properties.get(name);
248: }
249:
250: public Schema getSchema() {
251: return _schema;
252: }
253:
254: protected XMLReader getXMLReader() throws JAXBException {
255: return _xmlreader;
256: }
257:
258: public boolean isValidating() throws JAXBException {
259: return validating;
260: }
261:
262: public <A extends XmlAdapter> void setAdapter(Class<A> type,
263: A adapter) {
264: _adapters.put(type, adapter);
265: }
266:
267: public void setAdapter(XmlAdapter adapter) {
268: setAdapter((Class) adapter.getClass(), adapter);
269: }
270:
271: public void setAttachmentUnmarshaller(AttachmentUnmarshaller au) {
272: _attachmentUnmarshaller = au;
273: }
274:
275: public void setEventHandler(ValidationEventHandler handler)
276: throws JAXBException {
277: _validationEventHandler = handler;
278: }
279:
280: public void setListener(Listener listener) {
281: _listener = listener;
282: }
283:
284: public void setProperty(String name, Object value)
285: throws PropertyException {
286: _properties.put(name, value);
287: }
288:
289: public void setSchema(Schema schema) {
290: _schema = schema;
291: }
292:
293: public void setValidating(boolean validating) throws JAXBException {
294: this .validating = validating;
295: }
296:
297: public Object unmarshal(File f) throws JAXBException {
298: FileInputStream fis = null;
299: try {
300: fis = new FileInputStream(f);
301: XMLInputFactory factory = _context.getXMLInputFactory();
302: return unmarshal(factory.createXMLStreamReader(f
303: .getAbsolutePath(), fis));
304: } catch (XMLStreamException e) {
305: throw new JAXBException(e);
306: } catch (IOException e) {
307: throw new JAXBException(e);
308: } finally {
309: try {
310: if (fis != null)
311: fis.close();
312: } catch (IOException e) {
313: throw new JAXBException(e);
314: }
315: }
316: }
317:
318: public Object unmarshal(InputSource inputSource)
319: throws JAXBException {
320: try {
321: XMLEventReader reader = new SAXSourceXMLEventReaderImpl(
322: new SAXSource(inputSource));
323:
324: return unmarshal(reader);
325: } catch (XMLStreamException e) {
326: throw new JAXBException(e);
327: }
328: }
329:
330: public Object unmarshal(Reader reader) throws JAXBException {
331: try {
332: XMLInputFactory factory = _context.getXMLInputFactory();
333:
334: return unmarshal(factory.createXMLStreamReader(reader));
335: } catch (XMLStreamException e) {
336: throw new JAXBException(e);
337: }
338: }
339:
340: public Object unmarshal(Source source) throws JAXBException {
341: try {
342: XMLInputFactory factory = _context.getXMLInputFactory();
343:
344: return unmarshal(factory.createXMLEventReader(source));
345: } catch (XMLStreamException e) {
346: throw new JAXBException(e);
347: }
348: }
349:
350: public <T> JAXBElement<T> unmarshal(Node node, Class<T> declaredType)
351: throws JAXBException {
352: throw new UnsupportedOperationException(
353: "subclasses must override this");
354: }
355:
356: public <T> JAXBElement<T> unmarshal(Source node,
357: Class<T> declaredType) throws JAXBException {
358: try {
359: XMLInputFactory factory = XMLInputFactory.newInstance();
360: return unmarshal(factory.createXMLStreamReader(node),
361: declaredType);
362: } catch (XMLStreamException e) {
363: throw new JAXBException(e);
364: }
365: }
366:
367: public Object unmarshal(URL url) throws JAXBException {
368: try {
369: InputStream is = url.openStream();
370:
371: try {
372: return unmarshal(is);
373: } finally {
374: is.close();
375: }
376: } catch (IOException e) {
377: throw new JAXBException(e);
378: }
379: }
380:
381: private class UnmarshallerHandlerImpl implements
382: UnmarshallerHandler {
383: private ContentHandler _handler;
384: private SAXSourceXMLEventReaderImpl _reader;
385: private boolean _done = false;
386: private Object _result = null;
387:
388: public UnmarshallerHandlerImpl() {
389: _reader = new SAXSourceXMLEventReaderImpl();
390: _handler = _reader.getContentHandler();
391: }
392:
393: public Object getResult() throws JAXBException {
394: if (!_done)
395: throw new IllegalStateException();
396:
397: if (_result == null)
398: _result = unmarshal(_reader);
399:
400: return _result;
401: }
402:
403: public void characters(char[] ch, int start, int length)
404: throws SAXException {
405: _handler.characters(ch, start, length);
406: }
407:
408: public void endDocument() throws SAXException {
409: _handler.endDocument();
410: _done = true;
411: }
412:
413: public void endElement(String uri, String localName,
414: String qName) throws SAXException {
415: _handler.endElement(uri, localName, qName);
416: }
417:
418: public void endPrefixMapping(String prefix) throws SAXException {
419: _handler.endPrefixMapping(prefix);
420: }
421:
422: public void ignorableWhitespace(char[] ch, int start, int length)
423: throws SAXException {
424: _handler.ignorableWhitespace(ch, start, length);
425: }
426:
427: public void processingInstruction(String target, String data)
428: throws SAXException {
429: _handler.processingInstruction(target, data);
430: }
431:
432: public void setDocumentLocator(Locator locator) {
433: _handler.setDocumentLocator(locator);
434: }
435:
436: public void skippedEntity(String name) throws SAXException {
437: _handler.skippedEntity(name);
438: }
439:
440: public void startDocument() throws SAXException {
441: _handler.startDocument();
442: }
443:
444: public void startElement(String uri, String localName,
445: String qName, Attributes atts) throws SAXException {
446: _handler.startElement(uri, localName, qName, atts);
447: }
448:
449: public void startPrefixMapping(String prefix, String uri)
450: throws SAXException {
451: _handler.startPrefixMapping(prefix, uri);
452: }
453: }
454: }
|