001
014
015 package com.liferay.portal.deploy.hot;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.log.SanitizerLogWrapper;
020 import com.liferay.portal.kernel.url.URLContainer;
021 import com.liferay.portal.kernel.util.CharPool;
022 import com.liferay.portal.kernel.util.FileUtil;
023 import com.liferay.portal.kernel.util.GetterUtil;
024 import com.liferay.portal.kernel.util.StringBundler;
025 import com.liferay.portal.kernel.util.StringPool;
026 import com.liferay.portal.kernel.util.StringUtil;
027 import com.liferay.portal.kernel.util.Validator;
028 import com.liferay.portal.util.CustomJspRegistryUtil;
029 import com.liferay.portal.util.PortalUtil;
030 import com.liferay.registry.Filter;
031 import com.liferay.registry.Registry;
032 import com.liferay.registry.RegistryUtil;
033 import com.liferay.registry.ServiceReference;
034 import com.liferay.registry.ServiceTracker;
035 import com.liferay.registry.ServiceTrackerCustomizer;
036
037 import java.io.File;
038 import java.io.IOException;
039 import java.io.InputStream;
040
041 import java.net.URL;
042
043 import java.util.Collections;
044 import java.util.HashMap;
045 import java.util.HashSet;
046 import java.util.List;
047 import java.util.Map;
048 import java.util.Set;
049 import java.util.concurrent.ConcurrentHashMap;
050
051
055 public class CustomJspBagRegistryUtil {
056
057 public static Map<ServiceReference<CustomJspBag>, CustomJspBag>
058 getCustomJspBags() {
059
060 return Collections.unmodifiableMap(_instance._customJspBagsMap);
061 }
062
063 protected InputStream getCustomJspInputStream(
064 URLContainer urlContainer, String customJsp)
065 throws IOException {
066
067 URL url = urlContainer.getResource(customJsp);
068
069 return url.openStream();
070 }
071
072 protected void getCustomJsps(
073 URLContainer urlContainer, String resourcePath,
074 List<String> customJsps) {
075
076 Set<String> resourcePaths = urlContainer.getResources(resourcePath);
077
078 if ((resourcePaths == null) || resourcePaths.isEmpty()) {
079 return;
080 }
081
082 for (String curResourcePath : resourcePaths) {
083 if (curResourcePath.endsWith(StringPool.SLASH)) {
084 getCustomJsps(urlContainer, curResourcePath, customJsps);
085 }
086 else {
087 String customJsp = curResourcePath;
088
089 customJsp = StringUtil.replace(
090 customJsp, StringPool.DOUBLE_SLASH, StringPool.SLASH);
091
092 customJsps.add(customJsp);
093 }
094 }
095 }
096
097 protected String getPortalJsp(String customJsp, String customJspDir) {
098 if (Validator.isNull(customJsp) || Validator.isNull(customJspDir)) {
099 return null;
100 }
101
102 int pos = customJsp.indexOf(customJspDir);
103
104 return customJsp.substring(pos + customJspDir.length());
105 }
106
107 protected File getPortalJspBackupFile(File portalJspFile) {
108 String fileName = portalJspFile.getName();
109 String filePath = portalJspFile.toString();
110
111 int fileNameIndex = fileName.lastIndexOf(CharPool.PERIOD);
112
113 if (fileNameIndex > 0) {
114 int filePathIndex = filePath.lastIndexOf(fileName);
115
116 fileName =
117 fileName.substring(0, fileNameIndex) + ".portal" +
118 fileName.substring(fileNameIndex);
119
120 filePath = filePath.substring(0, filePathIndex) + fileName;
121 }
122 else {
123 filePath += ".portal";
124 }
125
126 return new File(filePath);
127 }
128
129 protected void initCustomJspBag(
130 String contextId, String contextName, CustomJspBag customJspBag)
131 throws Exception {
132
133 String customJspDir = customJspBag.getCustomJspDir();
134 boolean customJspGlobal = customJspBag.isCustomJspGlobal();
135 List<String> customJsps = customJspBag.getCustomJsps();
136
137 String portalWebDir = PortalUtil.getPortalWebDir();
138
139 for (String customJsp : customJsps) {
140 String portalJsp = getPortalJsp(customJsp, customJspDir);
141
142 if (customJspGlobal) {
143 File portalJspFile = new File(portalWebDir + portalJsp);
144 File portalJspBackupFile = getPortalJspBackupFile(
145 portalJspFile);
146
147 if (portalJspFile.exists() && !portalJspBackupFile.exists()) {
148 FileUtil.copyFile(portalJspFile, portalJspBackupFile);
149 }
150 }
151 else {
152 portalJsp = CustomJspRegistryUtil.getCustomJspFileName(
153 contextId, portalJsp);
154 }
155
156 FileUtil.write(
157 portalWebDir + portalJsp,
158 getCustomJspInputStream(
159 customJspBag.getURLContainer(), customJsp));
160 }
161
162 if (!customJspGlobal) {
163 CustomJspRegistryUtil.registerServletContextName(
164 contextId, contextName);
165 }
166 }
167
168 protected void verifyCustomJsps(String contextId, CustomJspBag customJspBag)
169 throws DuplicateCustomJspException {
170
171 Set<String> customJsps = new HashSet<>();
172
173 for (String customJsp : customJspBag.getCustomJsps()) {
174 String portalJsp = getPortalJsp(
175 customJsp, customJspBag.getCustomJspDir());
176
177 customJsps.add(portalJsp);
178 }
179
180 Map<String, String> conflictingCustomJsps = new HashMap<>();
181
182 for (Map.Entry<ServiceReference<CustomJspBag>, CustomJspBag> entry :
183 _customJspBagsMap.entrySet()) {
184
185 CustomJspBag currentCustomJspBag = entry.getValue();
186
187 if (!currentCustomJspBag.isCustomJspGlobal()) {
188 continue;
189 }
190
191 ServiceReference<CustomJspBag> serviceReference = entry.getKey();
192
193 String contextName = GetterUtil.getString(
194 serviceReference.getProperty("context.name"));
195
196 List<String> currentCustomJsps =
197 currentCustomJspBag.getCustomJsps();
198
199 for (String currentCustomJsp : currentCustomJsps) {
200 String currentPortalJsp = getPortalJsp(
201 currentCustomJsp, currentCustomJspBag.getCustomJspDir());
202
203 if (customJsps.contains(currentPortalJsp)) {
204 conflictingCustomJsps.put(currentPortalJsp, contextName);
205 }
206 }
207 }
208
209 if (conflictingCustomJsps.isEmpty()) {
210 return;
211 }
212
213 _log.error(contextId + " conflicts with the installed hooks");
214
215 if (_log.isDebugEnabled()) {
216 Log log = SanitizerLogWrapper.allowCRLF(_log);
217
218 StringBundler sb = new StringBundler(
219 conflictingCustomJsps.size() * 4 + 2);
220
221 sb.append("Colliding JSP files in ");
222 sb.append(contextId);
223 sb.append(StringPool.NEW_LINE);
224
225 int i = 0;
226
227 for (Map.Entry<String, String> entry :
228 conflictingCustomJsps.entrySet()) {
229
230 sb.append(entry.getKey());
231 sb.append(" with ");
232 sb.append(entry.getValue());
233
234 if ((i + 1) < conflictingCustomJsps.size()) {
235 sb.append(StringPool.NEW_LINE);
236 }
237
238 i++;
239 }
240
241 log.debug(sb.toString());
242 }
243
244 throw new DuplicateCustomJspException();
245 }
246
247 private CustomJspBagRegistryUtil() {
248 Registry registry = RegistryUtil.getRegistry();
249
250 Filter filter = registry.getFilter(
251 "(&(context.id=*)(context.name=*)(objectClass=" +
252 CustomJspBag.class.getName() + "))");
253
254 _serviceTracker = registry.trackServices(
255 filter, new CustomJspBagRegistryUtilServiceTrackerCustomizer());
256
257 _serviceTracker.open();
258 }
259
260 private static final Log _log = LogFactoryUtil.getLog(
261 CustomJspBagRegistryUtil.class);
262
263 private static final CustomJspBagRegistryUtil _instance =
264 new CustomJspBagRegistryUtil();
265
266 private final Map<ServiceReference<CustomJspBag>, CustomJspBag>
267 _customJspBagsMap = new ConcurrentHashMap<>();
268 private final ServiceTracker<CustomJspBag, CustomJspBag> _serviceTracker;
269
270 private class CustomJspBagRegistryUtilServiceTrackerCustomizer
271 implements ServiceTrackerCustomizer<CustomJspBag, CustomJspBag> {
272
273 @Override
274 public CustomJspBag addingService(
275 ServiceReference<CustomJspBag> serviceReference) {
276
277 Registry registry = RegistryUtil.getRegistry();
278
279 CustomJspBag customJspBag = registry.getService(serviceReference);
280
281 List<String> customJsps = customJspBag.getCustomJsps();
282
283 if (customJsps.isEmpty()) {
284 getCustomJsps(
285 customJspBag.getURLContainer(),
286 customJspBag.getCustomJspDir(),
287 customJspBag.getCustomJsps());
288
289 customJsps = customJspBag.getCustomJsps();
290
291 if (customJsps.isEmpty()) {
292 return null;
293 }
294 }
295
296 if (_log.isDebugEnabled()) {
297 StringBundler sb = new StringBundler(customJsps.size() * 2);
298
299 sb.append("Custom JSP files:\n");
300
301 for (int i = 0; i < customJsps.size(); i++) {
302 String customJsp = customJsps.get(i);
303
304 sb.append(customJsp);
305
306 if ((i + 1) < customJsps.size()) {
307 sb.append(StringPool.NEW_LINE);
308 }
309 }
310
311 Log log = SanitizerLogWrapper.allowCRLF(_log);
312
313 log.debug(sb.toString());
314 }
315
316 String contextId = GetterUtil.getString(
317 serviceReference.getProperty("context.id"));
318
319 if (customJspBag.isCustomJspGlobal() &&
320 !_customJspBagsMap.isEmpty()) {
321
322 try {
323 verifyCustomJsps(contextId, customJspBag);
324 }
325 catch (DuplicateCustomJspException e) {
326 return null;
327 }
328 }
329
330 _customJspBagsMap.put(serviceReference, customJspBag);
331
332 String contextName = GetterUtil.getString(
333 serviceReference.getProperty("context.name"));
334
335 try {
336 initCustomJspBag(contextId, contextName, customJspBag);
337 }
338 catch (Exception e) {
339 return null;
340 }
341
342 return customJspBag;
343 }
344
345 @Override
346 public void modifiedService(
347 ServiceReference<CustomJspBag> serviceReference,
348 CustomJspBag customJspBag) {
349
350 removedService(serviceReference, customJspBag);
351
352 addingService(serviceReference);
353 }
354
355 @Override
356 public void removedService(
357 ServiceReference<CustomJspBag> serviceReference,
358 CustomJspBag customJspBag) {
359
360 Registry registry = RegistryUtil.getRegistry();
361
362 registry.ungetService(serviceReference);
363
364 String contextId = GetterUtil.getString(
365 serviceReference.getProperty("context.id"));
366
367 for (String customJsp : customJspBag.getCustomJsps()) {
368 String customJspDir = customJspBag.getCustomJspDir();
369
370 int pos = customJsp.indexOf(customJspDir);
371
372 String portalJsp = customJsp.substring(
373 pos + customJspDir.length());
374
375 if (customJspBag.isCustomJspGlobal()) {
376 File portalJspFile = new File(
377 PortalUtil.getPortalWebDir() + portalJsp);
378 File portalJspBackupFile = getPortalJspBackupFile(
379 portalJspFile);
380
381 if (portalJspBackupFile.exists()) {
382 try {
383 FileUtil.copyFile(
384 portalJspBackupFile, portalJspFile);
385 }
386 catch (IOException e) {
387 return;
388 }
389
390 portalJspBackupFile.delete();
391 }
392 else if (portalJspFile.exists()) {
393 portalJspFile.delete();
394 }
395 }
396 else {
397 portalJsp = CustomJspRegistryUtil.getCustomJspFileName(
398 contextId, portalJsp);
399
400 File portalJspFile = new File(
401 PortalUtil.getPortalWebDir() + portalJsp);
402
403 if (portalJspFile.exists()) {
404 portalJspFile.delete();
405 }
406 }
407 }
408
409 if (!customJspBag.isCustomJspGlobal()) {
410 CustomJspRegistryUtil.unregisterServletContextName(contextId);
411 }
412
413 _customJspBagsMap.remove(serviceReference);
414 }
415
416 }
417
418 }