/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.isis.core.webapp;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.isis.core.commons.config.IsisConfigurationDefault;
import org.apache.isis.core.commons.config.NotFoundPolicy;
import org.apache.isis.core.commons.configbuilder.IsisConfigurationBuilder;
import org.apache.isis.core.commons.resource.ResourceStreamSourceContextLoaderClassPath;
import org.apache.isis.core.commons.resource.ResourceStreamSourceCurrentClassClassPath;
import org.apache.isis.core.commons.resource.ResourceStreamSourceFileSystem;
import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
import org.apache.isis.core.runtime.logging.IsisLoggingConfigurer;
import org.apache.isis.core.runtime.runner.IsisInjectModule;
import org.apache.isis.core.runtime.runner.opts.OptionHandlerInitParameters;
import org.apache.isis.core.runtime.system.DeploymentType;
import org.apache.isis.core.runtime.system.SystemConstants;
import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
import org.apache.isis.core.runtime.system.session.IsisSessionFactoryBuilder;
import org.apache.isis.core.webapp.config.ResourceStreamSourceForWebInf;
/**
* Initialize the {@link IsisSessionFactoryBuilder} when the web application starts, and
* destroys it when it ends.
* <p>
* Implementation note: we use a number of helper builders to keep this class as
* small and focused as possible. The builders are available for reuse by other
* bootstrappers.
*/
public class IsisWebAppBootstrapper implements ServletContextListener {
private static final Logger LOG = LoggerFactory.getLogger(IsisWebAppBootstrapper.class);
private final IsisLoggingConfigurer loggingConfigurer = new IsisLoggingConfigurer();
@com.google.inject.Inject
private IsisSessionFactory isisSessionFactory;
/**
* Convenience for servlets that need to obtain the {@link IsisSessionFactoryBuilder}.
*/
public static IsisSessionFactoryBuilder getSystemBoundTo(final ServletContext servletContext) {
final Object system = servletContext.getAttribute(WebAppConstants.ISIS_SESSION_FACTORY);
return (IsisSessionFactoryBuilder) system;
}
// /////////////////////////////////////////////////////
// Initialization
// /////////////////////////////////////////////////////
@Override
public void contextInitialized(final ServletContextEvent servletContextEvent) {
try {
final ServletContext servletContext = servletContextEvent.getServletContext();
final String webInfDir = servletContext.getRealPath("/WEB-INF");
loggingConfigurer.configureLogging(webInfDir, new String[0]);
final IsisConfigurationBuilder isisConfigurationBuilder = obtainIsisConfigurationBuilder(servletContext);
isisConfigurationBuilder.addDefaultConfigurationResourcesAndPrimers();
final DeploymentType deploymentType = determineDeploymentType(servletContext, isisConfigurationBuilder);
addConfigurationResourcesForDeploymentType(isisConfigurationBuilder, deploymentType);
final String webappDir = servletContext.getRealPath("/");
isisConfigurationBuilder.add(WebAppConstants.WEB_APP_DIR, webappDir);
final IsisConfigurationDefault isisConfiguration = isisConfigurationBuilder.getConfiguration();
final DeploymentCategory deploymentCategory = deploymentType.getDeploymentCategory();
final IsisInjectModule isisModule = new IsisInjectModule(deploymentCategory, isisConfiguration);
final Injector injector = Guice.createInjector(isisModule);
injector.injectMembers(this);
servletContext.setAttribute(WebAppConstants.ISIS_SESSION_FACTORY, isisSessionFactory);
} catch (final RuntimeException e) {
LOG.error("startup failed", e);
throw e;
}
LOG.info("server started");
}
protected IsisConfigurationBuilder obtainIsisConfigurationBuilder(final ServletContext servletContext) {
return obtainConfigBuilderFrom(servletContext);
}
/**
* publis so can also be used by Wicket viewer.
*/
public static IsisConfigurationBuilder obtainConfigBuilderFrom(final ServletContext servletContext) {
final IsisConfigurationBuilder isisConfigurationBuilder = lookupIsisConfigurationBuilder(servletContext);
isisConfigurationBuilder.primeWith(new OptionHandlerInitParameters(servletContext));
addResourceStreamSources(servletContext, isisConfigurationBuilder);
return isisConfigurationBuilder;
}
public static IsisConfigurationBuilder lookupIsisConfigurationBuilder(final ServletContext servletContext) {
IsisConfigurationBuilder isisConfigurationBuilder =
(IsisConfigurationBuilder) servletContext.getAttribute(WebAppConstants.CONFIGURATION_BUILDER_KEY);
if(isisConfigurationBuilder == null) {
isisConfigurationBuilder = new IsisConfigurationBuilder();
}
return isisConfigurationBuilder;
}
private static void addResourceStreamSources(
final ServletContext servletContext,
final IsisConfigurationBuilder isisConfigurationBuilder) {
// will load either from WEB-INF, from the classpath or from config directory.
final String configLocation = servletContext.getInitParameter(WebAppConstants.CONFIG_DIR_PARAM);
if ( configLocation != null ) {
LOG.info( "Config override location: " + configLocation );
isisConfigurationBuilder.addResourceStreamSource(ResourceStreamSourceFileSystem.create(configLocation));
} else {
LOG.info( "Config override location: No override location configured" );
isisConfigurationBuilder.addResourceStreamSource(ResourceStreamSourceContextLoaderClassPath.create());
isisConfigurationBuilder.addResourceStreamSource(new ResourceStreamSourceCurrentClassClassPath());
isisConfigurationBuilder.addResourceStreamSource(new ResourceStreamSourceForWebInf(servletContext));
}
}
private Injector createGuiceInjector(
final IsisConfigurationDefault isisConfiguration,
final DeploymentCategory deploymentCategory) {
final IsisInjectModule isisModule = new IsisInjectModule(deploymentCategory, isisConfiguration);
return Guice.createInjector(isisModule);
}
/**
* Checks {@link IsisConfigurationBuilder configuration} for
* {@value SystemConstants#DEPLOYMENT_TYPE_KEY}, (that is, from the command
* line), but otherwise searches in the {@link ServletContext}, first for
* {@value WebAppConstants#DEPLOYMENT_TYPE_KEY} and also
* {@value SystemConstants#DEPLOYMENT_TYPE_KEY}.
* <p>
* If no setting is found, defaults to {@link WebAppConstants#DEPLOYMENT_TYPE_DEFAULT}.
*/
protected DeploymentType determineDeploymentType(
final ServletContext servletContext,
final IsisConfigurationBuilder isisConfigurationBuilder) {
String deploymentTypeStr = determineDeploymentTypeStr(servletContext, isisConfigurationBuilder);
return DeploymentType.lookup(deploymentTypeStr);
}
private String determineDeploymentTypeStr(
final ServletContext servletContext,
final IsisConfigurationBuilder isisConfigurationBuilder) {
String deploymentTypeStr;
deploymentTypeStr = servletContext.getInitParameter(WebAppConstants.DEPLOYMENT_TYPE_KEY);
if (deploymentTypeStr != null) {
return deploymentTypeStr;
}
deploymentTypeStr = servletContext.getInitParameter(SystemConstants.DEPLOYMENT_TYPE_KEY);
if (deploymentTypeStr != null) {
return deploymentTypeStr;
}
deploymentTypeStr = isisConfigurationBuilder.peekConfiguration().getString(SystemConstants.DEPLOYMENT_TYPE_KEY);
if (deploymentTypeStr != null) {
return deploymentTypeStr;
}
return WebAppConstants.DEPLOYMENT_TYPE_DEFAULT;
}
protected void addConfigurationResourcesForDeploymentType(
final IsisConfigurationBuilder isisConfigurationBuilder,
final DeploymentType deploymentType) {
final String resourceName = deploymentType.name().toLowerCase() + ".properties";
isisConfigurationBuilder.addConfigurationResource(resourceName, NotFoundPolicy.CONTINUE, IsisConfigurationDefault.ContainsPolicy.IGNORE);
}
// /////////////////////////////////////////////////////
// Destroy
// /////////////////////////////////////////////////////
@Override
public void contextDestroyed(final ServletContextEvent ev) {
LOG.info("server shutting down");
final ServletContext servletContext = ev.getServletContext();
try {
final IsisSessionFactory isisSessionFactory = (IsisSessionFactory) servletContext.getAttribute(WebAppConstants.ISIS_SESSION_FACTORY);
if (isisSessionFactory != null) {
LOG.info("calling system shutdown");
isisSessionFactory.destroyServicesAndShutdown();
}
} finally {
servletContext.removeAttribute(WebAppConstants.ISIS_SESSION_FACTORY);
LOG.info("server shut down");
}
}
}