// Path: spring-multi-tenancy-core/src/main/java/biz/deinum/multitenant/context/TenantContext.java
// public interface TenantContext extends Serializable {
// 
// 
// 	/**
// 	 * Get the tenant
// 	 * @return the tenant
// 	 */
// 	String getTenant();
// 
// 	/**
// 	 * Set the tenant.
// 	 *
// 	 * @param tenant the tenant
// 	 */
// 	void setTenant(String tenant);
// }
// 
// Path: spring-multi-tenancy-core/src/main/java/biz/deinum/multitenant/context/TenantContextHolder.java
// public abstract class TenantContextHolder {
// 
// 	public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";
// 	public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";
// 	public static final String MODE_GLOBAL = "MODE_GLOBAL";
// 	public static final String SYSTEM_PROPERTY = "multi_tenant.strategy";
// 
// 	private static String strategyName = System.getProperty(SYSTEM_PROPERTY, MODE_THREADLOCAL);
// 
// 	private static TenantContextHolderStrategy strategy;
// 
// 	static {
// 		initialize();
// 	}
// 
// 	private static void initialize() {
// 		if ((strategyName == null) || "".equals(strategyName)) {
// 			// Set default
// 			strategyName = MODE_THREADLOCAL;
// 		}
// 
// 		if (strategyName.equals(MODE_THREADLOCAL)) {
// 			strategy = new ThreadLocalTenantContextHolderStrategy();
// 		}
// 		else if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) {
// 			strategy = new InheritableThreadLocalTenantContextHolderStrategy();
// 		}
// 		else if (strategyName.equals(MODE_GLOBAL)) {
// 			strategy = new GlobalTenantContextHolderStrategy();
// 		}
// 		else {
// 			// Try to load a custom strategy
// 			try {
// 				Class<?> clazz = Class.forName(strategyName);
// 				Constructor<?> customStrategy = clazz.getConstructor();
// 				strategy = (TenantContextHolderStrategy) customStrategy.newInstance();
// 			}
// 			catch (Exception ex) {
// 				ReflectionUtils.handleReflectionException(ex);
// 			}
// 		}
// 	}
// 
// 	public static TenantContext getContext() {
// 		TenantContext context = strategy.getContext();
// 		return context;
// 	}
// 
// 	public static void setContext(final TenantContext context) {
// 		strategy.setContext(context);
// 	}
// 
// 	public static void clearContext() {
// 		strategy.clearContext();
// 	}
// 
// 	public static TenantContext createEmptyContext() {
// 		return strategy.createEmptyContext();
// 	}
// 
// 	/**
// 	 * Changes the preferred strategy. Do <em>NOT</em> call this method more than once for
// 	 * a given JVM, as it will re-initialize the strategy and adversely affect any
// 	 * existing threads using the old strategy.
// 	 *
// 	 * @param strategyName the fully qualified class name of the strategy that should be
// 	 * used.
// 	 */
// 	public static void setStrategyName(String strategyName) {
// 		TenantContextHolder.strategyName = strategyName;
// 		initialize();
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return String.format("TenantContextHolder [strategy=%s]", strategyName);
// 	}
// }
// 
// Path: spring-multi-tenancy-core/src/main/java/biz/deinum/multitenant/web/TenantIdentificationStrategy.java
// public interface TenantIdentificationStrategy {
// 
// 	/**
// 	 * Determine the tenant based on the current request. If the strategy
// 	 * cannot determine a tenant, return {@code null}.
// 	 *
// 	 * @param request the current request
// 	 * @return the tenant or {@code null}.
// 	 */
// 	String getTenant(HttpServletRequest request);
// }


import biz.deinum.multitenant.web.TenantIdentificationStrategy;
import java.io.IOException;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter;
import biz.deinum.multitenant.context.TenantContext;
import biz.deinum.multitenant.context.TenantContextHolder;
/*
 * Copyright 2007-2016 the original author or authors.
 *
 * 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 biz.deinum.multitenant.web.filter;




/**
 * <p>{@code javax.servlet.Filter} which sets the context from the current request.
 *
 * <p>Delegates the actual lookup to a {@code TenantIdentificationStrategy}.
 *
 * <p>When no context is found an {@code IllegalStateException} is thrown, this can be
 * switched off by setting the {@code throwExceptionOnMissingTenant}property.
 *
 * @author Marten Deinum
 * @since 1.3
 **/
public class TenantContextFilter extends OncePerRequestFilter {

	private final Logger logger = LoggerFactory.getLogger(TenantContextFilter.class);

	private final List<TenantIdentificationStrategy> strategies;

	private boolean throwExceptionOnMissingTenant = true;

	public TenantContextFilter(List<TenantIdentificationStrategy> strategies) {
		super();
		Assert.notEmpty(strategies, "At least one TenantIdentificationStrategy is required.");
// Path: spring-multi-tenancy-core/src/main/java/biz/deinum/multitenant/context/TenantContext.java
// public interface TenantContext extends Serializable {
// 
// 
// 	/**
// 	 * Get the tenant
// 	 * @return the tenant
// 	 */
// 	String getTenant();
// 
// 	/**
// 	 * Set the tenant.
// 	 *
// 	 * @param tenant the tenant
// 	 */
// 	void setTenant(String tenant);
// }
// 
// Path: spring-multi-tenancy-core/src/main/java/biz/deinum/multitenant/context/TenantContextHolder.java
// public abstract class TenantContextHolder {
// 
// 	public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";
// 	public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";
// 	public static final String MODE_GLOBAL = "MODE_GLOBAL";
// 	public static final String SYSTEM_PROPERTY = "multi_tenant.strategy";
// 
// 	private static String strategyName = System.getProperty(SYSTEM_PROPERTY, MODE_THREADLOCAL);
// 
// 	private static TenantContextHolderStrategy strategy;
// 
// 	static {
// 		initialize();
// 	}
// 
// 	private static void initialize() {
// 		if ((strategyName == null) || "".equals(strategyName)) {
// 			// Set default
// 			strategyName = MODE_THREADLOCAL;
// 		}
// 
// 		if (strategyName.equals(MODE_THREADLOCAL)) {
// 			strategy = new ThreadLocalTenantContextHolderStrategy();
// 		}
// 		else if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) {
// 			strategy = new InheritableThreadLocalTenantContextHolderStrategy();
// 		}
// 		else if (strategyName.equals(MODE_GLOBAL)) {
// 			strategy = new GlobalTenantContextHolderStrategy();
// 		}
// 		else {
// 			// Try to load a custom strategy
// 			try {
// 				Class<?> clazz = Class.forName(strategyName);
// 				Constructor<?> customStrategy = clazz.getConstructor();
// 				strategy = (TenantContextHolderStrategy) customStrategy.newInstance();
// 			}
// 			catch (Exception ex) {
// 				ReflectionUtils.handleReflectionException(ex);
// 			}
// 		}
// 	}
// 
// 	public static TenantContext getContext() {
// 		TenantContext context = strategy.getContext();
// 		return context;
// 	}
// 
// 	public static void setContext(final TenantContext context) {
// 		strategy.setContext(context);
// 	}
// 
// 	public static void clearContext() {
// 		strategy.clearContext();
// 	}
// 
// 	public static TenantContext createEmptyContext() {
// 		return strategy.createEmptyContext();
// 	}
// 
// 	/**
// 	 * Changes the preferred strategy. Do <em>NOT</em> call this method more than once for
// 	 * a given JVM, as it will re-initialize the strategy and adversely affect any
// 	 * existing threads using the old strategy.
// 	 *
// 	 * @param strategyName the fully qualified class name of the strategy that should be
// 	 * used.
// 	 */
// 	public static void setStrategyName(String strategyName) {
// 		TenantContextHolder.strategyName = strategyName;
// 		initialize();
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return String.format("TenantContextHolder [strategy=%s]", strategyName);
// 	}
// }
// 
// Path: spring-multi-tenancy-core/src/main/java/biz/deinum/multitenant/web/TenantIdentificationStrategy.java
// public interface TenantIdentificationStrategy {
// 
// 	/**
// 	 * Determine the tenant based on the current request. If the strategy
// 	 * cannot determine a tenant, return {@code null}.
// 	 *
// 	 * @param request the current request
// 	 * @return the tenant or {@code null}.
// 	 */
// 	String getTenant(HttpServletRequest request);
// }


// Path: spring-multi-tenancy-core/src/main/java/biz/deinum/multitenant/web/filter/TenantContextFilter.java
import biz.deinum.multitenant.web.TenantIdentificationStrategy;
import java.io.IOException;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter;
import biz.deinum.multitenant.context.TenantContext;
import biz.deinum.multitenant.context.TenantContextHolder;

/*
 * Copyright 2007-2016 the original author or authors.
 *
 * 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 biz.deinum.multitenant.web.filter;




/**
 * <p>{@code javax.servlet.Filter} which sets the context from the current request.
 *
 * <p>Delegates the actual lookup to a {@code TenantIdentificationStrategy}.
 *
 * <p>When no context is found an {@code IllegalStateException} is thrown, this can be
 * switched off by setting the {@code throwExceptionOnMissingTenant}property.
 *
 * @author Marten Deinum
 * @since 1.3
 **/
public class TenantContextFilter extends OncePerRequestFilter {

	private final Logger logger = LoggerFactory.getLogger(TenantContextFilter.class);

	private final List<TenantIdentificationStrategy> strategies;

	private boolean throwExceptionOnMissingTenant = true;

	public TenantContextFilter(List<TenantIdentificationStrategy> strategies) {
		super();
		Assert.notEmpty(strategies, "At least one TenantIdentificationStrategy is required.");
		this.strategies = strategies;