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/sling-org-apache-sling-installer-factory-configuration.git


The following commit(s) were added to refs/heads/master by this push:
     new 6f14c8d  SLING-7786 : Use R7 configuration admin supporting named 
factory configurations
6f14c8d is described below

commit 6f14c8d17610d4d4c995f4927ebe01db053f0513
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Mon Aug 13 18:30:11 2018 +0200

    SLING-7786 : Use R7 configuration admin supporting named factory 
configurations
---
 pom.xml                                            |   2 +-
 .../configuration/impl/ConfigRemoveTask.java       |   5 -
 .../configuration/impl/ConfigTaskCreator.java      | 155 +++------------------
 .../configuration/impl/ConfigUpdateHandler.java    | 121 ++++++++++++++++
 .../configuration/impl/ServicesListener.java       |  63 +++------
 5 files changed, 167 insertions(+), 179 deletions(-)

diff --git a/pom.xml b/pom.xml
index dab6fe8..aaf3fa0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,7 +84,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.installer.core</artifactId>
-            <version>3.8.0</version>
+            <version>3.8.13-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigRemoveTask.java
 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigRemoveTask.java
index ba7296a..0e323c4 100644
--- 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigRemoveTask.java
+++ 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigRemoveTask.java
@@ -47,11 +47,6 @@ public class ConfigRemoveTask extends AbstractConfigTask {
         synchronized ( Coordinator.SHARED ) {
             try {
                 Configuration cfg = 
ConfigUtil.getConfiguration(this.getConfigurationAdmin(), this.factoryPid, 
this.configPid);
-                if ( cfg == null && this.factoryPid != null ) {
-                    // try support for legacy factory config handling
-                    cfg = 
ConfigUtil.getLegacyFactoryConfig(this.getConfigurationAdmin(), 
this.factoryPid, this.getResourceGroup().getAlias(), this.configPid);
-
-                }
                 if (cfg == null) {
                     this.getLogger().debug("Cannot delete config , pid={} not 
found, ignored ({})", getRealPID(), getResource());
                 } else {
diff --git 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigTaskCreator.java
 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigTaskCreator.java
index 36e8067..92d824e 100644
--- 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigTaskCreator.java
+++ 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigTaskCreator.java
@@ -21,19 +21,12 @@ package 
org.apache.sling.installer.factories.configuration.impl;
 import java.util.Arrays;
 import java.util.Dictionary;
 import java.util.HashMap;
+import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
 
 import org.apache.sling.installer.api.InstallableResource;
-import org.apache.sling.installer.api.OsgiInstaller;
 import org.apache.sling.installer.api.ResourceChangeListener;
-import org.apache.sling.installer.api.event.InstallationEvent;
-import org.apache.sling.installer.api.event.InstallationListener;
-import org.apache.sling.installer.api.info.InfoProvider;
-import org.apache.sling.installer.api.info.Resource;
-import org.apache.sling.installer.api.info.ResourceGroup;
 import org.apache.sling.installer.api.tasks.ChangeStateTask;
 import org.apache.sling.installer.api.tasks.InstallTask;
 import org.apache.sling.installer.api.tasks.InstallTaskFactory;
@@ -44,7 +37,9 @@ import org.apache.sling.installer.api.tasks.TaskResource;
 import org.apache.sling.installer.api.tasks.TaskResourceGroup;
 import org.apache.sling.installer.api.tasks.TransformationResult;
 import 
org.apache.sling.installer.factories.configuration.ConfigurationConstants;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.Configuration;
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.cm.ConfigurationEvent;
@@ -56,7 +51,7 @@ import org.slf4j.LoggerFactory;
  * Task creator for configurations.
  */
 public class ConfigTaskCreator
-    implements InstallTaskFactory, ConfigurationListener, ResourceTransformer, 
InstallationListener {
+    implements InstallTaskFactory, ConfigurationListener, ResourceTransformer {
 
     /** Logger. */
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
@@ -67,20 +62,25 @@ public class ConfigTaskCreator
     /** Resource change listener. */
     private final ResourceChangeListener changeListener;
 
-    /** Resource change listener. */
-    private final OsgiInstaller installer;
-
-    /** Resource change listener. */
-    private final InfoProvider infoProvider;
-
     public ConfigTaskCreator(final ResourceChangeListener listener,
-            final ConfigurationAdmin configAdmin,
-            final OsgiInstaller installer,
-            final InfoProvider infoProvider) {
+            final ConfigurationAdmin configAdmin) {
         this.changeListener = listener;
         this.configAdmin = configAdmin;
-        this.installer = installer;
-        this.infoProvider = infoProvider;
+    }
+
+    public ServiceRegistration<?> register(final BundleContext bundleContext) {
+        final Hashtable<String, String> props = new Hashtable<>();
+        props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Configuration 
Install Task Factory");
+        props.put(Constants.SERVICE_VENDOR, ServicesListener.VENDOR);
+        props.put(InstallTaskFactory.NAME, "org.osgi.service.cm");
+        props.put(ResourceTransformer.NAME, "org.osgi.service.cm");
+
+        final String [] serviceInterfaces = {
+                InstallTaskFactory.class.getName(),
+                ConfigurationListener.class.getName(),
+                ResourceTransformer.class.getName()
+        };
+        return bundleContext.registerService(serviceInterfaces, this, props);
     }
 
     /**
@@ -118,16 +118,11 @@ public class ConfigTaskCreator
      */
     @Override
     public void configurationEvent(final ConfigurationEvent event) {
-        Configuration updateConfig = null;
-        ResourceGroup updateGroup = null;
         synchronized ( Coordinator.SHARED ) {
             if ( event.getType() == ConfigurationEvent.CM_DELETED ) {
                 final Coordinator.Operation op = 
Coordinator.SHARED.get(event.getPid(), event.getFactoryPid(), true);
                 if ( op == null ) {
-                    updateGroup = this.convertOldInstallerResource(event);
-                    if ( updateGroup == null ) {
-                        
this.changeListener.resourceRemoved(InstallableResource.TYPE_CONFIG, 
event.getPid());
-                    }
+                    
this.changeListener.resourceRemoved(InstallableResource.TYPE_CONFIG, 
event.getPid());
                 } else {
                     this.logger.debug("Ignoring configuration event for 
{}:{}", event.getPid(), event.getFactoryPid());
                 }
@@ -156,12 +151,7 @@ public class ConfigTaskCreator
                             attrs.put(ConfigurationAdmin.SERVICE_FACTORYPID, 
event.getFactoryPid());
                         }
 
-                        updateGroup = this.convertOldInstallerResource(event);
-                        if ( updateGroup == null ) {
-                            
this.changeListener.resourceAddedOrUpdated(InstallableResource.TYPE_CONFIG, 
event.getPid(), null, dict, attrs);
-                        } else {
-                            updateConfig = config;
-                        }
+                        
this.changeListener.resourceAddedOrUpdated(InstallableResource.TYPE_CONFIG, 
event.getPid(), null, dict, attrs);
 
                     } else {
                         this.logger.debug("Ignoring configuration event for 
{}:{}", event.getPid(), event.getFactoryPid());
@@ -171,76 +161,6 @@ public class ConfigTaskCreator
                 }
             }
         }
-        if ( updateGroup != null ) {
-            // update installer state from old config to new config
-            // store config dictionary for update
-            final Dictionary<String, Object> dict = updateConfig == null ? 
null : ConfigUtil.cleanConfiguration(updateConfig.getProperties());
-            try {
-                String name = null;
-                for(final Resource r : updateGroup.getResources()) {
-                    if ( name == null ) {
-                        name = (String)r.getAttribute(Constants.SERVICE_PID);
-                    }
-                    final int pos = r.getURL().indexOf(':');
-                    final String rsrcPath = r.getURL().substring(pos +1);
-
-                    this.startListener(r.getURL(), 2);
-                    final Dictionary<String, Object> newProps = 
ConfigUtil.cleanConfiguration(r.getDictionary());
-                    newProps.put(this.getClass().getName(), "true");
-                    final InstallableResource ins1 = new 
InstallableResource(rsrcPath, null, newProps, r.getDigest(), r.getType(), 
r.getPriority());
-                    this.installer.updateResources(r.getScheme(), new 
InstallableResource[] {ins1}, null);
-                    this.waitForInstall();
-
-                    this.startListener(r.getURL(), 1);
-                    newProps.remove(this.getClass().getName());
-                    final InstallableResource ins2 = new 
InstallableResource(rsrcPath, null, newProps, r.getDigest(), r.getType(), 
r.getPriority());
-                    this.installer.updateResources(r.getScheme(), new 
InstallableResource[] {ins2}, null);
-                    this.waitForInstall();
-                }
-                if ( updateConfig != null ) {
-                    // then delete old config
-                    final Coordinator.Operation op = new 
Coordinator.Operation(event.getPid(), event.getFactoryPid(), true);
-                    Coordinator.SHARED.add(op);
-                    updateConfig.delete();
-
-                    // finally re-create new config
-                    final Configuration newConfig = 
this.configAdmin.getFactoryConfiguration(event.getFactoryPid(), name, null);
-                    newConfig.update(dict);
-                } else {
-                    // delete newly created config
-                    final Configuration newConfig = 
this.configAdmin.getFactoryConfiguration(event.getFactoryPid(), name, null);
-                    newConfig.delete();
-                }
-            } catch ( final Exception ignore) {
-                logger.error("An error occured while updating factory 
configuration " + event.getFactoryPid() + "-" + event.getPid(), ignore);
-            }
-        }
-    }
-
-    private ResourceGroup convertOldInstallerResource(final ConfigurationEvent 
event) {
-        if ( event.getFactoryPid() != null && !event.getPid().contains("~") ) {
-            // check if this configuration is processed by the installer
-            final String id =  event.getFactoryPid() + '.' + 
(event.getPid().startsWith(event.getFactoryPid() + '.') ?
-                    event.getPid().substring(event.getFactoryPid().length() + 
1) : event.getPid());
-            final List<ResourceGroup> groups = 
this.infoProvider.getInstallationState().getInstalledResources();
-            for(final ResourceGroup grp : groups) {
-                if ( grp.getAlias() != null ) {
-                    final String alias;
-                    if ( grp.getAlias().startsWith(event.getFactoryPid() + 
".") ) {
-                        alias = 
grp.getAlias().substring(event.getFactoryPid().length() + 1);
-                    } else {
-                        alias = grp.getAlias();
-                    }
-                    for(final Resource rsrc : grp.getResources()) {
-                        if ( 
InstallableResource.TYPE_CONFIG.equals(rsrc.getType()) && id.equals(alias) ) {
-                            // we need to update the installer state
-                            return grp;
-                        }
-                    }
-                }
-            }
-        }
-        return null;
     }
 
     /**
@@ -307,37 +227,6 @@ public class ConfigTaskCreator
         return new TransformationResult[] {tr};
     }
 
-    private volatile CountDownLatch latch;
-    private volatile String waitingForUrl;
-
-    @Override
-    public void onEvent(final InstallationEvent event) {
-        if ( waitingForUrl != null ) {
-            if ( event.getType() == InstallationEvent.TYPE.PROCESSED ) {
-                final TaskResource rsrc = (TaskResource) event.getSource();
-                if ( rsrc.getURL().equals(waitingForUrl) ) {
-                    latch.countDown();
-                }
-            }
-        }
-    }
-
-
-    private void startListener(final String url, final int count) {
-        this.latch = new CountDownLatch(count);
-        this.waitingForUrl = url;
-    }
-
-    public void waitForInstall() {
-        try {
-            this.latch.await(50, TimeUnit.SECONDS);
-        } catch (final InterruptedException e) {
-            Thread.currentThread().interrupt();
-        }
-        this.waitingForUrl = null;
-        this.latch = null;
-    }
-
     private static final List<String> EXTENSIONS = Arrays.asList(".config", 
".properties", ".cfg", ".cfg.json");
     private static String removeConfigExtension(final String id) {
         for(final String ext : EXTENSIONS) {
diff --git 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigUpdateHandler.java
 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigUpdateHandler.java
new file mode 100644
index 0000000..0a27403
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigUpdateHandler.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.installer.factories.configuration.impl;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.sling.installer.api.InstallableResource;
+import org.apache.sling.installer.api.tasks.ResourceUpdater;
+import org.apache.sling.installer.api.tasks.UpdatableResourceGroup;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Update handler for updating 1.x to 1.2
+ */
+public class ConfigUpdateHandler implements ResourceUpdater {
+
+    /** Logger. */
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    /** Configuration admin. */
+    private final ConfigurationAdmin configAdmin;
+
+    private final ServicesListener activator;
+
+
+    public ConfigUpdateHandler(final ConfigurationAdmin configAdmin,
+            final ServicesListener activator) {
+        this.configAdmin = configAdmin;
+        this.activator = activator;
+    }
+
+    public ServiceRegistration<?> register(final BundleContext bundleContext) {
+        final Hashtable<String, String> props = new Hashtable<>();
+        props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Configuration 
Install Task Factory Update Handler");
+        props.put(Constants.SERVICE_VENDOR, ServicesListener.VENDOR);
+
+        final String [] serviceInterfaces = {
+                ResourceUpdater.class.getName()
+        };
+        return bundleContext.registerService(serviceInterfaces, this, props);
+    }
+
+    @Override
+    public void update(final Collection<UpdatableResourceGroup> groups) {
+        for(final UpdatableResourceGroup group : groups) {
+            update(group);
+        }
+        this.activator.finishedUpdating();
+    }
+
+    private void update(final UpdatableResourceGroup group) {
+        if ( this.activator.isActive() ) {
+            // check if the group handles configurations and has an alias (aka 
factory config)
+            if ( 
InstallableResource.TYPE_CONFIG.equals(group.getResourceType()) && 
group.getAlias() != null ) {
+                this.updateFactoryConfig(group);
+            }
+        }
+    }
+
+    private void updateFactoryConfig(final UpdatableResourceGroup group) {
+        final String alias = group.getAlias();
+        final String oldId = group.getId();
+
+        // change group id
+        int pos = 0;
+        while ( alias.charAt(pos) == oldId.charAt(pos) ) {
+            pos++;
+        }
+        final String factoryPid = alias.substring(0, pos - 1);
+        final String pid = oldId.substring(factoryPid.length() + 1);
+
+        final String newId = ConfigUtil.getPIDOfFactoryPID(factoryPid, pid);
+        group.setId(newId);
+        // clear alias
+        group.setAlias(null);
+
+        this.logger.debug("Updating factory configuration from {} to {}", 
oldId, newId);
+        try {
+            final Configuration cfg = 
ConfigUtil.getLegacyFactoryConfig(this.configAdmin, factoryPid, alias, pid);
+            if ( cfg != null ) {
+                // keep existing values / location
+                final String location = cfg.getBundleLocation();
+                final Dictionary<String, Object> dict = 
ConfigUtil.cleanConfiguration(cfg.getProperties());
+                // delete old factory configuration
+                cfg.delete();
+                // create new named factory configuration with same properties 
and bundle location
+                final Configuration upCfg = 
this.configAdmin.getFactoryConfiguration(factoryPid, pid, location);
+                upCfg.update(dict);
+            }
+        } catch ( final IOException | InvalidSyntaxException io) {
+            // ignore for now
+        }
+        group.update();
+    }
+}
diff --git 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ServicesListener.java
 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ServicesListener.java
index 22e179b..526bdfe 100644
--- 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ServicesListener.java
+++ 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ServicesListener.java
@@ -18,14 +18,9 @@
  */
 package org.apache.sling.installer.factories.configuration.impl;
 
-import java.util.Hashtable;
+import java.util.concurrent.atomic.AtomicBoolean;
 
-import org.apache.sling.installer.api.OsgiInstaller;
 import org.apache.sling.installer.api.ResourceChangeListener;
-import org.apache.sling.installer.api.event.InstallationListener;
-import org.apache.sling.installer.api.info.InfoProvider;
-import org.apache.sling.installer.api.tasks.InstallTaskFactory;
-import org.apache.sling.installer.api.tasks.ResourceTransformer;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
@@ -34,7 +29,6 @@ import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.cm.ConfigurationListener;
 
 /**
  * The <code>ServicesListener</code> listens for the required services
@@ -49,12 +43,6 @@ public class ServicesListener {
     /** The bundle context. */
     private final BundleContext bundleContext;
 
-    /** The listener for the installer. */
-    private final Listener installerListener;
-
-    /** The listener for the info service */
-    private final Listener infoServiceListener;
-
     /** The listener for the change list handler. */
     private final Listener changeHandlerListener;
 
@@ -62,54 +50,40 @@ public class ServicesListener {
     private final Listener configAdminListener;
 
     /** Registration the service. */
-    private ServiceRegistration<?> configTaskCreatorRegistration;
+    private volatile ServiceRegistration<?> configTaskCreatorRegistration;
+
+    private volatile ConfigTaskCreator configTaskCreator;
 
-    private ConfigTaskCreator configTaskCreator;
+    private final AtomicBoolean active = new AtomicBoolean(false);
 
     public ServicesListener(final BundleContext bundleContext) {
         this.bundleContext = bundleContext;
-        this.installerListener = new Listener(OsgiInstaller.class.getName());
-        this.infoServiceListener = new Listener(InfoProvider.class.getName());
         this.changeHandlerListener = new 
Listener(ResourceChangeListener.class.getName());
         this.configAdminListener = new 
Listener(ConfigurationAdmin.class.getName());
         this.changeHandlerListener.start();
         this.configAdminListener.start();
-        this.installerListener.start();
-        this.infoServiceListener.start();
     }
 
     public synchronized void notifyChange() {
         // check if all services are available
         final ResourceChangeListener listener = 
(ResourceChangeListener)this.changeHandlerListener.getService();
         final ConfigurationAdmin configAdmin = 
(ConfigurationAdmin)this.configAdminListener.getService();
-        final OsgiInstaller installer = 
(OsgiInstaller)this.installerListener.getService();
-        final InfoProvider infoProvider = 
(InfoProvider)this.infoServiceListener.getService();
 
-        if ( configAdmin != null && listener != null && installer != null && 
infoProvider != null ) {
+        if ( configAdmin != null && listener != null ) {
             if ( configTaskCreator == null ) {
-                final Hashtable<String, String> props = new Hashtable<>();
-                props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling 
Configuration Install Task Factory");
-                props.put(Constants.SERVICE_VENDOR, VENDOR);
-                props.put(InstallTaskFactory.NAME, "org.osgi.service.cm");
-                props.put(ResourceTransformer.NAME, "org.osgi.service.cm");
-
-                this.configTaskCreator = new ConfigTaskCreator(listener, 
configAdmin, installer, infoProvider);
+                active.set(true);
                 // start and register osgi installer service
-                final String [] serviceInterfaces = {
-                        InstallTaskFactory.class.getName(),
-                        ConfigurationListener.class.getName(),
-                        ResourceTransformer.class.getName(),
-                        InstallationListener.class.getName()
-
-                };
-                configTaskCreatorRegistration = 
this.bundleContext.registerService(serviceInterfaces, configTaskCreator, props);
+                this.configTaskCreator = new ConfigTaskCreator(listener, 
configAdmin);
+                final ConfigUpdateHandler handler = new 
ConfigUpdateHandler(configAdmin, this);
+                configTaskCreatorRegistration = 
handler.register(this.bundleContext);
             }
         } else {
             this.stop();
         }
     }
 
-    private void stop() {
+    private synchronized void stop() {
+        active.set(false);
         // unregister
         if ( this.configTaskCreatorRegistration != null ) {
             this.configTaskCreatorRegistration.unregister();
@@ -118,14 +92,23 @@ public class ServicesListener {
         this.configTaskCreator = null;
     }
 
+    public boolean isActive() {
+        return this.active.get();
+    }
+
+    public synchronized void finishedUpdating() {
+        if ( this.isActive() ) {
+            this.configTaskCreatorRegistration.unregister();
+            this.configTaskCreatorRegistration = 
this.configTaskCreator.register(this.bundleContext);
+        }
+    }
+
     /**
      * Deactivate this listener.
      */
     public void deactivate() {
         this.changeHandlerListener.deactivate();
         this.configAdminListener.deactivate();
-        this.infoServiceListener.deactivate();
-        this.installerListener.deactivate();
         this.stop();
     }
 

Reply via email to