1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
14 |
| |
15 |
| package org.apache.hivemind.impl.servicemodel; |
16 |
| |
17 |
| import java.lang.reflect.Constructor; |
18 |
| import java.lang.reflect.Modifier; |
19 |
| |
20 |
| import org.apache.hivemind.ApplicationRuntimeException; |
21 |
| import org.apache.hivemind.events.RegistryShutdownListener; |
22 |
| import org.apache.hivemind.impl.ConstructableServicePoint; |
23 |
| import org.apache.hivemind.impl.ProxyBuilder; |
24 |
| import org.apache.hivemind.internal.ServicePoint; |
25 |
| import org.apache.hivemind.service.BodyBuilder; |
26 |
| import org.apache.hivemind.service.ClassFab; |
27 |
| import org.apache.hivemind.service.MethodSignature; |
28 |
| |
29 |
| |
30 |
| |
31 |
| |
32 |
| |
33 |
| |
34 |
| |
35 |
| |
36 |
| public final class SingletonServiceModel extends AbstractServiceModelImpl |
37 |
| { |
38 |
| |
39 |
| |
40 |
| |
41 |
| protected static final String SERVICE_ACCESSOR_METHOD_NAME = "_service"; |
42 |
| |
43 |
| private Object _serviceProxy; |
44 |
| |
45 |
| private SingletonInnerProxy _innerProxy; |
46 |
| |
47 |
| private Object _constructedService; |
48 |
| |
49 |
995
| public SingletonServiceModel(ConstructableServicePoint servicePoint)
|
50 |
| { |
51 |
995
| super(servicePoint);
|
52 |
| } |
53 |
| |
54 |
996
| public synchronized Object getService()
|
55 |
| { |
56 |
996
| if (_serviceProxy == null)
|
57 |
995
| _serviceProxy = createSingletonProxy();
|
58 |
| |
59 |
996
| return _serviceProxy;
|
60 |
| } |
61 |
| |
62 |
| |
63 |
| |
64 |
| |
65 |
495
| public synchronized Object getActualServiceImplementation()
|
66 |
| { |
67 |
495
| if (_constructedService == null)
|
68 |
| { |
69 |
495
| _constructedService = constructServiceImplementation();
|
70 |
495
| registerWithShutdownCoordinator(_constructedService);
|
71 |
| } |
72 |
| |
73 |
| |
74 |
| |
75 |
| |
76 |
| |
77 |
| |
78 |
| |
79 |
495
| Class serviceInterface = getServicePoint().getServiceInterface();
|
80 |
| |
81 |
495
| if (!serviceInterface.isInstance(_constructedService))
|
82 |
6
| _constructedService = constructBridgeProxy(_constructedService);
|
83 |
| |
84 |
495
| return _constructedService;
|
85 |
| } |
86 |
| |
87 |
| |
88 |
| |
89 |
| |
90 |
995
| private Object createSingletonProxy()
|
91 |
| { |
92 |
995
| if (_log.isDebugEnabled())
|
93 |
4
| _log.debug("Creating SingletonProxy for service "
|
94 |
| + getServicePoint().getExtensionPointId()); |
95 |
| |
96 |
995
| try
|
97 |
| { |
98 |
| |
99 |
| |
100 |
| |
101 |
| |
102 |
995
| Class proxyClass = createSingletonProxyClass();
|
103 |
| |
104 |
| |
105 |
| |
106 |
| |
107 |
995
| Class innerProxyClass = createInnerProxyClass(proxyClass);
|
108 |
| |
109 |
| |
110 |
| |
111 |
995
| Object result = proxyClass.newInstance();
|
112 |
| |
113 |
| |
114 |
| |
115 |
| |
116 |
995
| Constructor c = innerProxyClass.getConstructor(new Class[]
|
117 |
| { proxyClass, getClass() }); |
118 |
| |
119 |
995
| _innerProxy = (SingletonInnerProxy) c.newInstance(new Object[]
|
120 |
| { result, this }); |
121 |
| |
122 |
995
| RegistryShutdownListener asListener = (RegistryShutdownListener) result;
|
123 |
| |
124 |
995
| getServicePoint().addRegistryShutdownListener(asListener);
|
125 |
| |
126 |
995
| return result;
|
127 |
| } |
128 |
| catch (Exception ex) |
129 |
| { |
130 |
0
| throw new ApplicationRuntimeException(ex);
|
131 |
| } |
132 |
| |
133 |
| } |
134 |
| |
135 |
| |
136 |
| |
137 |
| |
138 |
| |
139 |
| |
140 |
| |
141 |
995
| private Class createSingletonProxyClass()
|
142 |
| { |
143 |
995
| ConstructableServicePoint servicePoint = getServicePoint();
|
144 |
| |
145 |
995
| ProxyBuilder proxyBuilder = new ProxyBuilder("SingletonProxy", servicePoint, true);
|
146 |
| |
147 |
995
| ClassFab classFab = proxyBuilder.getClassFab();
|
148 |
| |
149 |
995
| Class serviceInterface = servicePoint.getServiceInterface();
|
150 |
| |
151 |
| |
152 |
| |
153 |
| |
154 |
995
| classFab.addField("_inner", serviceInterface);
|
155 |
995
| classFab.addField("_shutdown", boolean.class);
|
156 |
995
| if (!RegistryShutdownListener.class.isAssignableFrom(serviceInterface))
|
157 |
| { |
158 |
994
| classFab.addInterface(RegistryShutdownListener.class);
|
159 |
| |
160 |
994
| classFab.addMethod(Modifier.PUBLIC | Modifier.FINAL, new MethodSignature(void.class,
|
161 |
| "registryDidShutdown", null, null), "{ _shutdown = true; }"); |
162 |
| } |
163 |
995
| classFab.addMethod(
|
164 |
| Modifier.PUBLIC | Modifier.SYNCHRONIZED | Modifier.FINAL, |
165 |
| new MethodSignature(void.class, "_setInner", new Class[] |
166 |
| { serviceInterface }, null), |
167 |
| "{ _inner = $1; }"); |
168 |
| |
169 |
995
| BodyBuilder builder = new BodyBuilder();
|
170 |
995
| builder.begin();
|
171 |
995
| builder.addln("if (_shutdown)");
|
172 |
995
| builder.begin();
|
173 |
995
| builder.addln("_inner = null;");
|
174 |
995
| builder.addln("throw org.apache.hivemind.HiveMind#createRegistryShutdownException();");
|
175 |
995
| builder.end();
|
176 |
| |
177 |
995
| builder.addln("return _inner;");
|
178 |
995
| builder.end();
|
179 |
| |
180 |
995
| classFab.addMethod(Modifier.PRIVATE, new MethodSignature(serviceInterface, "_getInner",
|
181 |
| null, null), builder.toString()); |
182 |
| |
183 |
995
| proxyBuilder.addServiceMethods("_getInner()");
|
184 |
| |
185 |
995
| return classFab.createClass();
|
186 |
| } |
187 |
| |
188 |
995
| private Class createInnerProxyClass(Class deferredProxyClass)
|
189 |
| { |
190 |
995
| ServicePoint servicePoint = getServicePoint();
|
191 |
| |
192 |
995
| Class serviceInterface = servicePoint.getServiceInterface();
|
193 |
995
| ProxyBuilder builder = new ProxyBuilder("InnerProxy", servicePoint);
|
194 |
| |
195 |
995
| ClassFab classFab = builder.getClassFab();
|
196 |
| |
197 |
995
| classFab.addField("_deferredProxy", deferredProxyClass);
|
198 |
995
| classFab.addField("_service", serviceInterface);
|
199 |
995
| classFab.addField("_serviceModel", getClass());
|
200 |
| |
201 |
995
| BodyBuilder body = new BodyBuilder();
|
202 |
| |
203 |
| |
204 |
| |
205 |
| |
206 |
995
| body.begin();
|
207 |
| |
208 |
995
| body.addln("super();");
|
209 |
995
| body.addln("_deferredProxy = $1;");
|
210 |
995
| body.addln("_serviceModel = $2;");
|
211 |
995
| body.addln("_deferredProxy._setInner(this);");
|
212 |
| |
213 |
995
| body.end();
|
214 |
| |
215 |
995
| classFab.addConstructor(new Class[]
|
216 |
| { deferredProxyClass, getClass() }, null, body.toString()); |
217 |
| |
218 |
| |
219 |
| |
220 |
| |
221 |
| |
222 |
995
| body.clear();
|
223 |
995
| body.begin();
|
224 |
| |
225 |
995
| body.add("if (_service == null)");
|
226 |
995
| body.begin();
|
227 |
| |
228 |
995
| body.add("_service = (");
|
229 |
995
| body.add(serviceInterface.getName());
|
230 |
995
| body.addln(") _serviceModel.getActualServiceImplementation();");
|
231 |
| |
232 |
995
| body.add("_deferredProxy._setInner(_service);");
|
233 |
| |
234 |
995
| body.end();
|
235 |
| |
236 |
995
| body.add("return _service;");
|
237 |
| |
238 |
995
| body.end();
|
239 |
| |
240 |
995
| classFab.addMethod(
|
241 |
| Modifier.PRIVATE | Modifier.FINAL | Modifier.SYNCHRONIZED, |
242 |
| new MethodSignature(serviceInterface, "_service", null, null), |
243 |
| body.toString()); |
244 |
| |
245 |
995
| builder.addServiceMethods("_service()");
|
246 |
| |
247 |
| |
248 |
| |
249 |
995
| body.clear();
|
250 |
995
| body.begin();
|
251 |
| |
252 |
995
| body.add("_service();");
|
253 |
| |
254 |
995
| body.end();
|
255 |
| |
256 |
995
| classFab.addMethod(Modifier.PUBLIC | Modifier.FINAL, new MethodSignature(void.class,
|
257 |
| "_instantiateServiceImplementation", null, null), body.toString()); |
258 |
| |
259 |
995
| classFab.addInterface(SingletonInnerProxy.class);
|
260 |
| |
261 |
995
| return classFab.createClass();
|
262 |
| } |
263 |
| |
264 |
1
| public void instantiateService()
|
265 |
| { |
266 |
| |
267 |
| |
268 |
1
| getService();
|
269 |
| |
270 |
| |
271 |
| |
272 |
| |
273 |
1
| _innerProxy._instantiateServiceImplementation();
|
274 |
| } |
275 |
| |
276 |
| } |