/* ================================================================== * SetupResourcesTag.java - 21/09/2016 10:44:07 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.support; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.util.Collection; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import org.springframework.web.servlet.tags.HtmlEscapingAwareTag; import org.springframework.web.servlet.tags.form.TagWriter; import org.springframework.web.util.UriUtils; import net.solarnetwork.node.setup.SetupResource; import net.solarnetwork.node.setup.SetupResourceProvider; import net.solarnetwork.node.setup.SetupResourceScope; import net.solarnetwork.node.setup.SetupResourceService; /** * Tag to generate HTML tags for supported {@link SetupResource} values. * * When rendering inline content, if any properties are provided via * {@link #setProperties(Map)} then the content will be wrapped in a * {@code <div>} element (or whatever is configured via * {@link #setPropertiesWrapperElement(String)}) and all properties added as * {@code data-} attributes. * * @author matt * @version 1.1 */ public class SetupResourcesTag extends HtmlEscapingAwareTag { private static final long serialVersionUID = 6291858407097698593L; private SetupResourceService setupResourceService; private String role; private String type = SetupResource.JAVASCRIPT_CONTENT_TYPE; private SetupResourceProvider provider; private SetupResourceScope scope; private boolean inline = false; private Map<String, ?> properties; private String wrapperElement = "div"; private String wrapperClass; @Override protected int doStartTagInternal() throws Exception { writeContent(new TagWriter(this.pageContext)); return SKIP_BODY; } private void writeContent(TagWriter tagWriter) throws JspException { if ( setupResourceService == null && provider == null ) { setupResourceService = getRequestContext().getWebApplicationContext() .getBean(SetupResourceService.class); if ( setupResourceService == null ) { return; } } Collection<SetupResource> resources = (provider != null ? provider.getSetupResourcesForConsumer(SetupResourceProvider.WEB_CONSUMER_TYPE, pageContext.getRequest().getLocale()) : setupResourceService.getSetupResourcesForConsumer( SetupResourceProvider.WEB_CONSUMER_TYPE, pageContext.getRequest().getLocale())); if ( resources == null || resources.isEmpty() ) { return; } String baseUrl = (role == null ? "/rsrc/" : "/a/rsrc/"); if ( inline && properties != null && wrapperElement != null ) { tagWriter.startTag(wrapperElement); if ( wrapperClass != null ) { tagWriter.writeAttribute("class", htmlEscape(wrapperClass)); } for ( Map.Entry<String, ?> me : properties.entrySet() ) { String value = (me.getValue() == null ? "" : me.getValue().toString()); tagWriter.writeAttribute("data-" + htmlEscape(me.getKey()), htmlEscape(value)); } tagWriter.forceBlock(); } for ( SetupResource rsrc : resources ) { if ( !type.equals(rsrc.getContentType()) ) { continue; } if ( !hasRequiredyRole(rsrc) ) { continue; } if ( !hasRequiredScope(rsrc) ) { continue; } if ( inline ) { try { writeInlineResource(rsrc); } catch ( IOException e ) { throw new JspException(e); } } else { String url = ""; try { url = getRequestContext().getContextUrl( baseUrl + UriUtils.encodePathSegment(rsrc.getResourceUID(), "UTF-8")); } catch ( UnsupportedEncodingException e ) { // should not be here ever } if ( SetupResource.JAVASCRIPT_CONTENT_TYPE.equals(rsrc.getContentType()) ) { tagWriter.startTag("script"); tagWriter.writeAttribute("type", rsrc.getContentType()); tagWriter.writeAttribute("src", url); tagWriter.endTag(true); } else if ( SetupResource.CSS_CONTENT_TYPE.equals(rsrc.getContentType()) ) { tagWriter.startTag("link"); tagWriter.writeAttribute("rel", "stylesheet"); tagWriter.writeAttribute("type", "text/css"); tagWriter.writeAttribute("href", url); } else if ( rsrc.getContentType().startsWith("image/") ) { tagWriter.startTag("img"); tagWriter.writeAttribute("src", url); } } } if ( inline && properties != null && wrapperElement != null ) { tagWriter.endTag(true); } } private void writeInlineResource(SetupResource rsrc) throws IOException { Reader in = new InputStreamReader(rsrc.getInputStream(), "UTF-8"); Writer out = this.pageContext.getOut(); try { char[] buffer = new char[4096]; int bytesRead = -1; while ( (bytesRead = in.read(buffer)) != -1 ) { out.write(buffer, 0, bytesRead); } out.flush(); } finally { try { in.close(); } catch ( IOException ex ) { // ignore this } } } private boolean hasRequiredyRole(SetupResource rsrc) { Set<String> roles = rsrc.getRequiredRoles(); if ( roles == null || roles.isEmpty() ) { return true; } for ( String role : roles ) { if ( ((HttpServletRequest) this.pageContext.getRequest()).isUserInRole(role) ) { return true; } } return false; } private boolean hasRequiredScope(SetupResource rsrc) { SetupResourceScope rsrcScope = rsrc.getScope(); if ( scope == null && (rsrcScope == null || rsrcScope.equals(SetupResourceScope.Default)) ) { return true; } else if ( scope != null && scope.equals(rsrcScope) ) { return true; } return false; } public void setSetupResourceService(SetupResourceService setupResourceService) { this.setupResourceService = setupResourceService; } public void setRole(String role) { this.role = role; } public void setType(String type) { this.type = type; } public void setProvider(SetupResourceProvider provider) { this.provider = provider; } public void setInline(boolean inline) { this.inline = inline; } public void setProperties(Map<String, ?> properties) { this.properties = properties; } public void setWrapperElement(String propertiesWrapperElement) { this.wrapperElement = propertiesWrapperElement; } public void setWrapperClass(String wrapperClass) { this.wrapperClass = wrapperClass; } /** * Set a scope to restrict resolved resources to. * * @param scope * the scope to set * @since 1.1 */ public void setScope(SetupResourceScope scope) { this.scope = scope; } }