blob: 58880c0f39cb1d8e5813d443f80bf6a6e706a25f [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.felix.bundlerepository.impl;
import java.io.InputStream;
import java.io.Reader;
import javax.xml.stream.Location;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
/**
* Repository XML xml based on StaX
*/
public class StaxParser extends RepositoryParser
{
static XMLInputFactory factory;
public static synchronized void setFactory(XMLInputFactory factory)
{
StaxParser.factory = factory;
}
public static synchronized XMLInputFactory getFactory()
{
if (factory == null)
{
XMLInputFactory factory = XMLInputFactory.newInstance();
setProperty(factory, XMLInputFactory.IS_NAMESPACE_AWARE, false);
setProperty(factory, XMLInputFactory.IS_VALIDATING, false);
setProperty(factory, XMLInputFactory.IS_COALESCING, false);
StaxParser.factory = factory;
}
return factory;
}
public StaxParser()
{
}
protected static boolean setProperty(XMLInputFactory factory, String name, boolean value)
{
try
{
factory.setProperty(name, Boolean.valueOf(value));
return true;
}
catch (Throwable t)
{
}
return false;
}
public RepositoryImpl parseRepository(InputStream is) throws Exception
{
XMLStreamReader reader = getFactory().createXMLStreamReader(is);
int event = reader.nextTag();
if (event != XMLStreamConstants.START_ELEMENT || !REPOSITORY.equals(reader.getLocalName()))
{
throw new Exception("Expected element 'repository' at the root of the document");
}
return parseRepository(reader);
}
public RepositoryImpl parseRepository(Reader r) throws Exception
{
XMLStreamReader reader = getFactory().createXMLStreamReader(r);
int event = reader.nextTag();
if (event != XMLStreamConstants.START_ELEMENT || !REPOSITORY.equals(reader.getLocalName()))
{
throw new Exception("Expected element 'repository' at the root of the document");
}
return parseRepository(reader);
}
public ResourceImpl parseResource(Reader r) throws Exception
{
XMLStreamReader reader = getFactory().createXMLStreamReader(r);
int event = reader.nextTag();
if (event != XMLStreamConstants.START_ELEMENT || !RESOURCE.equals(reader.getLocalName()))
{
throw new Exception("Expected element 'resource'");
}
return parseResource(reader);
}
public CapabilityImpl parseCapability(Reader r) throws Exception
{
XMLStreamReader reader = getFactory().createXMLStreamReader(r);
int event = reader.nextTag();
if (event != XMLStreamConstants.START_ELEMENT || !CAPABILITY.equals(reader.getLocalName()))
{
throw new Exception("Expected element 'capability'");
}
return parseCapability(reader);
}
public PropertyImpl parseProperty(Reader r) throws Exception
{
XMLStreamReader reader = getFactory().createXMLStreamReader(r);
int event = reader.nextTag();
if (event != XMLStreamConstants.START_ELEMENT || !P.equals(reader.getLocalName()))
{
throw new Exception("Expected element 'p'");
}
return parseProperty(reader);
}
public RequirementImpl parseRequirement(Reader r) throws Exception
{
XMLStreamReader reader = getFactory().createXMLStreamReader(r);
int event = reader.nextTag();
if (event != XMLStreamConstants.START_ELEMENT || !REQUIRE.equals(reader.getLocalName()))
{
throw new Exception("Expected element 'require'");
}
return parseRequire(reader);
}
public RepositoryImpl parseRepository(XMLStreamReader reader) throws Exception
{
RepositoryImpl repository = new RepositoryImpl();
for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
{
String name = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
if (NAME.equals(name))
{
repository.setName(value);
}
else if (LASTMODIFIED.equals(name))
{
repository.setLastModified(value);
}
}
int event;
while ((event = reader.nextTag()) == XMLStreamConstants.START_ELEMENT)
{
String element = reader.getLocalName();
if (REFERRAL.equals(element))
{
Referral referral = parseReferral(reader);
repository.addReferral(referral);
}
else if (RESOURCE.equals(element))
{
ResourceImpl resource = parseResource(reader);
repository.addResource(resource);
}
else
{
ignoreTag(reader);
}
}
// Sanity check
sanityCheckEndElement(reader, event, REPOSITORY);
return repository;
}
private void sanityCheckEndElement(XMLStreamReader reader, int event, String element)
{
if (event != XMLStreamConstants.END_ELEMENT || !element.equals(reader.getLocalName()))
{
throw new IllegalStateException("Unexpected state while finishing element " + element);
}
}
private Referral parseReferral(XMLStreamReader reader) throws Exception
{
Referral referral = new Referral();
for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
{
String name = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
if (DEPTH.equals(name))
{
referral.setDepth(value);
}
else if (URL.equals(name))
{
referral.setUrl(value);
}
}
sanityCheckEndElement(reader, reader.nextTag(), REFERRAL);
return referral;
}
private ResourceImpl parseResource(XMLStreamReader reader) throws Exception
{
ResourceImpl resource = new ResourceImpl();
try
{
for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
{
resource.put(reader.getAttributeLocalName(i), reader.getAttributeValue(i));
}
int event;
while ((event = reader.nextTag()) == XMLStreamConstants.START_ELEMENT)
{
String element = reader.getLocalName();
if (CATEGORY.equals(element))
{
String category = parseCategory(reader);
resource.addCategory(category);
}
else if (CAPABILITY.equals(element))
{
CapabilityImpl capability = parseCapability(reader);
resource.addCapability(capability);
}
else if (REQUIRE.equals(element))
{
RequirementImpl requirement = parseRequire(reader);
resource.addRequire(requirement);
}
else
{
StringBuffer sb = null;
String type = reader.getAttributeValue(null, "type");
while ((event = reader.next()) != XMLStreamConstants.END_ELEMENT)
{
switch (event)
{
case XMLStreamConstants.START_ELEMENT:
throw new Exception("Unexpected element inside <require/> element");
case XMLStreamConstants.CHARACTERS:
if (sb == null)
{
sb = new StringBuffer();
}
sb.append(reader.getText());
break;
}
}
if (sb != null)
{
resource.put(element, sb.toString().trim(), type);
}
}
}
// Sanity check
if (event != XMLStreamConstants.END_ELEMENT || !RESOURCE.equals(reader.getLocalName()))
{
throw new Exception("Unexpected state");
}
return resource;
}
catch (Exception e)
{
Location loc = reader.getLocation();
if (loc != null) {
throw new Exception("Error while parsing resource " + resource.getId() + " at line " + loc.getLineNumber() + " and column " + loc.getColumnNumber(), e);
}
else
{
throw new Exception("Error while parsing resource " + resource.getId(), e);
}
}
}
private String parseCategory(XMLStreamReader reader) throws XMLStreamException
{
String id = null;
for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
{
if (ID.equals(reader.getAttributeLocalName(i)))
{
id = reader.getAttributeValue(i);
}
}
sanityCheckEndElement(reader, reader.nextTag(), CATEGORY);
return id;
}
private CapabilityImpl parseCapability(XMLStreamReader reader) throws Exception
{
CapabilityImpl capability = new CapabilityImpl();
for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
{
String name = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
if (NAME.equals(name))
{
capability.setName(value);
}
}
int event;
while ((event = reader.nextTag()) == XMLStreamConstants.START_ELEMENT)
{
String element = reader.getLocalName();
if (P.equals(element))
{
PropertyImpl prop = parseProperty(reader);
capability.addProperty(prop);
}
else
{
ignoreTag(reader);
}
}
// Sanity check
sanityCheckEndElement(reader, event, CAPABILITY);
return capability;
}
private PropertyImpl parseProperty(XMLStreamReader reader) throws Exception
{
String n = null, t = null, v = null;
for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
{
String name = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
if (N.equals(name))
{
n = value;
}
else if (T.equals(name))
{
t = value;
}
else if (V.equals(name))
{
v = value;
}
}
PropertyImpl prop = new PropertyImpl(n, t, v);
// Sanity check
sanityCheckEndElement(reader, reader.nextTag(), P);
return prop;
}
private RequirementImpl parseRequire(XMLStreamReader reader) throws Exception
{
RequirementImpl requirement = new RequirementImpl();
for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
{
String name = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
if (NAME.equals(name))
{
requirement.setName(value);
}
else if (FILTER.equals(name))
{
requirement.setFilter(value);
}
else if (EXTEND.equals(name))
{
requirement.setExtend(Boolean.parseBoolean(value));
}
else if (MULTIPLE.equals(name))
{
requirement.setMultiple(Boolean.parseBoolean(value));
}
else if (OPTIONAL.equals(name))
{
requirement.setOptional(Boolean.parseBoolean(value));
}
}
int event;
StringBuffer sb = null;
while ((event = reader.next()) != XMLStreamConstants.END_ELEMENT)
{
switch (event)
{
case XMLStreamConstants.START_ELEMENT:
throw new Exception("Unexpected element inside <require/> element");
case XMLStreamConstants.CHARACTERS:
if (sb == null)
{
sb = new StringBuffer();
}
sb.append(reader.getText());
break;
}
}
if (sb != null)
{
requirement.addText(sb.toString());
}
// Sanity check
sanityCheckEndElement(reader, event, REQUIRE);
return requirement;
}
private void ignoreTag(XMLStreamReader reader) throws XMLStreamException
{
int level = 1;
int event = 0;
while (level > 0)
{
event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT)
{
level++;
}
else if (event == XMLStreamConstants.END_ELEMENT)
{
level--;
}
}
}
}