This is an automated email from the ASF dual-hosted git repository.
cziegeler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/felix-dev.git
The following commit(s) were added to refs/heads/master by this push:
new 09c897e FELIX-6436 : Exclude default values (from metatype) in
Configuration
09c897e is described below
commit 09c897e34d7d4f00084a89cc6113bc233b98f70a
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Mon Jun 28 09:17:58 2021 +0200
FELIX-6436 : Exclude default values (from metatype) in Configuration
---
.../org/apache/felix/webconsole/internal/Util.java | 10 +
.../internal/configuration/ConfigAdminSupport.java | 284 ++++++++++++---------
.../internal/configuration/ConfigManager.java | 111 ++++----
.../configuration/MetatypePropertyDescriptor.java | 6 +
.../internal/configuration/PropertyDescriptor.java | 4 +
5 files changed, 250 insertions(+), 165 deletions(-)
diff --git
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
index 115f8ef..398f0aa 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
@@ -17,12 +17,15 @@
package org.apache.felix.webconsole.internal;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Locale;
+import javax.servlet.http.HttpServletResponse;
+
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
@@ -242,4 +245,11 @@ public class Util
return 1;
}
}
+
+ public static void sendJsonOk(final HttpServletResponse response) throws
IOException
+ {
+ response.setContentType( "application/json" ); //$NON-NLS-1$
+ response.setCharacterEncoding( "UTF-8" ); //$NON-NLS-1$
+ response.getWriter().print( "{ \"status\": true }" ); //$NON-NLS-1$
+ }
}
\ No newline at end of file
diff --git
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java
index fb6a2ec..b876f26 100644
---
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java
+++
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
@@ -35,7 +36,6 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
-import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.Vector;
import java.util.regex.Matcher;
@@ -162,175 +162,227 @@ class ConfigAdminSupport
return ConfigManager.PLACEHOLDER_PID;
}
- String applyConfiguration( final HttpServletRequest request, final String
pid, final boolean isUpdate )
- throws IOException
+ boolean shouldSet(final PropertyDescriptor ad, final String value, final
boolean isUpdate)
{
- if ( request.getParameter( ConfigManager.ACTION_DELETE ) != null )
//$NON-NLS-1$
+ if ( ad.hasMetatype() && !isUpdate )
{
- // only delete if the PID is not our place holder
- if ( !ConfigManager.PLACEHOLDER_PID.equals( pid ) )
+ if ( value.isEmpty() && ad.getDefaultValue() == null )
+ {
+ return false;
+ }
+ if ( ad.getDefaultValue() != null &&
value.equals(ad.getDefaultValue()[0]) )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ boolean shouldSet(final PropertyDescriptor ad, final String[] values,
final boolean isUpdate)
+ {
+ if ( ad.hasMetatype() && !isUpdate )
+ {
+ if ( ad.getDefaultValue() == null )
+ {
+ if ( values.length == 0 || (values.length == 1 &&
values[0].isEmpty() ) )
+ {
+ return false;
+ }
+ }
+ if ( ad.getDefaultValue() != null &&
Arrays.equals(ad.getDefaultValue(), values) )
{
- configManager.log( "applyConfiguration: Deleting configuration
" + pid );
- Configuration config = service.getConfiguration( pid, null );
- config.delete();
+ return false;
}
- return null; // return request.getHeader( "Referer" );
}
+ return true;
+ }
+ boolean applyConfiguration( final HttpServletRequest request, final String
pid, final String propertyList, final boolean isUpdate )
+ throws IOException
+ {
final String factoryPid = request.getParameter(
ConfigManager.FACTORY_PID );
- Configuration config = null;
+ final Configuration config = getConfiguration( pid, factoryPid );
- String propertyList = request.getParameter(
ConfigManager.PROPERTY_LIST ); //$NON-NLS-1$
- if ( propertyList == null )
+ Dictionary<String, Object> props = config.getProperties();
+ if ( props == null )
{
- // FIXME: this would be a bug !!
+ props = new Hashtable<>();
}
- else
+
+ 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.split(","))
{
- config = getConfiguration( pid, factoryPid );
+ final String paramName = "action".equals(propName) //$NON-NLS-1$
+ || ConfigManager.ACTION_DELETE.equals(propName)
+ || ConfigManager.ACTION_APPLY.equals(propName)
+ || ConfigManager.PROPERTY_LIST.equals(propName)
+ ? '$' + propName : propName;
+ propsToKeep.add(propName);
- Dictionary<String, Object> props = config.getProperties();
- if ( props == null )
- {
- props = new Hashtable<>();
- }
+ PropertyDescriptor ad = adMap.get( propName );
- final MetaTypeServiceSupport mtss = getMetaTypeSupport();
- final Map<String, MetatypePropertyDescriptor> adMap = ( mtss !=
null ) ? mtss.getAttributeDefinitionMap( config, null ) : new HashMap<>();
- final StringTokenizer propTokens = new StringTokenizer(
propertyList, "," ); //$NON-NLS-1$
- final List<String> propsToKeep = new ArrayList<>();
- while ( propTokens.hasMoreTokens() )
- {
- String propName = propTokens.nextToken();
- String paramName = "action".equals(propName) //$NON-NLS-1$
- || 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 );
- }
+ // try to derive from current value
+ if (ad == null) {
+ Object currentValue = props.get( propName );
+ ad = MetaTypeSupport.createAttributeDefinition( propName,
currentValue );
+ }
- int attributeType = MetaTypeSupport.getAttributeType( ad );
+ final int attributeType = MetaTypeSupport.getAttributeType( ad );
- if ( ad == null
- || ( ad.getCardinality() == 0 && ( attributeType ==
AttributeDefinition.STRING || attributeType == AttributeDefinition.PASSWORD ) )
)
+ 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 ) ) )
{
- String prop = request.getParameter( paramName );
- if ( prop != null
- && ( attributeType != AttributeDefinition.PASSWORD
|| !MetaTypeSupport.PASSWORD_PLACEHOLDER_VALUE.equals( prop ) ) )
+ if ( shouldSet(ad, value, isUpdate) )
{
- props.put( propName, prop );
+ props.put( propName, value );
+ }
+ else
+ {
+ props.remove( propName );
}
}
- else if ( ad.getCardinality() == 0 )
+ }
+ else if ( ad.getCardinality() == 0 )
+ {
+ // scalar of non-string
+ final String value = request.getParameter( paramName );
+ if ( value != null )
{
- // scalar of non-string
- String prop = request.getParameter( paramName );
- if ( prop != null )
+ if ( shouldSet(ad, value, isUpdate) )
{
try
{
- props.put( propName, MetaTypeSupport.toType(
attributeType, prop ) );
+ props.put( propName, MetaTypeSupport.toType(
attributeType, value ) );
}
- catch ( NumberFormatException nfe )
+ catch ( final NumberFormatException nfe )
{
// the value is put as a string, for example this
could be a placeholder etc
- props.put( propName, prop);
+ props.put( propName, value);
}
}
+ else
+ {
+ props.remove( propName );
+ }
}
- else
- {
- // array or vector of any type
- Vector<Object> vec = new Vector<>();
- boolean formatError = false;
+ }
+ else
+ {
+ // array or vector of any type
+ Vector<Object> vec = new Vector<>();
+ boolean formatError = false;
- String[] properties = request.getParameterValues(
paramName );
- if ( properties != null )
+ final String[] values = request.getParameterValues( paramName
);
+ if ( values != null )
+ {
+ if ( attributeType == AttributeDefinition.PASSWORD )
{
- if ( attributeType == AttributeDefinition.PASSWORD )
- {
- MetaTypeSupport.setPasswordProps( vec, properties,
props.get( propName ) );
- }
- else
+ MetaTypeSupport.setPasswordProps( vec, values,
props.get( propName ) );
+ }
+ else
+ {
+ for ( int i = 0; i < values.length; i++ )
{
- for ( int i = 0; i < properties.length; i++ )
+ try
{
- try
- {
- vec.add( MetaTypeSupport.toType(
attributeType, properties[i] ) );
- }
- catch ( NumberFormatException nfe )
- {
- // the value is put as a string, for
example this could be a placeholder etc
- vec.add( properties[i] );
- formatError = true;
- }
+ 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 )
+ // if a format error occurred revert to String!
+ if ( formatError )
+ {
+ Vector<Object> newVec = new Vector<Object>();
+ for(final Object v : vec)
{
- Vector<Object> newVec = new Vector<Object>();
- for(final Object v : vec)
- {
- newVec.add(v.toString());
- }
- vec = newVec;
+ 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 );
+ }
- // 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 )
+ // 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();
+ }
+
+ final boolean shouldSet = shouldSet(ad, valueArray, isUpdate);
+
+ if ( ad.getCardinality() < 0 )
+ {
+ // keep the vector, but only add if not empty
+ if ( !shouldSet || vec.isEmpty() )
{
- vec.setSize( maxSize );
+ props.remove( propName );
}
-
- if ( ad.getCardinality() < 0 )
+ else
{
- // keep the vector, but only add if not empty
- if ( vec.isEmpty() )
- {
- props.remove( propName );
- }
- else
+ if ( shouldSet )
{
props.put( propName, vec );
- }
+ }
}
- else
+ }
+ else
+ {
+ if ( shouldSet )
{
// convert to an array
props.put( propName, MetaTypeSupport.toArray(
formatError ? AttributeDefinition.STRING : attributeType, vec ) );
}
+ else
+ {
+ props.remove( propName );
+ }
}
}
+ }
- 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(); )
+ 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 )
{
- final String key = e.nextElement();
- if ( propsToKeep.contains(key) )
- {
- updateProps.put(key, props.get(key));
- }
+ updateProps.put(key, props.get(key));
}
- props = updateProps;
}
+ props = updateProps;
+ }
+ if ( props.isEmpty() )
+ {
+ config.delete();
+ return false;
+ }
+ else
+ {
final String location =
request.getParameter(ConfigManager.LOCATION);
if ( location == null || location.trim().length() == 0 ||
ConfigManager.UNBOUND_LOCATION.equals(location) )
{
@@ -347,7 +399,8 @@ class ConfigAdminSupport
config.setBundleLocation( null );
}
}
- } else
+ }
+ else
{
if ( config.getBundleLocation() == null ||
!config.getBundleLocation().equals(location) )
{
@@ -355,10 +408,9 @@ class ConfigAdminSupport
}
}
config.update( props );
+
+ return true;
}
-
- // redirect to the new configuration (if existing)
- return (config != null) ? config.getPid() : ""; //$NON-NLS-1$
}
diff --git
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigManager.java
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigManager.java
index 8a8284a..37145c0 100644
---
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigManager.java
+++
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigManager.java
@@ -28,11 +28,11 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.utils.json.JSONWriter;
-import org.apache.felix.webconsole.DefaultVariableResolver;
import org.apache.felix.webconsole.SimpleWebConsolePlugin;
import org.apache.felix.webconsole.WebConsoleConstants;
import org.apache.felix.webconsole.WebConsoleUtil;
import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
+import org.apache.felix.webconsole.internal.Util;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.Configuration;
@@ -118,6 +118,14 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
@Override
protected void doPost( HttpServletRequest request, HttpServletResponse
response ) throws IOException
{
+ // service unavailable if config admin is not available
+ final ConfigAdminSupport cas = getConfigurationAdminSupport();
+ if ( cas == null )
+ {
+ response.sendError(503);
+ return;
+ }
+
// needed multiple times below
String pid = request.getParameter( ConfigManager.PID );
if ( pid == null )
@@ -125,62 +133,71 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
String info = request.getPathInfo();
pid = WebConsoleUtil.urlDecode( info.substring( info.lastIndexOf(
'/' ) + 1 ) );
}
-
- // the filter to select part of the configurations
- String pidFilter = request.getParameter( PID_FILTER );
-
- final ConfigAdminSupport cas = getConfigurationAdminSupport();
-
- // ignore this request if the PID and/or configuration admin is missing
- if ( pid == null || pid.length() == 0 || cas == null )
+ // ignore this request if the PID is invalid / not provided
+ if ( pid == null || pid.length() == 0 || !isAllowedPid(pid))
{
- // should log this here !!
+ response.sendError(400);
return;
}
- // ignore this request, if the PID is invalid
- if ( ! isAllowedPid(pid) )
+ // the filter to select part of the configurations
+ final String pidFilter = request.getParameter( PID_FILTER );
+ if ( pidFilter != null && ! isAllowedPid(pidFilter) )
{
- response.sendError(500);
+ response.sendError(400);
return;
}
- if ( pidFilter != null && ! isAllowedPid(pidFilter) )
+
+ if ( request.getParameter( ACTION_APPLY ) != null )
{
- response.sendError(500);
+ if ( request.getParameter( ConfigManager.ACTION_DELETE ) != null )
//$NON-NLS-1$
+ {
+ // only delete if the PID is not our place holder
+ if ( !ConfigManager.PLACEHOLDER_PID.equals( pid ) )
+ {
+ this.log( "applyConfiguration: Deleting configuration " +
pid );
+ cas.getConfiguration( pid, null ).delete();
+ }
+
+ Util.sendJsonOk(response);
+ }
+ else
+ {
+ final String propertyList = request.getParameter(
ConfigManager.PROPERTY_LIST ); //$NON-NLS-1$
+ if ( propertyList == null )
+ {
+ response.sendError(400);
+ return;
+ }
+
+ if (cas.applyConfiguration( request, pid, propertyList,
ACTION_UPDATE.equals(request.getParameter(ACTION_APPLY)) ) )
+ {
+ String redirect = pid;
+ if (pidFilter != null) {
+ redirect += '?' + PID_FILTER + '=' + pidFilter;
+ }
+
+ WebConsoleUtil.sendRedirect(request, response, redirect);
+ }
+ else
+ {
+ Util.sendJsonOk(response);
+ }
+ }
+
return;
}
// the configuration to operate on (to be created or "missing")
- Configuration config = null;
+ final Configuration config;
// should actually apply the configuration before redirecting
if ( request.getParameter( ACTION_CREATE ) != null )
{
- config = cas.getPlaceholderConfiguration( pid ); //
ca.createFactoryConfiguration( pid, null );
+ config = cas.getPlaceholderConfiguration( pid );
pid = config.getPid();
}
- else if ( request.getParameter( ACTION_APPLY ) != null )
- {
- String redirect = cas.applyConfiguration( request, pid,
ACTION_UPDATE.equals(request.getParameter(ACTION_APPLY)) );
- if ( redirect != null )
- {
- if (pidFilter != null) {
- redirect += '?' + PID_FILTER + '=' + pidFilter;
- }
-
- WebConsoleUtil.sendRedirect(request, response, redirect);
- }
- else
- {
- response.setContentType( "application/json" ); //$NON-NLS-1$
- response.setCharacterEncoding( "UTF-8" ); //$NON-NLS-1$
- response.getWriter().print( "{ \"status\": true }" );
//$NON-NLS-1$
- }
-
- return;
- }
-
- if ( config == null )
+ else
{
config = cas.getConfiguration( pid );
}
@@ -193,9 +210,7 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
config.setBundleLocation( UNBOUND_LOCATION );
}
- response.setContentType( "application/json" ); //$NON-NLS-1$
- response.setCharacterEncoding( "UTF-8" ); //$NON-NLS-1$
- response.getWriter().print( "{ \"status\": true }" ); //$NON-NLS-1$
+ Util.sendJsonOk(response);
return;
}
@@ -257,11 +272,11 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
// check both PID and PID filter
if ( pid != null && !isAllowedPid(pid) )
{
- response.sendError(500);
+ response.sendError(400);
}
if ( pidFilter != null && !isAllowedPid(pidFilter) )
{
- response.sendError(500);
+ response.sendError(400);
}
@@ -381,11 +396,11 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
// check both PID and PID filter
if ( pid != null && !isAllowedPid(pid) )
{
- response.sendError(500);
+ response.sendError(400);
}
if ( pidFilter != null && !isAllowedPid(pidFilter) )
{
- response.sendError(500);
+ response.sendError(400);
}
final Locale loc = getLocale( request );
@@ -427,7 +442,7 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
// prepare variables
final String referer = request.getParameter( REFERER );
final boolean factoryCreate = "true".equals(
request.getParameter(FACTORY_CREATE) ); //$NON-NLS-1$
- DefaultVariableResolver vars = ( ( DefaultVariableResolver )
WebConsoleUtil.getVariableResolver( request ) );
+ final Map<String, Object> vars = ( ( Map<String, Object> )
WebConsoleUtil.getVariableResolver( request ) );
vars.put( "__data__", json.toString() ); //$NON-NLS-1$
vars.put( "selectedPid", pid != null ? pid : "" ); //$NON-NLS-1$
//$NON-NLS-2$
vars.put( "configurationReferer", referer != null ? referer : "" );
//$NON-NLS-1$ //$NON-NLS-2$
@@ -451,7 +466,5 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
}
return null;
}
-
-
}
diff --git
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/MetatypePropertyDescriptor.java
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/MetatypePropertyDescriptor.java
index 96adeb0..64c53fa 100644
---
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/MetatypePropertyDescriptor.java
+++
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/MetatypePropertyDescriptor.java
@@ -86,4 +86,10 @@ public class MetatypePropertyDescriptor extends
PropertyDescriptor
{
return optional;
}
+
+
+ public boolean hasMetatype()
+ {
+ return true;
+ }
}
diff --git
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/PropertyDescriptor.java
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/PropertyDescriptor.java
index 9ea82e4..e06f385 100644
---
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/PropertyDescriptor.java
+++
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/PropertyDescriptor.java
@@ -100,4 +100,8 @@ class PropertyDescriptor
return false;
}
+ public boolean hasMetatype()
+ {
+ return false;
+ }
}
\ No newline at end of file