|
|||||||||||||||||||
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover | |||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
ServicePointImpl.java | 90% | 97.4% | 100% | 96.2% |
|
1 |
// Copyright 2004, 2005 The Apache Software Foundation
|
|
2 |
//
|
|
3 |
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4 |
// you may not use this file except in compliance with the License.
|
|
5 |
// You may obtain a copy of the License at
|
|
6 |
//
|
|
7 |
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8 |
//
|
|
9 |
// Unless required by applicable law or agreed to in writing, software
|
|
10 |
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11 |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12 |
// See the License for the specific language governing permissions and
|
|
13 |
// limitations under the License.
|
|
14 |
|
|
15 |
package org.apache.hivemind.impl;
|
|
16 |
|
|
17 |
import java.util.ArrayList;
|
|
18 |
import java.util.Iterator;
|
|
19 |
import java.util.List;
|
|
20 |
|
|
21 |
import org.apache.commons.logging.Log;
|
|
22 |
import org.apache.commons.logging.LogFactory;
|
|
23 |
import org.apache.hivemind.ApplicationRuntimeException;
|
|
24 |
import org.apache.hivemind.HiveMind;
|
|
25 |
import org.apache.hivemind.Occurances;
|
|
26 |
import org.apache.hivemind.ShutdownCoordinator;
|
|
27 |
import org.apache.hivemind.internal.ServiceImplementationConstructor;
|
|
28 |
import org.apache.hivemind.internal.ServiceInterceptorContribution;
|
|
29 |
import org.apache.hivemind.internal.ServiceModel;
|
|
30 |
import org.apache.hivemind.internal.ServiceModelFactory;
|
|
31 |
import org.apache.hivemind.order.Orderer;
|
|
32 |
import org.apache.hivemind.schema.Schema;
|
|
33 |
import org.apache.hivemind.service.InterfaceSynthesizer;
|
|
34 |
import org.apache.hivemind.util.ToStringBuilder;
|
|
35 |
|
|
36 |
/**
|
|
37 |
* Abstract implementation of {@link org.apache.hivemind.internal.ServicePoint}. Provides some of
|
|
38 |
* the machinery for creating new service instances, delegating most of it to the
|
|
39 |
* {@link org.apache.hivemind.internal.ServiceModel}instace for the service.
|
|
40 |
*
|
|
41 |
* @author Howard Lewis Ship
|
|
42 |
*/
|
|
43 |
public final class ServicePointImpl extends AbstractExtensionPoint implements |
|
44 |
ConstructableServicePoint |
|
45 |
{ |
|
46 |
private Object _service;
|
|
47 |
|
|
48 |
private boolean _building; |
|
49 |
|
|
50 |
private String _serviceInterfaceName;
|
|
51 |
|
|
52 |
private Class _serviceInterface;
|
|
53 |
|
|
54 |
private Class _declaredInterface;
|
|
55 |
|
|
56 |
private ServiceImplementationConstructor _defaultServiceConstructor;
|
|
57 |
|
|
58 |
private ServiceImplementationConstructor _serviceConstructor;
|
|
59 |
|
|
60 |
private List _interceptorContributions;
|
|
61 |
|
|
62 |
private boolean _interceptorsOrdered; |
|
63 |
|
|
64 |
private Schema _parametersSchema;
|
|
65 |
|
|
66 |
private Occurances _parametersCount;
|
|
67 |
|
|
68 |
private String _serviceModel;
|
|
69 |
|
|
70 |
private ShutdownCoordinator _shutdownCoordinator;
|
|
71 |
|
|
72 |
private ServiceModel _serviceModelObject;
|
|
73 |
|
|
74 | 1 |
protected void extendDescription(ToStringBuilder builder) |
75 |
{ |
|
76 | 1 |
if (_service != null) |
77 | 0 |
builder.append("service", _service);
|
78 |
|
|
79 | 1 |
builder.append("serviceInterfaceName", _serviceInterfaceName);
|
80 | 1 |
builder.append("defaultServiceConstructor", _defaultServiceConstructor);
|
81 | 1 |
builder.append("serviceConstructor", _serviceConstructor);
|
82 | 1 |
builder.append("interceptorContributions", _interceptorContributions);
|
83 | 1 |
builder.append("parametersSchema", _parametersSchema);
|
84 | 1 |
builder.append("parametersCount", _parametersCount);
|
85 | 1 |
builder.append("serviceModel", _serviceModel);
|
86 |
|
|
87 | 1 |
if (_building)
|
88 | 0 |
builder.append("building", _building);
|
89 |
} |
|
90 |
|
|
91 | 30 |
public void addInterceptorContribution(ServiceInterceptorContribution contribution) |
92 |
{ |
|
93 | 30 |
if (_interceptorContributions == null) |
94 | 28 |
_interceptorContributions = new ArrayList();
|
95 |
|
|
96 | 30 |
_interceptorContributions.add(contribution); |
97 |
} |
|
98 |
|
|
99 | 4896 |
public synchronized Class getServiceInterface() |
100 |
{ |
|
101 | 4896 |
if (_serviceInterface == null) |
102 | 1242 |
_serviceInterface = lookupServiceInterface(); |
103 |
|
|
104 | 4895 |
return _serviceInterface;
|
105 |
} |
|
106 |
|
|
107 | 3871 |
public synchronized Class getDeclaredInterface() |
108 |
{ |
|
109 | 3871 |
if (_declaredInterface == null) |
110 | 1242 |
_declaredInterface = lookupDeclaredInterface(); |
111 |
|
|
112 | 3870 |
return _declaredInterface;
|
113 |
} |
|
114 |
|
|
115 |
/** @since 1.1 */
|
|
116 |
|
|
117 | 2182 |
public String getServiceInterfaceClassName()
|
118 |
{ |
|
119 | 2182 |
return _serviceInterfaceName;
|
120 |
} |
|
121 |
|
|
122 | 1242 |
private Class lookupDeclaredInterface()
|
123 |
{ |
|
124 | 1242 |
Class result = null;
|
125 |
|
|
126 | 1242 |
try
|
127 |
{ |
|
128 | 1242 |
result = getModule().resolveType(_serviceInterfaceName); |
129 |
} |
|
130 |
catch (Exception ex)
|
|
131 |
{ |
|
132 | 1 |
throw new ApplicationRuntimeException(ImplMessages.badInterface( |
133 |
_serviceInterfaceName, |
|
134 |
getExtensionPointId()), getLocation(), ex); |
|
135 |
} |
|
136 |
|
|
137 | 1241 |
return result;
|
138 |
} |
|
139 |
|
|
140 | 1242 |
private Class lookupServiceInterface()
|
141 |
{ |
|
142 | 1242 |
Class declaredInterface = getDeclaredInterface(); |
143 |
|
|
144 | 1241 |
if (declaredInterface.isInterface())
|
145 | 1237 |
return declaredInterface;
|
146 |
|
|
147 |
// Not an interface ... a class. Synthesize an interface from the class itself.
|
|
148 |
|
|
149 | 4 |
InterfaceSynthesizer is = (InterfaceSynthesizer) getModule().getService( |
150 |
HiveMind.INTERFACE_SYNTHESIZER_SERVICE, |
|
151 |
InterfaceSynthesizer.class);
|
|
152 |
|
|
153 | 4 |
return is.synthesizeInterface(declaredInterface);
|
154 |
} |
|
155 |
|
|
156 | 2180 |
public void setServiceConstructor(ServiceImplementationConstructor contribution, |
157 |
boolean defaultConstructor)
|
|
158 |
{ |
|
159 | 2180 |
if (defaultConstructor)
|
160 | 2179 |
_defaultServiceConstructor = contribution; |
161 |
else
|
|
162 | 1 |
_serviceConstructor = contribution; |
163 |
} |
|
164 |
|
|
165 | 2184 |
public void setServiceInterfaceName(String string) |
166 |
{ |
|
167 | 2184 |
_serviceInterfaceName = string; |
168 |
} |
|
169 |
|
|
170 | 2182 |
public void setParametersSchema(Schema schema) |
171 |
{ |
|
172 | 2182 |
_parametersSchema = schema; |
173 |
} |
|
174 |
|
|
175 | 436 |
public Schema getParametersSchema()
|
176 |
{ |
|
177 | 436 |
return _parametersSchema;
|
178 |
} |
|
179 |
|
|
180 | 2180 |
public ServiceImplementationConstructor getServiceConstructor(boolean defaultConstructor) |
181 |
{ |
|
182 | 2180 |
return defaultConstructor ? _defaultServiceConstructor : _serviceConstructor;
|
183 |
} |
|
184 |
|
|
185 |
/**
|
|
186 |
* Invoked by {@link #getService(Class)}to get a service implementation from the
|
|
187 |
* {@link ServiceModel}.
|
|
188 |
* <p>
|
|
189 |
* TODO: I'm concerned that this synchronized method could cause a deadlock. It would take a LOT
|
|
190 |
* (mutually dependent services in multiple threads being realized at the same time).
|
|
191 |
*/
|
|
192 | 3417 |
private synchronized Object getService() |
193 |
{ |
|
194 | 3417 |
if (_service == null) |
195 |
{ |
|
196 |
|
|
197 | 1240 |
if (_building)
|
198 | 1 |
throw new ApplicationRuntimeException(ImplMessages.recursiveServiceBuild(this)); |
199 |
|
|
200 | 1239 |
_building = true;
|
201 |
|
|
202 | 1239 |
try
|
203 |
{ |
|
204 |
|
|
205 | 1239 |
ServiceModelFactory factory = getModule().getServiceModelFactory(getServiceModel()); |
206 |
|
|
207 | 1239 |
_serviceModelObject = factory.createServiceModelForService(this);
|
208 |
|
|
209 | 1239 |
_service = _serviceModelObject.getService(); |
210 |
} |
|
211 |
finally
|
|
212 |
{ |
|
213 | 1239 |
_building = false;
|
214 |
} |
|
215 |
} |
|
216 |
|
|
217 | 3413 |
return _service;
|
218 |
} |
|
219 |
|
|
220 | 3413 |
public Object getService(Class serviceInterface)
|
221 |
{ |
|
222 | 3413 |
Object result = getService(); |
223 |
|
|
224 | 3409 |
if (!serviceInterface.isAssignableFrom(result.getClass()))
|
225 |
{ |
|
226 | 1 |
throw new ApplicationRuntimeException(ImplMessages.serviceWrongInterface( |
227 |
this,
|
|
228 |
serviceInterface), getLocation(), null);
|
|
229 |
} |
|
230 |
|
|
231 | 3408 |
return result;
|
232 |
} |
|
233 |
|
|
234 | 1239 |
public String getServiceModel()
|
235 |
{ |
|
236 | 1239 |
return _serviceModel;
|
237 |
} |
|
238 |
|
|
239 | 2181 |
public void setServiceModel(String model) |
240 |
{ |
|
241 | 2181 |
_serviceModel = model; |
242 |
} |
|
243 |
|
|
244 | 768 |
public void clearConstructorInformation() |
245 |
{ |
|
246 | 768 |
_serviceConstructor = null;
|
247 | 768 |
_interceptorContributions = null;
|
248 |
} |
|
249 |
|
|
250 |
// Hm. Does this need to be synchronized?
|
|
251 |
|
|
252 | 794 |
public List getOrderedInterceptorContributions()
|
253 |
{ |
|
254 | 794 |
if (!_interceptorsOrdered)
|
255 |
{ |
|
256 | 794 |
_interceptorContributions = orderInterceptors(); |
257 | 794 |
_interceptorsOrdered = true;
|
258 |
} |
|
259 |
|
|
260 | 794 |
return _interceptorContributions;
|
261 |
} |
|
262 |
|
|
263 | 794 |
private List orderInterceptors()
|
264 |
{ |
|
265 | 794 |
if (HiveMind.isEmpty(_interceptorContributions))
|
266 | 778 |
return null; |
267 |
|
|
268 |
// Any error logging should go to the extension point
|
|
269 |
// we're constructing.
|
|
270 |
|
|
271 | 16 |
Log log = LogFactory.getLog(getExtensionPointId()); |
272 |
|
|
273 | 16 |
Orderer orderer = new Orderer(log, getModule().getErrorHandler(), ImplMessages
|
274 |
.interceptorContribution()); |
|
275 |
|
|
276 | 16 |
Iterator i = _interceptorContributions.iterator(); |
277 | 16 |
while (i.hasNext())
|
278 |
{ |
|
279 | 18 |
ServiceInterceptorContribution sic = (ServiceInterceptorContribution) i.next(); |
280 |
|
|
281 |
// Sort them into runtime excecution order. When we build
|
|
282 |
// the interceptor stack we'll apply them in reverse order,
|
|
283 |
// building outward from the core service implementation.
|
|
284 |
|
|
285 | 18 |
orderer.add(sic, sic.getFactoryServiceId(), sic.getPrecedingInterceptorIds(), sic |
286 |
.getFollowingInterceptorIds()); |
|
287 |
} |
|
288 |
|
|
289 | 16 |
return orderer.getOrderedObjects();
|
290 |
} |
|
291 |
|
|
292 | 897 |
public ShutdownCoordinator getShutdownCoordinator()
|
293 |
{ |
|
294 | 897 |
return _shutdownCoordinator;
|
295 |
} |
|
296 |
|
|
297 | 2182 |
public void setShutdownCoordinator(ShutdownCoordinator coordinator) |
298 |
{ |
|
299 | 2182 |
_shutdownCoordinator = coordinator; |
300 |
} |
|
301 |
|
|
302 |
/**
|
|
303 |
* Forces the service into existence.
|
|
304 |
*/
|
|
305 | 4 |
public void forceServiceInstantiation() |
306 |
{ |
|
307 | 4 |
getService(); |
308 |
|
|
309 | 4 |
_serviceModelObject.instantiateService(); |
310 |
} |
|
311 |
|
|
312 | 421 |
public Occurances getParametersCount()
|
313 |
{ |
|
314 | 421 |
return _parametersCount;
|
315 |
} |
|
316 |
|
|
317 | 2182 |
public void setParametersCount(Occurances occurances) |
318 |
{ |
|
319 | 2182 |
_parametersCount = occurances; |
320 |
} |
|
321 |
|
|
322 |
/**
|
|
323 |
* Returns the service constructor, if defined, or the default service constructor. The default
|
|
324 |
* service constructor comes from the <service-point> itself; other modules can override
|
|
325 |
* this default using an <implementation> element.
|
|
326 |
*/
|
|
327 |
|
|
328 | 3013 |
public ServiceImplementationConstructor getServiceConstructor()
|
329 |
{ |
|
330 | 3013 |
return _serviceConstructor == null ? _defaultServiceConstructor : _serviceConstructor; |
331 |
} |
|
332 |
} |
|