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 b298317 FELIX-6367 : Provide SPI for configuration management (WiP)
b298317 is described below
commit b298317cae647210b87c1a629501100e71607bdf
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Sun Aug 29 11:35:29 2021 +0200
FELIX-6367 : Provide SPI for configuration management (WiP)
---
.../org/apache/felix/webconsole/internal/Util.java | 11 ++
.../internal/configuration/ConfigAdminSupport.java | 24 ++---
.../internal/configuration/ConfigJsonSupport.java | 4 +-
.../internal/configuration/ConfigManager.java | 115 ++++++++++-----------
.../internal/configuration/ConfigurationUtil.java | 13 ++-
.../felix/webconsole/spi/ConfigurationHandler.java | 20 ++--
.../felix/webconsole/spi/ValidationException.java | 8 +-
7 files changed, 109 insertions(+), 86 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 398f0aa..2b2818c 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
@@ -24,6 +24,7 @@ import java.util.Comparator;
import java.util.Enumeration;
import java.util.Locale;
+import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.osgi.framework.Bundle;
@@ -252,4 +253,14 @@ public class Util
response.setCharacterEncoding( "UTF-8" ); //$NON-NLS-1$
response.getWriter().print( "{ \"status\": true }" ); //$NON-NLS-1$
}
+
+ public static final Locale getLocale( final HttpServletRequest request ) {
+ try {
+ return request.getLocale();
+ } catch ( Throwable t ) {
+ // expected in standard OSGi Servlet 2.1 environments
+ // fallback to using the default locale
+ return Locale.getDefault();
+ }
+ }
}
\ 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 33dab7a..c0f769d 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
@@ -37,6 +37,7 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.felix.webconsole.internal.misc.ServletSupport;
import org.apache.felix.webconsole.spi.ConfigurationHandler;
+import org.apache.felix.webconsole.spi.ValidationException;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.Configuration;
@@ -133,8 +134,8 @@ class ConfigAdminSupport {
* @param isUpdate {@code true} if this is a rest call, false if it is
done via the webconsole UI
* @throws IOException
*/
- void applyConfiguration( final HttpServletRequest request, final String
pid, final String propertyList, final boolean isUpdate )
- throws IOException
+ void 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 );
@@ -147,7 +148,7 @@ class ConfigAdminSupport {
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(","))
+ for(final String propName : propertyList)
{
final String paramName = "action".equals(propName) //$NON-NLS-1$
|| ConfigManager.ACTION_DELETE.equals(propName)
@@ -342,21 +343,16 @@ class ConfigAdminSupport {
config.update( props );
}
- public void deleteConfiguration(final String pid) throws IOException {
+ public void deleteConfiguration(final String pid) throws
ValidationException, IOException {
// only delete if the PID is not our place holder
if ( !ConfigurationUtil.getPlaceholderPid().equals( pid ) ) {
final Configuration config =
ConfigurationUtil.findConfiguration(this.service, pid);
- this.deleteConfiguration(config);
- }
- }
-
- void deleteConfiguration(final Configuration config) throws IOException {
- // only delete if the PID is not our place holder
- if ( config != null && !ConfigurationUtil.getPlaceholderPid().equals(
config.getPid() ) ) {
- for(final ConfigurationHandler h : this.configurationHandlers) {
- h.deleteConfiguration(config.getFactoryPid(), config.getPid());
+ if ( config != null ) {
+ for(final ConfigurationHandler h : this.configurationHandlers)
{
+ h.deleteConfiguration(config.getFactoryPid(),
config.getPid());
+ }
+ config.delete();
}
- config.delete();
}
}
diff --git
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigJsonSupport.java
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigJsonSupport.java
index a3a50d5..dfb7faa 100644
---
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigJsonSupport.java
+++
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigJsonSupport.java
@@ -241,7 +241,7 @@ class ConfigJsonSupport {
// ignore configuration object if an entry already exists in
the map
// or if it is invalid
final String pid = cfgs[i].getPid();
- if (optionsPlain.containsKey(pid) ||
!ConfigManager.isAllowedPid(pid) )
+ if (optionsPlain.containsKey(pid) ||
!ConfigurationUtil.isAllowedPid(pid) )
{
continue;
}
@@ -445,7 +445,7 @@ class ConfigJsonSupport {
for ( int i = 0; refs != null && i < refs.length; i++ ) {
Object pidObject = refs[i].getProperty( Constants.SERVICE_PID );
// only include valid PIDs
- if ( pidObject instanceof String &&
ConfigManager.isAllowedPid((String)pidObject) ) {
+ if ( pidObject instanceof String &&
ConfigurationUtil.isAllowedPid((String)pidObject) ) {
String pid = ( String ) pidObject;
String name = pid;
boolean haveOcd = !ocdRequired;
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 2e5baf0..221871f 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
@@ -19,7 +19,8 @@ package org.apache.felix.webconsole.internal.configuration;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.util.Collections;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -34,10 +35,13 @@ import org.apache.felix.webconsole.WebConsoleUtil;
import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
import org.apache.felix.webconsole.internal.Util;
import org.apache.felix.webconsole.internal.misc.ServletSupport;
+import org.apache.felix.webconsole.spi.ConfigurationHandler;
+import org.apache.felix.webconsole.spi.ValidationException;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.Configuration;
+import org.osgi.util.tracker.ServiceTracker;
/**
@@ -75,86 +79,73 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
// templates
private final String TEMPLATE;
+ // service tracker for SPI
+ private ServiceTracker<ConfigurationHandler, ConfigurationHandler>
spiTracker;
+
/** Default constructor */
- public ConfigManager()
- {
+ public ConfigManager() {
super(LABEL, TITLE, CATEGORY_OSGI, CSS);
// load templates
TEMPLATE = readTemplateFile( "/templates/config.html" ); //$NON-NLS-1$
}
- static final boolean isAllowedPid(final String pid)
- {
- for(int i = 0; i < pid.length(); i++)
- {
- final char c = pid.charAt(i);
- if ( c == '&' || c == '<' || c == '>' || c == '"' || c == '\'' )
- {
- return false;
- }
- }
- return true;
+ @Override
+ public void activate(final BundleContext bundleContext) {
+ super.activate(bundleContext);
+ this.spiTracker = new ServiceTracker<>(bundleContext,
ConfigurationHandler.class.getName(), null);
+ this.spiTracker.open();
}
- private static final Locale getLocale( HttpServletRequest request )
- {
- try
- {
- return request.getLocale();
- }
- catch ( Throwable t )
- {
- // expected in standard OSGi Servlet 2.1 environments
- // fallback to using the default locale
- return Locale.getDefault();
+ @Override
+ public void deactivate() {
+ if ( this.spiTracker != null ) {
+ this.spiTracker.close();
+ this.spiTracker = null;
}
+ super.deactivate();
}
-
/**
* @see
javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
javax.servlet.http.HttpServletResponse)
*/
@Override
- protected void doPost( HttpServletRequest request, HttpServletResponse
response ) throws IOException
- {
+ protected void doPost( HttpServletRequest request, HttpServletResponse
response ) throws IOException {
// service unavailable if config admin is not available
final ConfigAdminSupport cas = getConfigurationAdminSupport();
- if ( cas == null )
- {
+ if ( cas == null ) {
response.sendError(503);
return;
}
// needed multiple times below
String pid = request.getParameter( ConfigManager.PID );
- if ( pid == null )
- {
+ if ( pid == null ) {
String info = request.getPathInfo();
pid = WebConsoleUtil.urlDecode( info.substring( info.lastIndexOf(
'/' ) + 1 ) );
}
// ignore this request if the PID is invalid / not provided
- if ( pid == null || pid.length() == 0 || !isAllowedPid(pid))
- {
+ if ( pid == null || pid.length() == 0 ||
!ConfigurationUtil.isAllowedPid(pid)) {
response.sendError(400);
return;
}
// the filter to select part of the configurations
final String pidFilter = request.getParameter( PID_FILTER );
- if ( pidFilter != null && ! isAllowedPid(pidFilter) )
- {
+ if ( pidFilter != null && !ConfigurationUtil.isAllowedPid(pidFilter) )
{
response.sendError(400);
return;
}
- if ( request.getParameter( ACTION_APPLY ) != null )
- {
- if ( request.getParameter( ConfigManager.ACTION_DELETE ) != null )
//$NON-NLS-1$
- {
- cas.deleteConfiguration( pid );
- Util.sendJsonOk(response);
+ if ( request.getParameter( ACTION_APPLY ) != null ) {
+ if ( request.getParameter( ConfigManager.ACTION_DELETE ) != null )
{ //$NON-NLS-1$
+ try {
+ cas.deleteConfiguration( pid );
+ Util.sendJsonOk(response);
+ } catch ( final ValidationException ve) {
+ response.sendError(400, ve.getMessage());
+ }
}
else
{
@@ -164,13 +155,17 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
return;
}
- cas.applyConfiguration( request, pid, propertyList,
ACTION_UPDATE.equals(request.getParameter(ACTION_APPLY)));
- String redirect = pid;
- if (pidFilter != null) {
- redirect =
redirect.concat("?").concat(PID_FILTER).concat("=").concat(pidFilter);
+ try {
+ cas.applyConfiguration( request, pid,
propertyList.split(","),
ACTION_UPDATE.equals(request.getParameter(ACTION_APPLY)));
+ String redirect = pid;
+ if (pidFilter != null) {
+ redirect =
redirect.concat("?").concat(PID_FILTER).concat("=").concat(pidFilter);
+ }
+
+ WebConsoleUtil.sendRedirect(request, response, redirect);
+ } catch ( final ValidationException ve) {
+ response.sendError(400, ve.getMessage());
}
-
- WebConsoleUtil.sendRedirect(request, response, redirect);
}
return;
@@ -201,7 +196,7 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
// send the result
response.setContentType( "application/json" ); //$NON-NLS-1$
response.setCharacterEncoding( "UTF-8" ); //$NON-NLS-1$
- final Locale loc = getLocale( request );
+ final Locale loc = Util.getLocale( request );
final String locale = ( loc != null ) ? loc.toString() : null;
cas.getJsonSupport().printConfigurationJson( response.getWriter(),
pid, config, pidFilter, locale );
}
@@ -212,8 +207,7 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
*/
@Override
protected void doGet( HttpServletRequest request, HttpServletResponse
response )
- throws ServletException, IOException
- {
+ throws ServletException, IOException {
// check for "post" requests from previous versions
if ( "true".equals(request.getParameter("post")) ) { //$NON-NLS-1$
//$NON-NLS-2$
this.doPost(request, response);
@@ -254,17 +248,17 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
}
// check both PID and PID filter
- if ( pid != null && !isAllowedPid(pid) )
+ if ( pid != null && !ConfigurationUtil.isAllowedPid(pid) )
{
response.sendError(400);
}
- if ( pidFilter != null && !isAllowedPid(pidFilter) )
+ if ( pidFilter != null &&
!ConfigurationUtil.isAllowedPid(pidFilter) )
{
response.sendError(400);
}
- final Locale loc = getLocale( request );
+ final Locale loc = Util.getLocale( request );
final String locale = ( loc != null ) ? loc.toString() : null;
final PrintWriter pw = response.getWriter();
@@ -378,16 +372,16 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
}
// check both PID and PID filter
- if ( pid != null && !isAllowedPid(pid) )
+ if ( pid != null && !ConfigurationUtil.isAllowedPid(pid) )
{
response.sendError(400);
}
- if ( pidFilter != null && !isAllowedPid(pidFilter) )
+ if ( pidFilter != null && !ConfigurationUtil.isAllowedPid(pidFilter) )
{
response.sendError(400);
}
- final Locale loc = getLocale( request );
+ final Locale loc = Util.getLocale( request );
final String locale = ( loc != null ) ? loc.toString() : null;
@@ -443,11 +437,16 @@ public class ConfigManager extends SimpleWebConsolePlugin
implements OsgiManager
private ConfigAdminSupport getConfigurationAdminSupport() {
Object configurationAdmin = getService( CONFIGURATION_ADMIN_NAME );
if ( configurationAdmin != null ) {
- return new ConfigAdminSupport( this, configurationAdmin,
Collections.emptyList() );
+ final List<ConfigurationHandler> handlers = new ArrayList<>();
+ for(final Object o : this.spiTracker.getServices()) {
+ handlers.add((ConfigurationHandler)o);
+ }
+ return new ConfigAdminSupport( this, configurationAdmin, handlers
);
}
return null;
}
+ @Override
public BundleContext getBundleContext() {
return super.getBundleContext();
}
diff --git
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigurationUtil.java
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigurationUtil.java
index 5ebff02..71ae435 100644
---
a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigurationUtil.java
+++
b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigurationUtil.java
@@ -24,6 +24,7 @@ import java.util.Dictionary;
import java.util.List;
import org.apache.felix.webconsole.spi.ConfigurationHandler;
+import org.apache.felix.webconsole.spi.ValidationException;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.Configuration;
@@ -58,7 +59,7 @@ public class ConfigurationUtil {
public static Configuration getOrCreateConfiguration( final
ConfigurationAdmin service,
final List<ConfigurationHandler> handlers,
final String pid,
- final String factoryPid ) throws IOException {
+ final String factoryPid ) throws ValidationException, IOException {
Configuration cfg = null;
if ( !PLACEHOLDER_PID.equals(pid) ) {
cfg = findConfiguration(service, pid);
@@ -79,7 +80,17 @@ public class ConfigurationUtil {
return cfg;
}
+ public static final boolean isAllowedPid(final String pid) {
+ for(int i = 0; i < pid.length(); i++) {
+ final char c = pid.charAt(i);
+ if ( c == '&' || c == '<' || c == '>' || c == '"' || c == '\'' ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
public static Configuration getPlaceholderConfiguration( final String
factoryPid ) {
return new PlaceholderConfiguration( factoryPid );
}
diff --git
a/webconsole/src/main/java/org/apache/felix/webconsole/spi/ConfigurationHandler.java
b/webconsole/src/main/java/org/apache/felix/webconsole/spi/ConfigurationHandler.java
index f35f5e6..da92ad8 100644
---
a/webconsole/src/main/java/org/apache/felix/webconsole/spi/ConfigurationHandler.java
+++
b/webconsole/src/main/java/org/apache/felix/webconsole/spi/ConfigurationHandler.java
@@ -33,32 +33,36 @@ public interface ConfigurationHandler {
/**
* A new configuration with that pid should be created
* @param pid The pid
- * @throws IOException For an error or {@link ValidationException} if
creation is not allowed
+ * @throws IOException For an error
+ * @throws ValidationException if creation is not allowed
*/
- void createConfiguration(String pid) throws IOException;
+ void createConfiguration(String pid) throws ValidationException,
IOException;
/**
* A new factory configuration with that pid should be created
* @param factoryPid The factory pid
* @param name Optional name, might be {@code null} if unknown
- * @throws IOException For an error or {@link ValidationException} if
creation is not allowed
+ * @throws IOException For an error
+ * @throws ValidationException if creation is not allowed
*/
- void createFactoryConfiguration(String factoryPid, String name) throws
IOException;
+ void createFactoryConfiguration(String factoryPid, String name) throws
ValidationException, IOException;
/**
* A configuration should be deleted
* @param factoryPid Optional factory pid
* @param pid The pid
- * @throws IOException For an error or {@link ValidationException} if
deletion is not allowed
+ * @throws IOException For an error
+ * @throws ValidationException if deletion is not allowed
*/
- void deleteConfiguration(String factoryPid, String pid) throws IOException;
+ void deleteConfiguration(String factoryPid, String pid) throws
ValidationException, IOException;
/**
* A configuration should be updated
* @param factoryPid Optional factory pid
* @param pid The pid
* @param props Mutable dictionary
- * @throws IOException For an error or {@link ValidationException} if
deletion is not allowed
+ * @throws IOException For an error
+ * @throws ValidationException if updating is not allowed
*/
- void updateConfiguration(String factoryPid, String pid, Dictionary<String,
Object> props) throws IOException;
+ void updateConfiguration(String factoryPid, String pid, Dictionary<String,
Object> props) throws ValidationException, IOException;
}
\ No newline at end of file
diff --git
a/webconsole/src/main/java/org/apache/felix/webconsole/spi/ValidationException.java
b/webconsole/src/main/java/org/apache/felix/webconsole/spi/ValidationException.java
index a661b82..47cf2fe 100644
---
a/webconsole/src/main/java/org/apache/felix/webconsole/spi/ValidationException.java
+++
b/webconsole/src/main/java/org/apache/felix/webconsole/spi/ValidationException.java
@@ -18,9 +18,11 @@
*/
package org.apache.felix.webconsole.spi;
-import java.io.IOException;
-
-public class ValidationException extends IOException {
+/**
+ * A {@link ConfigurationHandler} should throws a validation exception
+ * if an operation is not allowed or not valid.
+ */
+public class ValidationException extends Exception {
/**
* Create validation exception