532623 Treat application contexts in META-INF/spring/ like contexts in OSGI-INF/blueprint

Alignment of header-driven context configuration and adjacent test cases. Integration tests are still failing and need to be updated with regard to the test expectations (blueprint == spring-dm)

Signed-off-by: ootto <olaf@x100.de>
diff --git a/core/src/main/java/org/eclipse/gemini/blueprint/context/support/OsgiBundleXmlApplicationContext.java b/core/src/main/java/org/eclipse/gemini/blueprint/context/support/OsgiBundleXmlApplicationContext.java
index 3f4d804..d72b11b 100644
--- a/core/src/main/java/org/eclipse/gemini/blueprint/context/support/OsgiBundleXmlApplicationContext.java
+++ b/core/src/main/java/org/eclipse/gemini/blueprint/context/support/OsgiBundleXmlApplicationContext.java
@@ -15,7 +15,6 @@
 
 package org.eclipse.gemini.blueprint.context.support;
 
-import org.eclipse.gemini.blueprint.io.OsgiBundleResource;
 import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
 import org.eclipse.gemini.blueprint.util.internal.BundleUtils;
 import org.osgi.framework.BundleContext;
@@ -54,10 +53,6 @@
  */
 public class OsgiBundleXmlApplicationContext extends AbstractDelegatedExecutionApplicationContext implements DisposableBean {
 
-	/** Default config location for the root context(s) */
-	public static final String DEFAULT_CONFIG_LOCATION =
-			OsgiBundleResource.BUNDLE_URL_PREFIX + "/META-INF/spring/*.xml";
-
 	/**
 	 * 
 	 * Creates a new <code>OsgiBundleXmlApplicationContext</code> with no parent.
diff --git a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintConfigUtils.java b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintConfigUtils.java
index 83927c3..b218045 100644
--- a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintConfigUtils.java
+++ b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintConfigUtils.java
@@ -7,223 +7,196 @@
  * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0

  * is available at http://www.opensource.org/licenses/apache2.0.php.

  * You may elect to redistribute this code under either of these licenses. 

- * 

+ *

  * Contributors:

  *   VMware Inc.

  *****************************************************************************/

 

 package org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support;

 

+import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;

+import org.osgi.framework.Constants;

+import org.springframework.util.ObjectUtils;

+

 import java.util.ArrayList;

 import java.util.Dictionary;

 import java.util.List;

 

-import org.osgi.framework.Constants;

-import org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext;

-import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;

-import org.springframework.util.ObjectUtils;

-import org.springframework.util.StringUtils;

+import static org.springframework.util.StringUtils.hasText;

 

 /**

  * RFC124-version of {@link ConfigUtils} class. Basically a small util class that handles the retrieval of relevant

  * headers from the any given bundle.

- * 

+ *

  * @author Costin Leau

- * 

  */

 public class BlueprintConfigUtils {

 

-	private static final String EQUALS = "=";

+    private static final String EQUALS = "=";

 

-	private static final String SEMI_COLON = ";";

+    private static final String SEMI_COLON = ";";

 

-	private static final String COMMA = ",";

+    private static final String COMMA = ",";

 

-	/** Manifest entry name for configuring Blueprint modules */

-	public static final String BLUEPRINT_HEADER = "Bundle-Blueprint";

+    /**

+     * Manifest entry name for configuring Blueprint modules

+     */

+    public static final String BLUEPRINT_HEADER = "Bundle-Blueprint";

 

-	/** Standard wait for dependencies header */

-	public static final String BLUEPRINT_GRACE_PERIOD = "blueprint.graceperiod";

-	/** Standard timeout header */

-	public static final String BLUEPRINT_TIMEOUT = "blueprint.timeout";

+    /**

+     * Standard wait for dependencies header

+     */

+    public static final String BLUEPRINT_GRACE_PERIOD = "blueprint.graceperiod";

+    /**

+     * Standard timeout header

+     */

+    public static final String BLUEPRINT_TIMEOUT = "blueprint.timeout";

 

-	public static final String EXTENDER_VERSION = "BlueprintExtender-Version";

+    public static final String EXTENDER_VERSION = "BlueprintExtender-Version";

 

-	/**

-	 * Returns the {@value #BLUEPRINT_HEADER} if present from the given dictionary.

-	 * 

-	 * @param headers

-	 * @return

-	 */

-	public static String getBlueprintHeader(Dictionary headers) {

-		Object header = null;

-		if (headers != null)

-			header = headers.get(BLUEPRINT_HEADER);

-		return (header != null ? header.toString().trim() : null);

-	}

+    /**

+     * Returns the {@value #BLUEPRINT_HEADER} if present from the given dictionary.

+     */

+    public static String getBlueprintHeader(Dictionary headers) {

+        Object header = null;

+        if (headers != null)

+            header = headers.get(BLUEPRINT_HEADER);

+        return (header != null ? header.toString().trim() : null);

+    }

 

-	public static String getSymNameHeader(Dictionary headers) {

-		Object header = null;

-		if (headers != null)

-			header = headers.get(Constants.BUNDLE_SYMBOLICNAME);

-		return (header != null ? header.toString().trim() : null);

-	}

+    public static String getSymNameHeader(Dictionary headers) {

+        Object header = null;

+        if (headers != null)

+            header = headers.get(Constants.BUNDLE_SYMBOLICNAME);

+        return (header != null ? header.toString().trim() : null);

+    }

 

-	/**

-	 * Shortcut method to retrieve directive values. Used internally by the dedicated getXXX.

-	 * 

-	 * @param directiveName

-	 * @return

-	 */

-	private static String getDirectiveValue(Dictionary headers, String directiveName) {

-		String header = getBlueprintHeader(headers);

-		if (header != null) {

-			String directive = ConfigUtils.getDirectiveValue(header, directiveName);

-			if (directive != null)

-				return directive;

-		}

-		return null;

-	}

+    /**

+     * Shortcut method to retrieve directive values. Used internally by the dedicated getXXX.

+     */

+    private static String getDirectiveValue(Dictionary headers, String directiveName) {

+        String header = getBlueprintHeader(headers);

+        if (header != null) {

+            String directive = ConfigUtils.getDirectiveValue(header, directiveName);

+            if (directive != null)

+                return directive;

+        }

+        return null;

+    }

 

-	/**

-	 * Shortcut method for retrieving the directive values. Different then

-	 * {@link #getDirectiveValue(Dictionary, String)} since it looks at the Bundle-Symbolic header and not at

-	 * Spring-Context.

-	 * 

-	 * @param headers

-	 * @param directiveName

-	 * @return

-	 */

-	private static String getBlueprintDirectiveValue(Dictionary headers, String directiveName) {

-		String header = getSymNameHeader(headers);

-		if (header != null) {

-			String directive = ConfigUtils.getDirectiveValue(header, directiveName);

-			if (directive != null)

-				return directive;

-		}

-		return null;

-	}

+    /**

+     * Shortcut method for retrieving the directive values. Different then

+     * {@link #getDirectiveValue(Dictionary, String)} since it looks at the Bundle-Symbolic header and not at

+     * Spring-Context.

+     */

+    private static String getBlueprintDirectiveValue(Dictionary headers, String directiveName) {

+        String header = getSymNameHeader(headers);

+        if (header != null) {

+            String directive = ConfigUtils.getDirectiveValue(header, directiveName);

+            if (directive != null)

+                return directive;

+        }

+        return null;

+    }

 

-	public static boolean hasTimeout(Dictionary headers) {

-		String header = getSymNameHeader(headers);

-		if (header != null) {

-			return StringUtils.hasText(ConfigUtils.getDirectiveValue(header, BLUEPRINT_TIMEOUT));

-		}

-		return false;

-	}

+    public static boolean hasTimeout(Dictionary headers) {

+        String header = getSymNameHeader(headers);

+        return header != null && hasText(ConfigUtils.getDirectiveValue(header, BLUEPRINT_TIMEOUT));

+    }

 

-	/**

-	 * Shortcut for finding the boolean value for {@link #BLUEPRINT_TIMEOUT} directive using the given headers.

-	 * 

-	 * Assumes the headers belong to a Spring powered bundle. Returns the timeout (in milliseconds) for which the application

-	 * context should wait to have its dependencies satisfied.

-	 * 

-	 * @param headers

-	 * @return

-	 */

-	public static long getTimeOut(Dictionary headers) {

-		String value = getBlueprintDirectiveValue(headers, BLUEPRINT_TIMEOUT);

+    /**

+     * Shortcut for finding the boolean value for {@link #BLUEPRINT_TIMEOUT} directive using the given headers.

+     * <p>

+     * Assumes the headers belong to a Spring powered bundle. Returns the timeout (in milliseconds) for which the application

+     * context should wait to have its dependencies satisfied.

+     */

+    public static long getTimeOut(Dictionary headers) {

+        String value = getBlueprintDirectiveValue(headers, BLUEPRINT_TIMEOUT);

 

-		if (value != null) {

-			if (ConfigUtils.DIRECTIVE_TIMEOUT_VALUE_NONE.equalsIgnoreCase(value)) {

-				return ConfigUtils.DIRECTIVE_NO_TIMEOUT;

-			}

-			return Long.valueOf(value).longValue();

-		}

+        if (value != null) {

+            if (ConfigUtils.DIRECTIVE_TIMEOUT_VALUE_NONE.equalsIgnoreCase(value)) {

+                return ConfigUtils.DIRECTIVE_NO_TIMEOUT;

+            }

+            return Long.valueOf(value);

+        }

 

-		return ConfigUtils.DIRECTIVE_TIMEOUT_DEFAULT * 1000;

-	}

+        return ConfigUtils.DIRECTIVE_TIMEOUT_DEFAULT * 1000;

+    }

 

-	/**

-	 * Shortcut for finding the boolean value for {@link #BLUEPRINT_GRACE_PERIOD} directive using the given headers.

-	 * Assumes the headers belong to a Spring powered bundle.

-	 * 

-	 * @param headers

-	 * @return

-	 */

-	public static boolean getWaitForDependencies(Dictionary headers) {

-		String value = getBlueprintDirectiveValue(headers, BLUEPRINT_GRACE_PERIOD);

+    /**

+     * Shortcut for finding the boolean value for {@link #BLUEPRINT_GRACE_PERIOD} directive using the given headers.

+     * Assumes the headers belong to a Spring powered bundle.

+     */

+    public static boolean getWaitForDependencies(Dictionary headers) {

+        String value = getBlueprintDirectiveValue(headers, BLUEPRINT_GRACE_PERIOD);

 

-		return (value != null ? Boolean.valueOf(value).booleanValue() : ConfigUtils.DIRECTIVE_WAIT_FOR_DEPS_DEFAULT);

-	}

+        return (value != null ? Boolean.valueOf(value) : ConfigUtils.DIRECTIVE_WAIT_FOR_DEPS_DEFAULT);

+    }

 

-	/**

-	 * Shortcut for finding the boolean value for {@link #DIRECTIVE_PUBLISH_CONTEXT} directive using the given headers.

-	 * Assumes the headers belong to a Spring powered bundle.

-	 * 

-	 * @param headers

-	 * @return

-	 */

-	public static boolean getPublishContext(Dictionary headers) {

-		String value = getDirectiveValue(headers, ConfigUtils.DIRECTIVE_PUBLISH_CONTEXT);

-		return (value != null ? Boolean.valueOf(value).booleanValue() : ConfigUtils.DIRECTIVE_PUBLISH_CONTEXT_DEFAULT);

-	}

+    /**

+     * Shortcut for finding the boolean value for {@link ConfigUtils#DIRECTIVE_PUBLISH_CONTEXT} directive using the given headers.

+     * Assumes the headers belong to a Spring powered bundle.

+     */

+    public static boolean getPublishContext(Dictionary headers) {

+        String value = getDirectiveValue(headers, ConfigUtils.DIRECTIVE_PUBLISH_CONTEXT);

+        return (value != null ? Boolean.valueOf(value) : ConfigUtils.DIRECTIVE_PUBLISH_CONTEXT_DEFAULT);

+    }

 

-	/**

-	 * Shortcut for finding the boolean value for {@link #DIRECTIVE_CREATE_ASYNCHRONOUSLY} directive using the given

-	 * headers.

-	 * 

-	 * Assumes the headers belong to a Spring powered bundle.

-	 * 

-	 * @param headers

-	 * @return

-	 */

-	public static boolean getCreateAsync(Dictionary headers) {

-		String value = getDirectiveValue(headers, ConfigUtils.DIRECTIVE_CREATE_ASYNCHRONOUSLY);

-		return (value != null ? Boolean.valueOf(value).booleanValue()

-				: ConfigUtils.DIRECTIVE_CREATE_ASYNCHRONOUSLY_DEFAULT);

-	}

+    /**

+     * Shortcut for finding the boolean value for {@link ConfigUtils#DIRECTIVE_CREATE_ASYNCHRONOUSLY} directive using the given

+     * headers.

+     * <p>

+     * Assumes the headers belong to a Spring powered bundle.

+     */

+    public static boolean getCreateAsync(Dictionary headers) {

+        String value = getDirectiveValue(headers, ConfigUtils.DIRECTIVE_CREATE_ASYNCHRONOUSLY);

+        return (value != null ? Boolean.valueOf(value)

+                : ConfigUtils.DIRECTIVE_CREATE_ASYNCHRONOUSLY_DEFAULT);

+    }

 

-	/**

-	 * Returns the location headers (if any) specified by the Blueprint-Bundle header (if available). The returned

-	 * Strings can be sent to a {@link org.springframework.core.io.ResourceLoader} for loading the configurations.

-	 * 

-	 * Different from {@link ConfigUtils#getLocationsFromHeader(String, String)} since "," is used for separating

-	 * clauses while ; is used inside a clause to allow parameters or directives besides paths.

-	 * 

-	 * Since the presence of the header, disables any processing this method will return null if the header is not

-	 * specified, an empty array if it's empty (disabled) or a populated array otherwise.

-	 * 

-	 * @param headers bundle headers

-	 * @return array of locations specified (if any)

-	 */

-	public static String[] getBlueprintHeaderLocations(Dictionary headers) {

-		String header = getBlueprintHeader(headers);

+    /**

+     * Returns the location headers (if any) specified by the Blueprint-Bundle header (if available). The returned

+     * Strings can be sent to a {@link org.springframework.core.io.ResourceLoader} for loading the configurations.

+     * <p>

+     * Different from {@link ConfigUtils#getSpringDmLocationsFromHeader(String)} since "," is used for separating

+     * clauses while ; is used inside a clause to allow parameters or directives besides paths.

+     * <p>

+     * Since the presence of the header, disables any processing this method will return null if the header is not

+     * specified, an empty array if it's empty (disabled) or a populated array otherwise.

+     *

+     * @param headers bundle headers

+     * @return array of locations specified (if any)

+     */

+    public static String[] getBlueprintHeaderLocations(Dictionary headers) {

+        String header = getBlueprintHeader(headers);

 

-		// no header specified

-		if (header == null) {

-			return null;

-		}

+        // no header specified

+        if (header == null) {

+            return null;

+        }

 

-		// empty header specified

-		if (header.length() == 0) {

-			return new String[0];

-		}

+        // empty header specified

+        if (header.length() == 0) {

+            return new String[0];

+        }

 

-		List<String> ctxEntries = new ArrayList<String>(4);

-		if (StringUtils.hasText(header)) {

-			String[] clauses = header.split(COMMA);

-			for (String clause : clauses) {

-				// split into directives

-				String[] directives = clause.split(SEMI_COLON);

-				if (!ObjectUtils.isEmpty(directives)) {

-					// check if it's a path or not

-					for (String directive : directives) {

-						if (!directive.contains(EQUALS)) {

-							ctxEntries.add(directive.trim());

-						}

-					}

-				}

-			}

-		}

+        List<String> ctxEntries = new ArrayList<>(4);

+        if (hasText(header)) {

+            String[] clauses = header.split(COMMA);

+            for (String clause : clauses) {

+                // split into directives

+                String[] directives = clause.split(SEMI_COLON);

+                if (!ObjectUtils.isEmpty(directives)) {

+                    // check if it's a path or not

+                    for (String directive : directives) {

+                        if (!directive.contains(EQUALS)) {

+                            ctxEntries.add(directive.trim());

+                        }

+                    }

+                }

+            }

+        }

 

-		// replace * with a 'digestable' location

-		for (int i = 0; i < ctxEntries.size(); i++) {

-			String ctxEntry = ctxEntries.get(i);

-			if (ConfigUtils.CONFIG_WILDCARD.equals(ctxEntry))

-				ctxEntry = OsgiBundleXmlApplicationContext.DEFAULT_CONFIG_LOCATION;

-		}

-

-		return (String[]) ctxEntries.toArray(new String[ctxEntries.size()]);

-	}

+        return ctxEntries.toArray(new String[ctxEntries.size()]);

+    }

 }
\ No newline at end of file
diff --git a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintConfigurationScanner.java b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintConfigurationScanner.java
index 6c3e503..86fee26 100644
--- a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintConfigurationScanner.java
+++ b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintConfigurationScanner.java
@@ -1,126 +1,124 @@
-/******************************************************************************

- * Copyright (c) 2006, 2010 VMware Inc.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * and Apache License v2.0 which accompanies this distribution. 

- * The Eclipse Public License is available at 

- * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0

- * is available at http://www.opensource.org/licenses/apache2.0.php.

- * You may elect to redistribute this code under either of these licenses. 

- * 

- * Contributors:

- *   VMware Inc.

- *****************************************************************************/

+/*

+ Copyright (c) 2006, 2010 VMware Inc.

+ All rights reserved. This program and the accompanying materials

+ are made available under the terms of the Eclipse Public License v1.0

+ and Apache License v2.0 which accompanies this distribution.

+ The Eclipse Public License is available at

+ http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0

+ is available at http://www.opensource.org/licenses/apache2.0.php.

+ You may elect to redistribute this code under either of these licenses.

+

+ Contributors:

+ VMware Inc.

+ */

 

 package org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support;

 

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;

+import org.eclipse.gemini.blueprint.extender.support.scanning.ConfigurationScanner;

+import org.eclipse.gemini.blueprint.io.OsgiBundleResourcePatternResolver;

+import org.eclipse.gemini.blueprint.util.OsgiStringUtils;

+import org.osgi.framework.Bundle;

+import org.springframework.core.io.Resource;

+import org.springframework.core.io.support.ResourcePatternResolver;

+import org.springframework.util.ObjectUtils;

+

 import java.io.IOException;

 import java.util.ArrayList;

 import java.util.Arrays;

 import java.util.List;

 

-import org.apache.commons.logging.Log;

-import org.apache.commons.logging.LogFactory;

-import org.eclipse.gemini.blueprint.extender.support.scanning.ConfigurationScanner;

-import org.eclipse.gemini.blueprint.io.OsgiBundleResource;

-import org.eclipse.gemini.blueprint.io.OsgiBundleResourcePatternResolver;

-import org.osgi.framework.Bundle;

-import org.springframework.core.io.Resource;

-import org.springframework.core.io.support.ResourcePatternResolver;

-import org.eclipse.gemini.blueprint.util.OsgiStringUtils;

-import org.springframework.util.ObjectUtils;

+import static org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils.BLUEPRINT_SPEC_CONTEXT_LOCATION;

+import static org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils.LEGACY_SPRING_DM_CONTEXT_LOCATION;

 

 /**

  * Dedication {@link ConfigurationScanner scanner} implementation suitable for Blueprint bundles.

- * 

+ *

  * @author Costin Leau

  */

 public class BlueprintConfigurationScanner implements ConfigurationScanner {

 

-	/** logger */

-	private static final Log log = LogFactory.getLog(BlueprintConfigurationScanner.class);

+    /**

+     * logger

+     */

+    private static final Log log = LogFactory.getLog(BlueprintConfigurationScanner.class);

 

-	private static final String CONTEXT_DIR = "OSGI-INF/blueprint/";

+    public String[] getConfigurations(Bundle bundle) {

+        String bundleName = OsgiStringUtils.nullSafeName(bundle);

 

-	private static final String CONTEXT_FILES = "*.xml";

+        boolean trace = log.isTraceEnabled();

+        boolean debug = log.isDebugEnabled();

 

-	/** Default configuration location */

-	public static final String DEFAULT_CONFIG = OsgiBundleResource.BUNDLE_URL_PREFIX + CONTEXT_DIR + CONTEXT_FILES;

+        if (debug)

+            log.debug("Scanning bundle '" + bundleName + "' for blueprint configurations...");

 

-	public String[] getConfigurations(Bundle bundle) {

-		String bundleName = OsgiStringUtils.nullSafeName(bundle);

+        String[] locations = BlueprintConfigUtils.getBlueprintHeaderLocations(bundle.getHeaders());

 

-		boolean trace = log.isTraceEnabled();

-		boolean debug = log.isDebugEnabled();

+        if (locations == null) {

+            locations = ConfigUtils.getSpringDmHeaderLocations(bundle.getHeaders());

+        }

 

-		if (debug)

-			log.debug("Scanning bundle '" + bundleName + "' for blueprint configurations...");

+        // if no location is specified in the header, try the defaults

+        if (locations == null) {

+            locations = new String[]{BLUEPRINT_SPEC_CONTEXT_LOCATION, LEGACY_SPRING_DM_CONTEXT_LOCATION};

 

-		String[] locations = BlueprintConfigUtils.getBlueprintHeaderLocations(bundle.getHeaders());

+            if (trace) {

+                log.trace("Bundle '" + bundleName + "' has no declared locations; trying defaults " + Arrays.toString(locations));

+            }

+        } else if (ObjectUtils.isEmpty(locations)) {

+            log.info("Bundle '" + bundleName + "' has an empty blueprint location header - ignoring bundle...");

+            return new String[0];

+        }

 

-		// if no location is specified in the header, try the defaults

-		if (locations == null) {

-			if (trace) {

-				log.trace("Bundle '" + bundleName + "' has no declared locations; trying default " + DEFAULT_CONFIG);

-			}

-			locations = new String[] { DEFAULT_CONFIG };

-		} else {

-			// check whether the header is empty

-			if (ObjectUtils.isEmpty(locations)) {

-				log.info("Bundle '" + bundleName + "' has an empty blueprint header - ignoring bundle...");

-				return new String[0];

-			}

-		}

+        String[] configs = findValidBlueprintConfigs(bundle, locations);

+        if (debug)

+            log.debug("Discovered in bundle '" + bundleName + "' blueprint configurations=" + Arrays.toString(configs));

+        return configs;

+    }

 

-		String[] configs = findValidBlueprintConfigs(bundle, locations);

-		if (debug)

-			log.debug("Discovered in bundle '" + bundleName + "' blueprint configurations=" + Arrays.toString(configs));

-		return configs;

-	}

+    /**

+     * Checks if the given bundle contains existing configurations. The absolute paths are returned without performing

+     * any checks.

+     */

+    private String[] findValidBlueprintConfigs(Bundle bundle, String[] locations) {

+        List<String> configs = new ArrayList<String>(locations.length);

+        ResourcePatternResolver loader = new OsgiBundleResourcePatternResolver(bundle);

 

-	/**

-	 * Checks if the given bundle contains existing configurations. The absolute paths are returned without performing

-	 * any checks.

-	 * 

-	 * @return

-	 */

-	private String[] findValidBlueprintConfigs(Bundle bundle, String[] locations) {

-		List<String> configs = new ArrayList<String>(locations.length);

-		ResourcePatternResolver loader = new OsgiBundleResourcePatternResolver(bundle);

+        boolean debug = log.isDebugEnabled();

+        for (String location : locations) {

+            if (isAbsolute(location)) {

+                configs.add(location);

+            }

+            // resolve the location to check if it's present

+            else {

+                try {

+                    String loc = location;

+                    if (loc.endsWith("/")) {

+                        loc = loc + "*.xml";

+                    }

+                    Resource[] resources = loader.getResources(loc);

+                    if (!ObjectUtils.isEmpty(resources)) {

+                        for (Resource resource : resources) {

+                            if (resource.exists()) {

+                                String value = resource.getURL().toString();

+                                if (debug)

+                                    log.debug("Found location " + value);

+                                configs.add(value);

+                            }

+                        }

+                    }

+                } catch (IOException ex) {

+                    if (debug)

+                        log.debug("Cannot resolve location " + location, ex);

+                }

+            }

+        }

+        return configs.toArray(new String[configs.size()]);

+    }

 

-		boolean debug = log.isDebugEnabled();

-		for (String location : locations) {

-			if (isAbsolute(location)) {

-				configs.add(location);

-			}

-			// resolve the location to check if it's present

-			else {

-				try {

-					String loc = location;

-					if (loc.endsWith("/")) {

-						loc = loc + "*.xml";

-					}

-					Resource[] resources = loader.getResources(loc);

-					if (!ObjectUtils.isEmpty(resources)) {

-						for (Resource resource : resources) {

-							if (resource.exists()) {

-								String value = resource.getURL().toString();

-								if (debug)

-									log.debug("Found location " + value);

-								configs.add(value);

-							}

-						}

-					}

-				} catch (IOException ex) {

-					if (debug)

-						log.debug("Cannot resolve location " + location, ex);

-				}

-			}

-		}

-		return (String[]) configs.toArray(new String[configs.size()]);

-	}

-

-	private boolean isAbsolute(String location) {

-		return !(location.endsWith("/") || location.contains("*"));

-	}

+    private boolean isAbsolute(String location) {

+        return !(location.endsWith("/") || location.contains("*"));

+    }

 }
\ No newline at end of file
diff --git a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/support/ApplicationContextConfiguration.java b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/support/ApplicationContextConfiguration.java
index d5c5dc9..8a4a9f6 100644
--- a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/support/ApplicationContextConfiguration.java
+++ b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/support/ApplicationContextConfiguration.java
@@ -32,6 +32,8 @@
  * Determines the configuration information available in a bundle for constructing an application context. Reads all the

  * Blueprint options present in the bundle header.

  *

+ * FIXME: This is the original SPRING DM configuration. Extract a common base class and create a specialized Blueprint and Spring DM implementation.

+ *

  * @author Adrian Colyer

  * @author Costin Leau

  */

diff --git a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/support/internal/ConfigUtils.java b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/support/internal/ConfigUtils.java
index 8214cc8..21948d4 100644
--- a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/support/internal/ConfigUtils.java
+++ b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/support/internal/ConfigUtils.java
@@ -14,17 +14,18 @@
 

 package org.eclipse.gemini.blueprint.extender.support.internal;

 

-import java.util.Dictionary;

-

 import org.apache.commons.logging.Log;

 import org.apache.commons.logging.LogFactory;

 import org.osgi.framework.Bundle;

 import org.osgi.framework.Version;

-import org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext;

 import org.springframework.util.Assert;

 import org.springframework.util.ObjectUtils;

 import org.springframework.util.StringUtils;

 

+import java.util.Dictionary;

+

+import static org.eclipse.gemini.blueprint.io.OsgiBundleResource.BUNDLE_URL_PREFIX;

+

 /**

  * Utility class for dealing with the extender configuration and OSGi bundle

  * manifest headers.

@@ -58,6 +59,9 @@
 	 */

 	public static final String SPRING_CONTEXT_HEADER = "Spring-Context";

 

+	public static final String BLUEPRINT_SPEC_CONTEXT_LOCATION = BUNDLE_URL_PREFIX + "/OSGI-INF/blueprint/*.xml";

+	public static final String LEGACY_SPRING_DM_CONTEXT_LOCATION = BUNDLE_URL_PREFIX + "/META-INF/spring/*.xml";

+

 	/**

 	 * Directive for publishing Spring application context as a service.

 	 */

@@ -324,21 +328,20 @@
 	 * @param headers bundle headers

 	 * @return array of locations specified (if any)

 	 */

-	public static String[] getHeaderLocations(Dictionary headers) {

-		return getLocationsFromHeader(getSpringContextHeader(headers),

-			OsgiBundleXmlApplicationContext.DEFAULT_CONFIG_LOCATION);

-

+	public static String[] getSpringDmHeaderLocations(Dictionary headers) {

+		return getSpringDmLocationsFromHeader(getSpringContextHeader(headers));

 	}

 

 	/**

-	 * Similar to {@link #getHeaderLocations(Dictionary)} but looks at a

+	 * Similar to {@link #getSpringDmHeaderLocations(Dictionary)} but looks at a

 	 * specified header directly.

 	 * 

 	 * @param header header to look at

-	 * @param defaultValue default locations if none is specified

-	 * @return

-	 */

-	public static String[] getLocationsFromHeader(String header, String defaultValue) {

+    */

+	public static String[] getSpringDmLocationsFromHeader(String header) {

+		if (header == null) {

+			return null;

+		}

 

 		String[] ctxEntries;

 		if (StringUtils.hasText(header) && !(';' == header.charAt(0))) {

@@ -350,7 +353,7 @@
 			// replace * with a 'digestable' location

 			for (int i = 0; i < ctxEntries.length; i++) {

 				if (CONFIG_WILDCARD.equals(ctxEntries[i]))

-					ctxEntries[i] = defaultValue;

+					ctxEntries[i] = LEGACY_SPRING_DM_CONTEXT_LOCATION;

 			}

 		}

 		else {

diff --git a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/BlueprintLoaderListenerTest.java b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/BlueprintLoaderListenerTest.java
index 79c1216..c4e389f 100644
--- a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/BlueprintLoaderListenerTest.java
+++ b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/BlueprintLoaderListenerTest.java
@@ -15,29 +15,30 @@
 package org.eclipse.gemini.blueprint.extender.internal;
 
 import junit.framework.TestCase;
+import org.eclipse.gemini.blueprint.blueprint.container.SpringBlueprintContainer;
 import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
 import org.eclipse.gemini.blueprint.extender.internal.activator.ListenerServiceActivator;
 import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.BlueprintLoaderListener;
 import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
 import org.eclipse.gemini.blueprint.extender.internal.support.TestTaskExecutor;
 import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
-import org.eclipse.gemini.blueprint.mock.EntryLookupControllingMockBundle;
+import org.eclipse.gemini.blueprint.mock.ArrayEnumerator;
 import org.eclipse.gemini.blueprint.mock.MockBundle;
 import org.eclipse.gemini.blueprint.mock.MockBundleContext;
-import org.eclipse.gemini.blueprint.mock.MockServiceRegistration;
-import org.mockito.Mockito;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.BundleListener;
 import org.osgi.framework.Constants;
 import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.task.TaskExecutor;
 
 import java.util.Dictionary;
+import java.util.Enumeration;
 import java.util.Hashtable;
 
-import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -45,75 +46,82 @@
 
 /**
  * @author Adrian Colyer
- * 
  */
 public class BlueprintLoaderListenerTest extends TestCase {
-	private BlueprintLoaderListener listener;
-    private ExtenderConfiguration configuration = mock(ExtenderConfiguration.class);
+    private ExtenderConfiguration extenderConfiguration = mock(ExtenderConfiguration.class);
     private OsgiBundleApplicationContextEventMulticaster multicaster = mock(OsgiBundleApplicationContextEventMulticaster.class);
-	private ListenerServiceActivator listenerServiceActivator;
-	private BundleContext context;
+    private BundleContext context = mock(BundleContext.class);
 
-	protected void setUp() throws Exception {
-		super.setUp();
-		doReturn(multicaster).when(this.configuration).getEventMulticaster();
-		this.context = mock(BundleContext.class);
-		this.listenerServiceActivator = new ListenerServiceActivator(this.configuration);
-		this.listener = new BlueprintLoaderListener(this.configuration, listenerServiceActivator);
-		this.listenerServiceActivator.start(this.context);
-	}
+    private BlueprintLoaderListener testee;
 
-	public void testStart() throws Exception {
-		BundleContext context = Mockito.mock(BundleContext.class);
-		// look for existing resolved bundles
-		when(context.getBundles()).thenReturn(new Bundle[0]);
+    protected void setUp() throws Exception {
+        super.setUp();
+        doReturn(multicaster).when(this.extenderConfiguration).getEventMulticaster();
+        doReturn((TaskExecutor) Runnable::run).when(this.extenderConfiguration).getTaskExecutor();
 
-		// register context service
-		when(context.registerService((String[]) null, null, null)).thenReturn(null);
+        ListenerServiceActivator listenerServiceActivator = new ListenerServiceActivator(this.extenderConfiguration);
+        listenerServiceActivator.start(this.context);
 
-		// create task executor
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(null);
-		aBundle.setEntryReturnOnNextCallToGetEntry(null);
-		when(context.getBundle()).thenReturn(aBundle);
+        this.testee = new BlueprintLoaderListener(this.extenderConfiguration, listenerServiceActivator);
+    }
 
-		// listen for bundle events
-		context.addBundleListener(null);
+    public void testStart() throws Exception {
+        when(context.registerService((String[]) null, null, null)).thenReturn(null);
 
-		when(context.registerService(isA(String[].class), any(), isA(Dictionary.class))).thenReturn(new MockServiceRegistration<>());
+        Bundle bundle = new MockBundle() {
+            @Override
+            public Enumeration findEntries(String path, String filePattern, boolean recurse) {
+                if (path.endsWith("/blueprint/extender/internal/")) {
+                    // Retrieval of all XML files in a discovered directory: return test XML context
+                    return new ArrayEnumerator<>(getClass().getResource("/org/eclipse/gemini/blueprint/extender/internal/BlueprintLoaderListenerTest.xml"));
+                } else {
+                    // Directory listing: return directory containing XML file
+                    return new ArrayEnumerator<>(getClass().getResource("/org/eclipse/gemini/blueprint/extender/internal/"));
+                }
+            }
 
-		this.listener.start(context);
+            @Override
+            public BundleContext getBundleContext() {
+                return context;
+            }
+        };
 
-		verify(context).registerService(isA(String[].class), any(), isA(Dictionary.class));
-	}
+        when(context.getBundle()).thenReturn(bundle);
+        when(context.getBundles()).thenReturn(new Bundle[]{bundle});
+        this.testee.start(context);
 
-	public void ignoredTestTaskExecutor() throws Exception {
-		Dictionary<String, String> headers = new Hashtable<>();
-		headers.put(Constants.BUNDLE_NAME, "Extender mock bundle");
-		final EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setEntryReturnOnNextCallToGetEntry(new ClassPathResource("META-INF/spring/moved-extender.xml").getURL());
+        // Verify a blueprint container is published for the resulting application context.
+        verify(context).registerService(isA(String[].class), isA(SpringBlueprintContainer.class), isA(Dictionary.class));
+    }
 
-		MockBundleContext ctx = new MockBundleContext() {
+    public void ignoredTestTaskExecutor() throws Exception {
+        Dictionary<String, String> headers = new Hashtable<>();
+        headers.put(Constants.BUNDLE_NAME, "Extender mock bundle");
+        final Bundle aBundle = mock(Bundle.class);
+        doReturn(new ClassPathResource("META-INF/spring/moved-extender.xml").getURL()).when(aBundle).getEntry(anyString());
 
-			public Bundle getBundle() {
-				return aBundle;
-			}
-		};
+        MockBundleContext ctx = new MockBundleContext() {
 
-		this.listener.start(ctx);
+            public Bundle getBundle() {
+                return aBundle;
+            }
+        };
 
-		Dictionary<String, String> hdrs = new Hashtable<>();
-		hdrs.put(ConfigUtils.SPRING_CONTEXT_HEADER, "bla bla");
-		MockBundle anotherBundle = new MockBundle(hdrs);
-		anotherBundle.setBundleId(1);
+        this.testee.start(ctx);
 
-		BundleEvent event = new BundleEvent(BundleEvent.STARTED, anotherBundle);
+        Dictionary<String, String> hdrs = new Hashtable<>();
+        hdrs.put(ConfigUtils.SPRING_CONTEXT_HEADER, "bla bla");
+        MockBundle anotherBundle = new MockBundle(hdrs);
+        anotherBundle.setBundleId(1);
 
-		BundleListener listener = ctx.getBundleListeners().iterator().next();
+        BundleEvent event = new BundleEvent(BundleEvent.STARTED, anotherBundle);
 
-		TestTaskExecutor.called = false;
+        BundleListener listener = ctx.getBundleListeners().iterator().next();
 
-		listener.bundleChanged(event);
-		assertTrue("task executor should have been called if configured properly", TestTaskExecutor.called);
-	}
+        TestTaskExecutor.called = false;
+
+        listener.bundleChanged(event);
+        assertTrue("task executor should have been called if configured properly", TestTaskExecutor.called);
+    }
 
 }
diff --git a/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintConfigUtilsTest.java b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/support/BlueprintConfigUtilsTest.java
similarity index 78%
rename from extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintConfigUtilsTest.java
rename to extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/support/BlueprintConfigUtilsTest.java
index d2242d0..5015d85 100644
--- a/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintConfigUtilsTest.java
+++ b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/support/BlueprintConfigUtilsTest.java
@@ -1,48 +1,46 @@
-/******************************************************************************

- * Copyright (c) 2006, 2010 VMware Inc.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * and Apache License v2.0 which accompanies this distribution. 

- * The Eclipse Public License is available at 

- * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0

- * is available at http://www.opensource.org/licenses/apache2.0.php.

- * You may elect to redistribute this code under either of these licenses. 

- * 

- * Contributors:

- *   VMware Inc.

- *****************************************************************************/

-

-package org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support;

-

-import java.util.Dictionary;

-import java.util.Properties;

-

-import junit.framework.TestCase;

-

-import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintConfigUtils;

-import org.osgi.framework.Constants;

-

-/**

- * @author Costin Leau

- */

-public class BlueprintConfigUtilsTest extends TestCase {

-

-	public void testNoWaitForDependencies() throws Exception {

-		Dictionary props = new Properties();

-		props.put(Constants.BUNDLE_SYMBOLICNAME, "foo.bar; " + BlueprintConfigUtils.BLUEPRINT_GRACE_PERIOD + ":=false");

-		assertFalse(BlueprintConfigUtils.getWaitForDependencies(props));

-

-	}

-

-	public void testWaitForDependencies() throws Exception {

-		Dictionary props = new Properties();

-		props.put(Constants.BUNDLE_SYMBOLICNAME, "foo.bar; " + BlueprintConfigUtils.BLUEPRINT_GRACE_PERIOD + ":=true");

-		assertTrue(BlueprintConfigUtils.getWaitForDependencies(props));

-	}

-

-	public void testNoWaitDefinedForDependencies() throws Exception {

-		Dictionary props = new Properties();

-		props.put(Constants.BUNDLE_SYMBOLICNAME, "foo.bar");

-		assertTrue(BlueprintConfigUtils.getWaitForDependencies(props));

-	}

-}

+/******************************************************************************
+ * Copyright (c) 2006, 2010 VMware Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Apache License v2.0 which accompanies this distribution. 
+ * The Eclipse Public License is available at 
+ * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
+ * is available at http://www.opensource.org/licenses/apache2.0.php.
+ * You may elect to redistribute this code under either of these licenses. 
+ * 
+ * Contributors:
+ *   VMware Inc.
+ *****************************************************************************/
+
+package org.eclipse.gemini.blueprint.extender.internal.activator.support;
+
+import junit.framework.TestCase;
+import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintConfigUtils;
+import org.osgi.framework.Constants;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+/**
+ * @author Costin Leau
+ */
+public class BlueprintConfigUtilsTest extends TestCase {
+
+	public void testNoWaitForDependencies() {
+		Dictionary<String, Object> props = new Hashtable<>();
+		props.put(Constants.BUNDLE_SYMBOLICNAME, "foo.bar; " + BlueprintConfigUtils.BLUEPRINT_GRACE_PERIOD + ":=false");
+		assertFalse(BlueprintConfigUtils.getWaitForDependencies(props));
+	}
+
+	public void testWaitForDependencies() {
+		Dictionary<String, Object> props = new Hashtable<>();
+		props.put(Constants.BUNDLE_SYMBOLICNAME, "foo.bar; " + BlueprintConfigUtils.BLUEPRINT_GRACE_PERIOD + ":=true");
+		assertTrue(BlueprintConfigUtils.getWaitForDependencies(props));
+	}
+
+	public void testNoWaitDefinedForDependencies() {
+		Dictionary<String, Object> props = new Hashtable<>();
+		props.put(Constants.BUNDLE_SYMBOLICNAME, "foo.bar");
+		assertTrue(BlueprintConfigUtils.getWaitForDependencies(props));
+	}
+}
diff --git a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ApplicationContextConfigurationTest.java b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ApplicationContextConfigurationTest.java
index 5d3b94b..f03d09b 100644
--- a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ApplicationContextConfigurationTest.java
+++ b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ApplicationContextConfigurationTest.java
@@ -15,250 +15,268 @@
 package org.eclipse.gemini.blueprint.extender.internal.support;
 
 import junit.framework.TestCase;
-import org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext;
 import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintContainerConfig;
 import org.eclipse.gemini.blueprint.extender.support.ApplicationContextConfiguration;
-import org.eclipse.gemini.blueprint.mock.EntryLookupControllingMockBundle;
+import org.eclipse.gemini.blueprint.mock.ArrayEnumerator;
+import org.osgi.framework.Bundle;
 
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Dictionary;
-import java.util.Enumeration;
 import java.util.Hashtable;
 
+import static org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils.LEGACY_SPRING_DM_CONTEXT_LOCATION;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
 /**
  * Test that given a bundle, we can correctly determine the spring configuration
  * required for it.
- * 
+ *
  * @author Adrian Colyer
  */
 public class ApplicationContextConfigurationTest extends TestCase {
+    private final URL metaInfSpringFolder;
 
-	private static final String[] META_INF_SPRING_CONTENT = new String[] { "file://META-INF/spring/context.xml",
-			"file://META-INF/spring/context-two.xml" };
+    {
+        try {
+            metaInfSpringFolder = new URL("file:///META-INF/spring/");
+        } catch (MalformedURLException e) {
+            throw new IllegalStateException(e);
+        }
+    }
 
-	public void testBundleWithNoHeaderAndNoMetaInfSpringResourcesIsNotSpringPowered() {
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(null);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(null);
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertFalse("bundle is not spring powered", config.isBlueprintConfigurationPresent());
-	}
+    private final URL context_xml = getClass().getClassLoader().getResource("org/eclipse/gemini/blueprint/extender/internal/support/META-INF/spring/context.xml");
+    private final URL context_two_xml = getClass().getClassLoader().getResource("org/eclipse/gemini/blueprint/extender/internal/support/META-INF/spring/context-two.xml");
 
-	public void testBundleWithSpringResourcesAndNoHeaderIsSpringPowered() {
-		EntryLookupControllingMockBundle aBundle = new RepeatingEntryLookupControllingMockBundle(null);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertTrue("bundle is spring powered", config.isBlueprintConfigurationPresent());
-	}
+    public void testBundleWithNoHeaderAndNoMetaInfSpringResourcesIsNotSpringPowered() {
+        Bundle bundle = mock(Bundle.class);
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertFalse("bundle is not spring powered", config.isBlueprintConfigurationPresent());
+    }
 
-	public void testBundleWithHeaderAndNoMetaInfResourcesIsSpringPowered() throws Exception {
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "META-INF/spring/context.xml");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(null);
-		aBundle.setEntryReturnOnNextCallToGetEntry(new URL("file://META-INF/spring/context.xml"));
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertTrue("bundle is spring powered", config.isBlueprintConfigurationPresent());
-	}
+    public void testBundleWithSpringResourcesAndNoHeaderIsSpringPowered() {
+        Bundle bundle = mock(Bundle.class);
+        addSpringContextConfigurationPresent(bundle);
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertTrue("bundle is spring powered", config.isBlueprintConfigurationPresent());
+    }
 
-	public void testBundleWithNoHeaderShouldWaitFiveMinutes() {
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(null);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertEquals("bundle should timeout in five minutes", new Long(5 * 60 * 1000), new Long(config.getTimeout()));
-	}
+    public void testBundleWithHeaderAndNoMetaInfResourcesIsSpringPowered() throws Exception {
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "META-INF/spring/context.xml");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        doReturn(new URL("file://META-INF/spring/context.xml")).when(bundle).getEntry(anyString());
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertTrue("bundle is spring powered", config.isBlueprintConfigurationPresent());
+    }
 
-	public void testBundleWithWaitFiveSecondWaitForTimeout() {
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "*;timeout:=5");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
-		assertEquals("bundle should timeout in 5 s", new Long(5 * 1000), new Long(config.getTimeout()));
-	}
+    public void testBundleWithNoHeaderShouldWaitFiveMinutes() {
+        Bundle bundle = mock(Bundle.class);
+        addSpringContextConfigurationPresent(bundle);
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertEquals("bundle should timeout in five minutes", new Long(5 * 60 * 1000), new Long(config.getTimeout()));
+    }
 
-	public void testBundleWithWaitForEver() {
-		// *;flavour
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "*;timeout:=none");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
-		assertEquals("bundle should timeout -2 (indicates forever)", new Long(-2), new Long(config.getTimeout()));
-	}
+    public void testBundleWithWaitFiveSecondWaitForTimeout() {
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "*;timeout:=5");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
+        assertEquals("bundle should timeout in 5 s", new Long(5 * 1000), new Long(config.getTimeout()));
+    }
 
-	public void tstConfigLocationsInMetaInfNoHeader() {
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(null);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		String[] configFiles = config.getConfigurationLocations();
-		assertEquals("0 config files", 0, configFiles.length);
-		// assertEquals("bundle-url:file://META-INF/spring/context.xml",
-		// configFiles[0]);
-		// assertEquals("bundle-url:file://META-INF/spring/context-two.xml",
-		// configFiles[1]);
-	}
+    public void testBundleWithWaitForEver() {
+        // *;flavour
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "*;timeout:=none");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
+        assertEquals("bundle should timeout -2 (indicates forever)", new Long(-2), new Long(config.getTimeout()));
+    }
 
-	public void tstConfigLocationsInMetaInfWithHeader() throws Exception {
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "META-INF/spring/context.xml");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		aBundle.setEntryReturnOnNextCallToGetEntry(new URL("file://META-INF/spring/context.xml"));
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		String[] configFiles = config.getConfigurationLocations();
-		assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
-		assertEquals("osgibundle:META-INF/spring/context.xml", configFiles[0]);
-	}
+    public void tstConfigLocationsInMetaInfNoHeader() {
+        Bundle bundle = mock(Bundle.class);
+        addSpringContextConfigurationPresent(bundle);
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        String[] configFiles = config.getConfigurationLocations();
+        assertEquals("0 config files", 0, configFiles.length);
+        // assertEquals("bundle-url:file://META-INF/spring/context.xml",
+        // configFiles[0]);
+        // assertEquals("bundle-url:file://META-INF/spring/context-two.xml",
+        // configFiles[1]);
+    }
 
-	public void tstConfigLocationsInMetaInfWithWildcardHeader() throws Exception {
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "*;wait-for-dependencies:=false");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		aBundle.setEntryReturnOnNextCallToGetEntry(new URL(META_INF_SPRING_CONTENT[0]));
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		String[] configFiles = config.getConfigurationLocations();
-		assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
-		assertEquals("1 config files", 1, configFiles.length);
-		assertEquals(OsgiBundleXmlApplicationContext.DEFAULT_CONFIG_LOCATION, configFiles[0]);
-	}
+    public void tstConfigLocationsInMetaInfWithHeader() throws Exception {
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "META-INF/spring/context.xml");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        doReturn(new URL("file://META-INF/spring/context.xml")).when(bundle).getEntry(anyString());
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        String[] configFiles = config.getConfigurationLocations();
+        assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
+        assertEquals("osgibundle:META-INF/spring/context.xml", configFiles[0]);
+    }
 
-	public void tstEmptyConfigLocationsInMetaInf() throws Exception {
-		System.out.println("tsst");
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", ";wait-for-dependencies:=false");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		aBundle.setEntryReturnOnNextCallToGetEntry(new URL(META_INF_SPRING_CONTENT[0]));
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		String[] configFiles = config.getConfigurationLocations();
-		assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
-		assertEquals("1 config files", 1, configFiles.length);
-		assertEquals(OsgiBundleXmlApplicationContext.DEFAULT_CONFIG_LOCATION, configFiles[0]);
-	}
+    public void tstConfigLocationsInMetaInfWithWildcardHeader() throws Exception {
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "*;wait-for-dependencies:=false");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        doReturn(context_xml).when(bundle).getEntry(anyString());
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        String[] configFiles = config.getConfigurationLocations();
+        assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
+        assertEquals("1 config files", 1, configFiles.length);
+        assertEquals(LEGACY_SPRING_DM_CONTEXT_LOCATION, configFiles[0]);
+    }
 
-	public void tstConfigLocationsInMetaInfWithHeaderAndDependencies() throws Exception {
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "META-INF/spring/context.xml;wait-for-dependencies:=false");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		aBundle.setEntryReturnOnNextCallToGetEntry(new URL(META_INF_SPRING_CONTENT[0]));
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		String[] configFiles = config.getConfigurationLocations();
-		assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
-		assertEquals("2 config files", 1, configFiles.length);
-		assertEquals("osgibundle:META-INF/spring/context.xml", configFiles[0]);
-	}
+    public void tstEmptyConfigLocationsInMetaInf() throws Exception {
+        System.out.println("tsst");
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", ";wait-for-dependencies:=false");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        doReturn(context_xml).when(bundle).getEntry(anyString());
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        String[] configFiles = config.getConfigurationLocations();
+        assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
+        assertEquals("1 config files", 1, configFiles.length);
+        assertEquals(LEGACY_SPRING_DM_CONTEXT_LOCATION, configFiles[0]);
+    }
 
-	public void tstBundleWithHeaderWithBadEntriesAndNoMetaInfResourcesIsNotSpringPowered() {
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "META-INF/splurge/context.xml");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(null);
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertFalse("bundle is not spring powered", config.isBlueprintConfigurationPresent());
-	}
+    public void tstConfigLocationsInMetaInfWithHeaderAndDependencies() throws Exception {
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "META-INF/spring/context.xml;wait-for-dependencies:=false");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        doReturn(context_xml).when(bundle).getEntry(anyString());
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        String[] configFiles = config.getConfigurationLocations();
+        assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
+        assertEquals("2 config files", 1, configFiles.length);
+        assertEquals("osgibundle:META-INF/spring/context.xml", configFiles[0]);
+    }
 
-	public void tstHeaderWithWildcardEntryAndNoMetaInfResources() {
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "*;wait-for-dependencies:=false");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(null);
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertFalse("not spring powered", config.isBlueprintConfigurationPresent());
-	}
+    public void tstBundleWithHeaderWithBadEntriesAndNoMetaInfResourcesIsNotSpringPowered() {
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "META-INF/splurge/context.xml");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertFalse("bundle is not spring powered", config.isBlueprintConfigurationPresent());
+    }
 
-	public void tstHeaderWithBadEntry() throws Exception {
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "META-INF/spring/context-two.xml,META-INF/splurge/context.xml,");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setEntryReturnOnNextCallToGetEntry(new URL("file://META-INF/spring/context-two.xml"));
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertFalse("bundle is not spring powered", config.isBlueprintConfigurationPresent());
-		String[] configFiles = config.getConfigurationLocations();
-		assertEquals("0 config file", 0, configFiles.length);
-	}
+    public void tstHeaderWithWildcardEntryAndNoMetaInfResources() {
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "*;wait-for-dependencies:=false");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertFalse("not spring powered", config.isBlueprintConfigurationPresent());
+    }
 
-	public void testCreateAsynchronouslyDefaultTrue() throws Exception {
-		// *;flavour
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "*;timeout:=none");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		aBundle.setEntryReturnOnNextCallToGetEntry(new URL(META_INF_SPRING_CONTENT[0]));
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
-		assertTrue("bundle should have create-asynchronously = true", config.isCreateAsynchronously());
-	}
+    public void tstHeaderWithBadEntry() throws Exception {
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "META-INF/spring/context-two.xml,META-INF/splurge/context.xml,");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        doReturn(new URL("file://META-INF/spring/context-two.xml")).when(bundle).getEntry(anyString());
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertFalse("bundle is not spring powered", config.isBlueprintConfigurationPresent());
+        String[] configFiles = config.getConfigurationLocations();
+        assertEquals("0 config file", 0, configFiles.length);
+    }
 
-	public void testSetCreateAsynchronouslyTrue() {
-		// *;flavour
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "*;create-asynchronously:=true");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
-		assertTrue("bundle should have create-asynchronously = true", config.isCreateAsynchronously());
-	}
+    public void testCreateAsynchronouslyDefaultTrue() throws Exception {
+        // *;flavour
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "*;timeout:=none");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        doReturn(context_xml).when(bundle).getEntry(anyString());
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
+        assertTrue("bundle should have create-asynchronously = true", config.isCreateAsynchronously());
+    }
 
-	public void testSetCreateAsynchronouslyFalse() throws Exception {
-		// *;flavour
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "META-INF/spring/context.xml;create-asynchronously:=false");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		aBundle.setEntryReturnOnNextCallToGetEntry(new URL(META_INF_SPRING_CONTENT[0]));
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
-		assertFalse("bundle should have create-asynchronously = false", config.isCreateAsynchronously());
-	}
+    public void testSetCreateAsynchronouslyTrue() {
+        // *;flavour
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "*;create-asynchronously:=true");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
+        assertTrue("bundle should have create-asynchronously = true", config.isCreateAsynchronously());
+    }
 
-	public void testCreateAsynchronouslyDefaultTrueIfAbsent() {
-		// *;flavour
-		Dictionary<String, Object> headers = new Hashtable<>();
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertTrue("bundle should have create-asynchronously = true", config.isCreateAsynchronously());
-	}
+    public void testSetCreateAsynchronouslyFalse() throws Exception {
+        // *;flavour
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "META-INF/spring/context.xml;create-asynchronously:=false");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        doReturn(context_xml).when(bundle).getEntry(anyString());
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertTrue("bundle should be Spring powered", config.isBlueprintConfigurationPresent());
+        assertFalse("bundle should have create-asynchronously = false", config.isCreateAsynchronously());
+    }
 
-	public void testCreateAsynchronouslyDefaultTrueIfGarbage() {
-		// *;flavour
-		Dictionary<String, Object> headers = new Hashtable<>();
-		headers.put("Spring-Context", "*;favour:=false");
-		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
-		aBundle.setResultsToReturnOnNextCallToFindEntries(META_INF_SPRING_CONTENT);
-		ApplicationContextConfiguration config = new BlueprintContainerConfig(aBundle);
-		assertTrue("bundle should have create-asynchronously = true", config.isCreateAsynchronously());
-	}
+    public void testCreateAsynchronouslyDefaultTrueIfAbsent() {
+        // *;flavour
+        Dictionary<String, Object> headers = new Hashtable<>();
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertTrue("bundle should have create-asynchronously = true", config.isCreateAsynchronously());
+    }
 
-	private static class RepeatingEntryLookupControllingMockBundle extends EntryLookupControllingMockBundle {
-		protected String[] findResult;
+    public void testCreateAsynchronouslyDefaultTrueIfGarbage() {
+        // *;flavour
+        Dictionary<String, Object> headers = new Hashtable<>();
+        headers.put("Spring-Context", "*;favour:=false");
+        Bundle bundle = mock(Bundle.class);
+        doReturn(headers).when(bundle).getHeaders();
+        addSpringContextConfigurationPresent(bundle);
+        ApplicationContextConfiguration config = new BlueprintContainerConfig(bundle);
+        assertTrue("bundle should have create-asynchronously = true", config.isCreateAsynchronously());
+    }
 
-		public RepeatingEntryLookupControllingMockBundle(Dictionary headers) {
-			super(headers);
-		}
+    private void addSpringContextConfigurationPresent(Bundle bundle) {
 
-		public Enumeration findEntries(String path, String filePattern, boolean recurse) {
-			if (this.nextFindResult == null) {
-				return super.findEntries(path, filePattern, recurse);
-			}
-			else {
-				Enumeration r = this.nextFindResult;
-				this.nextFindResult = createEnumerationOver(findResult);
-				return r;
-			}
-		}
+        doAnswer(r -> new ArrayEnumerator<>(metaInfSpringFolder))
+                .when(bundle)
+                .findEntries(
+                        "META-INF",
+                        "spring",
+                        false);
 
-		public void setResultsToReturnOnNextCallToFindEntries(String[] r) {
-			findResult = r;
-			if (findResult == null) {
-				findResult = new String[0];
-			}
-			this.nextFindResult = createEnumerationOver(findResult);
-		}
-	}
+        doAnswer(r -> new ArrayEnumerator<>(context_xml, context_two_xml))
+                .when(bundle)
+                .findEntries(
+                        "/META-INF/spring/",
+                        null,
+                        false);
+    }
 }
diff --git a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/util/ConfigUtilsTest.java b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/util/ConfigUtilsTest.java
index 8e60847..a3450a1 100644
--- a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/util/ConfigUtilsTest.java
+++ b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/util/ConfigUtilsTest.java
@@ -20,7 +20,6 @@
 import junit.framework.TestCase;

 

 import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;

-import org.eclipse.gemini.blueprint.io.OsgiBundleResource;

 

 /**

  * @author Costin Leau

@@ -40,7 +39,7 @@
 	}

 

 	public void testGetCompletelyEmptySpringContextHeader() throws Exception {

-		String[] locations = ConfigUtils.getHeaderLocations(headers);

+		String[] locations = ConfigUtils.getSpringDmHeaderLocations(headers);

 		assertEquals(0, locations.length);

 

 	}

@@ -48,7 +47,7 @@
 	public void testGetEmptyConfigLocations() throws Exception {

 		String entry = ";early-init-importers=true";

 		headers.put(ConfigUtils.SPRING_CONTEXT_HEADER, entry);

-		String[] locations = ConfigUtils.getHeaderLocations(headers);

+		String[] locations = ConfigUtils.getSpringDmHeaderLocations(headers);

 		assertEquals(0, locations.length);

 	}

 

@@ -57,7 +56,7 @@
 		String entry = location + "; early-init-importers=true";

 

 		headers.put(ConfigUtils.SPRING_CONTEXT_HEADER, entry);

-		String[] locations = ConfigUtils.getHeaderLocations(headers);

+		String[] locations = ConfigUtils.getSpringDmHeaderLocations(headers);

 		assertEquals(1, locations.length);

 		assertEquals(location, locations[0]);

 

@@ -67,7 +66,7 @@
 		String location = "classpath:/META-INF/spring/*.xml";

 		String entry = location + "; early-init-importers=true";

 		headers.put(ConfigUtils.SPRING_CONTEXT_HEADER, entry);

-		String[] locations = ConfigUtils.getHeaderLocations(headers);

+		String[] locations = ConfigUtils.getSpringDmHeaderLocations(headers);

 		assertEquals(1, locations.length);

 		assertEquals(location, locations[0]);

 	}

@@ -78,7 +77,7 @@
 

 		String entry = location1 + "," + location2 + "; early-init-importers=true";

 		headers.put(ConfigUtils.SPRING_CONTEXT_HEADER, entry);

-		String[] locations = ConfigUtils.getHeaderLocations(headers);

+		String[] locations = ConfigUtils.getSpringDmHeaderLocations(headers);

 		assertEquals(2, locations.length);

 		assertEquals(location1, locations[0]);

 		assertEquals(location2, locations[1]);

@@ -87,7 +86,7 @@
 	public void testLocationWithMultipleDots() throws Exception {

 		headers.put(ConfigUtils.SPRING_CONTEXT_HEADER,

 			"META-INF/file.with.multiple.dots.xml, META-INF/another.file.xml");

-		String[] locations = ConfigUtils.getHeaderLocations(headers);

+		String[] locations = ConfigUtils.getSpringDmHeaderLocations(headers);

 		assertEquals(2, locations.length);

 	}

 }

diff --git a/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/BlueprintLoaderListenerTest.xml b/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/BlueprintLoaderListenerTest.xml
new file mode 100644
index 0000000..9cca5b9
--- /dev/null
+++ b/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/BlueprintLoaderListenerTest.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="
+		http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+    <description>A simple, empty blueprint context</description>
+</blueprint>
\ No newline at end of file
diff --git a/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/support/META-INF/spring/context-two.xml b/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/support/META-INF/spring/context-two.xml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/support/META-INF/spring/context-two.xml
diff --git a/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/support/META-INF/spring/context.xml b/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/support/META-INF/spring/context.xml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/support/META-INF/spring/context.xml
diff --git a/io/src/main/java/org/eclipse/gemini/blueprint/io/OsgiBundleResourcePatternResolver.java b/io/src/main/java/org/eclipse/gemini/blueprint/io/OsgiBundleResourcePatternResolver.java
index a0fbbba..525c7a7 100644
--- a/io/src/main/java/org/eclipse/gemini/blueprint/io/OsgiBundleResourcePatternResolver.java
+++ b/io/src/main/java/org/eclipse/gemini/blueprint/io/OsgiBundleResourcePatternResolver.java
@@ -563,7 +563,6 @@
 		for (int i = 0; i < rootDirResources.length; i++) {

 			Resource rootDirResource = rootDirResources[i];

 			if (isJarResource(rootDirResource)) {

-				// FIXME: Spring 5 Migration

 				result.addAll(doFindPathMatchingJarResources(rootDirResource, new URL(""), subPattern));

 			} else {

 				result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern, searchType));

diff --git a/mock/src/main/java/org/eclipse/gemini/blueprint/mock/ArrayEnumerator.java b/mock/src/main/java/org/eclipse/gemini/blueprint/mock/ArrayEnumerator.java
index a1d94fe..175e21c 100644
--- a/mock/src/main/java/org/eclipse/gemini/blueprint/mock/ArrayEnumerator.java
+++ b/mock/src/main/java/org/eclipse/gemini/blueprint/mock/ArrayEnumerator.java
@@ -28,7 +28,7 @@
 	private int index = 0;

 

 

-	public ArrayEnumerator(E[] source) {

+	public ArrayEnumerator(E... source) {

 		this.source = source;

 	}

 

diff --git a/mock/src/main/java/org/eclipse/gemini/blueprint/mock/EntryLookupControllingMockBundle.java b/mock/src/main/java/org/eclipse/gemini/blueprint/mock/EntryLookupControllingMockBundle.java
deleted file mode 100644
index 2b86b32..0000000
--- a/mock/src/main/java/org/eclipse/gemini/blueprint/mock/EntryLookupControllingMockBundle.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/******************************************************************************

- * Copyright (c) 2006, 2010 VMware Inc.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * and Apache License v2.0 which accompanies this distribution. 

- * The Eclipse Public License is available at 

- * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0

- * is available at http://www.opensource.org/licenses/apache2.0.php.

- * You may elect to redistribute this code under either of these licenses. 

- * 

- * Contributors:

- *   VMware Inc.

- *****************************************************************************/

-

-package org.eclipse.gemini.blueprint.mock;

-

-import java.net.URL;

-import java.util.Dictionary;

-import java.util.Enumeration;

-

-import org.osgi.framework.BundleContext;

-

-/**

- * Dedicated Mock Bundle that provides control over the returned entries for

- * lookup calls.

- * 

- * @author Adrian Colyer

- */

-public class EntryLookupControllingMockBundle extends MockBundle {

-

-	protected Enumeration nextFindResult = null;

-

-	protected URL nextEntryResult = null;

-

-

-	/**

-	 * Constructs a new <code>EntryLookupControllingMockBundle</code>

-	 * instance.

-	 * 

-	 * @param headers

-	 */

-	public EntryLookupControllingMockBundle(Dictionary headers) {

-		super(headers);

-	}

-

-	public void setResultsToReturnOnNextCallToFindEntries(String[] findResult) {

-		if (findResult == null) {

-			findResult = new String[0];

-		}

-		this.nextFindResult = createEnumerationOver(findResult);

-	}

-

-	public Enumeration findEntries(String path, String filePattern, boolean recurse) {

-		if (this.nextFindResult == null) {

-			return super.findEntries(path, filePattern, recurse);

-		}

-		else {

-			Enumeration ret = this.nextFindResult;

-			this.nextFindResult = null;

-			return ret;

-		}

-	}

-

-	public void setEntryReturnOnNextCallToGetEntry(URL entry) {

-		this.nextEntryResult = entry;

-	}

-

-	public URL getEntry(String name) {

-		if (this.nextEntryResult != null) {

-			URL result = this.nextEntryResult;

-			this.nextEntryResult = null;

-			return result;

-		}

-		else {

-			return super.getEntry(name);

-		}

-	}

-

-	public URL getResource(String name) {

-		return getEntry(name);

-	}

-

-	// for OsgiResourceUtils

-	public BundleContext getContext() {

-		return super.getContext();

-	}

-

-	protected Enumeration createEnumerationOver(String[] entries) {

-		return new ArrayEnumerator(entries);

-	}

-}
\ No newline at end of file
diff --git a/mock/src/main/java/org/eclipse/gemini/blueprint/mock/MockBundle.java b/mock/src/main/java/org/eclipse/gemini/blueprint/mock/MockBundle.java
index 8cae7f8..65ec4e5 100644
--- a/mock/src/main/java/org/eclipse/gemini/blueprint/mock/MockBundle.java
+++ b/mock/src/main/java/org/eclipse/gemini/blueprint/mock/MockBundle.java
@@ -1,30 +1,19 @@
-/******************************************************************************

- * Copyright (c) 2006, 2010 VMware Inc.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * and Apache License v2.0 which accompanies this distribution. 

- * The Eclipse Public License is available at 

- * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0

- * is available at http://www.opensource.org/licenses/apache2.0.php.

- * You may elect to redistribute this code under either of these licenses. 

- * 

- * Contributors:

- *   VMware Inc.

- *****************************************************************************/

+/*

+ Copyright (c) 2006, 2010 VMware Inc.

+ All rights reserved. This program and the accompanying materials

+ are made available under the terms of the Eclipse Public License v1.0

+ and Apache License v2.0 which accompanies this distribution.

+ The Eclipse Public License is available at

+ http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0

+ is available at http://www.opensource.org/licenses/apache2.0.php.

+ You may elect to redistribute this code under either of these licenses.

+

+ Contributors:

+ VMware Inc.

+ */

 

 package org.eclipse.gemini.blueprint.mock;

 

-import java.io.File;

-import java.io.IOException;

-import java.io.InputStream;

-import java.net.URL;

-import java.util.Collections;

-import java.util.Dictionary;

-import java.util.Enumeration;

-import java.util.Hashtable;

-import java.util.Map;

-import java.util.NoSuchElementException;

-

 import org.osgi.framework.Bundle;

 import org.osgi.framework.BundleContext;

 import org.osgi.framework.BundleException;

@@ -32,6 +21,19 @@
 import org.osgi.framework.ServiceReference;

 import org.osgi.framework.Version;

 

+import java.io.File;

+import java.io.IOException;

+import java.io.InputStream;

+import java.net.URL;

+import java.security.cert.X509Certificate;

+import java.util.Collections;

+import java.util.Dictionary;

+import java.util.Enumeration;

+import java.util.Hashtable;

+import java.util.List;

+import java.util.Map;

+import java.util.NoSuchElementException;

+

 /**

  * Bundle mock. Except resource/class loading operations (which are executed on its internal class loader), the rest of

  * the methods are dummies.

@@ -42,7 +44,7 @@
 

 	private String location;

 

-	private final Dictionary headers;

+	private final Dictionary<String, String> headers;

 

 	private static int GENERAL_BUNDLE_ID = 0;

 

@@ -53,8 +55,6 @@
 

 	private ClassLoader loader = getClass().getClassLoader();

 

-	private final Dictionary defaultHeaders = new Hashtable(0);

-

 	private final String SYMBOLIC_NAME = "Mock-Bundle_" + System.currentTimeMillis();

 

 	private final String symName;

@@ -66,13 +66,13 @@
         return 0;  //To change body of implemented methods use File | Settings | File Templates.

     }

 

-    private static class EmptyEnumeration implements Enumeration {

+    private static class EmptyEnumeration<T> implements Enumeration<T> {

 

 		public boolean hasMoreElements() {

 			return false;

 		}

 

-		public Object nextElement() {

+		public T nextElement() {

 			throw new NoSuchElementException();

 		}

 	}

@@ -122,6 +122,7 @@
 	 */

 	public MockBundle(String symName, Dictionary headers, BundleContext context) {

 		this.symName = ((symName != null && symName.length() > 0) ? symName : SYMBOLIC_NAME);

+		Dictionary<String, String> defaultHeaders = new Hashtable<>(0);

 		defaultHeaders.put("Bundle-SymbolicName", this.symName);

 

 		this.location = "<default location>";

@@ -135,7 +136,7 @@
 	 * 

 	 * @see org.osgi.framework.Bundle#findEntries(java.lang.String, java.lang.String, boolean)

 	 */

-	public Enumeration findEntries(String path, String filePattern, boolean recurse) {

+	public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) {

 		Enumeration enm = null;

 

 		try {

@@ -159,15 +160,15 @@
 		return loader.getResource(name);

 	}

 

-	public Enumeration getEntryPaths(String path) {

-		return new EmptyEnumeration();

+	public Enumeration<String> getEntryPaths(String path) {

+		return new EmptyEnumeration<>();

 	}

 

-	public Dictionary getHeaders() {

+	public Dictionary<String, String> getHeaders() {

 		return headers;

 	}

 

-	public Dictionary getHeaders(String locale) {

+	public Dictionary<String, String> getHeaders(String locale) {

 		return getHeaders();

 	}

 

@@ -187,7 +188,7 @@
 		return loader.getResource(name);

 	}

 

-	public Enumeration getResources(String name) throws IOException {

+	public Enumeration<URL> getResources(String name) throws IOException {

 		return loader.getResources(name);

 	}

 

@@ -200,7 +201,7 @@
 	}

 

 	public String getSymbolicName() {

-		String name = (String) headers.get(Constants.BUNDLE_SYMBOLICNAME);

+		String name = headers.get(Constants.BUNDLE_SYMBOLICNAME);

 		return (name == null ? SYMBOLIC_NAME : name);

 	}

 

@@ -226,13 +227,13 @@
 	public void stop(int options) throws BundleException {

 	}

 

-	public void uninstall() throws BundleException {

+	public void uninstall() {

 	}

 

-	public void update() throws BundleException {

+	public void update() {

 	}

 

-	public void update(InputStream in) throws BundleException {

+	public void update(InputStream in) {

 	}

 

 	public Version getVersion() {

@@ -260,7 +261,7 @@
 		return Version.emptyVersion;

 	}

 

-	public Map getSignerCertificates(int signerType) {

+	public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signerType) {

 		return Collections.emptyMap();

 	}

 

diff --git a/mock/src/test/java/org/eclipse/gemini/blueprint/mock/EntryLookupControllingMockBundleTest.java b/mock/src/test/java/org/eclipse/gemini/blueprint/mock/EntryLookupControllingMockBundleTest.java
deleted file mode 100644
index 5db54cb..0000000
--- a/mock/src/test/java/org/eclipse/gemini/blueprint/mock/EntryLookupControllingMockBundleTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/******************************************************************************

- * Copyright (c) 2006, 2010 VMware Inc.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * and Apache License v2.0 which accompanies this distribution. 

- * The Eclipse Public License is available at 

- * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0

- * is available at http://www.opensource.org/licenses/apache2.0.php.

- * You may elect to redistribute this code under either of these licenses. 

- * 

- * Contributors:

- *   VMware Inc.

- *****************************************************************************/

-

-package org.eclipse.gemini.blueprint.mock;

-

-import java.net.URL;

-import java.util.Enumeration;

-import java.util.Properties;

-

-import org.eclipse.gemini.blueprint.mock.EntryLookupControllingMockBundle;

-

-import junit.framework.TestCase;

-

-/**

- * 

- * @author Costin Leau

- * 

- */

-public class EntryLookupControllingMockBundleTest extends TestCase {

-

-	private EntryLookupControllingMockBundle bundle;

-

-	protected void setUp() throws Exception {

-		bundle = new EntryLookupControllingMockBundle(new Properties());

-	}

-

-	protected void tearDown() throws Exception {

-		bundle = null;

-	}

-

-	public void testGetEntry() throws Exception {

-		URL url = new URL("http://bo/ho");

-		bundle.setEntryReturnOnNextCallToGetEntry(url);

-		assertSame(url, bundle.getEntry("bla"));

-	}

-

-	public void testFindEntries() throws Exception {

-		String[] source = new String[] {"A"};

-		bundle.setResultsToReturnOnNextCallToFindEntries(source);

-		Enumeration enm = bundle.findEntries(null, null, false);

-		assertNotNull(enm);

-		assertTrue(enm.hasMoreElements());

-		assertEquals("A", enm.nextElement());

-	}

-}

diff --git a/test-support/src/main/java/org/eclipse/gemini/blueprint/test/AbstractSynchronizedOsgiTests.java b/test-support/src/main/java/org/eclipse/gemini/blueprint/test/AbstractSynchronizedOsgiTests.java
index 8b6236d..d4e1e88 100644
--- a/test-support/src/main/java/org/eclipse/gemini/blueprint/test/AbstractSynchronizedOsgiTests.java
+++ b/test-support/src/main/java/org/eclipse/gemini/blueprint/test/AbstractSynchronizedOsgiTests.java
@@ -240,7 +240,7 @@
 	 * @return boolean true if spring managed or false.

 	 */

 	protected boolean isSpringDMManaged(Bundle bundle) {

-		if (!ObjectUtils.isEmpty(ConfigUtils.getHeaderLocations(bundle.getHeaders()))) {

+		if (!ObjectUtils.isEmpty(ConfigUtils.getSpringDmHeaderLocations(bundle.getHeaders()))) {

 			return true;

         }

         // TODO: do we need to check for blueprint?