package com.idega.util.resources; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.myfaces.renderkit.html.util.AddResource; import org.apache.myfaces.renderkit.html.util.DefaultAddResource; import org.apache.myfaces.renderkit.html.util.ResourcePosition; import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML; import com.idega.idegaweb.IWMainApplication; import com.idega.idegaweb.include.ExternalLink; import com.idega.idegaweb.include.JavaScriptLink; import com.idega.idegaweb.include.RSSLink; import com.idega.idegaweb.include.StyleSheetLink; import com.idega.util.CoreConstants; import com.idega.util.ListUtil; import com.idega.util.PresentationUtil; import com.idega.util.RequestUtil; import com.idega.util.StringUtil; import com.idega.util.expression.ELUtil; public class ResourcesAdder extends DefaultAddResource { private static final Logger LOGGER = Logger.getLogger(ResourcesAdder.class.getName()); public static final String OPTIMIZE_RESOURCES = "idega_core.optimize_resources"; public static final String OPTIMIZE_JAVA_SCRIPT = "idega_core.optimize_js"; public static final String OPTIMIZE_STYLE_SHEET = "idega_core.optimize_css"; public static final String OPTIMIZIED_RESOURCES = "optimizedResources_"; public static final String FILE_TYPE_JAVA_SCRIPT = ".js"; private static final String FILE_TYPE_CSS = ".css"; @Override public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, String uri) { List<JavaScriptLink> javaScriptResources = getJavaScriptResources(); if (containsResource(javaScriptResources, uri)) return; javaScriptResources.add(new JavaScriptLink(uri)); } @Override public void addStyleSheet(FacesContext context, ResourcePosition position, String uri) { List<StyleSheetLink> cssFiles = getCSSFiles(); if (containsResource(cssFiles, uri)) return; cssFiles.add(new StyleSheetLink(uri, getMediaMap().get(uri))); } @Override public void addInlineScriptAtPosition(FacesContext context, ResourcePosition position, String inlineScript) { List<JavaScriptLink> javaScriptActions = getJavaScriptActions(); if (containsResource(javaScriptActions, inlineScript)) return; JavaScriptLink action = new JavaScriptLink(); action.addAction(inlineScript); javaScriptActions.add(action); } private boolean containsResource(List<? extends ExternalLink> resources, String uri) { if (ListUtil.isEmpty(resources) || StringUtil.isEmpty(uri)) return false; for (ExternalLink resource: resources) { if (uri.equals(resource.getUrl())) return true; } return false; } @Override public void writeMyFacesJavascriptBeforeBodyEnd(HttpServletRequest request, HttpServletResponse response) throws IOException { manageHeader(RequestUtil.getServerURL(request)); super.writeMyFacesJavascriptBeforeBodyEnd(request, response); } @Override public void writeResponse(HttpServletRequest request, HttpServletResponse response) throws IOException { manageHeader(RequestUtil.getServerURL(request)); super.writeResponse(request, response); } @Override public void writeWithFullHeader(HttpServletRequest request, HttpServletResponse response) throws IOException { manageHeader(RequestUtil.getServerURL(request)); super.writeWithFullHeader(request, response); } @Override public String getResourceUri(FacesContext context, String uri, boolean withContextPath) { if (withContextPath) { try { return super.getResourceUri(context, uri, withContextPath); } catch(Exception e) {} } return uri; } private ResourcesManager getResourcesManager() { try { return ELUtil.getInstance().getBean(ResourcesManager.SPRING_BEAN_IDENTIFIER); } catch(Exception e) { LOGGER.log(Level.SEVERE, "Error getting resources manager", e); } return null; } private List<RSSLink> getFeedResources() { ResourcesManager manager = getResourcesManager(); return manager == null ? null : manager.getFeedLinks(); } private List<JavaScriptLink> getJavaScriptResources() { ResourcesManager manager = getResourcesManager(); return manager == null ? null : manager.getJavaScriptResources(); } private List<StyleSheetLink> getCSSFiles() { ResourcesManager manager = getResourcesManager(); return manager == null ? null : manager.getCSSFiles(); } private List<JavaScriptLink> getJavaScriptActions() { ResourcesManager manager = getResourcesManager(); return manager == null ? null : manager.getJavaScriptActions(); } private Map<String, String> getMediaMap() { ResourcesManager manager = getResourcesManager(); return manager == null ? null : manager.getMediaMap(); } private static boolean useOptimizer(String applicationPropertyName, Boolean defaultValue) { return IWMainApplication.getDefaultIWMainApplication().getSettings().getBoolean(applicationPropertyName, defaultValue); } public static boolean isOptimizationTurnedOn(String applicationPropertyName) { return useOptimizer(applicationPropertyName, Boolean.TRUE); } public static boolean isCSSOptimizationTurnedOn() { return isOptimizationTurnedOn(ResourcesAdder.OPTIMIZE_RESOURCES) && isOptimizationTurnedOn(ResourcesAdder.OPTIMIZE_STYLE_SHEET); } private void manageHeader(String serverName) { if (ListUtil.isEmpty(getJavaScriptActions()) && ListUtil.isEmpty(getJavaScriptResources()) && ListUtil.isEmpty(getCSSFiles()) && ListUtil.isEmpty(getFeedResources())) return; boolean useOptimizer = useOptimizer(OPTIMIZE_RESOURCES, Boolean.TRUE); FacesContext facesContext = FacesContext.getCurrentInstance(); // CSS if (useOptimizer && useOptimizer(OPTIMIZE_STYLE_SHEET, Boolean.TRUE)) { addResources(facesContext, getCSSFiles(), FILE_TYPE_CSS, serverName); } else { for (StyleSheetLink css: getCSSFiles()) { super.addStyleSheet(facesContext, AddResource.HEADER_BEGIN, PresentationUtil.getFixedUrl(css.getUrl())); } } // JavaScript if (useOptimizer && useOptimizer(OPTIMIZE_JAVA_SCRIPT, Boolean.TRUE)) { addResources(facesContext, getJavaScriptResources(), FILE_TYPE_JAVA_SCRIPT, serverName); } else { for (JavaScriptLink script: getJavaScriptResources()) { super.addJavaScriptAtPosition(facesContext, AddResource.BODY_END, PresentationUtil.getFixedUrl(script.getUrl())); } } // JS actions for (JavaScriptLink action: getJavaScriptActions()) { for (String scriptAction: action.getActions()) { super.addInlineScriptAtPosition(facesContext, AddResource.BODY_END, scriptAction); } } } @SuppressWarnings("unchecked") private void addResources(FacesContext facesContext, List<? extends ExternalLink> resources, String fileType, String serverName) { if (ListUtil.isEmpty(resources)) return; ResourcesManager resourcesManager = getResourcesManager(); if (resources == null) return; String concatenatedResourcesUri = resourcesManager.getConcatenatedResources(resources, fileType, serverName); if (!ListUtil.isEmpty(resources)) { // Restoring original resources for (final ExternalLink link: resources) { if (link instanceof JavaScriptLink) { super.addJavaScriptAtPosition(facesContext, AddResource.BODY_END, PresentationUtil.getFixedUrl(link.getUrl())); } else if (link instanceof StyleSheetLink) { super.addStyleSheet(facesContext, AddResource.HEADER_BEGIN, PresentationUtil.getFixedUrl(link.getUrl())); } } } if (!StringUtil.isEmpty(concatenatedResourcesUri)) { // Adding concatenated file to page if (concatenatedResourcesUri.endsWith(FILE_TYPE_JAVA_SCRIPT)) { super.addJavaScriptAtPosition(facesContext, AddResource.BODY_END, concatenatedResourcesUri); } else { super.addStyleSheet(facesContext, AddResource.HEADER_BEGIN, concatenatedResourcesUri); } } for (RSSLink feed: getFeedResources()) { getHeaderBeginInfos().add(new FeedInfo(feed)); } } public void addMediaType(String resourceUri, String mediaType) { if (StringUtil.isEmpty(resourceUri) || StringUtil.isEmpty(mediaType)) return; Map<String, String> mediaMap = getMediaMap(); if (mediaMap == null) return; mediaMap.put(resourceUri, mediaType); } public void addFeedLink(RSSLink feedLink) { if (!getFeedResources().contains(feedLink)) { getFeedResources().add(feedLink); } } private class FeedInfo implements WritablePositionedInfo { private final RSSLink feed; private FeedInfo(RSSLink feed) { this.feed = feed; } public void writePositionedInfo(HttpServletResponse response, ResponseWriter writer) throws IOException { writer.startElement(HTML.LINK_ELEM, null); writer.writeAttribute(HTML.REL_ATTR, StringUtil.isEmpty(feed.getRelationship()) ? "alternate" : feed.getRelationship(), null); writer.writeAttribute(HTML.HREF_ATTR, response.encodeURL(feed.getUrl()), null); writer.writeAttribute(HTML.TYPE_ATTR, feed.getType(), null); writer.writeAttribute(HTML.TITLE_ATTR, StringUtil.isEmpty(feed.getTitle()) ? "Feed" : feed.getTitle(), null); writer.endElement(HTML.LINK_ELEM); } } @Override public void parseResponse(HttpServletRequest request, String bufferedResponse, HttpServletResponse response) { if (StringUtil.isEmpty(bufferedResponse)) { super.parseResponse(request, bufferedResponse, response); return; } if (Boolean.TRUE.toString().equals(request.getParameter(CoreConstants.PARAMETER_CHECK_HTML_HEAD_AND_BODY))) { StringBuffer addons = new StringBuffer(); boolean noHTML = bufferedResponse.indexOf("<html") == -1; if (noHTML) addons.append("<html>"); if (bufferedResponse.indexOf("<head") == -1) addons.append("<head></head>"); if (bufferedResponse.indexOf("<body") == -1) addons.append("<body>").append(bufferedResponse).append("</body>"); if (noHTML) addons.append("</html>"); String htmlResponse = addons.toString(); bufferedResponse = StringUtil.isEmpty(htmlResponse) ? bufferedResponse : htmlResponse; } super.parseResponse(request, bufferedResponse, response); } }