/*
* Copyright (C) 2011 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.errai.ioc.client;
import java.util.ArrayList;
import java.util.List;
import org.jboss.errai.ioc.client.container.BeanManagerSetup;
import org.jboss.errai.ioc.client.container.ContextManager;
import org.jboss.errai.ioc.client.container.ErraiUncaughtExceptionHandler;
import org.jboss.errai.ioc.client.container.IOC;
import org.jboss.errai.ioc.client.container.IOCEnvironment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
public class Container implements EntryPoint {
private static final Logger logger = LoggerFactory.getLogger(Container.class);
@Override
public void onModuleLoad() {
bootstrapContainer();
}
private void setUncaughtExceptionHandler() {
final UncaughtExceptionHandler replacedHandler = GWT.getUncaughtExceptionHandler();
GWT.setUncaughtExceptionHandler(new ErraiUncaughtExceptionHandler(replacedHandler));
}
public void bootstrapContainer() {
setUncaughtExceptionHandler();
logger.info("Starting to bootstrap IOC container...");
final long bootstrapStart = System.currentTimeMillis();
try {
init = false;
logger.debug("Initializing {}...", QualifierEqualityFactory.class.getSimpleName());
long start = System.currentTimeMillis();
QualifierUtil.initFromFactoryProvider(() -> GWT.create(QualifierEqualityFactory.class));
logger.debug("{} initialized in {}ms", QualifierEqualityFactory.class.getSimpleName(), System.currentTimeMillis() - start);
final BeanManagerSetup beanManager;
if (GWT.<IOCEnvironment>create(IOCEnvironment.class).isAsync()) {
logger.info("Bean manager initialized in async mode.");
beanManager = (BeanManagerSetup) IOC.getAsyncBeanManager();
} else {
beanManager = (BeanManagerSetup) IOC.getBeanManager();
}
logger.debug("Creating new {} instance...", Bootstrapper.class.getSimpleName());
start = System.currentTimeMillis();
final Bootstrapper bootstrapper = GWT.create(Bootstrapper.class);
logger.debug("Created {} instance in {}ms", Bootstrapper.class.getSimpleName(), System.currentTimeMillis() - start);
logger.debug("Creating new {} instance...", ContextManager.class.getSimpleName());
start = System.currentTimeMillis();
final ContextManager contextManager = bootstrapper.bootstrapContainer();
logger.debug("Created {} instance in {}ms", ContextManager.class.getSimpleName(), System.currentTimeMillis() - start);
logger.debug("Initializing bean manager...");
start = System.currentTimeMillis();
beanManager.setContextManager(contextManager);
logger.debug("Bean manager initialized in {}ms", System.currentTimeMillis() - start);
logger.debug("Running post initialization runnables...");
start = System.currentTimeMillis();
init = true;
for (final Runnable run : afterInit) {
run.run();
}
afterInit.clear();
logger.debug("All post initialization runnables finished in {}ms", System.currentTimeMillis() - start);
logger.info("IOC bootstrapper successfully initialized in {}ms", System.currentTimeMillis() - bootstrapStart);
}
catch (final RuntimeException ex) {
logger.error("Critical error in IOC container bootstrap.", ex);
throw ex;
}
}
private static final List<Runnable> afterInit = new ArrayList<>();
private static boolean init = false;
/**
* Runs the specified {@link Runnable} only after the bean manager has fully initialized. It is generally not
* necessary to use this method from within beans themselves. But if you are generated out-of-container calls
* into the bean manager (such as for testing), it may be necessary to use this method to ensure that the beans
* you wish to lookup have been loaded.
* <p/>
* Use of this method is really only necessary when using the bean manager in asynchronous mode as wiring of the
* container synchronously does not yield during bootstrapping operations.
* <p/>
* If the bean manager is already initialized when you call this method, the <tt>Runnable</tt> is invoked immediately.
*
* @param runnable
* the {@link Runnable} to execute after bean manager initialization.
*/
public static void runAfterInit(final Runnable runnable) {
if (init) {
runnable.run();
} else {
afterInit.add(runnable);
}
}
/**
* Short-alias method for {@link #runAfterInit(Runnable)}.
*
* @param runnable
*/
public static void $(final Runnable runnable) {
runAfterInit(runnable);
}
public static void reset() {
init = false;
afterInit.clear();
}
}