Search in sources :

Example 1 with ClassParser

use of aQute.bnd.service.classparser.ClassParser in project bnd by bndtools.

the class Analyzer method analyze.

/**
	 * Calculates the data structures for generating a manifest.
	 * 
	 * @throws IOException
	 */
public void analyze() throws Exception {
    if (!analyzed) {
        analyzed = true;
        uses.clear();
        apiUses.clear();
        classspace.clear();
        classpathExports.clear();
        contracts.clear();
        packagesVisited.clear();
        // Parse all the class in the
        // the jar according to the OSGi bcp
        analyzeBundleClasspath();
        for (Jar current : getClasspath()) {
            getManifestInfoFromClasspath(current, classpathExports, contracts);
            Manifest m = current.getManifest();
            if (m == null)
                for (String dir : current.getDirectories().keySet()) {
                    learnPackage(current, "", getPackageRef(dir), classpathExports);
                }
        }
        // Handle the bundle activator
        String s = getProperty(BUNDLE_ACTIVATOR);
        if (s != null && !s.isEmpty()) {
            activator = getTypeRefFromFQN(s);
            referTo(activator);
            logger.debug("activator {} {}", s, activator);
        }
        // Conditional packages
        doConditionalPackages();
        // Execute any plugins
        // TODO handle better reanalyze
        doPlugins();
        //
        for (Clazz c : classspace.values()) {
            ees.add(c.getFormat());
        }
        if (since(About._2_3)) {
            try (ClassDataCollectors cds = new ClassDataCollectors(this)) {
                List<ClassParser> parsers = getPlugins(ClassParser.class);
                for (ClassParser cp : parsers) {
                    cds.add(cp.getClassDataCollector(this));
                }
                //
                // built ins
                //
                cds.add(annotationHeaders = new AnnotationHeaders(this));
                for (Clazz c : classspace.values()) {
                    cds.parse(c);
                }
            }
        }
        referred.keySet().removeAll(contained.keySet());
        //
        // EXPORTS
        //
        {
            Set<Instruction> unused = Create.set();
            Instructions filter = new Instructions(getExportPackage());
            filter.append(getExportContents());
            exports = filter(filter, contained, unused);
            if (!unused.isEmpty()) {
                warning("Unused " + Constants.EXPORT_PACKAGE + " instructions: %s ", unused).header(Constants.EXPORT_PACKAGE).context(unused.iterator().next().input);
            }
            // See what information we can find to augment the
            // exports. I.e. look on the classpath
            augmentExports(exports);
        }
        //
        // IMPORTS
        // Imports MUST come after exports because we use information from
        // the exports
        //
        {
            // Add all exports that do not have an -noimport: directive
            // to the imports.
            Packages referredAndExported = new Packages(referred);
            referredAndExported.putAll(doExportsToImports(exports));
            removeDynamicImports(referredAndExported);
            // Remove any Java references ... where are the closures???
            for (Iterator<PackageRef> i = referredAndExported.keySet().iterator(); i.hasNext(); ) {
                if (i.next().isJava())
                    i.remove();
            }
            Set<Instruction> unused = Create.set();
            String h = getProperty(IMPORT_PACKAGE);
            if (// If not set use a default
            h == null)
                h = "*";
            if (isPedantic() && h.trim().length() == 0)
                warning("Empty " + Constants.IMPORT_PACKAGE + " header");
            Instructions filter = new Instructions(h);
            imports = filter(filter, referredAndExported, unused);
            if (!unused.isEmpty()) {
                // We ignore the end wildcard catch
                if (!(unused.size() == 1 && unused.iterator().next().toString().equals("*")))
                    warning("Unused " + Constants.IMPORT_PACKAGE + " instructions: %s ", unused).header(Constants.IMPORT_PACKAGE).context(unused.iterator().next().input);
            }
            // See what information we can find to augment the
            // imports. I.e. look in the exports
            augmentImports(imports, exports);
        }
        //
        // USES
        //
        // Add the uses clause to the exports
        // brave,
        boolean api = true;
        // lets see
        doUses(exports, api ? apiUses : uses, imports);
        //
        // Verify that no exported package has a reference to a private
        // package
        // This can cause a lot of harm.
        // TODO restrict the check to public API only, but even then
        // exported packages
        // should preferably not refer to private packages.
        //
        Set<PackageRef> privatePackages = getPrivates();
        for (Iterator<PackageRef> p = privatePackages.iterator(); p.hasNext(); ) if (p.next().isJava())
            p.remove();
        for (PackageRef exported : exports.keySet()) {
            List<PackageRef> used = uses.get(exported);
            if (used != null) {
                Set<PackageRef> privateReferences = new HashSet<PackageRef>(apiUses.get(exported));
                privateReferences.retainAll(privatePackages);
                if (!privateReferences.isEmpty())
                    msgs.Export_Has_PrivateReferences_(exported, privateReferences.size(), privateReferences);
            }
        }
        //
        if (referred.containsKey(Descriptors.DEFAULT_PACKAGE)) {
            error("The default package '.' is not permitted by the " + Constants.IMPORT_PACKAGE + " syntax.%n" + " This can be caused by compile errors in Eclipse because Eclipse creates%n" + "valid class files regardless of compile errors.%n" + "The following package(s) import from the default package %s", uses.transpose().get(Descriptors.DEFAULT_PACKAGE));
        }
    }
}
Also used : SortedSet(java.util.SortedSet) EnumSet(java.util.EnumSet) Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) Manifest(java.util.jar.Manifest) Iterator(java.util.Iterator) PackageRef(aQute.bnd.osgi.Descriptors.PackageRef) ClassParser(aQute.bnd.service.classparser.ClassParser) HashSet(java.util.HashSet)

Aggregations

PackageRef (aQute.bnd.osgi.Descriptors.PackageRef)1 ClassParser (aQute.bnd.service.classparser.ClassParser)1 EnumSet (java.util.EnumSet)1 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 Set (java.util.Set)1 SortedSet (java.util.SortedSet)1 TreeSet (java.util.TreeSet)1 Manifest (java.util.jar.Manifest)1