Hello,

I've been using Karaf in a development setup for it's hot deployment.
During my coding, I noticed a few annoyances in the File Install
component and set out to fix those.


I've attached a patch ("fileinstall-lognstartlvl.patch") which changes
the following things:

- By default, the component produces no log output. I would expect
that errors are important enough that they should be offered to the
logging system, hence I changed DirectoryWatcher to default to
LOG_ERROR.
- If a Configuration from the config-admin contains no log settings, I
altered the code to use the global log level as a default. Vice versa,
a Configuration can still override the global log level.
- Stuff like corrupt bundles may simply go unnoticed because those are
logged as warnings. I've altered the logging level for non-recoverable
situations to see everything of interest as an error.
- When I configured the "felix.fileinstall.start.level" setting, the
component wouldn't run update or refresh when the framework's start
level is too low. I've introduced a new setting
"felix.fileinstall.active.level" to configure the scan behaviour, e.g.
so you can set it higher than the system bundle start-level so that
the framework bundles resolve first. By default, the file install
component now always updates, irregardless of the
"felix.fileinstall.start.level" setting.
- The bundle start level is now only set when a bundle is installed
and not every time a bundle gets restarted. I'd expect that a user
should be able to override the bundle start level instead of it being
reset each time the file install component triggers a bundle start.

The logging stuff is filed in issue
https://issues.apache.org/jira/browse/FELIX-3373 , whereas the start
level stuff is filed as
https://issues.apache.org/jira/browse/FELIX-3346 .


Due to my changes, the tests started to fail. I added some code to the
setup method so that the bundle context expects certain getProperty
calls.
While I was at it, I've also updated them to use the EasyMock 2 API -
now they no longer show those annoying deprecated warnings in Eclipse.
The second patch ("fileinstall-easymock2.patch") includes these changes.


Both patches are made against the trunk version. For the record, my
ICLA recently got filed with the Apache foundation, and I agree to
release these changes under the ASL v2.

If there are any comments after reviewing both patch files, just let me know.


With best regards,

Bert Jacobs
Index: src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java
===================================================================
--- src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java	(revision 1299274)
+++ src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java	(working copy)
@@ -54,6 +54,7 @@
 import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
 import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.startlevel.StartLevel;
 
 /**
  * -DirectoryWatcher-
@@ -92,6 +93,7 @@
     public final static String NO_INITIAL_DELAY = "felix.fileinstall.noInitialDelay";
     public final static String DISABLE_CONFIG_SAVE = "felix.fileinstall.disableConfigSave";
     public final static String START_LEVEL = "felix.fileinstall.start.level";
+    public final static String ACTIVE_LEVEL = "felix.fileinstall.active.level";
 
     static final SecureRandom random = new SecureRandom();
 
@@ -110,6 +112,7 @@
     String originatingFileName;
     boolean noInitialDelay;
     int startLevel;
+    int activeLevel;
 
     // Map of all installed artifacts
     Map/* <File, Artifact> */ currentManagedArtifacts = new HashMap/* <File, Artifact> */();
@@ -129,7 +132,7 @@
         this.properties = properties;
         this.context = context;
         poll = getLong(properties, POLL, 2000);
-        logLevel = getInt(properties, LOG_LEVEL, 0);
+        logLevel = getInt(properties, LOG_LEVEL, Util.getGlobalLogLevel(context));
         originatingFileName = (String) properties.get(FILENAME);
         watchedDirectory = getFile(properties, DIR, new File("./load"));
         verifyWatchedDir();
@@ -141,6 +144,7 @@
         filter = (String) properties.get(FILTER);
         noInitialDelay = getBoolean(properties, NO_INITIAL_DELAY, false);
         startLevel = getInt(properties, START_LEVEL, 0);    // by default, do not touch start level
+        activeLevel = getInt(properties, ACTIVE_LEVEL, 0);    // by default, always scan
         this.context.addBundleListener(this);
 
         FilenameFilter flt;
@@ -259,8 +263,8 @@
         {
             try
             {
-                // Waiting for start level
-                if (FileInstall.getStartLevel().getStartLevel() >= startLevel)
+                // Don't access the disk when the framework is still in a startup phase.
+                if (FileInstall.getStartLevel().getStartLevel() >= activeLevel)
                 {
                     Set/*<File>*/ files = scanner.scan(false);
                     // Check that there is a result.  If not, this means that the directory can not be listed,
@@ -368,7 +372,8 @@
                     }
                     catch (IOException e)
                     {
-                        log(Logger.LOG_WARNING,
+                        // Notify user of problem, won't retry until the dir is updated.
+                        log(Logger.LOG_ERROR,
                             "Unable to create jar for: " + file.getAbsolutePath(), e);
                         continue;
                     }
@@ -458,7 +463,7 @@
             refresh();
         }
 
-        if (startBundles || startLevel != 0)
+        if (startBundles)
         {
             // Try to start all the bundles that are not persistently stopped
             processAllBundles();
@@ -935,7 +940,7 @@
         }
         catch (Exception e)
         {
-            log(Logger.LOG_WARNING, "Failed to install artifact: " + path, e);
+            log(Logger.LOG_ERROR, "Failed to install artifact: " + path, e);
 
             // Add it our bad jars list, so that we don't
             // attempt to install it again and again until the underlying
@@ -988,6 +993,13 @@
         is.reset();
         Bundle b = context.installBundle(bundleLocation, is);
         Util.storeChecksum(b, checksum, context);
+        
+        // Change startLevel for bundle only once.
+        if (startLevel != 0)
+        {
+            FileInstall.getStartLevel().setBundleStartLevel(b, startLevel);
+        }
+        
         return b;
     }
 
@@ -1164,18 +1176,15 @@
 
     private void process(Bundle bundle)
     {
-        // Change startLevel for bundle
-        if (startLevel != 0)
+        StartLevel startLevelSvc = FileInstall.getStartLevel();
+        // Fragments can never be started.
+        // Bundles can only be started transient when the start level of the framework is high
+        // enough. Persistent (i.e. non-transient) starts will simply make the framework start the
+        // bundle when the start level is high enough.
+        if (!isFragment(bundle) && startBundles
+                && ( ! useStartTransient
+                     || startLevelSvc.getStartLevel() >= startLevelSvc.getBundleStartLevel(bundle)))
         {
-            FileInstall.getStartLevel().setBundleStartLevel(bundle, startLevel);
-        }
-
-        // Fragments can not be started.
-        // No need to check status of bundles
-        // before starting, because OSGi treats this
-        // as a noop when the bundle is already started
-        if (!isFragment(bundle) && startBundles)
-        {
             try
             {
                 int options = useStartTransient ? Bundle.START_TRANSIENT : 0;
@@ -1185,6 +1194,7 @@
             }
             catch (BundleException e)
             {
+                // Don't log this as an error, instead we start the bundle repeatedly.
                 log(Logger.LOG_WARNING, "Error while starting bundle: " + bundle.getLocation(), e);
             }
         }
Index: src/main/java/org/apache/felix/fileinstall/internal/Scanner.java
===================================================================
--- src/main/java/org/apache/felix/fileinstall/internal/Scanner.java	(revision 1299274)
+++ src/main/java/org/apache/felix/fileinstall/internal/Scanner.java	(working copy)
@@ -21,7 +21,6 @@
 import java.io.File;
 import java.io.FilenameFilter;
 import java.io.IOException;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
Index: src/main/java/org/apache/felix/fileinstall/internal/Util.java
===================================================================
--- src/main/java/org/apache/felix/fileinstall/internal/Util.java	(revision 1299274)
+++ src/main/java/org/apache/felix/fileinstall/internal/Util.java	(working copy)
@@ -27,10 +27,6 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.Set;
 import java.util.jar.JarFile;
 import java.util.jar.JarOutputStream;
@@ -47,6 +43,11 @@
 {
     private static final String CHECKSUM_SUFFIX = ".checksum";
 
+    /**
+     * Returns the log level as defined in the BundleContext or System properties.
+     * @param context {@link BundleContext} of the FileInstall bundle.
+     * @return the global log level, or {@link Logger#LOG_ERROR}.
+     */
     public static int getGlobalLogLevel(BundleContext context)
     {
         String s = (String) context.getProperty(DirectoryWatcher.LOG_LEVEL);
@@ -54,7 +55,7 @@
             ? System.getProperty(DirectoryWatcher.LOG_LEVEL.toUpperCase().replace('.', '_'))
             : s;
         s = (s == null) ? "1" : s;
-        int logLevel = 1;
+        int logLevel = Logger.LOG_ERROR;
         try
         {
             logLevel = Integer.parseInt(s);
Index: src/test/java/org/apache/felix/fileinstall/internal/ConfigInstallerTest.java
===================================================================
--- src/test/java/org/apache/felix/fileinstall/internal/ConfigInstallerTest.java	(revision 1299274)
+++ src/test/java/org/apache/felix/fileinstall/internal/ConfigInstallerTest.java	(working copy)
@@ -19,50 +19,40 @@
 package org.apache.felix.fileinstall.internal;
 
 import java.io.File;
-import java.util.Hashtable;
 import java.util.Dictionary;
+import java.util.Hashtable;
 
 import junit.framework.TestCase;
-import org.easymock.MockControl;
-import org.easymock.ArgumentsMatcher;
-import org.osgi.framework.BundleContext;
+
+import org.easymock.EasyMock;
+import org.easymock.IArgumentMatcher;
 import org.osgi.framework.Bundle;
-import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.framework.BundleContext;
 import org.osgi.service.cm.Configuration;
-import org.apache.felix.fileinstall.internal.ConfigInstaller;
-import org.apache.felix.fileinstall.internal.FileInstall;
+import org.osgi.service.cm.ConfigurationAdmin;
 
 /**
  * Tests for ConfigInstaller
  */
 public class ConfigInstallerTest extends TestCase {
 
-    MockControl mockBundleContextControl;
     BundleContext mockBundleContext;
-    MockControl mockBundleControl;
     Bundle mockBundle;
-    MockControl mockConfigurationAdminControl;
     ConfigurationAdmin mockConfigurationAdmin;
-    MockControl mockConfigurationControl;
     Configuration mockConfiguration;
 
     protected void setUp() throws Exception
     {
-        super.setUp();
-        mockBundleContextControl = MockControl.createControl( BundleContext.class );
-        mockBundleContext = ( BundleContext ) mockBundleContextControl.getMock();
-        mockBundleControl = MockControl.createControl( Bundle.class );
-        mockBundle = ( Bundle ) mockBundleControl.getMock();
-        mockConfigurationAdminControl = MockControl.createControl( ConfigurationAdmin.class );
-        mockConfigurationAdmin = ( ConfigurationAdmin ) mockConfigurationAdminControl.getMock();
-        mockConfigurationControl = MockControl.createControl( Configuration.class );
-        mockConfiguration = ( Configuration ) mockConfigurationControl.getMock();
+        super.setUp();
+        mockBundleContext = (BundleContext) EasyMock.createMock(BundleContext.class);
+        mockBundle = ( Bundle ) EasyMock.createMock(Bundle.class);
+        mockConfigurationAdmin = ( ConfigurationAdmin ) EasyMock.createMock(ConfigurationAdmin.class);
+        mockConfiguration = ( Configuration ) EasyMock.createMock(Configuration.class);
     }
 
 
     public void testParsePidWithoutFactoryPid()
     {
-        mockBundleContextControl.replay();
         ConfigInstaller ci = new ConfigInstaller(null, null);
 
         String path = "pid.cfg";
@@ -73,136 +63,109 @@
 
     public void testParsePidWithFactoryPid()
     {
-        mockBundleContextControl.replay();
         ConfigInstaller ci = new ConfigInstaller(null, null);
 
         String path = "factory-pid.cfg";
         assertEquals( "Pid with Factory Pid calculated", "factory", ci.parsePid( path )[0] );
         assertEquals( "Pid with Factory Pid calculated", "pid", ci.parsePid( path )[1] );
-    }
+    }
+    
 
     public void testGetNewFactoryConfiguration() throws Exception
     {
-        mockConfigurationControl.replay();
-        mockConfigurationAdmin.listConfigurations( null );
-        mockConfigurationAdminControl.setMatcher( MockControl.ALWAYS_MATCHER );
-        mockConfigurationAdminControl.setReturnValue( null );
-        mockConfigurationAdmin.createFactoryConfiguration( "pid", null );
-        mockConfigurationAdminControl.setReturnValue( mockConfiguration );
-        mockConfigurationAdminControl.replay();
-        mockBundleContextControl.replay();
+        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
+            .andReturn(null);
+        EasyMock.expect(mockConfigurationAdmin.createFactoryConfiguration( "pid", null ))
+            .andReturn(mockConfiguration);
+        EasyMock.replay(new Object[]{mockConfiguration, mockConfigurationAdmin, mockBundleContext});
 
         ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin );
 
-        assertEquals( "Factory configuration retrieved", mockConfiguration, ci.getConfiguration( "pid-factoryPid.cfg", "pid", "factoryPid" ) );
+        assertEquals( "Factory configuration retrieved", mockConfiguration,
+                ci.getConfiguration( "pid-factoryPid.cfg", "pid", "factoryPid" ) );
 
-        mockConfigurationAdminControl.verify();
-        mockConfigurationControl.verify();
-        mockBundleContextControl.verify();
+        EasyMock.verify(new Object[]{mockConfiguration, mockConfigurationAdmin, mockBundleContext});
     }
 
-
+
     public void testGetExistentFactoryConfiguration() throws Exception
     {
-        mockConfigurationControl.replay();
-        mockConfigurationAdmin.listConfigurations( null );
-        mockConfigurationAdminControl.setMatcher( MockControl.ALWAYS_MATCHER );
-        mockConfigurationAdminControl.setReturnValue( null );
-        mockConfigurationAdmin.createFactoryConfiguration( "pid", null );
-        mockConfigurationAdminControl.setReturnValue( mockConfiguration );
-        mockConfigurationAdminControl.replay();
-        mockBundleContextControl.replay();
+        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
+                .andReturn(null);
+        EasyMock.expect(mockConfigurationAdmin.createFactoryConfiguration( "pid", null ))
+                .andReturn(mockConfiguration);
+        EasyMock.replay(new Object[]{mockConfiguration, mockConfigurationAdmin, mockBundleContext});
 
         ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin );
 
-        assertEquals( "Factory configuration retrieved", mockConfiguration, ci.getConfiguration( "pid-factoryPid.cfg","pid", "factoryPid" ) );
+        assertEquals( "Factory configuration retrieved", mockConfiguration,
+                ci.getConfiguration( "pid-factoryPid.cfg","pid", "factoryPid" ) );
 
-        mockConfigurationAdminControl.verify();
-        mockConfigurationControl.verify();
-        mockBundleContextControl.verify();
+        EasyMock.verify(new Object[]{mockConfiguration, mockConfigurationAdmin, mockBundleContext});
     }
-
-
+
+    
     public void testGetExistentNoFactoryConfiguration() throws Exception
     {
-        mockConfigurationControl.replay();
-        mockConfigurationAdmin.listConfigurations( null );
-        mockConfigurationAdminControl.setMatcher( MockControl.ALWAYS_MATCHER );
-        mockConfigurationAdminControl.setReturnValue( null );
-        mockConfigurationAdmin.getConfiguration( "pid", null );
-        mockConfigurationAdminControl.setReturnValue( mockConfiguration );
-        mockConfigurationAdminControl.replay();
-        mockBundleContextControl.replay();
+        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
+                .andReturn(null);
+        EasyMock.expect(mockConfigurationAdmin.getConfiguration( "pid", null ))
+                .andReturn(mockConfiguration);
+        EasyMock.replay(new Object[]{mockConfiguration, mockConfigurationAdmin, mockBundleContext});
 
         ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin );
 
         assertEquals( "Factory configuration retrieved", mockConfiguration, ci.getConfiguration( "pid.cfg", "pid", null ) );
 
-        mockConfigurationAdminControl.verify();
-        mockConfigurationControl.verify();
-        mockBundleContextControl.verify();
+        EasyMock.verify(new Object[]{mockConfiguration, mockConfigurationAdmin, mockBundleContext});
     }
 
 
     public void testDeleteConfig() throws Exception
     {
         mockConfiguration.delete();
-        mockConfigurationControl.replay();
-        mockConfigurationAdmin.listConfigurations( null );
-        mockConfigurationAdminControl.setMatcher( MockControl.ALWAYS_MATCHER );
-        mockConfigurationAdminControl.setReturnValue( null );
-        mockConfigurationAdmin.getConfiguration( "pid", null );
-        mockConfigurationAdminControl.setReturnValue( mockConfiguration );
-        mockConfigurationAdminControl.replay();
-        mockBundleContextControl.replay();
+        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
+                .andReturn(null);
+        EasyMock.expect(mockConfigurationAdmin.getConfiguration("pid", null ))
+                .andReturn(mockConfiguration);
+        EasyMock.replay(new Object[]{mockConfiguration, mockConfigurationAdmin, mockBundleContext});
 
         ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin );
 
-        assertTrue( ci.deleteConfig( new File( "pid.cfg" ) ) );
+        assertTrue(ci.deleteConfig(new File( "pid.cfg")));
 
-        mockConfigurationAdminControl.verify();
-        mockConfigurationControl.verify();
-        mockBundleContextControl.verify();
+        EasyMock.verify(new Object[]{mockConfiguration, mockConfigurationAdmin, mockBundleContext});
     }
 
 
     public void testSetConfiguration() throws Exception
-    {
-        mockConfiguration.getBundleLocation();
-        mockConfigurationControl.setReturnValue( null );
-        mockConfiguration.getProperties();
-        mockConfigurationControl.setReturnValue( new Hashtable() );
-        mockConfiguration.update( new Hashtable() );
-        mockConfigurationControl.setMatcher( new ArgumentsMatcher()
+    {
+        EasyMock.expect(mockConfiguration.getBundleLocation()).andReturn(null);
+        EasyMock.expect(mockConfiguration.getProperties()).andReturn(new Hashtable());
+        EasyMock.reportMatcher(new IArgumentMatcher()
         {
-            public boolean matches( Object[] expected, Object[] actual )
+            public boolean matches(Object argument)
             {
-                return ( actual.length == 1 ) && ( (Dictionary) actual[0] ).get( "testkey" ).equals( "testvalue" );
+                return ((Dictionary) argument).get("testkey").equals("testvalue");
+            }
+            
+            
+            public void appendTo(StringBuffer buffer)
+            {
+                buffer.append("<Dictionary check: testkey present?>");
             }
+        });
+        mockConfiguration.update(new Hashtable());
+        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
+                .andReturn(null);
+        EasyMock.expect(mockConfigurationAdmin.getConfiguration("firstcfg", null))
+                .andReturn(mockConfiguration);
+        EasyMock.replay(new Object[]{mockConfiguration, mockConfigurationAdmin, mockBundleContext});
 
-
-            public String toString( Object[] arg0 )
-            {
-                return arg0.toString();
-            }
-        } );
-        mockConfigurationControl.replay();
-        mockConfigurationAdmin.listConfigurations( null );
-        mockConfigurationAdminControl.setMatcher( MockControl.ALWAYS_MATCHER );
-        mockConfigurationAdminControl.setReturnValue( null );
-        mockConfigurationAdmin.getConfiguration( "firstcfg", null );
-        mockConfigurationAdminControl.setReturnValue( mockConfiguration );
-        mockConfigurationAdminControl.replay();
-        mockBundleContextControl.replay();
-
         ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin );
 
         assertTrue( ci.setConfig( new File( "src/test/resources/watched/firstcfg.cfg" ) ) );
 
-        mockConfigurationAdminControl.verify();
-        mockConfigurationControl.verify();
-        mockBundleContextControl.verify();
+        EasyMock.verify(new Object[]{mockConfiguration, mockConfigurationAdmin, mockBundleContext});
     }
-
-
 }
Index: src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java
===================================================================
--- src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java	(revision 1299274)
+++ src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java	(working copy)
@@ -25,10 +25,11 @@
 
 import junit.framework.TestCase;
 
-import org.easymock.MockControl;
+import org.easymock.EasyMock;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleListener;
+import org.osgi.service.log.LogService;
 import org.osgi.service.packageadmin.PackageAdmin;
 
 
@@ -41,66 +42,76 @@
     private final static String TEST = "test.key";
     Dictionary props = new Hashtable();
     DirectoryWatcher dw;
-    MockControl mockBundleContextControl;
     BundleContext mockBundleContext;
-    MockControl mockPackageAdminControl;
     PackageAdmin mockPackageAdmin;
-    MockControl mockBundleControl;
     Bundle mockBundle;
 
 
     protected void setUp() throws Exception
     {
         super.setUp();
-        mockBundleContextControl = MockControl.createControl( BundleContext.class );
-        mockBundleContext = ( BundleContext ) mockBundleContextControl.getMock();
-        mockPackageAdminControl = MockControl.createControl( PackageAdmin.class );
-        mockPackageAdmin = ( PackageAdmin ) mockPackageAdminControl.getMock();
-        mockBundleControl = MockControl.createControl( Bundle.class );
-        mockBundle = ( Bundle ) mockBundleControl.getMock();
-        props.put( DirectoryWatcher.DIR, new File( "target/load" ).getAbsolutePath() );
+        mockBundleContext = (BundleContext) EasyMock.createMock(BundleContext.class);
+        mockPackageAdmin = (PackageAdmin) EasyMock.createMock(PackageAdmin.class);
+        mockBundle = (Bundle) EasyMock.createMock(Bundle.class);
+        props.put( DirectoryWatcher.DIR, new File( "target/load" ).getAbsolutePath() );
+        
+        // Might get called, but most of the time it doesn't matter whether they do or don't.
+        EasyMock.expect(mockBundleContext.getProperty(DirectoryWatcher.LOG_LEVEL))
+                .andStubReturn(null);
+        EasyMock.expect(mockBundleContext.getServiceReference(LogService.class.getName()))
+                .andStubReturn(null);
     }
+
 
-
     public void testGetLongWithNonExistentProperty()
     {
-        mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
-        mockBundleContextControl.replay();
-        dw = new DirectoryWatcher( props, mockBundleContext );
+        mockBundleContext.addBundleListener((BundleListener) EasyMock.anyObject());
+        EasyMock.replay(new Object[]{mockBundleContext});
+        
+        dw = new DirectoryWatcher( props, mockBundleContext );
+        
         assertEquals( "getLong gives the default value for non-existing properties", 100, dw.getLong( props, TEST, 100 ) );
+        EasyMock.verify(new Object[]{mockBundleContext});
     }
-
-
+
+    
     public void testGetLongWithExistentProperty()
     {
         props.put( TEST, "33" );
 
         mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
-        mockBundleContextControl.replay();
-        dw = new DirectoryWatcher( props, mockBundleContext );
+        EasyMock.replay(new Object[]{mockBundleContext});
+        
+        dw = new DirectoryWatcher( props, mockBundleContext );
+        
         assertEquals( "getLong retrieves the right property value", 33, dw.getLong( props, TEST, 100 ) );
+        EasyMock.verify(new Object[]{mockBundleContext});
     }
-
-
+
+    
     public void testGetLongWithIncorrectValue()
     {
         props.put( TEST, "incorrect" );
 
         mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
-        mockBundleContext.getServiceReference( "org.osgi.service.log.LogService" );
-        mockBundleContextControl.setReturnValue( null );
-        mockBundleContextControl.replay();
-        dw = new DirectoryWatcher( props, mockBundleContext );
+        EasyMock.replay(new Object[]{mockBundleContext});
+        
+        dw = new DirectoryWatcher( props, mockBundleContext );
+        
         assertEquals( "getLong retrieves the right property value", 100, dw.getLong( props, TEST, 100 ) );
+        EasyMock.verify(new Object[]{mockBundleContext});
     }
-
-
+
+    
     public void testGetBooleanWithNonExistentProperty()
     {
         mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
-        mockBundleContextControl.replay();
-        dw = new DirectoryWatcher( props, mockBundleContext );
+        EasyMock.replay(new Object[]{mockBundleContext});
+        
+        dw = new DirectoryWatcher( props, mockBundleContext );
+        
         assertEquals( "getBoolean gives the default value for non-existing properties", true, dw.getBoolean( props, TEST, true ) );
+        EasyMock.verify(new Object[]{mockBundleContext});
     }
 
 
@@ -109,9 +120,12 @@
         props.put( TEST, "true" );
 
         mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
-        mockBundleContextControl.replay();
-        dw = new DirectoryWatcher( props, mockBundleContext );
+        EasyMock.replay(new Object[]{mockBundleContext});
+        
+        dw = new DirectoryWatcher( props, mockBundleContext );
+        
         assertEquals( "getBoolean retrieves the right property value", true, dw.getBoolean( props, TEST, false ) );
+        EasyMock.verify(new Object[]{mockBundleContext});
     }
 
 
@@ -119,21 +133,25 @@
     {
         props.put( TEST, "incorrect" );
 
-        mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
-        mockBundleContext.getServiceReference( "org.osgi.service.log.LogService" );
-        mockBundleContextControl.setReturnValue( null );
-        mockBundleContextControl.replay();
-        dw = new DirectoryWatcher( props, mockBundleContext );
-        assertEquals( "getBoolean retrieves the right property value", false, dw.getBoolean( props, TEST, true ) );
+        mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
+        EasyMock.replay(new Object[]{mockBundleContext});
+        
+        dw = new DirectoryWatcher( props, mockBundleContext );
+        
+        assertEquals( "getBoolean retrieves the right property value", false, dw.getBoolean( props, TEST, true ) );
+        EasyMock.verify(new Object[]{mockBundleContext});
     }
 
 
     public void testGetFileWithNonExistentProperty()
     {
         mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
-        mockBundleContextControl.replay();
-        dw = new DirectoryWatcher( props, mockBundleContext );
-        assertEquals( "getFile gives the default value for non-existing properties", new File("tmp"), dw.getFile( props, TEST, new File("tmp") ) );
+        EasyMock.replay(new Object[]{mockBundleContext});
+        
+        dw = new DirectoryWatcher( props, mockBundleContext );
+        
+        assertEquals( "getFile gives the default value for non-existing properties", new File("tmp"), dw.getFile( props, TEST, new File("tmp") ) );
+        EasyMock.verify(new Object[]{mockBundleContext});        
     }
 
 
@@ -142,9 +160,12 @@
         props.put( TEST, "test" );
 
         mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
-        mockBundleContextControl.replay();
-        dw = new DirectoryWatcher( props, mockBundleContext );
+        EasyMock.replay(new Object[]{mockBundleContext});
+        
+        dw = new DirectoryWatcher( props, mockBundleContext );
+        
         assertEquals( "getBoolean retrieves the right property value", new File("test"), dw.getFile( props, TEST, new File("tmp") ) );
+        EasyMock.verify(new Object[]{mockBundleContext});
     }
 
 
@@ -158,7 +179,8 @@
         props.put( DirectoryWatcher.FILTER, ".*\\.cfg" );
 
         mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
-        mockBundleContextControl.replay();
+        EasyMock.replay(new Object[]{mockBundleContext});
+        
         dw = new DirectoryWatcher( props, mockBundleContext );
 
         assertEquals( "POLL parameter correctly read", 500l, dw.poll );
@@ -169,6 +191,7 @@
             "src" + File.separatorChar + "test" + File.separatorChar + "resources" ) );
         assertEquals( "START_NEW_BUNDLES parameter correctly read", false, dw.startBundles );
         assertEquals( "FILTER parameter correctly read", ".*\\.cfg", dw.filter );
+        EasyMock.verify(new Object[]{mockBundleContext});
     }
 
 
@@ -177,40 +200,51 @@
         props.put( DirectoryWatcher.DIR, new File( "src/test/resources" ).getAbsolutePath() );
 
         mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
-        mockBundleContextControl.replay();
+        EasyMock.replay(new Object[]{mockBundleContext});
+        
         dw = new DirectoryWatcher( props, mockBundleContext );
 
         assertTrue( "DIR parameter correctly read", dw.watchedDirectory.getAbsolutePath().endsWith(
             "src" + File.separatorChar + "test" + File.separatorChar + "resources" ) );
         assertEquals( "Default POLL parameter correctly read", 2000l, dw.poll );
-        assertEquals( "Default LOG_LEVEL parameter correctly read", 0, dw.logLevel );
+        assertEquals( "Default LOG_LEVEL parameter correctly read", 1, dw.logLevel );
         assertTrue( "Default TMPDIR parameter correctly read", dw.tmpDir.getAbsolutePath().startsWith(
                 new File(System.getProperty("java.io.tmpdir")).getAbsolutePath()) );
         assertEquals( "Default START_NEW_BUNDLES parameter correctly read", true, dw.startBundles );
-        assertEquals( "Default FILTER parameter correctly read", null, dw.filter );
+        assertEquals( "Default FILTER parameter correctly read", null, dw.filter );
+        EasyMock.verify(new Object[]{mockBundleContext});        
     }
 
 
     public void testIsFragment() throws Exception
     {
         mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
-        mockBundleContext.createFilter( "" );
-        mockBundleContextControl.setMatcher( MockControl.ALWAYS_MATCHER );
-        mockBundleContextControl.setReturnValue( null );
-        mockBundleContextControl.replay();
-        mockPackageAdmin.getBundleType( mockBundle );
-        mockPackageAdminControl.setReturnValue( new Long(PackageAdmin.BUNDLE_TYPE_FRAGMENT) );
-        mockPackageAdminControl.replay();
-        mockBundleControl.replay();
+        EasyMock.expect(mockBundleContext.createFilter((String) EasyMock.anyObject()))
+                .andReturn(null);
+        EasyMock.expect(Integer.valueOf(mockPackageAdmin.getBundleType(mockBundle)))
+                .andReturn(new Long(PackageAdmin.BUNDLE_TYPE_FRAGMENT) );
+        EasyMock.replay(new Object[]{mockBundleContext, mockPackageAdmin, mockBundle});
 
         FileInstall.padmin = new MockServiceTracker( mockBundleContext, mockPackageAdmin );
         dw = new DirectoryWatcher( props, mockBundleContext );
 
         assertTrue( "Fragment type correctly retrieved from Package Admin service", dw.isFragment( mockBundle ) );
 
-        mockPackageAdminControl.verify();
-        mockBundleContextControl.verify();
-    }
+        EasyMock.verify(new Object[]{mockBundleContext, mockBundle, mockPackageAdmin});
+    }
+    
+    
+    public void testLoggingUsesGlobalAsDefault()
+    {
+        props.put( DirectoryWatcher.DIR, new File( "src/test/resources" ).getAbsolutePath() );
 
+        mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
+        EasyMock.expect(mockBundleContext.getProperty(DirectoryWatcher.LOG_LEVEL)).andReturn("4");
+        EasyMock.replay(new Object[]{mockBundleContext});
+        
+        dw = new DirectoryWatcher( props, mockBundleContext );
 
+        assertEquals( "Global LOG_LEVEL parameter correctly read", 4, dw.logLevel );
+        EasyMock.verify(new Object[]{mockBundleContext});        
+    }
 }

Reply via email to