1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.osgi.service.importer.support;
18
19 import java.lang.reflect.Modifier;
20 import java.util.LinkedHashSet;
21 import java.util.Set;
22
23 import org.aopalliance.aop.Advice;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.osgi.framework.Bundle;
27 import org.osgi.framework.BundleContext;
28 import org.osgi.framework.ServiceReference;
29 import org.springframework.osgi.context.internal.classloader.AopClassLoaderFactory;
30 import org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker;
31 import org.springframework.osgi.service.importer.support.internal.aop.ServiceStaticInterceptor;
32 import org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor;
33 import org.springframework.osgi.util.OsgiServiceReferenceUtils;
34 import org.springframework.osgi.util.OsgiStringUtils;
35 import org.springframework.osgi.util.internal.ClassUtils;
36 import org.springframework.util.ObjectUtils;
37
38 /**
39 * @author Costin Leau
40 *
41 */
42 class StaticServiceProxyCreator extends AbstractServiceProxyCreator {
43
44 private static final Log log = LogFactory.getLog(StaticServiceProxyCreator.class);
45 /** greedy proxying mechanism */
46 private final boolean greedyProxying;
47 /** should greedy proxying consider just interfaces ? */
48 private final boolean interfacesOnlyProxying;
49
50
51 /**
52 * Constructs a new <code>StaticServiceProxyCreator</code> instance.
53 *
54 * @param classes
55 * @param classLoader
56 * @param bundleContext
57 * @param iccl
58 * @param greedyProxying
59 */
60 StaticServiceProxyCreator(Class[] classes, ClassLoader classLoader, BundleContext bundleContext,
61 ImportContextClassLoader iccl, boolean greedyProxying) {
62 super(classes, classLoader, bundleContext, iccl);
63 this.greedyProxying = greedyProxying;
64
65 boolean onlyInterfaces = true;
66
67
68 for (int i = 0; i < classes.length; i++) {
69 if (!classes[i].isInterface())
70 onlyInterfaces = false;
71 }
72
73 interfacesOnlyProxying = onlyInterfaces;
74
75 String msg = (interfacesOnlyProxying ? "NOT" : "");
76
77 if (log.isDebugEnabled())
78 log.debug("Greedy proxying will " + msg + " consider exposed classes");
79 }
80
81 ServiceInvoker createDispatcherInterceptor(ServiceReference reference) {
82 return new ServiceStaticInterceptor(bundleContext, reference);
83 }
84
85 Advice createServiceProviderTCCLAdvice(ServiceReference reference) {
86 Bundle bundle = reference.getBundle();
87
88
89 if (bundle == null)
90 return null;
91
92 return new ServiceTCCLInterceptor(AopClassLoaderFactory.getBundleClassLoaderFor(bundle));
93 }
94
95 /**
96 * Apply 'greedy' proxying by discovering the exposed classes.
97 *
98 * @param ref
99 * @return
100 */
101 Class[] discoverProxyClasses(ServiceReference ref) {
102 boolean trace = log.isTraceEnabled();
103
104 if (trace)
105 log.trace("Generating greedy proxy for service " + OsgiStringUtils.nullSafeToString(ref));
106
107 String[] classNames = OsgiServiceReferenceUtils.getServiceObjectClasses(ref);
108
109 if (trace)
110 log.trace("Discovered raw classes " + ObjectUtils.nullSafeToString(classNames));
111
112
113 Class[] classes = ClassUtils.loadClasses(classNames, classLoader);
114
115 if (trace)
116 log.trace("Visible classes are " + ObjectUtils.nullSafeToString(classes));
117
118
119 classes = ClassUtils.excludeClassesWithModifier(classes, Modifier.FINAL);
120
121 if (trace)
122 log.trace("Filtering out final classes; left out with " + ObjectUtils.nullSafeToString(classes));
123
124
125 if (interfacesOnlyProxying) {
126 Set clazzes = new LinkedHashSet(classes.length);
127 for (int classIndex = 0; classIndex < classes.length; classIndex++) {
128 Class clazz = classes[classIndex];
129 if (clazz.isInterface())
130 clazzes.add(clazz);
131 }
132 if (trace)
133 log.trace("Filtering out concrete classes; left out with " + clazzes);
134
135 classes = (Class[]) clazzes.toArray(new Class[clazzes.size()]);
136 }
137
138
139 classes = ClassUtils.removeParents(classes);
140
141 if (trace)
142 log.trace("Filtering out parent classes; left out with " + classes);
143
144 return classes;
145 }
146
147 Class[] getInterfaces(ServiceReference reference) {
148 if (greedyProxying) {
149 Class[] clazzes = discoverProxyClasses(reference);
150 if (log.isTraceEnabled())
151 log.trace("generating 'greedy' service proxy using classes " + ObjectUtils.nullSafeToString(clazzes)
152 + " over " + ObjectUtils.nullSafeToString(this.classes));
153 return clazzes;
154 }
155
156 return classes;
157 }
158 }