inti.ws.spring.resource.ResourceController Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ws-spring-resource Show documentation
Show all versions of ws-spring-resource Show documentation
An utility library for spring-based web-services for compressing / optimizing JS and CSS resources.
/**
* Copyright 2012 the project-owners
*
* 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 inti.ws.spring.resource;
import inti.util.DateFormatter;
import inti.ws.spring.exception.client.NotFoundException;
import inti.ws.spring.resource.config.ConfigParserSettings;
import inti.ws.spring.resource.config.ResourceConfig;
import inti.ws.spring.resource.config.ResourceConfigProvider;
import java.util.Map;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class ResourceController {
private static final Logger LOGGER = LoggerFactory.getLogger(ResourceController.class);
private static final String EXPIRES_IMMEDIATELY = "-1";
@Inject
ResourceConfigProvider configProvider;
@Inject
ServletContext ctx;
ThreadLocal contexts = new ThreadLocal() {
@Override
protected ResourceWorkingContext initialValue() {
return new ResourceWorkingContext();
}
};
DateFormatter dateFormatter = new DateFormatter();
protected void applyCachingHeader(HttpServletResponse response, WebResource resource, ConfigParserSettings settings) {
ResourceWorkingContext ctx = contexts.get();
if (settings.getExpires() > 0) {
// http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
ctx.clearBuilder();
dateFormatter.formatDate(System.currentTimeMillis() + settings.getExpires(), ctx.getBuilder());
response.addHeader(HttpHeaders.EXPIRES, ctx.getBuilder().toString());
response.setHeader(HttpHeaders.ETAG, resource.getMessageDigest());
response.setHeader(HttpHeaders.LAST_MODIFIED, resource.getLastModifiedString());
} else {
response.addHeader(HttpHeaders.EXPIRES, EXPIRES_IMMEDIATELY);
}
response.setHeader(HttpHeaders.CACHE_CONTROL, settings.getCacheControl());
}
protected void resource(String name, WebResource resource, HttpServletRequest request,
HttpServletResponse response, ConfigParserSettings settings) throws Exception {
String tmp;
resource.updateIfNeeded();
if ((tmp = request.getHeader(HttpHeaders.IF_MODIFIED_SINCE)) != null) {
if (resource.getLastModified() <= dateFormatter.parseDate(tmp)) {
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return;
}
} else if ((tmp = request.getHeader(HttpHeaders.IF_NONE_MATCH)) != null) {
if (tmp.equals(resource.getMessageDigest())) {
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return;
}
}
applyCachingHeader(response, resource, settings);
response.setHeader(HttpHeaders.CONTENT_TYPE, settings.getContentType());
response.setHeader(HttpHeaders.CONTENT_ENCODING, settings.getContentEncoding());
resource.processResponse(request, response, settings);
response.getOutputStream().write(resource.getByteContent(settings));
response.getOutputStream().close();
}
@RequestMapping(value = "/**/*.*", method = RequestMethod.GET)
public void resource(HttpServletRequest request, HttpServletResponse response) throws Exception {
String uri = request.getRequestURI();
Map config = configProvider.getResourceConfig(request);
if (!ctx.getContextPath().equals("")) {
uri = uri.replaceFirst(ctx.getContextPath(), "");
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("resource - handling request for uri={}", uri);
LOGGER.debug("resource - searching in={}", config);
}
for (Map.Entry route : config.entrySet()) {
if (uri.startsWith(route.getKey())) {
for (Map.Entry resource : route.getValue().getResources().entrySet()) {
if (uri.endsWith(resource.getKey())) {
LOGGER.debug("resource - resource found for uri={}", uri);
resource(resource.getKey(), resource.getValue(), request, response, route.getValue()
.getSettings());
return;
}
}
}
}
throw new NotFoundException("resource not found: " + uri);
}
}