public void startElement()

in scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java [109:445]


    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
        // So we check this for the first element, we receive.
        if ( firstElement )
        {
            firstElement = false;
            if ( localName.equals( XmlConstants.EL_COMPONENT ) && XmlConstants.NAMESPACE_URI_EMPTY.equals( uri ) )
            {
                overrideNamespace = XmlConstants.NAMESPACE_URI;
            }
        }

        if ( overrideNamespace != null && XmlConstants.NAMESPACE_URI_EMPTY.equals( uri ) )
        {
            uri = overrideNamespace;
        }

        // FELIX-695: however the spec also states that the inner elements
        // of a component are unqualified, so they don't have
        // the namespace - we allow both: with or without namespace!
        if ( this.isComponent && XmlConstants.NAMESPACE_URI_EMPTY.equals(uri) )
        {
            uri = XmlConstants.NAMESPACE_URI;
        }

        // get the namespace code for the namespace uri
        DSVersion namespaceCode = XmlConstants.NAMESPACE_CODE_MAP.get( uri );
        // from now on uri points to the namespace
        if ( namespaceCode != null )
        {
            try
            {

                // 112.4.3 Component Element
                if ( localName.equals( XmlConstants.EL_COMPONENT ) )
                {
                    this.isComponent = true;

                    // Create a new ComponentMetadata
                    m_currentComponent = new ComponentMetadata( namespaceCode );

                    // name attribute is optional (since DS 1.1)
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) != null )
                    {
                        m_currentComponent.setName( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) );
                    }

                    // enabled attribute is optional
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "enabled" ) != null )
                    {
                        m_currentComponent.setEnabled( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "enabled" ).equals( "true" ) );
                    }

                    // immediate attribute is optional
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "immediate" ) != null )
                    {
                        m_currentComponent.setImmediate( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "immediate" ).equals( "true" ) );
                    }

                    // factory attribute is optional
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "factory" ) != null )
                    {
                        m_currentComponent.setFactoryIdentifier( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "factory" ) );
                    }

                    // configuration-policy is optional (since DS 1.1)
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "configuration-policy" ) != null )
                    {
                        m_currentComponent.setConfigurationPolicy( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "configuration-policy" ) );
                    }

                    // activate attribute is optional (since DS 1.1)
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "activate" ) != null )
                    {
                        m_currentComponent.setActivate( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "activate" ) );
                    }

                    // deactivate attribute is optional (since DS 1.1)
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "deactivate" ) != null )
                    {
                        m_currentComponent.setDeactivate( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "deactivate" ) );
                    }

                    // modified attribute is optional (since DS 1.1)
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "modified" ) != null )
                    {
                        m_currentComponent.setModified( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "modified" ) );
                    }

                    // configuration-pid attribute is optional (since DS 1.2)
                    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.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.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.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.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_ACTIVATION_FIELDS );
                    if ( activationFields != null )
                    {
                        final String[] fields = activationFields.split(" ");
                        m_currentComponent.setActivationFields( fields );
                    }

                    // init is optional (since DS 1.4)
                    String init = attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_INIT );
                    if ( init != null )
                    {
                        m_currentComponent.setInit( init );
                    }

                    // Add this component to the list
                    m_components.add( m_currentComponent );
                }

                // not inside a component element, ignore current element
                else if ( !this.isComponent )
                {
                    m_logger.log(Level.DEBUG,
                            "Not currently parsing a component; ignoring element {0} (bundle {1})", null,
                                    localName, m_bundle.getLocation() );
                }

                // 112.4.4 Implementation
                else if ( localName.equals( XmlConstants.EL_IMPL ) )
                {
                    // Set the implementation class name (mandatory)
                    m_currentComponent.setImplementationClassName( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "class" ) );
                }
                // 112.4.5 [...] Property Elements
                else if ( localName.equals( XmlConstants.EL_PROPERTY ) )
                {
                    PropertyMetadata prop = new PropertyMetadata();

                    // name attribute is mandatory
                    prop.setName( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) );

                    // type attribute is optional
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_TYPE ) != null )
                    {
                        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.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_VALUE ) != null )
                    {
                        prop.setValue( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_VALUE ) );
                        m_currentComponent.addProperty( prop );
                    }
                    else
                    {
                        // hold the metadata pending
                        m_pendingProperty = prop;
                    }
                }
                // 112.4.5 Properties [...] Elements
                else if ( localName.equals( XmlConstants.EL_PROPERTIES ) )
                {
                    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() )
                    {
                        PropertyMetadata prop = new PropertyMetadata();
                        prop.setName( String.valueOf( pEntry.getKey() ) );
                        prop.setValue( String.valueOf( pEntry.getValue() ) );
                        m_currentComponent.addProperty( prop );
                    }

                }
                // 112.4.9 [...] Factory Property Element
                else if ( localName.equals( XmlConstants.EL_FACTORY_PROPERTY ) )
                {
                    PropertyMetadata prop = new PropertyMetadata();

                    // name attribute is mandatory
                    prop.setName( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) );

                    // type attribute is optional
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_TYPE ) != null )
                    {
                        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.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_VALUE ) != null )
                    {
                        prop.setValue( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_VALUE ) );
                        m_currentComponent.addFactoryProperty( prop );
                    }
                    else
                    {
                        // hold the metadata pending
                        m_pendingFactoryProperty = prop;
                    }
                }
                // 112.4.9 [...] Factory Properties Element
                else if ( localName.equals( XmlConstants.EL_FACTORY_PROPERTIES ) )
                {
                    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() )
                    {
                        PropertyMetadata prop = new PropertyMetadata();
                        prop.setName( String.valueOf( pEntry.getKey() ) );
                        prop.setValue( String.valueOf( pEntry.getValue() ) );
                        m_currentComponent.addFactoryProperty( prop );
                    }
                }
                // 112.4.6 Service Element
                else if ( localName.equals( XmlConstants.EL_SERVICE ) )
                {

                    m_currentService = new ServiceMetadata();

                    // servicefactory attribute is optional
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "servicefactory" ) != null )
                    {
                        m_currentService.setServiceFactory( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "servicefactory" ).equals( "true" ) );
                    }

                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "scope" ) != null )
                    {
                        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.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_INTERFACE ) );
                }

                // 112.4.7 Reference element
                else if ( localName.equals( XmlConstants.EL_REF ) )
                {
                    ReferenceMetadata ref = new ReferenceMetadata();

                    // name attribute is optional (since DS 1.1)
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) != null )
                    {
                        ref.setName( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_NAME ) );
                    }

                    ref.setInterface( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, XmlConstants.ATTR_INTERFACE ) );

                    // Cardinality
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "cardinality" ) != null )
                    {
                        ref.setCardinality( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "cardinality" ) );
                    }

                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "policy" ) != null )
                    {
                        ref.setPolicy( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "policy" ) );
                    }

                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "policy-option" ) != null )
                    {
                        ref.setPolicyOption( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "policy-option" ) );
                    }

                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "scope" ) != null )
                    {
                        ref.setScope( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "scope" ) );
                    }

                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "target" ) != null)
                    {
                        ref.setTarget( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "target" ) );
                        PropertyMetadata prop = new PropertyMetadata(true);
                        prop.setName( (ref.getName() == null? ref.getInterface(): ref.getName()) + ".target");
                        prop.setValue( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "target" ) );
                        m_currentComponent.addProperty( prop );

                    }

                    // method reference
                    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.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "field" ) );
                    ref.setFieldOption( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "field-option" ) );
                    ref.setCollectionType( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "field-collection-type" ) );

                    // DS 1.4 : references as parameter of the activator (method or constructor)
                    if ( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "parameter" ) != null)
                    {
                        ref.setParameter( attributes.getValue( XmlConstants.NAMESPACE_URI_EMPTY, "parameter" ) );

                    }

                    m_currentComponent.addDependency( ref );
                }

                // unexpected element (except the root element "components"
                // used by the Maven SCR Plugin, which is just silently ignored)
                else if ( !localName.equals( XmlConstants.EL_COMPONENTS ) )
                {
                    m_logger.log(Level.DEBUG,
                        "Ignoring unsupported element {0} (bundle {1})", null,
                            localName, m_bundle.getLocation() );
                }
            }
            catch ( Exception ex )
            {
                throw new SAXException( "Exception during parsing", ex );
            }
        }

        // unexpected namespace (except the root element "components"
        // used by the Maven SCR Plugin, which is just silently ignored)
        else if ( !localName.equals( XmlConstants.EL_COMPONENTS ) )
        {
            m_logger.log(Level.DEBUG,
                "Ignoring unsupported element '{'{0}'}'{1} (bundle {2})", null,
                    uri, localName, m_bundle.getLocation()  );
        }
    }