/**
* Injects the requested dependencies into the parameter object. It scans
* the serviceable object looking for methods tagged with the
* {@link Injected} annotation.Parameter types are extracted from the
* matching method. An instance of each type is created from the registered
* factories (see {@link IServiceFactory}). When instances for all the
* parameter types have been created the method is invoked and the next one
* is examined.
*
* @param serviceable
* the object to be serviced
* @throws ServiceException
*/
public static void service(Object serviceable) throws ServiceException {
ServiceLocator sl = getInstance();
if (sl.isAlreadyServiced(serviceable)) {
// prevent multiple initializations due to
// constructor hierarchies
System.out.println("Object " + serviceable
+ " has already been configured ");
return;
}
System.out.println("Configuring " + serviceable);
// Parse the class for the requested services
for (Method m : serviceable.getClass().getMethods()) {
boolean skip = false;
Injected ann = m.getAnnotation(Injected.class);
if (ann != null) {
Object[] services = new Object[m.getParameterTypes().length];
int i = 0;
for (Class<?> class : m.getParameterTypes()) {
IServiceFactory factory = sl.getFactory(class, ann
.optional());
if (factory == null) {
skip = true;
break;
}
Object service = factory.getServiceInstance();
// sanity check: verify that the returned
// service's class is the expected one
// from the method
assert (service.getClass().equals(class) || class
.isAssignableFrom(service.getClass()));
services[i++] = service;
}
try {
if (!skip)
m.invoke(serviceable, services);
} catch (IllegalAccessException iae) {
if (!ann.optional())
throw new ServiceException(
"Unable to initialize services on "
+ serviceable + ": " + iae.getMessage(), iae);
} catch (InvocationTargetException ite) {
if (!ann.optional())
throw new ServiceException(
"Unable to initialize services on "
+ serviceable + ": " + ite.getMessage(), ite);
}
}
}
sl.setAsServiced(serviceable);
}