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.CustomJspRegistryUtil;
023 import com.liferay.portal.kernel.util.FileUtil;
024 import com.liferay.portal.kernel.util.GetterUtil;
025 import com.liferay.portal.kernel.util.PortalUtil;
026 import com.liferay.portal.kernel.util.StringBundler;
027 import com.liferay.portal.kernel.util.StringPool;
028 import com.liferay.portal.kernel.util.StringUtil;
029 import com.liferay.portal.kernel.util.Validator;
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 dcje) {
326 if (_log.isDebugEnabled()) {
327 _log.debug(dcje.getMessage(), dcje);
328 }
329
330 registry.ungetService(serviceReference);
331
332 return null;
333 }
334 }
335
336 String contextName = GetterUtil.getString(
337 serviceReference.getProperty("context.name"));
338
339 try {
340 initCustomJspBag(contextId, contextName, customJspBag);
341 }
342 catch (Exception e) {
343 if (_log.isDebugEnabled()) {
344 _log.debug(e.getMessage(), e);
345 }
346
347 registry.ungetService(serviceReference);
348
349 return null;
350 }
351
352 _customJspBagsMap.put(serviceReference, customJspBag);
353
354 return customJspBag;
355 }
356
357 @Override
358 public void modifiedService(
359 ServiceReference<CustomJspBag> serviceReference,
360 CustomJspBag customJspBag) {
361
362 removedService(serviceReference, customJspBag);
363
364 addingService(serviceReference);
365 }
366
367 @Override
368 public void removedService(
369 ServiceReference<CustomJspBag> serviceReference,
370 CustomJspBag customJspBag) {
371
372 Registry registry = RegistryUtil.getRegistry();
373
374 registry.ungetService(serviceReference);
375
376 String contextId = GetterUtil.getString(
377 serviceReference.getProperty("context.id"));
378
379 for (String customJsp : customJspBag.getCustomJsps()) {
380 String customJspDir = customJspBag.getCustomJspDir();
381
382 int pos = customJsp.indexOf(customJspDir);
383
384 String portalJsp = customJsp.substring(
385 pos + customJspDir.length());
386
387 if (customJspBag.isCustomJspGlobal()) {
388 File portalJspFile = new File(
389 PortalUtil.getPortalWebDir() + portalJsp);
390 File portalJspBackupFile = getPortalJspBackupFile(
391 portalJspFile);
392
393 if (portalJspBackupFile.exists()) {
394 try {
395 FileUtil.copyFile(
396 portalJspBackupFile, portalJspFile);
397 }
398 catch (IOException ioe) {
399 return;
400 }
401
402 portalJspBackupFile.delete();
403 }
404 else if (portalJspFile.exists()) {
405 portalJspFile.delete();
406 }
407 }
408 else {
409 portalJsp = CustomJspRegistryUtil.getCustomJspFileName(
410 contextId, portalJsp);
411
412 File portalJspFile = new File(
413 PortalUtil.getPortalWebDir() + portalJsp);
414
415 if (portalJspFile.exists()) {
416 portalJspFile.delete();
417 }
418 }
419 }
420
421 if (!customJspBag.isCustomJspGlobal()) {
422 CustomJspRegistryUtil.unregisterServletContextName(contextId);
423 }
424
425 _customJspBagsMap.remove(serviceReference);
426 }
427
428 }
429
430 }