package ameba.mvc.template.internal;
import ameba.exception.UnprocessableEntityException;
import groovy.lang.Singleton;
import jersey.repackaged.com.google.common.collect.Sets;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.inject.Providers;
import org.glassfish.jersey.server.mvc.spi.TemplateProcessor;
import javax.annotation.Priority;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Set;
/**
* 404 跳转到模板
*
* @author icode
* @since 2013-08-27
*
*/
@Singleton
@Priority(Priorities.ENTITY_CODER)
public class NotFoundForward implements ContainerResponseFilter {
@Context
private Provider<UriInfo> uriInfo;
@Inject
private InjectionManager injectionManager;
private Set<TemplateProcessor> getTemplateProcessors() {
Set<TemplateProcessor> templateProcessors = Sets.newLinkedHashSet();
templateProcessors.addAll(Providers.getCustomProviders(injectionManager, TemplateProcessor.class));
templateProcessors.addAll(Providers.getProviders(injectionManager, TemplateProcessor.class));
return templateProcessors;
}
private String getCurrentPath() {
return "/" + uriInfo.get().getPath();
}
/**
* <p>mappedViewPath.</p>
*
* @return a {@link java.lang.String} object.
*/
public String mappedViewPath() {
String path = getCurrentPath();
//受保护目录,不允许直接访问
String pDir = Viewables.PROTECTED_DIR + "/";
if (path.startsWith(pDir)
|| path.startsWith("/" + pDir)) return null;
for (TemplateProcessor templateProcessor : getTemplateProcessors()) {
Object has = templateProcessor.resolve(path, MediaType.TEXT_HTML_TYPE);
if (has == null) {
path = path + (path.endsWith("/") ? "" : "/") + "index";
has = templateProcessor.resolve(path, MediaType.TEXT_HTML_TYPE);
}
if (has != null) {
return path;
}
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException {
int status = responseContext.getStatus();
if (status == 404 || status == UnprocessableEntityException.STATUS) {
String path = mappedViewPath();
if (path != null) {
responseContext.setEntity(Viewables.newDefaultViewable(path),
new Annotation[0], MediaType.TEXT_HTML_TYPE);
responseContext.setStatus(Response.Status.OK.getStatusCode());
}
}
}
}