1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.osgi.service.exporter.support.internal.support;
18
19 import java.lang.ref.WeakReference;
20 import java.util.Map;
21 import java.util.WeakHashMap;
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.ServiceFactory;
29 import org.osgi.framework.ServiceRegistration;
30 import org.springframework.beans.factory.BeanFactory;
31 import org.springframework.osgi.service.util.internal.aop.ProxyUtils;
32 import org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor;
33 import org.springframework.osgi.util.DebugUtils;
34
35
36
37
38
39
40
41
42 public class PublishingServiceFactory implements ServiceFactory {
43
44
45 private static final Log log = LogFactory.getLog(PublishingServiceFactory.class);
46
47
48 private final Object monitor = new Object();
49
50
51 private final Map proxyCache;
52
53 private final Class[] classes;
54 private final Object target;
55 private final BeanFactory beanFactory;
56 private final String targetBeanName;
57 private final boolean createTCCLProxy;
58 private final ClassLoader classLoader;
59 private final ClassLoader aopClassLoader;
60 private final BundleContext bundleContext;
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 public PublishingServiceFactory(Class[] classes, Object target, BeanFactory beanFactory, String targetBeanName,
78 boolean createTCCLProxy, ClassLoader classLoader, ClassLoader aopClassLoader, BundleContext bundleContext) {
79 super();
80 this.classes = classes;
81
82 this.target = target;
83 this.beanFactory = beanFactory;
84 this.targetBeanName = targetBeanName;
85 this.createTCCLProxy = createTCCLProxy;
86 this.classLoader = classLoader;
87 this.aopClassLoader = aopClassLoader;
88 this.bundleContext = bundleContext;
89
90 proxyCache = (createTCCLProxy ? new WeakHashMap(4) : null);
91 }
92
93 private Object getBean() {
94 synchronized (monitor) {
95
96
97 return (target == null ? beanFactory.getBean(targetBeanName) : target);
98 }
99 }
100
101 public Object getService(Bundle bundle, ServiceRegistration serviceRegistration) {
102 Object bn = getBean();
103
104 if (bn instanceof ServiceFactory) {
105 bn = ((ServiceFactory) bn).getService(bundle, serviceRegistration);
106 }
107
108 if (createTCCLProxy) {
109
110 synchronized (proxyCache) {
111 WeakReference value = (WeakReference) proxyCache.get(bn);
112 Object proxy = null;
113 if (value != null) {
114 proxy = value.get();
115 }
116 if (proxy == null) {
117 proxy = createCLLProxy(bn);
118 proxyCache.put(bn, new WeakReference(proxy));
119 }
120 bn = proxy;
121 }
122 }
123
124 return bn;
125 }
126
127
128
129
130
131
132
133
134
135
136 private Object createCLLProxy(final Object target) {
137 try {
138 return ProxyUtils.createProxy(classes, target, aopClassLoader, bundleContext,
139 new Advice[] { new ServiceTCCLInterceptor(classLoader) });
140 }
141 catch (Throwable th) {
142 log.error("Cannot create TCCL managed proxy; falling back to the naked object", th);
143 if (th instanceof NoClassDefFoundError) {
144 NoClassDefFoundError ncdfe = (NoClassDefFoundError) th;
145 if (log.isWarnEnabled()) {
146 DebugUtils.debugClassLoadingThrowable(ncdfe, bundleContext.getBundle(), classes);
147 }
148 throw ncdfe;
149 }
150 }
151
152 return target;
153 }
154
155 public void ungetService(Bundle bundle, ServiceRegistration serviceRegistration, Object service) {
156 Object bn = getBean();
157
158 if (bn instanceof ServiceFactory) {
159 ((ServiceFactory) bn).ungetService(bundle, serviceRegistration, service);
160 }
161
162 if (createTCCLProxy) {
163 synchronized (proxyCache) {
164 proxyCache.values().remove(new WeakReference(service));
165 }
166 }
167 }
168 }