/**
* Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.seed.rest.jersey2.internal;
import org.seedstack.seed.SeedException;
import org.seedstack.seed.rest.CacheControl;
import org.seedstack.seed.rest.CachePolicy;
import org.seedstack.seed.rest.internal.RestErrorCode;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Date;
@Provider
class CacheControlFeature implements DynamicFeature {
private static final CacheResponseFilter NO_CACHE_FILTER = new CacheResponseFilter(CachePolicy.NO_CACHE);
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext featureContext) {
CacheControl cacheControl = null;
Method resourceMethod = resourceInfo.getResourceMethod();
if (resourceMethod != null) {
cacheControl = resourceMethod.getAnnotation(CacheControl.class);
} else {
Class<?> resourceClass = resourceInfo.getResourceClass();
if (resourceClass != null) {
cacheControl = resourceClass.getAnnotation(CacheControl.class);
}
}
if (cacheControl == null) {
featureContext.register(NO_CACHE_FILTER);
} else {
featureContext.register(new CacheResponseFilter(cacheControl.value()));
}
}
private static class CacheResponseFilter implements ContainerResponseFilter {
private static final String MUST_REVALIDATE_PRIVATE = "must revalidate, private";
private final CachePolicy policy;
CacheResponseFilter(CachePolicy policy) {
this.policy = policy;
}
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
switch (this.policy) {
case NO_CACHE:
MultivaluedMap<String, Object> headers = responseContext.getHeaders();
headers.putSingle(HttpHeaders.LAST_MODIFIED, new Date());
headers.putSingle(HttpHeaders.EXPIRES, -1);
headers.putSingle(HttpHeaders.CACHE_CONTROL, MUST_REVALIDATE_PRIVATE);
break;
case CUSTOM:
break;
default:
throw SeedException.createNew(RestErrorCode.UNSUPPORTED_CACHE_POLICY)
.put("policy", this.policy.name());
}
}
}
}