/*
*
* Copyright 2014 McEvoy Software Ltd.
*
* 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 io.milton.context;
import java.io.Closeable;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RootContext extends Context implements Closeable {
private static final Logger log = LoggerFactory.getLogger(RootContext.class);
private final FactoryCatalog factoryCatalog;
public RootContext() {
factoryCatalog = new FactoryCatalog();
}
public RootContext(FactoryCatalog factoryCatalog) {
this(factoryCatalog, null);
}
public RootContext(FactoryCatalog factoryCatalog, List<Object> initialContents) {
if (factoryCatalog == null) {
throw new IllegalArgumentException("factoryCatalog cannot be null");
}
this.factoryCatalog = factoryCatalog;
put("configFile", factoryCatalog.getConfigFile());
try {
if (initialContents != null) {
for (Object o : initialContents) {
this.put(o);
}
}
for (Map.Entry<String, String> entry : factoryCatalog.keys.entrySet()) {
this.put(entry.getKey(), entry.getValue());
}
for (Factory f : factoryCatalog.factories) {
f.init(this);
}
} catch (Throwable e) {
log.error("Exception initializing the rootcontext. Forcing shutdown", e);
try {
this.shutdown();
} catch (Throwable e2) {
log.error("Failed to shutdown properly", e2);
}
throw new RuntimeException(e);
}
}
public void put(Object... beans) {
for (Object o : beans) {
put(o);
}
}
/**
* Execute without any return value
*/
public void execute(Executable2 exec) {
RequestContext.setCurrent(null);
RequestContext context = RequestContext.getInstance(this);
Registration reg = null;
try {
reg = context.put(exec, context); // the context is its own onRemove handler
exec.execute(context);
} catch (Throwable e) {
log.error("error executing: " + exec, e);
throw new RuntimeException(e);
} finally {
reg.remove();
context.tearDown();
RequestContext.setCurrent(null);
}
}
public <T> T execute(Executable<T> exec) {
RequestContext context = RequestContext.getInstance(this);
Registration reg = null;
try {
reg = context.put(exec, context); // the context is its own onRemove handler
T t = exec.execute(context);
return t;
} catch (Throwable e) {
throw new RuntimeException(e);
} finally {
reg.remove();
if (RequestContext.peekInstance() != null) {
throw new RuntimeException("Did not close down properly");
}
context.tearDown();
}
}
/**
* Throws an exception if returning null
*/
@Override
protected Registration getRegistration(Class c) throws IllegalArgumentException {
return getOrCreateRegistration(c, this);
}
@Override
protected Registration getRegistration(String id) {
return getOrCreateRegistration(id, this);
}
@Override
Registration getOrCreateRegistration(Class c, Context context) {
Registration reg = super.getRegistration(c);
if (reg != null) {
return reg;
}
Factory f = factoryCatalog.get(c);
if (f == null) {
return null;
}
reg = f.insert(this, context);
if (reg == null) {
throw new NullPointerException("factory " + f.getClass().getName() + " returned null reg");
}
return reg;
}
@Override
Registration getOrCreateRegistration(String id, Context context) {
Registration reg = super.getRegistration(id);
if (reg != null) {
return reg;
}
Factory f = factoryCatalog.get(id);
if (f == null) {
return null;
}
//if( f == null ) throw new IllegalArgumentException("No item of ID: " + id );
return f.insert(this, context);
}
public void shutdown() {
log.warn("shutdown");
Object[] items = itemByClass.values().toArray();
for (Object o : items) {
Registration r = (Registration) o;
try {
log.debug("remove: " + r.item.getClass());
r.remove();
} catch (Throwable e) {
log.error("Failed to do remove on registration: " + r);
}
}
for (Factory f : factoryCatalog.factories) {
log.warn("destroy: " + f.getClass());
try {
f.destroy();
} catch (Throwable e) {
log.error("Failed to do destroy on factory: " + f);
}
}
}
/**
* This weird little guy is to allow us to set this root context into a
* locator which was defined in spring config before this one.
*
* @param loc
*/
public void setRootContextLocator(RootContextLocator loc) {
loc.setRootContext(this);
}
/**
* Same as shutdown
*/
public void close() {
shutdown();
}
}