felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1791687 - in /felix/trunk/osgi-r7/configurator/src: main/java/org/apache/felix/configurator/impl/ test/java/org/apache/felix/configurator/impl/
Date Mon, 17 Apr 2017 11:55:09 GMT
Author: cziegeler
Date: Mon Apr 17 11:55:09 2017
New Revision: 1791687

URL: http://svn.apache.org/viewvc?rev=1791687&view=rev
Log:
Update configurator to only listen for starting/active bundles. Process bundles asyn

Added:
    felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/WorkerQueue.java
  (with props)
Modified:
    felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/Configurator.java
    felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/Util.java
    felix/trunk/osgi-r7/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java

Modified: felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/Configurator.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/Configurator.java?rev=1791687&r1=1791686&r2=1791687&view=diff
==============================================================================
--- felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/Configurator.java
(original)
+++ felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/Configurator.java
Mon Apr 17 11:55:09 2017
@@ -44,6 +44,7 @@ import org.osgi.framework.BundleEvent;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.service.cm.Configuration;
 import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.configurator.ConfiguratorConstants;
 import org.osgi.util.tracker.BundleTrackerCustomizer;
 
 /**
@@ -52,10 +53,6 @@ import org.osgi.util.tracker.BundleTrack
  */
 public class Configurator {
 
-    private static final String PROP_INITIAL = "configurator.initial";
-
-    private static final String PROP_DIRECTORY = "configurator.binaries";
-
     private final BundleContext bundleContext;
 
     private final ConfigurationAdmin configAdmin;
@@ -70,29 +67,37 @@ public class Configurator {
 
     private volatile Object coordinator;
 
+    private final WorkerQueue queue;
+
     /**
      * Create a new configurator and start it
      * @param bc The bundle context
      * @param ca The configuration admin
      */
     public Configurator(final BundleContext bc, final ConfigurationAdmin ca) {
+        this.queue = new WorkerQueue();
         this.bundleContext = bc;
         this.configAdmin = ca;
         this.activeEnvironments = Util.getActiveEnvironments(bc);
         this.state = State.createOrReadState(bundleContext);
         this.state.changeEnvironments(this.activeEnvironments);
-        this.tracker = new org.osgi.util.tracker.BundleTracker<Bundle>(this.bundleContext,
-                Bundle.INSTALLED|Bundle.ACTIVE|Bundle.RESOLVED|Bundle.STARTING,
+        this.tracker = new org.osgi.util.tracker.BundleTracker<>(this.bundleContext,
+                Bundle.ACTIVE|Bundle.STARTING|Bundle.UNINSTALLED,
 
                 new BundleTrackerCustomizer<Bundle>() {
 
             @Override
             public Bundle addingBundle(final Bundle bundle, final BundleEvent event) {
-                if ( active ) {
-                    synchronized ( this ) {
-                        processAddBundle(bundle);
-                        process();
-                    }
+                if ( active &&
+                    (event.getType() == Bundle.ACTIVE || event.getType() == Bundle.STARTING)
) {
+                    queue.enqueue(new Runnable() {
+
+                        @Override
+                        public void run() {
+                            processAddBundle(bundle);
+                            process();
+                        }
+                    });
                 }
                 return bundle;
             }
@@ -104,15 +109,19 @@ public class Configurator {
 
             @Override
             public void removedBundle(final Bundle bundle, final BundleEvent event, final
Bundle object) {
-                if ( active ) {
-                    try {
-                        synchronized ( this ) {
-                            processRemoveBundle(bundle.getBundleId());
-                            process();
+                if ( active && event.getType() == Bundle.UNINSTALLED ) {
+                    queue.enqueue(new Runnable() {
+
+                        @Override
+                        public void run() {
+                            try {
+                                processRemoveBundle(bundle.getBundleId());
+                                process();
+                            } catch ( final IllegalStateException ise) {
+                                SystemLogger.error("Error processing bundle " + bundle.getBundleId()
+ " - " + bundle.getSymbolicName(), ise);
+                            }
                         }
-                    } catch ( final IllegalStateException ise) {
-                        SystemLogger.error("Error processing bundle " + bundle.getBundleId()
+ " - " + bundle.getSymbolicName(), ise);
-                    }
+                    });
                 }
             }
 
@@ -124,6 +133,7 @@ public class Configurator {
      */
     public void shutdown() {
         this.active = false;
+        this.queue.stop();
         this.tracker.close();
     }
 
@@ -132,7 +142,7 @@ public class Configurator {
      */
     public void start() {
         // get the directory for storing binaries
-        String dirPath = this.bundleContext.getProperty(PROP_DIRECTORY);
+        String dirPath = this.bundleContext.getProperty(ConfiguratorConstants.CONFIGURATOR_BINARIES);
         if ( dirPath != null ) {
             final File dir = new File(dirPath);
             if ( dir.exists() && dir.isDirectory() ) {
@@ -159,7 +169,7 @@ public class Configurator {
         }
 
         // before we start the tracker we process all available bundles and initial configuration
-        final String initial = this.bundleContext.getProperty(PROP_INITIAL);
+        final String initial = this.bundleContext.getProperty(ConfiguratorConstants.CONFIGURATOR_INITIAL);
         if ( initial == null ) {
             this.processRemoveBundle(-1);
         } else {
@@ -187,7 +197,7 @@ public class Configurator {
             } else {
                 // JSON
                 hashes.add(Util.getSHA256(initial.trim()));
-                files.put(PROP_INITIAL, initial);
+                files.put(ConfiguratorConstants.CONFIGURATOR_INITIAL, initial);
             }
             if ( state.getInitialHashes() != null && state.getInitialHashes().equals(hashes))
{
                 if ( state.environmentsChanged() ) {
@@ -234,7 +244,7 @@ public class Configurator {
             final long bundleId = bundle.getBundleId();
             final long bundleLastModified = bundle.getLastModified();
             final Long lastModified = state.getLastModified(bundleId);
-            if ( lastModified != null && lastModified == bundleLastModified ) {
+            if ( lastModified != null && lastModified.longValue() == bundleLastModified
) {
                 if ( state.environmentsChanged() ) {
                     state.checkEnvironments(bundleId);
                 }
@@ -244,7 +254,7 @@ public class Configurator {
             if ( lastModified != null ) {
                 processRemoveBundle(bundleId);
             }
-            final Set<String> paths = Util.isConfigurerBundle(bundle);
+            final Set<String> paths = Util.isConfigurerBundle(bundle, this.bundleContext.getBundle().getBundleId());
             if ( paths != null ) {
                 final BundleState config = org.apache.felix.configurator.impl.json.JSONUtil.readConfigurationsFromBundle(bundle,
paths);
                 for(final String pid : config.getPids()) {

Modified: felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/Util.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/Util.java?rev=1791687&r1=1791686&r2=1791687&view=diff
==============================================================================
--- felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/Util.java
(original)
+++ felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/Util.java
Mon Apr 17 11:55:09 2017
@@ -34,15 +34,15 @@ import java.security.NoSuchAlgorithmExce
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
 import org.apache.felix.configurator.impl.logger.SystemLogger;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.resource.Requirement;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
 
 public class Util {
 
@@ -62,38 +62,45 @@ public class Util {
      * @return Set of locations or {@code null}
      */
     @SuppressWarnings("unchecked")
-    public static Set<String> isConfigurerBundle(final Bundle bundle) {
-        final BundleRevision bundleRevision = bundle.adapt(BundleRevision.class);
-        if ( bundleRevision == null ) {
+    public static Set<String> isConfigurerBundle(final Bundle bundle, final long configuratorBundleId)
{
+        // check for bundle wiring
+        final BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
+        if ( bundleWiring == null ) {
             return null;
         }
 
-        final List<Requirement> requirements = bundleRevision.getRequirements(NS_OSGI_IMPL);
+        // check for bundle requirement to implementation namespace
+        final List<BundleRequirement> requirements = bundleWiring.getRequirements(NS_OSGI_IMPL);
         if ( requirements == null || requirements.isEmpty() ) {
             return null;
         }
-        // TODO check version etc
-        for(final Requirement req : requirements) {
-            final Map<String, Object> attributes = req.getAttributes();
-
-            final Object val = attributes.get(PROP_CONFIGURATIONS);
-            if ( val != null ) {
-                if ( val instanceof String ) {
-                    return Collections.singleton((String)val);
-                }
-                if ( val instanceof List ) {
-                    final List<String> paths = (List<String>)val;
-                    final Set<String> result = new HashSet<>();
-                    for(final String p : paths) {
-                        result.add(p);
+        // get all wires for the implementation namespace
+        final List<BundleWire> wires = bundleWiring.getRequiredWires(NS_OSGI_IMPL);
+        for(final BundleWire wire : wires) {
+            // if the wire is to this bundle (configurator), it must be the correct
+            // requirement (no need to do additional checks like version etc.)
+            if ( wire.getProviderWiring() != null
+                 && wire.getProviderWiring().getBundle().getBundleId() == configuratorBundleId
) {
+                final Object val = wire.getRequirement().getAttributes().get(PROP_CONFIGURATIONS);
+                if ( val != null ) {
+                    if ( val instanceof String ) {
+                        return Collections.singleton((String)val);
+                    }
+                    if ( val instanceof List ) {
+                        final List<String> paths = (List<String>)val;
+                        final Set<String> result = new HashSet<>();
+                        for(final String p : paths) {
+                            result.add(p);
+                        }
+                        return result;
                     }
-                    return result;
+                    SystemLogger.error("Attribute " + PROP_CONFIGURATIONS + " for configurator
requirement has an invalid type: " + val +
+                                       ". Using default configuration.");
                 }
-                SystemLogger.error("Attribute " + PROP_CONFIGURATIONS + " for configurator
requirement has an invalid type: " + val +
-                                   ". Using default configuration.");
+                return Collections.singleton(DEFAULT_PATH);
             }
-            return Collections.singleton(DEFAULT_PATH);
         }
+
         return null;
     }
 

Added: felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/WorkerQueue.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/WorkerQueue.java?rev=1791687&view=auto
==============================================================================
--- felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/WorkerQueue.java
(added)
+++ felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/WorkerQueue.java
Mon Apr 17 11:55:09 2017
@@ -0,0 +1,82 @@
+/*
+ * 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.felix.configurator.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+import org.apache.felix.configurator.impl.logger.SystemLogger;
+
+public class WorkerQueue implements Runnable {
+
+    private final ThreadFactory threadFactory;
+
+    private final List<Runnable> tasks = new ArrayList<>();
+
+    private volatile Thread backgroundThread;
+
+    private volatile boolean stopped = false;
+
+    public WorkerQueue() {
+        this.threadFactory = Executors.defaultThreadFactory();
+    }
+
+    public void stop() {
+        synchronized ( this.tasks ) {
+            this.stopped = true;
+        }
+    }
+
+    public void enqueue(final Runnable r) {
+        synchronized ( this.tasks ) {
+            if ( !this.stopped ) {
+                this.tasks.add(r);
+                if ( this.backgroundThread == null ) {
+                    this.backgroundThread = this.threadFactory.newThread(this);
+                    this.backgroundThread.start();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void run() {
+        Runnable r;
+        do {
+            r = null;
+            synchronized ( this.tasks ) {
+                if ( !this.stopped && !this.tasks.isEmpty() ) {
+                    r = this.tasks.remove(0);
+                } else {
+                    this.backgroundThread = null;
+                }
+            }
+            if ( r != null ) {
+                try {
+                    r.run();
+                } catch ( final Throwable t) {
+                    // just to be sure our loop never dies
+                    SystemLogger.error("Error processing task" + t.getMessage(), t);
+                }
+            }
+        } while ( r != null );
+    }
+}

Propchange: felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/WorkerQueue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/WorkerQueue.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Modified: felix/trunk/osgi-r7/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java?rev=1791687&r1=1791686&r2=1791687&view=diff
==============================================================================
--- felix/trunk/osgi-r7/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java
(original)
+++ felix/trunk/osgi-r7/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java
Mon Apr 17 11:55:09 2017
@@ -38,8 +38,9 @@ import org.mockito.InOrder;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.resource.Requirement;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
 import org.osgi.service.cm.Configuration;
 import org.osgi.service.cm.ConfigurationAdmin;
 
@@ -49,10 +50,15 @@ public class ConfiguratorTest {
 
     private BundleContext bundleContext;
 
+    private Bundle bundle;
+
     private ConfigurationAdmin configurationAdmin;
 
     @Before public void setup() throws IOException {
+        bundle = mock(Bundle.class);
+        when(bundle.getBundleId()).thenReturn(42L);
         bundleContext = mock(BundleContext.class);
+        when(bundleContext.getBundle()).thenReturn(bundle);
         when(bundleContext.getBundles()).thenReturn(new Bundle[0]);
         when(bundleContext.getDataFile("binaries" + File.separatorChar + ".check")).thenReturn(Files.createTempDirectory("test").toFile());
         configurationAdmin = mock(ConfigurationAdmin.class);
@@ -64,10 +70,15 @@ public class ConfiguratorTest {
         final Bundle b = mock(Bundle.class);
         when(b.getBundleId()).thenReturn(id);
         when(b.getLastModified()).thenReturn(5L);
-        final BundleRevision rev = mock(BundleRevision.class);
-        when(b.adapt(BundleRevision.class)).thenReturn(rev);
-        final Requirement req = mock(Requirement.class);
-        when(rev.getRequirements(Util.NS_OSGI_IMPL)).thenReturn(Collections.singletonList(req));
+        final BundleWiring wiring = mock(BundleWiring.class);
+        when(b.adapt(BundleWiring.class)).thenReturn(wiring);
+        final BundleRequirement req = mock(BundleRequirement.class);
+        when(wiring.getRequirements(Util.NS_OSGI_IMPL)).thenReturn(Collections.singletonList(req));
+        final BundleWire wire = mock(BundleWire.class);
+        when(wire.getProviderWiring()).thenReturn(wiring);
+        when(wire.getRequirement()).thenReturn(req);
+        when(wiring.getBundle()).thenReturn(bundle);
+        when(wiring.getRequiredWires(Util.NS_OSGI_IMPL)).thenReturn(Collections.singletonList(wire));
         final Vector<URL> urls = new Vector<>();
         urls.add(this.getClass().getResource("/bundles/" + id + ".json"));
         when(b.findEntries("OSGI-INF/configurator", "*.json", false)).thenReturn(urls.elements());



Mime
View raw message