1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.osgi.extender.internal.activator;
18
19 import org.osgi.framework.Bundle;
20 import org.osgi.framework.BundleContext;
21 import org.springframework.osgi.io.internal.resolver.DependencyResolver;
22 import org.springframework.osgi.io.internal.resolver.ImportedBundle;
23 import org.springframework.osgi.io.internal.resolver.PackageAdminResolver;
24 import org.springframework.osgi.util.OsgiBundleUtils;
25 import org.springframework.util.Assert;
26
27 /**
28 * Simple utility class for checking the Spring compatibility between two
29 * different bundles.
30 *
31 * <p/> To escape bundle resolving (which can be difficult as the packages can
32 * be spread across multiple bundles), this class simply does class loading and
33 * the checks the compatibility between them. Since the bundles are all wired
34 * between them, the same Spring version should be used all over.
35 *
36 * @author Costin Leau
37 *
38 */
39 class SpringTypeCompatibilityChecker {
40
41 /** Spring class used for loading */
42 private static Class SPRING_TYPE = Assert.class;
43 /** hold a direct reference since it's a mandatory platform service */
44 private final DependencyResolver dependencyResolver;
45
46
47 SpringTypeCompatibilityChecker(BundleContext bundleContext) {
48
49 dependencyResolver = new PackageAdminResolver(bundleContext);
50 }
51
52 /**
53 * Returns the type compatibility between the given bundle and the Spring
54 * types used by the current version of Spring-DM. If the given bundle does
55 * not import Spring, then true is returned (the bundle is considered
56 * compatible).
57 *
58 * @param bundle
59 * @return
60 */
61 boolean checkCompatibility(Bundle bundle) {
62 Assert.notNull(bundle);
63
64 Boolean typeComparison = isTypeAvailable(bundle, SPRING_TYPE);
65
66 if (typeComparison != null) {
67 return typeComparison.booleanValue();
68 }
69
70 else {
71 ImportedBundle[] importedBundles = dependencyResolver.getImportedBundles(bundle);
72 return checkImportedBundles(importedBundles);
73 }
74 }
75
76 /**
77 * Check the Spring compatibility with the given imported bundles.
78 *
79 * @param importedBundles
80 * @return
81 */
82 private boolean checkImportedBundles(ImportedBundle[] importedBundles) {
83 for (int i = 0; i < importedBundles.length; i++) {
84 Bundle bundle = importedBundles[i].getBundle();
85
86 if (!OsgiBundleUtils.isSystemBundle(bundle)) {
87 Boolean comparsion = isTypeAvailable(bundle, SPRING_TYPE);
88 if (comparsion != null) {
89 return comparsion.booleanValue();
90 }
91 }
92 }
93
94 return true;
95 }
96
97 /**
98 * Returns a boolean representing the comparison result if the given type is
99 * found in the given bundle or null otherwise.
100 *
101 * @param bundle
102 * @param type
103 * @return
104 */
105 private static Boolean isTypeAvailable(Bundle bundle, Class type) {
106 try {
107 Class newType = bundle.loadClass(type.getName());
108 return Boolean.valueOf(type.equals(newType));
109 }
110 catch (ClassNotFoundException cnfe) {
111
112 return null;
113 }
114 }
115
116 /**
117 * Utility method used for finding bundles that load a specific type. This
118 * should be used if the PackageAdmin is not available.
119 *
120 * @param context
121 * @param type
122 * @return
123 */
124 static Bundle findOriginatingBundle(BundleContext context, Class type) {
125 Bundle[] bundles = context.getBundles();
126 for (int i = 0; i < bundles.length; i++) {
127 Bundle bundle = bundles[i];
128 Boolean isAvailable = isTypeAvailable(bundle, type);
129 if (isAvailable != null && isAvailable.booleanValue()) {
130 return bundle;
131 }
132 }
133
134 return null;
135 }
136 }