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;
11 import java.io.FileFilter;
12 import java.net.MalformedURLException;
13 import java.net.URISyntaxException;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.Dictionary;
18 import java.util.Enumeration;
19 import java.util.HashSet;
20 import java.util.Hashtable;
21 import java.util.List;
23 import java.util.regex.Pattern;
25 import org.junit.AfterClass;
26 import org.junit.Before;
27 import org.junit.BeforeClass;
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.junit.rules.TestName;
31 import org.osgi.framework.Bundle;
32 import org.osgi.framework.BundleContext;
33 import org.osgi.framework.BundleEvent;
34 import org.osgi.framework.Constants;
35 import org.springframework.osgi.mock.MockBundle;
36 import org.springframework.osgi.mock.MockBundleContext;
38 import static org.junit.Assert.assertFalse;
39 import static org.junit.Assert.assertNotNull;
40 import static org.junit.Assert.assertTrue;
42 public class BundleScannerTest {
44 private static BundleScanner bundleScanner;
45 private static List<Bundle> bundles;
47 public final TestName testName = new TestName();
50 public static void init() throws Exception {
51 bundles = makeMockBundles();
52 bundleScanner = new BundleScanner(bundles.toArray(new Bundle[bundles.size()]));
56 public static void destroy() throws Exception {
61 System.out.println("==== " + testName.getMethodName());
65 public void testValidateBundles() {
66 assertNotNull(bundleScanner);
67 BundleContext context = bundles.get(0).getBundleContext();
68 assertNotNull(context.getBundle());
69 assertNotNull(context.getBundles());
70 assertNotNull(context.getBundles().length >= 4);
74 public void testBundleEvents() throws Exception {
75 MockBundle newBundle = new TestMockBundle("misc", "", "bundle_misc");
76 assertTrue(bundleScanner.getAnnotatedClasses(
77 newBundle.getBundleContext(), null, null, false).size() == 0);
78 BundleEvent event = new BundleEvent(BundleEvent.RESOLVED, newBundle);
79 bundleScanner.bundleChanged(event);
80 assertTrue(bundleScanner.getAnnotatedClasses(
81 newBundle.getBundleContext(), null, null, false).size() == 1);
85 public void testAnnotatedClassesWithDependencies() throws Exception {
86 for (Bundle bundle : bundles) {
87 List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
88 bundle.getBundleContext(), null, null, true);
89 String name = bundle.getSymbolicName();
90 System.out.println("name:" + name + " classes:" + classes.size());
91 if ("misc".equals(name)) {
92 assertTrue(classes.size() == 1);
93 } else if ("base".equals(name)) {
94 assertTrue(classes.size() == 5);
95 } else if ("sub1".equals(name)) {
96 assertTrue(classes.size() == 6);
97 } else if ("sub2".equals(name)) {
98 assertTrue(classes.size() == 7);
104 public void testExactFiltering() {
105 Bundle bundle = findBundle("sub1");
106 String[] annos = { "javax.xml.bind.annotation.XmlTransient" };
107 List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
108 bundle.getBundleContext(), annos, null, true);
109 assertTrue(classes.size() == 1);
113 public void testNonExactFiltering() {
114 Bundle bundle = findBundle("sub1");
115 String[] annos = { "javax.xml.bind.annotation.*" };
116 List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
117 bundle.getBundleContext(), annos, null, true);
118 assertTrue(classes.size() == 6);
122 public void testFilteringUnmatched() {
123 Bundle bundle = findBundle("sub1");
124 String[] annos = { "non.existent.pkg" };
125 List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
126 bundle.getBundleContext(), annos, null, true);
127 assertTrue(classes.size() == 0);
131 public void testRegexMerge() {
132 Pattern pattern = BundleScanner.mergePatterns(
134 "javax.xml.bind.annotation.*",
139 assertTrue(pattern.matcher("Ljavax/xml/bind/annotation/FOO;").find());
140 assertFalse(pattern.matcher("Ljavax/servlet/FOO;").find());
144 public void testExclude() {
145 Set<String> excludes = new HashSet<String>();
146 excludes.add("bundle_base.Animal");
147 Bundle bundle = findBundle("sub1");
148 String[] annos = { "javax.xml.bind.annotation.*" };
149 List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
150 bundle.getBundleContext(), annos, excludes, true);
151 assertTrue(classes.size() == 5);
154 private static Bundle findBundle(String symName) {
155 for (Bundle bundle : bundles) {
156 if (bundle.getSymbolicName().equals(symName)) return bundle;
161 private static List<Bundle> makeMockBundles() throws Exception {
162 List<Bundle> result = new ArrayList<Bundle>();
163 result.add(new MockBundle());
164 result.add(new TestMockBundle("base", "", "bundle_base"));
165 result.add(new TestMockBundle("sub1", "bundle_base", "bundle_sub1"));
166 result.add(new TestMockBundle("sub2", "bundle_base", "bundle_sub2"));
170 private static List<URL> findClasses(String pkg) throws URISyntaxException {
171 if (pkg == null) return Collections.EMPTY_LIST;
172 String npkg = pkg.replaceAll("\\.", "/");
173 URL dirUrl = BundleScannerTest.class.getClassLoader().getResource(npkg);
174 final List<URL> result = new ArrayList<URL>();
175 File dir = new File(dirUrl.toURI());
176 dir.listFiles(new FileFilter() {
179 public boolean accept(File file) {
180 if (file.isFile() && file.getName().endsWith(".class")) {
182 result.add(file.toURI().toURL());
183 } catch (MalformedURLException e) {
184 throw new IllegalStateException(e);
194 public static class TestMockBundle extends MockBundle {
196 public TestMockBundle(String name, String imports, String exports) throws Exception {
197 super(name, makeHeaders(name, imports, exports), new MockBundleContext() {
199 public Bundle[] getBundles() {
200 return bundles.toArray(new Bundle[bundles.size()]);
203 MockBundleContext ctx = (MockBundleContext) this.getBundleContext();
205 this.classes = findClasses(exports);
208 private static Dictionary<String,String> makeHeaders(
209 String name, String imports, String exports)
211 Dictionary<String,String> headers = new Hashtable<String,String>();
212 headers.put(Constants.IMPORT_PACKAGE, imports);
213 headers.put(Constants.EXPORT_PACKAGE, exports);
214 headers.put(Constants.BUNDLE_SYMBOLICNAME, name);
219 public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) {
220 return Collections.enumeration(classes);
224 public long getBundleId() {