/** * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.controller.northbound.bundlescanner.internal; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Dictionary; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * BundleInfo holds information related to the bundle obtained during the * bundle scan process. */ /*package*/ class BundleInfo { private static final Logger LOGGER = LoggerFactory.getLogger(BundleInfo.class); private final Bundle bundle; private final Map> annotatedClasses; private final Set exportPkgs; private final Set importPkgs; public BundleInfo(Bundle bundle, Map> classes) { this.bundle = bundle; this.annotatedClasses = classes; Dictionary dict = bundle.getHeaders(); this.importPkgs = parsePackages(dict.get(Constants.IMPORT_PACKAGE)); this.exportPkgs = parsePackages(dict.get(Constants.EXPORT_PACKAGE)); } @Override public String toString() { StringBuilder sb = new StringBuilder(super.toString()); sb.append("{name:").append(bundle.getSymbolicName()) .append(" id:").append(getId()) .append(" annotated-classes:").append(annotatedClasses) .append(" imports:").append(importPkgs) .append(" exports:").append(exportPkgs).append("}"); return sb.toString(); } public Bundle getBundle() { return bundle; } public long getId() { return bundle.getBundleId(); } public List> getAnnotatedClasses(Pattern pattern) { List result = new ArrayList(); for (Map.Entry> entry : annotatedClasses.entrySet()) { if (matches(pattern, entry.getValue())) { result.add(entry.getKey()); } } return BundleScanner.loadClasses(bundle, result); } private boolean matches(Pattern pattern, Set values) { if (pattern == null) return true; //LOGGER.debug("Matching: {} {}", pattern.toString(), values); for (String s : values) { if (pattern.matcher(s).find()) return true; } return false; } public List> getAnnotatedClasses( Collection allbundles, Pattern pattern) { List> classes = getAnnotatedClasses(pattern); processAnnotatedClassesInternal(this, allbundles, pattern, new HashSet(), classes); return classes; } private List getExportedAnnotatedClasses(Pattern pattern) { List classes = new ArrayList(); for (Map.Entry> entry : annotatedClasses.entrySet()) { String cls = entry.getKey(); int idx = cls.lastIndexOf("."); String pkg = (idx == -1 ? "" : cls.substring(0, idx)); // for a class to match, the package has to be exported and // annotations should match the given pattern if (exportPkgs.contains(pkg) && matches(pattern, entry.getValue())) { classes.add(cls); } } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Found in bundle:{} exported classes:[{}]", getBundle().getSymbolicName(), classes); } return classes; } private static void processAnnotatedClassesInternal( BundleInfo target, Collection bundlesToScan, Pattern pattern, Collection visited, List> classes) { for (BundleInfo other : bundlesToScan) { if (other.getId() == target.getId()) continue; if (target.isDependantOn(other)) { if (!visited.contains(other)) { classes.addAll(BundleScanner.loadClasses(other.getBundle(), other.getExportedAnnotatedClasses(pattern))); visited.add(other); processAnnotatedClassesInternal(other, bundlesToScan, pattern, visited, classes); } } } } private boolean isDependantOn(BundleInfo other) { for (String pkg : importPkgs) { if (other.exportPkgs.contains(pkg)) return true; } return false; } public List getDependencies(Collection bundles) { List result = new ArrayList(); for(BundleInfo bundle : bundles) { if (isDependantOn(bundle)) result.add(bundle); } return result; } private static Set parsePackages(String packageString) { if (packageString == null) return Collections.emptySet(); String[] packages = packageString.split(","); Set result = new HashSet(); for (int i=0; i