/* ================================================================== * SetupResourceController.java - 21/09/2016 6:17:04 AM * * Copyright 2007-2016 SolarNetwork.net Dev Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA * ================================================================== */ package net.solarnetwork.node.setup.web; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.WebRequest; import net.solarnetwork.node.setup.SetupResource; import net.solarnetwork.node.setup.SetupResourceService; /** * Controller for serving setup resources. * * @author matt * @version 1.0 */ @Controller public class SetupResourceController extends BaseSetupWebServiceController { @Autowired private SetupResourceService resourceService; @RequestMapping({ "/rsrc/{id:.+}", "/a/rsrc/{id:.+}" }) public void setupResource(@PathVariable("id") String id, WebRequest req, HttpServletResponse res) throws IOException { final SetupResource rsrc = resourceService.getSetupResource(id, req.getLocale()); if ( rsrc == null ) { res.setStatus(HttpServletResponse.SC_NOT_FOUND); return; } if ( rsrc.getRequiredRoles() != null && !hasRequiredyRole(req, rsrc) ) { res.setStatus(HttpServletResponse.SC_FORBIDDEN); return; } if ( req.checkNotModified(rsrc.lastModified()) ) { return; } respondWithSetupResource(rsrc, res); } /** * Handle an {@link IOException}. * * @param e * the exception * @param response * the response */ @ExceptionHandler(IOException.class) public void handleIOException(IOException e, HttpServletResponse res) { log.warn("IOException serving setup resource: {}", e.getMessage()); res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } private boolean hasRequiredyRole(WebRequest req, SetupResource rsrc) { Set<String> roles = rsrc.getRequiredRoles(); if ( roles == null || roles.isEmpty() ) { return true; } for ( String role : roles ) { if ( req.isUserInRole(role) ) { return true; } } return false; } private void respondWithSetupResource(SetupResource rsrc, HttpServletResponse res) throws IOException { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType(rsrc.getContentType())); if ( rsrc.lastModified() > 0 ) { headers.setLastModified(rsrc.lastModified()); } if ( rsrc.contentLength() > 0 ) { headers.setContentLength(rsrc.contentLength()); } if ( rsrc.getCacheMaximumSeconds() > 0 ) { headers.setCacheControl(CacheControl.maxAge(rsrc.getCacheMaximumSeconds(), TimeUnit.SECONDS) .getHeaderValue()); } res.setStatus(HttpServletResponse.SC_OK); for ( Map.Entry<String, List<String>> me : headers.entrySet() ) { for ( String value : me.getValue() ) { res.addHeader(me.getKey(), value); } } FileCopyUtils.copy(rsrc.getInputStream(), res.getOutputStream()); } }