You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2017/11/09 10:20:58 UTC

svn commit: r1814712 - in /felix/trunk/osgi-r7/scr: ./ src/main/java/org/apache/felix/scr/impl/

Author: cziegeler
Date: Thu Nov  9 10:20:57 2017
New Revision: 1814712

URL: http://svn.apache.org/viewvc?rev=1814712&view=rev
Log:
FELIX-5739 : Strange behaviour with Lazy-ActivationPolicy and autostart

Added:
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/AbstractExtender.java   (with props)
Modified:
    felix/trunk/osgi-r7/scr/bnd.bnd
    felix/trunk/osgi-r7/scr/pom.xml
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java

Modified: felix/trunk/osgi-r7/scr/bnd.bnd
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/bnd.bnd?rev=1814712&r1=1814711&r2=1814712&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/bnd.bnd (original)
+++ felix/trunk/osgi-r7/scr/bnd.bnd Thu Nov  9 10:20:57 2017
@@ -21,8 +21,7 @@ Export-Package: org.apache.felix.scr.com
  org.osgi.util.function;version=1.0, \
  org.osgi.util.promise;version=1.0
 
-Private-Package: org.apache.felix.scr.impl.*, \
- org.apache.felix.utils.extender
+Private-Package: org.apache.felix.scr.impl.*
 
 # Configuration Admin is optional and dynamic, but allow eager wiring by importing it
 # LogService is optional but if present the R4.0 version 1.3 is sufficient.

Modified: felix/trunk/osgi-r7/scr/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/pom.xml?rev=1814712&r1=1814711&r2=1814712&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/pom.xml (original)
+++ felix/trunk/osgi-r7/scr/pom.xml Thu Nov  9 10:20:57 2017
@@ -106,6 +106,12 @@
  -->
         <dependency>
             <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.log</artifactId>
+            <version>1.3.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
             <artifactId>org.osgi.service.metatype</artifactId>
             <version>1.3.0</version>
             <scope>provided</scope>
@@ -123,12 +129,6 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.utils</artifactId>
-            <version>1.8.6</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>org.apache.felix.shell</artifactId>
             <version>1.0.0</version>

Added: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/AbstractExtender.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/AbstractExtender.java?rev=1814712&view=auto
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/AbstractExtender.java (added)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/AbstractExtender.java Thu Nov  9 10:20:57 2017
@@ -0,0 +1,258 @@
+/*
+ * Licensed 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.scr.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Constants;
+import org.osgi.framework.SynchronousBundleListener;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+
+/**
+ * Base class to write bundle extenders.
+ * This extender tracks started bundles (or starting if they have a lazy activation
+ * policy) and will create an extension for each of them to manage it.
+ *
+ * The extender will handle all concurrency and synchronization issues.
+ *
+ * The extender guarantee that all extensions will be stopped synchronously with
+ * the STOPPING event of a given bundle and that all extensions will be stopped
+ * before the extender bundle is stopped.
+ *
+ */
+public abstract class AbstractExtender implements BundleActivator, BundleTrackerCustomizer<Bundle>, SynchronousBundleListener {
+
+    private final ConcurrentMap<Bundle, Activator.ScrExtension> extensions = new ConcurrentHashMap<>();
+    private final ConcurrentMap<Bundle, FutureTask<Void>> destroying = new ConcurrentHashMap<>();
+    private volatile boolean stopping;
+    private volatile boolean stopped;
+
+    private BundleContext context;
+    private BundleTracker<Bundle> tracker;
+
+    public BundleContext getBundleContext() {
+        return context;
+    }
+
+    public boolean isStopping() {
+        return stopping;
+    }
+
+    @Override
+    public void start(BundleContext context) throws Exception {
+        this.context = context;
+        this.context.addBundleListener(this);
+        this.tracker = new BundleTracker<>(this.context, Bundle.ACTIVE | Bundle.STARTING, this);
+        doStart();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        stopping = true;
+        while (!extensions.isEmpty()) {
+            Collection<Bundle> toDestroy = chooseBundlesToDestroy(extensions.keySet());
+            if (toDestroy == null || toDestroy.isEmpty()) {
+                toDestroy = new ArrayList<>(extensions.keySet());
+            }
+            for (Bundle bundle : toDestroy) {
+                destroyExtension(bundle);
+            }
+        }
+        doStop();
+        stopped = true;
+    }
+
+    protected void doStart() throws Exception {
+        startTracking();
+    }
+
+    protected void doStop() throws Exception {
+        stopTracking();
+    }
+
+    protected void startTracking() {
+        this.tracker.open();
+    }
+
+    protected void stopTracking() {
+        this.tracker.close();
+    }
+
+    /**
+     * Create the executor used to start extensions asynchronously.
+     *
+     * @return an
+     */
+    protected ExecutorService createExecutor() {
+        return Executors.newScheduledThreadPool(3);
+    }
+
+    protected Collection<Bundle> chooseBundlesToDestroy(Set<Bundle> bundles) {
+        return null;
+    }
+
+
+    @Override
+    public void bundleChanged(BundleEvent event) {
+        if (stopped) {
+            return;
+        }
+        Bundle bundle = event.getBundle();
+        if (bundle.getState() != Bundle.ACTIVE && bundle.getState() != Bundle.STARTING) {
+            // The bundle is not in STARTING or ACTIVE state anymore
+            // so destroy the context.  Ignore our own bundle since it
+            // needs to kick the orderly shutdown.
+            if (bundle != this.context.getBundle()) {
+                destroyExtension(bundle);
+            }
+        }
+    }
+
+    @Override
+    public Bundle addingBundle(Bundle bundle, BundleEvent event) {
+        modifiedBundle(bundle, event, bundle);
+        return bundle;
+    }
+
+    @Override
+    public void modifiedBundle(Bundle bundle, BundleEvent event, Bundle object) {
+        if (bundle.getState() != Bundle.ACTIVE && bundle.getState() != Bundle.STARTING) {
+            // The bundle is not in STARTING or ACTIVE state anymore
+            // so destroy the context.  Ignore our own bundle since it
+            // needs to kick the orderly shutdown and not unregister the namespaces.
+            if (bundle != this.context.getBundle()) {
+                destroyExtension(bundle);
+            }
+            return;
+        }
+        // Do not track bundles given we are stopping
+        if (stopping) {
+            return;
+        }
+        // For starting bundles, ensure, it's a lazy activation,
+        // else we'll wait for the bundle to become ACTIVE
+        if (bundle.getState() == Bundle.STARTING) {
+            String activationPolicyHeader = bundle.getHeaders("").get(Constants.BUNDLE_ACTIVATIONPOLICY);
+            if (activationPolicyHeader == null
+                || !activationPolicyHeader.startsWith(Constants.ACTIVATION_LAZY)
+                || !bundle.adapt(BundleStartLevel.class).isActivationPolicyUsed()) {
+                // Do not track this bundle yet
+                return;
+            }
+        }
+        createExtension(bundle);
+    }
+
+    @Override
+    public void removedBundle(Bundle bundle, BundleEvent event, Bundle object) {
+        // Nothing to do
+        destroyExtension(bundle);
+    }
+
+    private void createExtension(final Bundle bundle) {
+        try {
+            BundleContext bundleContext = bundle.getBundleContext();
+            if (bundleContext == null) {
+                // The bundle has been stopped in the mean time
+                return;
+            }
+            final Activator.ScrExtension extension = doCreateExtension(bundle);
+            if (extension == null) {
+                // This bundle is not to be extended
+                return;
+            }
+            synchronized (extensions) {
+                if (extensions.putIfAbsent(bundle, extension) != null) {
+                    return;
+                }
+            }
+            debug(bundle, "Starting extension synchronously");
+            extension.start();
+        } catch (Throwable t) {
+            warn(bundle, "Error while creating extension", t);
+        }
+    }
+
+    private void destroyExtension(final Bundle bundle) {
+        FutureTask<Void> future;
+        synchronized (extensions) {
+            debug(bundle, "Starting destruction process");
+            future = destroying.get(bundle);
+            if (future == null) {
+                final Activator.ScrExtension extension = extensions.remove(bundle);
+                if (extension != null) {
+                    debug(bundle, "Scheduling extension destruction");
+                    future = new FutureTask<>(new Runnable() {
+                        @Override
+                        public void run() {
+                            debug(bundle, "Destroying extension");
+                            try {
+                                extension.destroy();
+                            } catch (Exception e) {
+                                warn(bundle, "Error while destroying extension", e);
+                            } finally {
+                                debug(bundle, "Finished destroying extension");
+                                synchronized (extensions) {
+                                    destroying.remove(bundle);
+                                }
+                            }
+                        }
+                    }, null);
+                    destroying.put(bundle, future);
+                } else {
+                    debug(bundle, "Not an extended bundle or destruction of extension already finished");
+                }
+            } else {
+                debug(bundle, "Destruction already scheduled");
+            }
+        }
+        if (future != null) {
+            try {
+                debug(bundle, "Waiting for extension destruction");
+                future.run();
+                future.get();
+            } catch (Throwable t) {
+                warn(bundle, "Error while destroying extension", t);
+            }
+        }
+    }
+
+    /**
+     * Create the extension for the given bundle, or null if the bundle is not to be extended.
+     *
+     * @param bundle the bundle to extend
+     * @return The extension
+     * @throws Exception If something goes wrong
+     */
+    protected abstract Activator.ScrExtension doCreateExtension(Bundle bundle) throws Exception;
+
+    protected abstract void debug(Bundle bundle, String msg);
+    protected abstract void warn(Bundle bundle, String msg, Throwable t);
+
+}

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

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

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/Activator.java?rev=1814712&r1=1814711&r2=1814712&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/Activator.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/Activator.java Thu Nov  9 10:20:57 2017
@@ -29,8 +29,6 @@ import org.apache.felix.scr.impl.config.
 import org.apache.felix.scr.impl.inject.ClassUtils;
 import org.apache.felix.scr.impl.logger.ScrLogger;
 import org.apache.felix.scr.impl.runtime.ServiceComponentRuntimeImpl;
-import org.apache.felix.utils.extender.AbstractExtender;
-import org.apache.felix.utils.extender.Extension;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -80,7 +78,6 @@ public class Activator extends AbstractE
     public Activator()
     {
         m_configuration = new ScrConfigurationImpl( this );
-        setSynchronous( true );
     }
 
     /**
@@ -225,12 +222,12 @@ public class Activator extends AbstractE
     //---------- Component Management -----------------------------------------
 
     @Override
-    protected Extension doCreateExtension(final Bundle bundle) throws Exception
+    protected ScrExtension doCreateExtension(final Bundle bundle) throws Exception
     {
         return new ScrExtension( bundle );
     }
 
-    protected class ScrExtension implements Extension
+    protected class ScrExtension
     {
 
         private final Bundle bundle;
@@ -241,7 +238,6 @@ public class Activator extends AbstractE
             this.bundle = bundle;
         }
 
-        @Override
         public void start()
         {
             boolean acquired = false;
@@ -269,7 +265,6 @@ public class Activator extends AbstractE
             }
         }
 
-        @Override
         public void destroy()
         {
             boolean acquired = false;
@@ -464,13 +459,4 @@ public class Activator extends AbstractE
             }
         }
     }
-
-    @Override
-    protected void error(final String msg, final Throwable t)
-    {
-        if ( logger.isLogEnabled(LogService.LOG_ERROR) )
-        {
-            logger.log( LogService.LOG_ERROR, msg, t );
-        }
-    }
 }
\ No newline at end of file

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java?rev=1814712&r1=1814711&r2=1814712&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java Thu Nov  9 10:20:57 2017
@@ -46,7 +46,6 @@ import org.apache.felix.scr.impl.manager
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.TargetedPID;
 import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ConfigurationAdmin;
@@ -458,48 +457,6 @@ public class ComponentRegistry
 
     //---------- Helper method
 
-    /**
-     * Returns <code>true</code> if the <code>bundle</code> is to be considered
-     * active from the perspective of declarative services.
-     * <p>
-     * As of R4.1 a bundle may have lazy activation policy which means a bundle
-     * remains in the STARTING state until a class is loaded from that bundle
-     * (unless that class is declared to not cause the bundle to start). And
-     * thus for DS 1.1 this means components are to be loaded for lazily started
-     * bundles being in the STARTING state (after the LAZY_ACTIVATION event) has
-     * been sent.  Hence DS must consider a bundle active when it is really
-     * active and when it is a lazily activated bundle in the STARTING state.
-     *
-     * @param bundle The bundle check
-     * @return <code>true</code> if <code>bundle</code> is not <code>null</code>
-     *          and the bundle is either active or has lazy activation policy
-     *          and is in the starting state.
-     *
-     * @see <a href="https://issues.apache.org/jira/browse/FELIX-1666">FELIX-1666</a>
-     */
-    static boolean isBundleActive( final Bundle bundle )
-    {
-        if ( bundle != null )
-        {
-            if ( bundle.getState() == Bundle.ACTIVE )
-            {
-                return true;
-            }
-
-            if ( bundle.getState() == Bundle.STARTING )
-            {
-                // according to the spec the activationPolicy header is only
-                // set to request a bundle to be lazily activated. So in this
-                // simple check we just verify the header is set to assume
-                // the bundle is considered a lazily activated bundle
-                return bundle.getHeaders("").get(Constants.BUNDLE_ACTIVATIONPOLICY) != null;
-            }
-        }
-
-        // fall back: bundle is not considered active
-        return false;
-    }
-
     private final ThreadLocal<List<ServiceReference<?>>> circularInfos = new ThreadLocal<List<ServiceReference<?>>> ()
     {
 

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java?rev=1814712&r1=1814711&r2=1814712&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java Thu Nov  9 10:20:57 2017
@@ -58,6 +58,7 @@ public class ScrCommand implements ScrIn
 
     private static final Comparator<ComponentDescriptionDTO> DESCRIPTION_COMP = new Comparator<ComponentDescriptionDTO>()
     {
+        @Override
         public int compare(final ComponentDescriptionDTO c1, final ComponentDescriptionDTO c2)
         {
             final long bundleId1 = c1.bundle.id;
@@ -85,6 +86,7 @@ public class ScrCommand implements ScrIn
 
     private static final Comparator<ComponentConfigurationDTO> CONFIGURATION_COMP = new Comparator<ComponentConfigurationDTO>()
     {
+        @Override
         public int compare(final ComponentConfigurationDTO c1, final ComponentConfigurationDTO c2)
         {
             return Long.signum(c1.id - c2.id);
@@ -124,7 +126,7 @@ public class ScrCommand implements ScrIn
         try
         {
             final ScrGogoCommand gogoCmd = new ScrGogoCommand(this);
-            final Hashtable<String, Object> props = new Hashtable<String, Object>();
+            final Hashtable<String, Object> props = new Hashtable<>();
             props.put("osgi.command.scope", "scr");
             props.put("osgi.command.function", new String[]
                 { "config", "disable", "enable", "info", "list" });
@@ -144,7 +146,7 @@ public class ScrCommand implements ScrIn
         {
             // Register "scr" impl command service as a
             // wrapper for the bundle repository service.
-            final Hashtable<String, Object> props = new Hashtable<String, Object>();
+            final Hashtable<String, Object> props = new Hashtable<>();
             props.put(Constants.SERVICE_DESCRIPTION, "SCR Legacy Shell Support");
             props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
             shellReg = bundleContext.registerService(org.apache.felix.shell.Command.class, new ScrShellCommand(this),
@@ -179,7 +181,7 @@ public class ScrCommand implements ScrIn
         {
             if ( reg == null )
             {
-                final Hashtable<String, Object> props = new Hashtable<String, Object>();
+                final Hashtable<String, Object> props = new Hashtable<>();
                 props.put(Constants.SERVICE_DESCRIPTION, "SCR Info service");
                 props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
                 reg = bundleContext.registerService( ScrInfo.class, this, props );
@@ -195,12 +197,55 @@ public class ScrCommand implements ScrIn
         }
     }
 
+    /**
+     * Returns <code>true</code> if the <code>bundle</code> is to be considered
+     * active from the perspective of declarative services.
+     * <p>
+     * As of R4.1 a bundle may have lazy activation policy which means a bundle
+     * remains in the STARTING state until a class is loaded from that bundle
+     * (unless that class is declared to not cause the bundle to start). And
+     * thus for DS 1.1 this means components are to be loaded for lazily started
+     * bundles being in the STARTING state (after the LAZY_ACTIVATION event) has
+     * been sent.  Hence DS must consider a bundle active when it is really
+     * active and when it is a lazily activated bundle in the STARTING state.
+     *
+     * @param bundle The bundle check
+     * @return <code>true</code> if <code>bundle</code> is not <code>null</code>
+     *          and the bundle is either active or has lazy activation policy
+     *          and is in the starting state.
+     *
+     * @see <a href="https://issues.apache.org/jira/browse/FELIX-1666">FELIX-1666</a>
+     */
+    private static boolean isBundleActive( final Bundle bundle )
+    {
+        if ( bundle != null )
+        {
+            if ( bundle.getState() == Bundle.ACTIVE )
+            {
+                return true;
+            }
+
+            if ( bundle.getState() == Bundle.STARTING )
+            {
+                // according to the spec the activationPolicy header is only
+                // set to request a bundle to be lazily activated. So in this
+                // simple check we just verify the header is set to assume
+                // the bundle is considered a lazily activated bundle
+                return bundle.getHeaders("").get(Constants.BUNDLE_ACTIVATIONPOLICY) != null;
+            }
+        }
+
+        // fall back: bundle is not considered active
+        return false;
+    }
+
     /* (non-Javadoc)
      * @see org.apache.felix.scr.impl.ScrInfo#list(java.lang.String, java.io.PrintStream, java.io.PrintStream)
      */
+    @Override
     public void list(final String bundleIdentifier, final PrintWriter out)
     {
-        final List<ComponentDescriptionDTO> descriptions = new ArrayList<ComponentDescriptionDTO>();
+        final List<ComponentDescriptionDTO> descriptions = new ArrayList<>();
 
         if (bundleIdentifier != null)
         {
@@ -228,7 +273,7 @@ public class ScrCommand implements ScrIn
             {
                 throw new IllegalArgumentException("Missing bundle with ID " + bundleIdentifier);
             }
-            if (ComponentRegistry.isBundleActive(bundle))
+            if (isBundleActive(bundle))
             {
                 descriptions.addAll(scrService.getComponentDescriptionDTOs(bundle));
                 if (descriptions.isEmpty())
@@ -260,7 +305,7 @@ public class ScrCommand implements ScrIn
         for(final ComponentDescriptionDTO desc : descriptions)
         {
             out.println( String.format( " [%1$4d]   %2$s  %3$s", desc.bundle.id, desc.name, desc.defaultEnabled ? "enabled" : "disabled" ) );
-            final List<ComponentConfigurationDTO> configs = new ArrayList<ComponentConfigurationDTO>(this.scrService.getComponentConfigurationDTOs(desc));
+            final List<ComponentConfigurationDTO> configs = new ArrayList<>(this.scrService.getComponentConfigurationDTOs(desc));
             Collections.sort( configs, CONFIGURATION_COMP);
             for ( final ComponentConfigurationDTO component : configs )
             {
@@ -287,6 +332,7 @@ public class ScrCommand implements ScrIn
     /**
      * @see org.apache.felix.scr.impl.ScrInfo#info(java.lang.String, java.io.PrintStream, java.io.PrintStream)
      */
+    @Override
     public void info(final String componentId, final PrintWriter out)
     {
         final Result result = getComponentsFromArg(componentId, false);
@@ -402,7 +448,7 @@ public class ScrCommand implements ScrIn
             	{
             		out.println("  (No Component Configurations)");
             	}
-            	else 
+            	else
             	{
             		for (final ComponentConfigurationDTO cc: componentConfigurationDTOs)
             		{
@@ -423,7 +469,7 @@ public class ScrCommand implements ScrIn
             out.print( prefix );
             out.print( label );
             out.println( " Properties:" );
-            TreeMap<String, Object> keys = new TreeMap<String, Object>( props );
+            TreeMap<String, Object> keys = new TreeMap<>( props );
             for ( Entry<String, Object> entry: keys.entrySet() )
             {
                 out.print( prefix );
@@ -546,6 +592,7 @@ public class ScrCommand implements ScrIn
     /**
      * @see org.apache.felix.scr.impl.ScrInfo#config(java.io.PrintStream)
      */
+    @Override
     public void config(final PrintWriter out)
     {
         out.print("Log Level: ");
@@ -584,7 +631,7 @@ public class ScrCommand implements ScrIn
     }
 
     private static final class Result {
-        public List<ComponentDescriptionDTO> components = new ArrayList<ComponentDescriptionDTO>();
+        public List<ComponentDescriptionDTO> components = new ArrayList<>();
         public ComponentConfigurationDTO configuration;
     }