/** * The contents of this file are subject to the OpenMRS Public License * Version 1.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://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Copyright (C) OpenMRS, LLC. All Rights Reserved. */ package org.openmrs.web.taglib; import java.io.IOException; import java.util.HashMap; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.TagSupport; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openmrs.util.OpenmrsConstants; import org.openmrs.web.WebConstants; public class HtmlIncludeTag extends TagSupport { public static final long serialVersionUID = 13472382822L; private final Log log = LogFactory.getLog(getClass()); private static final String POSSIBLE_TYPES_JS = ".js,javascript,jscript"; private static final String POSSIBLE_TYPES_CSS = ".css,style,stylesheet"; public static final String OPENMRS_HTML_INCLUDE_REQUEST_ID_KEY = "org.openmrs.htmlInclude.pageName"; public static final String OPENMRS_HTML_INCLUDE_MAP_KEY = "org.openmrs.htmlInclude.includeMap"; private String type; private String file; public int doStartTag() throws JspException { log.debug("\n\n"); // see if this is a JS or CSS file boolean isJs = false; boolean isCss = false; String fileExt = file.substring(file.lastIndexOf(".")); if (this.type != null) { if (this.type.length() > 0) { if (HtmlIncludeTag.POSSIBLE_TYPES_CSS.indexOf(type) >= 0) isCss = true; else if (HtmlIncludeTag.POSSIBLE_TYPES_JS.indexOf(type) >= 0) isJs = true; } } if (!isCss && !isJs && fileExt.length() > 0) { if (HtmlIncludeTag.POSSIBLE_TYPES_CSS.indexOf(fileExt) >= 0) isCss = true; else if (HtmlIncludeTag.POSSIBLE_TYPES_JS.indexOf(fileExt) >= 0) isJs = true; } if (isJs || isCss) { String initialRequestId = getInitialRequestUniqueId(); HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); log.debug("initialRequest id: [" + initialRequestId + "]"); log.debug("Object at pageContext." + HtmlIncludeTag.OPENMRS_HTML_INCLUDE_MAP_KEY + " is " + pageContext.getAttribute(HtmlIncludeTag.OPENMRS_HTML_INCLUDE_MAP_KEY, PageContext.SESSION_SCOPE) + ""); if (!isAlreadyUsed(file, initialRequestId)) { String output = ""; String prefix = ""; try { prefix = request.getContextPath(); if (file.startsWith(prefix + "/")) prefix = ""; } catch (ClassCastException cce) { log.debug("Could not cast request to HttpServletRequest in HtmlIncludeTag"); } // the openmrs version is inserted into the file src so that js and css files are cached across version releases if (isJs) { output = "<script src=\"" + prefix + file + "?v=" + OpenmrsConstants.OPENMRS_VERSION_SHORT + "\" type=\"text/javascript\" ></script>"; } else if (isCss) { output = "<link href=\"" + prefix + file + "?v=" + OpenmrsConstants.OPENMRS_VERSION_SHORT + "\" type=\"text/css\" rel=\"stylesheet\" />"; } log.debug("isAlreadyUsed() is FALSE - printing " + this.file + " to output."); try { pageContext.getOut().print(output); } catch (IOException e) { log.debug("Could not produce output in HtmlIncludeTag.java"); } } else { log.debug("isAlreadyUsed() is TRUE - suppressing file print for " + this.file + ""); } } resetValues(); return SKIP_BODY; } private String getInitialRequestUniqueId() { HttpServletRequest pageRequest = (HttpServletRequest) this.pageContext.getRequest(); Object attr = pageRequest.getAttribute(WebConstants.INIT_REQ_UNIQUE_ID); if (attr != null) { String uniqueId = (String) attr; log.debug("Returning initial request: " + uniqueId); return uniqueId; } else { log.error("Could not find value for " + WebConstants.INIT_REQ_UNIQUE_ID + " in pageContext"); return ""; } } @SuppressWarnings("unchecked") private boolean isAlreadyUsed(String fileName, String initialRequestId) { boolean isUsed = false; if (fileName != null) { log.debug("initialRequestId: " + initialRequestId); // retrieve the request id that the last mapping was added for String lastRequestId = (String) pageContext.getAttribute(HtmlIncludeTag.OPENMRS_HTML_INCLUDE_REQUEST_ID_KEY, PageContext.SESSION_SCOPE); // retrieve the htmlinclude map from the page request //HashMap<String,String> hmIncludeMap = (HashMap<String, String>) initialRequest.getAttribute(HtmlIncludeTag.OPENMRS_HTML_INCLUDE_KEY); HashMap<String, String> hmIncludeMap = (HashMap<String, String>) pageContext.getAttribute( HtmlIncludeTag.OPENMRS_HTML_INCLUDE_MAP_KEY, PageContext.SESSION_SCOPE); // reset the hmIncludeMap if not found or if not on the initial request anymore if (hmIncludeMap == null || !initialRequestId.equals(lastRequestId)) { log.debug("Creating new hmIncludeMap"); hmIncludeMap = new HashMap<String, String>(); } else log.debug("Using hmIncludeMap from object"); if (hmIncludeMap.containsKey(fileName)) { log.debug("HTMLINCLUDETAG HAS ALREADY INCLUDED FILE " + fileName); isUsed = true; } else { log.debug("HTMLINCLUDETAG IS WRITING HTML TO INCLUDE FILE " + fileName); log.debug("HashCode for file is " + fileName.hashCode()); hmIncludeMap.put(fileName, "true"); // save the hmIncludeMap to the pageContext.setAttribute(HtmlIncludeTag.OPENMRS_HTML_INCLUDE_MAP_KEY, hmIncludeMap, PageContext.SESSION_SCOPE); // save the name of the initial page pageContext.setAttribute(HtmlIncludeTag.OPENMRS_HTML_INCLUDE_REQUEST_ID_KEY, initialRequestId, PageContext.SESSION_SCOPE); } } return isUsed; } private void resetValues() { log.debug("resetting values"); this.type = null; this.file = null; } public String getType() { return type; } public void setType(String type) { this.type = type; } /** * @return Returns the file. */ public String getFile() { return file; } /** * @param file The file to set. */ public void setFile(String file) { this.file = file; if (file != null) this.file = file.trim(); } }