001
014
015 package com.liferay.portal.servlet.filters.dynamiccss;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.util.CharPool;
020 import com.liferay.portal.kernel.util.ParamUtil;
021 import com.liferay.portal.kernel.util.StringBundler;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.StringUtil;
024 import com.liferay.portal.kernel.util.Validator;
025 import com.liferay.portal.kernel.util.WebKeys;
026 import com.liferay.portal.model.PortletConstants;
027 import com.liferay.portal.model.Theme;
028 import com.liferay.portal.service.ThemeLocalServiceUtil;
029 import com.liferay.portal.theme.ThemeDisplay;
030 import com.liferay.portal.util.PortalUtil;
031
032 import java.net.URLDecoder;
033
034 import java.util.regex.Matcher;
035 import java.util.regex.Pattern;
036
037 import javax.servlet.ServletContext;
038 import javax.servlet.http.HttpServletRequest;
039
040
045 public class DynamicCSSUtil {
046
047 public static String replaceToken(
048 ServletContext servletContext, HttpServletRequest request,
049 String content)
050 throws Exception {
051
052 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
053 WebKeys.THEME_DISPLAY);
054
055 Theme theme = _getTheme(request);
056
057 if (theme == null) {
058 return content;
059 }
060
061 return replaceToken(
062 servletContext, request, themeDisplay, theme, content);
063 }
064
065 public static String replaceToken(
066 ServletContext servletContext, HttpServletRequest request,
067 ThemeDisplay themeDisplay, Theme theme, String parsedContent)
068 throws Exception {
069
070 String portalContextPath = PortalUtil.getPathContext();
071
072 String baseURL = servletContext.getContextPath();
073
074 if (baseURL.endsWith(StringPool.SLASH)) {
075 baseURL = baseURL.substring(0, baseURL.length() - 1);
076 }
077
078 parsedContent = StringUtil.replace(
079 parsedContent,
080 new String[] {"@base_url@", "@portal_ctx@", "@theme_image_path@"},
081 new String[] {
082 baseURL, portalContextPath,
083 _getThemeImagesPath(request, themeDisplay, theme)
084 });
085
086 return parsedContent;
087 }
088
089
093 protected static String propagateQueryString(
094 String content, String queryString) {
095
096 StringBuilder sb = new StringBuilder(content.length());
097
098 int pos = 0;
099
100 while (true) {
101 int importX = content.indexOf(_CSS_IMPORT_BEGIN, pos);
102 int importY = content.indexOf(
103 _CSS_IMPORT_END, importX + _CSS_IMPORT_BEGIN.length());
104
105 if ((importX == -1) || (importY == -1)) {
106 sb.append(content.substring(pos));
107
108 break;
109 }
110
111 sb.append(content.substring(pos, importX));
112 sb.append(_CSS_IMPORT_BEGIN);
113
114 String url = content.substring(
115 importX + _CSS_IMPORT_BEGIN.length(), importY);
116
117 char firstChar = url.charAt(0);
118
119 if (firstChar == CharPool.APOSTROPHE) {
120 sb.append(CharPool.APOSTROPHE);
121 }
122 else if (firstChar == CharPool.QUOTE) {
123 sb.append(CharPool.QUOTE);
124 }
125
126 url = StringUtil.unquote(url);
127
128 sb.append(url);
129
130 if (url.indexOf(CharPool.QUESTION) != -1) {
131 sb.append(CharPool.AMPERSAND);
132 }
133 else {
134 sb.append(CharPool.QUESTION);
135 }
136
137 sb.append(queryString);
138
139 if (firstChar == CharPool.APOSTROPHE) {
140 sb.append(CharPool.APOSTROPHE);
141 }
142 else if (firstChar == CharPool.QUOTE) {
143 sb.append(CharPool.QUOTE);
144 }
145
146 sb.append(_CSS_IMPORT_END);
147
148 pos = importY + _CSS_IMPORT_END.length();
149 }
150
151 return sb.toString();
152 }
153
154 private static Theme _getTheme(HttpServletRequest request)
155 throws Exception {
156
157 long companyId = PortalUtil.getCompanyId(request);
158
159 String themeId = ParamUtil.getString(request, "themeId");
160
161 if (Validator.isNotNull(themeId)) {
162 try {
163 Theme theme = ThemeLocalServiceUtil.getTheme(
164 companyId, themeId, false);
165
166 return theme;
167 }
168 catch (Exception e) {
169 _log.error(e, e);
170 }
171 }
172
173 String requestURI = URLDecoder.decode(
174 request.getRequestURI(), StringPool.UTF8);
175
176 Matcher portalThemeMatcher = _portalThemePattern.matcher(requestURI);
177
178 if (portalThemeMatcher.find()) {
179 String themePathId = portalThemeMatcher.group(1);
180
181 themePathId = StringUtil.replace(
182 themePathId, StringPool.UNDERLINE, StringPool.BLANK);
183
184 themeId = PortalUtil.getJsSafePortletId(themePathId);
185 }
186 else {
187 Matcher pluginThemeMatcher = _pluginThemePattern.matcher(
188 requestURI);
189
190 if (pluginThemeMatcher.find()) {
191 String themePathId = pluginThemeMatcher.group(1);
192
193 themePathId = StringUtil.replace(
194 themePathId, StringPool.UNDERLINE, StringPool.BLANK);
195
196 StringBundler sb = new StringBundler(4);
197
198 sb.append(themePathId);
199 sb.append(PortletConstants.WAR_SEPARATOR);
200 sb.append(themePathId);
201 sb.append("theme");
202
203 themePathId = sb.toString();
204
205 themeId = PortalUtil.getJsSafePortletId(themePathId);
206 }
207 }
208
209 if (Validator.isNull(themeId)) {
210 return null;
211 }
212
213 try {
214 Theme theme = ThemeLocalServiceUtil.getTheme(
215 companyId, themeId, false);
216
217 return theme;
218 }
219 catch (Exception e) {
220 _log.error(e, e);
221 }
222
223 return null;
224 }
225
226 private static String _getThemeImagesPath(
227 HttpServletRequest request, ThemeDisplay themeDisplay, Theme theme)
228 throws Exception {
229
230 String themeImagesPath = null;
231
232 if (themeDisplay != null) {
233 themeImagesPath = themeDisplay.getPathThemeImages();
234 }
235 else {
236 String cdnHost = PortalUtil.getCDNHost(request);
237 String themeStaticResourcePath = theme.getStaticResourcePath();
238
239 themeImagesPath =
240 cdnHost + themeStaticResourcePath + theme.getImagesPath();
241 }
242
243 return themeImagesPath;
244 }
245
246 private static final String _CSS_IMPORT_BEGIN = "@import url(";
247
248 private static final String _CSS_IMPORT_END = ");";
249
250 private static final Log _log = LogFactoryUtil.getLog(DynamicCSSUtil.class);
251
252 private static final Pattern _pluginThemePattern = Pattern.compile(
253 "\\/([^\\/]+)-theme\\/", Pattern.CASE_INSENSITIVE);
254 private static final Pattern _portalThemePattern = Pattern.compile(
255 "themes\\/([^\\/]+)\\/css", Pattern.CASE_INSENSITIVE);
256
257 }