/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Adam Megacz */ package com.caucho.jaxb; import com.caucho.jaxb.adapters.BeanAdapter; import com.caucho.jaxb.skeleton.ClassSkeleton; import com.caucho.jaxb.property.Property; import com.caucho.util.L10N; import com.caucho.vfs.*; import com.caucho.xml.stream.*; import org.w3c.dom.*; import org.xml.sax.*; import javax.xml.bind.*; import javax.xml.bind.annotation.adapters.*; import javax.xml.bind.attachment.*; import javax.xml.bind.helpers.*; import javax.xml.namespace.QName; import javax.xml.stream.*; import javax.xml.stream.events.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.sax.*; import javax.xml.validation.*; import java.net.URL; import java.io.*; import java.util.*; // XXX extends AbstractUnmarshallerImpl public class UnmarshallerImpl implements Unmarshaller { private static final L10N L = new L10N(UnmarshallerImpl.class); private JAXBContextImpl _context; protected boolean validating; private AttachmentUnmarshaller _attachmentUnmarshaller = null; private ValidationEventHandler _validationEventHandler = null; private Listener _listener = null; private HashMap<String,Object> _properties = new HashMap<String,Object>(); private Schema _schema = null; private XMLReader _xmlreader = null; private XmlAdapter _adapter = null; private HashMap<Class,XmlAdapter> _adapters = new HashMap<Class,XmlAdapter>(); UnmarshallerImpl(JAXBContextImpl context) throws JAXBException { _context = context; setEventHandler(JAXBContextImpl.DEFAULT_VALIDATION_EVENT_HANDLER); } // // unmarshallers. // /** * Unmarshall from a DOM node. */ public Object unmarshal(Node node) throws JAXBException { try { XMLInputFactory factory = _context.getXMLInputFactory(); return unmarshal(factory.createXMLStreamReader(new DOMSource(node))); } catch (XMLStreamException e) { throw new JAXBException(e); } } /** * Unmarshall from an input source. */ protected Object unmarshal(XMLReader reader, InputSource source) throws JAXBException { throw new UnsupportedOperationException(); } /** * Unmarshall from an event reader. */ public Object unmarshal(XMLEventReader reader) throws JAXBException { throw new UnsupportedOperationException(); /* try { XMLEvent event = null; while (reader.hasNext()) { event = reader.peek(); if (event.isStartElement()) { StartElement start = (StartElement) event; ClassSkeleton skel = _context.getRootElement(start.getName()); if (skel == null) throw new JAXBException(L.l("'{0}' is an unknown root element", start.getName())); return skel.read(this, reader); } event = reader.nextEvent(); } throw new JAXBException(L.l("Expected root element")); } catch (JAXBException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); }*/ } public <T> JAXBElement<T> unmarshal(XMLEventReader xmlEventReader, Class<T> declaredType) throws JAXBException { throw new UnsupportedOperationException(); } public Object unmarshal(XMLStreamReader reader) throws JAXBException { try { if (reader.nextTag() != XMLStreamReader.START_ELEMENT) throw new JAXBException(L.l("Expected root element")); ClassSkeleton skel = _context.getRootElement(reader.getName()); if (skel == null) throw new JAXBException(L.l("'{0}' is an unknown root element", reader.getName())); return skel.read(this, reader); } catch (JAXBException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } /** * Parses the XML based on an InputStream */ public Object unmarshal(InputStream is) throws JAXBException { try { XMLStreamReader reader = new XMLStreamReaderImpl(is); try { return unmarshal(reader); } finally { reader.close(); } } catch (XMLStreamException e) { throw new JAXBException(e); } } public <T> JAXBElement<T> unmarshal(XMLStreamReader reader, Class<T> declaredType) throws JAXBException { try { while (reader.getEventType() != XMLStreamReader.START_ELEMENT) reader.next(); QName name = reader.getName(); Property property = _context.createProperty(declaredType); T val = (T) property.read(this, reader, null); return new JAXBElement<T>(name, declaredType, val); } catch (Exception e) { throw new RuntimeException(e); } } // // From AbstractUnmarshallerImpl // public UnmarshallerHandler getUnmarshallerHandler() { // The idea here is that we return a SAX ContentHandler which the // user writes to and we use those writes to construct an object. // The object is retrieved using UnmarshallerHandler.getResult(). // This is a "reusable" operation, so we should return a new handler // (or at least a reset one) for each call of this function. return new UnmarshallerHandlerImpl(); } protected UnmarshalException createUnmarshalException(SAXException e) { return new UnmarshalException(e); } public <A extends XmlAdapter> A getAdapter(Class<A> type) { A a = (A)_adapters.get(type); if (a == null) return (A)new BeanAdapter(); return a; } public AttachmentUnmarshaller getAttachmentUnmarshaller() { return _attachmentUnmarshaller; } public ValidationEventHandler getEventHandler() throws JAXBException { return _validationEventHandler; } public Listener getListener() { return _listener; } public Object getProperty(String name) throws PropertyException { return _properties.get(name); } public Schema getSchema() { return _schema; } protected XMLReader getXMLReader() throws JAXBException { return _xmlreader; } public boolean isValidating() throws JAXBException { return validating; } public <A extends XmlAdapter> void setAdapter(Class<A> type, A adapter) { _adapters.put(type, adapter); } public void setAdapter(XmlAdapter adapter) { setAdapter((Class)adapter.getClass(), adapter); } public void setAttachmentUnmarshaller(AttachmentUnmarshaller au) { _attachmentUnmarshaller = au; } public void setEventHandler(ValidationEventHandler handler) throws JAXBException { _validationEventHandler = handler; } public void setListener(Listener listener) { _listener = listener; } public void setProperty(String name, Object value) throws PropertyException { _properties.put(name, value); } public void setSchema(Schema schema) { _schema = schema; } public void setValidating(boolean validating) throws JAXBException { this.validating = validating; } public Object unmarshal(File f) throws JAXBException { FileInputStream fis = null; try { fis = new FileInputStream(f); XMLInputFactory factory = _context.getXMLInputFactory(); return unmarshal(factory.createXMLStreamReader(f.getAbsolutePath(), fis)); } catch (XMLStreamException e) { throw new JAXBException(e); } catch (IOException e) { throw new JAXBException(e); } finally { try { if (fis != null) fis.close(); } catch (IOException e) { throw new JAXBException(e); } } } public Object unmarshal(InputSource inputSource) throws JAXBException { try { XMLEventReader reader = new SAXSourceXMLEventReaderImpl(new SAXSource(inputSource)); return unmarshal(reader); } catch (XMLStreamException e) { throw new JAXBException(e); } } public Object unmarshal(Reader reader) throws JAXBException { try { XMLInputFactory factory = _context.getXMLInputFactory(); return unmarshal(factory.createXMLStreamReader(reader)); } catch (XMLStreamException e) { throw new JAXBException(e); } } public Object unmarshal(Source source) throws JAXBException { try { XMLInputFactory factory = _context.getXMLInputFactory(); return unmarshal(factory.createXMLEventReader(source)); } catch (XMLStreamException e) { throw new JAXBException(e); } } public <T> JAXBElement<T> unmarshal(Node node, Class<T> declaredType) throws JAXBException { throw new UnsupportedOperationException("subclasses must override this"); } public <T> JAXBElement<T> unmarshal(Source node, Class<T> declaredType) throws JAXBException { try { XMLInputFactory factory = XMLInputFactory.newInstance(); return unmarshal(factory.createXMLStreamReader(node), declaredType); } catch (XMLStreamException e) { throw new JAXBException(e); } } public Object unmarshal(URL url) throws JAXBException { try { InputStream is = url.openStream(); try { return unmarshal(is); } finally { is.close(); } } catch (IOException e) { throw new JAXBException(e); } } private class UnmarshallerHandlerImpl implements UnmarshallerHandler { private ContentHandler _handler; private SAXSourceXMLEventReaderImpl _reader; private boolean _done = false; private Object _result = null; public UnmarshallerHandlerImpl() { _reader = new SAXSourceXMLEventReaderImpl(); _handler = _reader.getContentHandler(); } public Object getResult() throws JAXBException { if (! _done) throw new IllegalStateException(); if (_result == null) _result = unmarshal(_reader); return _result; } public void characters(char[] ch, int start, int length) throws SAXException { _handler.characters(ch, start, length); } public void endDocument() throws SAXException { _handler.endDocument(); _done = true; } public void endElement(String uri, String localName, String qName) throws SAXException { _handler.endElement(uri, localName, qName); } public void endPrefixMapping(String prefix) throws SAXException { _handler.endPrefixMapping(prefix); } public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { _handler.ignorableWhitespace(ch, start, length); } public void processingInstruction(String target, String data) throws SAXException { _handler.processingInstruction(target, data); } public void setDocumentLocator(Locator locator) { _handler.setDocumentLocator(locator); } public void skippedEntity(String name) throws SAXException { _handler.skippedEntity(name); } public void startDocument() throws SAXException { _handler.startDocument(); } public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { _handler.startElement(uri, localName, qName, atts); } public void startPrefixMapping(String prefix, String uri) throws SAXException { _handler.startPrefixMapping(prefix, uri); } } }