Package biz.aQute.resolve

Source Code of biz.aQute.resolve.GenericResolveContext$CacheKey

package biz.aQute.resolve;

import static org.osgi.framework.namespace.BundleNamespace.*;
import static org.osgi.framework.namespace.PackageNamespace.*;

import java.io.*;
import java.text.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.*;

import org.osgi.framework.*;
import org.osgi.framework.namespace.*;
import org.osgi.namespace.contract.*;
import org.osgi.resource.*;
import org.osgi.service.log.*;
import org.osgi.service.repository.*;
import org.osgi.service.resolver.*;

import aQute.bnd.build.model.*;
import aQute.bnd.deployer.repository.*;
import aQute.bnd.header.*;
import aQute.bnd.osgi.resource.*;
import aQute.bnd.service.resolve.hook.*;
import aQute.lib.utf8properties.*;
import aQute.libg.filters.*;
import aQute.libg.filters.Filter;
import biz.aQute.resolve.internal.*;

/**
* This is the Resolve Context as outlined in the Resolver specfication. It
* manages the access to the repository and orders the capabilities. It also
* provides the capabilities of the environment.
*/
public class GenericResolveContext extends ResolveContext {

  protected static final String          CONTRACT_OSGI_FRAMEWORK    = "OSGiFramework";
  protected static final String          IDENTITY_INITIAL_RESOURCE  = "<<INITIAL>>";
  protected static final String          IDENTITY_SYSTEM_RESOURCE  = "<<SYSTEM>>";

  protected final LogService            log;

  private final List<Capability>          systemCapabilities;
  private final List<Capability>          capabilities        = new ArrayList<Capability>();
  private final List<Requirement>          systemRequirements;
  private final List<Requirement>          requirements        = new ArrayList<Requirement>();

  protected CapabilityIndex            systemCapabilityIndex;

  protected final List<Repository>        repositories        = new ArrayList<Repository>();

  protected final List<Requirement>        failed            = new ArrayList<Requirement>();
  protected final Map<CacheKey,List<Capability>>  providerCache        = new HashMap<CacheKey,List<Capability>>();
  protected final Set<Resource>          optionalRoots        = new HashSet<Resource>();
  protected final ConcurrentMap<Resource,Integer>  resourcePriorities      = new ConcurrentHashMap<Resource,Integer>();

  protected final Comparator<Capability>      capabilityComparator    = new CapabilityComparator();

  protected Map<String,Set<String>>        effectiveSet;

  protected final List<ResolverHook>        resolverHooks        = new ArrayList<ResolverHook>();
  protected final List<ResolutionCallback>    callbacks          = new LinkedList<ResolutionCallback>();

  protected boolean                initialised          = false;
  protected Resource                systemResource;
  protected Resource                inputResource;
  protected Set<Resource>              blacklistedResources    = new HashSet<Resource>();

  public GenericResolveContext(LogService log) {
    this(Collections.<Capability> emptyList(), Collections.<Requirement> emptyList(), log);
  }

  /**
   * @param systemCapabilities
   * @param systemRequirements
   * @param blacklist
   * @param log
   */
  public GenericResolveContext(List<Capability> systemCapabilities, List<Requirement> systemRequirements,
      LogService log) {
    this.systemCapabilities = systemCapabilities;
    this.systemRequirements = systemRequirements;
    this.log = log;

    systemCapabilityIndex = new CapabilityIndex();
  }

  protected synchronized void init() {
    if (initialised)
      return;

    try {
      failed.clear();

      getSystemResource();
      getInputResource();

      initialised = true;
    }
    catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public void addInputRequirement(Requirement requirement) {
    requirements.add(requirement);
  }

  public void addInputCapability(Capability capability) {
    capabilities.add(capability);
  }

  @Override
  public List<Capability> findProviders(Requirement requirement) {
    List<Capability> result = findProviders0(requirement);
    if (result == null || result.isEmpty()) {
      failed.add(requirement);
    }
    return result;
  }

  private List<Capability> findProviders0(Requirement requirement) {

    init();

    List<Capability> result;

    CacheKey cacheKey = getCacheKey(requirement);
    List<Capability> cached = providerCache.get(cacheKey);
    if (cached != null) {
      result = new ArrayList<Capability>(cached);
    } else {
      // First stage: framework and self-capabilities. This should never
      // be reordered by preferences or resolver
      // hooks
      LinkedHashSet<Capability> firstStageResult = new LinkedHashSet<Capability>();

      // The selected OSGi framework always has the first chance to
      // provide the capabilities
      systemCapabilityIndex.appendMatchingCapabilities(requirement, firstStageResult);

      // Next find out if the requirement is satisfied by a capability on
      // the same resource
      Resource resource = requirement.getResource();
      if (resource != null) {
        List<Capability> selfCaps = resource.getCapabilities(requirement.getNamespace());
        if (selfCaps != null) {
          for (Capability selfCap : selfCaps) {
            if (matches(requirement, selfCap))
              firstStageResult.add(selfCap);
          }
        }
      }

      // If the requirement is optional and doesn't come from an optional
      // root resource,
      // then we are done already, no need to look for providers from the
      // repos.
      boolean optional = Namespace.RESOLUTION_OPTIONAL.equals(requirement.getDirectives().get(
          Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE));
      if (optional && !optionalRoots.contains(requirement.getResource())) {

        result = new ArrayList<Capability>(firstStageResult);
        Collections.sort(result, capabilityComparator);

      } else {

        // Second stage results: repository contents; may be reordered.
        ArrayList<Capability> secondStageResult = new ArrayList<Capability>();

        // Iterate over the repos
        int order = 0;
        ArrayList<Capability> repoCapabilities = new ArrayList<Capability>();
        for (Repository repo : repositories) {
          repoCapabilities.clear();
          Map<Requirement,Collection<Capability>> providers = findProviders(repo, requirement);
          Collection<Capability> capabilities = providers.get(requirement);
          if (capabilities != null && !capabilities.isEmpty()) {
            repoCapabilities.ensureCapacity(capabilities.size());
            for (Capability capability : capabilities) {
              if (isPermitted(capability.getResource())) {
                repoCapabilities.add(capability);
                setResourcePriority(order, capability.getResource());
              }
            }
            secondStageResult.addAll(repoCapabilities);
          }
          order++;
        }
        Collections.sort(secondStageResult, capabilityComparator);

        // Convert second-stage results to a list and post-process
        ArrayList<Capability> secondStageList = new ArrayList<Capability>(secondStageResult);

        // Post-processing second stage results
        postProcessProviders(requirement, firstStageResult, secondStageList);

        // Concatenate both stages, eliminating duplicates between the
        // two
        firstStageResult.addAll(secondStageList);
        result = new ArrayList<Capability>(firstStageResult);
      }
      providerCache.put(cacheKey, result);
    }

    return result;

  }

  /**
   * Return any capabilities from the given repo. This method will filter the
   * blacklist.
   *
   * @param repo
   *            The repo to fetch requirements from
   * @param requirement
   *            the requirement
   * @return a list of caps for the asked requirement minus and capabilities
   *         that are skipped.
   */
  protected Map<Requirement,Collection<Capability>> findProviders(Repository repo, Requirement requirement) {
    Map<Requirement,Collection<Capability>> map = repo.findProviders(Collections.singleton(requirement));
    if (map.isEmpty())
      return map;

    Collection<Capability> caps = map.get(requirement);

    for (Iterator<Capability> c = caps.iterator(); c.hasNext();) {
      Capability capability = c.next();

      if (blacklistedResources.contains(capability.getResource()))
        c.remove();
    }
    return map;
  }

  private void setResourcePriority(int priority, Resource resource) {
    resourcePriorities.putIfAbsent(resource, priority);
  }

  public static Requirement createBundleRequirement(String bsn, String versionStr) {
    return CapReqBuilder.createBundleRequirement(bsn, versionStr).buildSyntheticRequirement();
  }

  private boolean matches(Requirement requirement, Capability selfCap) {
    boolean match = false;
    try {
      String filterStr = requirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
      org.osgi.framework.Filter filter = filterStr != null ? org.osgi.framework.FrameworkUtil
          .createFilter(filterStr) : null;

      if (filter == null)
        match = true;
      else
        match = filter.match(new MapToDictionaryAdapter(selfCap.getAttributes()));
    }
    catch (InvalidSyntaxException e) {
      log.log(LogService.LOG_ERROR, "Invalid filter directive on requirement: " + requirement, e);
    }
    return match;
  }

  @Override
  public int insertHostedCapability(List<Capability> caps, HostedCapability hc) {
    Integer prioObj = resourcePriorities.get(hc.getResource());
    int priority = prioObj != null ? prioObj.intValue() : Integer.MAX_VALUE;

    for (int i = 0; i < caps.size(); i++) {
      Capability c = caps.get(i);

      Integer otherPrioObj = resourcePriorities.get(c.getResource());
      int otherPriority = otherPrioObj != null ? otherPrioObj.intValue() : 0;
      if (otherPriority > priority) {
        caps.add(i, hc);
        return i;
      }
    }

    caps.add(hc);
    return caps.size() - 1;
  }

  @Override
  public boolean isEffective(Requirement requirement) {
    init();
    String effective = requirement.getDirectives().get(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE);
    if (effective == null || Namespace.EFFECTIVE_RESOLVE.equals(effective))
      return true;

    if (effectiveSet != null && effectiveSet.containsKey(effective)
        && !effectiveSet.get(effective).contains(requirement.getNamespace()))
      return true;

    return false;
  }

  @Override
  public Map<Resource,Wiring> getWirings() {
    return Collections.emptyMap();
  }

  public void setOptionalRoots(Collection<Resource> roots) {
    this.optionalRoots.clear();
    this.optionalRoots.addAll(roots);
  }

  public void addRepository(Repository repo) {
    repositories.add(repo);
  }

  public List<Repository> getRepositories() {
    return repositories;
  }

  public List<Requirement> getFailed() {
    return failed;
  }

  private boolean isPermitted(Resource resource) {
    // OSGi frameworks cannot be selected as ordinary resources
    Capability fwkCap = findFrameworkContractCapability(resource);
    if (fwkCap != null) {
      return false;
    }

    // Remove osgi.core and any ee JAR
    List<Capability> idCaps = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
    if (idCaps == null || idCaps.isEmpty()) {
      log.log(LogService.LOG_ERROR, "Resource is missing an identity capability (osgi.identity).");
      return false;
    }
    if (idCaps.size() > 1) {
      log.log(LogService.LOG_ERROR, "Resource has more than one identity capability (osgi.identity).");
      return false;
    }
    String identity = (String) idCaps.get(0).getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE);
    if (identity == null) {
      log.log(LogService.LOG_ERROR, "Resource is missing an identity capability (osgi.identity).");
      return false;
    }

    if ("osgi.core".equals(identity))
      return false;

    if (identity.startsWith("ee."))
      return false;

    return true;
  }

  protected static Capability findFrameworkContractCapability(Resource resource) {
    List<Capability> contractCaps = resource.getCapabilities(ContractNamespace.CONTRACT_NAMESPACE);
    if (contractCaps != null)
      for (Capability cap : contractCaps) {
        if (CONTRACT_OSGI_FRAMEWORK.equals(cap.getAttributes().get(ContractNamespace.CONTRACT_NAMESPACE)))
          return cap;
      }
    return null;
  }

  public static boolean isInputRequirementResource(Resource resource) {
    Capability id = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0);
    return IDENTITY_INITIAL_RESOURCE.equals(id.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
  }

  private static CacheKey getCacheKey(Requirement requirement) {
    return new CacheKey(requirement.getNamespace(), requirement.getDirectives(), requirement.getAttributes());
  }

  private static class CacheKey {
    final String        namespace;
    final Map<String,String>  directives;
    final Map<String,Object>  attributes;
    final int          hashcode;

    CacheKey(String namespace, Map<String,String> directives, Map<String,Object> attributes) {
      this.namespace = namespace;
      this.directives = directives;
      this.attributes = attributes;
      this.hashcode = calculateHashCode(namespace, directives, attributes);
    }

    private static int calculateHashCode(String namespace, Map<String,String> directives,
        Map<String,Object> attributes) {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
      result = prime * result + ((directives == null) ? 0 : directives.hashCode());
      result = prime * result + ((namespace == null) ? 0 : namespace.hashCode());
      return result;
    }

    @Override
    public int hashCode() {
      return hashcode;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      CacheKey other = (CacheKey) obj;
      if (attributes == null) {
        if (other.attributes != null)
          return false;
      } else if (!attributes.equals(other.attributes))
        return false;
      if (directives == null) {
        if (other.directives != null)
          return false;
      } else if (!directives.equals(other.directives))
        return false;
      if (namespace == null) {
        if (other.namespace != null)
          return false;
      } else if (!namespace.equals(other.namespace))
        return false;
      return true;
    }

  }

  static Version getVersion(Capability cap, String attr) {
    Object versionatt = cap.getAttributes().get(attr);
    if (versionatt instanceof Version)
      return (Version) versionatt;
    else if (versionatt instanceof String)
      return Version.parseVersion((String) versionatt);
    else
      return Version.emptyVersion;
  }

  private class CapabilityComparator implements Comparator<Capability> {

    public CapabilityComparator() {}

    public int compare(Capability o1, Capability o2) {

      Resource res1 = o1.getResource();
      Resource res2 = o2.getResource();

      // 1. Framework bundle
      if (isSystemResource(res1))
        return -1;
      if (isSystemResource(res2))
        return +1;

      // 2. Wired
      Map<Resource,Wiring> wirings = getWirings();
      Wiring w1 = wirings.get(res1);
      Wiring w2 = wirings.get(res2);

      if (w1 != null && w2 == null)
        return -1;
      if (w1 == null && w2 != null)
        return +1;

      // 3. Input requirements
      if (isInputResource(res1)) {
        if (!isInputResource(res2))
          return -1;
      }
      if (isInputResource(res2)) {
        if (!isInputResource(res1))
          return +1;
      }

      // 4. Higher package version
      String ns1 = o1.getNamespace();
      String ns2 = o2.getNamespace();
      if (PACKAGE_NAMESPACE.equals(ns1) && PACKAGE_NAMESPACE.equals(ns2)) {
        Version v1 = getVersion(o1, PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
        Version v2 = getVersion(o2, PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
        if (!v1.equals(v2))
          return v2.compareTo(v1);
      }

      // 5. Higher resource version
      if (BUNDLE_NAMESPACE.equals(ns1) && BUNDLE_NAMESPACE.equals(ns2)) {
        Version v1 = getVersion(o1, BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
        Version v2 = getVersion(o2, BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
        if (!v1.equals(v2))
          return v2.compareTo(v1);
      } else if (IdentityNamespace.IDENTITY_NAMESPACE.equals(ns1)
          && IdentityNamespace.IDENTITY_NAMESPACE.equals(ns2)) {
        Version v1 = getVersion(o1, IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
        Version v2 = getVersion(o2, IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
        if (!v1.equals(v2))
          return v2.compareTo(v1);
      }

      // 6. Same package version, higher bundle version
      if (PACKAGE_NAMESPACE.equals(ns1) && PACKAGE_NAMESPACE.equals(ns2)) {
        String bsn1 = (String) o1.getAttributes().get(aQute.bnd.osgi.Constants.BUNDLE_SYMBOLIC_NAME_ATTRIBUTE);
        String bsn2 = (String) o2.getAttributes().get(aQute.bnd.osgi.Constants.BUNDLE_SYMBOLIC_NAME_ATTRIBUTE);
        if (bsn1 != null && bsn1.equals(bsn2)) {
          Version v1 = getVersion(o1, BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
          Version v2 = getVersion(o2, BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
          if (!v1.equals(v2))
            return v2.compareTo(v1);
        }
      }

      // 7. The resource with the fewest requirements
      int diff = res1.getRequirements(null).size() - res2.getRequirements(null).size();
      if (diff != 0)
        return diff;

      // 8. The resource with most capabilities
      return res2.getCapabilities(null).size() - res1.getCapabilities(null).size();
    }
  }

  public Resource getInputResource() {
    if (inputResource != null) {
      return inputResource;
    }
    ResourceBuilder resBuilder = new ResourceBuilder();
    CapReqBuilder identity = new CapReqBuilder(IdentityNamespace.IDENTITY_NAMESPACE).addAttribute(
        IdentityNamespace.IDENTITY_NAMESPACE, IDENTITY_INITIAL_RESOURCE);
    resBuilder.addCapability(identity);

    for (Requirement req : requirements) {
      resBuilder.addRequirement(req);
    }
    for (Capability cap : capabilities) {
      resBuilder.addCapability(cap);
    }
    inputResource = resBuilder.build();
    return inputResource;
  }

  public Resource getSystemResource() {
    if (systemResource != null) {
      return systemResource;
    }
    ResourceBuilder resBuilder = new ResourceBuilder();

    CapReqBuilder identity = new CapReqBuilder(IdentityNamespace.IDENTITY_NAMESPACE).addAttribute(
        IdentityNamespace.IDENTITY_NAMESPACE, IDENTITY_SYSTEM_RESOURCE);
    resBuilder.addCapability(identity);
    for (Requirement req : systemRequirements) {
      resBuilder.addRequirement(req);
    }
    for (Capability cap : systemCapabilities) {
      resBuilder.addCapability(cap);
    }
    systemResource = resBuilder.build();
    for (Capability capability : systemResource.getCapabilities(null)) {
      systemCapabilityIndex.addCapability(capability);
    }
    return systemResource;

  }

  @Override
  public Collection<Resource> getMandatoryResources() {
    init();
    List<Resource> resources = new ArrayList<Resource>();
    Resource resource = getSystemResource();
    if (resource != null) {
      resources.add(resource);
    }
    resource = getInputResource();
    if (resource != null) {
      resources.add(resource);
    }
    return resources;
  }

  public void addEffectiveDirective(String effectiveDirective) {
    this.effectiveSet.put(effectiveDirective, new HashSet<String>());
  }

  public void addEffectiveDirective(String effectiveDirective, Set<String> excludedNamespaces) {
    this.effectiveSet.put(effectiveDirective, excludedNamespaces != null ? excludedNamespaces
        : new HashSet<String>());
  }

  protected void postProcessProviders(Requirement requirement, Set<Capability> wired, List<Capability> candidates) {
    if (candidates.size() == 0)
      return;

    // Call resolver hooks
    for (ResolverHook resolverHook : resolverHooks) {
      resolverHook.filterMatches(requirement, candidates);
    }

    // If preferences were applied, then don't need to call the callbacks
    for (ResolutionCallback callback : callbacks) {
      callback.processCandidates(requirement, wired, candidates);
    }
  }

  public void addResolverHook(ResolverHook resolverHook) {
    resolverHooks.add(resolverHook);
  }

  public void addCallbacks(Collection<ResolutionCallback> callbacks) {
    this.callbacks.addAll(callbacks);
  }

  public static Requirement createIdentityRequirement(String identity, String versionRange) {
    // Construct a filter & requirement to find matches
    Filter filter = new SimpleFilter(IdentityNamespace.IDENTITY_NAMESPACE, identity);
    if (versionRange != null)
      filter = new AndFilter().addChild(filter).addChild(
          new LiteralFilter(Filters.fromVersionRange(versionRange)));
    Requirement frameworkReq = new CapReqBuilder(IdentityNamespace.IDENTITY_NAMESPACE).addDirective(
        Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString()).buildSyntheticRequirement();
    return frameworkReq;
  }

  public boolean isInputResource(Resource resource) {
    return GenericResolveContext.resourceIdentityEquals(resource, inputResource);
  }

  public boolean isSystemResource(Resource resource) {
    return GenericResolveContext.resourceIdentityEquals(resource, systemResource);
  }

  public Resource getFrameworkResource(List<Repository> repos, String bsn, String version) {

    Requirement frameworkRequirement = GenericResolveContext.createIdentityRequirement(bsn, version);
    if (frameworkRequirement == null) {
      return null;
    }
    Version current = null;
    Resource result = null;
    for (Repository repo : repos) {
      Map<Requirement,Collection<Capability>> providers = findProviders(repo,frameworkRequirement);
      Collection<Capability> frameworkCaps = providers.get(frameworkRequirement);
      if (frameworkCaps != null) {
        for (Capability frameworkCap : frameworkCaps) {
          if (findFrameworkContractCapability(frameworkCap.getResource()) != null) {
            Version foundVersion = toVersion(frameworkCap.getAttributes().get(
                IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE));
            if (foundVersion != null) {
              if (current == null || (foundVersion.compareTo(current) > 0)) {
                result = frameworkCap.getResource();
                ResourceBuilder resBuilder = new ResourceBuilder();
                for (Capability cap : result.getCapabilities(null)) {
                  resBuilder.addCapability(cap);
                }
                for (Requirement req : result.getRequirements(null)) {
                  resBuilder.addRequirement(req);
                }
                // Add system.bundle alias
                Version frameworkVersion = Utils.findIdentityVersion(result);
                resBuilder.addCapability(new CapReqBuilder(BundleNamespace.BUNDLE_NAMESPACE)
                    .addAttribute(BundleNamespace.BUNDLE_NAMESPACE,
                        Constants.SYSTEM_BUNDLE_SYMBOLICNAME)
                    .addAttribute(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE,
                        frameworkVersion).setResource(result).buildCapability());
                resBuilder.addCapability(new CapReqBuilder(HostNamespace.HOST_NAMESPACE)
                    .addAttribute(HostNamespace.HOST_NAMESPACE,
                        Constants.SYSTEM_BUNDLE_SYMBOLICNAME)
                    .addAttribute(HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE,
                        frameworkVersion).setResource(result).buildCapability());
                result = resBuilder.build();
                current = foundVersion;
              }
            }
          }
        }
      }
    }
    return result;
  }

  protected static Version toVersion(Object object) throws IllegalArgumentException {
    if (object == null)
      return null;

    if (object instanceof Version)
      return (Version) object;

    if (object instanceof String)
      return Version.parseVersion((String) object);

    throw new IllegalArgumentException(MessageFormat.format("Cannot convert type {0} to Version.", object
        .getClass().getName()));
  }

  public static List<Capability> getEECapabilities(EE ee) {

    List<Capability> caps = new ArrayList<Capability>();
    addEECapability(ee, caps);
    for (EE compatibleEE : ee.getCompatible()) {
      addEECapability(compatibleEE, caps);
    }
    getJRECapabilities(ee);
    return caps;
  }

  public static List<Capability> getJRECapabilities(EE ee) {

    List<Capability> caps = new ArrayList<Capability>();
    loadJREPackages(ee, caps);
    return caps;
  }

  private static void addEECapability(EE ee, List<Capability> capabilities) {
    CapReqBuilder builder;

    // Correct version according to R5 specification section 3.4.1
    // BREE J2SE-1.4 ==> osgi.ee=JavaSE, version:Version=1.4
    // See bug 329, https://github.com/bndtools/bnd/issues/329
    builder = new CapReqBuilder(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
    builder.addAttribute(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE, ee.getCapabilityName());
    builder.addAttribute(ExecutionEnvironmentNamespace.CAPABILITY_VERSION_ATTRIBUTE, ee.getCapabilityVersion());
    capabilities.add(builder.buildSyntheticCapability());

    // Compatibility with old version...
    builder = new CapReqBuilder(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
    builder.addAttribute(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE, ee.getEEName());
    capabilities.add(builder.buildSyntheticCapability());

  }

  protected static void loadJREPackages(EE ee, List<Capability> capabilities) {
    InputStream stream = FrameworkResourceRepository.class.getResourceAsStream(ee.name() + ".properties");
    if (stream != null) {
      try {
        Properties properties = new UTF8Properties();
        properties.load(stream);

        Parameters params = new Parameters(properties.getProperty("org.osgi.framework.system.packages", ""));
        for (String packageName : params.keySet()) {
          CapReqBuilder builder = new CapReqBuilder(PackageNamespace.PACKAGE_NAMESPACE);
          builder.addAttribute(PackageNamespace.PACKAGE_NAMESPACE, packageName);
          builder.addAttribute(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE, new Version(0, 0, 0));
          Capability cap = builder.buildSyntheticCapability();
          capabilities.add(cap);
        }
      }
      catch (IOException e) {
        throw new IllegalStateException("Error loading JRE package properties", e);
      }
    }
  }

  public static Repository createRepository(final List<Resource> resources) {
    return new Repository() {

      @Override
      public Map<Requirement,Collection<Capability>> findProviders(Collection< ? extends Requirement> requirements) {
        Map<Requirement,Collection<Capability>> reqMap = null;
        for (Requirement requirement : requirements) {
          Resource resource = requirement.getResource();
          List<Capability> result = new ArrayList<Capability>();
          for (Resource found : resources) {
            String filterStr = requirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
            try {
              org.osgi.framework.Filter filter = filterStr != null ? org.osgi.framework.FrameworkUtil
                  .createFilter(filterStr) : null;

              List<Capability> caps = found.getCapabilities(requirement.getNamespace());
              for (Capability c : caps) {
                if (filter != null && filter.matches(c.getAttributes())) {
                  result.add(c);
                }
              }
            }
            catch (InvalidSyntaxException e) {}
          }
          if (result.size() > 0) {
            if (reqMap == null) {
              reqMap = new LinkedHashMap<Requirement,Collection<Capability>>();
            }
            reqMap.put(requirement, result);
          }
        }
        if (reqMap != null) {
          return reqMap;
        }
        return Collections.emptyMap();
      }
    };
  }

  public static Capability createPackageCapability(String packageName, String versionString) {
    CapReqBuilder builder = new CapReqBuilder(PackageNamespace.PACKAGE_NAMESPACE);
    builder.addAttribute(PackageNamespace.PACKAGE_NAMESPACE, packageName);
    Version version = versionString != null ? new Version(versionString) : Version.emptyVersion;
    builder.addAttribute(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
    return builder.buildSyntheticCapability();
  }

  public static boolean resourceIdentityEquals(Resource r1, Resource r2) {
    String id1 = getResourceIdentity(r1);
    String id2 = getResourceIdentity(r2);
    if (id1 != null && id1.equals(id2)) {
      Version v1 = getResourceVersion(r1);
      Version v2 = getResourceVersion(r2);
      if (v1 == null && v2 == null || v1 != null && v1.equals(v2)) {
        return true;
      }
    }
    return false;
  }

  public static Capability getIdentityCapability(Resource resource) {
    if (resource == null) {
      return null;
    }
    List<Capability> identityCaps = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
    if (identityCaps == null || identityCaps.isEmpty()) {
      return null;
    }
    return identityCaps.iterator().next();
  }

  public static String getResourceIdentity(Resource resource) {
    Capability cap = getIdentityCapability(resource);
    if (cap == null) {
      return null;
    }
    return (String) cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE);
  }

  public static Version getResourceVersion(Resource resource) {
    Capability cap = getIdentityCapability(resource);
    if (cap == null) {
      return null;
    }
    return getVersion(cap, IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
  }

  /**
   * If the blacklist is set, we have a list of requirements of resources that
   * should not be included (blacklist). We try to find those resources and
   * add them to the blacklistedResources
   */
  protected void setBlackList(Collection<Requirement> reject) {
    for (Repository repo : repositories) {
      Map<Requirement,Collection<Capability>> caps = repo.findProviders(reject);
      for (Entry<Requirement,Collection<Capability>> entry : caps.entrySet()) {
        for (Capability cap : entry.getValue()) {
          blacklistedResources.add(cap.getResource());
        }
      }
    }
  }

}
TOP

Related Classes of biz.aQute.resolve.GenericResolveContext$CacheKey

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.