Package aQute.lib.osgi

Source Code of aQute.lib.osgi.Processor

/* Copyright 2006 aQute SARL
* Licensed under the Apache License, Version 2.0, see http://www.apache.org/licenses/LICENSE-2.0 */
package aQute.lib.osgi;

import java.io.*;
import java.util.*;
import java.util.regex.*;
import aQute.qtokens.QuotedTokenizer;

public class Processor {
  public final static String DEFAULT_BND_EXTENSION = ".bnd";
  public final static String DEFAULT_JAR_EXTENSION = ".jar";
  public final static String DEFAULT_BAR_EXTENSION = ".bar";

  List                       errors                = new ArrayList();
  List                       warnings              = new ArrayList();

  public void getInfo(Processor processor) {
    errors.addAll(processor.errors);
    warnings.addAll(processor.warnings);
  }

  public void warning(String string) {
    warnings.add(string);
  }

  public void error(String string) {
    errors.add(string);
  }

  public List getWarnings() {
    return warnings;
  }

  public List getErrors() {
    return errors;
  }

  public Map parseHeader(String value) {
    return parseHeader(value, this);
  }
  /**
   * Standard OSGi header parser. This parser can handle the format clauses ::=
   * clause ( ',' clause ) + clause ::= name ( ';' name ) (';' key '=' value )
   *
   * This is mapped to a Map { name => Map { attr|directive => value } }
   *
   * @param value
   * @return
   * @throws MojoExecutionException
   */
  static public Map parseHeader(String value,
      Processor logger) {
    if (value == null || value.trim().length() == 0) return new HashMap();

    Map result = new LinkedHashMap();
    QuotedTokenizer qt = new QuotedTokenizer(value, ";=,");
    char del;
    do {
      boolean hadAttribute = false;
      Map clause = new HashMap();
      List aliases = new ArrayList();
      aliases.add(qt.nextToken());
      del = qt.getSeparator();
      while (del == ';') {
        String adname = qt.nextToken();
        if ((del = qt.getSeparator()) != '=') {
          if (hadAttribute) throw new IllegalArgumentException(
              "Header contains name field after attribute or directive: "
                  + adname + " from " + value);
          aliases.add(adname);
        } else {
          String advalue = qt.nextToken();
          clause.put(adname, advalue);
          del = qt.getSeparator();
          hadAttribute = true;
        }
      }
      for (Iterator i = aliases.iterator(); i.hasNext();) {
        String packageName = (String) i.next();
        if (result.containsKey(packageName)) {
          if (logger != null) logger
              .warning("Duplicate package name in header: "
                  + packageName
                  + ". Multiple package names in one clause not supported in Bnd.");
        } else result.put(packageName, clause);
      }
    } while (del == ',');
    return result;
  }

  public Map analyzeBundleClasspath(Jar dot, Map bundleClasspath,
      Map contained, Map referred, Map uses)
      throws IOException {
    Map classSpace = new HashMap();

    if (bundleClasspath.isEmpty()) {
      analyzeJar(dot, "", classSpace, contained, referred,
          uses);
    } else {
      for (Iterator j = bundleClasspath.keySet().iterator(); j
          .hasNext();) {
        String path = (String) j.next();
        if ( path.equals(".") ) {
            analyzeJar(dot, "", classSpace, contained,
                    referred, uses);
            continue;
        }
        //
        // There are 3 cases:
        // - embedded JAR file
        // - directory
        // - error
        //

        Resource resource = dot.getResource(path);
        if (resource != null) {
          try {
            Jar jar = new Jar(path);
            EmbeddedResource.build(jar, resource
                .openInputStream());
            analyzeJar(jar, "", classSpace, contained,
                referred, uses);
          } catch (Exception e) {
            warning("Invalid bundle classpath entry: "
                + path + " " + e);
          }
        } else {
          if (dot.getDirectories().containsKey(path)) {
            analyzeJar(dot, path, classSpace, contained,
                referred, uses);
          } else {
            warning("No sub JAR or directory " + path);
          }
        }
      }
    }
    return classSpace;
  }

  /**
   * We traverse through al the classes that we can find and calculate the
   * contained and referred set and uses. This method ignores the Bundle
   * classpath.
   *
   * @param jar
   * @param contained
   * @param referred
   * @param uses
   * @throws IOException
   */
  private void analyzeJar(Jar jar, String prefix,
      Map classSpace, Map contained, Map referred, Map uses)
      throws IOException {
    next: for (Iterator r = jar.getResources().keySet()
        .iterator(); r.hasNext();) {
      String path = (String) r.next();
      if (path.startsWith(prefix)) {
        String relativePath = path.substring(prefix
            .length());
        String pack = getPackage(relativePath);

        if (!contained.containsKey(pack)) {
          if (!(pack.equals(".") || pack.equals("META-INF"))) {

            Map map = new HashMap();
            contained.put(pack, map);
            Resource pinfo = jar.getResource(prefix
                + pack.replace('.', '/') + "/packageinfo");
            if (pinfo != null) {
              String version = parsePackageInfo(pinfo
                  .openInputStream());
              if (version != null) map.put("version",
                  version);
            }
          }
        }

        if (path.endsWith(".class")) {
          Resource resource = jar.getResource(path);
          Clazz clazz;

          try {
            clazz = new Clazz(relativePath, resource
                .openInputStream());
          } catch (Throwable e) {
            errors.add("Invalid class file: "
                + relativePath + " " + e.getMessage());
            continue next;
          }
          classSpace.put(relativePath, clazz);
          referred.putAll(clazz.getReferred());

          // Add all the used packages
          // to this package
          Set t = (Set) uses.get(pack);
          if (t == null) uses.put(pack, t = new HashSet());
          t.addAll(clazz.getReferred().keySet());
          t.remove(pack);
        }
      }
    }
  }

  public String getPackage(String clazz) {
    int n = clazz.lastIndexOf('/');
    if (n < 0) return ".";
    return clazz.substring(0, n).replace('/', '.');
  }

  static Pattern packageinfo = Pattern
                                 .compile("version\\s+([0-9.]+).*");

  static String parsePackageInfo(InputStream jar)
      throws IOException {
    try {
      byte[] buf = EmbeddedResource.collect(jar, 0);
      String line = new String(buf).trim();
      Matcher m = packageinfo.matcher(line);
      if (m.matches()) {
        return m.group(1);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  static Map removeKeys(Map source, String prefix) {
    Map temp = new TreeMap(source);
    for (Iterator p = temp.keySet().iterator(); p.hasNext();) {
      String pack = (String) p.next();
      if (pack.startsWith(prefix)) p.remove();
    }
    return temp;
  }

}
TOP

Related Classes of aQute.lib.osgi.Processor

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.