{
private Logger log = LoggerFactory.getLogger(DiscoverServices.class);
public void execute(final BootstrapContext context)
{
final ErraiServiceConfiguratorImpl config = (ErraiServiceConfiguratorImpl)context.getConfig();
boolean autoScanModules = true;
final Set<String> loadedComponents = new HashSet<String>();
/*** Extensions ***/
if (config.hasProperty("errai.auto_discover_services")) {
autoScanModules = Boolean.parseBoolean(config.getProperty("errai.auto_discover_services"));
}
if (autoScanModules) {
log.info("beging searching for services ...");
List<File> configRootTargets = ConfigUtil.findAllConfigTargets();
visitAllTargets(configRootTargets,
new ConfigVisitor() {
public void visit(final Class<?> loadClass) {
if (loadedComponents.contains(loadClass.getName())) return;
if (Module.class.isAssignableFrom(loadClass)) {
final Class<? extends Module> clazz = loadClass.asSubclass(Module.class);
loadedComponents.add(loadClass.getName());
if (clazz.isAnnotationPresent(LoadModule.class)) {
log.info("discovered module : " + clazz.getName() + " -- don't use Modules! Use @Service and MessageCallback!");
Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(Module.class).to(clazz);
bind(MessageBus.class).toInstance(context.getBus());
}
}).getInstance(Module.class).init();
}
} else if (loadClass.isAnnotationPresent(Service.class)) {
Object svc = null;
Class remoteImpl = getRemoteImplementation(loadClass);
if (remoteImpl != null) {
createRPCScaffolding(remoteImpl, loadClass, context);
} else if (MessageCallback.class.isAssignableFrom(loadClass)) {
final Class<? extends MessageCallback> clazz = loadClass.asSubclass(MessageCallback.class);
loadedComponents.add(loadClass.getName());
log.info("discovered service: " + clazz.getName());
try {
svc = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(MessageCallback.class).to(clazz);
bind(MessageBus.class).toInstance(context.getBus());
bind(RequestDispatcher.class).toInstance(context.getService().getDispatcher());
// Add any extension bindings.
for (Map.Entry<Class<?>, ResourceProvider> entry : config.getExtensionBindings().entrySet()) {
bind(entry.getKey()).toProvider(new GuiceProviderProxy(entry.getValue()));
}
}
}).getInstance(MessageCallback.class);
}
catch (Throwable t) {
t.printStackTrace();
}
String svcName = clazz.getAnnotation(Service.class).value();
// If no name is specified, just use the class name as the service
// by default.
if ("".equals(svcName)) {
svcName = clazz.getSimpleName();
}
// Subscribe the service to the bus.
context.getBus().subscribe(svcName, (MessageCallback) svc);
RolesRequiredRule rule = null;
if (clazz.isAnnotationPresent(RequireRoles.class)) {
rule = new RolesRequiredRule(clazz.getAnnotation(RequireRoles.class).value(), context.getBus());
} else if (clazz.isAnnotationPresent(RequireAuthentication.class)) {
rule = new RolesRequiredRule(new HashSet<Object>(), context.getBus());
}
if (rule != null) {
context.getBus().addRule(svcName, rule);
}
}
if (svc == null) {
svc = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(MessageBus.class).toInstance(context.getBus());
bind(RequestDispatcher.class).toInstance(context.getService().getDispatcher());
// Add any extension bindings.
for (Map.Entry<Class<?>, ResourceProvider> entry : config.getExtensionBindings().entrySet()) {
bind(entry.getKey()).toProvider(new GuiceProviderProxy(entry.getValue()));
}
}
}).getInstance(loadClass);
}
Map<String, MessageCallback> epts = new HashMap<String, MessageCallback>();
// we scan for endpoints
for (final Method method : loadClass.getDeclaredMethods()) {
if (method.isAnnotationPresent(Endpoint.class)) {
epts.put(method.getName(), method.getReturnType() == Void.class ?
new EndpointCallback(svc, method) :
new ConversationalEndpointCallback(svc, method, context.getBus()));
}
}
if (!epts.isEmpty()) {
context.getBus().subscribe(loadClass.getSimpleName() + ":RPC", new RemoteServiceCallback(epts));
}
} else if (loadClass.isAnnotationPresent(ExposeEntity.class)) {
log.info("Marked " + loadClass + " as serializable.");
loadedComponents.add(loadClass.getName());
config.getSerializableTypes().add(loadClass);
}
}
}
);
} else {
log.info("auto-discovery of services disabled.");
}
try {
ResourceBundle bundle = ResourceBundle.getBundle("ErraiApp");
if (bundle != null) {
log.info("checking ErraiApp.properties for configured types ...");
Enumeration<String> keys = bundle.getKeys();
while(keys.hasMoreElements())
{
String key = keys.nextElement();
if(key.equals(ErraiServiceConfigurator.CONFIG_ERRAI_SERIALIZABLE_TYPE))
{
for (String s : key.split(" ")) {
try {
Class<?> cls = Class.forName(s.trim());
log.info("Marked " + cls + " as serializable.");
loadedComponents.add(cls.getName());
config.getSerializableTypes().add(cls);
}
catch (Exception e) {
throw new ErraiBootstrapFailure(e);
}