/*******************************************************************************
* Copyright (c) 2012-2016 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.everrest.core.servlet;
import org.everrest.core.DependencySupplier;
import org.everrest.core.Filter;
import org.everrest.core.RequestHandler;
import org.everrest.core.ResourceBinder;
import org.everrest.core.impl.ApplicationProviderBinder;
import org.everrest.core.impl.EverrestApplication;
import org.everrest.core.impl.EverrestConfiguration;
import org.everrest.core.impl.EverrestProcessor;
import org.everrest.core.impl.ProviderBinder;
import org.everrest.core.impl.RequestDispatcher;
import org.everrest.core.impl.RequestHandlerImpl;
import org.everrest.core.impl.ResourceBinderImpl;
import org.everrest.core.impl.async.AsynchronousJobPool;
import org.everrest.core.impl.async.AsynchronousJobService;
import org.everrest.core.impl.async.AsynchronousProcessListWriter;
import org.everrest.core.impl.method.filter.SecurityConstraint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletContext;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import javax.ws.rs.ext.Provider;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/** @author andrew00x */
public class EverrestServletContextInitializer {
private static final Logger LOG = LoggerFactory.getLogger(EverrestServletContextInitializer.class);
public static final String EVERREST_SCAN_COMPONENTS = "org.everrest.scan.components";
public static final String EVERREST_SCAN_SKIP_PACKAGES = "org.everrest.scan.skip.packages";
public static final String JAXRS_APPLICATION = "javax.ws.rs.Application";
protected final ServletContext servletContext;
public EverrestServletContextInitializer(ServletContext servletContext) {
this.servletContext = servletContext;
}
/**
* Try get application's FQN from context-param javax.ws.rs.Application and instantiate it. If such parameter is not
* specified then scan web application's folders WEB-INF/classes and WEB-INF/lib for classes which contains JAX-RS
* annotations. Interesting for three annotations {@link Path}, {@link Provider} and {@link Filter} .
*
* @return instance of javax.ws.rs.core.Application
*/
public Application getApplication() {
Application application = null;
String applicationFQN = getParameter(JAXRS_APPLICATION);
boolean scan = getBoolean(EVERREST_SCAN_COMPONENTS, false);
if (applicationFQN != null) {
if (scan) {
String msg = "Scan of JAX-RS components is disabled cause to specified 'javax.ws.rs.Application'.";
LOG.warn(msg);
}
try {
Class<?> cl = Thread.currentThread().getContextClassLoader().loadClass(applicationFQN);
application = (Application)cl.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
} else if (scan) {
application = new Application() {
@Override
public Set<Class<?>> getClasses() {
return new LinkedHashSet<>(ComponentFinder.findComponents());
}
};
}
return application;
}
public EverrestConfiguration createConfiguration() {
EverrestConfiguration config = new EverrestConfiguration();
for (String parameterName : getParameterNames()) {
config.setProperty(parameterName, getParameter(parameterName));
}
return config;
}
public RequestHandler createRequestHandler() {
return new RequestHandlerImpl(createRequestDispatcher(), createProviderBinder());
}
public RequestDispatcher createRequestDispatcher() {
return new RequestDispatcher(createResourceBinder());
}
public ResourceBinder createResourceBinder() {
return new ResourceBinderImpl();
}
public DependencySupplier getDependencySupplier() {
DependencySupplier dependencySupplier = (DependencySupplier)servletContext.getAttribute(DependencySupplier.class.getName());
if (dependencySupplier == null) {
dependencySupplier = new ServletContextDependencySupplier(servletContext);
}
return dependencySupplier;
}
public ProviderBinder createProviderBinder() {
return new ApplicationProviderBinder();
}
private EverrestApplication getEverrestApplication(EverrestConfiguration configuration) {
EverrestApplication everrest = new EverrestApplication();
if (configuration.isAsynchronousSupported()) {
everrest.addResource(configuration.getAsynchronousServicePath(), AsynchronousJobService.class);
everrest.addSingleton(new AsynchronousJobPool(configuration));
everrest.addSingleton(new AsynchronousProcessListWriter());
}
if (configuration.isCheckSecurity()) {
everrest.addSingleton(new SecurityConstraint());
}
everrest.addApplication(getApplication());
return everrest;
}
public EverrestProcessor createEverrestProcessor() {
EverrestConfiguration configuration = createConfiguration();
return new EverrestProcessor(configuration,
getDependencySupplier(),
createRequestHandler(),
getEverrestApplication(configuration));
}
protected List<String> getParameterNames() {
return Collections.list(servletContext.getInitParameterNames());
}
/**
* Get parameter with specified name from servlet context initial parameters.
*
* @param name
* parameter name
* @return value of parameter with specified name
*/
protected String getParameter(String name) {
String str = servletContext.getInitParameter(name);
if (str != null) {
return str.trim();
}
return null;
}
protected String getParameter(String name, String def) {
String value = getParameter(name);
if (value == null) {
return def;
}
return value;
}
protected boolean getBoolean(String name, boolean def) {
String str = getParameter(name);
if (str != null) {
return "true".equalsIgnoreCase(str) || "yes".equalsIgnoreCase(str) || "on".equalsIgnoreCase(str) || "1".equals(str);
}
return def;
}
protected Double getNumber(String name, double def) {
String str = getParameter(name);
if (str != null) {
try {
return Double.parseDouble(str);
} catch (NumberFormatException ignored) {
}
}
return def;
}
}