String applyConfiguration()

in webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java [118:307]


    String applyConfiguration( final HttpServletRequest request, final String pid, final String[] propertyList, final boolean isUpdate )
            throws ValidationException, IOException
    {
        final String factoryPid = request.getParameter( ConfigManager.FACTORY_PID );
        final Configuration config = ConfigurationUtil.getOrCreateConfiguration( this.service, this.configurationHandlers, pid, factoryPid );

        Dictionary<String, Object> props = config.getProperties();
        if ( props == null ) {
            props = new Hashtable<>();
        }
        // filter properties and keep filtered values
        final Map<String, Object> allowedValues = getAllowedValues(config, props);

        final MetaTypeServiceSupport mtss = getMetaTypeSupport();
        final Map<String, MetatypePropertyDescriptor> adMap = ( mtss != null ) ? mtss.getAttributeDefinitionMap( config, null ) : new HashMap<>();
        final List<String> propsToKeep = new ArrayList<>();
        for(final String propName : propertyList)
        {
            final String paramName = "action".equals(propName)
                    || ConfigManager.ACTION_DELETE.equals(propName)
                    || ConfigManager.ACTION_APPLY.equals(propName)
                    || ConfigManager.PROPERTY_LIST.equals(propName)
                    ? '$' + propName : propName;
            propsToKeep.add(propName);

            PropertyDescriptor ad = adMap.get( propName );

            // try to derive from current value
            if (ad == null) {
                Object currentValue = props.get( propName );
                ad = MetaTypeSupport.createAttributeDefinition( propName, currentValue );
            }

            final int attributeType = MetaTypeSupport.getAttributeType( ad );

            if ( ad.getCardinality() == 0 && ( attributeType == AttributeDefinition.STRING || attributeType == AttributeDefinition.PASSWORD ) )
            {
                final String value = request.getParameter( paramName );
                if ( value != null
                    && ( attributeType != AttributeDefinition.PASSWORD || !MetaTypeSupport.PASSWORD_PLACEHOLDER_VALUE.equals( value ) ) )
                {
                    props.put( propName, value );
                }
            }
            else if ( ad.getCardinality() == 0 )
            {
                // scalar of non-string
                final String value = request.getParameter( paramName );
                if ( value != null )
                {
                    try
                    {
                        props.put( propName, MetaTypeSupport.toType( attributeType, value ) );
                    }
                    catch ( final NumberFormatException nfe )
                    {
                        // the value is put as a string, for example this could be a placeholder etc
                        props.put( propName, value);
                    }
                }
            }
            else
            {
                // array or vector of any type
                Vector<Object> vec = new Vector<>();
                boolean formatError = false;

                final String[] values = request.getParameterValues( paramName );
                if ( values != null )
                {
                    if ( attributeType == AttributeDefinition.PASSWORD )
                    {
                        MetaTypeSupport.setPasswordProps( vec, values, props.get( propName ) );
                    }
                    else
                    {
                        for ( int i = 0; i < values.length; i++ )
                        {
                            try
                            {
                                vec.add( MetaTypeSupport.toType( attributeType, values[i] ) );
                            }
                            catch ( NumberFormatException nfe )
                            {
                                // the value is put as a string, for example this could be a placeholder etc
                                vec.add( values[i] );
                                formatError = true;
                            }
                        }
                    }
                }

                // if a format error occurred revert to String!
                if ( formatError )
                {
                    Vector<Object> newVec = new Vector<Object>();
                    for(final Object v : vec)
                    {
                        newVec.add(v.toString());
                    }
                    vec = newVec;
                }

                // but ensure size (check for positive value since
                // abs(Integer.MIN_VALUE) is still INTEGER.MIN_VALUE)
                int maxSize = Math.abs( ad.getCardinality() );
                if ( vec.size() > maxSize && maxSize > 0 )
                {
                    vec.setSize( maxSize );
                }

                // create array to compare
                final String[] valueArray = new String[vec.size()];
                for(int i=0; i<vec.size();i++)
                {
                    valueArray[i] = vec.get(i).toString();
                }

                if ( ad.getCardinality() < 0 )
                {
                    // keep the vector, but only add if not empty
                    if ( vec.isEmpty() )
                    {
                        props.remove( propName );
                    }
                    else
                    {
                        props.put( propName, vec );
                    }
                }
                else
                {
                    // convert to an array
                    props.put( propName, MetaTypeSupport.toArray( formatError ? AttributeDefinition.STRING : attributeType, vec ) );
                }
            }
        }

        if ( !isUpdate )
        {
            // remove the properties that are not specified in the request
            final Dictionary<String, Object> updateProps = new Hashtable<>(props.size());
            for ( Enumeration<String> e = props.keys(); e.hasMoreElements(); )
            {
                final String key = e.nextElement();
                if ( propsToKeep.contains(key) && props.get(key) != null )
                {
                    updateProps.put(key, props.get(key));
                }
            }
            props = updateProps;
        }

        // call update handlers
        for(final ConfigurationHandler h : this.configurationHandlers) {
            h.updateConfiguration(factoryPid, pid, props);
        }

        // reapply allowed values
        for(final Map.Entry<String, Object> allowed : allowedValues.entrySet()) {
            props.put(allowed.getKey(), allowed.getValue());
        }

        final String location = request.getParameter(ConfigManager.LOCATION);
        if ( location == null || location.trim().length() == 0 || ConfigManager.UNBOUND_LOCATION.equals(location) )
        {
            if ( config.getBundleLocation() != null )
            {
                config.setBundleLocation(null);
                // workaround for Felix Config Admin 1.2.8 not clearing dynamic
                // bundle location when clearing static bundle location. In
                // this case we first set the static bundle location to the
                // dynamic bundle location and then try to set both to null
                if ( config.getBundleLocation() != null )
                {
                    config.setBundleLocation( "??invalid:bundle/location" );
                    config.setBundleLocation( null );
                }
            }
        }
        else
        {
            if ( config.getBundleLocation() == null || !config.getBundleLocation().equals(location) )
            {
                config.setBundleLocation(location);
            }
        }
        config.update( props );
        return config.getPid();
    }