/*
* Copyright 2017 OmniFaces
*
* 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.omnifaces.component.output.cache;
import java.util.Map;
import javax.faces.context.FacesContext;
/**
* Base class for Cache providers where for each scope a new instance of the cache is created if for that scope no instance
* is present yet.
* <p>
* This kind of cache provider is suitable for simple in-memory cache implementations, where the cache is very cheap
* to create. This is in contrast to caches where there is typically one expensive to create instance active per JVM,
* and where scoped caches are better expressed as nodes in a tree structure.
*
* @since 1.1
* @author Arjan Tijms
*
*/
public abstract class CacheInstancePerScopeProvider implements CacheProvider {
public static final String DEFAULT_CACHE_PARAM_NAME = "org.omnifaces.defaultcache";
public static final String APP_TTL_PARAM_NAME = "APPLICATION_TTL";
public static final String SESSION_TTL_PARAM_NAME = "SESSION_TTL";
public static final String APP_MAX_CAP_PARAM_NAME = "APPLICATION_MAX_CAPACITY";
public static final String SESSION_MAX_CAP_PARAM_NAME = "SESSION_MAX_CAPACITY";
private Integer appDefaultTimeToLive;
private Integer sessionDefaultTimeToLive;
private Integer appMaxCapacity;
private Integer sessionMaxCapacity;
private Map<String, String> parameters;
@Override
public Cache getCache(FacesContext context, String scope) {
if ("application".equals(scope)) {
return getAppScopeCache(context);
} else if ("session".equals(scope)) {
return getSessionScopeCache(context);
}
throw new IllegalArgumentException("Scope " + scope + " not supported by provider" + DefaultCacheProvider.class.getName());
}
@Override
public void setParameters(Map<String, String> parameters) {
this.parameters = parameters;
if (parameters.containsKey(APP_TTL_PARAM_NAME)) {
appDefaultTimeToLive = Integer.valueOf(parameters.get(APP_TTL_PARAM_NAME));
}
if (parameters.containsKey(SESSION_TTL_PARAM_NAME)) {
sessionDefaultTimeToLive = Integer.valueOf(parameters.get(SESSION_TTL_PARAM_NAME));
}
if (parameters.containsKey(APP_MAX_CAP_PARAM_NAME)) {
appMaxCapacity = Integer.valueOf(parameters.get(APP_MAX_CAP_PARAM_NAME));
}
if (parameters.containsKey(SESSION_MAX_CAP_PARAM_NAME)) {
sessionMaxCapacity = Integer.valueOf(parameters.get(SESSION_MAX_CAP_PARAM_NAME));
}
}
public Map<String, String> getParameters() {
return parameters;
}
private Cache getAppScopeCache(FacesContext context) {
Map<String, Object> applicationMap = context.getExternalContext().getApplicationMap();
if (!applicationMap.containsKey(DEFAULT_CACHE_PARAM_NAME)) {
synchronized (DefaultCacheProvider.class) {
if (!applicationMap.containsKey(DEFAULT_CACHE_PARAM_NAME)) {
applicationMap.put(DEFAULT_CACHE_PARAM_NAME, createCache(appDefaultTimeToLive, appMaxCapacity));
}
}
}
return (Cache) applicationMap.get(DEFAULT_CACHE_PARAM_NAME);
}
private Cache getSessionScopeCache(FacesContext context) {
Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
if (!sessionMap.containsKey(DEFAULT_CACHE_PARAM_NAME)) {
Object session = context.getExternalContext().getSession(true);
synchronized (session) {
if (!sessionMap.containsKey(DEFAULT_CACHE_PARAM_NAME)) {
sessionMap.put(DEFAULT_CACHE_PARAM_NAME, createCache(sessionDefaultTimeToLive, sessionMaxCapacity));
}
}
}
return (Cache) sessionMap.get(DEFAULT_CACHE_PARAM_NAME);
}
protected abstract Cache createCache(Integer timeToLive, Integer maxCapacity);
}