blob: ff319621a481954f6469a3eea43e7235ebcd39d0 [file] [log] [blame]
/*
* 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 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;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
/**
* 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 XmlPullParserException {
XmlPullParser parser = XMLUtils.createParser(stream);
try {
while (true) {
int event = parser.getEventType();
if (event == XmlPullParser.START_TAG) {
QName name = new QName(parser.getNamespace(), 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 {
// 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(XmlPullParser parser) throws XmlPullParserException {
ServiceDoc result = new ServiceDoc();
XMLUtils.next(parser);
while (true) {
int event = parser.getEventType();
if (event == XmlPullParser.START_TAG) {
QName name = new QName(parser.getNamespace(), 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 == XmlPullParser.END_TAG) {
break;
} else {
if (!XMLUtils.next(parser)) {
break;
}
}
}
return result;
}
/**
* Parses a workspace element in a service document.
*/
private static RepositoryWorkspace parseWorkspace(XmlPullParser parser) throws XmlPullParserException {
RepositoryWorkspace workspace = new RepositoryWorkspace();
XMLUtils.next(parser);
while (true) {
int event = parser.getEventType();
if (event == XmlPullParser.START_TAG) {
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 == XmlPullParser.END_TAG) {
break;
} else {
if (!XMLUtils.next(parser)) {
break;
}
}
}
XMLUtils.next(parser);
return workspace;
}
/**
* Parses an Atom feed.
*/
private AtomFeed parseFeed(XmlPullParser parser) throws XmlPullParserException {
AtomFeed result = new AtomFeed();
XMLUtils.next(parser);
while (true) {
int event = parser.getEventType();
if (event == XmlPullParser.START_TAG) {
QName name = new QName(parser.getNamespace(), 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 {
XMLUtils.skip(parser);
}
} else if (event == XmlPullParser.END_TAG) {
break;
} else {
if (!XMLUtils.next(parser)) {
break;
}
}
}
XMLUtils.next(parser);
return result;
}
/**
* Parses an Atom entry.
*
* @throws XmlPullParserException
*/
private AtomEntry parseEntry(XmlPullParser parser) throws XmlPullParserException {
AtomEntry result = new AtomEntry();
XMLUtils.next(parser);
// walk through all tags in entry
while (true) {
int event = parser.getEventType();
if (event == XmlPullParser.START_TAG) {
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 == XmlPullParser.END_TAG) {
break;
} else {
if (!XMLUtils.next(parser)) {
break;
}
}
}
XMLUtils.next(parser);
return result;
}
/**
* Parses an Allowable Actions document.
*/
private static AtomAllowableActions parseAllowableActions(XmlPullParser parser) throws XmlPullParserException {
return new AtomAllowableActions(XMLConverter.convertAllowableActions(parser));
}
/**
* Parses an ACL document.
*/
private static AtomAcl parseACL(XmlPullParser parser) throws XmlPullParserException {
return new AtomAcl(XMLConverter.convertAcl(parser));
}
/**
* Parses an element.
*
* @throws XmlPullParserException
*/
private AtomElement parseElement(XmlPullParser parser) throws XmlPullParserException {
QName name = new QName(parser.getNamespace(), 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(XmlPullParser parser) throws XmlPullParserException {
AtomElement result = null;
QName childName = new QName(parser.getNamespace(), parser.getName());
XMLUtils.next(parser);
// walk through the children tag
while (true) {
int event = parser.getEventType();
if (event == XmlPullParser.START_TAG) {
QName name = new QName(parser.getNamespace(), 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 == XmlPullParser.END_TAG) {
break;
} else {
if (!XMLUtils.next(parser)) {
break;
}
}
}
XMLUtils.next(parser);
return result;
}
/**
* Parses a workspace element.
*/
private static AtomElement parseWorkspaceElement(XmlPullParser parser) throws XmlPullParserException {
QName name = new QName(parser.getNamespace(), 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(XmlPullParser parser) throws XmlPullParserException {
QName name = new QName(parser.getNamespace(), 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 == XmlPullParser.START_TAG) {
QName tagName = new QName(parser.getNamespace(), 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 == XmlPullParser.END_TAG) {
break;
} else {
if (!XMLUtils.next(parser)) {
break;
}
}
}
XMLUtils.next(parser);
return new AtomElement(name, result);
}
/**
* Parses a template tag.
*/
private static AtomElement parseTemplate(XmlPullParser parser) throws XmlPullParserException {
QName name = new QName(parser.getNamespace(), parser.getName());
Map<String, String> result = new HashMap<String, String>();
XMLUtils.next(parser);
while (true) {
int event = parser.getEventType();
if (event == XmlPullParser.START_TAG) {
QName tagName = new QName(parser.getNamespace(), 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 == XmlPullParser.END_TAG) {
break;
} else {
if (!XMLUtils.next(parser)) {
break;
}
}
}
XMLUtils.next(parser);
return new AtomElement(name, result);
}
/**
* Parses a link tag.
*/
private static AtomElement parseLink(XmlPullParser parser) throws XmlPullParserException {
QName name = new QName(parser.getNamespace(), parser.getName());
AtomLink result = new AtomLink();
// save attributes
for (int i = 0; i < parser.getAttributeCount(); i++) {
if (LINK_REL.equals(parser.getAttributeName(i))) {
result.setRel(parser.getAttributeValue(i));
} else if (LINK_HREF.equals(parser.getAttributeName(i))) {
result.setHref(parser.getAttributeValue(i));
} else if (LINK_TYPE.equals(parser.getAttributeName(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(XmlPullParser parser) throws XmlPullParserException {
QName name = new QName(parser.getNamespace(), 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.getAttributeName(i))) {
result.setHref(parser.getAttributeValue(i));
}
}
// skip enclosed tags, if any
XMLUtils.skip(parser);
return new AtomElement(name, result);
}
/**
* Parses a text tag.
*
* @throws XmlPullParserException
*/
private static AtomElement parseText(XmlPullParser parser) throws XmlPullParserException {
QName name = new QName(parser.getNamespace(), 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(XmlPullParser parser) throws XmlPullParserException {
QName name = new QName(parser.getNamespace(), parser.getName());
return new AtomElement(name, new BigInteger(XMLUtils.readText(parser, XMLConstraints.MAX_STRING_LENGTH)));
}
}