Package aQute.bnd.indexer.analyzers

Source Code of aQute.bnd.indexer.analyzers.BundleAnalyzer

package aQute.bnd.indexer.analyzers;

import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.jar.*;

import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.osgi.resource.*;

import aQute.bnd.header.*;
import aQute.bnd.header.Attrs.Type;
import aQute.bnd.indexer.*;
import aQute.bnd.osgi.*;
import aQute.bnd.osgi.resource.*;
import aQute.bnd.version.*;

public class BundleAnalyzer implements ResourceAnalyzer {
  // Filename suffix for JAR files
  private static final String SUFFIX_JAR = ".jar";


  public void analyzeResource(Jar resource, ResourceBuilder rb) throws Exception {
    Manifest manifest = resource.getManifest();
    if( manifest == null)
      return;
   
    Domain domain = Domain.domain(manifest);
    MimeType mimeType = MimeType.Jar;
   
    if (resource.getBsn() != null) {
      mimeType = MimeType.Bundle;
     
      if ( domain.getFragmentHost() != null)
        mimeType = MimeType.Fragment;
     
//      doBundleIdentity(domain, mimeType, capabilities);
//      doBundleAndHost(domain, capabilities);
//      doExports(domain, capabilities);
//      doImports(domain, requirements);
//      doRequireBundles(domain, requirements);
//      doFragment(domain, requirements);
//      doExportService(domain, capabilities);
//      doImportService(domain, requirements);
//      doBREE(domain, requirements);
//      doCapabilities(domain, capabilities);
//      doRequirements(domain, requirements);
//      doBundleNativeCode(domain, requirements);
    } else {
//      doPlainJarIdentity(resource, capabilities);
    }
  }

  private void doBundleIdentity(Domain domain, MimeType mimeType, List<? super Capability> caps) throws Exception {

    String type;
    switch (mimeType) {
    case Bundle:
      type = Namespaces.RESOURCE_TYPE_BUNDLE;
      break;
    case Fragment:
      type = Namespaces.RESOURCE_TYPE_FRAGMENT;
      break;
    default:
      type = Namespaces.RESOURCE_TYPE_PLAIN_JAR;
      break;
    }
   
    Entry<String,Attrs> bundleSymbolicName = domain.getBundleSymbolicName();
    String bsn = bundleSymbolicName.getKey();
    String s = bundleSymbolicName.getValue().get(Constants.SINGLETON_DIRECTIVE+":");
   
    boolean singleton = Boolean.TRUE.toString().equalsIgnoreCase(s);

    Version version = Version.parseVersion(domain.getBundleVersion());

    CapReqBuilder builder = new CapReqBuilder(Namespaces.NS_IDENTITY).addAttribute(Namespaces.NS_IDENTITY, bsn).addAttribute(Namespaces.ATTR_IDENTITY_TYPE, type)
        .addAttribute(Namespaces.ATTR_VERSION, version);
    if (singleton)
      builder.addDirective(Namespaces.DIRECTIVE_SINGLETON, Boolean.TRUE.toString());
    caps.add(builder.buildCapability());
  }

  private void doPlainJarIdentity(Jar resource, List<? super Capability> caps) {
    String name = resource.getName();
    if (name.toLowerCase().endsWith(SUFFIX_JAR))
      name = name.substring(0, name.length() - SUFFIX_JAR.length());

    Version version = null;
    int dashIndex = name.lastIndexOf('-');
    if (dashIndex > 0) {
      try {
        String versionStr = name.substring(dashIndex + 1);
        version = new Version(versionStr);
        name = name.substring(0, dashIndex);
      } catch (Exception e) {
        version = null;
      }
    }

    CapReqBuilder builder = new CapReqBuilder(Namespaces.NS_IDENTITY).addAttribute(Namespaces.NS_IDENTITY, name)
        .addAttribute(Namespaces.ATTR_IDENTITY_TYPE, Namespaces.RESOURCE_TYPE_PLAIN_JAR);
    if (version != null)
      builder.addAttribute(Namespaces.ATTR_VERSION, version);
    caps.add(builder.buildCapability());
  }


  private void doBundleAndHost(Domain domain, List<? super Capability> caps) throws Exception {
   
    CapReqBuilder bundleBuilder = new CapReqBuilder(Namespaces.NS_WIRING_BUNDLE);
    CapReqBuilder hostBuilder = new CapReqBuilder(Namespaces.NS_WIRING_HOST);
    boolean allowFragments = true;

    if (domain.getFragmentHost() != null)
      return;

    Map.Entry<String,Attrs> bsn = domain.getBundleSymbolicName();
    Version version = Version.parseVersion(bsn.getValue().getVersion());

    bundleBuilder.addAttribute(Namespaces.NS_WIRING_BUNDLE, bsn.getKey()).addAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE, version);
    hostBuilder.addAttribute(Namespaces.NS_WIRING_HOST, bsn.getKey()).addAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE, version);

    for (Entry<String, String> entry : bsn.getValue().entrySet()) {
      String key = entry.getKey();
      if (key.endsWith(":")) {
        String directiveName = key.substring(0, key.length() - 1);
        if (Constants.FRAGMENT_ATTACHMENT_DIRECTIVE.equalsIgnoreCase(directiveName)) {
          if (Constants.FRAGMENT_ATTACHMENT_NEVER.equalsIgnoreCase(entry.getValue()))
            allowFragments = false;
        } else if (!Constants.SINGLETON_DIRECTIVE.equalsIgnoreCase(directiveName)) {
          bundleBuilder.addDirective(directiveName, entry.getValue());
        }
      } else {
        bundleBuilder.addAttribute(key, entry.getValue());
      }
    }

    caps.add(bundleBuilder.buildCapability());
    if (allowFragments)
      caps.add(hostBuilder.buildCapability());
  }

  private void doExports(Domain domain, List<? super Capability> caps) throws Exception {
    Parameters exports = domain.getExportPackage();
   
    for (Entry<String,Attrs> entry : exports.entrySet()) {
      CapReqBuilder builder = new CapReqBuilder(Namespaces.NS_WIRING_PACKAGE);

      String pkgName = Processor.removeDuplicateMarker(entry.getKey());
      builder.addAttribute(Namespaces.NS_WIRING_PACKAGE, pkgName);

      String versionStr = entry.getValue().getVersion();
      Version version = Version.parseVersion(versionStr);
     
      builder.addAttribute(Namespaces.ATTR_VERSION, version);

      for (Entry<String, String> attribEntry : entry.getValue().entrySet()) {
        String key = attribEntry.getKey();
        if (!"specification-version".equalsIgnoreCase(key) && !Constants.VERSION_ATTRIBUTE.equalsIgnoreCase(key)) {
          if (key.endsWith(":"))
            builder.addDirective(key.substring(0, key.length() - 1), attribEntry.getValue());
          else
            builder.addAttribute(key, attribEntry.getValue());
        }
      }

      Entry<String,Attrs> bsn = domain.getBundleSymbolicName();
     
      builder.addAttribute(Namespaces.ATTR_BUNDLE_SYMBOLIC_NAME, bsn.getKey());
      builder.addAttribute(Namespaces.ATTR_BUNDLE_VERSION, Version.parseVersion(bsn.getValue().getVersion()));

      caps.add(builder.buildCapability());
    }
  }

  private void doImports(Domain domain, List<? super Requirement> reqs) throws Exception {
    Parameters imports = domain.getImportPackage();

    for (Entry<String, Attrs> entry : imports.entrySet()) {
      StringBuilder filter = new StringBuilder();

      String pkgName = Processor.removeDuplicateMarker(entry.getKey());
      filter.append("(osgi.wiring.package=").append(pkgName).append(")");

      String versionStr = entry.getValue().get(Constants.VERSION_ATTRIBUTE);
      if (versionStr != null) {
        VersionRange version = new VersionRange(versionStr);
        filter.insert(0, "(&");
        filter.append(version.toFilter());
        filter.append(")");
      }

      CapReqBuilder builder = new CapReqBuilder(Namespaces.NS_WIRING_PACKAGE).addDirective(Namespaces.DIRECTIVE_FILTER, filter.toString());

      copyAttribsAndDirectives(entry.getValue(), builder, Constants.VERSION_ATTRIBUTE, "specification-version");

      reqs.add(builder.buildRequirement());
    }
  }

  private void copyAttribsAndDirectives(Map<String, String> input, CapReqBuilder output, String... ignores) {
    Set<String> ignoreSet = new HashSet<String>(Arrays.asList(ignores));

    for (Entry<String, String> entry : input.entrySet()) {
      String key = entry.getKey();
      if (!ignoreSet.contains(key)) {
        if (key.endsWith(":")) {
          String directive = key.substring(0, key.length() - 1);
          output.addDirective(directive, entry.getValue());
        } else {
          output.addAttribute(key, entry.getValue());
        }
      }
    }
  }

  private void doRequireBundles(Domain domain, List<? super Requirement> reqs) throws Exception {
   
    Parameters requires = domain.getRequireBundle();

    for (Entry<String, Attrs> entry : requires.entrySet()) {
      StringBuilder filter = new StringBuilder();

      String bsn = Processor.removeDuplicateMarker(entry.getKey());
      filter.append("(osgi.wiring.bundle=").append(bsn).append(")");

      String versionStr = entry.getValue().get(Constants.BUNDLE_VERSION_ATTRIBUTE);
      if (versionStr != null) {
        VersionRange version = new VersionRange(versionStr);
        filter.insert(0, "(&");
        filter.append(version.toFilter());
        filter.append(")");
      }

      CapReqBuilder builder = new CapReqBuilder(Namespaces.NS_WIRING_BUNDLE).addDirective(Namespaces.DIRECTIVE_FILTER, filter.toString());

      copyAttribsAndDirectives(entry.getValue(), builder, Constants.BUNDLE_VERSION_ATTRIBUTE);

      reqs.add(builder.buildRequirement());
    }
  }

  private void doFragment(Domain domain, List<? super Requirement> reqs) throws Exception {
    Entry<String,Attrs> fragmentHost = domain.getFragmentHost();

    if (fragmentHost != null) {
      StringBuilder filter = new StringBuilder();
     
      String bsn = fragmentHost.getKey();
      filter.append("(&(osgi.wiring.host=").append(bsn).append(")");

      String versionStr = fragmentHost.getValue().get(Constants.BUNDLE_VERSION_ATTRIBUTE);
      VersionRange range = new VersionRange(versionStr);
      filter.append( range.toFilter());
      filter.append(")");

      CapReqBuilder builder = new CapReqBuilder(Namespaces.NS_WIRING_HOST).addDirective(Namespaces.DIRECTIVE_FILTER, filter.toString());

      reqs.add(builder.buildRequirement());
    }
  }

  private void doExportService(Domain domain, List<? super Capability> caps) throws Exception {
    @SuppressWarnings("deprecation")
    Parameters exports = new Parameters(domain.get(Constants.EXPORT_SERVICE));

    for (Entry<String, Attrs> export : exports.entrySet()) {
      String service = Processor.removeDuplicateMarker(export.getKey());
      CapReqBuilder builder = new CapReqBuilder(Namespaces.NS_SERVICE).addAttribute(Constants.OBJECTCLASS, service);
      for (Entry<String, String> attribEntry : export.getValue().entrySet())
        builder.addAttribute(attribEntry.getKey(), attribEntry.getValue());
      builder.addDirective(Namespaces.DIRECTIVE_EFFECTIVE, Namespaces.EFFECTIVE_ACTIVE);
      caps.add(builder.buildCapability());
    }
  }

  private void doImportService(Domain domain, List<? super Requirement> reqs) throws Exception {
    @SuppressWarnings("deprecation")
    Parameters imports = new Parameters(domain.get(Constants.IMPORT_SERVICE));

    for (Entry<String, Attrs> imp : imports.entrySet()) {
      String service = Processor.removeDuplicateMarker(imp.getKey());
      StringBuilder filter = new StringBuilder();
      filter.append('(').append(Constants.OBJECTCLASS).append('=').append(service).append(')');

      CapReqBuilder builder = new CapReqBuilder(Namespaces.NS_SERVICE).addDirective(Namespaces.DIRECTIVE_FILTER, filter.toString())
          .addDirective(Namespaces.DIRECTIVE_EFFECTIVE, Namespaces.EFFECTIVE_ACTIVE);
      reqs.add(builder.buildRequirement());
    }
  }

  private void doBREE(Domain domain, List<? super Requirement> reqs) throws Exception {
    Parameters brees = domain.getBundleRequiredExecutionEnvironment();
   
    final String filter;
    if (!brees.isEmpty()) {
      if (brees.size() == 1) {
        String bree = brees.keySet().iterator().next();
        filter = EE.parseBREE(bree).toFilter();
      } else {
        StringBuilder builder = new StringBuilder().append("(|");
        for (String bree : brees.keySet()) {
          bree = Processor.removeDuplicateMarker(bree);
          builder.append(EE.parseBREE(bree).toFilter());
        }
        builder.append(')');
        filter = builder.toString();
      }

      Requirement requirement = new CapReqBuilder(Namespaces.NS_EE).addDirective(Namespaces.DIRECTIVE_FILTER, filter).buildRequirement();
      reqs.add(requirement);
    }
  }

  private void doCapabilities(Domain domain, final List<? super Capability> caps) throws Exception {
    buildFromHeader(domain.getProvideCapability(), new Yield<CapReqBuilder>() {
      public void yield(CapReqBuilder builder) {
        caps.add(builder.buildCapability());
      }
    });
  }

  private void doRequirements(Domain domain, final List<? super Requirement> reqs) throws IOException {
    buildFromHeader(domain.getRequireCapability(), new Yield<CapReqBuilder>() {
      public void yield(CapReqBuilder builder) {
        reqs.add(builder.buildRequirement());
      }
    });
  }

  private void doBundleNativeCode(Domain domain, final List<? super Requirement> reqs) throws IOException {

    Parameters nativeHeader = new Parameters(domain.get(Constants.BUNDLE_NATIVECODE));
    if (nativeHeader.isEmpty())
      return;
   
    boolean optional = false;
    List<String> options = new LinkedList<String>();

   
    for (Entry<String, Attrs> entry : nativeHeader.entrySet()) {
      String name = entry.getKey();
      if ("*".equals(name)) {
        optional = true;
        continue;
      }

      StringBuilder builder = new StringBuilder().append("(&");
      Map<String, String> attribs = entry.getValue();

      String osnamesFilter = buildFilter(attribs, Constants.BUNDLE_NATIVECODE_OSNAME, Namespaces.ATTR_NATIVE_OSNAME);
      if (osnamesFilter != null)
        builder.append(osnamesFilter);

      String versionRangeStr = attribs.get(Constants.BUNDLE_NATIVECODE_OSVERSION);
      if (versionRangeStr != null) {
        VersionRange range = new VersionRange(versionRangeStr);
        builder.append(range.toFilter());
      }

      String processorFilter = buildFilter(attribs, Constants.BUNDLE_NATIVECODE_PROCESSOR, Namespaces.ATTR_NATIVE_PROCESSOR);
      if (processorFilter != null)
        builder.append(processorFilter);

      String languageFilter = buildFilter(attribs, Constants.BUNDLE_NATIVECODE_LANGUAGE, Namespaces.ATTR_NATIVE_LANGUAGE);
      if (languageFilter != null)
        builder.append(languageFilter);

      String selectionFilter = attribs.get(Constants.SELECTION_FILTER_ATTRIBUTE);
      if (selectionFilter != null)
        builder.append(selectionFilter);

      builder.append(")");
      options.add(builder.toString());
    }
    if (options.isEmpty())
      return;

    String filter;
    if (options.size() == 1)
      filter = options.get(0);
    else {
      StringBuilder builder = new StringBuilder();
      builder.append("(|");
      for (String option : options)
        builder.append(option);
      builder.append(")");
      filter = builder.toString();
    }

    CapReqBuilder builder = new CapReqBuilder(Namespaces.NS_NATIVE).addDirective(Namespaces.DIRECTIVE_FILTER, filter);
    if (optional)
      builder.addDirective(Namespaces.DIRECTIVE_RESOLUTION, Namespaces.RESOLUTION_OPTIONAL);
    reqs.add(builder.buildRequirement());
  }

  /*
   * Assemble a compound filter by searching a map of attributes. E.g. the
   * following values:
   *
   * 1. foo=bar 2. foo=baz 3. foo=quux
   *
   * become the filter (|(foo~=bar)(foo~=baz)(foo~=quux)).
   *
   * Note that the duplicate foo keys will have trailing tildes as duplicate
   * markers, these will be removed.
   */
  private String buildFilter(Map<String, String> attribs, String match, String filterKey) {
    List<String> options = new LinkedList<String>();
    for (Entry<String, String> entry : attribs.entrySet()) {
      String key = Processor.removeDuplicateMarker(entry.getKey());
      if (match.equals(key)) {
        String filter = String.format("(%s~=%s)", filterKey, entry.getValue());
        options.add(filter);
      }
    }

    if (options.isEmpty())
      return null;
    if (options.size() == 1)
      return options.get(0);

    StringBuilder builder = new StringBuilder();
    builder.append("(|");
    for (String option : options)
      builder.append(option);
    builder.append(")");

    return builder.toString();
  }

  private static void buildFromHeader(Parameters p, Yield<CapReqBuilder> output) {
    for (Entry<String, Attrs> entry : p.entrySet()) {
      String namespace = Processor.removeDuplicateMarker(entry.getKey());
      CapReqBuilder builder = new CapReqBuilder(namespace);

      copyAttribsToBuilder(builder, entry.getValue());
      output.yield(builder);
    }
  }

  public static void copyAttribsToBuilder(CapReqBuilder builder, Attrs attribs) {
    for (Entry<String, String> attrib : attribs.entrySet()) {
      String key = attrib.getKey();

      if (key.endsWith(":")) {
        String directiveName = key.substring(0, key.length() - 1);
        builder.addDirective(directiveName, attrib.getValue());
      } else {
        // TODO
        Type type = attribs.getType(key);
        Object value = attribs.getTyped(key);
        builder.addAttribute(key, value);
      }
    }
  }

}
TOP

Related Classes of aQute.bnd.indexer.analyzers.BundleAnalyzer

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.