Skip to content

Commit

Permalink
FELIX-2106, FELIX-692: Control which repositories are used for a give…
Browse files Browse the repository at this point in the history
…n resolver

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@915288 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
gnodet committed Feb 23, 2010
1 parent 7b9f751 commit 66b87bd
Show file tree
Hide file tree
Showing 16 changed files with 735 additions and 595 deletions.
5 changes: 5 additions & 0 deletions bundlerepository/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -98,10 +88,15 @@ private void addBundle(Bundle bundle, Logger logger)
* 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)
{
Expand Down Expand Up @@ -149,6 +144,11 @@ public synchronized Resource[] getResources()
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
Expand All @@ -173,314 +173,4 @@ private void initialize()
}
}

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);
}
}
}
}
Loading

0 comments on commit 66b87bd

Please sign in to comment.