Package: ClassLoadingHelper

ClassLoadingHelper

nameinstructionbranchcomplexitylinemethod
ClassLoadingHelper()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
addURLs(HashSet, Enumeration, String)
M: 1 C: 22
96%
M: 2 C: 6
75%
M: 2 C: 3
60%
M: 1 C: 6
86%
M: 0 C: 1
100%
convertToClassName(String)
M: 6 C: 25
81%
M: 2 C: 4
67%
M: 2 C: 2
50%
M: 2 C: 6
75%
M: 0 C: 1
100%
convertToResourcePath(String)
M: 10 C: 30
75%
M: 3 C: 5
63%
M: 3 C: 2
40%
M: 2 C: 6
75%
M: 0 C: 1
100%
findEntries(Bundle, String)
M: 0 C: 43
100%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 8
100%
M: 0 C: 1
100%
getBundlesContainingResource(BundleContext, String)
M: 0 C: 39
100%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 0 C: 7
100%
M: 0 C: 1
100%
getBundlesLoadingClass(BundleContext, String)
M: 0 C: 37
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
getBundlesLoadingClass(BundleContext, String, String)
M: 26 C: 80
75%
M: 2 C: 10
83%
M: 2 C: 5
71%
M: 2 C: 20
91%
M: 0 C: 1
100%
getOriginBundleOfClass(String, BundleContext, Bundle)
M: 0 C: 19
100%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 7
100%
M: 0 C: 1
100%
isPackageExported(BundleContext, String, Bundle)
M: 1 C: 44
98%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 8
100%
M: 0 C: 1
100%
tryToLoadClass(String, Bundle)
M: 0 C: 12
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2010 SAP AG
3: * All rights reserved. This program and the accompanying materials
4: * are made available under the terms of the Eclipse Public License v1.0
5: * which accompanies this distribution, and is available at
6: * http://www.eclipse.org/legal/epl-v10.html
7: *
8: * Contributors:
9: * Hristo Iliev, SAP AG - initial contribution
10: *******************************************************************************/
11: package org.eclipse.virgo.shell.osgicommand.helper;
12:
13: import org.eclipse.osgi.service.resolver.BundleDescription;
14: import org.eclipse.osgi.service.resolver.ExportPackageDescription;
15: import org.eclipse.osgi.service.resolver.PlatformAdmin;
16: import org.osgi.framework.Bundle;
17: import org.osgi.framework.BundleContext;
18: import org.osgi.framework.FrameworkUtil;
19: import org.osgi.framework.ServiceReference;
20: import org.osgi.service.packageadmin.PackageAdmin;
21:
22: import java.net.URL;
23: import java.util.*;
24:
25: /**
26: * Helper for class loading supporting commands
27: */
28: @SuppressWarnings("deprecation")
29: public class ClassLoadingHelper {
30:
31: /**
32: * Determines if a class package is exported by a bundle
33: *
34: * @param bundleContext Bundle context for interaction with the OSGi framework
35: * @param classPackage Class package to check for
36: * @param testBundle The bundle that has to be tested
37: * @return TRUE if the bundle is exported by the package, FALSE if the class is not exported or it does not have a package
38: */
39: public static boolean isPackageExported(BundleContext bundleContext, String classPackage, Bundle testBundle) {
40: ServiceReference<PlatformAdmin> reference = bundleContext.getServiceReference(PlatformAdmin.class);
41: PlatformAdmin platformAdmin = bundleContext.getService(reference);
42: BundleDescription bundleDescription = platformAdmin.getState(false).getBundle(testBundle.getBundleId());
43:
44: ExportPackageDescription[] exportDescriptions = bundleDescription.getSelectedExports();
45:• for (ExportPackageDescription exportDescription : exportDescriptions) {
46:• if (exportDescription.getName().equals(convertToClassName(classPackage)))
47: return true;
48: }
49:
50: // not found
51: return false;
52: }
53:
54: /**
55: * Returns the bundles that can load a class and the originating bundle in a map
56: *
57: * @param bundleContext Bundle context for interaction with the OSGi framework
58: * @param className Fully qualified class name (in the form <package>.<class name>)
59: * @return Map between the bundles that can load the class and the bundle that provides it in each case
60: */
61: public static Map<Bundle, Bundle> getBundlesLoadingClass(BundleContext bundleContext, String className) {
62: Bundle[] bundles = bundleContext.getBundles();
63: HashMap<Bundle, Bundle> foundBundles = new HashMap<Bundle, Bundle>();
64:• for (Bundle bundle : bundles) {
65: Bundle originBundle = getOriginBundleOfClass(className, bundleContext, bundle);
66:• if (originBundle != null) {
67: foundBundles.put(bundle, originBundle);
68: }
69: }
70:
71: return foundBundles;
72: }
73:
74: /**
75: * Find the originating bundle of a class loaded by a bundle
76: *
77: * @param className Fully qualified class name (in the form <package>.<class name> name)
78: * @param bundleContext Bundle context for interaction with the OSGi framework
79: * @param loadingBundle Bundle instance to load class from
80: * @return originating {@link Bundle} or null if it cannot be loaded by <code>testBundle</code>
81: */
82: public static Bundle getOriginBundleOfClass(String className, BundleContext bundleContext, Bundle loadingBundle) {
83: Class<?> clasz = tryToLoadClass(className, loadingBundle);
84: Bundle originBundle = null;
85:• if (clasz != null) {
86: originBundle = FrameworkUtil.getBundle(clasz);
87:• if (originBundle == null) {
88: // this is the system bundle
89: originBundle = bundleContext.getBundle(0);
90: }
91: }
92: return originBundle;
93: }
94:
95: /**
96: * Tries to load a class
97: *
98: * @param className Fully qualified class name (in the form <package>.<class name>)
99: * @param bundle Bundle instance that has to be checked
100: * @return The loaded class or null if it cannot be loaded from this bundle
101: */
102: public static Class<?> tryToLoadClass(String className, Bundle bundle) {
103:• if (bundle == null)
104: return null;
105:
106: try {
107: return bundle.loadClass(convertToClassName(className));
108: } catch (ClassNotFoundException e) {
109: // do nothing - if the class is not found we don't care
110: }
111: return null;
112: }
113:
114: /**
115: * Converts resource path (/javax/servlet/Servlet.class) to class name (javax.servlet.Servlet)
116: *
117: * @param resourcePath Path to the resource
118: * @return Class name
119: */
120: public static String convertToClassName(String resourcePath) {
121:• if (resourcePath == null)
122: return null;
123:
124: resourcePath = resourcePath.replace("/", ".");
125:• if (resourcePath.startsWith(".")) {
126: resourcePath = resourcePath.substring(1);
127: }
128:• if (resourcePath.endsWith(".class")) {
129: resourcePath = resourcePath.substring(0, resourcePath.length() - 6);
130: }
131:
132: return resourcePath;
133: }
134:
135: /**
136: * Convert from package to path format (javax.servlet.Servlet --> javax/servlet/Servlet.class)
137: *
138: * @param className Class name
139: * @return Path to a resource
140: */
141: public static String convertToResourcePath(String className) {
142:• if (className == null)
143: return null;
144:
145: String result = className;
146:• if (!className.contains("/") && !className.contains("*")) {
147:• if (className.endsWith(".class")) {
148: result = className.substring(0, className.length() - 6);
149: }
150: return result.replace(".", "/") + ".class";
151: }
152:
153: return result;
154: }
155:
156: /**
157: * Returns all bundles that can load a class
158: *
159: * @param bundleContext Bundle context for interaction with the OSGi framework
160: * @param className Fully qualified class name (in the form <package>.<class name>)
161: * @param bundle Bundle name or ID that has to be checked
162: * @return Map between the bundle that can load the class (key) and the one that provides it (value)
163: * @throws IllegalArgumentException if there is no bundle with such name/id
164: */
165: public static Map<Bundle, Bundle> getBundlesLoadingClass(BundleContext bundleContext, String className, String bundle) throws IllegalArgumentException {
166: HashMap<Bundle, Bundle> result = new HashMap<Bundle, Bundle>();
167: long id = Long.MIN_VALUE;
168: try {
169: id = Long.parseLong(bundle);
170: } catch (NumberFormatException e) {
171: // not a number - then it is bundle name
172: }
173:
174:• if (id >= 0) {
175: Bundle testBundle = bundleContext.getBundle(id);
176:• if (testBundle == null)
177: throw new IllegalArgumentException("Bundle with ID [" + id + "] not found");
178:
179: Bundle originBundle = getOriginBundleOfClass(className, bundleContext, testBundle);
180:• if (originBundle != null) {
181: result.put(testBundle, originBundle);
182: }
183: } else {
184: ServiceReference<PackageAdmin> reference = bundleContext.getServiceReference(PackageAdmin.class);
185: PackageAdmin packageAdmin = bundleContext.getService(reference);
186: Bundle[] bundles = packageAdmin.getBundles(bundle, null);
187:• if (bundles == null)
188: throw new IllegalArgumentException("Bundle with symbolic name [" + bundle + "] not found");
189:
190:• for (Bundle testBundle : bundles) {
191: Bundle originBundle = getOriginBundleOfClass(className, bundleContext, testBundle);
192:• if (originBundle != null) {
193: result.put(testBundle, originBundle);
194: }
195: }
196: }
197:
198: return result;
199: }
200:
201: /**
202: * Returns all bundles that contain a class
203: *
204: * @param bundleContext Bundle context for interaction with the OSGi framework
205: * @param resourcePattern Search pattern in the form <package>/<class name>. The pattern can contain wildcards
206: * @return Map between the bundle (key) and the URL(s) of the resources (value)
207: */
208: public static Map<Bundle, List<String>> getBundlesContainingResource(BundleContext bundleContext, String resourcePattern) {
209: Map<Bundle, List<String>> result = new HashMap<Bundle, List<String>>();
210:
211: Bundle[] bundles = bundleContext.getBundles();
212:• for (Bundle bundle : bundles) {
213: List<String> entries = findEntries(bundle, resourcePattern);
214:• if (entries != null && entries.size() != 0) {
215: result.put(bundle, entries);
216: }
217: }
218:
219: return result;
220: }
221:
222: /**
223: * Returns a list with bundle entries matching a resource pattern
224: *
225: * @param bundle Bundle to scan for entries
226: * @param resourcePattern Pattern used for matching
227: * @return List with found entries
228: */
229: private static List<String> findEntries(Bundle bundle, String resourcePattern) {
230: HashSet<String> urls = new HashSet<String>();
231:
232: int index = resourcePattern.lastIndexOf("/");
233:• if (index != -1) {
234: String resourcePath = resourcePattern.substring(0, index);
235: String resourceEntity = resourcePattern.substring(index + 1);
236: // Search the whole bundle for entity starting from the root. We need this since "the pattern is only
237: // matched against the last element of the entry path" as stated in findEntries JavaDoc. This means that
238: // web bundle that packages a class in WEB-INF/classes will not be found by findEntries since the path is
239: // prepended with WEB-INF/classes. Therefore we search for a class everywhere in the bundle and then
240: // filter the result.
241: addURLs(urls, bundle.findEntries("/", resourceEntity, true), resourcePath);
242: }
243:
244: // Search the root of the bundle for entity matching the specified pattern
245: addURLs(urls, bundle.findEntries("/", resourcePattern, true), null);
246: return new ArrayList<String>(urls);
247: }
248:
249: /**
250: * Adds all found resources eliminating the duplicates or the ones that do not contain the requested path
251: *
252: * @param urls Result set with URLs as string
253: * @param foundURLs Enumeration to scan
254: * @param path Expected path of the entities. The entities are not put in the result set unless they contain
255: * this path.
256: */
257: private static void addURLs(HashSet<String> urls, Enumeration<URL> foundURLs, String path) {
258:• if (foundURLs != null) {
259:• while (foundURLs.hasMoreElements()) {
260: String url = foundURLs.nextElement().getFile();
261:• if (path != null && !url.contains(path)) {
262: continue;
263: }
264: urls.add(url);
265: }
266: }
267: }
268:
269: }