FELIX-2106, FELIX-692: Control which repositories are used for a given resolver
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@915288 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundlerepository/pom.xml b/bundlerepository/pom.xml
index 058a13a..5f41be9 100644
--- a/bundlerepository/pom.xml
+++ b/bundlerepository/pom.xml
@@ -65,6 +65,11 @@
<version>4.0.7</version>
<optional>true</optional>
</dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>2.4</version>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/LocalRepositoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/LocalRepositoryImpl.java
index 4614aba..093cdca 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/LocalRepositoryImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/LocalRepositoryImpl.java
@@ -19,25 +19,15 @@
package org.apache.felix.bundlerepository;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Enumeration;
import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
import org.osgi.framework.AllServiceListener;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
-import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceReference;
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.service.obr.Repository;
import org.osgi.service.obr.Resource;
@@ -98,10 +88,15 @@
* is synchronized on this instance to prevent data structure
* corruption.
*/
-
+
+ // Ignore system bundle
+ if (bundle.getBundleId() == 0)
+ {
+ return;
+ }
try
{
- m_localResourceList.put(new Long(bundle.getBundleId()), new LocalResourceImpl(bundle, m_logger));
+ m_localResourceList.put(new Long(bundle.getBundleId()), new LocalResourceImpl(bundle));
}
catch (InvalidSyntaxException ex)
{
@@ -149,6 +144,11 @@
return (Resource[]) m_localResourceList.values().toArray(new Resource[m_localResourceList.size()]);
}
+ public boolean isLocal()
+ {
+ return true;
+ }
+
private void initialize()
{
// register for bundle and service events now
@@ -173,314 +173,4 @@
}
}
- public static class LocalResourceImpl extends ResourceImpl
- {
- private Bundle m_bundle = null;
-
- LocalResourceImpl(Bundle bundle, Logger logger) throws InvalidSyntaxException
- {
- this(null, bundle, logger);
- }
-
- LocalResourceImpl(ResourceImpl resource, Bundle bundle, Logger logger)
- throws InvalidSyntaxException
- {
- super(resource);
- m_bundle = bundle;
- initialize();
- }
-
- public Bundle getBundle()
- {
- return m_bundle;
- }
-
- private void initialize() throws InvalidSyntaxException
- {
- Dictionary dict = m_bundle.getHeaders();
-
- // Convert bundle manifest header attributes to resource properties.
- convertAttributesToProperties(dict);
-
- // Convert properties to bundle capability
- convertAttributesToBundleCapability();
-
- // Convert import package declarations into requirements.
- convertImportPackageToRequirement(dict);
-
- // Convert import service declarations into requirements.
- convertImportServiceToRequirement(dict);
-
- // Convert export package declarations into capabilities.
- convertExportPackageToCapability(dict);
-
- // Convert export service declarations and services into capabilities.
- convertExportServiceToCapability(dict, m_bundle);
-
- // For the system bundle, add a special platform capability.
- if (m_bundle.getBundleId() == 0)
- {
- // set the execution environment(s) as Capability ee of the
- // system bundle to resolve bundles with specifc requirements
- String ee = m_bundle.getBundleContext().getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
- if (ee != null)
- {
- StringTokenizer tokener = new StringTokenizer(ee, ",");
- List eeList = new ArrayList();
- while (tokener.hasMoreTokens())
- {
- String eeName = tokener.nextToken().trim();
- if (eeName.length() > 0)
- {
- eeList.add(eeName);
- }
- }
- CapabilityImpl cap = new CapabilityImpl();
- cap.setName("ee");
- cap.addP("ee", eeList);
- addCapability(cap);
- }
-
-/* TODO: OBR - Fix system capabilities.
- // Create a case-insensitive map.
- Map map = new TreeMap(new Comparator() {
- public int compare(Object o1, Object o2)
- {
- return o1.toString().compareToIgnoreCase(o2.toString());
- }
- });
- map.put(
- Constants.FRAMEWORK_VERSION,
- m_context.getProperty(Constants.FRAMEWORK_VERSION));
- map.put(
- Constants.FRAMEWORK_VENDOR,
- m_context.getProperty(Constants.FRAMEWORK_VENDOR));
- map.put(
- Constants.FRAMEWORK_LANGUAGE,
- m_context.getProperty(Constants.FRAMEWORK_LANGUAGE));
- map.put(
- Constants.FRAMEWORK_OS_NAME,
- m_context.getProperty(Constants.FRAMEWORK_OS_NAME));
- map.put(
- Constants.FRAMEWORK_OS_VERSION,
- m_context.getProperty(Constants.FRAMEWORK_OS_VERSION));
- map.put(
- Constants.FRAMEWORK_PROCESSOR,
- m_context.getProperty(Constants.FRAMEWORK_PROCESSOR));
-// map.put(
-// FelixConstants.FELIX_VERSION_PROPERTY,
-// m_context.getProperty(FelixConstants.FELIX_VERSION_PROPERTY));
- Map[] capMaps = (Map[]) bundleMap.get("capability");
- if (capMaps == null)
- {
- capMaps = new Map[] { map };
- }
- else
- {
- Map[] newCaps = new Map[capMaps.length + 1];
- newCaps[0] = map;
- System.arraycopy(capMaps, 0, newCaps, 1, capMaps.length);
- capMaps = newCaps;
- }
- bundleMap.put("capability", capMaps);
-*/
- }
- }
-
- private void convertAttributesToProperties(Dictionary dict)
- {
- for (Enumeration keys = dict.keys(); keys.hasMoreElements(); )
- {
- String key = (String) keys.nextElement();
- if (key.equalsIgnoreCase(Constants.BUNDLE_SYMBOLICNAME))
- {
- String sn = (String) dict.get(key);
- sn = sn.trim();
- int index = sn.indexOf(";singleton:=true");
- if (index != -1) {
- sn = sn.substring(0, index);
- }
- put(Resource.SYMBOLIC_NAME, sn);
- }
- else if (key.equalsIgnoreCase(Constants.BUNDLE_NAME))
- {
- put(Resource.PRESENTATION_NAME, (String) dict.get(key));
- }
- else if (key.equalsIgnoreCase(Constants.BUNDLE_VERSION))
- {
- put(Resource.VERSION, (String) dict.get(key));
- }
- else if (key.equalsIgnoreCase("Bundle-Source"))
- {
- put(Resource.SOURCE_URL, (String) dict.get(key));
- }
- else if (key.equalsIgnoreCase(Constants.BUNDLE_DESCRIPTION))
- {
- put(Resource.DESCRIPTION, (String) dict.get(key));
- }
- else if (key.equalsIgnoreCase(Constants.BUNDLE_DOCURL))
- {
- put(Resource.DOCUMENTATION_URL, (String) dict.get(key));
- }
- else if (key.equalsIgnoreCase(Constants.BUNDLE_COPYRIGHT))
- {
- put(Resource.COPYRIGHT, (String) dict.get(key));
- }
- else if (key.equalsIgnoreCase("Bundle-License"))
- {
- put(Resource.LICENSE_URL, (String) dict.get(key));
- }
- }
- }
-
- private void convertAttributesToBundleCapability()
- {
- CapabilityImpl cap = new CapabilityImpl();
- cap.setName("bundle");
- if (getPresentationName() != null) {
- cap.addP(Resource.PRESENTATION_NAME, getPresentationName());
- }
- cap.addP(Resource.SYMBOLIC_NAME, getSymbolicName());
- cap.addP(Resource.VERSION, getVersion());
- addCapability(cap);
- }
-
- private void convertImportPackageToRequirement(Dictionary dict)
- throws InvalidSyntaxException
- {
- String target = (String) dict.get(Constants.IMPORT_PACKAGE);
- if (target != null)
- {
- R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
- R4Import[] imports = new R4Import[pkgs.length];
- for (int i = 0; i < pkgs.length; i++)
- {
- imports[i] = new R4Import(pkgs[i]);
- }
-
- for (int impIdx = 0; impIdx < imports.length; impIdx++)
- {
- RequirementImpl req = new RequirementImpl();
- req.setMultiple("false");
- req.setOptional(Boolean.toString(imports[impIdx].isOptional()));
- req.setName("package");
- req.addText("Import package " + imports[impIdx].toString());
-
- String low = imports[impIdx].isLowInclusive()
- ? "(version>=" + imports[impIdx].getVersion() + ")"
- : "(!(version<=" + imports[impIdx].getVersion() + "))";
-
- if (imports[impIdx].getVersionHigh() != null)
- {
- String high = imports[impIdx].isHighInclusive()
- ? "(version<=" + imports[impIdx].getVersionHigh() + ")"
- : "(!(version>=" + imports[impIdx].getVersionHigh() + "))";
- req.setFilter("(&(package="
- + imports[impIdx].getName() + ")"
- + low + high + ")");
- }
- else
- {
- req.setFilter(
- "(&(package="
- + imports[impIdx].getName() + ")"
- + low + ")");
- }
-
- addRequire(req);
- }
- }
- }
-
- private void convertImportServiceToRequirement(Dictionary dict)
- throws InvalidSyntaxException
- {
- String target = (String) dict.get(Constants.IMPORT_SERVICE);
- if (target != null)
- {
- R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
- for (int pkgIdx = 0; (pkgs != null) && (pkgIdx < pkgs.length); pkgIdx++)
- {
- RequirementImpl req = new RequirementImpl();
- req.setMultiple("false");
- req.setName("service");
- req.addText("Import service " + pkgs[pkgIdx].toString());
- req.setFilter("(service="
- + pkgs[pkgIdx].getName() + ")");
- addRequire(req);
- }
- }
- }
-
- private void convertExportPackageToCapability(Dictionary dict)
- {
- String target = (String) dict.get(Constants.EXPORT_PACKAGE);
- if (target != null)
- {
- R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
- for (int pkgIdx = 0; (pkgs != null) && (pkgIdx < pkgs.length); pkgIdx++)
- {
- CapabilityImpl cap = new CapabilityImpl();
- cap.setName("package");
- cap.addP(new PropertyImpl("package", null, pkgs[pkgIdx].getName()));
- cap.addP(new PropertyImpl("version", "version", pkgs[pkgIdx].getVersion().toString()));
- for (int i = 0; i < pkgs[pkgIdx].getAttributes().length; i++)
- {
- R4Attribute attribute = pkgs[pkgIdx].getAttributes()[i];
- String key = attribute.getName();
- if (!key.equalsIgnoreCase("specification-version")
- && !key.equalsIgnoreCase("version"))
- {
- Object value = attribute.getValue();
- cap.addP(key, value);
- }
- }
- for (int i = 0; i < pkgs[pkgIdx].getDirectives().length; i++)
- {
- R4Directive directive = pkgs[pkgIdx].getDirectives()[i];
- String key = directive.getName() + ":";
- Object value = directive.getValue();
- cap.addP(key, value);
- }
- addCapability(cap);
- }
- }
- }
-
- private void convertExportServiceToCapability(Dictionary dict, Bundle bundle)
- {
- Set services = new HashSet();
-
- // collect Export-Service
- String target = (String) dict.get(Constants.EXPORT_SERVICE);
- if (target != null)
- {
- R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
- for (int pkgIdx = 0; (pkgs != null) && (pkgIdx < pkgs.length); pkgIdx++)
- {
- services.add(pkgs[pkgIdx].getName());
- }
- }
-
- // add actual registered services
- ServiceReference[] refs = bundle.getRegisteredServices();
- for (int i = 0; refs != null && i < refs.length; i++)
- {
- String[] cls = (String[]) refs[i].getProperty(Constants.OBJECTCLASS);
- for (int j = 0; cls != null && j < cls.length; j++)
- {
- services.add(cls[j]);
- }
- }
-
- // register capabilities for combined set
- for (Iterator si = services.iterator(); si.hasNext();)
- {
- CapabilityImpl cap = new CapabilityImpl();
- cap.setName("service");
- cap.addP(new PropertyImpl("service", null, (String) si.next()));
- addCapability(cap);
- }
- }
- }
}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/LocalResourceImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/LocalResourceImpl.java
new file mode 100644
index 0000000..785efec
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/LocalResourceImpl.java
@@ -0,0 +1,345 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.bundlerepository;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.obr.Resource;
+
+public class LocalResourceImpl extends ResourceImpl
+{
+ private Bundle m_bundle = null;
+
+ LocalResourceImpl(Bundle bundle) throws InvalidSyntaxException
+ {
+ this(null, bundle);
+ }
+
+ LocalResourceImpl(ResourceImpl resource, Bundle bundle)
+ throws InvalidSyntaxException
+ {
+ super(resource);
+ m_bundle = bundle;
+ initialize();
+ }
+
+ public Bundle getBundle()
+ {
+ return m_bundle;
+ }
+
+ private void initialize() throws InvalidSyntaxException
+ {
+ Dictionary dict = m_bundle.getHeaders();
+
+ // Convert bundle manifest header attributes to resource properties.
+ convertAttributesToProperties(dict);
+
+ // Convert properties to bundle capability
+ convertAttributesToBundleCapability();
+
+ // Convert import package declarations into requirements.
+ convertImportPackageToRequirement(dict);
+
+ // Convert import service declarations into requirements.
+ convertImportServiceToRequirement(dict);
+
+ // Convert export package declarations into capabilities.
+ convertExportPackageToCapability(dict);
+
+ // Convert export service declarations and services into capabilities.
+ convertExportServiceToCapability(dict, m_bundle);
+
+ // For the system bundle, add a special platform capability.
+ if (m_bundle.getBundleId() == 0)
+ {
+ // set the execution environment(s) as Capability ee of the
+ // system bundle to resolve bundles with specifc requirements
+ String ee = m_bundle.getBundleContext().getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
+ if (ee != null)
+ {
+ StringTokenizer tokener = new StringTokenizer(ee, ",");
+ List eeList = new ArrayList();
+ while (tokener.hasMoreTokens())
+ {
+ String eeName = tokener.nextToken().trim();
+ if (eeName.length() > 0)
+ {
+ eeList.add(eeName);
+ }
+ }
+ CapabilityImpl cap = new CapabilityImpl();
+ cap.setName("ee");
+ cap.addP("ee", eeList);
+ addCapability(cap);
+ }
+
+/* TODO: OBR - Fix system capabilities.
+ // Create a case-insensitive map.
+ Map map = new TreeMap(new Comparator() {
+ public int compare(Object o1, Object o2)
+ {
+ return o1.toString().compareToIgnoreCase(o2.toString());
+ }
+ });
+ map.put(
+ Constants.FRAMEWORK_VERSION,
+ m_context.getProperty(Constants.FRAMEWORK_VERSION));
+ map.put(
+ Constants.FRAMEWORK_VENDOR,
+ m_context.getProperty(Constants.FRAMEWORK_VENDOR));
+ map.put(
+ Constants.FRAMEWORK_LANGUAGE,
+ m_context.getProperty(Constants.FRAMEWORK_LANGUAGE));
+ map.put(
+ Constants.FRAMEWORK_OS_NAME,
+ m_context.getProperty(Constants.FRAMEWORK_OS_NAME));
+ map.put(
+ Constants.FRAMEWORK_OS_VERSION,
+ m_context.getProperty(Constants.FRAMEWORK_OS_VERSION));
+ map.put(
+ Constants.FRAMEWORK_PROCESSOR,
+ m_context.getProperty(Constants.FRAMEWORK_PROCESSOR));
+// map.put(
+// FelixConstants.FELIX_VERSION_PROPERTY,
+// m_context.getProperty(FelixConstants.FELIX_VERSION_PROPERTY));
+ Map[] capMaps = (Map[]) bundleMap.get("capability");
+ if (capMaps == null)
+ {
+ capMaps = new Map[] { map };
+ }
+ else
+ {
+ Map[] newCaps = new Map[capMaps.length + 1];
+ newCaps[0] = map;
+ System.arraycopy(capMaps, 0, newCaps, 1, capMaps.length);
+ capMaps = newCaps;
+ }
+ bundleMap.put("capability", capMaps);
+*/
+ }
+ }
+
+ private void convertAttributesToProperties(Dictionary dict)
+ {
+ for (Enumeration keys = dict.keys(); keys.hasMoreElements(); )
+ {
+ String key = (String) keys.nextElement();
+ if (key.equalsIgnoreCase(Constants.BUNDLE_SYMBOLICNAME))
+ {
+ String sn = (String) dict.get(key);
+ sn = sn.trim();
+ int index = sn.indexOf(";singleton:=true");
+ if (index != -1) {
+ sn = sn.substring(0, index);
+ }
+ put(Resource.SYMBOLIC_NAME, sn);
+ }
+ else if (key.equalsIgnoreCase(Constants.BUNDLE_NAME))
+ {
+ put(Resource.PRESENTATION_NAME, (String) dict.get(key));
+ }
+ else if (key.equalsIgnoreCase(Constants.BUNDLE_VERSION))
+ {
+ put(Resource.VERSION, (String) dict.get(key));
+ }
+ else if (key.equalsIgnoreCase("Bundle-Source"))
+ {
+ put(Resource.SOURCE_URL, (String) dict.get(key));
+ }
+ else if (key.equalsIgnoreCase(Constants.BUNDLE_DESCRIPTION))
+ {
+ put(Resource.DESCRIPTION, (String) dict.get(key));
+ }
+ else if (key.equalsIgnoreCase(Constants.BUNDLE_DOCURL))
+ {
+ put(Resource.DOCUMENTATION_URL, (String) dict.get(key));
+ }
+ else if (key.equalsIgnoreCase(Constants.BUNDLE_COPYRIGHT))
+ {
+ put(Resource.COPYRIGHT, (String) dict.get(key));
+ }
+ else if (key.equalsIgnoreCase("Bundle-License"))
+ {
+ put(Resource.LICENSE_URL, (String) dict.get(key));
+ }
+ }
+ }
+
+ private void convertAttributesToBundleCapability()
+ {
+ CapabilityImpl cap = new CapabilityImpl();
+ cap.setName("bundle");
+ if (getPresentationName() != null) {
+ cap.addP(Resource.PRESENTATION_NAME, getPresentationName());
+ }
+ cap.addP(Resource.SYMBOLIC_NAME, getSymbolicName());
+ cap.addP(Resource.VERSION, getVersion());
+ addCapability(cap);
+ }
+
+ private void convertImportPackageToRequirement(Dictionary dict)
+ throws InvalidSyntaxException
+ {
+ String target = (String) dict.get(Constants.IMPORT_PACKAGE);
+ if (target != null)
+ {
+ R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
+ R4Import[] imports = new R4Import[pkgs.length];
+ for (int i = 0; i < pkgs.length; i++)
+ {
+ imports[i] = new R4Import(pkgs[i]);
+ }
+
+ for (int impIdx = 0; impIdx < imports.length; impIdx++)
+ {
+ RequirementImpl req = new RequirementImpl();
+ req.setMultiple("false");
+ req.setOptional(Boolean.toString(imports[impIdx].isOptional()));
+ req.setName("package");
+ req.addText("Import package " + imports[impIdx].toString());
+
+ String low = imports[impIdx].isLowInclusive()
+ ? "(version>=" + imports[impIdx].getVersion() + ")"
+ : "(!(version<=" + imports[impIdx].getVersion() + "))";
+
+ if (imports[impIdx].getVersionHigh() != null)
+ {
+ String high = imports[impIdx].isHighInclusive()
+ ? "(version<=" + imports[impIdx].getVersionHigh() + ")"
+ : "(!(version>=" + imports[impIdx].getVersionHigh() + "))";
+ req.setFilter("(&(package="
+ + imports[impIdx].getName() + ")"
+ + low + high + ")");
+ }
+ else
+ {
+ req.setFilter(
+ "(&(package="
+ + imports[impIdx].getName() + ")"
+ + low + ")");
+ }
+
+ addRequire(req);
+ }
+ }
+ }
+
+ private void convertImportServiceToRequirement(Dictionary dict)
+ throws InvalidSyntaxException
+ {
+ String target = (String) dict.get(Constants.IMPORT_SERVICE);
+ if (target != null)
+ {
+ R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
+ for (int pkgIdx = 0; (pkgs != null) && (pkgIdx < pkgs.length); pkgIdx++)
+ {
+ RequirementImpl req = new RequirementImpl();
+ req.setMultiple("false");
+ req.setName("service");
+ req.addText("Import service " + pkgs[pkgIdx].toString());
+ req.setFilter("(service="
+ + pkgs[pkgIdx].getName() + ")");
+ addRequire(req);
+ }
+ }
+ }
+
+ private void convertExportPackageToCapability(Dictionary dict)
+ {
+ String target = (String) dict.get(Constants.EXPORT_PACKAGE);
+ if (target != null)
+ {
+ R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
+ for (int pkgIdx = 0; (pkgs != null) && (pkgIdx < pkgs.length); pkgIdx++)
+ {
+ CapabilityImpl cap = new CapabilityImpl();
+ cap.setName("package");
+ cap.addP(new PropertyImpl("package", null, pkgs[pkgIdx].getName()));
+ cap.addP(new PropertyImpl("version", "version", pkgs[pkgIdx].getVersion().toString()));
+ for (int i = 0; i < pkgs[pkgIdx].getAttributes().length; i++)
+ {
+ R4Attribute attribute = pkgs[pkgIdx].getAttributes()[i];
+ String key = attribute.getName();
+ if (!key.equalsIgnoreCase("specification-version")
+ && !key.equalsIgnoreCase("version"))
+ {
+ Object value = attribute.getValue();
+ cap.addP(key, value);
+ }
+ }
+ for (int i = 0; i < pkgs[pkgIdx].getDirectives().length; i++)
+ {
+ R4Directive directive = pkgs[pkgIdx].getDirectives()[i];
+ String key = directive.getName() + ":";
+ Object value = directive.getValue();
+ cap.addP(key, value);
+ }
+ addCapability(cap);
+ }
+ }
+ }
+
+ private void convertExportServiceToCapability(Dictionary dict, Bundle bundle)
+ {
+ Set services = new HashSet();
+
+ // collect Export-Service
+ String target = (String) dict.get(Constants.EXPORT_SERVICE);
+ if (target != null)
+ {
+ R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
+ for (int pkgIdx = 0; (pkgs != null) && (pkgIdx < pkgs.length); pkgIdx++)
+ {
+ services.add(pkgs[pkgIdx].getName());
+ }
+ }
+
+ // add actual registered services
+ ServiceReference[] refs = bundle.getRegisteredServices();
+ for (int i = 0; refs != null && i < refs.length; i++)
+ {
+ String[] cls = (String[]) refs[i].getProperty(Constants.OBJECTCLASS);
+ for (int j = 0; cls != null && j < cls.length; j++)
+ {
+ services.add(cls[j]);
+ }
+ }
+
+ // register capabilities for combined set
+ for (Iterator si = services.iterator(); si.hasNext();)
+ {
+ CapabilityImpl cap = new CapabilityImpl();
+ cap.setName("service");
+ cap.addP(new PropertyImpl("service", null, (String) si.next()));
+ addCapability(cap);
+ }
+ }
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Logger.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Logger.java
index b40630d..f8b8005 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Logger.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Logger.java
@@ -49,7 +49,7 @@
/**
* Constructor.
*
- * @param bundleContext bundle context
+ * @param context bundle context
*/
Logger(BundleContext context)
{
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdminImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdminImpl.java
index 3b1f1da..7149e62 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdminImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdminImpl.java
@@ -42,6 +42,7 @@
{
static BundleContext m_context = null;
private final Logger m_logger;
+ private final SystemRepositoryImpl m_system;
private final LocalRepositoryImpl m_local;
private List m_urlList = new ArrayList();
private Map m_repoMap = new HashMap();
@@ -57,14 +58,20 @@
{
m_context = context;
m_logger = logger;
+ m_system = new SystemRepositoryImpl(context, logger);
m_local = new LocalRepositoryImpl(context, logger);
}
- LocalRepositoryImpl getLocalRepository()
+ public Repository getLocalRepository()
{
return m_local;
}
+ public Repository getSystemRepository()
+ {
+ return m_system;
+ }
+
public void dispose()
{
m_local.dispose();
@@ -118,7 +125,22 @@
initialize();
}
- return new ResolverImpl(m_context, this, m_logger);
+ List repositories = new ArrayList();
+ repositories.add(m_system);
+ repositories.add(m_local);
+ repositories.addAll(m_repoMap.values());
+
+ return resolver((Repository[]) repositories.toArray(new Repository[repositories.size()]));
+ }
+
+ public synchronized Resolver resolver(Repository[] repositories)
+ {
+ if (!m_initialized)
+ {
+ initialize();
+ }
+
+ return new ResolverImpl(m_context, repositories, m_logger);
}
public synchronized Resource[] discoverResources(String filterExpr)
@@ -231,6 +253,11 @@
return new FilterImpl(filter);
}
+ public Repository repository(URL url) throws Exception
+ {
+ return new RepositoryImpl(null, url, 0, m_logger);
+ }
+
private void initialize()
{
m_initialized = true;
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryImpl.java
index 825bbac..f4e6c04 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryImpl.java
@@ -170,6 +170,11 @@
}
}
+ public boolean isLocal()
+ {
+ return false;
+ }
+
/**
* Default setter method when setting parsed data from the XML file,
* which currently ignores everything.
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/ResolverImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/ResolverImpl.java
index 79cc0c7..a8375fb 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/ResolverImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/ResolverImpl.java
@@ -21,7 +21,6 @@
import java.net.URL;
import java.util.*;
-import org.apache.felix.bundlerepository.LocalRepositoryImpl.LocalResourceImpl;
import org.osgi.framework.*;
import org.osgi.service.obr.*;
@@ -30,9 +29,8 @@
public static final String PREFER_LOCAL = "obr.resolver.preferLocal";
private final BundleContext m_context;
- private final RepositoryAdmin m_admin;
private final Logger m_logger;
- private final LocalRepositoryImpl m_local;
+ private final Repository[] m_repositories;
private final Set m_addedSet = new HashSet();
private final Set m_addedRequirementSet = new HashSet();
private final Set m_failedSet = new HashSet();
@@ -45,12 +43,11 @@
private long m_resolveTimeStamp;
private boolean m_preferLocal = true;
- public ResolverImpl(BundleContext context, RepositoryAdminImpl admin, Logger logger)
+ public ResolverImpl(BundleContext context, Repository[] repositories, Logger logger)
{
m_context = context;
- m_admin = admin;
m_logger = logger;
- m_local = admin.getLocalRepository();
+ m_repositories = repositories;
String s = context.getProperty(PREFER_LOCAL);
if (s != null)
{
@@ -131,10 +128,34 @@
throw new IllegalStateException("The resources have not been resolved.");
}
+ private Resource[] getResources(boolean local)
+ {
+ List resources = new ArrayList();
+ for (int repoIdx = 0; (m_repositories != null) && (repoIdx < m_repositories.length); repoIdx++)
+ {
+ if (m_repositories[repoIdx].isLocal() == local)
+ {
+ resources.addAll(Arrays.asList(m_repositories[repoIdx].getResources()));
+ }
+ }
+ return (Resource[]) resources.toArray(new Resource[resources.size()]);
+ }
+
public synchronized boolean resolve()
{
+ // Find resources
+ Resource[] locals = getResources(true);
+ Resource[] remotes = getResources(false);
+
// time of the resolution process start
- m_resolveTimeStamp = m_local.getLastModified();
+ m_resolveTimeStamp = 0;
+ for (int repoIdx = 0; (m_repositories != null) && (repoIdx < m_repositories.length); repoIdx++)
+ {
+ if (m_repositories[repoIdx].isLocal())
+ {
+ m_resolveTimeStamp = Math.max(m_resolveTimeStamp, m_repositories[repoIdx].getLastModified());
+ }
+ }
// Reset instance values.
m_failedSet.clear();
@@ -155,7 +176,7 @@
{
fake.addRequire((Requirement) iter.next());
}
- if (!resolve(fake))
+ if (!resolve(fake, locals, remotes))
{
result = false;
}
@@ -164,7 +185,7 @@
// Loop through each resource in added list and resolve.
for (Iterator iter = m_addedSet.iterator(); iter.hasNext(); )
{
- if (!resolve((Resource) iter.next()))
+ if (!resolve((Resource) iter.next(), locals, remotes))
{
// If any resource does not resolve, then the
// entire result will be false.
@@ -173,18 +194,17 @@
}
// Clean up the resulting data structures.
- List locals = Arrays.asList(m_local.getResources());
m_requiredSet.removeAll(m_addedSet);
- m_requiredSet.removeAll(locals);
+ m_requiredSet.removeAll(Arrays.asList(locals));
m_optionalSet.removeAll(m_addedSet);
m_optionalSet.removeAll(m_requiredSet);
- m_optionalSet.removeAll(locals);
+ m_optionalSet.removeAll(Arrays.asList(locals));
// Return final result.
return result;
}
- private boolean resolve(Resource resource)
+ private boolean resolve(Resource resource, Resource[] locals, Resource[] remotes)
{
boolean result = true;
@@ -216,8 +236,8 @@
candidate = searchResolvingResources(reqs[reqIdx]);
if (candidate == null)
{
- List candidateCapabilities = searchLocalResources(reqs[reqIdx]);
- candidateCapabilities.addAll(searchRemoteResources(reqs[reqIdx]));
+ List candidateCapabilities = searchResources(reqs[reqIdx], locals);
+ candidateCapabilities.addAll(searchResources(reqs[reqIdx], remotes));
// Determine the best candidate available that
// can resolve.
@@ -226,7 +246,7 @@
Capability bestCapability = getBestCandidate(candidateCapabilities);
// Try to resolve the best resource.
- if (resolve(((CapabilityImpl) bestCapability).getResource()))
+ if (resolve(((CapabilityImpl) bestCapability).getResource(), locals, remotes))
{
candidate = ((CapabilityImpl) bestCapability).getResource();
}
@@ -262,7 +282,7 @@
{
// Try to resolve the candidate.
- if (resolve(candidate))
+ if (resolve(candidate, locals, remotes))
{
// The resolved succeeded; record the candidate
// as either optional or required.
@@ -340,49 +360,16 @@
}
/**
- * Returns a local resource meeting the given requirement
- * @param req The requirement that the local resource must meet
- * @return Returns the found local resource if available
- */
- private List searchLocalResources(Requirement req)
- {
- List matchingCapabilities = new ArrayList();
- Resource[] resources = m_local.getResources();
- for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++)
- {
- checkInterrupt();
- // We don't need to look at resources we've already looked at.
- if (!m_failedSet.contains(resources[resIdx])
- && !m_resolveSet.contains(resources[resIdx]))
- {
- Capability[] caps = resources[resIdx].getCapabilities();
- for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
- {
- if (caps[capIdx].getName().equals(req.getName())
- && req.isSatisfied(caps[capIdx]))
- {
- matchingCapabilities.add(caps[capIdx]);
- }
- }
- }
- }
-
- return matchingCapabilities;
- }
-
- /**
- * Searches for remote resources that do meet the given requirement
+ * Searches for resources that do meet the given requirement
* @param req
- * @return all remote resources meeting the given requirement
+ * @return all resources meeting the given requirement
*/
- private List searchRemoteResources(Requirement req)
+ private List searchResources(Requirement req, Resource[] resources)
{
List matchingCapabilities = new ArrayList();
- Repository[] repos = m_admin.listRepositories();
- for (int repoIdx = 0; (repos != null) && (repoIdx < repos.length); repoIdx++)
+ for (int repoIdx = 0; (m_repositories != null) && (repoIdx < m_repositories.length); repoIdx++)
{
- Resource[] resources = repos[repoIdx].getResources();
for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++)
{
checkInterrupt();
@@ -499,9 +486,13 @@
// the state can still change during the operation, but we will
// be optimistic. This could also be made smarter so that it checks
// to see if the local state changes overlap with the resolver.
- if (m_resolveTimeStamp != m_local.getLastModified())
+ for (int repoIdx = 0; (m_repositories != null) && (repoIdx < m_repositories.length); repoIdx++)
{
- throw new IllegalStateException("Framework state has changed, must resolve again.");
+ if (m_repositories[repoIdx].isLocal()
+ && m_repositories[repoIdx].getLastModified() > m_resolveTimeStamp)
+ {
+ throw new IllegalStateException("Framework state has changed, must resolve again.");
+ }
}
// Eliminate duplicates from target, required, optional resources.
@@ -535,7 +526,7 @@
// For the resource being deployed, see if there is an older
// version of the resource already installed that can potentially
// be updated.
- LocalRepositoryImpl.LocalResourceImpl localResource =
+ LocalResourceImpl localResource =
findUpdatableLocalResource(deployResources[i]);
// If a potentially updatable older version was found,
// then verify that updating the local resource will not
@@ -691,7 +682,7 @@
// without breaking constraints of existing local resources.
for (int i = 0; i < localResources.length; i++)
{
- if (isResourceUpdatable(localResources[i], resource, m_local.getResources()))
+ if (isResourceUpdatable(localResources[i], resource, localResources))
{
return (LocalResourceImpl) localResources[i];
}
@@ -707,7 +698,7 @@
*/
private Resource[] findLocalResources(String symName)
{
- Resource[] localResources = m_local.getResources();
+ Resource[] localResources = getResources(true);
List matchList = new ArrayList();
for (int i = 0; i < localResources.length; i++)
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/SystemRepositoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/SystemRepositoryImpl.java
new file mode 100644
index 0000000..0ed0c56
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/SystemRepositoryImpl.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.bundlerepository;
+
+import java.net.URL;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.obr.Repository;
+import org.osgi.service.obr.Resource;
+
+public class SystemRepositoryImpl implements Repository
+{
+
+ private final Logger m_logger;
+ private final long lastModified;
+ private final LocalResourceImpl systemBundleResource;
+
+ public SystemRepositoryImpl(BundleContext context, Logger logger)
+ {
+ m_logger = logger;
+ lastModified = System.currentTimeMillis();
+ try
+ {
+ systemBundleResource = new LocalResourceImpl(context.getBundle(0));
+ }
+ catch (InvalidSyntaxException ex)
+ {
+ // This should never happen since we are generating filters,
+ // but ignore the resource if it does occur.
+ m_logger.log(Logger.LOG_WARNING, ex.getMessage(), ex);
+ throw new IllegalStateException("Unexpected error", ex);
+ }
+ }
+
+ public URL getURL()
+ {
+ return null;
+ }
+
+ public Resource[] getResources()
+ {
+ return new Resource[] { systemBundleResource };
+ }
+
+ public String getName()
+ {
+ return "System Repository";
+ }
+
+ public long getLastModified()
+ {
+ return lastModified;
+ }
+
+ public boolean isLocal()
+ {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/MockBundleContext.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/MockBundleContext.java
deleted file mode 100644
index 350f587..0000000
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/MockBundleContext.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.Dictionary;
-import java.util.Properties;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkListener;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-public class MockBundleContext implements BundleContext
-{
- private Properties props = new Properties();
-
- public void setProperty(String key, String val)
- {
- props.setProperty(key, val);
- }
-
- public void addBundleListener(BundleListener arg0)
- {
- }
-
- public void addFrameworkListener(FrameworkListener arg0)
- {
- }
-
- public void addServiceListener(ServiceListener arg0)
- {
- }
-
- public void addServiceListener(ServiceListener arg0, String arg1)
- {
- }
-
- public Filter createFilter(String arg0)
- {
- // returns a match-all filter always
- return new Filter()
- {
- public boolean matchCase(Dictionary arg0)
- {
- return true;
- }
-
- public boolean match(Dictionary arg0)
- {
- return true;
- }
-
- public boolean match(ServiceReference arg0)
- {
- return true;
- }
- };
- }
-
- public ServiceReference[] getAllServiceReferences(String arg0, String arg1)
- {
- return null;
- }
-
- public Bundle getBundle()
- {
- return null;
- }
-
- public Bundle getBundle(long arg0)
- {
- return null;
- }
-
- public Bundle[] getBundles()
- {
- return null;
- }
-
- public File getDataFile(String arg0)
- {
- return null;
- }
-
- public String getProperty(String name)
- {
- return props.getProperty(name);
- }
-
- public Object getService(ServiceReference arg0)
- {
- return null;
- }
-
- public ServiceReference getServiceReference(String arg0)
- {
- return null;
- }
-
- public ServiceReference[] getServiceReferences(String arg0, String arg1)
- {
- return null;
- }
-
- public Bundle installBundle(String arg0)
- {
- return null;
- }
-
- public Bundle installBundle(String arg0, InputStream arg1)
- {
- return null;
- }
-
- public ServiceRegistration registerService(String[] arg0, Object arg1, Dictionary arg2)
- {
- return null;
- }
-
- public ServiceRegistration registerService(String arg0, Object arg1, Dictionary arg2)
- {
- return null;
- }
-
- public void removeBundleListener(BundleListener arg0)
- {
- }
-
- public void removeFrameworkListener(FrameworkListener arg0)
- {
- }
-
- public void removeServiceListener(ServiceListener arg0)
- {
- }
-
- public boolean ungetService(ServiceReference arg0)
- {
- return false;
- }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryAdminTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryAdminTest.java
index d08cdf1..40d6576 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryAdminTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryAdminTest.java
@@ -19,9 +19,17 @@
package org.apache.felix.bundlerepository;
import java.net.URL;
+import java.util.Hashtable;
import junit.framework.TestCase;
-import org.osgi.framework.Filter;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.easymock.internal.matchers.Captures;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.ServiceListener;
import org.osgi.service.obr.Repository;
import org.osgi.service.obr.Resource;
@@ -43,13 +51,28 @@
assertEquals(1, resources.length);
}
- private RepositoryAdminImpl createRepositoryAdmin()
+ private RepositoryAdminImpl createRepositoryAdmin() throws Exception
{
- final MockBundleContext bundleContext = new MockBundleContext() {
- public Filter createFilter(String arg0) {
- return new FilterImpl(arg0);
+ BundleContext bundleContext = (BundleContext) EasyMock.createMock(BundleContext.class);
+ Bundle systemBundle = (Bundle) EasyMock.createMock(Bundle.class);
+
+ EasyMock.expect(bundleContext.getProperty((String) EasyMock.anyObject())).andReturn(null).anyTimes();
+ EasyMock.expect(bundleContext.getBundle(0)).andReturn(systemBundle);
+ EasyMock.expect(systemBundle.getHeaders()).andReturn(new Hashtable());
+ EasyMock.expect(systemBundle.getRegisteredServices()).andReturn(null);
+ EasyMock.expect(new Long(systemBundle.getBundleId())).andReturn(new Long(0)).anyTimes();
+ EasyMock.expect(systemBundle.getBundleContext()).andReturn(bundleContext);
+ bundleContext.addBundleListener((BundleListener) EasyMock.anyObject());
+ bundleContext.addServiceListener((ServiceListener) EasyMock.anyObject());
+ EasyMock.expect(bundleContext.getBundles()).andReturn(new Bundle[] { systemBundle });
+ final Capture c = new Capture();
+ EasyMock.expect(bundleContext.createFilter((String) capture(c))).andAnswer(new IAnswer() {
+ public Object answer() throws Throwable {
+ return new FilterImpl((String) c.getValue());
}
- };
+ }).anyTimes();
+ EasyMock.replay(new Object[] { bundleContext, systemBundle });
+
RepositoryAdminImpl repoAdmin = new RepositoryAdminImpl(bundleContext, new Logger(bundleContext));
// force initialization && remove all initial repositories
@@ -61,4 +84,10 @@
return repoAdmin;
}
-}
\ No newline at end of file
+
+ static Object capture(Capture capture) {
+ EasyMock.reportMatcher(new Captures(capture));
+ return null;
+ }
+
+}
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryImplTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryImplTest.java
index 38f02c8..38d6971 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryImplTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryImplTest.java
@@ -19,8 +19,17 @@
package org.apache.felix.bundlerepository;
import java.net.URL;
+import java.util.Dictionary;
+import java.util.Hashtable;
import junit.framework.TestCase;
+import org.easymock.EasyMock;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
import org.osgi.service.obr.Repository;
import org.osgi.service.obr.Resource;
@@ -80,9 +89,33 @@
assertEquals("referral1_repository", res[0].getRepository().getName());
}
- private RepositoryAdminImpl createRepositoryAdmin()
+ private RepositoryAdminImpl createRepositoryAdmin() throws Exception
{
- final MockBundleContext bundleContext = new MockBundleContext();
+ BundleContext bundleContext = (BundleContext) EasyMock.createMock(BundleContext.class);
+ Bundle systemBundle = (Bundle) EasyMock.createMock(Bundle.class);
+
+ EasyMock.expect(bundleContext.getProperty((String) EasyMock.anyObject())).andReturn(null).anyTimes();
+ EasyMock.expect(bundleContext.getBundle(0)).andReturn(systemBundle);
+ EasyMock.expect(systemBundle.getHeaders()).andReturn(new Hashtable());
+ EasyMock.expect(systemBundle.getRegisteredServices()).andReturn(null);
+ EasyMock.expect(new Long(systemBundle.getBundleId())).andReturn(new Long(0)).anyTimes();
+ EasyMock.expect(systemBundle.getBundleContext()).andReturn(bundleContext);
+ bundleContext.addBundleListener((BundleListener) EasyMock.anyObject());
+ bundleContext.addServiceListener((ServiceListener) EasyMock.anyObject());
+ EasyMock.expect(bundleContext.getBundles()).andReturn(new Bundle[] { systemBundle });
+ EasyMock.expect(bundleContext.createFilter(null)).andReturn(new Filter() {
+ public boolean match(ServiceReference reference) {
+ return true;
+ }
+ public boolean match(Dictionary dictionary) {
+ return true;
+ }
+ public boolean matchCase(Dictionary dictionary) {
+ return true;
+ }
+ }).anyTimes();
+ EasyMock.replay(new Object[] { bundleContext, systemBundle });
+
RepositoryAdminImpl repoAdmin = new RepositoryAdminImpl(bundleContext, new Logger(bundleContext));
// force initialization && remove all initial repositories
@@ -94,4 +127,5 @@
return repoAdmin;
}
+
}
\ No newline at end of file
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/ResolverImplTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/ResolverImplTest.java
index e55288d..dd3a706 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/ResolverImplTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/ResolverImplTest.java
@@ -19,9 +19,18 @@
package org.apache.felix.bundlerepository;
import java.net.URL;
+import java.util.Hashtable;
import junit.framework.TestCase;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.easymock.internal.matchers.Captures;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.ServiceListener;
import org.osgi.service.obr.InterruptedResolutionException;
import org.osgi.service.obr.Repository;
import org.osgi.service.obr.Requirement;
@@ -39,19 +48,11 @@
Resolver resolver = repoAdmin.resolver();
- Resource r = null;
- //MockContext doesn't support filtering!
- Resource[] discoverResources = repoAdmin.discoverResources("");
- for (int i = 0; i < discoverResources.length; i++)
- {
- Resource resource = discoverResources[i];
- if (resource.getSymbolicName().contains("org.apache.felix.test"))
- {
- r = resource;
- }
- }
+ Resource[] discoverResources = repoAdmin.discoverResources("(symbolicname=org.apache.felix.test*)");
+ assertNotNull(discoverResources);
+ assertEquals(1, discoverResources.length);
- resolver.add(r);
+ resolver.add(discoverResources[0]);
assertTrue(resolver.resolve());
}
@@ -102,11 +103,30 @@
new ResolverImplTest().testReferral1();
}
- private RepositoryAdminImpl createRepositoryAdmin()
+ private RepositoryAdminImpl createRepositoryAdmin() throws Exception
{
- final MockBundleContext bundleContext = new MockBundleContext();
- bundleContext.setProperty(RepositoryAdminImpl.REPOSITORY_URL_PROP,
- getClass().getResource("/referred.xml").toExternalForm());
+ BundleContext bundleContext = (BundleContext) EasyMock.createMock(BundleContext.class);
+ Bundle systemBundle = (Bundle) EasyMock.createMock(Bundle.class);
+
+ EasyMock.expect(bundleContext.getProperty(RepositoryAdminImpl.REPOSITORY_URL_PROP))
+ .andReturn(getClass().getResource("/referred.xml").toExternalForm());
+ EasyMock.expect(bundleContext.getProperty((String) EasyMock.anyObject())).andReturn(null).anyTimes();
+ EasyMock.expect(bundleContext.getBundle(0)).andReturn(systemBundle);
+ EasyMock.expect(systemBundle.getHeaders()).andReturn(new Hashtable());
+ EasyMock.expect(systemBundle.getRegisteredServices()).andReturn(null);
+ EasyMock.expect(new Long(systemBundle.getBundleId())).andReturn(new Long(0)).anyTimes();
+ EasyMock.expect(systemBundle.getBundleContext()).andReturn(bundleContext);
+ bundleContext.addBundleListener((BundleListener) EasyMock.anyObject());
+ bundleContext.addServiceListener((ServiceListener) EasyMock.anyObject());
+ EasyMock.expect(bundleContext.getBundles()).andReturn(new Bundle[] { systemBundle });
+ final Capture c = new Capture();
+ EasyMock.expect(bundleContext.createFilter((String) capture(c))).andAnswer(new IAnswer() {
+ public Object answer() throws Throwable {
+ return new FilterImpl((String) c.getValue());
+ }
+ }).anyTimes();
+ EasyMock.replay(new Object[] { bundleContext, systemBundle });
+
RepositoryAdminImpl repoAdmin = new RepositoryAdminImpl(bundleContext, new Logger(bundleContext));
// force initialization && remove all initial repositories
@@ -118,4 +138,10 @@
return repoAdmin;
}
+
+ static Object capture(Capture capture) {
+ EasyMock.reportMatcher(new Captures(capture));
+ return null;
+ }
+
}
\ No newline at end of file
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/StaxParserTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/StaxParserTest.java
index b78e889..4232a60 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/StaxParserTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/StaxParserTest.java
@@ -19,8 +19,17 @@
package org.apache.felix.bundlerepository;
import java.net.URL;
+import java.util.Hashtable;
import junit.framework.TestCase;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.easymock.internal.matchers.Captures;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.ServiceListener;
import org.osgi.service.obr.Repository;
import org.osgi.service.obr.Resolver;
import org.osgi.service.obr.Resource;
@@ -35,20 +44,11 @@
Resolver resolver = repoAdmin.resolver();
- Resource r = null;
- //MockContext doesn't support filtering!
- Resource[] discoverResources = repoAdmin.discoverResources("");
- for (int i = 0; i < discoverResources.length; i++)
- {
- Resource resource = discoverResources[i];
- if (resource.getSymbolicName().contains("org.apache.felix.test"))
- {
- r = resource;
- }
- }
- assertNotNull(r);
+ Resource[] discoverResources = repoAdmin.discoverResources("(symbolicname=org.apache.felix.test*)");
+ assertNotNull(discoverResources);
+ assertEquals(1, discoverResources.length);
- resolver.add(r);
+ resolver.add(discoverResources[0]);
assertTrue(resolver.resolve());
}
@@ -116,13 +116,32 @@
new StaxParserTest().testStaxParser();
}
- private RepositoryAdminImpl createRepositoryAdmin(Class repositoryParser)
+ private RepositoryAdminImpl createRepositoryAdmin(Class repositoryParser) throws Exception
{
- final MockBundleContext bundleContext = new MockBundleContext();
- bundleContext.setProperty(RepositoryAdminImpl.REPOSITORY_URL_PROP,
- getClass().getResource("/referral1_repository.xml").toExternalForm());
- bundleContext.setProperty(RepositoryImpl.OBR_PARSER_CLASS,
- repositoryParser.getName());
+ BundleContext bundleContext = (BundleContext) EasyMock.createMock(BundleContext.class);
+ Bundle systemBundle = (Bundle) EasyMock.createMock(Bundle.class);
+
+ EasyMock.expect(bundleContext.getProperty(RepositoryAdminImpl.REPOSITORY_URL_PROP))
+ .andReturn(getClass().getResource("/referral1_repository.xml").toExternalForm());
+ EasyMock.expect(bundleContext.getProperty(RepositoryImpl.OBR_PARSER_CLASS))
+ .andReturn(repositoryParser.getName());
+ EasyMock.expect(bundleContext.getProperty((String) EasyMock.anyObject())).andReturn(null).anyTimes();
+ EasyMock.expect(bundleContext.getBundle(0)).andReturn(systemBundle);
+ EasyMock.expect(systemBundle.getHeaders()).andReturn(new Hashtable());
+ EasyMock.expect(systemBundle.getRegisteredServices()).andReturn(null);
+ EasyMock.expect(new Long(systemBundle.getBundleId())).andReturn(new Long(0)).anyTimes();
+ EasyMock.expect(systemBundle.getBundleContext()).andReturn(bundleContext);
+ bundleContext.addBundleListener((BundleListener) EasyMock.anyObject());
+ bundleContext.addServiceListener((ServiceListener) EasyMock.anyObject());
+ EasyMock.expect(bundleContext.getBundles()).andReturn(new Bundle[] { systemBundle });
+ final Capture c = new Capture();
+ EasyMock.expect(bundleContext.createFilter((String) capture(c))).andAnswer(new IAnswer() {
+ public Object answer() throws Throwable {
+ return new FilterImpl((String) c.getValue());
+ }
+ }).anyTimes();
+ EasyMock.replay(new Object[] { bundleContext, systemBundle });
+
RepositoryAdminImpl repoAdmin = new RepositoryAdminImpl(bundleContext, new Logger(bundleContext));
// force initialization && remove all initial repositories
@@ -134,4 +153,10 @@
return repoAdmin;
}
+
+ static Object capture(Capture capture) {
+ EasyMock.reportMatcher(new Captures(capture));
+ return null;
+ }
+
}
\ No newline at end of file
diff --git a/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Repository.java b/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Repository.java
index 30adeb9..172c5f2 100644
--- a/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Repository.java
+++ b/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Repository.java
@@ -42,7 +42,7 @@
Resource[] getResources();
/**
- * Return the name of this reposotory.
+ * Return the name of this repository.
*
* @return a non-null name
*/
@@ -50,4 +50,14 @@
long getLastModified();
+ /**
+ * Returns whether this repository is a local one
+ * or not.
+ *
+ * Local repositories contains resources that are already available
+ * in the OSGi framework and thus will be preferred over other
+ * resources.
+ */
+ boolean isLocal();
+
}
\ No newline at end of file
diff --git a/org.osgi.service.obr/src/main/java/org/osgi/service/obr/RepositoryAdmin.java b/org.osgi.service.obr/src/main/java/org/osgi/service/obr/RepositoryAdmin.java
index dc822d0..8b6b520 100644
--- a/org.osgi.service.obr/src/main/java/org/osgi/service/obr/RepositoryAdmin.java
+++ b/org.osgi.service.obr/src/main/java/org/osgi/service/obr/RepositoryAdmin.java
@@ -35,11 +35,11 @@
* <li>Capabilities - Capabilities provide a named aspect: a bundle, a display,
* memory, etc.</li>
* <li>Requirements - A named filter expression. The filter must be satisfied
- * by one or more Capabilties with the given name. These capabilities can come
+ * by one or more Capabilities with the given name. These capabilities can come
* from other resources or from the platform. If multiple resources provide the
* requested capability, one is selected. (### what algorithm? ###)</li>
* <li>Requests - Requests are like requirements, except that a request can be
- * fullfilled by 0..n resources. This feature can be used to link to resources
+ * fulfilled by 0..n resources. This feature can be used to link to resources
* that are compatible with the given resource and provide extra functionality.
* For example, a bundle could request all its known fragments. The UI
* associated with the repository could list these as optional downloads.</li>
@@ -85,12 +85,20 @@
/**
* Create a resolver.
- *
+ *
* @return
*/
Resolver resolver();
/**
+ * Create a resolver on the given repositories.
+ *
+ * @param repositories the list of repositories to use for the resolution
+ * @return
+ */
+ Resolver resolver(Repository[] repositories);
+
+ /**
* Add a new repository to the federation.
*
* The url must point to a repository XML file.
@@ -101,6 +109,14 @@
*/
Repository addRepository(URL repository) throws Exception;
+ /**
+ * Remove a repository from the federation
+ *
+ * The url must point to a repository XML file.
+ *
+ * @param repository
+ * @return
+ */
boolean removeRepository(URL repository);
/**
@@ -110,6 +126,20 @@
*/
Repository[] listRepositories();
+ /**
+ * Return the repository containing the system bundle
+ *
+ * @return
+ */
+ Repository getSystemRepository();
+
+ /**
+ * Return the repository containing locally installed resources
+ *
+ * @return
+ */
+ Repository getLocalRepository();
+
Resource getResource(String repositoryId);
/**
@@ -128,4 +158,12 @@
*/
Filter filter(String filter) throws InvalidSyntaxException;
+ /**
+ * Create a repository from the specified URL.
+ *
+ * @param repository
+ * @return
+ */
+ Repository repository(URL repository) throws Exception;
+
}
\ No newline at end of file
diff --git a/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Resource.java b/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Resource.java
index 7064b75..274b533 100644
--- a/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Resource.java
+++ b/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Resource.java
@@ -85,4 +85,5 @@
String[] getCategories();
Repository getRepository();
+
}
\ No newline at end of file