public void validate()

in scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java [839:1090]


    public void validate( )
    {
        // nothing to do if already validated
        if ( m_validated )
        {
            return;
        }

        // 112.10 The name of the component is required
        if ( m_name == null )
        {
            // 112.4.3 name is optional defaulting to implementation class name since DS 1.1
            if ( !m_dsVersion.isDS11() )
            {
                throw new ComponentException( "The component name has not been set" );
            }
            setName( getImplementationClassName() );
        }

        // 112.10 There must be one implementation element and the class atribute is required
        if ( m_implementationClassName == null )
        {
            throw validationFailure( "Implementation class name missing" );
        }
        else if ( m_implementationClassName == IMPLEMENTATION_CLASS_DUPLICATE )
        {
            throw validationFailure( "Implementation element must occur exactly once" );
        }

        // 112.4.3 configuration-policy (since DS 1.1)
        if ( m_configurationPolicy == null )
        {
            // default if not specified or pre DS 1.1
            m_configurationPolicy = CONFIGURATION_POLICY_OPTIONAL;
        }
        else if ( !m_dsVersion.isDS11() )
        {
            throw validationFailure( "configuration-policy declaration requires DS 1.1 or later namespace " );
        }
        else if ( !CONFIGURATION_POLICY_VALID.contains( m_configurationPolicy ) )
        {
            throw validationFailure( "configuration-policy must be one of " + CONFIGURATION_POLICY_VALID );
        }

        // 112.5.8 activate can be specified (since DS 1.1)
        if ( m_activate == null )
        {
            // default if not specified or pre DS 1.1
            m_activate = "activate";
        }
        else if ( !m_dsVersion.isDS11() )
        {
            throw validationFailure( "activate method declaration requires DS 1.1 or later namespace " );
        }

        // 112.5.12 deactivate can be specified (since DS 1.1)
        if ( m_deactivate == null )
        {
            // default if not specified or pre DS 1.1
            m_deactivate = "deactivate";
        }
        else if ( !m_dsVersion.isDS11() )
        {
            throw validationFailure( "deactivate method declaration requires DS 1.1 or later namespace " );
        }

        // 112.??.?? modified can be specified (since DS 1.1)
        if ( m_modified != null && !m_dsVersion.isDS11() )
        {
            throw validationFailure( "modified method declaration requires DS 1.1 or later namespace " );
        }

        // 112.4.4 configuration-pid can be specified since DS 1.2
        if ( m_configurationPid == null )
        {
            m_configurationPid = Collections.singletonList( getName() );
        }
        else
        {
            if ( !m_dsVersion.isDS12() )
            {
                throw validationFailure( "configuration-pid attribute requires DS 1.2 or later namespace " );
            }
            if (m_configurationPid.isEmpty())
            {
                throw validationFailure( "configuration-pid nust not be empty string " );
            }
            if (m_configurationPid.size() > 1 && !m_dsVersion.isDS13())
            {
                throw validationFailure( "multiple configuration-pid requires DS 1.3 or later namespace " );
            }
            for (int i = 0; i < m_configurationPid.size(); i++)
            {
                if ("$".equals( m_configurationPid.get(i)))
                {
                    if (!m_dsVersion.isDS13())
                    {
                        throw validationFailure( "Use of '$' configuration-pid wildcard requires DS 1.3 or later namespace " );
                    }
                    m_configurationPid.set( i, getName() );
                }
            }
            if ( new HashSet<>( m_configurationPid ).size() != m_configurationPid.size())
            {
                throw validationFailure( "Duplicate pids not allowed: " + m_configurationPid );
            }
        }

        // Next check if the properties are valid (and extract property values)
        for ( PropertyMetadata propMeta: m_propertyMetaData )
        {
            propMeta.validate( this );
            if (m_dsVersion.isDS15() && propMeta.isReferenceTarget())
            {
                // for DS 15 the reference target property must not override,
                // only add if the key does not exist yet
                m_properties.putIfAbsent(propMeta.getName(), propMeta.getValue());
            }
            else
            {
                m_properties.put(propMeta.getName(), propMeta.getValue());
            }
        }
        m_propertyMetaData.clear();

        // Next check if the factory properties are valid (and extract property values)
        if ( !m_dsVersion.isDS14() && !m_factoryPropertyMetaData.isEmpty() )
        {
            throw validationFailure( "Use of factory properties requires DS 1.4 or later namespace " );
        }
        if ( m_dsVersion.isDS14() && isFactory() )
        {
        	    for ( PropertyMetadata propMeta: m_factoryPropertyMetaData )
        	    {
        		    propMeta.validate( this );
        		    m_factoryProperties.put( propMeta.getName(), propMeta.getValue() );
        	    }
        }
        // if this is not a factory, these props are ignored, so nothing else to do
        m_factoryPropertyMetaData.clear();

        // Check that the provided services are valid too
        if ( m_service == SERVICE_DUPLICATE )
        {
            throw validationFailure( "Service element must occur at most once" );
        }
        else if ( m_service != null )
        {
            m_service.validate( this );
        }

        // Check that the references are ok
        Set<String> refs = new HashSet<>();
        for ( ReferenceMetadata refMeta: m_references )
        {
            refMeta.validate( this );

            // flag duplicates
            if ( !refs.add( refMeta.getName() ) )
            {
                throw validationFailure( "Detected duplicate reference name: ''" + refMeta.getName() + "''" );
            }
        }

        // verify value of immediate attribute if set
        if ( m_immediate != null )
        {
            if ( isImmediate() )
            {
                // FELIX-593: 112.4.3 clarification, immediate is false for factory
                if ( isFactory() )
                {
                    throw validationFailure( "Factory cannot be immediate" );
                }
            }
            else
            {
                // 112.2.3 A delayed component specifies a service, is not specified to be a factory component
                // and does not have the immediate attribute of the component element set to true.
                // FELIX-593: 112.4.3 clarification, immediate may be true for factory
                if ( m_service == null && !isFactory() )
                {
                    throw validationFailure( "Delayed must provide a service or be a factory" );
                }
            }
        }

        // 112.4.6 The serviceFactory attribute (of a provided service) must not be true if
        // the component is a factory component or an immediate component
        if ( m_service != null )
        {
            if ( (m_service.getScope() != ServiceMetadata.Scope.singleton) && ( isFactory() || isImmediate() ) )
            {
                throw validationFailure( "factory or immediate must be scope singleton not " +  m_service.getScope());
            }
        }

        // activation fields require DS 1.4
        if ( m_activationFields != null && !m_dsVersion.isDS14() )
        {
            throw validationFailure( "Activation fields require version 1.4 or later");
        }

        // constructor injection requires DS 1.4
        if ( this.m_init != null )
        {
            if ( !m_dsVersion.isDS14() )
            {
                throw validationFailure( "Constructor injection requires version 1.4 or later");
            }
            int constructorParameters = 0;
            try
            {
                constructorParameters = Integer.valueOf(m_init);
                if ( constructorParameters < 0)
                {
                    throw validationFailure( "Init parameter must have non negative value: " + m_init);
                }
            }
            catch ( final NumberFormatException nfe)
            {
                throw validationFailure( "Init parameter is not a number: " + m_init);
            }
        }

        if (m_dsVersion == DSVersion.DS12Felix)
        {
            m_configurableServiceProperties = true;
        }
        if ( m_configurableServiceProperties && getServiceScope() != Scope.singleton )
        {
            throw validationFailure( "configurable service properties only allowed with singleton scope" );
        }
        if (m_dsVersion.isDS13())
        {
        	    m_deleteCallsModify = true; //spec behavior as of 1.3
        }
        if ( !m_dsVersion.isDS13() && m_configureWithInterfaces)
        {
        	    throw validationFailure("Configuration with interfaces or annotations only possible with version 1.3 or later");
        }
        if (m_dsVersion.isDS13() && m_obsoleteFactoryComponentFactory != null)
        {
          	throw validationFailure("Configuration of component factory instances through config admin factory pids supported only through the 1.2 namespace");
        }
        if (m_persistentFactoryComponent && !isFactory())
        {
         	throw validationFailure("Only a factory component can be a persistent factory component");
        }

        m_validated = true;
    }