2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.northbound.bundlescanner.internal;
13 import java.io.FileFilter;
14 import java.net.MalformedURLException;
15 import java.net.URISyntaxException;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.Dictionary;
20 import java.util.Enumeration;
21 import java.util.HashSet;
22 import java.util.Hashtable;
23 import java.util.List;
25 import java.util.regex.Pattern;
27 import org.junit.AfterClass;
28 import org.junit.Before;
29 import org.junit.BeforeClass;
30 import org.junit.Rule;
31 import org.junit.Test;
32 import org.junit.rules.TestName;
33 import org.osgi.framework.Bundle;
34 import org.osgi.framework.BundleContext;
35 import org.osgi.framework.BundleEvent;
36 import org.osgi.framework.Constants;
37 import org.springframework.osgi.mock.MockBundle;
38 import org.springframework.osgi.mock.MockBundleContext;
40 import static junit.framework.Assert.assertNotNull;
41 import static org.junit.Assert.assertFalse;
42 import static org.junit.Assert.assertTrue;
44 public class BundleScannerTest {
46 private static BundleScanner bundleScanner;
47 private static List<Bundle> bundles;
49 public final TestName testName = new TestName();
52 public static void init() throws Exception {
53 bundles = makeMockBundles();
54 bundleScanner = new BundleScanner(bundles.toArray(new Bundle[bundles.size()]));
58 public static void destroy() throws Exception {
63 System.out.println("==== " + testName.getMethodName());
67 public void testValidateBundles() {
68 assertNotNull(bundleScanner);
69 BundleContext context = bundles.get(0).getBundleContext();
70 assertNotNull(context.getBundle());
71 assertNotNull(context.getBundles());
72 assertNotNull(context.getBundles().length >= 4);
76 public void testBundleEvents() throws Exception {
77 MockBundle newBundle = new TestMockBundle("misc", "", "bundle_misc");
78 assertTrue(bundleScanner.getAnnotatedClasses(
79 newBundle.getBundleContext(), null, null, false).size() == 0);
80 BundleEvent event = new BundleEvent(BundleEvent.RESOLVED, newBundle);
81 bundleScanner.bundleChanged(event);
82 assertTrue(bundleScanner.getAnnotatedClasses(
83 newBundle.getBundleContext(), null, null, false).size() == 1);
87 public void testAnnotatedClassesWithDependencies() throws Exception {
88 for (Bundle bundle : bundles) {
89 List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
90 bundle.getBundleContext(), null, null, true);
91 String name = bundle.getSymbolicName();
92 System.out.println("name:" + name + " classes:" + classes.size());
93 if ("misc".equals(name)) {
94 assertTrue(classes.size() == 1);
95 } else if ("base".equals(name)) {
96 assertTrue(classes.size() == 5);
97 } else if ("sub1".equals(name)) {
98 assertTrue(classes.size() == 6);
99 } else if ("sub2".equals(name)) {
100 assertTrue(classes.size() == 7);
106 public void testExactFiltering() {
107 Bundle bundle = findBundle("sub1");
108 String[] annos = { "javax.xml.bind.annotation.XmlTransient" };
109 List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
110 bundle.getBundleContext(), annos, null, true);
111 assertTrue(classes.size() == 1);
115 public void testNonExactFiltering() {
116 Bundle bundle = findBundle("sub1");
117 String[] annos = { "javax.xml.bind.annotation.*" };
118 List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
119 bundle.getBundleContext(), annos, null, true);
120 assertTrue(classes.size() == 6);
124 public void testFilteringUnmatched() {
125 Bundle bundle = findBundle("sub1");
126 String[] annos = { "non.existent.pkg" };
127 List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
128 bundle.getBundleContext(), annos, null, true);
129 assertTrue(classes.size() == 0);
133 public void testRegexMerge() {
134 Pattern pattern = BundleScanner.mergePatterns(
136 "javax.xml.bind.annotation.*",
141 assertTrue(pattern.matcher("Ljavax/xml/bind/annotation/FOO;").find());
142 assertFalse(pattern.matcher("Ljavax/servlet/FOO;").find());
146 public void testExclude() {
147 Set<String> excludes = new HashSet<String>();
148 excludes.add("bundle_base.Animal");
149 Bundle bundle = findBundle("sub1");
150 String[] annos = { "javax.xml.bind.annotation.*" };
151 List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
152 bundle.getBundleContext(), annos, excludes, true);
153 assertTrue(classes.size() == 5);
156 private static Bundle findBundle(String symName) {
157 for (Bundle bundle : bundles) {
158 if (bundle.getSymbolicName().equals(symName)) return bundle;
163 private static List<Bundle> makeMockBundles() throws Exception {
164 List<Bundle> result = new ArrayList<Bundle>();
165 result.add(new MockBundle());
166 result.add(new TestMockBundle("base", "", "bundle_base"));
167 result.add(new TestMockBundle("sub1", "bundle_base", "bundle_sub1"));
168 result.add(new TestMockBundle("sub2", "bundle_base", "bundle_sub2"));
172 private static List<URL> findClasses(String pkg) throws URISyntaxException {
173 if (pkg == null) return Collections.EMPTY_LIST;
174 String npkg = pkg.replaceAll("\\.", "/");
175 URL dirUrl = BundleScannerTest.class.getClassLoader().getResource(npkg);
176 final List<URL> result = new ArrayList<URL>();
177 File dir = new File(dirUrl.toURI());
178 dir.listFiles(new FileFilter() {
181 public boolean accept(File file) {
182 if (file.isFile() && file.getName().endsWith(".class")) {
184 result.add(file.toURI().toURL());
185 } catch (MalformedURLException e) {
186 throw new IllegalStateException(e);
196 public static class TestMockBundle extends MockBundle {
198 public TestMockBundle(String name, String imports, String exports) throws Exception {
199 super(name, makeHeaders(name, imports, exports), new MockBundleContext() {
201 public Bundle[] getBundles() {
202 return bundles.toArray(new Bundle[bundles.size()]);
205 MockBundleContext ctx = (MockBundleContext) this.getBundleContext();
207 this.classes = findClasses(exports);
210 private static Dictionary<String,String> makeHeaders(
211 String name, String imports, String exports)
213 Dictionary<String,String> headers = new Hashtable<String,String>();
214 headers.put(Constants.IMPORT_PACKAGE, imports);
215 headers.put(Constants.EXPORT_PACKAGE, exports);
216 headers.put(Constants.BUNDLE_SYMBOLICNAME, name);
221 public Enumeration findEntries(String path, String filePattern, boolean recurse) {
222 return Collections.enumeration(classes);
226 public long getBundleId() {