/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*/
package com.liferay.frontend.theme.contributor.extender.internal;
import com.liferay.frontend.theme.contributor.extender.BundleWebResources;
import com.liferay.portal.kernel.servlet.PortalWebResourceConstants;
import com.liferay.portal.kernel.servlet.PortalWebResourcesUtil;
import com.liferay.portal.kernel.servlet.taglib.DynamicInclude;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.Portal;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.WebKeys;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.TreeSet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
/**
* @author Carlos Sierra Andrés
*/
@Component(immediate = true)
public class ThemeContributorDynamicInclude implements DynamicInclude {
@Override
public void include(
HttpServletRequest request, HttpServletResponse response,
String key)
throws IOException {
ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
WebKeys.THEME_DISPLAY);
long themeLastModified = PortalWebResourcesUtil.getLastModified(
PortalWebResourceConstants.RESOURCE_TYPE_THEME_CONTRIBUTOR);
if (_cssResourceURLs.length > 0) {
if (themeDisplay.isThemeCssFastLoad()) {
_renderComboCSS(
themeLastModified, request, response.getWriter());
}
else {
_renderSimpleCSS(
themeLastModified, request, themeDisplay.getPortalURL(),
response.getWriter(), _cssResourceURLs);
}
}
if (_jsResourceURLs.length == 0) {
return;
}
if (themeDisplay.isThemeJsFastLoad()) {
_renderComboJS(themeLastModified, request, response.getWriter());
}
else {
_renderSimpleJS(
themeLastModified, request, themeDisplay.getPortalURL(),
response.getWriter(), _jsResourceURLs);
}
}
@Override
public void register(DynamicIncludeRegistry dynamicIncludeRegistry) {
dynamicIncludeRegistry.register(
"/html/common/themes/top_head.jsp#post");
}
@Reference(unbind = "-")
public void setPortal(Portal portal) {
String pathContext = portal.getPathContext();
_comboContextPath = pathContext.concat("/combo");
_portal = portal;
}
@Activate
protected void activate(BundleContext bundleContext) {
_bundleContext = bundleContext;
}
@Reference(
cardinality = ReferenceCardinality.MULTIPLE,
policy = ReferencePolicy.DYNAMIC, unbind = "removeBundleWebResources"
)
protected void addBundleWebResources(
ServiceReference<BundleWebResources>
bundleWebResourcesServiceReference) {
synchronized (_bundleWebResourcesServiceReferences) {
_bundleWebResourcesServiceReferences.add(
bundleWebResourcesServiceReference);
_rebuild();
}
}
protected void removeBundleWebResources(
ServiceReference<BundleWebResources>
bundleWebResourcesServiceReference) {
synchronized (_bundleWebResourcesServiceReferences) {
_bundleWebResourcesServiceReferences.remove(
bundleWebResourcesServiceReference);
_rebuild();
}
}
private void _rebuild() {
Collection<String> cssResourceURLs = new ArrayList<>();
Collection<String> jsResourceURLs = new ArrayList<>();
for (ServiceReference<BundleWebResources>
bundleWebResourcesServiceReference :
_bundleWebResourcesServiceReferences) {
BundleWebResources bundleWebResources = _bundleContext.getService(
bundleWebResourcesServiceReference);
try {
String servletContextPath =
bundleWebResources.getServletContextPath();
for (String cssResourcePath :
bundleWebResources.getCssResourcePaths()) {
cssResourceURLs.add(
servletContextPath.concat(cssResourcePath));
}
for (String jsResourcePath :
bundleWebResources.getJsResourcePaths()) {
jsResourceURLs.add(
servletContextPath.concat(jsResourcePath));
}
}
finally {
_bundleContext.ungetService(bundleWebResourcesServiceReference);
}
}
_cssResourceURLs = cssResourceURLs.toArray(
new String[cssResourceURLs.size()]);
StringBundler sb = new StringBundler(cssResourceURLs.size() * 2 + 1);
for (String cssResourceURL : cssResourceURLs) {
sb.append("&");
sb.append(cssResourceURL);
}
sb.append("\" rel=\"stylesheet\" type = \"text/css\" />\n");
_mergedCSSResourceURLs = sb.toString();
_jsResourceURLs = jsResourceURLs.toArray(
new String[jsResourceURLs.size()]);
sb = new StringBundler(jsResourceURLs.size() * 2 + 1);
for (String jsResourceURL : jsResourceURLs) {
sb.append("&");
sb.append(jsResourceURL);
}
sb.append("\" \" type = \"text/javascript\"></script>\n");
_mergedJSResourceURLs = sb.toString();
}
private void _renderComboCSS(
long themeLastModified, HttpServletRequest request,
PrintWriter printWriter) {
printWriter.write("<link data-senna-track=\"temporary\" href=\"");
printWriter.write(
_portal.getStaticResourceURL(
request, _comboContextPath, "minifierType=css",
themeLastModified));
printWriter.write(_mergedCSSResourceURLs);
}
private void _renderComboJS(
long themeLastModified, HttpServletRequest request,
PrintWriter printWriter) {
printWriter.write("<script data-senna-track=\"temporary\" src=\"");
printWriter.write(
_portal.getStaticResourceURL(
request, _comboContextPath, "minifierType=js",
themeLastModified));
printWriter.write(_mergedJSResourceURLs);
}
private void _renderSimpleCSS(
long themeLastModified, HttpServletRequest request, String portalURL,
PrintWriter printWriter, String[] resourceURLs) {
for (String resourceURL : resourceURLs) {
String staticResourceURL = _portal.getStaticResourceURL(
request,
portalURL.concat(_portal.getPathProxy()).concat(resourceURL),
themeLastModified);
printWriter.write("<link data-senna-track=\"temporary\" href=\"");
printWriter.write(staticResourceURL);
printWriter.write("\" rel=\"stylesheet\" type = \"text/css\" />\n");
}
}
private void _renderSimpleJS(
long themeLastModified, HttpServletRequest request, String portalURL,
PrintWriter printWriter, String[] resourceURLs) {
for (String resourceURL : resourceURLs) {
String staticResourceURL = _portal.getStaticResourceURL(
request,
portalURL.concat(_portal.getPathProxy()).concat(resourceURL),
themeLastModified);
printWriter.write("<script data-senna-track=\"temporary\" src=\"");
printWriter.write(staticResourceURL);
printWriter.write("\" \" type = \"text/javascript\"></script>\n");
}
}
private BundleContext _bundleContext;
private final Collection<ServiceReference<BundleWebResources>>
_bundleWebResourcesServiceReferences = new TreeSet<>();
private String _comboContextPath;
private volatile String[] _cssResourceURLs = StringPool.EMPTY_ARRAY;
private volatile String[] _jsResourceURLs = StringPool.EMPTY_ARRAY;
private volatile String _mergedCSSResourceURLs;
private volatile String _mergedJSResourceURLs;
private Portal _portal;
}