| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.chemistry.opencmis.client.bindings.spi.atompub; |
| |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.CONTENT_SRC; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.LINK_HREF; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.LINK_REL; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.LINK_TYPE; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_ACL; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_ALLOWABLEACTIONS; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_CHILDREN; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_COLLECTION; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_COLLECTION_TYPE; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_CONTENT; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_ENTRY; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_FEED; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_HTML; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_LINK; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_NUM_ITEMS; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_OBJECT; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_PATH_SEGMENT; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_RELATIVE_PATH_SEGMENT; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_REPOSITORY_INFO; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_SERVICE; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_TEMPLATE_TEMPLATE; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_TEMPLATE_TYPE; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_TYPE; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_URI_TEMPLATE; |
| import static org.apache.chemistry.opencmis.client.bindings.spi.atompub.CmisAtomPubConstants.TAG_WORKSPACE; |
| |
| import java.io.InputStream; |
| import java.math.BigInteger; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import javax.xml.namespace.QName; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.XMLStreamReader; |
| |
| import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomAcl; |
| import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomAllowableActions; |
| import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomBase; |
| import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomElement; |
| import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomEntry; |
| import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomFeed; |
| import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomLink; |
| import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.HtmlDoc; |
| import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.RepositoryWorkspace; |
| import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.ServiceDoc; |
| import org.apache.chemistry.opencmis.commons.data.ObjectData; |
| import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; |
| import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition; |
| import org.apache.chemistry.opencmis.commons.impl.IOUtils; |
| import org.apache.chemistry.opencmis.commons.impl.XMLConstants; |
| import org.apache.chemistry.opencmis.commons.impl.XMLConstraints; |
| import org.apache.chemistry.opencmis.commons.impl.XMLConverter; |
| import org.apache.chemistry.opencmis.commons.impl.XMLUtils; |
| |
| /** |
| * AtomPub Parser. |
| */ |
| public class AtomPubParser { |
| |
| // public constants |
| public static final String LINK_REL_CONTENT = "@@content@@"; |
| |
| private final InputStream stream; |
| private AtomBase parseResult; |
| |
| public AtomPubParser(InputStream stream) { |
| if (stream == null) { |
| throw new IllegalArgumentException("No stream."); |
| } |
| |
| this.stream = stream; |
| } |
| |
| /** |
| * Parses the stream. |
| */ |
| public void parse() throws XMLStreamException { |
| XMLStreamReader parser = XMLUtils.createParser(stream); |
| |
| try { |
| while (true) { |
| int event = parser.getEventType(); |
| if (event == XMLStreamReader.START_ELEMENT) { |
| QName name = parser.getName(); |
| |
| if (XMLConstants.NAMESPACE_ATOM.equals(name.getNamespaceURI())) { |
| if (TAG_FEED.equals(name.getLocalPart())) { |
| parseResult = parseFeed(parser); |
| break; |
| } else if (TAG_ENTRY.equals(name.getLocalPart())) { |
| parseResult = parseEntry(parser); |
| break; |
| } |
| } else if (XMLConstants.NAMESPACE_CMIS.equals(name.getNamespaceURI())) { |
| if (TAG_ALLOWABLEACTIONS.equals(name.getLocalPart())) { |
| parseResult = parseAllowableActions(parser); |
| break; |
| } else if (TAG_ACL.equals(name.getLocalPart())) { |
| parseResult = parseACL(parser); |
| break; |
| } |
| } else if (XMLConstants.NAMESPACE_APP.equals(name.getNamespaceURI())) { |
| if (TAG_SERVICE.equals(name.getLocalPart())) { |
| parseResult = parseServiceDoc(parser); |
| break; |
| } |
| } else if (TAG_HTML.equalsIgnoreCase(name.getLocalPart())) { |
| parseResult = new HtmlDoc(); |
| break; |
| } |
| } |
| |
| if (!XMLUtils.next(parser)) { |
| break; |
| } |
| } |
| |
| } finally { |
| try { |
| parser.close(); |
| } catch (XMLStreamException xse) { |
| // there is nothing we can do |
| } |
| |
| // make sure the stream is read and closed in all cases |
| IOUtils.consumeAndClose(stream); |
| } |
| } |
| |
| /** |
| * Return the parse results. |
| */ |
| public AtomBase getResults() { |
| return parseResult; |
| } |
| |
| /** |
| * Parses a service document. |
| */ |
| private static ServiceDoc parseServiceDoc(XMLStreamReader parser) throws XMLStreamException { |
| ServiceDoc result = new ServiceDoc(); |
| |
| XMLUtils.next(parser); |
| |
| while (true) { |
| int event = parser.getEventType(); |
| if (event == XMLStreamReader.START_ELEMENT) { |
| QName name = parser.getName(); |
| |
| if (XMLConstants.NAMESPACE_APP.equals(name.getNamespaceURI())) { |
| if (TAG_WORKSPACE.equals(name.getLocalPart())) { |
| result.addWorkspace(parseWorkspace(parser)); |
| } else { |
| XMLUtils.skip(parser); |
| } |
| } else { |
| XMLUtils.skip(parser); |
| } |
| } else if (event == XMLStreamReader.END_ELEMENT) { |
| break; |
| } else { |
| if (!XMLUtils.next(parser)) { |
| break; |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Parses a workspace element in a service document. |
| */ |
| private static RepositoryWorkspace parseWorkspace(XMLStreamReader parser) throws XMLStreamException { |
| RepositoryWorkspace workspace = new RepositoryWorkspace(); |
| |
| XMLUtils.next(parser); |
| |
| while (true) { |
| int event = parser.getEventType(); |
| if (event == XMLStreamReader.START_ELEMENT) { |
| AtomElement element = parseWorkspaceElement(parser); |
| |
| // check if we can extract the workspace id |
| if ((element != null) && (element.getObject() instanceof RepositoryInfo)) { |
| workspace.setId(((RepositoryInfo) element.getObject()).getId()); |
| } |
| |
| // add to workspace |
| workspace.addElement(element); |
| } else if (event == XMLStreamReader.END_ELEMENT) { |
| break; |
| } else { |
| if (!XMLUtils.next(parser)) { |
| break; |
| } |
| } |
| } |
| |
| XMLUtils.next(parser); |
| |
| return workspace; |
| } |
| |
| /** |
| * Parses an Atom feed. |
| */ |
| private AtomFeed parseFeed(XMLStreamReader parser) throws XMLStreamException { |
| AtomFeed result = new AtomFeed(); |
| |
| XMLUtils.next(parser); |
| |
| while (true) { |
| int event = parser.getEventType(); |
| if (event == XMLStreamReader.START_ELEMENT) { |
| QName name = parser.getName(); |
| |
| if (XMLConstants.NAMESPACE_ATOM.equals(name.getNamespaceURI())) { |
| if (TAG_LINK.equals(name.getLocalPart())) { |
| result.addElement(parseLink(parser)); |
| } else if (TAG_ENTRY.equals(name.getLocalPart())) { |
| result.addEntry(parseEntry(parser)); |
| } else { |
| XMLUtils.skip(parser); |
| } |
| } else if (XMLConstants.NAMESPACE_RESTATOM.equals(name.getNamespaceURI())) { |
| if (TAG_NUM_ITEMS.equals(name.getLocalPart())) { |
| result.addElement(parseBigInteger(parser)); |
| } else { |
| XMLUtils.skip(parser); |
| } |
| } else if (XMLConstants.NAMESPACE_APACHE_CHEMISTRY.equals(name.getNamespaceURI())) { |
| result.addElement(parseText(parser)); |
| } else { |
| XMLUtils.skip(parser); |
| } |
| } else if (event == XMLStreamReader.END_ELEMENT) { |
| break; |
| } else { |
| if (!XMLUtils.next(parser)) { |
| break; |
| } |
| } |
| } |
| |
| XMLUtils.next(parser); |
| |
| return result; |
| } |
| |
| /** |
| * Parses an Atom entry. |
| */ |
| private AtomEntry parseEntry(XMLStreamReader parser) throws XMLStreamException { |
| AtomEntry result = new AtomEntry(); |
| |
| XMLUtils.next(parser); |
| |
| // walk through all tags in entry |
| while (true) { |
| int event = parser.getEventType(); |
| if (event == XMLStreamReader.START_ELEMENT) { |
| AtomElement element = parseElement(parser); |
| if (element != null) { |
| // add to entry |
| result.addElement(element); |
| |
| // find and set object id |
| if (element.getObject() instanceof ObjectData) { |
| result.setId(((ObjectData) element.getObject()).getId()); |
| } else if (element.getObject() instanceof TypeDefinition) { |
| result.setId(((TypeDefinition) element.getObject()).getId()); |
| } |
| } |
| } else if (event == XMLStreamReader.END_ELEMENT) { |
| break; |
| } else { |
| if (!XMLUtils.next(parser)) { |
| break; |
| } |
| } |
| } |
| |
| XMLUtils.next(parser); |
| |
| return result; |
| } |
| |
| /** |
| * Parses an Allowable Actions document. |
| */ |
| private static AtomAllowableActions parseAllowableActions(XMLStreamReader parser) throws XMLStreamException { |
| return new AtomAllowableActions(XMLConverter.convertAllowableActions(parser)); |
| } |
| |
| /** |
| * Parses an ACL document. |
| */ |
| private static AtomAcl parseACL(XMLStreamReader parser) throws XMLStreamException { |
| return new AtomAcl(XMLConverter.convertAcl(parser)); |
| } |
| |
| /** |
| * Parses an element. |
| */ |
| private AtomElement parseElement(XMLStreamReader parser) throws XMLStreamException { |
| QName name = parser.getName(); |
| |
| if (XMLConstants.NAMESPACE_RESTATOM.equals(name.getNamespaceURI())) { |
| if (TAG_OBJECT.equals(name.getLocalPart())) { |
| return new AtomElement(name, XMLConverter.convertObject(parser)); |
| } else if (TAG_PATH_SEGMENT.equals(name.getLocalPart()) |
| || TAG_RELATIVE_PATH_SEGMENT.equals(name.getLocalPart())) { |
| return parseText(parser); |
| } else if (TAG_TYPE.equals(name.getLocalPart())) { |
| return new AtomElement(name, XMLConverter.convertTypeDefinition(parser)); |
| } else if (TAG_CHILDREN.equals(name.getLocalPart())) { |
| return parseChildren(parser); |
| } |
| } else if (XMLConstants.NAMESPACE_ATOM.equals(name.getNamespaceURI())) { |
| if (TAG_LINK.equals(name.getLocalPart())) { |
| return parseLink(parser); |
| } else if (TAG_CONTENT.equals(name.getLocalPart())) { |
| return parseAtomContentSrc(parser); |
| } |
| } |
| |
| // we don't know it - skip it |
| XMLUtils.skip(parser); |
| |
| return null; |
| } |
| |
| /** |
| * Parses a children element. |
| */ |
| private AtomElement parseChildren(XMLStreamReader parser) throws XMLStreamException { |
| AtomElement result = null; |
| QName childName = parser.getName(); |
| |
| XMLUtils.next(parser); |
| |
| // walk through the children tag |
| while (true) { |
| int event = parser.getEventType(); |
| if (event == XMLStreamReader.START_ELEMENT) { |
| QName name = parser.getName(); |
| |
| if (XMLConstants.NAMESPACE_ATOM.equals(name.getNamespaceURI())) { |
| if (TAG_FEED.equals(name.getLocalPart())) { |
| result = new AtomElement(childName, parseFeed(parser)); |
| } else { |
| XMLUtils.skip(parser); |
| } |
| } else { |
| XMLUtils.skip(parser); |
| } |
| } else if (event == XMLStreamReader.END_ELEMENT) { |
| break; |
| } else { |
| if (!XMLUtils.next(parser)) { |
| break; |
| } |
| } |
| } |
| |
| XMLUtils.next(parser); |
| |
| return result; |
| } |
| |
| /** |
| * Parses a workspace element. |
| */ |
| private static AtomElement parseWorkspaceElement(XMLStreamReader parser) throws XMLStreamException { |
| QName name = parser.getName(); |
| |
| if (XMLConstants.NAMESPACE_RESTATOM.equals(name.getNamespaceURI())) { |
| if (TAG_REPOSITORY_INFO.equals(name.getLocalPart())) { |
| return new AtomElement(name, XMLConverter.convertRepositoryInfo(parser)); |
| } else if (TAG_URI_TEMPLATE.equals(name.getLocalPart())) { |
| return parseTemplate(parser); |
| } |
| } else if (XMLConstants.NAMESPACE_ATOM.equals(name.getNamespaceURI())) { |
| if (TAG_LINK.equals(name.getLocalPart())) { |
| return parseLink(parser); |
| } |
| } else if (XMLConstants.NAMESPACE_APP.equals(name.getNamespaceURI())) { |
| if (TAG_COLLECTION.equals(name.getLocalPart())) { |
| return parseCollection(parser); |
| } |
| } |
| |
| // we don't know it - skip it |
| XMLUtils.skip(parser); |
| |
| return null; |
| } |
| |
| /** |
| * Parses a collection tag. |
| */ |
| private static AtomElement parseCollection(XMLStreamReader parser) throws XMLStreamException { |
| QName name = parser.getName(); |
| Map<String, String> result = new HashMap<String, String>(); |
| |
| result.put("href", parser.getAttributeValue(null, "href")); |
| |
| XMLUtils.next(parser); |
| |
| while (true) { |
| int event = parser.getEventType(); |
| if (event == XMLStreamReader.START_ELEMENT) { |
| QName tagName = parser.getName(); |
| if (XMLConstants.NAMESPACE_RESTATOM.equals(tagName.getNamespaceURI()) |
| && TAG_COLLECTION_TYPE.equals(tagName.getLocalPart())) { |
| result.put("collectionType", XMLUtils.readText(parser, XMLConstraints.MAX_STRING_LENGTH)); |
| } else { |
| XMLUtils.skip(parser); |
| } |
| } else if (event == XMLStreamReader.END_ELEMENT) { |
| break; |
| } else { |
| if (!XMLUtils.next(parser)) { |
| break; |
| } |
| } |
| } |
| |
| XMLUtils.next(parser); |
| |
| return new AtomElement(name, result); |
| } |
| |
| /** |
| * Parses a template tag. |
| */ |
| private static AtomElement parseTemplate(XMLStreamReader parser) throws XMLStreamException { |
| QName name = parser.getName(); |
| Map<String, String> result = new HashMap<String, String>(); |
| |
| XMLUtils.next(parser); |
| |
| while (true) { |
| int event = parser.getEventType(); |
| if (event == XMLStreamReader.START_ELEMENT) { |
| QName tagName = parser.getName(); |
| if (XMLConstants.NAMESPACE_RESTATOM.equals(tagName.getNamespaceURI())) { |
| if (TAG_TEMPLATE_TEMPLATE.equals(tagName.getLocalPart())) { |
| result.put("template", XMLUtils.readText(parser, XMLConstraints.MAX_STRING_LENGTH)); |
| } else if (TAG_TEMPLATE_TYPE.equals(tagName.getLocalPart())) { |
| result.put("type", XMLUtils.readText(parser, XMLConstraints.MAX_STRING_LENGTH)); |
| } else { |
| XMLUtils.skip(parser); |
| } |
| } else { |
| XMLUtils.skip(parser); |
| } |
| } else if (event == XMLStreamReader.END_ELEMENT) { |
| break; |
| } else { |
| if (!XMLUtils.next(parser)) { |
| break; |
| } |
| } |
| } |
| |
| XMLUtils.next(parser); |
| |
| return new AtomElement(name, result); |
| } |
| |
| /** |
| * Parses a link tag. |
| */ |
| private static AtomElement parseLink(XMLStreamReader parser) throws XMLStreamException { |
| QName name = parser.getName(); |
| AtomLink result = new AtomLink(); |
| |
| // save attributes |
| for (int i = 0; i < parser.getAttributeCount(); i++) { |
| if (LINK_REL.equals(parser.getAttributeLocalName(i))) { |
| result.setRel(parser.getAttributeValue(i)); |
| } else if (LINK_HREF.equals(parser.getAttributeLocalName(i))) { |
| result.setHref(parser.getAttributeValue(i)); |
| } else if (LINK_TYPE.equals(parser.getAttributeLocalName(i))) { |
| result.setType(parser.getAttributeValue(i)); |
| } |
| } |
| |
| // skip enclosed tags, if any |
| XMLUtils.skip(parser); |
| |
| return new AtomElement(name, result); |
| } |
| |
| /** |
| * Parses a link tag. |
| */ |
| private static AtomElement parseAtomContentSrc(XMLStreamReader parser) throws XMLStreamException { |
| QName name = parser.getName(); |
| AtomLink result = new AtomLink(); |
| result.setRel(LINK_REL_CONTENT); |
| |
| // save attributes |
| for (int i = 0; i < parser.getAttributeCount(); i++) { |
| if (CONTENT_SRC.equals(parser.getAttributeLocalName(i))) { |
| result.setHref(parser.getAttributeValue(i)); |
| } |
| } |
| |
| // skip enclosed tags, if any |
| XMLUtils.skip(parser); |
| |
| return new AtomElement(name, result); |
| } |
| |
| /** |
| * Parses a text tag. |
| */ |
| private static AtomElement parseText(XMLStreamReader parser) throws XMLStreamException { |
| QName name = parser.getName(); |
| return new AtomElement(name, XMLUtils.readText(parser, XMLConstraints.MAX_STRING_LENGTH)); |
| } |
| |
| /** |
| * Parses a text tag and convert it into an integer. |
| */ |
| private static AtomElement parseBigInteger(XMLStreamReader parser) throws XMLStreamException { |
| QName name = parser.getName(); |
| return new AtomElement(name, new BigInteger(XMLUtils.readText(parser, XMLConstraints.MAX_STRING_LENGTH))); |
| } |
| } |