FELIX-6218 : Replace kxml2 with standard SAX XML parser. Apply patch provided by Mat Booth.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1874024 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/bnd.bnd b/scr/bnd.bnd
index 420c0e0..ebba0c1 100644
--- a/scr/bnd.bnd
+++ b/scr/bnd.bnd
@@ -39,5 +39,3 @@
org.osgi.service.cm;version="[1.6,2)", \
org.osgi.service.log;version="[1.3,2)", \
org.osgi.service.metatype;version="[1.1,2)"
-
-Embed-Dependency: kxml2;inline=org/kxml2/io/KXmlParser.class|org/xmlpull/v1/XmlPull**
diff --git a/scr/pom.xml b/scr/pom.xml
index fc03501..847b1c5 100644
--- a/scr/pom.xml
+++ b/scr/pom.xml
@@ -129,12 +129,6 @@
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>net.sf.kxml</groupId>
- <artifactId>kxml2</artifactId>
- <version>2.2.2</version>
- <scope>provided</scope>
- </dependency>
<!-- Testing -->
<dependency>
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
index 3494b09..0b2469d 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
@@ -18,10 +18,8 @@
*/
package org.apache.felix.scr.impl;
-import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
@@ -34,6 +32,9 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
import org.apache.felix.scr.impl.helper.ConfigAdminTracker;
import org.apache.felix.scr.impl.logger.BundleLogger;
import org.apache.felix.scr.impl.logger.ComponentLogger;
@@ -47,7 +48,6 @@
import org.apache.felix.scr.impl.manager.RegionConfigurationSupport;
import org.apache.felix.scr.impl.manager.ScrConfiguration;
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
-import org.apache.felix.scr.impl.parser.KXml2SAXParser;
import org.apache.felix.scr.impl.xml.XmlHandler;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -276,7 +276,7 @@
/**
* Gets the MetaData location, parses the meta data and requests the processing
* of binder instances
- * @param cachedComponentMetadata
+ * @param cachedComponentMetadata
*
* @throws IllegalStateException If the bundle has already been uninstalled.
*/
@@ -321,6 +321,7 @@
continue;
}
+
// load from the descriptors
for (URL descriptorURL : descriptorURLs)
{
@@ -434,12 +435,13 @@
{
stream = descriptorURL.openStream();
- BufferedReader in = new BufferedReader( new InputStreamReader( stream, "UTF-8" ) );
XmlHandler handler = new XmlHandler( m_bundle, this.logger, getConfiguration().isFactoryEnabled(),
getConfiguration().keepInstances() );
- final KXml2SAXParser parser = new KXml2SAXParser( in );
+ final SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ final SAXParser parser = factory.newSAXParser();
- parser.parseXML( handler );
+ parser.parse( stream, handler );
// 112.4.2 Component descriptors may contain a single, root component element
// or one or more component elements embedded in a larger document
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXHandler.java b/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXHandler.java
deleted file mode 100644
index b6e4c36..0000000
--- a/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXHandler.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.scr.impl.parser;
-
-import org.apache.felix.scr.impl.parser.KXml2SAXParser.Attributes;
-
-/**
- * Interface for a SAX like handler with kXML
- */
-public interface KXml2SAXHandler {
-
- /**
- * Method called when parsing text
- *
- * @param text
- * @exception ParseException
- */
- void characters(String text) throws ParseException;
-
- /**
- * Method called when a tag opens
- *
- * @param uri
- * @param localName
- * @param attributes
- * @exception ParseException
- */
- void startElement(
- String uri,
- String localName,
- Attributes attributes)
- throws ParseException;
-
- /**
- * Method called when a tag closes
- *
- * @param uri
- * @param localName
- * @exception ParseException
- */
- void endElement(
- String uri,
- String localName)
- throws ParseException;
-
- void processingInstruction(String target,
- String data)
- throws Exception;
-
- void setLineNumber(int lineNumber);
-
- void setColumnNumber(int columnNumber);
-}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXParser.java b/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXParser.java
deleted file mode 100644
index 39717c8..0000000
--- a/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXParser.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.scr.impl.parser;
-
-
-import java.io.Reader;
-import java.util.Stack;
-
-import org.kxml2.io.KXmlParser;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-
-/**
- * The KXml2SAXParser extends the XmlParser from kxml. This is a very
- * simple parser that does not take into account the DTD
- *
- */
-public class KXml2SAXParser extends KXmlParser
-{
-
- /**
- * The constructor for a parser, it receives a java.io.Reader.
- *
- * @param reader The reader
- * @throws XmlPullParserException
- */
- public KXml2SAXParser( Reader reader ) throws XmlPullParserException
- {
- super();
- setInput( reader );
- setFeature( FEATURE_PROCESS_NAMESPACES, true );
- }
-
-
- /**
- * Parser from the reader provided in the constructor, and call
- * the startElement and endElement in a KxmlHandler
- *
- * @param handler The handler
- * @exception Exception thrown by the superclass
- */
- public void parseXML( KXml2SAXHandler handler ) throws Exception
- {
-
- final Stack<XmlElement> openElements = new Stack<XmlElement>();
- XmlElement currentElement = null;
- final Attributes attributes = new Attributes();
-
- while ( next() != XmlPullParser.END_DOCUMENT )
- {
- handler.setLineNumber( getLineNumber() );
- handler.setColumnNumber( getColumnNumber() );
-
- if ( getEventType() == XmlPullParser.START_TAG )
- {
- currentElement = new XmlElement( getNamespace(), getName(), getLineNumber(), getColumnNumber() );
- openElements.push( currentElement );
-
- handler.startElement( getNamespace(), getName(), attributes );
- }
- else if ( getEventType() == XmlPullParser.END_TAG )
- {
- ensureMatchingCurrentElement(currentElement);
- openElements.pop();
- currentElement = openElements.isEmpty() ? null : ( XmlElement ) openElements.peek();
-
- handler.endElement( getNamespace(), getName() );
- }
- else if ( getEventType() == XmlPullParser.TEXT )
- {
- String text = getText();
- handler.characters( text );
- }
- else if ( getEventType() == XmlPullParser.PROCESSING_INSTRUCTION )
- {
- // TODO extract the target from the evt.getText()
- handler.processingInstruction( null, getText() );
- }
- else
- {
- // do nothing
- }
- }
-
- if ( !openElements.isEmpty() )
- {
- throw new ParseException( "Unclosed elements found: " + openElements, null );
- }
- }
-
-
- private void ensureMatchingCurrentElement( final XmlElement currentElement ) throws Exception
- {
- if ( currentElement == null )
- {
- throw new ParseException( "Unexpected closing element "
- + new XmlElement( getNamespace(), getName(), getLineNumber(), getColumnNumber() ), null );
- }
-
- if ( !currentElement.match( getNamespace(), getName() ) )
- {
- throw new ParseException( "Unexpected closing element "
- + new XmlElement( getNamespace(), getName(), getLineNumber(), getColumnNumber() )
- + ": Does not match opening element " + currentElement, null );
- }
- }
-
- private static class XmlElement
- {
-
- final String namespaceUri;
- final String name;
- final int line;
- final int col;
-
-
- XmlElement( final String namespaceUri, final String name, final int line, final int col )
- {
- this.namespaceUri = namespaceUri;
- this.name = name;
- this.line = line;
- this.col = col;
- }
-
-
- boolean match( final String namespaceUri, final String name )
- {
- return namespaceUri.equals( this.namespaceUri ) && name.equals( this.name );
- }
-
- @Override
- public String toString()
- {
- return name + "@" + line + ":" + col;
- }
- }
-
- public class Attributes {
-
- public String getAttribute(String name) {
- return getAttributeValue("", name);
- }
-
- public String getAttribute(String uri, String name) {
- return getAttributeValue(uri, name);
- }
-
- public boolean getBoolAttribute(String name, boolean defaultValue) {
- return getBoolAttribute("", name, defaultValue);
- }
-
- public boolean getBoolAttribute(String uri, String name, boolean defaultValue) {
- final String val = getAttribute(uri, name);
- if ( val != null ) {
- return "true".equals(val);
- }
- return defaultValue;
- }
- }
-}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/parser/ParseException.java b/scr/src/main/java/org/apache/felix/scr/impl/parser/ParseException.java
deleted file mode 100644
index c1bf6f2..0000000
--- a/scr/src/main/java/org/apache/felix/scr/impl/parser/ParseException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.scr.impl.parser;
-
-public class ParseException extends Exception
-{
- private static final long serialVersionUID = 7476908955452692098L;
-
- public ParseException(String msg, Exception originalException) {
- super(msg, originalException);
- }
-
-}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java b/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java
index aa7acf2..0d461fd 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java
@@ -32,16 +32,16 @@
import org.apache.felix.scr.impl.metadata.PropertyMetadata;
import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
import org.apache.felix.scr.impl.metadata.ServiceMetadata;
-import org.apache.felix.scr.impl.parser.KXml2SAXHandler;
-import org.apache.felix.scr.impl.parser.KXml2SAXParser.Attributes;
-import org.apache.felix.scr.impl.parser.ParseException;
import org.osgi.framework.Bundle;
import org.osgi.service.log.LogService;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
/**
* XML Parser for the component XML
*/
-public class XmlHandler implements KXml2SAXHandler
+public class XmlHandler extends DefaultHandler
{
// the bundle containing the XML resource being parsed
private final Bundle m_bundle;
@@ -68,6 +68,8 @@
// PropertyMetaData whose value attribute is missing, hence has element data
private PropertyMetadata m_pendingFactoryProperty;
+ private StringBuilder propertyBuilder;
+
/** Flag for detecting the first element. */
protected boolean firstElement = true;
@@ -99,16 +101,8 @@
}
- /**
- * Method called when a tag opens
- *
- * @param uri
- * @param localName
- * @param attributes
- * @exception ParseException
- **/
@Override
- public void startElement( String uri, String localName, Attributes attributes ) throws ParseException
+ public void startElement( String uri, String localName, String qName, Attributes attributes ) throws SAXException
{
// according to the spec, the elements should have the namespace,
// except when the root element is the "component" element
@@ -152,77 +146,77 @@
m_currentComponent = new ComponentMetadata( namespaceCode );
// name attribute is optional (since DS 1.1)
- if ( attributes.getAttribute( XmlConstants.ATTR_NAME ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) != null )
{
- m_currentComponent.setName( attributes.getAttribute( XmlConstants.ATTR_NAME ) );
+ m_currentComponent.setName( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) );
}
// enabled attribute is optional
- if ( attributes.getAttribute( "enabled" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "enabled" ) != null )
{
- m_currentComponent.setEnabled( attributes.getAttribute( "enabled" ).equals( "true" ) );
+ m_currentComponent.setEnabled( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "enabled" ).equals( "true" ) );
}
// immediate attribute is optional
- if ( attributes.getAttribute( "immediate" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "immediate" ) != null )
{
- m_currentComponent.setImmediate( attributes.getAttribute( "immediate" ).equals( "true" ) );
+ m_currentComponent.setImmediate( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "immediate" ).equals( "true" ) );
}
// factory attribute is optional
- if ( attributes.getAttribute( "factory" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "factory" ) != null )
{
- m_currentComponent.setFactoryIdentifier( attributes.getAttribute( "factory" ) );
+ m_currentComponent.setFactoryIdentifier( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "factory" ) );
}
// configuration-policy is optional (since DS 1.1)
- if ( attributes.getAttribute( "configuration-policy" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "configuration-policy" ) != null )
{
- m_currentComponent.setConfigurationPolicy( attributes.getAttribute( "configuration-policy" ) );
+ m_currentComponent.setConfigurationPolicy( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "configuration-policy" ) );
}
// activate attribute is optional (since DS 1.1)
- if ( attributes.getAttribute( "activate" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "activate" ) != null )
{
- m_currentComponent.setActivate( attributes.getAttribute( "activate" ) );
+ m_currentComponent.setActivate( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "activate" ) );
}
// deactivate attribute is optional (since DS 1.1)
- if ( attributes.getAttribute( "deactivate" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "deactivate" ) != null )
{
- m_currentComponent.setDeactivate( attributes.getAttribute( "deactivate" ) );
+ m_currentComponent.setDeactivate( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "deactivate" ) );
}
// modified attribute is optional (since DS 1.1)
- if ( attributes.getAttribute( "modified" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "modified" ) != null )
{
- m_currentComponent.setModified( attributes.getAttribute( "modified" ) );
+ m_currentComponent.setModified( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "modified" ) );
}
// configuration-pid attribute is optional (since DS 1.2)
- String configurationPidString = attributes.getAttribute( "configuration-pid" );
+ String configurationPidString = attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "configuration-pid" );
if (configurationPidString != null)
{
String[] configurationPid = configurationPidString.split( " " );
m_currentComponent.setConfigurationPid( configurationPid );
}
- m_currentComponent.setConfigurableServiceProperties("true".equals(attributes.getAttribute(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_CONFIGURABLE_SERVICE_PROPERTIES)));
- m_currentComponent.setPersistentFactoryComponent("true".equals(attributes.getAttribute(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_PERSISTENT_FACTORY_COMPONENT)));
- m_currentComponent.setDeleteCallsModify("true".equals(attributes.getAttribute(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_DELETE_CALLS_MODIFY)));
- if ( attributes.getAttribute(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_OBSOLETE_FACTORY_COMPONENT_FACTORY) != null)
+ m_currentComponent.setConfigurableServiceProperties("true".equals(attributes.getValue(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_CONFIGURABLE_SERVICE_PROPERTIES)));
+ m_currentComponent.setPersistentFactoryComponent("true".equals(attributes.getValue(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_PERSISTENT_FACTORY_COMPONENT)));
+ m_currentComponent.setDeleteCallsModify("true".equals(attributes.getValue(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_DELETE_CALLS_MODIFY)));
+ if ( attributes.getValue(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_OBSOLETE_FACTORY_COMPONENT_FACTORY) != null)
{
- m_currentComponent.setObsoleteFactoryComponentFactory("true".equals(attributes.getAttribute(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_OBSOLETE_FACTORY_COMPONENT_FACTORY)));
+ m_currentComponent.setObsoleteFactoryComponentFactory("true".equals(attributes.getValue(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_OBSOLETE_FACTORY_COMPONENT_FACTORY)));
}
else if ( !namespaceCode.isDS13() )
{
m_currentComponent.setObsoleteFactoryComponentFactory(m_globalObsoleteFactoryComponentFactory);
}
- m_currentComponent.setConfigureWithInterfaces("true".equals(attributes.getAttribute(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_CONFIGURE_WITH_INTERFACES)));
- m_currentComponent.setDelayedKeepInstances(m_globalDelayedKeepInstances || "true".equals(attributes.getAttribute(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_DELAYED_KEEP_INSTANCES)));
+ m_currentComponent.setConfigureWithInterfaces("true".equals(attributes.getValue(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_CONFIGURE_WITH_INTERFACES)));
+ m_currentComponent.setDelayedKeepInstances(m_globalDelayedKeepInstances || "true".equals(attributes.getValue(XmlConstants.NAMESPACE_URI_1_0_FELIX_EXTENSIONS, XmlConstants.ATTR_DELAYED_KEEP_INSTANCES)));
// activation-fields is optional (since DS 1.4)
- String activationFields = attributes.getAttribute( XmlConstants.ATTR_ACTIVATION_FIELDS );
+ String activationFields = attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_ACTIVATION_FIELDS );
if ( activationFields != null )
{
final String[] fields = activationFields.split(" ");
@@ -230,7 +224,7 @@
}
// init is optional (since DS 1.4)
- String init = attributes.getAttribute( XmlConstants.ATTR_INIT );
+ String init = attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_INIT );
if ( init != null )
{
m_currentComponent.setInit( init );
@@ -252,7 +246,7 @@
else if ( localName.equals( XmlConstants.EL_IMPL ) )
{
// Set the implementation class name (mandatory)
- m_currentComponent.setImplementationClassName( attributes.getAttribute( "class" ) );
+ m_currentComponent.setImplementationClassName( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "class" ) );
}
// 112.4.5 [...] Property Elements
else if ( localName.equals( XmlConstants.EL_PROPERTY ) )
@@ -260,18 +254,18 @@
PropertyMetadata prop = new PropertyMetadata();
// name attribute is mandatory
- prop.setName( attributes.getAttribute( XmlConstants.ATTR_NAME ) );
+ prop.setName( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) );
// type attribute is optional
- if ( attributes.getAttribute( XmlConstants.ATTR_TYPE ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_TYPE ) != null )
{
- prop.setType( attributes.getAttribute( XmlConstants.ATTR_TYPE ) );
+ prop.setType( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_TYPE ) );
}
// 112.4.5: If the value attribute is specified, the body of the element is ignored.
- if ( attributes.getAttribute( XmlConstants.ATTR_VALUE ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_VALUE ) != null )
{
- prop.setValue( attributes.getAttribute( XmlConstants.ATTR_VALUE ) );
+ prop.setValue( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_VALUE ) );
m_currentComponent.addProperty( prop );
}
else
@@ -283,7 +277,7 @@
// 112.4.5 Properties [...] Elements
else if ( localName.equals( XmlConstants.EL_PROPERTIES ) )
{
- final Properties props = readPropertiesEntry( attributes.getAttribute( "entry" ) );
+ final Properties props = readPropertiesEntry( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "entry" ) );
// create PropertyMetadata for the properties from the file
for ( Map.Entry<Object, Object> pEntry: props.entrySet() )
{
@@ -300,18 +294,18 @@
PropertyMetadata prop = new PropertyMetadata();
// name attribute is mandatory
- prop.setName( attributes.getAttribute( XmlConstants.ATTR_NAME ) );
+ prop.setName( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) );
// type attribute is optional
- if ( attributes.getAttribute( XmlConstants.ATTR_TYPE ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_TYPE ) != null )
{
- prop.setType( attributes.getAttribute( XmlConstants.ATTR_TYPE ) );
+ prop.setType( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_TYPE ) );
}
// 112.4.5: If the value attribute is specified, the body of the element is ignored.
- if ( attributes.getAttribute( XmlConstants.ATTR_VALUE ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_VALUE ) != null )
{
- prop.setValue( attributes.getAttribute( XmlConstants.ATTR_VALUE ) );
+ prop.setValue( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_VALUE ) );
m_currentComponent.addFactoryProperty( prop );
}
else
@@ -323,7 +317,7 @@
// 112.4.9 [...] Factory Properties Element
else if ( localName.equals( XmlConstants.EL_FACTORY_PROPERTIES ) )
{
- final Properties props = readPropertiesEntry( attributes.getAttribute( "entry" ) );
+ final Properties props = readPropertiesEntry( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "entry" ) );
// create PropertyMetadata for the properties from the file
for ( Map.Entry<Object, Object> pEntry: props.entrySet() )
{
@@ -340,21 +334,21 @@
m_currentService = new ServiceMetadata();
// servicefactory attribute is optional
- if ( attributes.getAttribute( "servicefactory" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "servicefactory" ) != null )
{
- m_currentService.setServiceFactory( attributes.getAttribute( "servicefactory" ).equals( "true" ) );
+ m_currentService.setServiceFactory( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "servicefactory" ).equals( "true" ) );
}
- if ( attributes.getAttribute( "scope" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "scope" ) != null )
{
- m_currentService.setScope( attributes.getAttribute( "scope" ) );
+ m_currentService.setScope( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "scope" ) );
}
m_currentComponent.setService( m_currentService );
}
else if ( localName.equals( XmlConstants.EL_PROVIDE ) )
{
- m_currentService.addProvide( attributes.getAttribute( XmlConstants.ATTR_INTERFACE ) );
+ m_currentService.addProvide( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_INTERFACE ) );
}
// 112.4.7 Reference element
@@ -363,58 +357,58 @@
ReferenceMetadata ref = new ReferenceMetadata();
// name attribute is optional (since DS 1.1)
- if ( attributes.getAttribute( XmlConstants.ATTR_NAME ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) != null )
{
- ref.setName( attributes.getAttribute( XmlConstants.ATTR_NAME ) );
+ ref.setName( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) );
}
- ref.setInterface( attributes.getAttribute( XmlConstants.ATTR_INTERFACE ) );
+ ref.setInterface( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_INTERFACE ) );
// Cardinality
- if ( attributes.getAttribute( "cardinality" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "cardinality" ) != null )
{
- ref.setCardinality( attributes.getAttribute( "cardinality" ) );
+ ref.setCardinality( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "cardinality" ) );
}
- if ( attributes.getAttribute( "policy" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "policy" ) != null )
{
- ref.setPolicy( attributes.getAttribute( "policy" ) );
+ ref.setPolicy( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "policy" ) );
}
- if ( attributes.getAttribute( "policy-option" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "policy-option" ) != null )
{
- ref.setPolicyOption( attributes.getAttribute( "policy-option" ) );
+ ref.setPolicyOption( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "policy-option" ) );
}
- if ( attributes.getAttribute( "scope" ) != null )
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "scope" ) != null )
{
- ref.setScope( attributes.getAttribute( "scope" ) );
+ ref.setScope( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "scope" ) );
}
- if ( attributes.getAttribute( "target" ) != null)
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "target" ) != null)
{
- ref.setTarget( attributes.getAttribute( "target" ) );
+ ref.setTarget( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "target" ) );
PropertyMetadata prop = new PropertyMetadata();
prop.setName( (ref.getName() == null? ref.getInterface(): ref.getName()) + ".target");
- prop.setValue( attributes.getAttribute( "target" ) );
+ prop.setValue( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "target" ) );
m_currentComponent.addProperty( prop );
}
// method reference
- ref.setBind( attributes.getAttribute( "bind" ) );
- ref.setUpdated( attributes.getAttribute( "updated" ) );
- ref.setUnbind( attributes.getAttribute( "unbind" ) );
+ ref.setBind( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "bind" ) );
+ ref.setUpdated( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "updated" ) );
+ ref.setUnbind( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "unbind" ) );
// field reference
- ref.setField( attributes.getAttribute( "field" ) );
- ref.setFieldOption( attributes.getAttribute( "field-option" ) );
- ref.setFieldCollectionType( attributes.getAttribute( "field-collection-type" ) );
+ ref.setField( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "field" ) );
+ ref.setFieldOption( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "field-option" ) );
+ ref.setFieldCollectionType( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "field-collection-type" ) );
// DS 1.4 : references as parameter of the activator (method or constructor)
- if ( attributes.getAttribute( "parameter" ) != null)
+ if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "parameter" ) != null)
{
- ref.setParameter( attributes.getAttribute( "parameter" ) );
+ ref.setParameter( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "parameter" ) );
}
@@ -431,7 +425,7 @@
}
catch ( Exception ex )
{
- throw new ParseException( "Exception during parsing", ex );
+ throw new SAXException( "Exception during parsing", ex );
}
}
@@ -445,14 +439,8 @@
}
- /**
- * Method called when a tag closes
- *
- * @param uri
- * @param localName
- */
@Override
- public void endElement( String uri, String localName )
+ public void endElement(String uri, String localName, String qName) throws SAXException
{
if ( overrideNamespace != null && XmlConstants.NAMESPACE_URI_EMPTY.equals( uri ) )
{
@@ -472,71 +460,41 @@
}
else if ( localName.equals( XmlConstants.EL_PROPERTY ) && m_pendingProperty != null )
{
- // 112.4.5 body expected to contain property value
- // if so, the m_pendingProperty field would be null
- // currently, we just ignore this situation
+ if (propertyBuilder != null) {
+ m_pendingProperty.setValues(propertyBuilder.toString());
+ propertyBuilder = null;
+ } else {
+ m_pendingProperty.setValues("");
+ }
+ m_currentComponent.addProperty( m_pendingProperty );
m_pendingProperty = null;
}
else if ( localName.equals( XmlConstants.EL_FACTORY_PROPERTY ) && m_pendingFactoryProperty != null )
{
- // 112.4.5 body expected to contain property value
- // if so, the m_pendingFactoryProperty field would be null
- // currently, we just ignore this situation
+ if (propertyBuilder != null) {
+ m_pendingFactoryProperty.setValues(propertyBuilder.toString());
+ propertyBuilder = null;
+ } else {
+ m_pendingFactoryProperty.setValues("");
+ }
+ m_currentComponent.addFactoryProperty( m_pendingFactoryProperty );
m_pendingFactoryProperty = null;
}
}
}
- /**
- * @see org.apache.felix.scr.impl.parser.KXml2SAXHandler#characters(java.lang.String)
- */
@Override
- public void characters( String text )
+ public void characters(char[] ch, int start, int length) throws SAXException
{
// 112.4.5 If the value attribute is not specified, the body must contain one or more values
- if ( m_pendingProperty != null )
+ if ( m_pendingProperty != null || m_pendingFactoryProperty != null )
{
- m_pendingProperty.setValues( text );
- m_currentComponent.addProperty( m_pendingProperty );
- m_pendingProperty = null;
+ if (propertyBuilder == null) {
+ propertyBuilder = new StringBuilder();
+ }
+ propertyBuilder.append(String.valueOf( ch, start, length));
}
- if ( m_pendingFactoryProperty != null )
- {
- m_pendingFactoryProperty.setValues( text );
- m_currentComponent.addFactoryProperty( m_pendingFactoryProperty );
- m_pendingFactoryProperty = null;
- }
- }
-
-
- /**
- * @see org.apache.felix.scr.impl.parser.KXml2SAXHandler#processingInstruction(java.lang.String, java.lang.String)
- */
- @Override
- public void processingInstruction( String target, String data )
- {
- // Not used
- }
-
-
- /**
- * @see org.apache.felix.scr.impl.parser.KXml2SAXHandler#setLineNumber(int)
- */
- @Override
- public void setLineNumber( int lineNumber )
- {
- // Not used
- }
-
-
- /**
- * @see org.apache.felix.scr.impl.parser.KXml2SAXHandler#setColumnNumber(int)
- */
- @Override
- public void setColumnNumber( int columnNumber )
- {
- // Not used
}
@@ -548,21 +506,21 @@
* @param entryName The name of the bundle entry containing the propertes
* to be added. This must not be <code>null</code>.
*
- * @throws ParseException If the entry name is <code>null</code> or no
+ * @throws SAXException If the entry name is <code>null</code> or no
* entry with the given name exists in the bundle or an error occurrs
* reading the properties file.
*/
- private Properties readPropertiesEntry( String entryName ) throws ParseException
+ private Properties readPropertiesEntry( String entryName ) throws SAXException
{
if ( entryName == null )
{
- throw new ParseException( "Missing entry attribute of properties element", null );
+ throw new SAXException( "Missing entry attribute of properties element", null );
}
URL entryURL = m_bundle.getEntry( entryName );
if ( entryURL == null )
{
- throw new ParseException( "Missing bundle entry " + entryName, null );
+ throw new SAXException( "Missing bundle entry " + entryName, null );
}
Properties props = new Properties();
@@ -574,7 +532,7 @@
}
catch ( IOException ioe )
{
- throw new ParseException( "Failed to read properties entry " + entryName, ioe );
+ throw new SAXException( "Failed to read properties entry " + entryName, ioe );
}
finally
{
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentBase.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentBase.java
index 84ccb18..8b93ac9 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentBase.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentBase.java
@@ -19,19 +19,23 @@
package org.apache.felix.scr.impl.metadata;
import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.util.Iterator;
import java.util.List;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
import org.apache.felix.scr.impl.MockBundle;
import org.apache.felix.scr.impl.logger.MockBundleLogger;
-import org.apache.felix.scr.impl.parser.KXml2SAXParser;
import org.apache.felix.scr.impl.xml.XmlHandler;
import org.osgi.service.component.ComponentException;
-import org.xmlpull.v1.XmlPullParserException;
+import org.xml.sax.SAXException;
import junit.framework.TestCase;
@@ -47,45 +51,32 @@
logger = new MockBundleLogger();
}
- private List readMetadata(final Reader reader)
- throws IOException, ComponentException, XmlPullParserException, Exception
+ private List readMetadata(InputStream in)
+ throws IOException, ComponentException, SAXException, Exception
{
+ final SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ final SAXParser parser = factory.newSAXParser();
- try
- {
- final KXml2SAXParser parser = new KXml2SAXParser(reader);
+ XmlHandler handler = new XmlHandler(new MockBundle(), logger, false, false);
+ parser.parse(in, handler);
- XmlHandler handler = new XmlHandler(new MockBundle(), logger, false, false);
- parser.parseXML(handler);
-
- return handler.getComponentMetadataList();
- }
- finally
- {
- try
- {
- reader.close();
- }
- catch (IOException ignore)
- {
- }
- }
+ return handler.getComponentMetadataList();
}
protected List readMetadata(String filename)
- throws IOException, ComponentException, XmlPullParserException, Exception
+ throws IOException, ComponentException, SAXException, Exception
{
- try (BufferedReader in = new BufferedReader(
- new InputStreamReader(getClass().getResourceAsStream(filename), "UTF-8")))
+ try (InputStream in = getClass().getResourceAsStream(filename))
{
return readMetadata(in);
}
}
protected List readMetadataFromString(final String source)
- throws IOException, ComponentException, XmlPullParserException, Exception
+ throws IOException, ComponentException, SAXException, Exception
{
- return readMetadata(new StringReader(source));
+ return readMetadata(new ByteArrayInputStream(source.getBytes()));
}
protected ReferenceMetadata getReference(final ComponentMetadata cm,
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetaDataCacheTest.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetaDataCacheTest.java
index 8836e36..fe2546a 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetaDataCacheTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetaDataCacheTest.java
@@ -30,7 +30,7 @@
import org.apache.felix.scr.impl.metadata.MetadataStoreHelper.MetaDataReader;
import org.apache.felix.scr.impl.metadata.MetadataStoreHelper.MetaDataWriter;
-import org.xmlpull.v1.XmlPullParserException;
+import org.xml.sax.SAXException;
public class ComponentMetaDataCacheTest extends ComponentBase
{
@@ -61,7 +61,7 @@
}
private void doTestCachedComponentMetadata(String xmlFile, DSVersion version)
- throws IOException, XmlPullParserException, Exception
+ throws IOException, SAXException, Exception
{
final List<?> metadataList = readMetadata(xmlFile);
assertEquals("Component Descriptors size not as expected", 1,
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
index 281c53c..6ee8992 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
@@ -21,8 +21,8 @@
import java.util.List;
-import org.apache.felix.scr.impl.parser.ParseException;
import org.osgi.service.component.ComponentException;
+import org.xml.sax.SAXException;
public class XmlHandlerTest extends ComponentBase
@@ -35,7 +35,7 @@
readMetadataFromString( "<component name=\"n\"><implementation class=\"n\" /><component name=\"x\">" );
fail( "ParseException expected for unclosed elements" );
}
- catch ( ParseException pe )
+ catch ( SAXException pe )
{
// exptected
}
@@ -49,7 +49,7 @@
readMetadataFromString( "</component>" );
fail( "Exception expected for element without opening element" );
}
- catch ( Exception p )
+ catch ( SAXException p )
{
// exptected
}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/xml/XmlHandlerTest.java b/scr/src/test/java/org/apache/felix/scr/impl/xml/XmlHandlerTest.java
new file mode 100755
index 0000000..94d8c62
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/impl/xml/XmlHandlerTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.scr.impl.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.felix.scr.impl.logger.MockBundleLogger;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.framework.Bundle;
+
+public class XmlHandlerTest {
+
+ @Test
+ public void testPropertiesWithoutValue() throws Exception {
+ final URL url = this.getClass().getClassLoader().getResource("parsertest-nopropvalue.xml");
+ parse(url);
+ }
+
+ private void parse(final URL descriptorURL) throws Exception {
+ final Bundle bundle = Mockito.mock(Bundle.class);
+ Mockito.when(bundle.getLocation()).thenReturn("bundle");
+
+ InputStream stream = null;
+ try {
+ stream = descriptorURL.openStream();
+
+ XmlHandler handler = new XmlHandler(bundle, new MockBundleLogger(), false, false);
+ final SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ final SAXParser parser = factory.newSAXParser();
+
+ parser.parse(stream, handler);
+
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException ignore) {
+ }
+ }
+ }
+
+ }
+}
diff --git a/scr/src/test/resources/parsertest-nopropvalue.xml b/scr/src/test/resources/parsertest-nopropvalue.xml
new file mode 100755
index 0000000..c1d5b2a
--- /dev/null
+++ b/scr/src/test/resources/parsertest-nopropvalue.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.0.0" name="org.apache.sling.server.impl.jmx.ManagedRepository">
+ <property name="jmx.objectname" value="org.apache.sling:type=Repository"/>
+ <property name="repository.config"/>
+ <property name="bootstrap.properties"/>
+ <property name="service.vendor" value="The Apache Software Foundation"/>
+ <service servicefactory="false">
+ <provide interface="org.apache.sling.server.jmx.ManagedRepositoryMBean"/>
+ </service>
+ <reference name="productInfo" interface="org.apache.sling.license.ProductInfoService" cardinality="1..1" policy="static" bind="bindProductInfo" unbind="unbindProductInfo"/>
+ <reference name="repository" interface="org.apache.sling.Repository" cardinality="1..1" policy="static" bind="bindRepository" unbind="unbindRepository"/>
+ <reference name="backup" interface="org.apache.sling.FileStoreBackupService" cardinality="1..1" policy="static" bind="bindBackup" unbind="unbindBackup"/>
+ <reference name="repositoryManagementMBean" interface="org.apache.jackrabbit.oak.api.jmx.RepositoryManagementMBean" cardinality="1..1" policy="static" bind="bindRepositoryManagementMBean" unbind="unbindRepositoryMa
+nagementMBean"/>
+ <implementation class="org.apache.sling.server.impl.jmx.ManagedRepository"/>
+</scr:component>
\ No newline at end of file