| /******************************************************************************* |
| * Copyright (c) 2012-2014 SAP SE. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * SAP SE - initial API and implementation and/or initial documentation |
| * |
| *******************************************************************************/ |
| package org.eclipse.ogee.client.parser; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.UnsupportedEncodingException; |
| import java.util.logging.Logger; |
| |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.parsers.SAXParser; |
| import javax.xml.parsers.SAXParserFactory; |
| |
| import org.eclipse.ogee.client.exceptions.MarshalerException; |
| import org.eclipse.ogee.client.exceptions.ParserException; |
| import org.eclipse.ogee.client.model.atom.AppService; |
| import org.eclipse.ogee.client.model.atom.AtomEntry; |
| import org.eclipse.ogee.client.model.atom.AtomFeed; |
| import org.eclipse.ogee.client.model.atom.ODataPropertyImpl; |
| import org.eclipse.ogee.client.model.edmx.Edmx; |
| import org.eclipse.ogee.client.model.generic.ODataCollection; |
| import org.eclipse.ogee.client.model.generic.ODataEntry; |
| import org.eclipse.ogee.client.model.generic.ODataProperty; |
| import org.eclipse.ogee.client.model.generic.ServiceDocument; |
| import org.eclipse.ogee.client.nls.messages.Messages; |
| import org.eclipse.ogee.client.parser.impl.AppServiceTagFactory; |
| import org.eclipse.ogee.client.parser.impl.AtomFeedAndEntryTagFactory; |
| import org.eclipse.ogee.client.parser.impl.Marshaller; |
| import org.eclipse.ogee.client.parser.impl.ODataSaxHandler; |
| import org.eclipse.ogee.client.parser.impl.TagFactory; |
| import org.eclipse.ogee.client.parser.impl.TypeConverter; |
| import org.eclipse.ogee.client.util.Util; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.XMLReader; |
| |
| /** |
| * Atom specific implementation of IODataParser |
| * |
| */ |
| public class ODataAtomParser implements IODataParser { |
| private static final String CHARACTER_ENCODING = "utf-8"; //$NON-NLS-1$ |
| private final static Logger LOGGER = Logger.getLogger(ODataAtomParser.class |
| .getName()); |
| private TypeConverter typeConverter = TypeConverter.ATOM; |
| |
| /** |
| * Construcs a new Atom parser. |
| */ |
| public ODataAtomParser() { |
| super(); |
| } |
| |
| /** |
| * Converts OData entry XML in ATOM format to an AtomEntry object |
| * |
| * @param xml |
| * ATOM format |
| * @return AtomEntry |
| * @throws ParserException |
| */ |
| private AtomEntry fromXmlToAtomEntry(String xml) throws ParserException { |
| if (xml != null) { |
| xml = xml.trim(); |
| } |
| if (xml == null || xml.isEmpty()) { |
| String message = Messages.getString("ODataAtomParser.1"); //$NON-NLS-1$ |
| LOGGER.warning(message); |
| throw new ParserException(message); |
| } |
| |
| InputStream inputStream = null; |
| |
| try { |
| inputStream = new ByteArrayInputStream( |
| xml.getBytes(CHARACTER_ENCODING)); |
| AtomEntry atomEntry = fromXmlToAtomEntry(inputStream); |
| |
| return atomEntry; |
| } catch (UnsupportedEncodingException e) { |
| throw logAndCreateParserException(inputStream, e); |
| } finally { |
| if (inputStream != null) { |
| try { |
| inputStream.close(); |
| } catch (IOException e) { |
| LOGGER.severe(e.getMessage()); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Converts input stream in OData ATOM format to AtomEntry object |
| * |
| * @param inputStream |
| * stream in OData ATOM format |
| * @return AtomEntry |
| * @throws ParserException |
| */ |
| private AtomEntry fromXmlToAtomEntry(InputStream inputStream) |
| throws ParserException { |
| if (inputStream == null) { |
| String message = Messages.getString("ODataAtomParser.2"); //$NON-NLS-1$ |
| LOGGER.warning(message); |
| throw new ParserException(message); |
| } |
| |
| AtomEntry atomEntry = (AtomEntry) parseObject(inputStream, |
| new AtomFeedAndEntryTagFactory()); |
| return atomEntry; |
| } |
| |
| /** |
| * Converts OData Collection XML in OData ATOM format to AtomFeed object |
| * |
| * @param xml |
| * OData ATOM format |
| * @return AtomFeed |
| * @throws ParserException |
| */ |
| private AtomFeed fromXmlToAtomFeed(String xml) throws ParserException { |
| if (xml != null) { |
| xml = xml.trim(); |
| } |
| if (xml == null || xml.isEmpty()) { |
| String message = Messages.getString("ODataAtomParser.3"); //$NON-NLS-1$ |
| LOGGER.warning(message); |
| throw new ParserException(message); |
| } |
| |
| InputStream inputStream = null; |
| |
| try { |
| inputStream = new ByteArrayInputStream( |
| xml.getBytes(CHARACTER_ENCODING)); |
| AtomFeed atomFeed = fromXmlToAtomFeed(inputStream); |
| |
| return atomFeed; |
| } catch (IOException e) { |
| throw logAndCreateParserException(inputStream, e); |
| } finally { |
| if (inputStream != null) { |
| try { |
| inputStream.close(); |
| } catch (IOException e) { |
| LOGGER.severe(e.getMessage()); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Converts input stream in OData ATOM format to AtomFeed object |
| * |
| * @param inputStream |
| * stream in OData ATOM format |
| * @return AtomFeed |
| * @throws ParserException |
| */ |
| private AtomFeed fromXmlToAtomFeed(InputStream inputStream) |
| throws ParserException { |
| if (inputStream == null) { |
| String message = Messages.getString("ODataAtomParser.4"); //$NON-NLS-1$ |
| LOGGER.warning(message); |
| throw new ParserException(message); |
| } |
| |
| AtomFeed atomFeed = (AtomFeed) parseObject(inputStream, |
| new AtomFeedAndEntryTagFactory()); |
| return atomFeed; |
| } |
| |
| /** |
| * Converts Service Document XML in OData ATOM format to AppService object |
| * |
| * @param xml |
| * OData ATOM format |
| * @return AppService |
| * @throws ParserException |
| */ |
| private AppService fromXmlToAppService(String xml) throws ParserException { |
| if (xml != null) { |
| xml = xml.trim(); |
| } |
| if (xml == null || xml.length() == 0) { |
| String message = Messages.getString("ODataAtomParser.5"); //$NON-NLS-1$ |
| LOGGER.warning(message); |
| throw new ParserException(message); |
| } |
| if (!xml.contains("<app:service") && !xml.contains("<service")) //$NON-NLS-1$ //$NON-NLS-2$ |
| { |
| String message = Messages.getString("ODataAtomParser.8"); //$NON-NLS-1$ |
| LOGGER.warning(message); |
| throw new ParserException(message); |
| } |
| |
| InputStream inputStream = null; |
| |
| try { |
| inputStream = new ByteArrayInputStream( |
| xml.getBytes(CHARACTER_ENCODING)); |
| AppService appService = fromXmlToAppService(inputStream); |
| |
| return appService; |
| } catch (IOException e) { |
| throw logAndCreateParserException(inputStream, e); |
| } finally { |
| if (inputStream != null) { |
| try { |
| inputStream.close(); |
| } catch (IOException e) { |
| LOGGER.severe(e.getMessage()); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Converts input stream in OData ATOM format to AppService object |
| * |
| * @param inputStream |
| * stream in SAP Data Protocol format |
| * @return AppService |
| * @throws ParserException |
| */ |
| private AppService fromXmlToAppService(InputStream inputStream) |
| throws ParserException { |
| if (inputStream == null) { |
| String message = Messages.getString("ODataAtomParser.9"); //$NON-NLS-1$ |
| LOGGER.warning(message); |
| throw new ParserException(message); |
| } |
| |
| AppService appService = (AppService) parseObject(inputStream, |
| new AppServiceTagFactory()); |
| return appService; |
| |
| } |
| |
| /** |
| * Parses an object given the inputstream and tag factory parameters. |
| * |
| * @param inputStream |
| * - input stream. |
| * @param tagFactory |
| * - tag factory. |
| * @return - a parsed object. |
| * @throws ParserException |
| */ |
| public Object parseObject(InputStream inputStream, TagFactory tagFactory) |
| throws ParserException { |
| try { |
| ODataSaxHandler handler = new ODataSaxHandler(tagFactory); |
| SAXParserFactory factory = SAXParserFactory.newInstance(); |
| factory.setValidating(true); |
| factory.setFeature( |
| "http://xml.org/sax/features/namespace-prefixes", true); |
| factory.setFeature("http://xml.org/sax/features/namespaces", true); |
| factory.setFeature("http://xml.org/sax/features/validation", true); |
| factory.setFeature( |
| "http://apache.org/xml/features/validation/schema", true); |
| factory.setFeature( |
| "http://apache.org/xml/features/validation/schema-full-checking", |
| true); |
| factory.setFeature( |
| "http://xml.org/sax/features/external-general-entities", false); //$NON-NLS-1$ |
| factory.setFeature( |
| "http://xml.org/sax/features/external-parameter-entities", false); //$NON-NLS-1$ |
| factory.setFeature( |
| "http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$ |
| |
| SAXParser parser = factory.newSAXParser(); |
| XMLReader reader = parser.getXMLReader(); |
| try { |
| reader.setFeature( |
| "http://xml.org/sax/features/namespaces", true); //$NON-NLS-1$ |
| } catch (SAXException e) { |
| LOGGER.severe(Messages.getString("ODataAtomParser.14")); //$NON-NLS-1$ |
| } |
| |
| parser.parse(inputStream, handler); |
| |
| return handler.getRoot(); |
| } catch (ParserConfigurationException e) { |
| throw logAndCreateParserException(inputStream, e); |
| } catch (SAXException e) { |
| throw logAndCreateParserException(inputStream, e); |
| } catch (IOException e) { |
| throw logAndCreateParserException(inputStream, e); |
| } finally { |
| try { |
| inputStream.close(); |
| } catch (IOException e) { |
| LOGGER.severe(e.getMessage()); |
| } |
| } |
| } |
| |
| private static ParserException logAndCreateParserException(String xml, |
| Exception e) { |
| LOGGER.severe(Messages.getString("ODataAtomParser.17") + xml); //$NON-NLS-1$ |
| LOGGER.severe(e.getMessage()); |
| |
| return new ParserException(e.getMessage()); |
| } |
| |
| private static ParserException logAndCreateParserException( |
| InputStream inputStream, Exception e) { |
| try { |
| String xml = Util.convertStreamToString(inputStream); |
| return logAndCreateParserException(xml, e); |
| } catch (IOException ioe) { |
| LOGGER.severe(ioe.getMessage()); |
| return new ParserException(e); |
| } |
| } |
| |
| /** |
| * Converts XML in OData ATOM format to ODataPropertyImpl object |
| * |
| * @param xml |
| * OData ATOM format |
| * @return ODataPropertyImpl |
| * @throws ParserException |
| */ |
| private ODataPropertyImpl fromXmlToDataValue(String xml) |
| throws ParserException { |
| if (xml != null) { |
| xml = xml.trim(); |
| } |
| if (xml == null || xml.length() == 0) { |
| String message = Messages.getString("ODataAtomParser.18"); //$NON-NLS-1$ |
| LOGGER.warning(message); |
| throw new ParserException(message); |
| } |
| |
| InputStream inputStream = null; |
| |
| try { |
| inputStream = new ByteArrayInputStream( |
| xml.getBytes(CHARACTER_ENCODING)); |
| ODataPropertyImpl dataValue = fromXmlToDataValue(inputStream); |
| |
| return dataValue; |
| } catch (IOException e) { |
| LOGGER.severe(e.getMessage()); |
| throw new ParserException(e); |
| } finally { |
| if (inputStream != null) { |
| try { |
| inputStream.close(); |
| } catch (IOException e) { |
| LOGGER.severe(e.getMessage()); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Converts input stream in OData ATOM format to ODataPropertyImpl object |
| * |
| * @param inputStream |
| * stream in OData ATOM format |
| * @return ODataPropertyImpl |
| * @throws ParserException |
| */ |
| private ODataPropertyImpl fromXmlToDataValue(InputStream inputStream) |
| throws ParserException { |
| if (inputStream == null) { |
| String message = Messages.getString("ODataAtomParser.19"); //$NON-NLS-1$ |
| LOGGER.warning(message); |
| throw new ParserException(message); |
| } |
| |
| ODataPropertyImpl dataValue = (ODataPropertyImpl) parseObject( |
| inputStream, new AtomFeedAndEntryTagFactory()); |
| return dataValue; |
| } |
| |
| /** |
| * Converts AtomFeed object to XML in OData ATOM format |
| * |
| * @param atomFeed |
| * AtomFeed |
| * @return String |
| * @throws MarshalerException |
| */ |
| private String toXml(AtomFeed atomFeed) |
| throws org.eclipse.ogee.client.exceptions.MarshalerException { |
| String xml = Marshaller.getInstance().marshal(atomFeed); |
| |
| return xml; |
| } |
| |
| /** |
| * Formats the given entry to string representation. |
| * |
| * @param entry |
| * - the OData entry to format. |
| * @return - A string representation of the given entry. |
| * @throws MarshalerException |
| */ |
| public String format(ODataEntry entry) throws MarshalerException { |
| return toXml((AtomEntry) entry); |
| } |
| |
| /** |
| * Formats the given OData collection to string representation. |
| * |
| * @param collection |
| * - the OData collection to format. |
| * @return - A string representation of the given collection. |
| * @throws MarshalerException |
| */ |
| public String format(ODataCollection collection) throws MarshalerException { |
| return toXml((AtomFeed) collection); |
| } |
| |
| /** |
| * Converts AtomEntry object to XML in OData ATOM format |
| * |
| * @param atomEntry |
| * @return String |
| * @throws MarshalerException |
| */ |
| private String toXml(AtomEntry atomEntry) throws MarshalerException { |
| String xml = Marshaller.getInstance().marshal(atomEntry); |
| |
| return xml; |
| } |
| |
| /** |
| * Parses the given xml to a service document object. |
| * |
| * @param xml |
| * - the xml to parse. |
| * @return - A Service Document object. |
| * @throws ParserException |
| */ |
| public ServiceDocument parseServiceDocument(String xml) |
| throws ParserException { |
| return fromXmlToAppService(xml); |
| } |
| |
| /** |
| * Parses the given xml to an OData collection object. |
| * |
| * @param xml |
| * - the xml to parse. |
| * @return - An OData collection object. |
| * @throws ParserException |
| */ |
| public ODataCollection parseODataCollection(String xml) |
| throws ParserException { |
| return fromXmlToAtomFeed(xml); |
| } |
| |
| /** |
| * Parses the given xml to an OData entry object. |
| * |
| * @param xml |
| * - the xml to parse. |
| * @return - An OData entry object. |
| * @throws ParserException |
| */ |
| public ODataEntry parseODataEntry(String xml) throws ParserException { |
| return fromXmlToAtomEntry(xml); |
| } |
| |
| /** |
| * Parses the given xml to an OData property object. |
| * |
| * @param xml |
| * - the xml to parse. |
| * @return - An OData property object. |
| * @throws ParserException |
| */ |
| public ODataProperty parseODataProperty(String xml) throws ParserException { |
| return fromXmlToDataValue(xml); |
| } |
| |
| @Override |
| public TypeConverter getTypeConverter() { |
| return typeConverter; |
| } |
| |
| @Override |
| public Representation getRepresentation() { |
| return Representation.ATOM; |
| } |
| |
| @Override |
| public String format(Edmx edmx) throws MarshalerException { |
| return Marshaller.getInstance().format(edmx); |
| } |
| } |